emacs-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

scratch/etags-regen 1db074f: Merge branch 'master' into scratch/etags-re


From: Dmitry Gutov
Subject: scratch/etags-regen 1db074f: Merge branch 'master' into scratch/etags-regen
Date: Mon, 29 Mar 2021 20:47:33 -0400 (EDT)

branch: scratch/etags-regen
commit 1db074f70777cd5f9d1d384824fe319d71c29ed7
Merge: 519e149 24c92b3
Author: Dmitry Gutov <dgutov@yandex.ru>
Commit: Dmitry Gutov <dgutov@yandex.ru>

    Merge branch 'master' into scratch/etags-regen
---
 .gitignore                                         |     3 +
 CONTRIBUTE                                         |    17 +-
 ChangeLog.3                                        |   395 +-
 Makefile.in                                        |    66 +-
 admin/CPP-DEFINES                                  |    45 -
 admin/admin.el                                     |    13 +-
 admin/charsets/Makefile.in                         |    12 +-
 admin/charsets/mapfiles/README                     |     4 +-
 admin/check-doc-strings                            |    57 +-
 admin/cus-test.el                                  |    12 +-
 admin/emake                                        |     6 +
 admin/grammars/Makefile.in                         |    13 +-
 admin/grammars/c.by                                |     2 +-
 admin/grammars/grammar.wy                          |    10 +-
 admin/grammars/python.wy                           |    33 +-
 admin/make-tarball.txt                             |    92 +-
 admin/notes/emba                                   |    15 +
 admin/unidata/Makefile.in                          |    18 +-
 build-aux/make-info-dir                            |    30 +
 configure.ac                                       |    68 +-
 doc/emacs/Makefile.in                              |    28 +-
 doc/emacs/basic.texi                               |    16 +
 doc/emacs/custom.texi                              |    14 +-
 doc/emacs/dired.texi                               |     6 +
 doc/emacs/emacs.texi                               |     1 +
 doc/emacs/files.texi                               |     5 +-
 doc/emacs/m-x.texi                                 |    20 +-
 doc/emacs/maintaining.texi                         |    20 +
 doc/emacs/mini.texi                                |     7 +-
 doc/emacs/package.texi                             |     7 +
 doc/lispintro/Makefile.in                          |    25 +-
 doc/lispintro/emacs-lisp-intro.texi                |    17 +-
 doc/lispref/Makefile.in                            |    25 +-
 doc/lispref/buffers.texi                           |     3 -
 doc/lispref/commands.texi                          |   106 +-
 doc/lispref/control.texi                           |    12 +-
 doc/lispref/customize.texi                         |    26 +-
 doc/lispref/debugging.texi                         |     3 +-
 doc/lispref/display.texi                           |    23 +-
 doc/lispref/edebug.texi                            |    92 +-
 doc/lispref/elisp.texi                             |     3 +-
 doc/lispref/eval.texi                              |     1 -
 doc/lispref/files.texi                             |     7 +-
 doc/lispref/frames.texi                            |    12 +-
 doc/lispref/functions.texi                         |    23 +-
 doc/lispref/keymaps.texi                           |    12 -
 doc/lispref/loading.texi                           |     6 +-
 doc/lispref/maps.texi                              |     3 -
 doc/lispref/markers.texi                           |     4 +-
 doc/lispref/minibuf.texi                           |     9 +-
 doc/lispref/modes.texi                             |    25 +-
 doc/lispref/numbers.texi                           |     2 +-
 doc/lispref/objects.texi                           |     3 -
 doc/lispref/positions.texi                         |     1 -
 doc/lispref/processes.texi                         |   334 +-
 doc/lispref/sequences.texi                         |     2 +-
 doc/lispref/strings.texi                           |    16 +
 doc/lispref/text.texi                              |    11 +-
 doc/lispref/tips.texi                              |     4 +-
 doc/lispref/variables.texi                         |     2 -
 doc/lispref/windows.texi                           |     2 +-
 doc/misc/Makefile.in                               |    74 +-
 doc/misc/calc.texi                                 |   111 +-
 doc/misc/efaq-w32.texi                             |     9 +-
 doc/misc/efaq.texi                                 |   119 +-
 doc/misc/forms.texi                                |     3 +-
 doc/misc/gnus-faq.texi                             |    12 +-
 doc/misc/gnus.texi                                 |    18 +-
 doc/misc/message.texi                              |     6 +-
 doc/misc/modus-themes.org                          |  3300 +++
 doc/misc/modus-themes.texi                         |  2834 ---
 doc/misc/nxml-mode.texi                            |     2 +-
 doc/misc/octave-mode.texi                          |     5 +-
 doc/misc/org-setup.org                             |    53 +
 doc/misc/org.org                                   | 21904 ++++++++++++++++++
 doc/misc/org.texi                                  | 23148 -------------------
 doc/misc/remember.texi                             |     3 +-
 doc/misc/texinfo.tex                               |     4 +-
 doc/misc/tramp.texi                                |   569 +-
 etc/HISTORY                                        |     2 +
 etc/NEWS                                           |   421 +-
 etc/NEWS.19                                        |     1 +
 etc/NEWS.27                                        |    25 -
 etc/ORG-NEWS                                       |     2 +-
 etc/compilation.txt                                |     8 +
 etc/emacs-mail.desktop                             |     2 +
 etc/facemenu-removal.txt                           |    20 +
 etc/grep.txt                                       |     4 +
 .../OpenDocument-schema-v1.3+libreoffice.rnc       |   892 +
 ...ma-v1.2-os.rnc => OpenDocument-schema-v1.3.rnc} | 11694 +++++-----
 etc/schema/schemas.xml                             |     6 +-
 etc/themes/modus-operandi-theme.el                 |  4673 +---
 etc/themes/modus-themes.el                         |  6456 ++++++
 etc/themes/modus-vivendi-theme.el                  |  4673 +---
 etc/themes/wombat-theme.el                         |     2 +
 leim/Makefile.in                                   |    14 +-
 lib-src/Makefile.in                                |    29 +-
 lib/Makefile.in                                    |    21 +-
 lib/pipe2.c                                        |     2 +-
 lisp/Makefile.in                                   |    20 +-
 lisp/align.el                                      |     4 +-
 lisp/allout-widgets.el                             |    98 +-
 lisp/allout.el                                     |   139 +-
 lisp/ansi-color.el                                 |     3 +-
 lisp/arc-mode.el                                   |     6 +-
 lisp/auth-source-pass.el                           |     8 +-
 lisp/auth-source.el                                |     6 +-
 lisp/battery.el                                    |     4 +-
 lisp/bindings.el                                   |    20 +-
 lisp/bookmark.el                                   |    80 +-
 lisp/buff-menu.el                                  |   186 +-
 lisp/button.el                                     |     4 +-
 lisp/calc/calc-ext.el                              |     4 +-
 lisp/calc/calc-menu.el                             |     2 +-
 lisp/calc/calc-prog.el                             |    65 +-
 lisp/calc/calc-sel.el                              |     4 +-
 lisp/calc/calc-yank.el                             |     5 +-
 lisp/calculator.el                                 |    64 +-
 lisp/calendar/appt.el                              |     4 +-
 lisp/calendar/cal-bahai.el                         |     2 +-
 lisp/calendar/icalendar.el                         |    31 +-
 lisp/calendar/iso8601.el                           |     2 +-
 lisp/calendar/parse-time.el                        |     2 +-
 lisp/calendar/todo-mode.el                         |     8 +-
 lisp/cedet/cedet-cscope.el                         |    13 +-
 lisp/cedet/cedet-files.el                          |     2 +-
 lisp/cedet/cedet-global.el                         |    11 +-
 lisp/cedet/cedet-idutils.el                        |    21 +-
 lisp/cedet/cedet.el                                |    41 +-
 lisp/cedet/data-debug.el                           |    57 +-
 lisp/cedet/ede.el                                  |    79 +-
 lisp/cedet/ede/auto.el                             |     6 +-
 lisp/cedet/ede/autoconf-edit.el                    |     2 +-
 lisp/cedet/ede/base.el                             |    29 +-
 lisp/cedet/ede/config.el                           |    10 +-
 lisp/cedet/ede/cpp-root.el                         |    12 +-
 lisp/cedet/ede/custom.el                           |    66 +-
 lisp/cedet/ede/detect.el                           |     2 +-
 lisp/cedet/ede/dired.el                            |    13 +-
 lisp/cedet/ede/emacs.el                            |    27 +-
 lisp/cedet/ede/files.el                            |    24 +-
 lisp/cedet/ede/generic.el                          |    18 +-
 lisp/cedet/ede/linux.el                            |     6 +-
 lisp/cedet/ede/locate.el                           |    48 +-
 lisp/cedet/ede/make.el                             |    19 +-
 lisp/cedet/ede/makefile-edit.el                    |     2 +-
 lisp/cedet/ede/pconf.el                            |    24 +-
 lisp/cedet/ede/pmake.el                            |    85 +-
 lisp/cedet/ede/proj-archive.el                     |     4 +-
 lisp/cedet/ede/proj-aux.el                         |     2 +-
 lisp/cedet/ede/proj-comp.el                        |    46 +-
 lisp/cedet/ede/proj-elisp.el                       |    41 +-
 lisp/cedet/ede/proj-info.el                        |     9 +-
 lisp/cedet/ede/proj-misc.el                        |     2 +-
 lisp/cedet/ede/proj-obj.el                         |    11 +-
 lisp/cedet/ede/proj-prog.el                        |     6 +-
 lisp/cedet/ede/proj-scheme.el                      |     4 +-
 lisp/cedet/ede/proj-shared.el                      |     8 +-
 lisp/cedet/ede/proj.el                             |    22 +-
 lisp/cedet/ede/project-am.el                       |     8 +-
 lisp/cedet/ede/shell.el                            |     2 +-
 lisp/cedet/ede/simple.el                           |     6 +-
 lisp/cedet/ede/source.el                           |     4 +-
 lisp/cedet/ede/speedbar.el                         |    52 +-
 lisp/cedet/ede/srecode.el                          |     3 +-
 lisp/cedet/ede/system.el                           |     2 +-
 lisp/cedet/ede/util.el                             |     2 +-
 lisp/cedet/mode-local.el                           |     2 +-
 lisp/cedet/pulse.el                                |   108 +-
 lisp/cedet/semantic.el                             |    71 +-
 lisp/cedet/semantic/analyze.el                     |    32 +-
 lisp/cedet/semantic/analyze/complete.el            |    16 +-
 lisp/cedet/semantic/analyze/debug.el               |    25 +-
 lisp/cedet/semantic/analyze/fcn.el                 |     4 +-
 lisp/cedet/semantic/analyze/refs.el                |     4 +-
 lisp/cedet/semantic/bovine.el                      |    32 +-
 lisp/cedet/semantic/bovine/c.el                    |    96 +-
 lisp/cedet/semantic/bovine/debug.el                |     4 +-
 lisp/cedet/semantic/bovine/el.el                   |    48 +-
 lisp/cedet/semantic/bovine/gcc.el                  |    13 +-
 lisp/cedet/semantic/bovine/grammar.el              |     8 +-
 lisp/cedet/semantic/bovine/make.el                 |    12 +-
 lisp/cedet/semantic/bovine/scm.el                  |    11 +-
 lisp/cedet/semantic/chart.el                       |    12 +-
 lisp/cedet/semantic/complete.el                    |   123 +-
 lisp/cedet/semantic/ctxt.el                        |    24 +-
 lisp/cedet/semantic/db-debug.el                    |     6 +-
 lisp/cedet/semantic/db-ebrowse.el                  |    44 +-
 lisp/cedet/semantic/db-el.el                       |    12 +-
 lisp/cedet/semantic/db-file.el                     |    37 +-
 lisp/cedet/semantic/db-find.el                     |    17 +-
 lisp/cedet/semantic/db-global.el                   |    17 +-
 lisp/cedet/semantic/db-javascript.el               |    18 +-
 lisp/cedet/semantic/db-mode.el                     |     2 +-
 lisp/cedet/semantic/db-ref.el                      |     8 +-
 lisp/cedet/semantic/db-typecache.el                |    26 +-
 lisp/cedet/semantic/debug.el                       |    52 +-
 lisp/cedet/semantic/decorate.el                    |    11 +-
 lisp/cedet/semantic/decorate/include.el            |    16 +-
 lisp/cedet/semantic/decorate/mode.el               |    28 +-
 lisp/cedet/semantic/dep.el                         |    26 +-
 lisp/cedet/semantic/doc.el                         |     4 +-
 lisp/cedet/semantic/ede-grammar.el                 |    22 +-
 lisp/cedet/semantic/edit.el                        |    17 +-
 lisp/cedet/semantic/find.el                        |     6 +-
 lisp/cedet/semantic/format.el                      |    10 +-
 lisp/cedet/semantic/fw.el                          |    80 +-
 lisp/cedet/semantic/grammar-wy.el                  |   687 +-
 lisp/cedet/semantic/grammar.el                     |    62 +-
 lisp/cedet/semantic/html.el                        |    10 +-
 lisp/cedet/semantic/ia-sb.el                       |    36 +-
 lisp/cedet/semantic/ia.el                          |    13 +-
 lisp/cedet/semantic/idle.el                        |   203 +-
 lisp/cedet/semantic/imenu.el                       |    26 +-
 lisp/cedet/semantic/java.el                        |    22 +-
 lisp/cedet/semantic/lex-spp.el                     |    59 +-
 lisp/cedet/semantic/lex.el                         |    67 +-
 lisp/cedet/semantic/mru-bookmark.el                |    20 +-
 lisp/cedet/semantic/sb.el                          |     6 +-
 lisp/cedet/semantic/scope.el                       |     4 +-
 lisp/cedet/semantic/senator.el                     |    21 +-
 lisp/cedet/semantic/sort.el                        |    20 +-
 lisp/cedet/semantic/symref.el                      |     8 +-
 lisp/cedet/semantic/symref/cscope.el               |     4 +-
 lisp/cedet/semantic/symref/filter.el               |    10 +-
 lisp/cedet/semantic/symref/global.el               |     2 +-
 lisp/cedet/semantic/symref/grep.el                 |     2 +-
 lisp/cedet/semantic/symref/idutils.el              |     4 +-
 lisp/cedet/semantic/symref/list.el                 |    30 +-
 lisp/cedet/semantic/tag-file.el                    |     2 +-
 lisp/cedet/semantic/tag-ls.el                      |    23 +-
 lisp/cedet/semantic/tag-write.el                   |     4 +-
 lisp/cedet/semantic/tag.el                         |    80 +-
 lisp/cedet/semantic/texi.el                        |    18 +-
 lisp/cedet/semantic/util-modes.el                  |    66 +-
 lisp/cedet/semantic/util.el                        |    11 +-
 lisp/cedet/semantic/wisent.el                      |    28 +-
 lisp/cedet/semantic/wisent/comp.el                 |    88 +-
 lisp/cedet/semantic/wisent/grammar.el              |    19 +-
 lisp/cedet/semantic/wisent/java-tags.el            |    12 +-
 lisp/cedet/semantic/wisent/javascript.el           |    23 +-
 lisp/cedet/semantic/wisent/python.el               |    14 +-
 lisp/cedet/semantic/wisent/wisent.el               |    16 +-
 lisp/cedet/srecode.el                              |     2 +-
 lisp/cedet/srecode/args.el                         |     2 +-
 lisp/cedet/srecode/compile.el                      |     6 +-
 lisp/cedet/srecode/cpp.el                          |     7 +-
 lisp/cedet/srecode/ctxt.el                         |     2 +-
 lisp/cedet/srecode/dictionary.el                   |    21 +-
 lisp/cedet/srecode/document.el                     |    11 +-
 lisp/cedet/srecode/el.el                           |     2 +-
 lisp/cedet/srecode/expandproto.el                  |     2 +-
 lisp/cedet/srecode/extract.el                      |    20 +-
 lisp/cedet/srecode/fields.el                       |    31 +-
 lisp/cedet/srecode/filters.el                      |     2 +-
 lisp/cedet/srecode/find.el                         |    23 +-
 lisp/cedet/srecode/getset.el                       |     4 +-
 lisp/cedet/srecode/java.el                         |     2 +-
 lisp/cedet/srecode/map.el                          |     6 +-
 lisp/cedet/srecode/mode.el                         |    35 +-
 lisp/cedet/srecode/srt-mode.el                     |    16 +-
 lisp/cedet/srecode/srt.el                          |     8 +-
 lisp/cedet/srecode/table.el                        |     6 +-
 lisp/cedet/srecode/template.el                     |     8 +-
 lisp/cedet/srecode/texi.el                         |     4 +-
 lisp/cmuscheme.el                                  |     4 +-
 lisp/comint.el                                     |    20 +-
 lisp/completion.el                                 |    82 +-
 lisp/cus-start.el                                  |     3 +-
 lisp/custom.el                                     |    26 +
 lisp/dired-aux.el                                  |     9 +-
 lisp/dired-x.el                                    |     4 +-
 lisp/dired.el                                      |   527 +-
 lisp/doc-view.el                                   |     2 +
 lisp/emacs-lisp/autoload.el                        |    15 +-
 lisp/emacs-lisp/backtrace.el                       |     8 +-
 lisp/emacs-lisp/benchmark.el                       |    97 +-
 lisp/emacs-lisp/bindat.el                          |   868 +-
 lisp/emacs-lisp/byte-opt.el                        |   108 +-
 lisp/emacs-lisp/byte-run.el                        |    21 +-
 lisp/emacs-lisp/bytecomp.el                        |   235 +-
 lisp/emacs-lisp/cconv.el                           |   230 +-
 lisp/emacs-lisp/chart.el                           |    70 +-
 lisp/emacs-lisp/checkdoc.el                        |    20 +-
 lisp/emacs-lisp/cl-extra.el                        |    27 +-
 lisp/emacs-lisp/cl-generic.el                      |    98 +-
 lisp/emacs-lisp/cl-lib.el                          |    13 +-
 lisp/emacs-lisp/cl-macs.el                         |   265 +-
 lisp/emacs-lisp/debug.el                           |     2 +-
 lisp/emacs-lisp/derived.el                         |     7 +-
 lisp/emacs-lisp/easy-mmode.el                      |    39 +-
 lisp/emacs-lisp/easymenu.el                        |    22 +-
 lisp/emacs-lisp/edebug.el                          |   749 +-
 lisp/emacs-lisp/eieio-compat.el                    |     2 +-
 lisp/emacs-lisp/eieio-core.el                      |     2 +-
 lisp/emacs-lisp/eieio.el                           |    20 +-
 lisp/emacs-lisp/eldoc.el                           |     7 +-
 lisp/emacs-lisp/elp.el                             |     2 +-
 lisp/emacs-lisp/ert-x.el                           |    12 +-
 lisp/emacs-lisp/ert.el                             |    65 +-
 lisp/emacs-lisp/generator.el                       |     2 +-
 lisp/emacs-lisp/gv.el                              |    17 +-
 lisp/emacs-lisp/inline.el                          |     2 +-
 lisp/emacs-lisp/lisp-mode.el                       |    30 +-
 lisp/emacs-lisp/macroexp.el                        |   177 +-
 lisp/emacs-lisp/map-ynp.el                         |     6 +-
 lisp/emacs-lisp/map.el                             |   320 +-
 lisp/emacs-lisp/memory-report.el                   |     2 +-
 lisp/emacs-lisp/package.el                         |    93 +-
 lisp/emacs-lisp/pcase.el                           |   343 +-
 lisp/emacs-lisp/radix-tree.el                      |    13 +-
 lisp/emacs-lisp/re-builder.el                      |    78 +-
 lisp/emacs-lisp/rx.el                              |    37 +-
 lisp/emacs-lisp/seq.el                             |    10 +-
 lisp/emacs-lisp/shortdoc.el                        |    12 +-
 lisp/emacs-lisp/smie.el                            |     2 +-
 lisp/emacs-lisp/subr-x.el                          |    22 -
 lisp/emacs-lisp/syntax.el                          |    13 +-
 lisp/emacs-lisp/tcover-ses.el                      |     4 +-
 lisp/emacs-lisp/trace.el                           |     4 +-
 lisp/emulation/cua-base.el                         |   211 +-
 lisp/emulation/cua-gmrk.el                         |    53 +-
 lisp/emulation/cua-rect.el                         |   150 +-
 lisp/emulation/edt-mapper.el                       |     6 +-
 lisp/emulation/edt.el                              |   140 +-
 lisp/emulation/keypad.el                           |    18 +-
 lisp/emulation/viper-cmd.el                        |   168 +-
 lisp/emulation/viper-ex.el                         |    35 +-
 lisp/emulation/viper-init.el                       |     6 +-
 lisp/emulation/viper-keym.el                       |    66 +-
 lisp/emulation/viper-macs.el                       |    65 +-
 lisp/emulation/viper-mous.el                       |    53 +-
 lisp/emulation/viper-util.el                       |    96 +-
 lisp/emulation/viper.el                            |     6 +-
 lisp/epa.el                                        |    57 +-
 lisp/erc/erc-autoaway.el                           |    54 +-
 lisp/erc/erc-backend.el                            |    45 +-
 lisp/erc/erc-button.el                             |    54 +-
 lisp/erc/erc-capab.el                              |    36 +-
 lisp/erc/erc-dcc.el                                |    76 +-
 lisp/erc/erc-desktop-notifications.el              |    10 +-
 lisp/erc/erc-ezbounce.el                           |    18 +-
 lisp/erc/erc-fill.el                               |    17 +-
 lisp/erc/erc-goodies.el                            |    65 +-
 lisp/erc/erc-ibuffer.el                            |     9 +-
 lisp/erc/erc-identd.el                             |    19 +-
 lisp/erc/erc-imenu.el                              |     9 +-
 lisp/erc/erc-join.el                               |    28 +-
 lisp/erc/erc-lang.el                               |     4 +-
 lisp/erc/erc-list.el                               |    26 +-
 lisp/erc/erc-log.el                                |    59 +-
 lisp/erc/erc-match.el                              |    50 +-
 lisp/erc/erc-menu.el                               |     9 +-
 lisp/erc/erc-netsplit.el                           |    25 +-
 lisp/erc/erc-networks.el                           |    20 +-
 lisp/erc/erc-notify.el                             |    26 +-
 lisp/erc/erc-page.el                               |    18 +-
 lisp/erc/erc-pcomplete.el                          |    18 +-
 lisp/erc/erc-replace.el                            |    15 +-
 lisp/erc/erc-ring.el                               |    32 +-
 lisp/erc/erc-services.el                           |    42 +-
 lisp/erc/erc-sound.el                              |    15 +-
 lisp/erc/erc-speedbar.el                           |    21 +-
 lisp/erc/erc-spelling.el                           |    10 +-
 lisp/erc/erc-stamp.el                              |    15 +-
 lisp/erc/erc-status-sidebar.el                     |    30 +-
 lisp/erc/erc-track.el                              |    76 +-
 lisp/erc/erc-truncate.el                           |     7 +-
 lisp/erc/erc-xdcc.el                               |    16 +-
 lisp/erc/erc.el                                    |   202 +-
 lisp/eshell/em-ls.el                               |     6 +-
 lisp/eshell/esh-mode.el                            |     2 +-
 lisp/eshell/esh-opt.el                             |     8 -
 lisp/eshell/esh-var.el                             |     2 +-
 lisp/expand.el                                     |    22 +-
 lisp/facemenu.el                                   |    21 +-
 lisp/faces.el                                      |    51 +-
 lisp/filenotify.el                                 |     1 +
 lisp/files-x.el                                    |    13 +-
 lisp/files.el                                      |    48 +-
 lisp/filesets.el                                   |    64 +-
 lisp/finder.el                                     |    54 +-
 lisp/follow.el                                     |    98 +-
 lisp/font-lock.el                                  |    12 +
 lisp/format.el                                     |    18 +-
 lisp/frame.el                                      |    19 +-
 lisp/gnus/.dir-locals.el                           |     4 -
 lisp/gnus/deuglify.el                              |    10 +-
 lisp/gnus/gnus-art.el                              |   299 +-
 lisp/gnus/gnus-bookmark.el                         |    24 +-
 lisp/gnus/gnus-cache.el                            |     8 +-
 lisp/gnus/gnus-cite.el                             |    12 +-
 lisp/gnus/gnus-cus.el                              |     9 +-
 lisp/gnus/gnus-delay.el                            |     8 +-
 lisp/gnus/gnus-diary.el                            |     4 +-
 lisp/gnus/gnus-dired.el                            |     9 +-
 lisp/gnus/gnus-draft.el                            |     6 +-
 lisp/gnus/gnus-eform.el                            |     4 +-
 lisp/gnus/gnus-fun.el                              |    19 +-
 lisp/gnus/gnus-gravatar.el                         |     4 +-
 lisp/gnus/gnus-group.el                            |   276 +-
 lisp/gnus/gnus-icalendar.el                        |    14 +-
 lisp/gnus/gnus-int.el                              |     2 +-
 lisp/gnus/gnus-kill.el                             |     4 +-
 lisp/gnus/gnus-mh.el                               |     2 +-
 lisp/gnus/gnus-msg.el                              |   100 +-
 lisp/gnus/gnus-picon.el                            |     8 +-
 lisp/gnus/gnus-registry.el                         |    12 +-
 lisp/gnus/gnus-salt.el                             |    10 +-
 lisp/gnus/gnus-score.el                            |    51 +-
 lisp/gnus/gnus-search.el                           |    20 +-
 lisp/gnus/gnus-sieve.el                            |     2 +-
 lisp/gnus/gnus-srvr.el                             |    68 +-
 lisp/gnus/gnus-start.el                            |    16 +-
 lisp/gnus/gnus-sum.el                              |   607 +-
 lisp/gnus/gnus-topic.el                            |   101 +-
 lisp/gnus/gnus-util.el                             |     8 +-
 lisp/gnus/gnus-uu.el                               |    99 +-
 lisp/gnus/gnus-vm.el                               |     4 +-
 lisp/gnus/gnus.el                                  |    48 +-
 lisp/gnus/message.el                               |   147 +-
 lisp/gnus/mml-sec.el                               |    44 +-
 lisp/gnus/mml.el                                   |     2 +-
 lisp/gnus/nnagent.el                               |     1 +
 lisp/gnus/nnbabyl.el                               |     4 +-
 lisp/gnus/nnfolder.el                              |     4 +-
 lisp/gnus/nnimap.el                                |     3 +-
 lisp/gnus/nnmail.el                                |     8 -
 lisp/gnus/nnmaildir.el                             |     2 +-
 lisp/gnus/nnmh.el                                  |     2 +
 lisp/gnus/nnrss.el                                 |    65 +-
 lisp/gnus/nnselect.el                              |     2 +-
 lisp/gnus/nntp.el                                  |     2 +-
 lisp/gnus/score-mode.el                            |     6 +-
 lisp/gnus/smiley.el                                |     2 +-
 lisp/gnus/smime.el                                 |     4 +-
 lisp/gnus/spam-report.el                           |     6 +-
 lisp/gnus/spam-stat.el                             |     1 -
 lisp/gnus/spam.el                                  |    11 +-
 lisp/help-at-pt.el                                 |     5 +-
 lisp/help-fns.el                                   |    59 +-
 lisp/help-macro.el                                 |   226 +-
 lisp/help-mode.el                                  |    32 +-
 lisp/help.el                                       |   153 +-
 lisp/hi-lock.el                                    |    52 +-
 lisp/htmlfontify.el                                |    32 +-
 lisp/ibuffer.el                                    |   585 +-
 lisp/ido.el                                        |     4 +-
 lisp/iimage.el                                     |    13 +-
 lisp/image-dired.el                                |     7 +-
 lisp/image-mode.el                                 |    34 +-
 lisp/image.el                                      |    52 +-
 lisp/image/exif.el                                 |     5 +-
 lisp/imenu.el                                      |    70 +-
 lisp/info.el                                       |    83 +-
 lisp/international/ccl.el                          |     6 -
 lisp/international/mule-cmds.el                    |    12 +-
 lisp/international/mule-conf.el                    |     6 +-
 lisp/international/mule-diag.el                    |     2 +
 lisp/international/mule-util.el                    |     3 +-
 lisp/international/quail.el                        |    43 +-
 lisp/isearch.el                                    |   292 +-
 lisp/jit-lock.el                                   |     2 +-
 lisp/json.el                                       |   380 +-
 lisp/language/cyrillic.el                          |     2 +-
 lisp/ldefs-boot.el                                 |   462 +-
 lisp/leim/quail/hangul.el                          |    22 +-
 lisp/leim/quail/indian.el                          |    20 +-
 lisp/leim/quail/ipa-praat.el                       |     2 +-
 lisp/leim/quail/ipa.el                             |    12 +-
 lisp/leim/quail/japanese.el                        |    10 +-
 lisp/leim/quail/lao.el                             |     4 +-
 lisp/leim/quail/latin-ltx.el                       |     2 +-
 lisp/leim/quail/latin-post.el                      |     2 +-
 lisp/leim/quail/latin-pre.el                       |     2 +-
 lisp/leim/quail/lrt.el                             |     4 +-
 lisp/leim/quail/programmer-dvorak.el               |     2 +-
 lisp/leim/quail/sisheng.el                         |     2 +-
 lisp/leim/quail/thai.el                            |     2 +-
 lisp/leim/quail/tibetan.el                         |     8 +-
 lisp/leim/quail/uni-input.el                       |    19 +-
 lisp/loadup.el                                     |     6 +-
 lisp/mail/binhex.el                                |    14 +-
 lisp/mail/blessmail.el                             |     2 +-
 lisp/mail/emacsbug.el                              |    28 +-
 lisp/mail/feedmail.el                              |    12 +-
 lisp/mail/flow-fill.el                             |     4 +-
 lisp/mail/ietf-drums.el                            |     4 +-
 lisp/mail/mail-extr.el                             |    47 +-
 lisp/mail/mail-hist.el                             |    15 +-
 lisp/mail/mail-utils.el                            |    10 +-
 lisp/mail/mailabbrev.el                            |    30 +-
 lisp/mail/mailclient.el                            |     2 +-
 lisp/mail/mailheader.el                            |    35 +-
 lisp/mail/mspools.el                               |    10 +-
 lisp/mail/rfc822.el                                |     2 +-
 lisp/mail/rmail-spam-filter.el                     |    46 +-
 lisp/mail/rmail.el                                 |     8 +-
 lisp/mail/rmailedit.el                             |     8 +-
 lisp/mail/rmailkwd.el                              |     4 +-
 lisp/mail/rmailmm.el                               |   194 +-
 lisp/mail/rmailmsc.el                              |     4 +-
 lisp/mail/rmailout.el                              |    11 +-
 lisp/mail/rmailsort.el                             |     6 +-
 lisp/mail/smtpmail.el                              |     8 +-
 lisp/mail/supercite.el                             |   102 +-
 lisp/mail/uce.el                                   |    27 +-
 lisp/mail/unrmail.el                               |     4 +-
 lisp/man.el                                        |    41 +-
 lisp/master.el                                     |    15 +-
 lisp/mb-depth.el                                   |    15 +-
 lisp/menu-bar.el                                   |     2 +-
 lisp/mh-e/mh-acros.el                              |    33 +-
 lisp/mh-e/mh-alias.el                              |    19 +-
 lisp/mh-e/mh-buffers.el                            |     2 +-
 lisp/mh-e/mh-comp.el                               |    20 +-
 lisp/mh-e/mh-compat.el                             |     8 +-
 lisp/mh-e/mh-e.el                                  |    75 +-
 lisp/mh-e/mh-folder.el                             |    24 +-
 lisp/mh-e/mh-funcs.el                              |     4 +-
 lisp/mh-e/mh-gnus.el                               |     4 +-
 lisp/mh-e/mh-identity.el                           |    12 +-
 lisp/mh-e/mh-inc.el                                |    18 +-
 lisp/mh-e/mh-junk.el                               |     2 +-
 lisp/mh-e/mh-letter.el                             |    15 +-
 lisp/mh-e/mh-limit.el                              |     4 +-
 lisp/mh-e/mh-mime.el                               |    58 +-
 lisp/mh-e/mh-print.el                              |     7 +-
 lisp/mh-e/mh-scan.el                               |     4 +-
 lisp/mh-e/mh-search.el                             |    12 +-
 lisp/mh-e/mh-seq.el                                |    28 +-
 lisp/mh-e/mh-show.el                               |    10 +-
 lisp/mh-e/mh-speed.el                              |    12 +-
 lisp/mh-e/mh-thread.el                             |     2 +-
 lisp/mh-e/mh-tool-bar.el                           |     6 +-
 lisp/mh-e/mh-utils.el                              |    22 +-
 lisp/mh-e/mh-xface.el                              |     4 +-
 lisp/minibuffer.el                                 |    21 +-
 lisp/misc.el                                       |     2 +-
 lisp/mouse-copy.el                                 |     5 +-
 lisp/mouse-drag.el                                 |     2 +-
 lisp/mouse.el                                      |     4 +-
 lisp/mwheel.el                                     |     1 +
 lisp/net/ange-ftp.el                               |     7 +-
 lisp/net/browse-url.el                             |    42 +-
 lisp/net/dbus.el                                   |     6 +-
 lisp/net/dictionary-connection.el                  |    18 +-
 lisp/net/dictionary.el                             |   106 +-
 lisp/net/dig.el                                    |     4 +-
 lisp/net/dns.el                                    |    31 +-
 lisp/net/eudc-bob.el                               |    20 +-
 lisp/net/eudc-export.el                            |    78 +-
 lisp/net/eudc-hotlist.el                           |    14 +-
 lisp/net/eudc.el                                   |    20 +-
 lisp/net/eudcb-bbdb.el                             |   125 +-
 lisp/net/eudcb-ldap.el                             |    18 +-
 lisp/net/eudcb-mab.el                              |     2 +-
 lisp/net/eudcb-macos-contacts.el                   |     6 +-
 lisp/net/eww.el                                    |    82 +-
 lisp/net/gnutls.el                                 |     9 +-
 lisp/net/goto-addr.el                              |    28 +-
 lisp/net/mailcap.el                                |     2 +-
 lisp/net/net-utils.el                              |    84 +-
 lisp/net/network-stream.el                         |     3 +-
 lisp/net/newst-backend.el                          |   263 +-
 lisp/net/newst-plainview.el                        |   124 +-
 lisp/net/newst-reader.el                           |    10 +-
 lisp/net/newst-ticker.el                           |    12 +-
 lisp/net/newst-treeview.el                         |   208 +-
 lisp/net/nsm.el                                    |     2 +-
 lisp/net/puny.el                                   |     6 +-
 lisp/net/quickurl.el                               |    29 +-
 lisp/net/rcirc.el                                  |     5 +-
 lisp/net/secrets.el                                |    10 +-
 lisp/net/shr-color.el                              |    14 +-
 lisp/net/shr.el                                    |    27 +-
 lisp/net/sieve-mode.el                             |     6 +-
 lisp/net/sieve.el                                  |    82 +-
 lisp/net/snmp-mode.el                              |    44 +-
 lisp/net/soap-client.el                            |    26 +-
 lisp/net/soap-inspect.el                           |    46 +-
 lisp/net/socks.el                                  |     4 +-
 lisp/net/telnet.el                                 |    20 +-
 lisp/net/tramp-adb.el                              |     2 -
 lisp/net/tramp-cache.el                            |    28 +-
 lisp/net/tramp-cmds.el                             |    19 +-
 lisp/net/tramp-compat.el                           |     2 +-
 lisp/net/tramp-crypt.el                            |    24 +
 lisp/net/tramp-fuse.el                             |   205 +
 lisp/net/tramp-gvfs.el                             |     4 +-
 lisp/net/tramp-integration.el                      |    24 +-
 lisp/net/tramp-rclone.el                           |   256 +-
 lisp/net/tramp-sh.el                               |   443 +-
 lisp/net/tramp-smb.el                              |    12 +-
 lisp/net/tramp-sshfs.el                            |   367 +
 lisp/net/tramp-sudoedit.el                         |    25 +-
 lisp/net/tramp.el                                  |   174 +-
 lisp/net/trampver.el                               |     5 +
 lisp/net/webjump.el                                |     2 +-
 lisp/newcomment.el                                 |     6 +-
 lisp/notifications.el                              |    99 +-
 lisp/novice.el                                     |     2 +-
 lisp/nxml/nxml-mode.el                             |     2 +-
 lisp/nxml/rng-cmpct.el                             |     2 +-
 lisp/nxml/rng-nxml.el                              |     1 -
 lisp/nxml/rng-xsd.el                               |     6 +-
 lisp/obsolete/abbrevlist.el                        |     4 +-
 lisp/obsolete/bruce.el                             |    10 +-
 lisp/obsolete/cc-compat.el                         |     4 +-
 lisp/obsolete/cl-compat.el                         |    51 +-
 lisp/obsolete/cl.el                                |    38 +-
 lisp/obsolete/complete.el                          |    76 +-
 lisp/obsolete/crisp.el                             |   130 +-
 lisp/obsolete/cust-print.el                        |    47 +-
 lisp/obsolete/erc-compat.el                        |     7 +-
 lisp/obsolete/erc-hecomplete.el                    |    11 +-
 lisp/obsolete/eudcb-ph.el                          |     6 +-
 lisp/obsolete/fast-lock.el                         |   142 +-
 lisp/obsolete/gs.el                                |     4 +-
 lisp/obsolete/gulp.el                              |    17 +-
 lisp/obsolete/html2text.el                         |     2 +-
 lisp/obsolete/info-edit.el                         |     2 +-
 lisp/{cedet => obsolete}/inversion.el              |    36 +-
 lisp/obsolete/iswitchb.el                          |   192 +-
 lisp/obsolete/landmark.el                          |   153 +-
 lisp/obsolete/lazy-lock.el                         |   166 +-
 lisp/obsolete/longlines.el                         |    53 +-
 lisp/obsolete/mailpost.el                          |     4 +-
 lisp/obsolete/mantemp.el                           |     2 +-
 lisp/obsolete/meese.el                             |     2 +-
 lisp/obsolete/messcompat.el                        |     2 +-
 lisp/obsolete/metamail.el                          |    13 +-
 lisp/obsolete/mouse-sel.el                         |    16 +-
 lisp/obsolete/nnir.el                              |   101 +-
 lisp/obsolete/old-emacs-lock.el                    |    14 +-
 lisp/obsolete/otodo-mode.el                        |   111 +-
 lisp/obsolete/patcomp.el                           |     2 +-
 lisp/obsolete/pc-mode.el                           |    18 +-
 lisp/obsolete/pc-select.el                         |    15 +-
 lisp/obsolete/pgg-def.el                           |    10 +-
 lisp/obsolete/pgg-gpg.el                           |    12 +-
 lisp/obsolete/pgg-parse.el                         |    18 +-
 lisp/obsolete/pgg-pgp.el                           |    16 +-
 lisp/obsolete/pgg-pgp5.el                          |    14 +-
 lisp/obsolete/pgg.el                               |   113 +-
 lisp/obsolete/rcompile.el                          |    21 +-
 lisp/obsolete/s-region.el                          |     8 +-
 lisp/obsolete/sb-image.el                          |     2 +-
 lisp/obsolete/sregex.el                            |    36 +-
 lisp/obsolete/starttls.el                          |    34 +-
 lisp/obsolete/sup-mouse.el                         |     2 +-
 lisp/obsolete/terminal.el                          |    74 +-
 lisp/obsolete/tls.el                               |    33 +-
 lisp/obsolete/tpu-edt.el                           |   435 +-
 lisp/obsolete/tpu-extras.el                        |    35 +-
 lisp/obsolete/tpu-mapper.el                        |     2 +-
 lisp/obsolete/url-ns.el                            |    43 +-
 lisp/obsolete/vc-arch.el                           |    31 +-
 lisp/obsolete/vi.el                                |   308 +-
 lisp/obsolete/vip.el                               |   324 +-
 lisp/obsolete/ws-mode.el                           |   242 +-
 lisp/obsolete/yow.el                               |     5 +-
 lisp/org/ob-clojure.el                             |     2 +-
 lisp/org/ob-comint.el                              |     6 +-
 lisp/org/ob-core.el                                |    17 +-
 lisp/org/ob-lilypond.el                            |     6 +-
 lisp/org/ob-ocaml.el                               |     2 +-
 lisp/org/ob-tangle.el                              |     3 +-
 lisp/org/ol-gnus.el                                |     4 +-
 lisp/org/ol.el                                     |     6 +-
 lisp/org/org-agenda.el                             |    11 +-
 lisp/org/org-clock.el                              |    14 +-
 lisp/org/org-crypt.el                              |     2 +
 lisp/org/org-element.el                            |     2 +-
 lisp/org/org-install.el                            |     2 +-
 lisp/org/org-macs.el                               |    61 +-
 lisp/org/org-pcomplete.el                          |    11 +-
 lisp/org/org-protocol.el                           |     4 +-
 lisp/org/org-tempo.el                              |     2 +-
 lisp/org/org-version.el                            |     2 +-
 lisp/org/org.el                                    |     6 +-
 lisp/org/ox-odt.el                                 |    11 +-
 lisp/org/ox-texinfo.el                             |    16 +
 lisp/org/ox.el                                     |     4 +-
 lisp/outline.el                                    |    89 +-
 lisp/pcmpl-gnu.el                                  |     8 +-
 lisp/pcmpl-linux.el                                |    11 +-
 lisp/pcmpl-unix.el                                 |     2 +-
 lisp/pcmpl-x.el                                    |     5 +-
 lisp/play/5x5.el                                   |    31 +-
 lisp/play/blackbox.el                              |    16 +-
 lisp/play/bubbles.el                               |   148 +-
 lisp/play/decipher.el                              |   104 +-
 lisp/play/doctor.el                                |     2 +-
 lisp/play/gomoku.el                                |   109 +-
 lisp/play/handwrite.el                             |     3 +-
 lisp/play/morse.el                                 |     2 +-
 lisp/play/snake.el                                 |    15 +-
 lisp/play/tetris.el                                |    19 +-
 lisp/plstore.el                                    |     3 +-
 lisp/printing.el                                   |    90 +-
 lisp/progmodes/antlr-mode.el                       |   476 +-
 lisp/progmodes/asm-mode.el                         |    20 +-
 lisp/progmodes/bug-reference.el                    |     3 +-
 lisp/progmodes/cc-align.el                         |     7 +-
 lisp/progmodes/cc-cmds.el                          |   109 +-
 lisp/progmodes/cc-defs.el                          |    20 +-
 lisp/progmodes/cc-engine.el                        |   244 +-
 lisp/progmodes/cc-langs.el                         |    50 +-
 lisp/progmodes/cfengine.el                         |     8 +-
 lisp/progmodes/cmacexp.el                          |    12 +-
 lisp/progmodes/compile.el                          |    12 +-
 lisp/progmodes/cperl-mode.el                       |  1017 +-
 lisp/progmodes/cpp.el                              |    43 +-
 lisp/progmodes/cwarn.el                            |     9 +-
 lisp/progmodes/dcl-mode.el                         |   187 +-
 lisp/progmodes/ebnf-abn.el                         |     6 +-
 lisp/progmodes/ebnf-bnf.el                         |     2 +-
 lisp/progmodes/ebnf-dtd.el                         |     2 +-
 lisp/progmodes/ebnf-ebx.el                         |     2 +-
 lisp/progmodes/ebnf-iso.el                         |     4 +-
 lisp/progmodes/ebnf-otz.el                         |     2 +-
 lisp/progmodes/ebnf-yac.el                         |     2 +-
 lisp/progmodes/ebnf2ps.el                          |    10 +-
 lisp/progmodes/ebrowse.el                          |     5 +-
 lisp/progmodes/elisp-mode.el                       |   305 +-
 lisp/progmodes/etags.el                            |    18 +-
 lisp/progmodes/executable.el                       |    29 +-
 lisp/progmodes/flymake.el                          |    18 +-
 lisp/progmodes/grep.el                             |    87 +-
 lisp/progmodes/gud.el                              |    28 +-
 lisp/progmodes/hideif.el                           |     2 +-
 lisp/progmodes/hideshow.el                         |     7 +-
 lisp/progmodes/icon.el                             |   119 +-
 lisp/progmodes/idlw-complete-structtag.el          |     9 +-
 lisp/progmodes/idlw-help.el                        |    97 +-
 lisp/progmodes/idlw-shell.el                       |   213 +-
 lisp/progmodes/idlw-toolbar.el                     |   117 +-
 lisp/progmodes/idlwave.el                          |  1030 +-
 lisp/progmodes/inf-lisp.el                         |    19 +-
 lisp/progmodes/js.el                               |    60 +-
 lisp/progmodes/ld-script.el                        |     3 +-
 lisp/progmodes/m4-mode.el                          |    76 +-
 lisp/progmodes/make-mode.el                        |   188 +-
 lisp/progmodes/meta-mode.el                        |    99 +-
 lisp/progmodes/modula2.el                          |    71 +-
 lisp/progmodes/octave.el                           |    53 +-
 lisp/progmodes/pascal.el                           |    30 +-
 lisp/progmodes/perl-mode.el                        |    10 +-
 lisp/progmodes/prog-mode.el                        |     6 +-
 lisp/progmodes/project.el                          |    48 +-
 lisp/progmodes/prolog.el                           |     1 -
 lisp/progmodes/ps-mode.el                          |     1 -
 lisp/progmodes/ruby-mode.el                        |     6 +-
 lisp/progmodes/scheme.el                           |    60 +-
 lisp/progmodes/sh-script.el                        |   116 +-
 lisp/progmodes/simula.el                           |   110 +-
 lisp/progmodes/sql.el                              |     2 +-
 lisp/progmodes/tcl.el                              |     4 +-
 lisp/progmodes/vera-mode.el                        |     6 +-
 lisp/progmodes/verilog-mode.el                     |   468 +-
 lisp/progmodes/vhdl-mode.el                        |     5 +-
 lisp/progmodes/xref.el                             |   131 +-
 lisp/progmodes/xscheme.el                          |    16 +-
 lisp/ps-samp.el                                    |     2 +-
 lisp/recentf.el                                    |     1 -
 lisp/repeat.el                                     |    73 +-
 lisp/replace.el                                    |    78 +-
 lisp/ruler-mode.el                                 |    53 +-
 lisp/ses.el                                        |    36 +-
 lisp/shell.el                                      |    12 +-
 lisp/simple.el                                     |   334 +-
 lisp/skeleton.el                                   |    11 +-
 lisp/speedbar.el                                   |    60 +-
 lisp/subr.el                                       |   301 +-
 lisp/tab-bar.el                                    |   778 +-
 lisp/tab-line.el                                   |   132 +-
 lisp/talk.el                                       |     4 +-
 lisp/tar-mode.el                                   |    76 +-
 lisp/term.el                                       |     6 +-
 lisp/term/w32-win.el                               |     3 +
 lisp/textmodes/artist.el                           |    92 +-
 lisp/textmodes/bib-mode.el                         |    12 +-
 lisp/textmodes/bibtex-style.el                     |     4 +-
 lisp/textmodes/bibtex.el                           |     4 +-
 lisp/textmodes/conf-mode.el                        |    83 +-
 lisp/textmodes/css-mode.el                         |     2 +-
 lisp/textmodes/dns-mode.el                         |    26 +-
 lisp/textmodes/enriched.el                         |    57 +-
 lisp/textmodes/fill.el                             |    15 +-
 lisp/textmodes/flyspell.el                         |     4 +-
 lisp/textmodes/ispell.el                           |    94 +-
 lisp/textmodes/less-css-mode.el                    |    10 +-
 lisp/textmodes/makeinfo.el                         |    12 +-
 lisp/textmodes/mhtml-mode.el                       |     2 +-
 lisp/textmodes/nroff-mode.el                       |    54 +-
 lisp/textmodes/page-ext.el                         |     2 +-
 lisp/textmodes/paragraphs.el                       |    25 +-
 lisp/textmodes/picture.el                          |    24 +-
 lisp/textmodes/refbib.el                           |    27 +-
 lisp/textmodes/refer.el                            |    18 +-
 lisp/textmodes/refill.el                           |    21 +-
 lisp/textmodes/reftex-auc.el                       |    54 +-
 lisp/textmodes/reftex-cite.el                      |    71 +-
 lisp/textmodes/reftex-dcr.el                       |    46 +-
 lisp/textmodes/reftex-global.el                    |    34 +-
 lisp/textmodes/reftex-index.el                     |   259 +-
 lisp/textmodes/reftex-parse.el                     |    17 +-
 lisp/textmodes/reftex-ref.el                       |    38 +-
 lisp/textmodes/reftex-sel.el                       |   207 +-
 lisp/textmodes/reftex-toc.el                       |   114 +-
 lisp/textmodes/reftex-vars.el                      |    20 +-
 lisp/textmodes/reftex.el                           |   196 +-
 lisp/textmodes/remember.el                         |    75 +-
 lisp/textmodes/rst.el                              |     6 +-
 lisp/textmodes/sgml-mode.el                        |    92 +-
 lisp/textmodes/table.el                            |   108 +-
 lisp/textmodes/tex-mode.el                         |    72 +-
 lisp/textmodes/texinfmt.el                         |   160 +-
 lisp/textmodes/texinfo.el                          |   145 +-
 lisp/textmodes/texnfo-upd.el                       |    32 +-
 lisp/textmodes/text-mode.el                        |    49 +-
 lisp/textmodes/tildify.el                          |    15 +-
 lisp/textmodes/two-column.el                       |    48 +-
 lisp/thumbs.el                                     |    92 +-
 lisp/time.el                                       |    13 +-
 lisp/tooltip.el                                    |    13 +-
 lisp/tutorial.el                                   |    12 +-
 lisp/uniquify.el                                   |    22 +-
 lisp/url/ChangeLog.1                               |     2 +-
 lisp/url/url-cookie.el                             |     2 +-
 lisp/url/url-http.el                               |     2 +-
 lisp/url/url-news.el                               |     5 -
 lisp/userlock.el                                   |    83 +-
 lisp/vc/add-log.el                                 |   113 +-
 lisp/vc/compare-w.el                               |    26 +-
 lisp/vc/cvs-status.el                              |    16 +-
 lisp/vc/diff-mode.el                               |    16 +-
 lisp/vc/diff.el                                    |    12 +-
 lisp/vc/ediff-diff.el                              |     2 +-
 lisp/vc/ediff-help.el                              |     2 +-
 lisp/vc/ediff-init.el                              |    50 +-
 lisp/vc/ediff-merg.el                              |     2 +-
 lisp/vc/ediff-mult.el                              |    49 +-
 lisp/vc/ediff-util.el                              |   148 +-
 lisp/vc/ediff-vers.el                              |    18 +-
 lisp/vc/ediff-wind.el                              |     6 +-
 lisp/vc/ediff.el                                   |    52 +-
 lisp/vc/emerge.el                                  |    69 +-
 lisp/vc/pcvs-defs.el                               |    19 +-
 lisp/vc/pcvs-info.el                               |     6 +-
 lisp/vc/pcvs-parse.el                              |    27 +-
 lisp/vc/pcvs-util.el                               |    30 +-
 lisp/vc/pcvs.el                                    |    14 +-
 lisp/vc/smerge-mode.el                             |    47 +-
 lisp/vc/vc-annotate.el                             |    24 +-
 lisp/vc/vc-bzr.el                                  |    73 +-
 lisp/vc/vc-cvs.el                                  |    49 +-
 lisp/vc/vc-dav.el                                  |    22 +-
 lisp/vc/vc-dir.el                                  |   151 +-
 lisp/vc/vc-dispatcher.el                           |    12 +-
 lisp/vc/vc-filewise.el                             |     2 +-
 lisp/vc/vc-git.el                                  |    65 +-
 lisp/vc/vc-hg.el                                   |    55 +-
 lisp/vc/vc-hooks.el                                |    72 +-
 lisp/vc/vc-mtn.el                                  |    20 +-
 lisp/vc/vc-rcs.el                                  |    28 +-
 lisp/vc/vc-sccs.el                                 |    36 +-
 lisp/vc/vc-src.el                                  |    21 +-
 lisp/vc/vc-svn.el                                  |    78 +-
 lisp/vc/vc.el                                      |     8 +-
 lisp/view.el                                       |   169 +-
 lisp/w32-fns.el                                    |     1 +
 lisp/wdired.el                                     |   384 +-
 lisp/wid-browse.el                                 |    34 +-
 lisp/wid-edit.el                                   |    15 +-
 lisp/window.el                                     |    27 +-
 lisp/woman.el                                      |   233 +-
 lisp/xdg.el                                        |     4 +-
 lwlib/Makefile.in                                  |    19 +-
 nt/Makefile.in                                     |    19 +-
 oldXMenu/Makefile.in                               |    19 +-
 src/Makefile.in                                    |    38 +-
 src/alloc.c                                        |    33 +
 src/buffer.c                                       |    19 +-
 src/buffer.h                                       |     3 +
 src/callint.c                                      |     9 +-
 src/callproc.c                                     |     6 +-
 src/coding.c                                       |     6 +
 src/data.c                                         |    98 +-
 src/dispnew.c                                      |    30 +-
 src/editfns.c                                      |    11 +-
 src/emacs-module.c                                 |     8 +-
 src/eval.c                                         |    43 +-
 src/filelock.c                                     |    28 +-
 src/fns.c                                          |   124 +-
 src/font.c                                         |     2 +-
 src/frame.c                                        |    10 +-
 src/gnutls.c                                       |     2 +
 src/gtkutil.c                                      |    22 +-
 src/image.c                                        |    36 +-
 src/indent.c                                       |     2 +-
 src/json.c                                         |    77 +-
 src/keyboard.c                                     |     9 +-
 src/keymap.c                                       |    25 +-
 src/lisp.h                                         |     7 +-
 src/marker.c                                       |     7 +-
 src/minibuf.c                                      |   369 +-
 src/nsterm.h                                       |     1 +
 src/nsterm.m                                       |    77 +-
 src/pdumper.c                                      |     9 +-
 src/process.c                                      |     2 +-
 src/sysdep.c                                       |    17 +-
 src/verbose.mk.in                                  |    42 +
 src/w32.c                                          |    51 +
 src/w32fns.c                                       |     2 +-
 src/window.c                                       |     3 +-
 src/window.h                                       |     4 -
 src/xdisp.c                                        |    46 +-
 src/xfaces.c                                       |    11 +-
 src/xfns.c                                         |     9 +-
 test/Makefile.in                                   |    39 +-
 test/README                                        |    13 +-
 test/file-organization.org                         |     4 +
 test/infra/Dockerfile.emba                         |    15 +-
 test/infra/gitlab-ci.yml                           |    37 +-
 test/lisp/autorevert-tests.el                      |     4 +-
 test/lisp/calc/calc-tests.el                       |    76 +
 .../import-rrule-anniversary.diary-american        |     2 +-
 .../import-rrule-anniversary.diary-european        |     2 +-
 .../import-rrule-anniversary.diary-iso             |     2 +-
 .../import-rrule-yearly.diary-american             |     2 +-
 .../import-rrule-yearly.diary-european             |     2 +-
 .../import-rrule-yearly.diary-iso                  |     2 +-
 test/lisp/calendar/icalendar-tests.el              |   112 +-
 test/lisp/cedet/semantic-utest-c.el                |     1 -
 test/lisp/cedet/semantic-utest.el                  |     2 +-
 test/lisp/cedet/semantic/bovine/gcc-tests.el       |     2 +-
 .../cedet/semantic/format-resources/test-fmt.el    |     2 +-
 test/lisp/cedet/semantic/format-tests.el           |     2 +-
 test/lisp/cedet/semantic/fw-tests.el               |     2 +-
 test/lisp/comint-tests.el                          |     1 +
 test/lisp/custom-tests.el                          |   171 +-
 test/lisp/electric-tests.el                        |    34 +-
 test/lisp/emacs-lisp/bindat-tests.el               |   134 +-
 test/lisp/emacs-lisp/bytecomp-tests.el             |    61 +-
 test/lisp/emacs-lisp/cconv-tests.el                |     9 +-
 test/lisp/emacs-lisp/checkdoc-tests.el             |    42 +-
 test/lisp/emacs-lisp/cl-generic-tests.el           |    12 +-
 test/lisp/emacs-lisp/cl-macs-tests.el              |    30 +-
 .../edebug-resources/edebug-test-code.el           |    20 +-
 test/lisp/emacs-lisp/edebug-tests.el               |    91 +-
 test/lisp/emacs-lisp/ert-tests.el                  |     2 +-
 test/lisp/emacs-lisp/generator-tests.el            |     3 +-
 test/lisp/emacs-lisp/macroexp-resources/m1.el      |    36 +
 test/lisp/emacs-lisp/macroexp-resources/m2.el      |    33 +
 test/lisp/emacs-lisp/macroexp-tests.el             |    72 +
 test/lisp/emacs-lisp/map-tests.el                  |   474 +-
 test/lisp/emacs-lisp/pcase-tests.el                |    27 +-
 test/lisp/emacs-lisp/rx-tests.el                   |    22 +-
 test/lisp/erc/erc-tests.el                         |    64 +
 test/lisp/filenotify-tests.el                      |   247 +-
 test/lisp/files-tests.el                           |    55 +-
 test/lisp/help-tests.el                            |    24 +-
 test/lisp/image-tests.el                           |    15 +-
 test/lisp/json-tests.el                            |   195 +-
 test/lisp/jsonrpc-tests.el                         |     2 +-
 test/lisp/kmacro-tests.el                          |     2 +-
 test/lisp/mail/mail-utils-tests.el                 |   104 +
 test/lisp/minibuffer-tests.el                      |     6 +
 test/lisp/net/network-stream-tests.el              |     1 +
 test/lisp/net/ntlm-resources/authinfo              |     1 +
 test/lisp/net/ntlm-tests.el                        |   368 +
 test/lisp/net/puny-tests.el                        |     6 +-
 test/lisp/net/socks-tests.el                       |   291 +-
 test/lisp/net/tramp-tests.el                       |   103 +-
 test/lisp/{cedet => obsolete}/inversion-tests.el   |     0
 .../lisp/progmodes/cperl-mode-resources/grammar.pl |   158 +
 test/lisp/progmodes/cperl-mode-tests.el            |   143 +
 test/lisp/progmodes/elisp-mode-tests.el            |    19 +-
 test/lisp/progmodes/f90-tests.el                   |     3 -
 test/lisp/progmodes/xref-resources/file1.txt       |     2 +-
 test/lisp/progmodes/xref-resources/file3.txt       |     1 +
 test/lisp/progmodes/xref-tests.el                  |    48 +-
 test/lisp/simple-tests.el                          |   118 +-
 test/lisp/subr-tests.el                            |     7 +-
 test/lisp/textmodes/dns-mode-tests.el              |    21 +
 test/lisp/thumbs-tests.el                          |    34 +
 test/manual/biditest.el                            |     6 +-
 test/manual/cedet/cedet-utests.el                  |    45 +-
 test/manual/cedet/semantic-tests.el                |    21 +-
 test/manual/image-circular-tests.el                |     2 +-
 test/manual/image-size-tests.el                    |     5 +-
 test/manual/redisplay-testsuite.el                 |     2 +-
 test/misc/test-custom-deps.el                      |    42 +
 test/misc/test-custom-libs.el                      |    48 +
 test/misc/test-custom-noloads.el                   |    45 +
 test/misc/test-custom-opts.el                      |    39 +
 test/src/data-tests.el                             |    23 +
 test/src/editfns-tests.el                          |     4 +
 test/src/filelock-tests.el                         |   183 +
 test/src/json-tests.el                             |    28 +
 test/src/keyboard-tests.el                         |    39 +-
 test/src/keymap-tests.el                           |    58 +-
 test/src/process-tests.el                          |    23 +-
 test/src/undo-tests.el                             |     2 +
 1006 files changed, 64393 insertions(+), 62892 deletions(-)

diff --git a/.gitignore b/.gitignore
index dd4eab7..b653ef2 100644
--- a/.gitignore
+++ b/.gitignore
@@ -76,6 +76,7 @@ lib/unistd.h
 src/buildobj.h
 src/globals.h
 src/lisp.mk
+src/verbose.mk
 
 # Lisp-level sources built by 'make'.
 *cus-load.el
@@ -253,6 +254,8 @@ doc/*/*/*.ps
 doc/emacs/emacsver.texi
 doc/man/emacs.1
 doc/misc/cc-mode.ss
+doc/misc/modus-themes.texi
+doc/misc/org.texi
 etc/DOC
 etc/refcards/emacsver.tex
 gnustmp*
diff --git a/CONTRIBUTE b/CONTRIBUTE
index 9b2af9c..2d70c49 100644
--- a/CONTRIBUTE
+++ b/CONTRIBUTE
@@ -66,11 +66,18 @@ more reliably, and makes the job of applying the patches 
easier and less
 error-prone.  It also allows sending patches whose author is someone
 other than the email sender.
 
-Once the cumulative amount of your submissions exceeds about 15 lines
-of non-trivial code, we will need you to assign to the FSF the
-copyright for your contributions.  Ask on emacs-devel@gnu.org, and we
-will send you the necessary form together with the instructions to
-fill and email it, in order to start this legal paperwork.
+Once the cumulative amount of your submissions exceeds a dozen or so
+lines of non-trivial changes, we will need you to assign to the FSF
+the copyright for your contributions.  (To see how many lines were
+non-trivially changed, count only added and modified lines in the
+patched code.  Consider an added or changed line non-trivial if it
+includes at least one identifier, string, or substantial comment.)
+In most cases, to start the assignment process you should download
+https://git.savannah.gnu.org/cgit/gnulib.git/plain/doc/Copyright/request-assign.future
+and return the completed information to the address at the top.
+(There are other assignment options, but they are much less commonly used.)
+If you have questions about the assignment process, you can ask the
+address listed on the form, and/or emacs-devel@gnu.org.
 
 ** Issue tracker (a.k.a. "bug tracker")
 
diff --git a/ChangeLog.3 b/ChangeLog.3
index 460a1d2..8b872a0 100644
--- a/ChangeLog.3
+++ b/ChangeLog.3
@@ -1,3 +1,393 @@
+2021-03-25  Eli Zaretskii  <eliz@gnu.org>
+
+       * Version 27.2 released.
+
+2021-03-18 Basil L. Contovounesios <contovob@tcd.ie>
+
+       Fix 'frame-inner-height' in non-GUI builds
+
+       Include tab bar in frame's inner height in non-GUI builds that
+       don't define 'tab-bar-height'.  This is consistent with the
+       inclusion of the menu bar in the calculated height.  It is also
+       consistent with TTY frames of GUI builds, for which
+       'tab-bar-height' is always zero anyway (bug#47234).
+       Fix suggested by Eli Zaretskii <eliz@gnu.org>.
+
+       * lisp/frame.el (frame-inner-height): Don't assume
+       'tab-bar-height' is defined in builds --without-x.
+
+2021-03-18  Eli Zaretskii  <eliz@gnu.org>
+
+       * etc/HISTORY: Update for Emacs 27.2.
+
+       * README:
+       * configure.ac:
+       * nt/README.W32:
+       * msdos/sed2v2.inp: Set version to 27.2
+
+2021-03-18  Lars Ingebrigtsen  <larsi@gnus.org>
+
+       Document that `buffer-string' retains text properties
+
+       * doc/lispref/text.texi (Buffer Contents): Mention text properties
+       in the `buffer-string' documentation.
+       * src/editfns.c (Fbuffer_string): Mention text properties in the
+       doc string (bug#47220).
+
+       (cherry picked from commit 60af754170f22f5d25510af069ed0ebfec95f992)
+
+2021-03-18  Fabrice Bauzac  <noon@mykolab.com>
+
+       Remove duplicate @table item from ELisp manual
+
+       * doc/lispref/objects.texi (Special Read Syntax): Remove duplicate
+       item "#@N" from the table of Special Read Syntax.  (Bug#47200)
+
+2021-03-18  Daniel Martín  <mardani29@yahoo.es>
+
+       Fix reference to 'diff-font-lock-syntax' in diff-mode documentation
+
+       * doc/emacs/files.texi (Diff Mode): Add the omitted name of the
+       variable.  (Bug#47129)
+
+2021-03-18  Alan Third  <alan@idiocy.org>
+
+       Fix buffer overflow in xbm_scan (bug#47094)
+
+       * src/image.c (xbm_scan): Ensure reading a string doesn't overflow the
+       buffer.
+
+       (cherry picked from commit ebc3b25409dd614c1814a0643960452683e37aa3)
+
+2021-03-18  Matt Armstrong  <matt@rfc20.org>
+
+       Fix typos and omissions for (elisp)Button Buffer Commands
+
+       * doc/lispref/display.texi (Button Buffer Commands): Minor
+       typo and omission fixes `backward-button' and
+       `forward-button'.  (Bug#47051)
+
+2021-03-18  Eli Zaretskii  <eliz@gnu.org>
+
+       Teach Rmail about NBSP in "Re:"
+
+       * lisp/mail/rmail.el (rmail-simplified-subject)
+       (rmail-reply-regexp): Allow NBSP in "RE:" prefixes.
+
+2021-03-18  Stefan Monnier  <monnier@iro.umontreal.ca>
+
+       Revert "* lisp/mouse.el: Fix mouse-1-clock-follows-mouse = double"
+
+       This reverts commit 02a5cfce471613f671722b35536d2a78f17b0429.
+       That commit breaks because of a missing patch to 
`parse_modifiers_uncached`
+       in `src/keyboard.c`.  IOW, too risky for `emacs-27`.
+
+       Don't merge to `master`.
+
+2021-03-18  Stefan Monnier  <monnier@iro.umontreal.ca>
+
+       * lisp/mouse.el: Fix mouse-1-clock-follows-mouse = double
+
+       This functionality was broken by commit 3d5e31eceb9dc1fb62b2b2,
+       the problem being that we end up considering as distinct the events
+       `down-double-mouse-1` and `double-down-mouse-1`.
+
+       Reported by Eyal Soha <eyalsoha@gmail.com>
+
+       (mouse--click-1-maybe-follows-link): Make sure the last element of
+       the list passed to `event-convert-list` is indeed a "basic" event.
+
+2021-03-18  Stefan Monnier  <monnier@iro.umontreal.ca>
+
+       * lisp/emacs-lisp/gv.el (edebug-after): Don't run the getter in the 
setter
+
+       This fixes bug#46573 which was introduced by commit
+       d79cf638f278e50c22feb53d6ba556f5ce9d7853.
+       The new code is a middle ground, which makes sure the instrumentation
+       point is used (so the coverage checker won't have ghost unreachable
+       instrumentation points) yet without artificially running the getter
+       when we only need to run the setter.
+
+2021-03-18  Masahiro Nakamura  <tsuucat@icloud.com>
+
+       * doc/misc/tramp.texi (Remote shell setup): Fix reference. (Do not 
merge)
+
+2021-03-18  Eli Zaretskii  <eliz@gnu.org>
+
+       Fix initialization of 'while-no-input-ignore-events'
+
+       * src/keyboard.c (syms_of_keyboard_for_pdumper): Don't reset
+       'while-no-input-ignore-events' after loading the dump file.
+       (Bug#46940)
+
+2021-03-18  Eli Zaretskii  <eliz@gnu.org>
+
+       Update documentation of reading passwords
+
+       * doc/emacs/mini.texi (Passwords): Update to match the modified
+       implementation.  (Bug#46902)  Add indexing.
+
+2021-03-18  Lars Ingebrigtsen  <larsi@gnus.org>
+
+       Improve the 'dired-do-kill-lines' doc string
+
+       * lisp/dired-aux.el (dired-do-kill-lines): Document the FMT
+       parameter (bug#46867).
+
+       (cherry picked from commit b9cb3b904008a80c69ab433f4851377967b100db)
+
+2021-03-18  Eli Zaretskii  <eliz@gnu.org>
+
+       Avoid crashes in Mew due to corrupted tool-bar label
+
+       * src/gtkutil.c (update_frame_tool_bar): Don't keep around a
+       'char *' pointer to a Lisp string's contents when calling Lisp,
+       because that could relocate string data; keep the Lisp string
+       itself instead.  This avoids crashes in Mew.  (Bug#46791)
+
+2021-03-18  Stefan Kangas  <stefan@marxist.se>
+
+       * lisp/tooltip.el (tooltip): Doc fix for GTK.
+
+2021-03-18  Stefan Kangas  <stefan@marxist.se>
+
+       * lisp/help.el (help-for-help-internal): Doc fix; use imperative.
+
+2021-03-18  Eli Zaretskii  <eliz@gnu.org>
+
+       More accurate documentation of the "r" interactive spec
+
+       * doc/lispref/commands.texi (Interactive Codes): Describe the
+       effect of 'mark-even-if-inactive'.
+
+2021-03-18  Stefan Kangas  <stefan@marxist.se>
+
+       Mention the GNU Kind Communications Guidelines in the FAQ
+
+       * doc/misc/efaq.texi (Guidelines for newsgroup postings): Mention
+       the GNU Kind Communications Guidelines.
+
+2021-03-18  Ryan Prior  <rprior@protonmail.com>  (tiny change)
+
+       Allow newlines in password prompts again in comint
+
+       * lisp/comint.el (comint-password-prompt-regexp): Match all
+       whitespace (including newline) at the end of the passphrase, not
+       just space and \t (bug#46609).
+       (comint-watch-for-password-prompt): Remove trailing newlines from
+       the prompt (bug#46609).
+
+2021-03-18  Eli Zaretskii  <eliz@gnu.org>
+
+       Avoid point movement when visiting image files
+
+       * lisp/image-mode.el (image-toggle-display-image): Preserve point
+       around the call to exif-parse-buffer, to prevent it from moving
+       into the image data.  (Bug#46552)
+
+2021-03-18  Eli Zaretskii  <eliz@gnu.org>
+
+       Avoid assertion violation in callproc.c
+
+       * src/callproc.c (call_process): Avoid assertion violation when
+       DESTINATION is a cons cell '(:file . "FOO")'.  (Bug#46426)
+
+2021-03-18  Lars Ingebrigtsen  <larsi@gnus.org>
+
+       Clarify "changes" in CONTRIBUTE
+
+       * CONTRIBUTE: Clarify that "changes" doesn't include removing code
+       (bug#44834).
+
+       (cherry picked from commit 33c9556c9db9b8c62dcd80dd3cc665e669ea66d4)
+
+2021-03-18  Lars Ingebrigtsen  <larsi@gnus.org>
+
+       Clarify when activate-mark-hook is run
+
+       * doc/lispref/markers.texi (The Mark):
+       * lisp/simple.el (activate-mark-hook): Clarify when the hook is
+       run (bug#23444).
+
+2021-03-18  Eli Zaretskii  <eliz@gnu.org>
+
+       Fix language-environment and font selection on MS-Windows
+
+       These changes improve setting the language-environment and font
+       selection when MS-Windows returns useless "ZZZ" as the "language
+       name", which then disrupts all the setup of the locale-dependent
+       stuff, and in particular font selection.
+       * lisp/w32-fns.el (w32-charset-info-alist): Add an element for
+       "iso8859-5", in case LANG is set to something unusable, like
+       "ZZZ".  This allows fonts capable of displaying Cyrillic
+       characters to be used even when language preferences are screwed.
+
+       * src/w32.c (init_environment): If GetLocaleInfo returns "ZZZ" as
+       the "language name" for LOCALE_USER_DEFAULT, try again with locale
+       ID based on what GetUserDefaultUILanguage returns.  (Bug#39286)
+
+2021-03-18  Petteri Hintsanen  <petterih@iki.fi>
+
+       Fix example in Sequence Functions node in the manual
+
+       * doc/lispref/sequences.texi (Sequence Functions): Fix the result
+       from the example.
+
+2021-03-18  Eli Zaretskii  <eliz@gnu.org>
+
+       Improve doc string of 'text-scale-adjust'
+
+       * lisp/face-remap.el (text-scale-adjust): Clarify that "default
+       face height" refers to the 'default' face.  (Bug#25168)
+
+2021-03-18  Lars Ingebrigtsen  <larsi@gnus.org>
+
+       Clarify the indent-rigidly doc string
+
+       * lisp/indent.el (indent-rigidly): Clarify exiting the transient
+       mode (bug#46296).
+
+2021-03-18  Martin Rudalics  <rudalics@gmx.at>
+
+       Fix two small tab bar issues
+
+       * lisp/cus-start.el (frame-inhibit-implied-resize): Update version tag.
+       * lisp/frame.el (frame-inner-height): Do not count in tab bar.
+
+2021-03-18  Eli Zaretskii  <eliz@gnu.org>
+
+       Fix last change in syntax.texi
+
+       * doc/lispref/syntax.texi (Syntax Properties): Fix wording in last
+       change.  (Bug#46274)
+
+2021-03-18  Lars Ingebrigtsen  <larsi@gnus.org>
+
+       Correct the lispref manual about flushing ppss info
+
+       * doc/lispref/syntax.texi (Syntax Properties): Correct the
+       information about flushing the state by copying the text from the
+       doc string (bug#46274).
+
+       (cherry picked from commit ff701ce2b261acce1dfcd1fe137268d87d5eab35)
+
+2021-03-18  Lars Ingebrigtsen  <larsi@gnus.org>
+
+       Clarify how transient indentation modes are exited in the manual
+
+       * doc/emacs/indent.texi (Indentation Commands): Clarify that the
+       other keys don't just exit the transient mode, but are also
+       handled as normally (bug#46296).
+
+2021-03-18  Dmitry Gutov  <dgutov@yandex.ru>
+
+       Fix the previous change
+
+       * lisp/progmodes/project.el (project-find-regexp):
+       Fix the previous change (project-root is not defined in this version).
+       (project-or-external-find-regexp): Same.
+
+2021-03-18  Dmitry Gutov  <dgutov@yandex.ru>
+
+       Bind default-directory to the project root
+
+       * lisp/progmodes/project.el (project-find-regexp):
+       Bind default-directory to the project root, to save this value
+       in the resulting buffer (esp. if the project selector was used,
+       (https://lists.gnu.org/archive/html/emacs-devel/2021-02/msg00140.html).
+       (project-or-external-find-regexp): Same.
+
+       (cherry picked from commit c07ebfcbe084e8219d8c2588f23f77ba4ef39087)
+
+2021-03-18  Dmitry Gutov  <dgutov@yandex.ru>
+
+       Make sure default-directory relates to the originating buffer
+
+       * lisp/progmodes/xref.el (xref--show-xref-buffer):
+       Pick up default-directory value from the caller
+       (https://lists.gnu.org/archive/html/emacs-devel/2021-01/msg00551.html).
+       (xref-show-definitions-buffer-at-bottom): Same.
+
+       (cherry picked from commit 6e73e07a6f5cbdd1c5ae6e0f3fbd0f8f56813f1a)
+
+2021-03-18  Eli Zaretskii  <eliz@gnu.org>
+
+       Initialize signal descriptions after pdumping
+
+       * src/sysdep.c (init_signals) [!HAVE_DECL_SYS_SIGLIST]: Reinit
+       sys_siglist also after pdumping.  (Bug#46284)
+
+2021-03-18  Lars Ingebrigtsen  <larsi@gnus.org>
+
+       Clarify the "Sentinels" node in the lispref manual
+
+       * doc/lispref/processes.texi (Sentinels): Mention "run" and that
+       the strings can be anything (bug#30461).
+
+       (cherry picked from commit 859a4cb6b22f75a3456e29d08fcfe9b8940fbe8b)
+
+2021-03-18  Alexandre Duret-Lutz  <adl@lrde.epita.fr>  (tiny change)
+
+       Fix problem with non-ASCII characters in nnmaildir
+
+       * lisp/gnus/nnmaildir.el (nnmaildir-request-article): Enable
+       multipart 8bit-content-transfer-encoded files to be displayed
+       correctly by reading as `raw-text' instead of having Emacs
+       (incorrectly) decode the files (bug#44307).
+
+2021-03-18  Eli Zaretskii  <eliz@gnu.org>
+
+       * lisp/window.el (recenter-top-bottom): Clarify doc string.
+
+2021-03-18  Thomas Fitzsimmons  <fitzsim@fitzsim.org>
+
+       url-http.el: Special-case NTLM authentication
+
+       * lisp/url/url-http.el (url-http-handle-authentication): Do not
+       signal an error on NTLM authorization strings.  (Bug#43566)
+
+2021-03-18  Juri Linkov  <juri@linkov.net>
+
+       * lisp/isearch.el (isearch-lazy-highlight): Fix defcustom type 
(bug#46208)
+
+2021-03-18  Stefan Kangas  <stefan@marxist.se>
+
+       Sync latest SKK-JISYO.L
+
+       * leim/SKK-DIC/SKK-JISYO.L: Sync to current upstream version.
+
+2021-03-18  Alan Third  <alan@idiocy.org>
+
+       Fix build failure on macOS 10.7 (bug#46036)
+
+       * src/nsfns.m (ns_set_represented_filename): Define the NSNumber in a
+       more compatible manner.
+
+2021-03-18  Eli Zaretskii  <eliz@gnu.org>
+
+       Improve documentation of auto-resize-tool/tab-bars
+
+       * src/xdisp.c (syms_of_xdisp) <auto-resize-tool-bars>
+       <auto-resize-tab-bars>: Doc fix.  (Bug#46178)
+
+2021-03-18  Dmitry Gutov  <dgutov@yandex.ru>
+
+       (xref-revert-buffer): Also 'erase-buffer' when handling a user-error
+
+       * lisp/progmodes/xref.el (xref-revert-buffer):
+       Also 'erase-buffer' when handling a user-error (bug#46042).
+
+       (cherry picked from commit e86b30d6fd04070b86560774ec82392dbe24ca1e)
+
+2021-03-18  Eli Zaretskii  <eliz@gnu.org>
+
+       Update files for 27.1.91 pretest
+
+       * ChangeLog.3:
+       * etc/AUTHORS
+       * lisp/ldefs-boot.el: Update.
+
+2021-03-18  Eli Zaretskii  <eliz@gnu.org>
 2021-02-03  Eli Zaretskii  <eliz@gnu.org>
 
        Bump Emacs version to 27.1.91
@@ -76559,7 +76949,7 @@
 
        * lisp/emacs-lisp/lisp-mode.el (lisp-cl-font-lock-keywords-2):
        Highlight the Common Lisp conventional names as described in
-       http://www.cliki.net/Naming+conventions.
+       https://www.cliki.net/Naming+conventions.
        (lisp-el-font-lock-keywords-2): Remove the already commented out
        code for `do-' and `with-' because Emacs Lisp does not have a similar
        convention.
@@ -121750,7 +122140,7 @@
 
        I roughly followed the Bordeaux threads API:
 
-       http://trac.common-lisp.net/bordeaux-threads/wiki/ApiDocumentation
+       https://sionescu.github.io/bordeaux-threads/
 
        ... but not identically.  In particular I chose not to implement
        interrupt-thread or destroy-thread, but instead a thread-signaling
@@ -144446,6 +144836,7 @@
 
 This file records repository revisions from
 commit 9d56a21e6a696ad19ac65c4b405aeca44785884a (exclusive) to
+2021-03-18bd67a4f40a733cb139ace3af4616bc2702282 (inclusive).
 2021-02-03d9244f7cbef9f91e697ad5fc0ce49ec97 (inclusive).
 commit 1ca4da054be7eb340c511d817f3ec89c8b819db7 (inclusive).
 See ChangeLog.2 for earlier changes.
diff --git a/Makefile.in b/Makefile.in
index 2068362..4fa7c9e 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -95,18 +95,8 @@ configuration=@configuration@
 ### The nt/ subdirectory gets built only for MinGW
 NTDIR=@NTDIR@
 
-# 'make' verbosity.
-AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
-
-AM_V_GEN = $(am__v_GEN_@AM_V@)
-am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
-am__v_GEN_0 = @echo "  GEN     " $@;
-am__v_GEN_1 =
-
-AM_V_at = $(am__v_at_@AM_V@)
-am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
-am__v_at_0 = @
-am__v_at_1 =
+top_builddir = @top_builddir@
+-include ${top_builddir}/src/verbose.mk
 
 # ==================== Where To Install Things ====================
 
@@ -166,9 +156,6 @@ infodir=@infodir@
 # Info files not in the doc/misc directory (we get those via make echo-info).
 INFO_NONMISC=emacs.info eintr.info elisp.info
 
-# If no makeinfo was found and configured --without-makeinfo, "no"; else "yes".
-HAVE_MAKEINFO=@HAVE_MAKEINFO@
-
 # Directory for local state files for all programs.
 localstatedir=@localstatedir@
 
@@ -650,9 +637,6 @@ install-etcdoc: src install-arch-indep
 ## If info/dir is missing, but we have install-info, we should let
 ## that handle it.  If info/dir is present and we do not have install-info,
 ## we should check for missing entries and add them by hand.
-##
-## FIXME:
-## If HAVE_MAKEINFO = no and there are no info files, do not install info/dir.
 install-info: info
        umask 022; ${MKDIR_P} "$(DESTDIR)${infodir}"
        -unset CDPATH; \
@@ -664,10 +648,9 @@ install-info: info
           [ -f "$(DESTDIR)${infodir}/dir" ] || \
              [ ! -f ${srcdir}/info/dir ] || \
              ${INSTALL_DATA} ${srcdir}/info/dir "$(DESTDIR)${infodir}/dir"; \
-          info_misc=`$(MAKE) --no-print-directory -s -C doc/misc echo-info`; \
+          info_misc=`MAKEFLAGS= $(MAKE) --no-print-directory -s -C doc/misc 
echo-info`; \
           cd ${srcdir}/info ; \
           for elt in ${INFO_NONMISC} $${info_misc}; do \
-             test "$(HAVE_MAKEINFO)" = "no" && test ! -f $$elt && continue; \
              for f in `ls $$elt $$elt-[1-9] $$elt-[1-9][0-9] 2>/dev/null`; do \
               (cd "$${thisdir}"; \
                ${INSTALL_DATA} ${srcdir}/info/$$f "$(DESTDIR)${infodir}/$$f"); 
\
@@ -779,7 +762,7 @@ uninstall: uninstall-$(NTDIR) uninstall-doc
        done
        -rm -rf "$(DESTDIR)${libexecdir}/emacs/${version}"
        thisdir=`/bin/pwd`; \
-       (info_misc=`$(MAKE) --no-print-directory -s -C doc/misc echo-info`; \
+       (info_misc=`MAKEFLAGS= $(MAKE) --no-print-directory -s -C doc/misc 
echo-info`; \
         if cd "$(DESTDIR)${infodir}"; then \
           for elt in ${INFO_NONMISC} $${info_misc}; do \
             (cd "$${thisdir}"; \
@@ -958,6 +941,10 @@ extraclean: $(extraclean_dirs:=_extraclean)
 # I removed it because it causes `make tags` to build Emacs.
 TAGS tags: lib lib-src # src
        $(MAKE) -C src tags
+       $(MAKE) -C doc/emacs tags
+       $(MAKE) -C doc/lispintro tags
+       $(MAKE) -C doc/lispref tags
+       $(MAKE) -C doc/misc tags
 
 CHECK_TARGETS = check check-maybe check-expensive check-all
 .PHONY: $(CHECK_TARGETS)
@@ -987,24 +974,34 @@ $(DOCS):
        $(MAKE) -C doc/$(subst -, ,$@)
 
 .PHONY: $(DOCS) docs pdf ps
-.PHONY: info dvi dist html info-real info-dir check-info
+.PHONY: info dvi dist html info-dir check-info
 
 ## TODO add etc/refcards.
 docs: $(DOCS)
 dvi: $(DVIS)
 html: $(HTMLS)
-info-real: $(INFOS)
+info: $(INFOS) info-dir
 pdf: $(PDFS)
 ps: $(PSS)
 
+# This dependency is due to those doc/misc/ manuals that use .org sources.
+# Depending on src is sufficient, but ends up being slow, since the
+# uncompiled lisp/org/*.el files are used to build the .texi files
+# (which can be slow even with the elc files).
+misc-info: lisp
+# Using src rather than lisp because one is less likely to get unnecessary
+# rebuilds of stuff that is not strictly necessary for generating manuals.
+misc-dvi misc-html misc-pdf misc-ps: src
+
 info-dir: ${srcdir}/info/dir
 
-## Hopefully doc/misc/*.texi is not too long for some systems?
+texi_misc = $(shell MAKEFLAGS= ${MAKE} --no-print-directory -s -C doc/misc 
echo-sources)
+
 srcdir_doc_info_dir_inputs = \
   ${srcdir}/doc/emacs/emacs.texi \
   ${srcdir}/doc/lispintro/emacs-lisp-intro.texi \
   ${srcdir}/doc/lispref/elisp.texi \
-  $(sort $(wildcard ${srcdir}/doc/misc/*.texi))
+  $(addprefix ${srcdir}/doc/misc/,${texi_misc})
 info_dir_inputs = \
   ../build-aux/dir_top \
   $(subst ${srcdir}/doc/,,${srcdir_doc_info_dir_inputs})
@@ -1017,7 +1014,7 @@ info_dir_deps = \
 ## installation location by the install-info rule, but we also
 ## need one in the source directory for people running uninstalled.
 ## FIXME it would be faster to use the install-info program if we have it,
-## but then we would need to depend on info-real, which would
+## but then we would need to depend on ${INFOS}, which would
 ## slow down parallelization.
 ${srcdir}/info/dir: ${info_dir_deps}
        $(AM_V_at)${MKDIR_P} ${srcdir}/info
@@ -1072,23 +1069,6 @@ uninstall-html: $(UNINSTALL_HTML)
 uninstall-pdf: $(UNINSTALL_PDF)
 uninstall-ps: $(UNINSTALL_PS)
 
-
-# Note that man/Makefile knows how to put the info files in $(srcdir),
-# so we can do ok running make in the build dir.
-# This used to have a clause that exited with an error if MAKEINFO = no.
-# But it is inappropriate to do so without checking if makeinfo is
-# actually needed - it is not if the info files are up-to-date.  (Bug#3982)
-# Only the doc/*/Makefiles can decide that, so we let those rules run
-# and give a standard error if makeinfo is needed but missing.
-# While it would be nice to give a more detailed error message, that
-# would require changing every rule in doc/ that builds an info file,
-# and it's not worth it.  This case is only relevant if you download a
-# release, then change the .texi files.
-info:
-  ifneq ($(HAVE_MAKEINFO),no)
-       $(MAKE) info-real info-dir
-  endif
-
 ## build-aux/make-info-dir expects only certain dircategories.
 check-info: info
        cd info ; \
diff --git a/admin/CPP-DEFINES b/admin/CPP-DEFINES
index a40b430..68c1243 100644
--- a/admin/CPP-DEFINES
+++ b/admin/CPP-DEFINES
@@ -81,7 +81,6 @@ anymore, so they can be removed.
 
 AMPERSAND_FULL_NAME
 BROKEN_DATAGRAM_SOCKETS
-BROKEN_FIONREAD
 BROKEN_GET_CURRENT_DIR_NAME
 BROKEN_PTY_READ_AFTER_EAGAIN
 DEFAULT_SOUND_DEVICE
@@ -94,16 +93,12 @@ EMACS_CONFIG_OPTIONS
 EMACS_INT
 EMACS_UINT
 GC_MARK_SECONDARY_STACK
-GC_MARK_STACK
 GC_SETJMP_WORKS
 GNU_MALLOC
-HAVE_AIX_SMT_EXP
-HAVE_ALARM
 HAVE_ALLOCA
 HAVE_ALLOCA_H
 HAVE_ALSA
 HAVE_BDFFONT
-HAVE_BOXES
 HAVE_CFMAKERAW
 HAVE_CFSETSPEED
 HAVE_CLOCK_GETTIME
@@ -117,7 +112,6 @@ HAVE_DBUS_VALIDATE_INTERFACE
 HAVE_DBUS_VALIDATE_MEMBER
 HAVE_DBUS_VALIDATE_PATH
 HAVE_DBUS_WATCH_GET_UNIX_FD
-HAVE_DECL_GETENV
 HAVE_DECL_LOCALTIME_R
 HAVE_DECL_STRMODE
 HAVE_DECL_STRTOIMAX
@@ -126,8 +120,6 @@ HAVE_DECL_STRTOULL
 HAVE_DECL_STRTOUMAX
 HAVE_DECL_TZNAME
 HAVE_DIALOGS
-HAVE_DIFFTIME
-HAVE_DUP2
 HAVE_ENDGRENT
 HAVE_ENDPWENT
 HAVE_ENVIRON_DECL
@@ -141,11 +133,9 @@ HAVE_FUTIMES
 HAVE_FUTIMESAT
 HAVE_GAI_STRERROR
 HAVE_GCONF
-HAVE_GETDELIM
 HAVE_GETGRENT
 HAVE_GETHOSTNAME
 HAVE_GETIFADDRS
-HAVE_GETLINE
 HAVE_GETLOADAVG
 HAVE_GETOPT_H
 HAVE_GETOPT_LONG_ONLY
@@ -164,18 +154,8 @@ HAVE_GPM
 HAVE_GRANTPT
 HAVE_GSETTINGS
 HAVE_GTK3
-HAVE_GTK_ADJUSTMENT_GET_PAGE_SIZE
-HAVE_GTK_DIALOG_GET_ACTION_AREA
 HAVE_GTK_FILE_SELECTION_NEW
-HAVE_GTK_MAIN
-HAVE_GTK_MULTIDISPLAY
-HAVE_GTK_ORIENTABLE_SET_ORIENTATION
-HAVE_GTK_WIDGET_GET_MAPPED
-HAVE_GTK_WIDGET_GET_SENSITIVE
-HAVE_GTK_WIDGET_GET_WINDOW
-HAVE_GTK_WIDGET_SET_HAS_WINDOW
 HAVE_GTK_WINDOW_SET_HAS_RESIZE_GRIP
-HAVE_G_TYPE_INIT
 HAVE_IFADDRS_H
 HAVE_IMAGEMAGICK
 HAVE_INTTYPES_H
@@ -193,10 +173,8 @@ HAVE_LIBLOCKFILE
 HAVE_LIBMAIL
 HAVE_LIBOTF
 HAVE_LIBPERFSTAT
-HAVE_LIBPNG_PNG_H
 HAVE_LIBSELINUX
 HAVE_LIBXML2
-HAVE_LIBXMU
 HAVE_LOCALTIME_R
 HAVE_LOCAL_SOCKETS
 HAVE_LRAND48
@@ -209,24 +187,18 @@ HAVE_MAGICKEXPORTIMAGEPIXELS
 HAVE_MAGICKMERGEIMAGELAYERS
 HAVE_MAILLOCK_H
 HAVE_MALLOC_MALLOC_H
-HAVE_MATHERR
 HAVE_MBSTATE_T
-HAVE_MEMCMP
-HAVE_MEMMOVE
 HAVE_MEMORY_H
 HAVE_MEMSET
-HAVE_MENUS
 HAVE_MKSTEMP
 HAVE_MMAP
 HAVE_MULTILINGUAL_MENU
-HAVE_NANOTIME
 HAVE_NET_IF_DL_H
 HAVE_NET_IF_H
 HAVE_NLIST_H
 HAVE_OTF_GET_VARIATION_GLYPHS
 HAVE_PERSONALITY_ADDR_NO_RANDOMIZE
 HAVE_PNG
-HAVE_PNG_H
 HAVE_POSIX_MEMALIGN
 HAVE_PROCFS
 HAVE_PSELECT
@@ -263,15 +235,12 @@ HAVE_SOUNDCARD_H
 HAVE_STDINT_H
 HAVE_STDIO_EXT_H
 HAVE_STDLIB_H
-HAVE_STLIB_H_1
 HAVE_STRINGS_H
 HAVE_STRING_H
-HAVE_STRNCASECMP
 HAVE_STRSIGNAL
 HAVE_STRTOIMAX
 HAVE_STRTOLL
 HAVE_STRTOULL
-HAVE_STRTOUMAX
 HAVE_STRUCT_ERA_ENTRY
 HAVE_STRUCT_IFREQ_IFR_ADDR
 HAVE_STRUCT_IFREQ_IFR_ADDR_SA_LEN
@@ -287,9 +256,7 @@ HAVE_STRUCT_STAT_ST_ATIM_TV_NSEC
 HAVE_STRUCT_STAT_ST_BIRTHTIMENSEC
 HAVE_STRUCT_STAT_ST_BIRTHTIMESPEC_TV_NSEC
 HAVE_STRUCT_STAT_ST_BIRTHTIM_TV_NSEC
-HAVE_STRUCT_TIMEZONE
 HAVE_STRUCT_TM_TM_ZONE
-HAVE_STRUCT_UTIMBUF
 HAVE_ST_DM_MODE
 HAVE_SYMLINK
 HAVE_SYNC
@@ -303,26 +270,20 @@ HAVE_SYS_SOCKET_H
 HAVE_SYS_SOUNDCARD_H
 HAVE_SYS_STAT_H
 HAVE_SYS_SYSTEMINFO_H
-HAVE_SYS_TIMEB_H
 HAVE_SYS_TIME_H
 HAVE_SYS_TYPES_H
 HAVE_SYS_UN_H
 HAVE_SYS_UTSNAME_H
 HAVE_SYS_VLIMIT_H
 HAVE_SYS_WAIT_H
-HAVE_TCATTR
 HAVE_TERM_H
 HAVE_TIFF
-HAVE_TIMEVAL
 HAVE_TM_GMTOFF
 HAVE_TM_ZONE
 HAVE_TOUCHLOCK
 HAVE_TZNAME
-HAVE_TZSET
 HAVE_UTIL_H
 HAVE_UTIMENSAT
-HAVE_UTIMES
-HAVE_UTIME_H
 HAVE_UTMP_H
 HAVE_VFORK
 HAVE_VFORK_H
@@ -342,14 +303,10 @@ HAVE_XRMSETDATABASE
 HAVE_XSCREENNUMBEROFSCREEN
 HAVE_XSCREENRESOURCESTRING
 HAVE_X_I18N
-HAVE_X_MENU
 HAVE_X_SM
 HAVE_X_WINDOWS
-HAVE__BOOL
-HAVE__FTIME
 HAVE___BUILTIN_UNWIND_INIT
 HAVE___EXECUTABLE_START
-HAVE___FPENDING
 INTERNAL_TERMINAL
 IS_ANY_SEP
 IS_DIRECTORY_SEP
@@ -359,7 +316,6 @@ MAIL_USE_POP
 MAIL_USE_SYSTEM_LOCK
 MAXPATHLEN
 NLIST_STRUCT
-NO_EDITRES
 NSIG
 NSIG_MINIMUM
 NULL_DEVICE
@@ -378,7 +334,6 @@ SYSTEM_MALLOC
 TAB3
 TABDLY
 TERM
-TIME_WITH_SYS_TIME
 TIOCSIGSEND
 TM_IN_SYS_TIME
 UNIX98_PTYS
diff --git a/admin/admin.el b/admin/admin.el
index d032c1c..ad4208b 100644
--- a/admin/admin.el
+++ b/admin/admin.el
@@ -151,7 +151,7 @@ Root must be the root of an Emacs source tree."
           (display-warning 'admin
                            "NEWS file contains empty sections - remove them?"))
         (goto-char (point-min))
-        (if (re-search-forward "^\\(\\+\\+\\+ *$\\|--- *$\\|Temporary 
note:\\)" nil t)
+        (if (re-search-forward "^\\(\\+\\+\\+? *$\\|---? *$\\|Temporary 
note:\\)" nil t)
             (display-warning 'admin
                              "NEWS file still contains temporary markup.
 Documentation changes might not have been completed!"))))
@@ -545,7 +545,7 @@ Leave point after the table."
        (forward-line 1)
        (while (not done)
          (cond ((re-search-forward "<tr><td.*&bull; \\(<a.*</a>\\)\
-:</td><td>&nbsp;&nbsp;</td><td[^>]*>\\(.*\\)" (line-end-position) t)
+:?</td><td>&nbsp;&nbsp;</td><td[^>]*>\\(.*\\)" (line-end-position) t)
                 (replace-match (format "<tr><td%s>\\1</td>\n<td>\\2"
                                        (if table-workaround
                                            " bgcolor=\"white\"" "")))
@@ -665,6 +665,8 @@ style=\"text-align:left\">")
 
 (defconst make-manuals-dist-output-variables
   '(("@\\(top_\\)?srcdir@" . ".")      ; top_srcdir is wrong, but not used
+    ("@\\(abs_\\)?top_builddir@" . ".") ; wrong but unused
+    ("^\\(EMACS *=\\).*" . "\\1 emacs")
     ("^\\(\\(?:texinfo\\|buildinfo\\|emacs\\)dir *=\\).*" . "\\1 .")
     ("^\\(clean:.*\\)" . "\\1 infoclean")
     ("@MAKEINFO@" . "makeinfo")
@@ -682,9 +684,7 @@ style=\"text-align:left\">")
     ("@INSTALL@" . "install -c")
     ("@INSTALL_DATA@" . "${INSTALL} -m 644")
     ("@configure_input@" . "")
-    ("@AM_DEFAULT_VERBOSITY@" . "0")
-    ("@AM_V@" . "${V}")
-    ("@AM_DEFAULT_V@" . "${AM_DEFAULT_VERBOSITY}"))
+    ("@AM_DEFAULT_VERBOSITY@" . "0"))
   "Alist of (REGEXP . REPLACEMENT) pairs for `make-manuals-dist'.")
 
 (defun make-manuals-dist--1 (root type)
@@ -714,7 +714,8 @@ style=\"text-align:left\">")
                   (string-match-p "\\.\\(eps\\|pdf\\)\\'" file)))
          (copy-file file stem)))
     (with-temp-buffer
-      (let ((outvars make-manuals-dist-output-variables))
+      (let ((outvars make-manuals-dist-output-variables)
+            (case-fold-search nil))
        (push `("@version@" . ,version) outvars)
        (insert-file-contents (format "../doc/%s/Makefile.in" type))
        (dolist (cons outvars)
diff --git a/admin/charsets/Makefile.in b/admin/charsets/Makefile.in
index 0fd130d..1fe0299 100644
--- a/admin/charsets/Makefile.in
+++ b/admin/charsets/Makefile.in
@@ -31,6 +31,7 @@ AWK = @AWK@
 
 srcdir = @srcdir@
 top_srcdir = @top_srcdir@
+top_builddir = @top_builddir@
 
 charsetdir = ${top_srcdir}/etc/charsets
 lispintdir = ${top_srcdir}/lisp/international
@@ -38,16 +39,7 @@ mapfiledir = ${srcdir}/mapfiles
 
 GLIBC_CHARMAPS = ${srcdir}/glibc
 
-AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
-AM_V_GEN = $(am__v_GEN_@AM_V@)
-am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
-am__v_GEN_0 = @echo "  GEN     " $@;
-am__v_GEN_1 =
-
-AM_V_at = $(am__v_at_@AM_V@)
-am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
-am__v_at_0 = @
-am__v_at_1 =
+-include ${top_builddir}/src/verbose.mk
 
 # Note: We can not prepend "ISO-" to these map files because of file
 # name limits on DOS.
diff --git a/admin/charsets/mapfiles/README b/admin/charsets/mapfiles/README
index 60f0912..fb07826 100644
--- a/admin/charsets/mapfiles/README
+++ b/admin/charsets/mapfiles/README
@@ -63,8 +63,8 @@ to "JIS X 0213:2004".
 
 * MULE-*.map
 
-Created by using ../mule-charsets.el in Emacs 22 as this:
-    % emacs-22 -batch -l ../mule-charsets.el
+Created by using ../mule-charsets.el in Emacs as this:
+    % emacs -batch -l ../mule-charsets.el
 
 
 This file is part of GNU Emacs.
diff --git a/admin/check-doc-strings b/admin/check-doc-strings
index 63856d3..135090b 100755
--- a/admin/check-doc-strings
+++ b/admin/check-doc-strings
@@ -59,7 +59,7 @@ sub Check_texi_function {
     $arglist_parm{$parm} = 1;
   }
 
-  foreach my $parm ($docstring =~ /\@var{([^{}]+)}/g) {
+  foreach my $parm ($docstring =~ /\@var\{([^{}]+)\}/g) {
     $docstring_parm{$parm} = 1;
   }
 
@@ -111,7 +111,9 @@ sub Check_function {
   #  $arglist_parm{$parm} = 1;
   #}
   foreach my $parm (@parms) {
-    next if $parm eq '&optional' || $parm eq '&rest';
+    next if $parm eq '&optional'
+      || $parm eq '&rest'
+      || $parm eq 'Lisp-Object';
     $arglist_parm{$parm} = 1;
   }
   my $doc_tmp = $docstring;
@@ -150,6 +152,22 @@ sub Check_function {
     next if $parm eq 'primary';
     next if $parm eq 'secondary';
     next if $parm eq 'clipboard';
+    next if $parm eq 'bbdb';
+    next if $parm eq 'dos';
+    next if $parm eq 'erc';
+    next if $parm eq 'exif';
+    next if $parm eq 'ldap';
+    next if $parm eq 'ime';
+    next if $parm eq 'rfc';
+    next if $parm eq 'ms-dos';
+    next if $parm eq 'url';
+    next if $parm eq 'w32';
+    next if $parm eq 'todo'; # org-mode
+    next if $parm eq 'done'; # org-mode
+    next if $parm eq 'waiting'; #org-mode
+    next if $parm eq 'ordered'; #org-mode
+    next if $parm eq 'deadline'; #org-mode
+    next if $parm eq 'scheduled'; #org-mode
     next if length $parm < 3;
     if (! exists $arglist_parm{$parm}) {
       print "bogus parm: $function: $parm\n";
@@ -228,20 +246,43 @@ open (FIND, "find src -name '*.c' -print |") or die;
 while (my $file = <FIND>) {
   my @matches =
     ((FileContents $file) =~
-     
/\bDEFUN\s*\(\s*\"((?:[^\\\"]|\\.)+)\"\s*,\s*\S+\s*,\s*(\S+)\s*,\s*(\S+)\s*,\s*((?:0|\"(?:(?:[^\\\"]|\\.)*)\"))\s*,\s*\/\*(.*?)\*\/\s*\(([^()]*)\)\)/sgo);
+     /\b
+      DEFUN\s*\(\s*
+      ## $function
+      \"((?:[^\\\"]|\\.)+)\"\s*,
+      \s*\S+\s*, \s*\S+\s*,
+      ## $minargs
+      \s*(\S+)\s*,
+      ## $maxargs
+      \s*(\S+)\s*,
+      ## $interactive
+      \s*((?:0|\"(?:(?:[^\\\"]|\\.)*)\"))\s*,
+      ## $docstring
+      \s*doc:\s*\/\*\s*(.*?)\s*\*\/
+      # attributes -- skip
+      (?:\s*attributes:\s*
+          (?:noreturn|const)
+          \s*)?
+      \s*\)
+      ### $parms
+      \s*\(
+      ([^()]*)
+      \)
+     /sgox);
   while (@matches) {
     my ($function, $minargs, $maxargs, $interactive, $docstring, $parms) = 
splice (@matches, 0, 6);
     $docstring =~ s/^\n+//s;
     $docstring =~ s/\n+$//s;
     $parms =~ s/,/ /g;
-    my @parms = split (' ',$parms);
+    my @parms = $parms eq 'void' ? () : split (' ', $parms);
     for (@parms) { tr/_/-/; s/-$//; }
     if ($parms !~ /Lisp_Object/) {
       if ($minargs < @parms) {
-       if ($maxargs =~ /^\d+$/) {
-         die unless $maxargs eq @parms;
-         splice (@parms, $minargs, 0, '&optional');
-       }
+        if ($maxargs =~ /^\d+$/) {
+          die "$function: $maxargs"
+            unless $maxargs eq @parms;
+          splice (@parms, $minargs, 0, '&optional');
+        }
       }
     }
     my $funtype = ($interactive =~ /\"/ ? 'Command' : 'Function');
diff --git a/admin/cus-test.el b/admin/cus-test.el
index 995586f..30b5f65 100644
--- a/admin/cus-test.el
+++ b/admin/cus-test.el
@@ -37,6 +37,13 @@
 ;;
 ;;   src/emacs -batch -l admin/cus-test.el -f cus-test-noloads
 ;;
+;; or as a part of the test suite with
+;;
+;;   make -C test test-custom-opts
+;;   make -C test test-custom-deps
+;;   make -C test test-custom-libs
+;;   make -C test test-custom-noloads
+;;
 ;; in the emacs source directory.
 ;;
 ;; For interactive use: Load this file.  Then
@@ -320,7 +327,8 @@ If it is \"all\", load all Lisp files."
       (lambda (file)
        (condition-case alpha
            (unless (member file cus-test-libs-noloads)
-             (load (file-name-sans-extension (expand-file-name file lispdir)))
+             (load (file-name-sans-extension (expand-file-name file lispdir))
+                    nil t)
              (push file cus-test-libs-loaded))
          (error
           (push (cons file alpha) cus-test-libs-errors)
@@ -349,6 +357,8 @@ Optional argument ALL non-nil means list all (non-obsolete) 
Lisp files."
        (mapcar (lambda (e) (substring e 2))
                (apply #'process-lines find-program
                       "." "-name" "obsolete" "-prune" "-o"
+                       "-name" "ldefs-boot.el" "-prune" "-o"
+                       "-name" "*loaddefs.el" "-prune" "-o"
                       "-name" "[^.]*.el" ; ignore .dir-locals.el
                       (if all
                           '("-print")
diff --git a/admin/emake b/admin/emake
index d9aa4ea..e95b17d 100755
--- a/admin/emake
+++ b/admin/emake
@@ -83,3 +83,9 @@ do
   [[ "X${REPLY:0:3}" == "X   " ]] && C="\033[1;31m"
   [[ "X$C" == "X" ]] && printf "%s\n" "$REPLY" || printf "$C%s\033[0m\n" 
"$REPLY"
 done
+
+# Run a "make check" on all test files belonging to files that have
+# changed since last time.
+make -j$cores check-maybe 2>&1 | \
+    sed -n '/contained unexpected results/,$p' | \
+    egrep --line-buffered -v "^make"
diff --git a/admin/grammars/Makefile.in b/admin/grammars/Makefile.in
index 98c9c62..aa09d9e 100644
--- a/admin/grammars/Makefile.in
+++ b/admin/grammars/Makefile.in
@@ -28,18 +28,7 @@ srcdir = @srcdir@
 top_srcdir = @top_srcdir@
 top_builddir = @top_builddir@
 
-# 'make' verbosity.
-AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
-
-AM_V_GEN = $(am__v_GEN_@AM_V@)
-am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
-am__v_GEN_0 = @echo "  GEN     " $@;
-am__v_GEN_1 =
-
-AM_V_at = $(am__v_at_@AM_V@)
-am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
-am__v_at_0 = @
-am__v_at_1 =
+-include ${top_builddir}/src/verbose.mk
 
 # Prevent any settings in the user environment causing problems.
 unexport EMACSDATA EMACSDOC EMACSPATH
diff --git a/admin/grammars/c.by b/admin/grammars/c.by
index 2d04c99..289081e 100644
--- a/admin/grammars/c.by
+++ b/admin/grammars/c.by
@@ -415,7 +415,7 @@ typesimple
   : struct-or-class opt-class opt-name opt-template-specifier
     opt-class-parents semantic-list
     (TYPE-TAG (car $3) (car $1)
-          (let ((semantic-c-classname (cons (car ,$3) (car ,$1))))
+          (dlet ((semantic-c-classname (cons (car ,$3) (car ,$1))))
             (EXPANDFULL $6 classsubparts))
           $5
           :template-specifier $4
diff --git a/admin/grammars/grammar.wy b/admin/grammars/grammar.wy
index 054e85b..35fb7e8 100644
--- a/admin/grammars/grammar.wy
+++ b/admin/grammars/grammar.wy
@@ -128,7 +128,7 @@ epilogue:
 ;;
 declaration:
     decl
-    (eval $1)
+    (eval $1 t)
   ;
 
 decl:
@@ -206,7 +206,7 @@ put_decl:
 
 put_name_list:
     BRACE_BLOCK
-    (mapcar 'semantic-tag-name (EXPANDFULL $1 put_names))
+    (mapcar #'semantic-tag-name (EXPANDFULL $1 put_names))
   ;
 
 put_names:
@@ -226,7 +226,7 @@ put_name:
 
 put_value_list:
     BRACE_BLOCK
-    (mapcar 'semantic-tag-code-detail (EXPANDFULL $1 put_values))
+    (mapcar #'semantic-tag-code-detail (EXPANDFULL $1 put_values))
   ;
 
 put_values:
@@ -300,7 +300,7 @@ plist:
 
 use_name_list:
     BRACE_BLOCK
-    (mapcar 'semantic-tag-name (EXPANDFULL $1 use_names))
+    (mapcar #'semantic-tag-name (EXPANDFULL $1 use_names))
   ;
 
 use_names:
@@ -356,7 +356,7 @@ nonterminal:
 
 rules:
     lifo_rules
-    (apply 'nconc (nreverse $1))
+    (apply #'nconc (nreverse $1))
   ;
 
 lifo_rules:
diff --git a/admin/grammars/python.wy b/admin/grammars/python.wy
index aaa25ce..2539d1b 100644
--- a/admin/grammars/python.wy
+++ b/admin/grammars/python.wy
@@ -88,15 +88,17 @@
 
 %package wisent-python-wy
 %provide semantic/wisent/python-wy
-%expectedconflicts 4
+%expectedconflicts 5
 
 %{
+(require 'semantic/tag)
 (declare-function wisent-python-reconstitute-function-tag
                  "semantic/wisent/python" (tag suite))
 (declare-function wisent-python-reconstitute-class-tag "semantic/wisent/python"
                  (tag))
 (declare-function semantic-parse-region "semantic"
                  (start end &optional nonterminal depth returnonerror))
+(defvar wisent-python-EXPANDING-block)
 }
 
 %languagemode python-mode
@@ -184,6 +186,7 @@
 %token <punctuation> ASSIGN    "="
 %token <punctuation> BACKQUOTE "`"
 %token <punctuation> AT         "@"
+%token <punctuation> FOLLOWS    "->"
 
 
 ;; -----------------
@@ -808,12 +811,17 @@ decorators
 
 ;; funcdef: [decorators] 'def' NAME parameters ':' suite
 funcdef
-  : DEF NAME function_parameter_list COLON suite
+  : DEF NAME function_parameter_list return_type_hint COLON suite
     (wisent-python-reconstitute-function-tag
-     (FUNCTION-TAG $2 nil $3) $5)
-  | decorators DEF NAME function_parameter_list COLON suite
+     (FUNCTION-TAG $2 nil $3) $6)
+  | decorators DEF NAME function_parameter_list return_type_hint COLON suite
     (wisent-python-reconstitute-function-tag
-     (FUNCTION-TAG $3 nil $4 :decorators $1) $6)
+     (FUNCTION-TAG $3 nil $4 :decorators $1) $7)
+  ;
+
+return_type_hint
+  : ;;EMPTY
+  | FOLLOWS type
   ;
 
 function_parameter_list
@@ -865,7 +873,7 @@ paren_class_list_opt
 paren_class_list
   : PAREN_BLOCK
     (let ((wisent-python-EXPANDING-block t))
-      (mapcar 'semantic-tag-name (EXPANDFULL $1 paren_classes)))
+      (mapcar #'semantic-tag-name (EXPANDFULL $1 paren_classes)))
   ;
 
 ;; parameters: '(' [varargslist] ')'
@@ -887,7 +895,7 @@ paren_classes
 ;; parser can parse general expressions, I don't see much benefit in
 ;; generating a string of expression as base class "name".
 paren_class
-  : dotted_name
+  : type
   ;
 
 ;;;****************************************************************************
@@ -1140,7 +1148,7 @@ fpdef_opt_test
 
 ;; fpdef: NAME | '(' fplist ')'
 fpdef
-  : NAME
+  : NAME type_hint
     (VARIABLE-TAG $1 nil nil)
  ;; Below breaks the parser.  Don't know why, but my guess is that
  ;; LPAREN/RPAREN clashes with the ones in function_parameters.
@@ -1160,6 +1168,15 @@ fpdef
 ;;   | fpdef_list COMMA fpdef
 ;;   ;
 
+type_hint
+  : ;;EMPTY
+  | COLON type
+  ;
+
+type
+  : test
+  ;
+
 ;; ['=' test]
 eq_test_opt
   : ;;EMPTY
diff --git a/admin/make-tarball.txt b/admin/make-tarball.txt
index 5125086..c207895 100644
--- a/admin/make-tarball.txt
+++ b/admin/make-tarball.txt
@@ -33,6 +33,11 @@ General steps (for each step, check for possible errors):
     or some form of "git clean -x".  It's probably simpler and safer to
     make a new working directory exclusively for the release branch.
 
+    If the working directory has subdirectories created when making
+    previous releases or pretests, remove those subdirectories, as the
+    command which updates the ChangeLog file might attempt to recurse
+    there and scan any ChangeLog.* files there.
+
     Make sure the tree is built, or at least configured.  That's
     because some of the commands below run Make, so they need
     Makefiles to be present.
@@ -68,20 +73,29 @@ General steps (for each step, check for possible errors):
 
 3.  Set the version number (M-x load-file RET admin/admin.el RET, then
     M-x set-version RET).  For a pretest, start at version .90.  After
-    .99, use .990 (so that it sorts).
+    .99, use .990 (so that it sorts).  Commit the resulting changes
+    as one, with nothing else included, and using a log message
+    of the format "Bump Emacs version to ...", so that the commit can
+    be skipped when merging branches (see admin/gitmerge.el).
 
     The final pretest should be a release candidate.
     Before a release candidate is made, the tasks listed in
     admin/release-process must be completed.
 
-    Set the version number to that of the actual release.  Pick a date
-    about a week from now when you intend to make the release.  Use M-x
-    add-release-logs to add entries to etc/HISTORY and the ChangeLog
-    file.  It's best not to commit these files until the release is
-    actually made.  Merge the entries from (unversioned) ChangeLog
-    into the top of the current versioned ChangeLog.N and commit that
-    along with etc/HISTORY.  Then you can tag that commit as the
-    release.
+    Set the version number to that of the actual release (commit in
+    one, as described above). Pick a date about a week from now when
+    you intend to make the release.  Use M-x add-release-logs to add
+    entries to etc/HISTORY and the ChangeLog file.  It's best not to
+    commit these files until the release is actually made.  Merge the
+    entries from (unversioned) ChangeLog into the top of the current
+    versioned ChangeLog.N and commit that along with etc/HISTORY.
+    Then you can tag that commit as the release.
+
+    Alternatively, you can commit and tag with the RC tag right away,
+    and delay the final tagging until you actually decide to make a
+    release and announce it.  The "git tag" command can tag a specific
+    commit if you give it the SHA1 of that commit, even if additional
+    commits have been pushed in the meantime.
 
     Name the tar file as emacs-XX.Y-rc1.tar.  If all goes well in the
     following week, you can simply rename the file and use it for the
@@ -96,11 +110,11 @@ General steps (for each step, check for possible errors):
     Never replace an existing tarfile!  If you need to fix something,
     always upload it with a different name.
 
-4.   autoreconf -i -I m4 --force
-     make bootstrap
+4.    autoreconf -i -I m4 --force
+      make bootstrap
 
-     make -C etc/refcards
-     make -C etc/refcards clean
+      make -C etc/refcards
+      make -C etc/refcards clean
 
     If some of the etc/refcards, especially the non-English ones, fail
     to build, you probably need to install some TeX/LaTeX packages, in
@@ -114,13 +128,18 @@ General steps (for each step, check for possible errors):
 5.  Copy lisp/loaddefs.el to lisp/ldefs-boot.el.
 
     Commit ChangeLog.N, etc/AUTHORS, lisp/ldefs-boot.el, and the
-    files changed by M-x set-version.
+    files changed by M-x set-version.  The easiest way of doing that
+    is "C-x v d ROOT-DIR RET", then go to the first modified file,
+    press 'M' to mark all modified files, and finally 'v' to commit
+    them.  Make sure the commit log message mentions all the changes
+    in all modified files, as by default 'v' doesn't necessarily do
+    so.
 
     If someone else made a commit between step 1 and now,
     you need to repeat from step 4 onwards.  (You can commit the files
     from step 2 and 3 earlier to reduce the chance of this.)
 
-6.  ./make-dist --snapshot --no-compress
+6.   ./make-dist --snapshot --no-compress
 
     Check the contents of the new tar with admin/diff-tar-files
     against the previous release (if this is the first pretest) or the
@@ -128,6 +147,14 @@ General steps (for each step, check for possible errors):
     yourself, find it at <https://alpha.gnu.org/gnu/emacs/pretest>.
     Releases are of course at <https://ftp.gnu.org/pub/gnu/emacs/>.
 
+     ./admin/diff-tar-files emacs-OLD.tar.gz emacs-NEW.tar.gz
+
+    Alternatively:
+
+     tar tJf emacs-OLD.tar.xz | sed -e 's,^[^/]*,,' | sort > old_tmp
+     tar tJf emacs-NEW.tar.xz | sed -e 's,^[^/]*,,' | sort > new_tmp
+     diff -u old_tmp new_tmp
+
     If this is the first pretest of a major release, just comparing
     with the previous release may overlook many new files.  You can try
     something like 'find . | sort' in a clean repository, and compare the
@@ -135,6 +162,7 @@ General steps (for each step, check for possible errors):
 
 7.   tar -xf emacs-NEW.tar; cd emacs-NEW
      ./configure --prefix=/tmp/emacs && make check && make install
+
     Use 'script' or M-x compile to save the compilation log in
     compile-NEW.log and compare it against an old one.  The easiest way
     to do that is to visit the old log in Emacs, change the version
@@ -142,8 +170,23 @@ General steps (for each step, check for possible errors):
     M-x ediff.  Especially check that Info files aren't built, and that
     no autotools (autoconf etc) run.
 
-8.  cd EMACS_ROOT_DIR && git tag -a TAG && git push origin tag TAG
-    TAG is emacs-XX.Y.ZZ for a pretest, emacs-XX.Y for a release.
+8.  You can now tag the release/pretest and push it together with the
+    last commit:
+
+     cd EMACS_ROOT_DIR && git tag -a TAG -m "Emacs TAG"
+     git push
+     git push --tags
+
+    Here TAG is emacs-XX.Y.ZZ for a pretest, emacs-XX.Y for a release.
+    For a release, if you are producing a release candidate first, use
+    emacs-XX.Y-rcN (N = 1, 2, ...) when you tar the RC, and add the
+    actual release tag later, when the official release tarball is
+    uploaded to ftp.gnu.org.  When adding a tag later, it is safer to
+    use the SHA1 of the last commit which went into the release
+    tarball, in case there were some intervening commits since then:
+
+     git tag -a TAG -m "Emacs TAG" SHA1
+     git push --tags
 
 9. Decide what compression schemes to offer.
     For a release, at least gz and xz:
@@ -207,8 +250,12 @@ General steps (for each step, check for possible errors):
     because replies that invariably are not announcements also get
     sent out as if they were.)
 
-12. After a release, update the Emacs pages as below.
+12. After a release, update the Emacs pages as described below.
 
+13. Bump the Emacs version on the release branch.
+    If the released version was XX.Y, use 'set-version' from
+    admin/admin.el to bump the version on the release branch to
+    XX.Y.50.  Commit the changes.
 
 UPDATING THE EMACS WEB PAGES AFTER A RELEASE
 
@@ -228,5 +275,14 @@ page for about a month, then comment it again.
 Regenerate the various manuals in manual/.
 The scripts admin/make-manuals and admin/upload-manuals summarize the process.
 
+If you have Texinfo installed locally, make-manuals might fail if it
+cannot find epsf.tex.  In that case define in the environment
+
+  TEXINPUTS=:/path/to/texinfo-tree/doc
+
+where /path/to/texinfo-tree is the absolute file name of the top-level
+directory where you have the Texinfo source tree.  Then re-run
+make-manuals.
+
 Browsing <https://web.cvs.savannah.gnu.org/viewvc/?root=emacs> is one
 way to check for any files that still need updating.
diff --git a/admin/notes/emba b/admin/notes/emba
index adebcef..36b126e 100644
--- a/admin/notes/emba
+++ b/admin/notes/emba
@@ -36,6 +36,21 @@ of the Emacs git repository to perform a bootstrap and test 
of Emacs.
 This could happen for several jobs with changed configuration, compile
 and test parameters.
 
+There are different types of jobs: 'prep-image-base' is responsible to
+prepare the environment for the following jobs.  'build-image-*' jobs
+are responsible to compile Emacs in different configuration.  The
+corresponding 'test-*' jobs run the ert tests.
+
+A special job is 'test-all-inotify', which runs 'make check-expensive'.
+While most of the jobs run as soon as a respective file has been
+committed into the Emacs git repository, this test job runs scheduled,
+every 8 hours.
+
+The log files for every test job are kept on the server for a week.
+They can be downloaded from the server, visiting the URL
+<https://emba.gnu.org/emacs/emacs/-/pipelines>, and selecting the job
+in question.
+
 * Emba configuration
 
 The emba configuration files are hosted on
diff --git a/admin/unidata/Makefile.in b/admin/unidata/Makefile.in
index f31e1bb..183569f 100644
--- a/admin/unidata/Makefile.in
+++ b/admin/unidata/Makefile.in
@@ -36,23 +36,7 @@ emacs = "${EMACS}" -batch --no-site-file --no-site-lisp
 lparen = (
 unifiles = $(addprefix ${unidir}/,$(sort $(shell sed -n 's/^[ \t][ 
\t]*${lparen}"\(uni-[^"]*\)"$$/\1/p' ${srcdir}/unidata-gen.el)))
 
-# 'make' verbosity.
-AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
-
-AM_V_ELC = $(am__v_ELC_@AM_V@)
-am__v_ELC_ = $(am__v_ELC_@AM_DEFAULT_V@)
-am__v_ELC_0 = @echo "  ELC     " $@;
-am__v_ELC_1 =
-
-AM_V_GEN = $(am__v_GEN_@AM_V@)
-am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
-am__v_GEN_0 = @echo "  GEN     " $@;
-am__v_GEN_1 =
-
-AM_V_at = $(am__v_at_@AM_V@)
-am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
-am__v_at_0 = @
-am__v_at_1 =
+-include ${top_builddir}/src/verbose.mk
 
 .PHONY: all
 
diff --git a/build-aux/make-info-dir b/build-aux/make-info-dir
index ea26479..256c9f0 100755
--- a/build-aux/make-info-dir
+++ b/build-aux/make-info-dir
@@ -52,8 +52,11 @@ exec "${AWK-awk}" '
     topic[ntopics++] = "Emacs misc features"
     topic[ntopics++] = "Emacs lisp libraries"
     topic[ntopics] = "Unknown category"
+    texinfo = 0
   }
+
   /^@dircategory / {
+    texinfo = 1
     sub(/^@dircategory /, "")
     detexinfo()
     for (dircat = 0; dircat < ntopics && topic[dircat] != $0; dircat++)
@@ -66,6 +69,33 @@ exec "${AWK-awk}" '
       data[dircat] = data[dircat] $0 "\n"
     }
   }
+
+  ## Org stuff. TODO we assume the order of the texinfo items.
+  {
+    ## TODO Check FILENAME suffix instead?
+    ## TODO Is this portable awk?
+    if (FNR == 1) texinfo = 0
+
+    ## If applied to the generated org.texi file, this picks up the examples.
+    ## Thanks for making life more difficult...
+    if (texinfo) next
+
+    if (tolower($0) ~ /^#\+texinfo_dir_category/) {
+      sub(/^#[^:]*: /, "")
+      for (dircat = 0; dircat < ntopics && topic[dircat] != $0; dircat++)
+        continue;
+    }
+    if (tolower($0) ~ /^#\+texinfo_dir_title/) {
+      sub(/^#[^:]*: /, "")
+      ## Note this does not fill any long descriptions.
+      data[dircat] = data[dircat] sprintf("* %-30s", ($0 ". "))
+    }
+    if (tolower($0) ~ /^#\+texinfo_dir_desc/) {
+      sub(/^#[^:]*: /, "")
+      data[dircat] = data[dircat] $0 ".\n"
+    }
+  }
+
   END {
     for (dircat = 0; dircat <= ntopics; dircat++)
       if (data[dircat])
diff --git a/configure.ac b/configure.ac
index 08f3c0c..2c62a9f 100644
--- a/configure.ac
+++ b/configure.ac
@@ -409,19 +409,18 @@ dnl This should be the last --with option, because 
--with-x is
 dnl added later on when we find the file name of X, and it's best to
 dnl keep them together visually.
 AC_ARG_WITH([x-toolkit],[AS_HELP_STRING([--with-x-toolkit=KIT],
- [use an X toolkit (KIT one of: yes or gtk, gtk2, gtk3, lucid or athena, 
motif, no)])],
+ [use an X toolkit (KIT one of: yes or gtk, gtk2, gtk3, lucid or athena, 
no)])],
 [        case "${withval}" in
            y | ye | yes )      val=gtk ;;
            n | no )            val=no  ;;
            l | lu | luc | luci | lucid )       val=lucid ;;
            a | at | ath | athe | athen | athena )      val=athena ;;
-           m | mo | mot | moti | motif )       val=motif ;;
            g | gt | gtk  )     val=gtk ;;
            gtk2  )     val=gtk2 ;;
            gtk3  )     val=gtk3 ;;
            * )
 AC_MSG_ERROR(['--with-x-toolkit=$withval' is invalid;
-this option's value should be 'yes', 'no', 'lucid', 'athena', 'motif', 'gtk',
+this option's value should be 'yes', 'no', 'lucid', 'athena', 'gtk',
 'gtk2' or 'gtk3'.  'yes' and 'gtk' are synonyms.
 'athena' and 'lucid' are synonyms.])
            ;;
@@ -460,7 +459,7 @@ OPTION_DEFAULT_ON([harfbuzz],[don't use HarfBuzz for text 
shaping])
 OPTION_DEFAULT_ON([libotf],[don't use libotf for OpenType font support])
 OPTION_DEFAULT_ON([m17n-flt],[don't use m17n-flt for text shaping])
 
-OPTION_DEFAULT_ON([toolkit-scroll-bars],[don't use Motif/Xaw3d/GTK toolkit 
scroll bars])
+OPTION_DEFAULT_ON([toolkit-scroll-bars],[don't use Xaw3d/GTK toolkit scroll 
bars])
 OPTION_DEFAULT_ON([xaw3d],[don't use Xaw3d])
 OPTION_DEFAULT_ON([xim],[at runtime, default X11 XIM to off])
 OPTION_DEFAULT_ON([xdbe],[don't use X11 double buffering support])
@@ -507,11 +506,6 @@ otherwise for the first of 'inotify', 'kqueue' or 'gfile' 
that is usable.])
 OPTION_DEFAULT_OFF([xwidgets],
   [enable use of xwidgets in Emacs buffers (requires gtk3 or macOS Cocoa)])
 
-## For the times when you want to build Emacs but don't have
-## a suitable makeinfo, and can live without the manuals.
-dnl https://lists.gnu.org/r/emacs-devel/2008-04/msg01844.html
-OPTION_DEFAULT_ON([makeinfo],[don't require makeinfo for building manuals])
-
 ## Makefile.in needs the cache file name.
 AC_SUBST(cache_file)
 
@@ -1190,9 +1184,6 @@ AC_DEFUN([AM_CONDITIONAL],
 
 dnl Prefer silent make output.  For verbose output, use
 dnl 'configure --disable-silent-rules' or 'make V=1' .
-dnl This code is adapted from Automake.
-dnl Although it can be simplified now that GNU Make is assumed,
-dnl the simplification hasn't been done yet.
 AC_ARG_ENABLE([silent-rules],
   [AS_HELP_STRING(
      [--disable-silent-rules],
@@ -1202,11 +1193,8 @@ if test "$enable_silent_rules" = no; then
 else
   AM_DEFAULT_VERBOSITY=0
 fi
-AM_V='$(V)'
-AM_DEFAULT_V='$(AM_DEFAULT_VERBOSITY)'
-AC_SUBST([AM_V])
-AC_SUBST([AM_DEFAULT_V])
 AC_SUBST([AM_DEFAULT_VERBOSITY])
+AC_CONFIG_FILES([src/verbose.mk])
 
 dnl Some other nice autoconf tests.
 AC_PROG_INSTALL
@@ -1345,14 +1333,13 @@ if test -n "$BREW"; then
 fi
 
 ## Require makeinfo >= 4.13 (last of the 4.x series) to build the manuals.
-if test "${MAKEINFO:=makeinfo}" != "no"; then
-  case `($MAKEINFO --version) 2>/dev/null` in
-    *' (GNU texinfo) '4.1[[3-9]]* | \
-    *' (GNU texinfo) '[[5-9]]* | \
-    *' (GNU texinfo) '[[1-9][0-9]]* ) ;;
-    *) MAKEINFO=no;;
-  esac
-fi
+: ${MAKEINFO:=makeinfo}
+case `($MAKEINFO --version) 2>/dev/null` in
+  *' (GNU texinfo) '4.1[[3-9]]* | \
+  *' (GNU texinfo) '[[5-9]]* | \
+  *' (GNU texinfo) '[[1-9][0-9]]* ) ;;
+  *) MAKEINFO=no;;
+esac
 
 ## Makeinfo is unusual.  For a released Emacs, the manuals are
 ## pre-built, and not deleted by the normal clean rules.  makeinfo is
@@ -1363,21 +1350,19 @@ fi
 ## should test for it as it does for any other build requirement.
 ## We use the presence of $srcdir/info/emacs to distinguish a release,
 ## with pre-built manuals, from a repository checkout.
-HAVE_MAKEINFO=yes
-
 if test "$MAKEINFO" = "no"; then
   MAKEINFO=makeinfo
-  if test "x${with_makeinfo}" = "xno"; then
-    HAVE_MAKEINFO=no
-  elif test ! -e "$srcdir/info/emacs" && test ! -e "$srcdir/info/emacs.info"; 
then
+  if test ! -e "$srcdir/info/emacs" && test ! -e "$srcdir/info/emacs.info"; 
then
     AC_MSG_ERROR( [You do not seem to have makeinfo >= 4.13, and your
 source tree does not seem to have pre-built manuals in the 'info' directory.
-Either install a suitable version of makeinfo, or re-run configure
-with the '--without-makeinfo' option to build without the manuals.] )
+Please install a suitable version of makeinfo.] )
+  else
+    AC_MSG_WARN( [You do not seem to have makeinfo >= 4.13.
+You will not be able to rebuild the manuals if you delete them or change
+their sources.] )
   fi
 fi
 AC_SUBST([MAKEINFO])
-AC_SUBST(HAVE_MAKEINFO)
 
 if test $opsys = mingw32; then
    DOCMISC_W32=efaq-w32
@@ -1768,8 +1753,8 @@ fi
 
 dnl On Solaris 8 there's a compilation warning for term.h because
 dnl it doesn't define 'bool'.
-AC_CHECK_HEADERS(term.h, , , -)
-AC_HEADER_TIME
+AC_PREPROC_IFELSE([AC_LANG_PROGRAM([[#include <term.h>]],[[]])],
+  AC_DEFINE(HAVE_TERM_H, 1, [Define to 1 if you have the <term.h> header 
file.]))
 AC_HEADER_SYS_WAIT
 
 AC_CHECK_HEADERS_ONCE(sys/socket.h)
@@ -2252,7 +2237,7 @@ if test "$window_system" = none && test "X$with_x" != 
"Xno"; then
    then
         AC_MSG_ERROR([You seem to be running X, but no X development libraries
 were found.  You should install the relevant development files for X
-and for the toolkit you want, such as Gtk+ or Motif.  Also make
+and for the toolkit you want, such as Gtk+.  Also make
 sure you have development files for image handling, i.e.
 tiff, gif, jpeg, png and xpm.
 If you are sure you want Emacs compiled without X window support, pass
@@ -3912,6 +3897,11 @@ case $with_json,$HAVE_JSON in
      WITH_IFAVAILABLE="$WITH_IFAVAILABLE --with-json=ifavailable";;
 esac
 if test "X${MISSING}" != X; then
+  # If we have a missing library, and we don't have pkg-config installed,
+  # the missing pkg-config may be the reason.  Give the user a hint.
+  if test "X${PKG_CONFIG}" = X; then
+    AC_MSG_WARN([Unable to locate a usable pkg-config])
+  fi
   AC_MSG_ERROR([The following required libraries were not found:
     $MISSING
 Maybe some development libraries/packages are missing?
@@ -4717,10 +4707,10 @@ if test "$USE_X_TOOLKIT" != "none"; then
     else
       OTHERLIBS="-lXt -$LIBXMU"
     fi
-    AC_TRY_LINK(
-      [#include <X11/Intrinsic.h>
-       #include <X11/Xmu/Editres.h>],
-      [_XEditResCheckMessages (0, 0, 0, 0);],
+    AC_LINK_IFELSE([AC_LANG_PROGRAM(
+      [[#include <X11/Intrinsic.h>
+       #include <X11/Xmu/Editres.h>]],
+      [[_XEditResCheckMessages (0, 0, 0, 0);]])],
       [AC_DEFINE([X_TOOLKIT_EDITRES], 1,
         [Define to 1 if we should use XEditRes.])])
     LIBS=$OLDLIBS
diff --git a/doc/emacs/Makefile.in b/doc/emacs/Makefile.in
index 2a3f53f..69d39ef 100644
--- a/doc/emacs/Makefile.in
+++ b/doc/emacs/Makefile.in
@@ -28,6 +28,8 @@ srcdir=@srcdir@
 
 top_srcdir = @top_srcdir@
 
+top_builddir = @top_builddir@
+
 version = @version@
 
 ## Where the output files go.
@@ -73,13 +75,7 @@ TEXI2DVI = texi2dvi
 TEXI2PDF = texi2pdf
 DVIPS = dvips
 
-# 'make' verbosity.
-AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
-
-AM_V_GEN = $(am__v_GEN_@AM_V@)
-am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
-am__v_GEN_0 = @echo "  GEN     " $@;
-am__v_GEN_1 =
+-include ${top_builddir}/src/verbose.mk
 
 ENVADD = $(AM_V_GEN)TEXINPUTS="$(srcdir):$(texinfodir):$(TEXINPUTS)" \
          MAKEINFO="$(MAKEINFO) $(MAKEINFO_OPTS)"
@@ -224,7 +220,7 @@ infoclean:
          $(buildinfodir)/emacs.info-[1-9][0-9]
 
 bootstrap-clean maintainer-clean: distclean infoclean
-       rm -f ${srcdir}/emacsver.texi
+       rm -f ${srcdir}/emacsver.texi TAGS
 
 .PHONY: install-dvi install-html install-pdf install-ps install-doc
 
@@ -273,4 +269,20 @@ uninstall-pdf:
 uninstall-doc: uninstall-dvi uninstall-html uninstall-pdf uninstall-ps
 
 
+ETAGS = ../../lib-src/etags${EXEEXT}
+
+${ETAGS}: FORCE
+       $(MAKE) -C $(dir $@) $(notdir $@)
+
+texifiles = $(wildcard ${srcdir}/*.texi)
+
+TAGS: ${ETAGS} $(texifiles)
+       $(AM_V_GEN)${ETAGS} --include=../lispref/TAGS --include=../misc/TAGS 
$(texifiles)
+
+tags: TAGS
+.PHONY: tags
+
+FORCE:
+.PHONY: FORCE
+
 ### Makefile ends here
diff --git a/doc/emacs/basic.texi b/doc/emacs/basic.texi
index 444b28f..4a34fd3 100644
--- a/doc/emacs/basic.texi
+++ b/doc/emacs/basic.texi
@@ -331,6 +331,11 @@ a plain prefix argument.  Alternatively, you can use the 
command
 @code{goto-line-relative} to move point to the line relative to the
 accessible portion of the narrowed buffer.
 
+@code{goto-line} has its own history list (@pxref{Minibuffer
+History}).  You can have either a single list shared between all
+buffers (the default) or a separate list for each buffer, by
+customizing the user option @code{goto-line-history-local}.
+
 @item M-g @key{TAB}
 @kindex M-g TAB
 @findex move-to-column
@@ -880,3 +885,14 @@ characters.  You can repeat that command (including its 
argument) three
 additional times, to delete a total of 80 characters, by typing @kbd{C-x
 z z z}.  The first @kbd{C-x z} repeats the command once, and each
 subsequent @kbd{z} repeats it once again.
+
+@findex repeat-mode
+  Also you can activate @code{repeat-mode} that temporarily enables
+a transient mode with short keys after a limited number of commands.
+Currently supported shorter key sequences are @kbd{C-x u u} instead of
+@kbd{C-x u C-x u} to undo many changes, @kbd{C-x o o} instead of
+@kbd{C-x o C-x o} to switch several windows, @kbd{C-x @{ @{ @} @} ^ ^
+v v} to resize the selected window interactively, @kbd{M-g n n p p} to
+navigate @code{next-error} matches.  Any other key exits transient mode
+and then is executed normally.  The user option @code{repeat-exit-key}
+defines an additional key to exit this transient mode.
diff --git a/doc/emacs/custom.texi b/doc/emacs/custom.texi
index 22900c5..bd505d2 100644
--- a/doc/emacs/custom.texi
+++ b/doc/emacs/custom.texi
@@ -388,15 +388,15 @@ file.  For example:
 Emacs versions, like this:
 
 @example
-(cond ((< emacs-major-version 22)
-       ;; @r{Emacs 21 customization.}
-       (setq custom-file "~/.config/custom-21.el"))
-      ((and (= emacs-major-version 22)
+(cond ((< emacs-major-version 28)
+       ;; @r{Emacs 27 customization.}
+       (setq custom-file "~/.config/custom-27.el"))
+      ((and (= emacs-major-version 26)
             (< emacs-minor-version 3))
-       ;; @r{Emacs 22 customization, before version 22.3.}
-       (setq custom-file "~/.config/custom-22.el"))
+       ;; @r{Emacs 26 customization, before version 26.3.}
+       (setq custom-file "~/.config/custom-26.el"))
       (t
-       ;; @r{Emacs version 22.3 or later.}
+       ;; @r{Emacs version 28.1 or later.}
        (setq custom-file "~/.config/emacs-custom.el")))
 
 (load custom-file)
diff --git a/doc/emacs/dired.texi b/doc/emacs/dired.texi
index 34d12ac..f57606d 100644
--- a/doc/emacs/dired.texi
+++ b/doc/emacs/dired.texi
@@ -129,6 +129,12 @@ options (that is, single characters) requiring no 
arguments, and long
 options (starting with @samp{--}) whose arguments are specified with
 @samp{=}.
 
+  Dired does not handle files that have names with embedded newline
+characters well.  If you have many such files, you may consider adding
+@samp{-b} to @code{dired-listing-switches}.  This will quote all
+special characters and allow Dired to handle them better.  (You can
+also use the @kbd{C-u C-x d} command to add @samp{-b} temporarily.)
+
 @vindex dired-switches-in-mode-line
   Dired displays in the mode line an indication of what were the
 switches used to invoke @command{ls}.  By default, Dired will try to
diff --git a/doc/emacs/emacs.texi b/doc/emacs/emacs.texi
index 4054b09..925c701 100644
--- a/doc/emacs/emacs.texi
+++ b/doc/emacs/emacs.texi
@@ -861,6 +861,7 @@ Projects
 * Project File Commands::   Commands for handling project files.
 * Project Buffer Commands:: Commands for handling project buffers.
 * Switching Projects::      Switching between projects.
+* Managing Projects::       Managing the project list file.
 
 Change Logs
 
diff --git a/doc/emacs/files.texi b/doc/emacs/files.texi
index 6b3bc43..912980b 100644
--- a/doc/emacs/files.texi
+++ b/doc/emacs/files.texi
@@ -1670,8 +1670,9 @@ modify the original (``old'') source files rather than 
the patched
 (``new'') source files.
 
 @vindex diff-font-lock-syntax
-  If non-@code{nil}, fragments of source in hunks are highlighted
-according to the appropriate major mode.
+  If @code{diff-font-lock-syntax} is non-@code{nil}, fragments of
+source in hunks are highlighted according to the appropriate major
+mode.
 
 @node Copying and Naming
 @section Copying, Naming and Renaming Files
diff --git a/doc/emacs/m-x.texi b/doc/emacs/m-x.texi
index 865220f..d35a835 100644
--- a/doc/emacs/m-x.texi
+++ b/doc/emacs/m-x.texi
@@ -46,9 +46,25 @@ from running the command by name.
 @cindex obsolete command
   When @kbd{M-x} completes on commands, it ignores the commands that
 are declared @dfn{obsolete}; for these, you will have to type their
-full name.  Obsolete commands are those for which newer, better
+full name.  (Obsolete commands are those for which newer, better
 alternatives exist, and which are slated for removal in some future
-Emacs release.
+Emacs release.)
+
+@vindex read-extended-command-predicate
+  In addition, @kbd{M-x} completion can exclude commands that are not
+relevant to, and generally cannot work with, the current buffer's
+major mode (@pxref{Major Modes}) and minor modes (@pxref{Minor
+Modes}).  By default, no commands are excluded, but you can customize
+the option @code{read-extended-command-predicate} to exclude those
+irrelevant commands from completion results.
+
+@kindex M-S-x
+  Conversely, Emacs can exclude all commands except those that are
+particularly relevant to the current buffer.  The @kbd{M-S-x} (that's
+``meta shift x'') command works just like @kbd{M-x}, but instead of
+listing all (or most) of the commands Emacs knows about, it will only
+list the commands that have been marked as ``belonging'' to the
+current major mode, or any enabled minor modes.
 
   To cancel the @kbd{M-x} and not run a command, type @kbd{C-g} instead
 of entering the command name.  This takes you back to command level.
diff --git a/doc/emacs/maintaining.texi b/doc/emacs/maintaining.texi
index bc276c4..dfe4eb0 100644
--- a/doc/emacs/maintaining.texi
+++ b/doc/emacs/maintaining.texi
@@ -1611,6 +1611,10 @@ branch ID for a branch starting at the current revision. 
 For example,
 if the current revision is 2.5, the branch ID should be 2.5.1, 2.5.2,
 and so on, depending on the number of existing branches at that point.
 
+  This procedure will not work for distributed version control systems
+like git or Mercurial.  For those systems you should use the prefix
+argument to @code{vc-create-tag} (@kbd{C-u C-x v s}) instead.
+
   To create a new branch at an older revision (one that is no longer
 the head of a branch), first select that revision (@pxref{Switching
 Branches}).  Your procedure will then differ depending on whether you
@@ -1660,6 +1664,7 @@ the project back-end.  For example, the VC back-end 
doesn't consider
 * Project File Commands::   Commands for handling project files.
 * Project Buffer Commands:: Commands for handling project buffers.
 * Switching Projects::      Switching between projects.
+* Managing Projects::       Managing the project list file.
 @end menu
 
 @node Project File Commands
@@ -1839,6 +1844,21 @@ in the menu, and which key invokes each command.
 records the list of known projects.  It defaults to the file
 @file{projects} in @code{user-emacs-directory} (@pxref{Find Init}).
 
+@node Managing Projects
+@subsection Managing the Project List File
+
+@table @kbd
+@item M-x project-remove-known-project
+Remove a known project from the @code{project-list-file}.
+@end table
+
+@findex project-remove-known-project
+  Normally Emacs automatically adds and removes projects to and from the
+@code{project-list-file}, but sometimes you may want to manually edit
+the available projects.  @kbd{M-x project-remove-known-project}
+prompts you to choose one of the available projects, and then removes
+it from the file.
+
 @node Change Log
 @section Change Logs
 
diff --git a/doc/emacs/mini.texi b/doc/emacs/mini.texi
index f81e64b..d0865c5 100644
--- a/doc/emacs/mini.texi
+++ b/doc/emacs/mini.texi
@@ -82,7 +82,9 @@ after a recursive minibuffer has been opened in the current 
command
 (@pxref{Recursive Mini,,, elisp}).  This option is mainly to retain
 (approximately) the behavior prior to Emacs 28.1.  Note that the
 effect of the command, when you finally finish using the minibuffer,
-always takes place in the frame where you first opened it.
+always takes place in the frame where you first opened it.  The sole
+exception is that when that frame no longer exists, the action takes
+place in the currently selected frame.
 
 @node Minibuffer File
 @section Minibuffers for File Names
@@ -800,6 +802,7 @@ can re-execute a command by calling @code{eval} with the
 
 @node Passwords
 @section Entering passwords
+@cindex entering passwords
 
 Sometimes, you may need to enter a password into Emacs.  For instance,
 when you tell Emacs to visit a file on another machine via a network
@@ -810,7 +813,7 @@ access to the machine (@pxref{Remote Files}).
 displays a prompt in the echo area (such as @samp{Password: }); after
 you type the required password, press @key{RET} to submit it.  To
 prevent others from seeing your password, every character you type is
-displayed as a dot (@samp{.}) instead of its usual form.
+displayed as an asterisk (@samp{*}) instead of its usual form.
 
   Most of the features and commands associated with the minibuffer
 @emph{cannot} be used when entering a password.  There is no history
diff --git a/doc/emacs/package.texi b/doc/emacs/package.texi
index 038a31a..c2bd5cb 100644
--- a/doc/emacs/package.texi
+++ b/doc/emacs/package.texi
@@ -126,6 +126,13 @@ line; typing @kbd{x} (see below) will delete the package.
 @xref{Package Files}, for information about what package deletion
 entails.
 
+@item w
+@kindex w @r{(Package Menu)}
+@findex package-browse-url
+Open the home page of the package on the current line in a browser
+(@code{package-browse-url}).  @code{browse-url} is used to open the
+browser.
+
 @item ~
 @kindex ~ @r{(Package Menu)}
 @findex package-menu-mark-obsolete-for-deletion
diff --git a/doc/lispintro/Makefile.in b/doc/lispintro/Makefile.in
index d8b909c..294b310 100644
--- a/doc/lispintro/Makefile.in
+++ b/doc/lispintro/Makefile.in
@@ -20,6 +20,7 @@
 SHELL = @SHELL@
 
 srcdir = @srcdir@
+top_builddir = @top_builddir@
 
 buildinfodir = $(srcdir)/../../info
 # Directory with the (customized) texinfo.tex file.
@@ -55,13 +56,7 @@ TEXI2DVI = texi2dvi
 TEXI2PDF = texi2pdf
 DVIPS = dvips
 
-# 'make' verbosity.
-AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
-
-AM_V_GEN = $(am__v_GEN_@AM_V@)
-am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
-am__v_GEN_0 = @echo "  GEN     " $@;
-am__v_GEN_1 =
+-include ${top_builddir}/src/verbose.mk
 
 ENVADD = \
   $(AM_V_GEN)TEXINPUTS="$(srcdir):$(texinfodir):$(emacsdir):$(TEXINPUTS)" \
@@ -124,6 +119,7 @@ infoclean:
          $(buildinfodir)/eintr.info-[1-9]
 
 bootstrap-clean maintainer-clean: distclean infoclean
+       rm -f TAGS
 
 .PHONY: install-dvi install-html install-pdf install-ps install-doc
 
@@ -171,5 +167,20 @@ uninstall-pdf:
 
 uninstall-doc: uninstall-dvi uninstall-html uninstall-pdf uninstall-ps
 
+ETAGS = ../../lib-src/etags${EXEEXT}
+
+${ETAGS}: FORCE
+       $(MAKE) -C $(dir $@) $(notdir $@)
+
+texifiles = $(wildcard ${srcdir}/*.texi)
+
+TAGS: ${ETAGS} $(texifiles)
+       $(AM_V_GEN)${ETAGS} $(texifiles)
+
+tags: TAGS
+.PHONY: tags
+
+FORCE:
+.PHONY: FORCE
 
 ### Makefile ends here
diff --git a/doc/lispintro/emacs-lisp-intro.texi 
b/doc/lispintro/emacs-lisp-intro.texi
index d5c280b..5b15a45 100644
--- a/doc/lispintro/emacs-lisp-intro.texi
+++ b/doc/lispintro/emacs-lisp-intro.texi
@@ -17532,10 +17532,9 @@ Here is the definition:
 @need 1250
 Now for the keybinding.
 
-Nowadays, function keys as well as mouse button events and
-non-@sc{ascii} characters are written within square brackets, without
-quotation marks.  (In Emacs version 18 and before, you had to write
-different function key bindings for each different make of terminal.)
+Function keys as well as mouse button events and non-@sc{ascii}
+characters are written within square brackets, without quotation
+marks.
 
 I bind @code{line-to-top-of-window} to my @key{F6} function key like
 this:
@@ -17550,18 +17549,18 @@ Your Init File, emacs, The GNU Emacs Manual}.
 @cindex Conditional 'twixt two versions of Emacs
 @cindex Version of Emacs, choosing
 @cindex Emacs version, choosing
-If you run two versions of GNU Emacs, such as versions 22 and 23, and
+If you run two versions of GNU Emacs, such as versions 27 and 28, and
 use one @file{.emacs} file, you can select which code to evaluate with
 the following conditional:
 
 @smallexample
 @group
 (cond
- ((= 22 emacs-major-version)
-  ;; evaluate version 22 code
+ ((= 27 emacs-major-version)
+  ;; evaluate version 27 code
   ( @dots{} ))
- ((= 23 emacs-major-version)
-  ;; evaluate version 23 code
+ ((= 28 emacs-major-version)
+  ;; evaluate version 28 code
   ( @dots{} )))
 @end group
 @end smallexample
diff --git a/doc/lispref/Makefile.in b/doc/lispref/Makefile.in
index 271f06e..a7701c5 100644
--- a/doc/lispref/Makefile.in
+++ b/doc/lispref/Makefile.in
@@ -24,6 +24,7 @@ SHELL = @SHELL@
 
 # Standard configure variables.
 srcdir = @srcdir@
+top_builddir = @top_builddir@
 
 buildinfodir = $(srcdir)/../../info
 # Directory with the (customized) texinfo.tex file.
@@ -59,13 +60,7 @@ TEXI2DVI = texi2dvi
 TEXI2PDF = texi2pdf
 DVIPS = dvips
 
-# 'make' verbosity.
-AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
-
-AM_V_GEN = $(am__v_GEN_@AM_V@)
-am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
-am__v_GEN_0 = @echo "  GEN     " $@;
-am__v_GEN_1 =
+-include ${top_builddir}/src/verbose.mk
 
 ENVADD = \
   $(AM_V_GEN)TEXINPUTS="$(srcdir):$(texinfodir):$(emacsdir):$(TEXINPUTS)" \
@@ -185,6 +180,7 @@ infoclean:
          $(buildinfodir)/elisp.info-[1-9][0-9]
 
 bootstrap-clean maintainer-clean: distclean infoclean
+       rm -f TAGS
 
 .PHONY: install-dvi install-html install-pdf install-ps install-doc
 
@@ -232,5 +228,20 @@ uninstall-pdf:
 
 uninstall-doc: uninstall-dvi uninstall-html uninstall-pdf uninstall-ps
 
+ETAGS = ../../lib-src/etags${EXEEXT}
+
+${ETAGS}: FORCE
+       $(MAKE) -C $(dir $@) $(notdir $@)
+
+texifiles = $(wildcard ${srcdir}/*.texi)
+
+TAGS: ${ETAGS} $(texifiles)
+       $(AM_V_GEN)${ETAGS} $(texifiles)
+
+tags: TAGS
+.PHONY: tags
+
+FORCE:
+.PHONY: FORCE
 
 ### Makefile ends here
diff --git a/doc/lispref/buffers.texi b/doc/lispref/buffers.texi
index 69733f9..0d31b0b 100644
--- a/doc/lispref/buffers.texi
+++ b/doc/lispref/buffers.texi
@@ -309,7 +309,6 @@ foo
 This function renames the current buffer to @var{newname}.  An error
 is signaled if @var{newname} is not a string.
 
-@c Emacs 19 feature
 Ordinarily, @code{rename-buffer} signals an error if @var{newname} is
 already in use.  However, if @var{unique} is non-@code{nil}, it modifies
 @var{newname} to make a name that is not in use.  Interactively, you can
@@ -344,7 +343,6 @@ a name.  For example:
 See also the function @code{get-buffer-create} in @ref{Creating Buffers}.
 @end defun
 
-@c Emacs 19 feature
 @defun generate-new-buffer-name starting-name &optional ignore
 This function returns a name that would be unique for a new buffer---but
 does not create the buffer.  It starts with @var{starting-name}, and
@@ -879,7 +877,6 @@ then @code{other-buffer} uses that predicate to decide 
which buffers to
 consider.  It calls the predicate once for each buffer, and if the value
 is @code{nil}, that buffer is ignored.  @xref{Buffer Parameters}.
 
-@c Emacs 19 feature
 If @var{visible-ok} is @code{nil}, @code{other-buffer} avoids returning
 a buffer visible in any window on any visible frame, except as a last
 resort.  If @var{visible-ok} is non-@code{nil}, then it does not matter
diff --git a/doc/lispref/commands.texi b/doc/lispref/commands.texi
index 3a2c7d0..8199ece 100644
--- a/doc/lispref/commands.texi
+++ b/doc/lispref/commands.texi
@@ -144,6 +144,7 @@ commands by adding the @code{interactive} form to them.
 * Interactive Codes::     The standard letter-codes for reading arguments
                              in various ways.
 * Interactive Examples::  Examples of how to read interactive arguments.
+* Command Modes::         Specifying that commands are for a specific mode.
 * Generic Commands::      Select among command alternatives.
 @end menu
 
@@ -156,7 +157,7 @@ commands by adding the @code{interactive} form to them.
 makes a Lisp function an interactively-callable command, and how to
 examine a command's @code{interactive} form.
 
-@defspec interactive arg-descriptor
+@defspec interactive &optional arg-descriptor &rest modes
 This special form declares that a function is a command, and that it
 may therefore be called interactively (via @kbd{M-x} or by entering a
 key sequence bound to it).  The argument @var{arg-descriptor} declares
@@ -177,6 +178,10 @@ forms are executed; at this time, if the 
@code{interactive} form
 occurs within the body, the form simply returns @code{nil} without
 even evaluating its argument.
 
+The @var{modes} list allows specifying which modes the command is
+meant to be used in.  See @ref{Command Modes} for more details about
+the effect of specifying @var{modes}, and when to use it.
+
 By convention, you should put the @code{interactive} form in the
 function body, as the first top-level form.  If there is an
 @code{interactive} form in both the @code{interactive-form} symbol
@@ -488,7 +493,10 @@ I/O.
 Point and the mark, as two numeric arguments, smallest first.  This is
 the only code letter that specifies two successive arguments rather than
 one.  This will signal an error if the mark is not set in the buffer
-which is current when the command is invoked.  No I/O.
+which is current when the command is invoked.  If Transient Mark mode
+is turned on (@pxref{The Mark}) --- as it is by default --- and user
+option @code{mark-even-if-inactive} is @code{nil}, Emacs will signal
+an error even if the mark @emph{is} set, but is inactive.  No I/O.
 
 @item s
 Arbitrary text, read in the minibuffer and returned as a string
@@ -588,6 +596,77 @@ Put them into three windows, selecting the last one."
 @end group
 @end example
 
+@node Command Modes
+@subsection Specifying Modes For Commands
+
+Many commands in Emacs are general, and not tied to any specific mode.
+For instance, @kbd{M-x kill-region} can be used in pretty much any
+mode that has editable text, and commands that display information
+(like @kbd{M-x list-buffers}) can be used in pretty much any context.
+
+Many other commands, however, are specifically tied to a mode, and
+make no sense outside of that context.  For instance, @code{M-x
+dired-diff} will just signal an error if used outside of a Dired
+buffer.
+
+Emacs therefore has a mechanism for specifying what mode (or modes) a
+command ``belongs'' to:
+
+@lisp
+(defun dired-diff (...)
+  ...
+  (interactive "p" dired-mode)
+  ...)
+@end lisp
+
+This will mark the command as applicable to @code{dired-mode} only (or
+any modes that are derived from @code{dired-mode}).  Any number of
+modes can be added to the @code{interactive} form.
+
+@vindex read-extended-command-predicate
+Specifying modes may affect completion in @kbd{M-x}, depending on the
+value of @code{read-extended-command-predicate}.
+
+For instance, when using the
+@code{command-completion-default-include-p} predicate, @kbd{M-x} won't
+list commands that have been marked as being applicable to a specific
+mode (unless you are in a buffer that uses that mode, of course).
+This goes for both major and minor modes.
+
+Marking commands this way will also make @kbd{C-h m} list these
+commands (if they aren't bound to any keys).
+
+If using this extended @code{interactive} form isn't convenient
+(because the code is supposed to work in older versions of Emacs that
+don't support the extended @code{interactive} form), the following
+equivalent declaration (@pxref{Declare Form}) can be used instead:
+
+@lisp
+(declare (modes dired-mode))
+@end lisp
+
+Which commands to tag with modes is to some degree a matter of taste,
+but commands that clearly do not work outside of the mode should be
+tagged.  This includes commands that will signal an error if called
+from somewhere else, but also commands that are destructive when
+called from an unexpected mode.  (This usually includes most of the
+commands that are written for special (i.e., non-editing) modes.)
+
+Some commands may be harmless, and ``work'' when called from other
+modes, but should still be tagged with a mode if they don't actually
+make much sense to use elsewhere.  For instance, many special modes
+have commands to exit the buffer bound to @kbd{q}, and may not do
+anything but issue a message like "Goodbye from this mode" and then
+call @code{kill-buffer}.  This command will ``work'' from any mode,
+but it is highly unlikely that anybody would actually want to use the
+command outside the context of this special mode.
+
+Many modes have a set of different commands that start the mode in
+different ways (e.g., @code{eww-open-in-new-buffer} and
+@code{eww-open-file}).  Commands like that should never be tagged as
+mode-specific, as they can be issued by the user from pretty much any
+context.
+
 @node Generic Commands
 @subsection Select among Command Alternatives
 @cindex generic commands
@@ -756,6 +835,29 @@ part of the prompt.
      @result{} t
 @end group
 @end example
+
+@vindex read-extended-command-predicate
+@findex command-completion-default-include-p
+This command heeds the @code{read-extended-command-predicate}
+variable, which can filter out commands that are not applicable to the
+current major mode (or enabled minor modes).  By default, the value of
+this variable is @code{nil}, and no commands are filtered out.
+However, customizing it to invoke the function
+@code{command-completion-default-include-p} will perform
+mode-dependent filtering.  @code{read-extended-command-predicate} can
+be any predicate function; it will be called with two parameters: the
+command's symbol and the current buffer.  If should return
+non-@code{nil} if the command is to be included when completing in
+that buffer.
+@end deffn
+
+@deffn Command execute-extended-command-for-buffer prefix-argument
+This is like @code{execute-extended-command}, but limits the commands
+offered for completion to those commands that are of particular
+relevance to the current major mode (and enabled minor modes).  This
+includes commands that are tagged with the modes (@pxref{Using
+Interactive}), and also commands that are bound to locally active
+keymaps.
 @end deffn
 
 @node Distinguish Interactive
diff --git a/doc/lispref/control.texi b/doc/lispref/control.texi
index 80e9eb7..3388102 100644
--- a/doc/lispref/control.texi
+++ b/doc/lispref/control.texi
@@ -617,17 +617,13 @@ match, @code{and} matches.
 @item (or @var{pattern1} @var{pattern2}@dots{})
 Attempts to match @var{pattern1}, @var{pattern2}, @dots{}, in order,
 until one of them succeeds.  In that case, @code{or} likewise matches,
-and the rest of the sub-patterns are not tested.  (Note that there
-must be at least two sub-patterns.
-Simply @w{@code{(or @var{pattern1})}} signals error.)
-@c Issue: Is this correct and intended?
-@c        Are there exceptions, qualifications?
-@c        (Btw, ``Please avoid it'' is a poor error message.)
+and the rest of the sub-patterns are not tested.
 
 To present a consistent environment (@pxref{Intro Eval})
 to @var{body-forms} (thus avoiding an evaluation error on match),
-if any of the sub-patterns let-binds a set of symbols,
-they @emph{must} all bind the same set of symbols.
+the set of variables bound by the pattern is the union of the
+variables bound by each sub-pattern.  If a variable is not bound by
+the sub-pattern that matched, then it is bound to @code{nil}.
 
 @ifnottex
 @anchor{rx in pcase}
diff --git a/doc/lispref/customize.texi b/doc/lispref/customize.texi
index 8fd12f7..bc35982 100644
--- a/doc/lispref/customize.texi
+++ b/doc/lispref/customize.texi
@@ -1474,7 +1474,7 @@ To protect against loading themes containing malicious 
code, Emacs
 displays the source file and asks for confirmation from the user
 before loading any non-built-in theme for the first time.  As
 such, themes are not ordinarily byte-compiled, and source files
-always take precedence when Emacs is looking for a theme to load.
+usually take precedence when Emacs is looking for a theme to load.
 
   The following functions are useful for programmatically enabling and
 disabling themes:
@@ -1508,6 +1508,30 @@ confirmation before loading the theme, unless the 
optional argument
 @var{no-confirm} is non-@code{nil}.
 @end deffn
 
+@defun require-theme feature &optional noerror
+This function searches @code{custom-theme-load-path} for a file that
+provides @var{feature} and then loads it.  This is like the function
+@code{require} (@pxref{Named Features}), except it searches
+@code{custom-theme-load-path} instead of @code{load-path}
+(@pxref{Library Search}).  This can be useful in Custom themes that
+need to load supporting Lisp files when @code{require} is unsuitable
+for that.
+
+If @var{feature}, which should be a symbol, is not already present in
+the current Emacs session according to @code{featurep}, then
+@code{require-theme} searches for a file named @var{feature} with an
+added @samp{.elc} or @samp{.el} suffix, in that order, in the
+directories specified by @code{custom-theme-load-path}.
+
+If a file providing @var{feature} is successfully found and loaded,
+then @code{require-theme} returns @var{feature}.  The optional
+argument @var{noerror} determines what happens if the search or
+loading fails.  If it is @code{nil}, the function signals an error;
+otherwise, it returns @code{nil}.  If the file loads successfully but
+does not provide @var{feature}, then @code{require-theme} signals an
+error; this cannot be suppressed.
+@end defun
+
 @deffn Command enable-theme theme
 This function enables the Custom theme named @var{theme}.  It signals
 an error if no such theme has been loaded.
diff --git a/doc/lispref/debugging.texi b/doc/lispref/debugging.texi
index 8e4b0eb..de98d22 100644
--- a/doc/lispref/debugging.texi
+++ b/doc/lispref/debugging.texi
@@ -1041,7 +1041,8 @@ functions written in Lisp, it cannot profile Emacs 
primitives.
 @cindex @file{benchmark.el}
 @cindex benchmarking
 You can measure the time it takes to evaluate individual Emacs Lisp
-forms using the @file{benchmark} library.  See the macros
+forms using the @file{benchmark} library.  See the function
+@code{benchmark-call} as well as the macros
 @code{benchmark-run}, @code{benchmark-run-compiled} and
 @code{benchmark-progn} in @file{benchmark.el}.  You can also use the
 @code{benchmark} command for timing forms interactively.
diff --git a/doc/lispref/display.texi b/doc/lispref/display.texi
index 93e935c..2e1b4a6 100644
--- a/doc/lispref/display.texi
+++ b/doc/lispref/display.texi
@@ -1997,7 +1997,7 @@ the beginning of the result if a multi-column character in
 
 If @var{ellipsis} is non-@code{nil}, it should be a string which will
 replace the end of @var{string} when it is truncated.  In this case,
-more charcaters will be removed from @var{string} to free enough space
+more characters will be removed from @var{string} to free enough space
 for @var{ellipsis} to fit within @var{width} columns.  However, if
 the display width of @var{string} is less than the display width of
 @var{ellipsis}, @var{ellipsis} will not be appended to the result.  If
@@ -5392,6 +5392,21 @@ are supported, unless the image type is 
@code{imagemagick}.  Positive
 values rotate clockwise, negative values counter-clockwise.  Rotation
 is performed after scaling and cropping.
 
+@item :transform-smoothing @var{smooth}
+If this is @code{t}, any image transform will have smoothing applied;
+if @code{nil}, no smoothing will be applied.  The exact algorithm used
+is platform dependent, but should be equivalent to bilinear
+filtering.  Disabling smoothing will use the nearest neighbor
+algorithm.
+
+If this property is not specified, @code{create-image} will use the
+@code{image-transform-smoothing} user option to say whether scaling
+should be done or not.  This option can be @code{nil} (no smoothing),
+@code{t} (use smoothing) or a predicate function that's called with
+the image object as the only parameter, and should return either
+@code{nil} or @code{t}.  The default is for down-scaling to apply
+smoothing, and for large up-scaling to not apply smoothing.
+
 @item :index @var{frame}
 @xref{Multi-Frame Images}.
 
@@ -7041,11 +7056,11 @@ end of the buffer continues from the other end.  If
 @var{display-message} is non-@code{nil}, the button's help-echo string
 is displayed.  Any button with a non-@code{nil} @code{skip} property
 is skipped over.  Returns the button found, and signals an error if no
-buttons can be found.  If @var{no-error} in non-@code{nil}, return nil
+buttons can be found.  If @var{no-error} is non-@code{nil}, return nil
 instead of signaling the error.
 @end deffn
 
-@deffn Command backward-button n &optional wrap display-message
+@deffn Command backward-button n &optional wrap display-message no-error
 Move to the @var{n}th previous button, or @var{n}th next button if
 @var{n} is negative.  If @var{n} is zero, move to the start of any
 button at point.  If @var{wrap} is non-@code{nil}, moving past either
@@ -7053,7 +7068,7 @@ end of the buffer continues from the other end.  If
 @var{display-message} is non-@code{nil}, the button's help-echo string
 is displayed.  Any button with a non-@code{nil} @code{skip} property
 is skipped over.  Returns the button found, and signals an error if no
-buttons can be found.  If @var{no-error} in non-@code{nil}, return nil
+buttons can be found.  If @var{no-error} is non-@code{nil}, return nil
 instead of signaling the error.
 @end deffn
 
diff --git a/doc/lispref/edebug.texi b/doc/lispref/edebug.texi
index 569545d..8942f55 100644
--- a/doc/lispref/edebug.texi
+++ b/doc/lispref/edebug.texi
@@ -1203,7 +1203,7 @@ define Edebug specifications for special forms 
implemented in C.
 
 @defmac def-edebug-spec macro specification
 Specify which expressions of a call to macro @var{macro} are forms to be
-evaluated.  @var{specification} should be the edebug specification.
+evaluated.  @var{specification} should be the Edebug specification.
 Neither argument is evaluated.
 
 The @var{macro} argument can actually be any symbol, not just a macro
@@ -1290,14 +1290,6 @@ Short for @code{&rest form}.  See @code{&rest} below.  
If your macro
 wraps its body of code with @code{lambda} before it is evaluated, use
 @code{def-body} instead.  See @code{def-body} below.
 
-@item function-form
-A function form: either a quoted function symbol, a quoted lambda
-expression, or a form (that should evaluate to a function symbol or
-lambda expression).  This is useful when an argument that's a lambda
-expression might be quoted with @code{quote} rather than
-@code{function}, since it instruments the body of the lambda expression
-either way.
-
 @item lambda-expr
 A lambda expression with no quoting.
 
@@ -1370,6 +1362,21 @@ is primarily used to generate more specific syntax error 
messages.  See
 edebug-spec; it aborts the instrumentation, displaying the message in
 the minibuffer.
 
+@item &interpose
+Lets a function control the parsing of the remaining code.
+It takes the form @code{&interpose @var{spec} @var{fun} @var{args...}}
+and means that Edebug will first match @var{spec} against the code and
+then call @var{fun} with the code that matched @code{spec}, a parsing
+function @var{pf}, and finally @var{args...}.  The parsing
+function expects a single argument indicating the specification list
+to use to parse the remaining code.  It should be called exactly once
+and returns the instrumented code that @var{fun} is expected to return.
+For example @code{(&interpose symbolp pcase--match-pat-args)} matches
+sexps whose first element is a symbol and then lets
+@code{pcase--match-pat-args} lookup the specs associated
+with that head symbol according to @code{pcase--match-pat-args} and
+pass them to the @var{pf} it received as argument.
+
 @item @var{other-symbol}
 @cindex indirect specifications
 Any other symbol in a specification list may be a predicate or an
@@ -1378,8 +1385,13 @@ indirect specification.
 If the symbol has an Edebug specification, this @dfn{indirect
 specification} should be either a list specification that is used in
 place of the symbol, or a function that is called to process the
-arguments.  The specification may be defined with @code{def-edebug-spec}
-just as for macros.  See the @code{defun} example.
+arguments.  The specification may be defined with
+@code{def-edebug-elem-spec}:
+
+@defun def-edebug-elem-spec element specification
+Define the @var{specification} to use in place of the symbol @var{element}.
+@var{specification} has to be a list.
+@end defun
 
 Otherwise, the symbol should be a predicate.  The predicate is called
 with the argument, and if the predicate returns @code{nil}, the
@@ -1428,29 +1440,23 @@ Here is a list of additional specifications that may 
appear only after
 @code{&define}.  See the @code{defun} example.
 
 @table @code
+@item &name
+Extracts the name of the current defining form from the code.
+It takes the form @code{&name [@var{prestring}] @var{spec}
+[@var{poststring}] @var{fun} @var{args...}} and means that Edebug will
+match @var{spec} against the code and then call @var{fun} with the
+concatenation of the current name, @var{args...}, @var{prestring},
+the code that matched @code{spec}, and @var{poststring}.  If @var{fun}
+is absent, it defaults to a function that concatenates the arguments
+(with an @code{@@} between the previous name and the new).
+
 @item name
 The argument, a symbol, is the name of the defining form.
+Shorthand for @code{[&name symbolp]}.
 
 A defining form is not required to have a name field; and it may have
 multiple name fields.
 
-@item :name
-This construct does not actually match an argument.  The element
-following @code{:name} should be a symbol; it is used as an additional
-name component for the definition.  You can use this to add a unique,
-static component to the name of the definition.  It may be used more
-than once.
-
-@item :unique
-This construct is like @code{:name}, but generates unique names.  It
-does not match an argument.  The element following @code{:unique}
-should be a string; it is used as the prefix for an additional name
-component for the definition.  You can use this to add a unique,
-dynamic component to the name of the definition.  This is useful for
-macros that can define the same symbol multiple times in different
-scopes, such as @code{cl-flet}; @ref{Function Bindings,,,cl}.  It may
-be used more than once.
-
 @item arg
 The argument, a symbol, is the name of an argument of the defining form.
 However, lambda-list keywords (symbols starting with @samp{&})
@@ -1557,14 +1563,14 @@ specification for @code{defmacro} is very similar to 
that for
            [&optional ("interactive" interactive)]
            def-body))
 
-(def-edebug-spec lambda-list
-  (([&rest arg]
-    [&optional ["&optional" arg &rest arg]]
-    &optional ["&rest" arg]
-    )))
+(def-edebug-elem-spec 'lambda-list
+  '(([&rest arg]
+     [&optional ["&optional" arg &rest arg]]
+     &optional ["&rest" arg]
+     )))
 
-(def-edebug-spec interactive
-  (&optional &or stringp def-form))    ; @r{Notice: @code{def-form}}
+(def-edebug-elem-spec 'interactive
+  '(&optional &or stringp def-form))    ; @r{Notice: @code{def-form}}
 @end smallexample
 
 The specification for backquote below illustrates how to match
@@ -1577,11 +1583,11 @@ could fail.)
 @smallexample
 (def-edebug-spec \` (backquote-form))   ; @r{Alias just for clarity.}
 
-(def-edebug-spec backquote-form
-  (&or ([&or "," ",@@"] &or ("quote" backquote-form) form)
-       (backquote-form . [&or nil backquote-form])
-       (vector &rest backquote-form)
-       sexp))
+(def-edebug-elem-spec 'backquote-form
+  '(&or ([&or "," ",@@"] &or ("quote" backquote-form) form)
+        (backquote-form . [&or nil backquote-form])
+        (vector &rest backquote-form)
+        sexp))
 @end smallexample
 
 
@@ -1624,10 +1630,10 @@ option.  @xref{Instrumenting}.
 
 @defopt edebug-eval-macro-args
 When this is non-@code{nil}, all macro arguments will be instrumented
-in the generated code.  For any macro, an @code{edebug-form-spec}
+in the generated code.  For any macro, the @code{debug} declaration
 overrides this option.  So to specify exceptions for macros that have
-some arguments evaluated and some not, use @code{def-edebug-spec} to
-specify an @code{edebug-form-spec}.
+some arguments evaluated and some not, use the @code{debug} declaration
+specify an Edebug form specification.
 @end defopt
 
 @defopt edebug-save-windows
diff --git a/doc/lispref/elisp.texi b/doc/lispref/elisp.texi
index 12255d1..dade855 100644
--- a/doc/lispref/elisp.texi
+++ b/doc/lispref/elisp.texi
@@ -1408,8 +1408,9 @@ Low-Level Network Access
 
 Packing and Unpacking Byte Arrays
 
-* Bindat Spec::             Describing data layout.
+* Bindat Types::            Describing data layout.
 * Bindat Functions::        Doing the unpacking and packing.
+* Bindat Computed Types::   Advanced data layout specifications.
 
 Emacs Display
 
diff --git a/doc/lispref/eval.texi b/doc/lispref/eval.texi
index 80e038c..448b8ae 100644
--- a/doc/lispref/eval.texi
+++ b/doc/lispref/eval.texi
@@ -332,7 +332,6 @@ or just
   The built-in function @code{indirect-function} provides an easy way to
 perform symbol function indirection explicitly.
 
-@c Emacs 19 feature
 @defun indirect-function function &optional noerror
 @anchor{Definition of indirect-function}
 This function returns the meaning of @var{function} as a function.  If
diff --git a/doc/lispref/files.texi b/doc/lispref/files.texi
index 4110c51..a8b921e 100644
--- a/doc/lispref/files.texi
+++ b/doc/lispref/files.texi
@@ -455,7 +455,6 @@ Even though this is not a normal hook, you can use 
@code{add-hook} and
 @code{remove-hook} to manipulate the list.  @xref{Hooks}.
 @end defvar
 
-@c Emacs 19 feature
 @defvar write-contents-functions
 This works just like @code{write-file-functions}, but it is intended
 for hooks that pertain to the buffer's contents, not to the particular
@@ -486,7 +485,6 @@ this hook to make sure the file you are saving has the 
current year in
 its copyright notice.
 @end defopt
 
-@c Emacs 19 feature
 @defopt after-save-hook
 This normal hook runs after a buffer has been saved in its visited file.
 @end defopt
@@ -622,7 +620,6 @@ If @var{start} is @code{nil}, then the command writes the 
entire buffer
 contents (@emph{not} just the accessible portion) to the file and
 ignores @var{end}.
 
-@c Emacs 19 feature
 If @var{start} is a string, then @code{write-region} writes or appends
 that string, rather than text from the buffer.  @var{end} is ignored in
 this case.
@@ -653,7 +650,6 @@ It also sets the last file modification time for the 
current buffer to
 feature is used by @code{save-buffer}, but you probably should not use
 it yourself.
 
-@c Emacs 19 feature
 If @var{visit} is a string, it specifies the file name to visit.  This
 way, you can write the data to one file (@var{filename}) while recording
 the buffer as visiting another file (@var{visit}).  The argument
@@ -768,6 +764,8 @@ This function unlocks the file being visited in the current 
buffer,
 if the buffer is modified.  If the buffer is not modified, then
 the file should not be locked, so this function does nothing.  It also
 does nothing if the current buffer is not visiting a file, or is not locked.
+This function handles file system errors by calling @code{display-warning}
+and otherwise ignores the error.
 @end defun
 
 @defopt create-lockfiles
@@ -3094,7 +3092,6 @@ which generate the listing with Lisp code.
 @node Create/Delete Dirs
 @section Creating, Copying and Deleting Directories
 @cindex creating, copying and deleting directories
-@c Emacs 19 features
 
   Most Emacs Lisp file-manipulation functions get errors when used on
 files that are directories.  For example, you cannot delete a directory
diff --git a/doc/lispref/frames.texi b/doc/lispref/frames.texi
index f4316b7..cd2ff8f 100644
--- a/doc/lispref/frames.texi
+++ b/doc/lispref/frames.texi
@@ -1120,9 +1120,9 @@ The optional fourth argument @var{pixelwise} 
non-@code{nil} means that
 refuse to truly honor the request if it does not increase/decrease the
 frame height to a multiple of its character height.
 
-When used interactively, this command will set the height of the
-currently selected frame to the number of lines specified by the
-numeric prefix.
+When used interactively, this command will ask the user for the number
+of lines to set the height of the currently selected frame.  You can
+also provide this value with a numeric prefix.
 @end defun
 
 @defun set-frame-width frame width &optional pretend pixelwise
@@ -1136,9 +1136,9 @@ The optional fourth argument @var{pixelwise} 
non-@code{nil} means that
 refuse to fully honor the request if it does not increase/decrease the
 frame width to a multiple of its character width.
 
-When used interactively, this command will set the width of the
-currently selected frame to the number of columns specified by the
-numeric prefix.
+When used interactively, this command will ask the user for the number
+of columns to set the width of the currently selected frame.  You can
+also provide this value with a numeric prefix.
 @end defun
 
 None of these three functions will make a frame smaller than needed to
diff --git a/doc/lispref/functions.texi b/doc/lispref/functions.texi
index 414035f..64883bf 100644
--- a/doc/lispref/functions.texi
+++ b/doc/lispref/functions.texi
@@ -863,6 +863,10 @@ This function returns @var{argument} and has no side 
effects.
 This function ignores any @var{arguments} and returns @code{nil}.
 @end defun
 
+@defun always &rest arguments
+This function ignores any @var{arguments} and returns @code{t}.
+@end defun
+
   Some functions are user-visible @dfn{commands}, which can be called
 interactively (usually by a key sequence).  It is possible to invoke
 such a command exactly as though it was called interactively, by using
@@ -1177,7 +1181,7 @@ This form defines a method like @code{cl-defmethod} does.
 @end table
 @end defmac
 
-@defmac cl-defmethod name [qualifier] arguments [&context (expr spec)@dots{}] 
&rest [docstring] body
+@defmac cl-defmethod name [extra] [qualifier] arguments [&context (expr 
spec)@dots{}] &rest [docstring] body
 This macro defines a particular implementation for the generic
 function called @var{name}.  The implementation code is given by
 @var{body}.  If present, @var{docstring} is the documentation string
@@ -1263,6 +1267,10 @@ Parent type: @code{array}.
 @item font-object
 @end table
 
+The optional @var{extra} element, expressed as @samp{:extra
+@var{string}}, allows you to add more methods, distinguished by
+@var{string}, for the same specializers and qualifiers.
+
 The optional @var{qualifier} allows combining several applicable
 methods.  If it is not present, the defined method is a @dfn{primary}
 method, responsible for providing the primary implementation of the
@@ -1284,9 +1292,6 @@ This auxiliary method will run @emph{instead} of the 
primary method.
 The most specific of such methods will be run before any other method.
 Such methods normally use @code{cl-call-next-method}, described below,
 to invoke the other auxiliary or primary methods.
-@item :extra @var{string}
-This allows you to add more methods, distinguished by @var{string},
-for the same specializers and qualifiers.
 @end table
 
 Functions defined using @code{cl-defmethod} cannot be made
@@ -2309,6 +2314,16 @@ form @code{(lambda (@var{arg}) @var{body})} in which 
case that function will
 additionally have access to the macro (or function)'s arguments and it will
 be passed to @code{gv-define-setter}.
 
+@item (completion @var{completion-predicate})
+Declare @var{completion-predicate} as a function to determine whether
+to include the symbol in the list of functions when asking for
+completions in @kbd{M-x}.  @var{completion-predicate} is called with
+two parameters: The first parameter is the symbol, and the second is
+the current buffer.
+
+@item (modes @var{modes})
+Specify that this command is meant to be applicable for @var{modes}
+only.
 @end table
 
 @end defmac
diff --git a/doc/lispref/keymaps.texi b/doc/lispref/keymaps.texi
index 55d179b..dabf985 100644
--- a/doc/lispref/keymaps.texi
+++ b/doc/lispref/keymaps.texi
@@ -369,7 +369,6 @@ appear directly as bindings in @var{keymap} are also copied 
recursively,
 and so on to any number of levels.  However, recursive copying does not
 take place when the definition of a character is a symbol whose function
 definition is a keymap; the same symbol appears in the new copy.
-@c Emacs 19 feature
 
 @example
 @group
@@ -574,12 +573,6 @@ key.
 key.
 
 @item
-@cindex @kbd{M-o}
-@vindex facemenu-keymap
-@code{facemenu-keymap} is the global keymap used for the @kbd{M-o}
-prefix key.
-
-@item
 The other Emacs prefix keys are @kbd{C-x @@}, @kbd{C-x a i}, @kbd{C-x
 @key{ESC}} and @kbd{@key{ESC} @key{ESC}}.  They use keymaps that have
 no special names.
@@ -1146,7 +1139,6 @@ and have extra events at the end that do not fit into a 
single key
 sequence.  Then the value is a number, the number of events at the front
 of @var{key} that compose a complete key.
 
-@c Emacs 19 feature
 If @var{accept-defaults} is non-@code{nil}, then @code{lookup-key}
 considers default bindings as well as bindings for the specific events
 in @var{key}.  Otherwise, @code{lookup-key} reports only bindings for
@@ -1188,7 +1180,6 @@ not cause an error.
 This function returns the binding for @var{key} in the current
 local keymap, or @code{nil} if it is undefined there.
 
-@c Emacs 19 feature
 The argument @var{accept-defaults} controls checking for default bindings,
 as in @code{lookup-key} (above).
 @end defun
@@ -1197,12 +1188,10 @@ as in @code{lookup-key} (above).
 This function returns the binding for command @var{key} in the
 current global keymap, or @code{nil} if it is undefined there.
 
-@c Emacs 19 feature
 The argument @var{accept-defaults} controls checking for default bindings,
 as in @code{lookup-key} (above).
 @end defun
 
-@c Emacs 19 feature
 @defun minor-mode-key-binding key &optional accept-defaults
 This function returns a list of all the active minor mode bindings of
 @var{key}.  More precisely, it returns an alist of pairs
@@ -1420,7 +1409,6 @@ standard bindings:
 @end group
 @end smallexample
 
-@c Emacs 19 feature
 If @var{oldmap} is non-@code{nil}, that changes the behavior of
 @code{substitute-key-definition}: the bindings in @var{oldmap} determine
 which keys to rebind.  The rebindings still happen in @var{keymap}, not
diff --git a/doc/lispref/loading.texi b/doc/lispref/loading.texi
index 22f0dde..e68a1ef 100644
--- a/doc/lispref/loading.texi
+++ b/doc/lispref/loading.texi
@@ -510,6 +510,9 @@ specification is not given here; it's not needed unless the 
user
 actually calls @var{function}, and when that happens, it's time to load
 the real definition.
 
+If @var{interactive} is a list, it is interpreted as a list of modes
+this command is applicable for.
+
 You can autoload macros and keymaps as well as ordinary functions.
 Specify @var{type} as @code{macro} if @var{function} is really a macro.
 Specify @var{type} as @code{keymap} if @var{function} is really a
@@ -1049,7 +1052,6 @@ rather than replacing that element.  @xref{Eval}.
 @section Unloading
 @cindex unloading packages
 
-@c Emacs 19 feature
   You can discard the functions and variables loaded by a library to
 reclaim memory for other Lisp objects.  To do this, use the function
 @code{unload-feature}:
@@ -1125,7 +1127,7 @@ You don't need to give a directory or extension in the 
file name
 @var{library}.  Normally, you just give a bare file name, like this:
 
 @example
-(with-eval-after-load "edebug" (def-edebug-spec c-point t))
+(with-eval-after-load "js" (define-key js-mode-map "\C-c\C-c" 'js-eval))
 @end example
 
 To restrict which files can trigger the evaluation, include a
diff --git a/doc/lispref/maps.texi b/doc/lispref/maps.texi
index aea0242..59c6e6f 100644
--- a/doc/lispref/maps.texi
+++ b/doc/lispref/maps.texi
@@ -53,9 +53,6 @@ A sparse keymap for subcommands of the prefix @kbd{C-x r}.@*
 @item esc-map
 A full keymap for @key{ESC} (or @key{Meta}) commands.
 
-@item facemenu-keymap
-A sparse keymap used for the @kbd{M-o} prefix key.
-
 @item function-key-map
 The parent keymap of all @code{local-function-key-map} (q.v.@:) instances.
 
diff --git a/doc/lispref/markers.texi b/doc/lispref/markers.texi
index b39373f..80f79b6 100644
--- a/doc/lispref/markers.texi
+++ b/doc/lispref/markers.texi
@@ -609,8 +609,8 @@ the function @code{use-region-p} for that (@pxref{The 
Region}).
 @defvarx deactivate-mark-hook
 These normal hooks are run, respectively, when the mark becomes active
 and when it becomes inactive.  The hook @code{activate-mark-hook} is
-also run at the end of the command loop if the mark is active and it
-is possible that the region may have changed.
+also run when the region is reactivated, for instance after using a
+command that switches back to a buffer that has an active mark.
 @ignore
 This piece of command_loop_1, run unless deactivating the mark:
   if (current_buffer != prev_buffer || MODIFF != prev_modiff)
diff --git a/doc/lispref/minibuf.texi b/doc/lispref/minibuf.texi
index b60775d..d16409d 100644
--- a/doc/lispref/minibuf.texi
+++ b/doc/lispref/minibuf.texi
@@ -379,8 +379,6 @@ default, it makes the following bindings:
 @end table
 @end defvar
 
-@c In version 18, initial is required
-@c Emacs 19 feature
 @defun read-no-blanks-input prompt &optional initial inherit-input-method
 This function reads a string from the minibuffer, but does not allow
 whitespace characters as part of the input: instead, those characters
@@ -701,8 +699,9 @@ A history list for numbers read by @code{read-number}.
 @end defvar
 
 @defvar goto-line-history
-A history list for arguments to @code{goto-line}.  This variable is
-buffer local.
+A history list for arguments to @code{goto-line}.  This variable can
+be made local in every buffer by customizing the user option
+@code{goto-line-history-local}.
 @end defvar
 
 @c Less common: coding-system-history, input-method-history,
@@ -2474,7 +2473,6 @@ usual minibuffer input functions because they all start 
by choosing the
 minibuffer window according to the selected frame.
 @end defun
 
-@c Emacs 19 feature
 @defun window-minibuffer-p &optional window
 This function returns @code{t} if @var{window} is a minibuffer window.
 @var{window} defaults to the selected window.
@@ -2618,7 +2616,6 @@ when the minibuffer is active, not even if you switch to 
another window
 to do it.
 @end defopt
 
-@c Emacs 19 feature
 If a command name has a property @code{enable-recursive-minibuffers}
 that is non-@code{nil}, then the command can use the minibuffer to read
 arguments even if it is invoked from the minibuffer.  A command can
diff --git a/doc/lispref/modes.texi b/doc/lispref/modes.texi
index ce7727b..6cf4dd2 100644
--- a/doc/lispref/modes.texi
+++ b/doc/lispref/modes.texi
@@ -861,6 +861,13 @@ abbrev table as @var{parent}, or 
@code{fundamental-mode-abbrev-table}
 if @var{parent} is @code{nil}.  (Again, a @code{nil} value is
 @emph{not} equivalent to not specifying this keyword.)
 
+@item :interactive
+Modes are interactive commands by default.  If you specify a
+@code{nil} value, the mode defined here won't be interactive.  This is
+useful for modes that are never meant to be activated by users
+manually, but are only supposed to be used in some specially-formatted
+buffer.
+
 @item :group
 If this is specified, the value should be the customization group for
 this mode.  (Not all major modes have one.)  The command
@@ -1454,6 +1461,16 @@ used only with Diff mode.
 other minor modes in effect.  It should be possible to activate and
 deactivate minor modes in any order.
 
+@defvar local-minor-modes
+This buffer-local variable lists the currently enabled minor modes in
+the current buffer, and is a list of symbols.
+@end defvar
+
+@defvar global-minor-modes
+This variable lists the currently enabled global minor modes, and is a
+list of symbols.
+@end defvar
+
 @defvar minor-mode-list
 The value of this variable is a list of all minor mode commands.
 @end defvar
@@ -1730,6 +1747,11 @@ and @var{set} is a function of one argument (a state) 
that sets it.
 @item :after-hook @var{after-hook}
 This defines a single Lisp form which is evaluated after the mode hooks
 have run.  It should not be quoted.
+
+@item :interactive @var{value}
+Minor modes are interactive commands by default.  If @var{value} is
+@code{nil}, this is inhibited.  If @var{value} is a list of symbols,
+it's used to say which major modes this minor mode is useful in.
 @end table
 
 Any other keyword arguments are passed directly to the
@@ -3225,8 +3247,7 @@ set by means of @var{other-vars} in 
@code{font-lock-defaults}
 @defvar font-lock-mark-block-function
 If this variable is non-@code{nil}, it should be a function that is
 called with no arguments, to choose an enclosing range of text for
-refontification for the command @kbd{M-o M-o}
-(@code{font-lock-fontify-block}).
+refontification for the command @kbd{M-x font-lock-fontify-block}.
 
 The function should report its choice by placing the region around it.
 A good choice is a range of text large enough to give proper results,
diff --git a/doc/lispref/numbers.texi b/doc/lispref/numbers.texi
index 63e3e0b..4c5f7212 100644
--- a/doc/lispref/numbers.texi
+++ b/doc/lispref/numbers.texi
@@ -1250,7 +1250,7 @@ other strings to choose various seed values.
 This function returns a pseudo-random integer.  Repeated calls return a
 series of pseudo-random integers.
 
-If @var{limit} is a positive fixnum, the value is chosen to be
+If @var{limit} is a positive integer, the value is chosen to be
 nonnegative and less than @var{limit}.  Otherwise, the value might be
 any fixnum, i.e., any integer from @code{most-negative-fixnum} through
 @code{most-positive-fixnum} (@pxref{Integer Basics}).
diff --git a/doc/lispref/objects.texi b/doc/lispref/objects.texi
index 64e7d53..0d0caeb 100644
--- a/doc/lispref/objects.texi
+++ b/doc/lispref/objects.texi
@@ -148,9 +148,6 @@ starting list count:
 object, so when reading back the object, they will be the same object
 instead of copies (@pxref{Circular Objects}).
 
-@item #@@N
-Skip the next @samp{N} characters (@pxref{Comments}).
-
 @item #xN
 @samp{N} represented as a hexadecimal number (@samp{#x2a}).
 
diff --git a/doc/lispref/positions.texi b/doc/lispref/positions.texi
index dc0c744..769aeed 100644
--- a/doc/lispref/positions.texi
+++ b/doc/lispref/positions.texi
@@ -232,7 +232,6 @@ backward until encountering the front of a word, rather 
than forward.
 @end deffn
 
 @defopt words-include-escapes
-@c Emacs 19 feature
 This variable affects the behavior of @code{forward-word} and
 @code{backward-word}, and everything that uses them.  If it is
 non-@code{nil}, then characters in the escape and character-quote
diff --git a/doc/lispref/processes.texi b/doc/lispref/processes.texi
index 8346165..b324649 100644
--- a/doc/lispref/processes.texi
+++ b/doc/lispref/processes.texi
@@ -3354,24 +3354,37 @@ To use the functions referred to in this section, load 
the
 direction is also known as @dfn{serializing} or @dfn{packing}.
 
 @menu
-* Bindat Spec::         Describing data layout.
-* Bindat Functions::    Doing the unpacking and packing.
+* Bindat Types::            Describing data layout.
+* Bindat Functions::        Doing the unpacking and packing.
+* Bindat Computed Types::   Advanced data layout specifications.
 @end menu
 
-@node Bindat Spec
+@node Bindat Types
 @subsection Describing Data Layout
+@cindex bindat types
 
+@cindex data layout specification
+@cindex bindat type expression
+@cindex base type, in bindat specification
+@cindex composite type, in bindat specification
   To control unpacking and packing, you write a @dfn{data layout
-specification}, a special nested list describing named and typed
-@dfn{fields}.  This specification controls the length of each field to be
-processed, and how to pack or unpack it.  We normally keep bindat specs
-in variables whose names end in @samp{-bindat-spec}; that kind of name
-is automatically recognized as risky.
-
-@cindex endianness
-@cindex big endian
-@cindex little endian
-@cindex network byte ordering
+specification}, also called a @dfn{Bindat type expression}.  This can
+be a @dfn{base type} or a @dfn{composite type} made of several fields,
+where the specification controls the length of each field to be
+processed, and how to pack or unpack it.  We normally keep bindat type
+values in variables whose names end in @code{-bindat-spec}; that kind
+of name is automatically recognized as risky (@pxref{File Local
+Variables}).
+
+@defmac bindat-type &rest type
+Creates a Bindat type @emph{value} object according to the Bindat type
+@emph{expression} @var{type}.
+@end defmac
+
+@cindex endianness, in bindat specification
+@cindex big endian, in bindat specification
+@cindex little endian, in bindat specification
+@cindex network byte ordering, in Bindat specification
   A field's @dfn{type} describes the size (in bytes) of the object
 that the field represents and, in the case of multibyte fields, how
 the bytes are ordered within the field.  The two possible orderings
@@ -3386,164 +3399,91 @@ type values:
 @itemx byte
 Unsigned byte, with length 1.
 
-@item u16
-@itemx word
-@itemx short
-Unsigned integer in network byte order, with length 2.
+@item uint @var{bitlen}
+Unsigned integer in network byte order, with @var{bitlen} bits.
+@var{bitlen} has to be a multiple of 8.
 
-@item u24
-Unsigned integer in network byte order, with length 3.
-
-@item u32
-@itemx dword
-@itemx long
-Unsigned integer in network byte order, with length 4.
-Note: These values may be limited by Emacs's integer implementation limits.
-
-@item u16r
-@itemx u24r
-@itemx u32r
-Unsigned integer in little endian order, with length 2, 3 and 4, respectively.
+@item uintr @var{bitlen}
+Unsigned integer in little endian order, with @var{bitlen} bits.
+@var{bitlen} has to be a multiple of 8.
 
 @item str @var{len}
-String of length @var{len}.
+String of bytes of length @var{len}.
 
 @item strz @var{len}
-Zero-terminated string, in a fixed-size field with length @var{len}.
+Zero-terminated string of bytes, in a fixed-size field with length @var{len}.
 
 @item vec @var{len} [@var{type}]
-Vector of @var{len} elements of type @var{type}, defaulting to bytes.
-The @var{type} is any of the simple types above, or another vector
-specified as a list of the form @code{(vec @var{len} [@var{type}])}.
+Vector of @var{len} elements.  The type of the elements is given by
+@var{type}, defaulting to bytes.  The @var{type} can be any Bindat
+type expression.
 
-@item ip
-@c FIXME?  IPv6?
-Four-byte vector representing an Internet address.  For example:
-@code{[127 0 0 1]} for localhost.
+@item repeat @var{len} [@var{type}]
+Like @code{vec}, but it unpacks to and packs from lists, whereas
+@code{vec} unpacks to vectors.
 
 @item bits @var{len}
-List of set bits in @var{len} bytes.  The bytes are taken in big
-endian order and the bits are numbered starting with @code{8 *
-@var{len} @minus{} 1} and ending with zero.  For example: @code{bits
-2} unpacks @code{#x28} @code{#x1c} to @code{(2 3 4 11 13)} and
-@code{#x1c} @code{#x28} to @code{(3 5 10 11 12)}.
-
-@item (eval @var{form})
-@var{form} is a Lisp expression evaluated at the moment the field is
-unpacked or packed.  The result of the evaluation should be one of the
-above-listed type specifications.
-@end table
-
-For a fixed-size field, the length @var{len} is given as an integer
-specifying the number of bytes in the field.
-
-When the length of a field is not fixed, it typically depends on the
-value of a preceding field.  In this case, the length @var{len} can be
-given either as a list @code{(@var{name} ...)} identifying a
-@dfn{field name} in the format specified for @code{bindat-get-field}
-below, or by an expression @code{(eval @var{form})} where @var{form}
-should evaluate to an integer, specifying the field length.
-
-A field specification generally has the form @code{([@var{name}]
-@var{handler})}, where @var{name} is optional.  Don't use names that
-are symbols meaningful as type specifications (above) or handler
-specifications (below), since that would be ambiguous.  @var{name} can
-be a symbol or an expression @code{(eval @var{form})}, in which case
-@var{form} should evaluate to a symbol.
-
-@var{handler} describes how to unpack or pack the field and can be one
-of the following:
-
-@table @code
-@item @var{type}
-Unpack/pack this field according to the type specification @var{type}.
-
-@item eval @var{form}
-Evaluate @var{form}, a Lisp expression, for side-effect only.  If the
-field name is specified, the value is bound to that field name.
+List of bits that are set to 1 in @var{len} bytes.  The bytes are
+taken in big-endian order, and the bits are numbered starting with
+@code{8 * @var{len} @minus{} 1} and ending with zero.  For example:
+@code{bits 2} unpacks @code{#x28} @code{#x1c} to @w{@code{(2 3 4 11 13)}}
+and @code{#x1c} @code{#x28} to @w{@code{(3 5 10 11 12)}}.
 
 @item fill @var{len}
-Skip @var{len} bytes.  In packing, this leaves them unchanged,
-which normally means they remain zero.  In unpacking, this means
-they are ignored.
+@var{len} bytes used as a mere filler.  In packing, these bytes are
+are left unchanged, which normally means they remain zero.
+When unpacking, this just returns nil.
 
 @item align @var{len}
-Skip to the next multiple of @var{len} bytes.
-
-@item struct @var{spec-name}
-Process @var{spec-name} as a sub-specification.  This describes a
-structure nested within another structure.
-
-@item union @var{form} (@var{tag} @var{spec})@dots{}
-@c ??? I don't see how one would actually  use this.
-@c ??? what kind of expression would be useful for @var{form}?
-Evaluate @var{form}, a Lisp expression, find the first @var{tag}
-that matches it, and process its associated data layout specification
-@var{spec}.  Matching can occur in one of three ways:
-
-@itemize
-@item
-If a @var{tag} has the form @code{(eval @var{expr})}, evaluate
-@var{expr} with the variable @code{tag} dynamically bound to the value
-of @var{form}.  A non-@code{nil} result indicates a match.
-
-@item
-@var{tag} matches if it is @code{equal} to the value of @var{form}.
-
-@item
-@var{tag} matches unconditionally if it is @code{t}.
-@end itemize
-
-@item repeat @var{count} @var{field-specs}@dots{}
-Process the @var{field-specs} recursively, in order, then repeat
-starting from the first one, processing all the specifications @var{count}
-times overall.  The @var{count} is given using the same formats as a
-field length---if an @code{eval} form is used, it is evaluated just once.
-For correct operation, each specification in @var{field-specs} must
-include a name.
+Same as @code{fill} except the number of bytes is that needed to skip
+to the next multiple of @var{len} bytes.
+
+@item type @var{exp}
+This lets you refer to a type indirectly: @var{exp} is a Lisp
+expression which should return a Bindat type @emph{value}.
+
+@item unit @var{exp}
+This is a trivial type which uses up 0 bits of space.  @var{exp}
+describes the value returned when we try to ``unpack'' such a field.
+
+@item struct @var{fields}...
+Composite type made of several fields.  Every field is of the form
+@code{(@var{name} @var{type})} where @var{type} can be any Bindat
+type expression.  @var{name} can be @code{_} when the field's value
+does not deserve to be named, as is often the case for @code{align}
+and @code{fill} fields.
+When the context makes it clear that this is a Bindat type expression,
+the symbol @code{struct} can be omitted.
 @end table
 
-For the @code{(eval @var{form})} forms used in a bindat specification,
-the @var{form} can access and update these dynamically bound variables
-during evaluation:
+In the types above, @var{len} and @var{bitlen} are given as an integer
+specifying the number of bytes (or bits) in the field.  When the
+length of a field is not fixed, it typically depends on the value of
+preceding fields.  For this reason, the length @var{len} does not have
+to be a constant but can be any Lisp expression and it can refer to
+the value of previous fields via their name.
 
-@table @code
-@item last
-Value of the last field processed.
-
-@item bindat-raw
-The data as a byte array.
-
-@item bindat-idx
-Current index (within @code{bindat-raw}) for unpacking or packing.
-
-@item struct
-The alist containing the structured data that have been unpacked so
-far, or the entire structure being packed.  You can use
-@code{bindat-get-field} to access specific fields of this structure.
-
-@item count
-@itemx index
-Inside a @code{repeat} block, these contain the maximum number of
-repetitions (as specified by the @var{count} parameter), and the
-current repetition number (counting from 0).  Setting @code{count} to
-zero will terminate the inner-most repeat block after the current
-repetition has completed.
-@end table
+For example, the specification of a data layout where a leading byte gives
+the size of a subsequent vector of 16 bit integers could be:
+@example
+(bindat-type
+  (len      u8)
+  (payload  vec (1+ len) uint 16))
+@end example
 
 @node Bindat Functions
 @subsection Functions to Unpack and Pack Bytes
+@cindex bindat functions
 
-  In the following documentation, @var{spec} refers to a data layout
-specification, @code{bindat-raw} to a byte array, and @var{struct} to an
-alist representing unpacked field data.
+  In the following documentation, @var{type} refers to a Bindat type
+value as returned from @code{bindat-type}, @var{raw} to a byte
+array, and @var{struct} to an alist representing unpacked field data.
 
-@defun bindat-unpack spec bindat-raw &optional bindat-idx
-@c FIXME?  Again, no multibyte?
+@defun bindat-unpack type raw &optional idx
 This function unpacks data from the unibyte string or byte
-array @code{bindat-raw}
-according to @var{spec}.  Normally, this starts unpacking at the
-beginning of the byte array, but if @var{bindat-idx} is non-@code{nil}, it
+array @var{raw}
+according to @var{type}.  Normally, this starts unpacking at the
+beginning of the byte array, but if @var{idx} is non-@code{nil}, it
 specifies a zero-based starting position to use instead.
 
 The value is an alist or nested alist in which each element describes
@@ -3555,12 +3495,13 @@ This function selects a field's data from the nested 
alist
 @var{struct}.  Usually @var{struct} was returned by
 @code{bindat-unpack}.  If @var{name} corresponds to just one argument,
 that means to extract a top-level field value.  Multiple @var{name}
-arguments specify repeated lookup of sub-structures.  An integer name
-acts as an array index.
+arguments specify repeated lookup of sub-structures.  An integer
+@var{name} acts as an array index.
 
-For example, if @var{name} is @code{(a b 2 c)}, that means to find
-field @code{c} in the third element of subfield @code{b} of field
-@code{a}.  (This corresponds to @code{struct.a.b[2].c} in C.)
+For example, @w{@code{(bindat-get-field @var{struct} a b 2 c)}} means
+to find field @code{c} in the third element of subfield @code{b} of
+field @code{a}.  (This corresponds to @code{@var{struct}.a.b[2].c} in
+the C programming language syntax.)
 @end defun
 
   Although packing and unpacking operations change the organization of
@@ -3571,20 +3512,20 @@ both pieces of information contribute to its 
calculation.  Likewise, the
 length of a string or array being unpacked may be longer than the data's
 total length as described by the specification.
 
-@defun bindat-length spec struct
+@defun bindat-length type struct
 This function returns the total length of the data in @var{struct},
-according to @var{spec}.
+according to @var{type}.
 @end defun
 
-@defun bindat-pack spec struct &optional bindat-raw bindat-idx
-This function returns a byte array packed according to @var{spec} from
+@defun bindat-pack type struct &optional raw idx
+This function returns a byte array packed according to @var{type} from
 the data in the alist @var{struct}.  It normally creates and fills a
-new byte array starting at the beginning.  However, if @var{bindat-raw}
+new byte array starting at the beginning.  However, if @var{raw}
 is non-@code{nil}, it specifies a pre-allocated unibyte string or vector to
-pack into.  If @var{bindat-idx} is non-@code{nil}, it specifies the starting
-offset for packing into @code{bindat-raw}.
+pack into.  If @var{idx} is non-@code{nil}, it specifies the starting
+offset for packing into @var{raw}.
 
-When pre-allocating, you should make sure @code{(length @var{bindat-raw})}
+When pre-allocating, you should make sure @code{(length @var{raw})}
 meets or exceeds the total length to avoid an out-of-range error.
 @end defun
 
@@ -3598,3 +3539,74 @@ dotted notation.
      @result{} "127.0.0.1"
 @end example
 @end defun
+
+@node Bindat Computed Types
+@subsection Advanced data layout specifications
+@cindex bindat computed types
+
+Bindat type expressions are not limited to the types described
+earlier.  They can also be arbitrary Lisp forms returning Bindat
+type expressions.  For example, the type below describes data which
+can either contain a 24-bit error code or a vector of bytes:
+
+@example
+(bindat-type
+  (len      u8)
+  (payload  . (if (zerop len) (uint 24) (vec (1- len)))))
+@end example
+
+@cindex bindat packing and unpacking into arbitrary types
+Furthermore, while composite types are normally unpacked to (and
+packed from) association lists, this can be changed via the use of
+the following special keyword arguments:
+
+@table @code
+@item :unpack-val @var{exp}
+When the list of fields ends with this keyword argument, then the value
+returned when unpacking is the value of @var{exp} instead of the
+standard alist.  @var{exp} can refer to all the previous fields by
+their name.
+
+@item :pack-val @var{exp}
+If a field's type is followed by this keyword argument, then the value
+packed into this field is returned by @var{exp} instead of being
+extracted from the alist.
+
+@item :pack-var @var{name}
+If the list of fields is preceded by this keyword argument, then all
+the subsequent @code{:pack-val} arguments can refer to the overall
+value to pack into this composite type via the variable named
+@var{name}.
+@end table
+
+For example, one could describe a 16-bit signed integer as follows:
+
+@example
+(defconst sint16-bindat-spec
+  (let* ((max (ash 1 15))
+         (wrap (+ max max)))
+    (bindat-type :pack-var v
+                 (n uint 16 :pack-val (if (< v 0) (+ v wrap) v))
+                 :unpack-val (if (>= n max) (- n wrap) n))))
+@end example
+
+Which would then behave as follows:
+@example
+(bindat-pack sint16-bindat-spec -8)
+     @result{} "\377\370"
+
+(bindat-unpack sint16-bindat-spec "\300\100")
+     @result{} -16320
+@end example
+
+@cindex define new bindat type forms
+@cindex bindat, define new type forms
+Finally, you can define new Bindat type forms to use in Bindat type
+expressions with @code{bindat-defmacro}:
+
+@defmac bindat-defmacro name args &rest body
+Define a new Bindat type expression named @var{name} and taking
+arguments @var{args}.  Its behavior follows that of @code{defmacro},
+which the important difference that the new forms can only be used
+within Bindat type expressions.
+@end defmac
diff --git a/doc/lispref/sequences.texi b/doc/lispref/sequences.texi
index 0c74dbe..545fd40 100644
--- a/doc/lispref/sequences.texi
+++ b/doc/lispref/sequences.texi
@@ -609,7 +609,7 @@ returned value is a list.
 (seq-map-indexed (lambda (elt idx)
                    (list idx elt))
                  '(a b c))
-@result{} ((0 a) (b 1) (c 2))
+@result{} ((0 a) (1 b) (2 c))
 @end group
 @end example
 @end defun
diff --git a/doc/lispref/strings.texi b/doc/lispref/strings.texi
index 5cae939..b4d7bc7 100644
--- a/doc/lispref/strings.texi
+++ b/doc/lispref/strings.texi
@@ -390,6 +390,22 @@ whitespace to a single space character, as well as 
removing all
 whitespace from the start and the end of @var{string}.
 @end defun
 
+@defun string-trim-left string &optional regexp
+Remove the leading text that matches @var{regexp} from @var{string}.
+@var{regexp} defaults to @samp{[ \t\n\r]+}.
+@end defun
+
+@defun string-trim-right string &optional regexp
+Remove the trailing text that matches @var{regexp} from @var{string}.
+@var{regexp} defaults to @samp{[ \t\n\r]+}.
+@end defun
+
+@defun string-trim string &optional trim-left trim-right
+Remove the leading text that matches @var{trim-left} and trailing text
+that matches @var{trim-right} from from @var{string}.  Both regexps
+default to @samp{[ \t\n\r]+}.
+@end defun
+
 @defun string-fill string length
 Attempt to Word-wrap @var{string} so that no lines are longer than
 @var{length}.  Filling is done on whitespace boundaries only.  If
diff --git a/doc/lispref/text.texi b/doc/lispref/text.texi
index b367346..44c4b90 100644
--- a/doc/lispref/text.texi
+++ b/doc/lispref/text.texi
@@ -222,7 +222,9 @@ properties, just the characters themselves.  @xref{Text 
Properties}.
 
 @defun buffer-string
 This function returns the contents of the entire accessible portion of
-the current buffer, as a string.
+the current buffer, as a string.  If the text being copied has any
+text properties, these are copied into the string along with the
+characters they belong to.
 @end defun
 
   If you need to make sure the resulting string, when copied to a
@@ -5288,10 +5290,9 @@ object parsed.
 Signaled when encountering invalid JSON syntax.
 @end table
 
-  Only top-level values (arrays and objects) can be serialized to
-JSON@.  The subobjects within these top-level values can be of any
-type.  Likewise, the parsing functions will only return vectors,
-hashtables, alists, and plists.
+  Top-level values and the subobjects within these top-level values
+can be serialized to JSON@.  Likewise, the parsing functions will
+return any of the possible types described above.
 
 @defun json-serialize object &rest args
 This function returns a new Lisp string which contains the JSON
diff --git a/doc/lispref/tips.texi b/doc/lispref/tips.texi
index 4a7793a..36c68ee 100644
--- a/doc/lispref/tips.texi
+++ b/doc/lispref/tips.texi
@@ -75,8 +75,8 @@ example, it is our convention to have commands that list 
objects named
 as @samp{list-@var{something}}, e.g., a package called @samp{frob}
 could have a command @samp{list-frobs}, when its other global symbols
 begin with @samp{frob-}.  Also, constructs that define functions,
-variables, etc., work better if they start with @samp{defun} or
-@samp{defvar}, so put the name prefix later on in the name.
+variables, etc., work better if they start with @samp{define-}, so put
+the name prefix later on in the name.
 
 This recommendation applies even to names for traditional Lisp
 primitives that are not primitives in Emacs Lisp---such as
diff --git a/doc/lispref/variables.texi b/doc/lispref/variables.texi
index 6343817..0ddf3e4 100644
--- a/doc/lispref/variables.texi
+++ b/doc/lispref/variables.texi
@@ -1696,7 +1696,6 @@ buffer has a buffer-local binding.  For example, you 
could use
 you are in a C or Lisp mode buffer that has a buffer-local value for
 this variable.
 
-@c Emacs 19 feature
   The special forms @code{defvar} and @code{defconst} also set the
 default value (if they set the variable at all), rather than any
 buffer-local value.
@@ -1708,7 +1707,6 @@ this variable.  If @var{symbol} is not buffer-local, this 
is equivalent
 to @code{symbol-value} (@pxref{Accessing Variables}).
 @end defun
 
-@c Emacs 19 feature
 @defun default-boundp symbol
 The function @code{default-boundp} tells you whether @var{symbol}'s
 default value is nonvoid.  If @code{(default-boundp 'foo)} returns
diff --git a/doc/lispref/windows.texi b/doc/lispref/windows.texi
index f305d1a..c32d711 100644
--- a/doc/lispref/windows.texi
+++ b/doc/lispref/windows.texi
@@ -2557,7 +2557,7 @@ frame visible and, unless @var{alist} contains an
 This function tries to display @var{buffer} by finding a window
 that is displaying a buffer in a given mode.
 
-If @var{alist} contains a @code{mode} entry, its value specifes a
+If @var{alist} contains a @code{mode} entry, its value specifies a
 major mode (a symbol) or a list of major modes.  If @var{alist}
 contains no @code{mode} entry, the current major mode of @var{buffer}
 is used instead.  A window is a candidate if it displays a buffer
diff --git a/doc/misc/Makefile.in b/doc/misc/Makefile.in
index d627055..63d4bf0 100644
--- a/doc/misc/Makefile.in
+++ b/doc/misc/Makefile.in
@@ -23,6 +23,8 @@ SHELL = @SHELL@
 # of the source tree.  This is set by configure's '--srcdir' option.
 srcdir=@srcdir@
 
+top_builddir = @top_builddir@
+
 ## Where the output files go.
 ## Note that all the Info targets build the Info files in srcdir.
 ## There is no provision for Info files to exist in the build directory.
@@ -82,11 +84,27 @@ INFO_INSTALL = $(INFO_COMMON) $(DOCMISC_W32)
 ## because the info files are pre-built in release tarfiles.
 INFO_TARGETS = $(INFO_COMMON) efaq-w32
 
+## Some manuals have their source in .org format.
+## This is discouraged because the .texi files it generates
+## are not as well formatted as handwritten ones.
+ORG_SETUP = $(wildcard ${srcdir}/*-setup.org)
+ORG_SRC = $(filter-out ${ORG_SETUP},$(wildcard ${srcdir}/*.org))
+TEXI_FROM_ORG = ${ORG_SRC:.org=.texi}
+
 # There are some naming differences between the info targets and the other
 # targets, so let's resolve them here.
 TARGETS_1 = $(INFO_INSTALL:ccmode=cc-mode)
 TARGETS = $(TARGETS_1:info.info=info)
 
+texi_sources = $(addsuffix .texi,${TARGETS})
+texi_notgen = $(filter-out $(notdir ${TEXI_FROM_ORG}),${texi_sources})
+texi_and_org = $(notdir ${ORG_SRC}) ${texi_notgen}
+SOURCES = $(sort ${texi_and_org})
+.PHONY: echo-sources
+## Used by the top-level Makefile.
+echo-sources:
+       @echo ${SOURCES}
+
 DVI_TARGETS  = $(TARGETS:=.dvi)
 HTML_TARGETS = $(TARGETS:=.html)
 PDF_TARGETS  = $(TARGETS:=.pdf)
@@ -96,13 +114,7 @@ TEXI2DVI = texi2dvi
 TEXI2PDF = texi2pdf
 DVIPS = dvips
 
-# 'make' verbosity.
-AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
-
-AM_V_GEN = $(am__v_GEN_@AM_V@)
-am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
-am__v_GEN_0 = @echo "  GEN     " $@;
-am__v_GEN_1 =
+-include ${top_builddir}/src/verbose.mk
 
 ENVADD = $(AM_V_GEN)TEXINPUTS="$(srcdir):$(emacsdir):$(TEXINPUTS)" \
          MAKEINFO="$(MAKEINFO) $(MAKEINFO_OPTS)"
@@ -221,6 +233,30 @@ gnus.pdf: $(gnus_deps)
 ${buildinfodir}/tramp.info tramp.html: ${srcdir}/trampver.texi
 
 
+abs_top_builddir = @abs_top_builddir@
+EMACS = ${abs_top_builddir}/src/emacs
+emacs = "${EMACS}" -batch --no-site-file --no-site-lisp
+
+# Generated .texi files go in srcdir so they can be included in the
+# release tarfile along with the others.
+# Work in srcdir (and use abs_top_builddir) so that +setupfile and
+# things like org-setup's "version" macro work.  Sigh.
+define org_template
+ $(1:.org=.texi): $(1)
+       $${AM_V_GEN}cd "$${srcdir}" && $${emacs} -l ox-texinfo \
+         -f org-texinfo-export-to-texinfo-batch $$(notdir $$<) $$(notdir $$@)
+endef
+
+$(foreach orgfile,${ORG_SRC},$(eval $(call org_template,$(orgfile))))
+
+## foo.org depends on foo-setup.org, if the latter exists.
+define org_setup_template
+  $(1:-setup.org=.texi): $(1)
+endef
+
+$(foreach orgfile,${ORG_SETUP},$(eval $(call org_setup_template,$(orgfile))))
+
+
 .PHONY: mostlyclean clean distclean bootstrap-clean maintainer-clean
 
 mostlyclean:
@@ -245,7 +281,13 @@ infoclean:
            $(buildinfodir)/$${file}-[1-9][0-9]; \
        done
 
-bootstrap-clean maintainer-clean: distclean infoclean
+.PHONY: orgclean
+
+orgclean:
+       rm -f ${TEXI_FROM_ORG}
+
+bootstrap-clean maintainer-clean: distclean infoclean orgclean
+       rm -f TAGS
 
 .PHONY: install-dvi install-html install-pdf install-ps install-doc
 
@@ -295,4 +337,20 @@ uninstall-pdf:
 uninstall-doc: uninstall-dvi uninstall-html uninstall-pdf uninstall-ps
 
 
+ETAGS = ../../lib-src/etags${EXEEXT}
+
+${ETAGS}: FORCE
+       $(MAKE) -C $(dir $@) $(notdir $@)
+
+texifiles = $(wildcard ${srcdir}/*.texi)
+
+TAGS: ${ETAGS} $(texifiles)
+       $(AM_V_GEN)${ETAGS} $(texifiles)
+
+tags: TAGS
+.PHONY: tags
+
+FORCE:
+.PHONY: FORCE
+
 ### Makefile ends here
diff --git a/doc/misc/calc.texi b/doc/misc/calc.texi
index c4ccea3..b409c1f 100644
--- a/doc/misc/calc.texi
+++ b/doc/misc/calc.texi
@@ -6612,7 +6612,8 @@ further discussion of infinite and indeterminate values.
 @subsection Modes Tutorial Exercise 1
 
 @noindent
-Calc always stores its numbers in decimal, so even though one-third has
+Calc always stores its floating-point numbers in decimal,
+so even though one-third has
 an exact base-3 representation (@samp{3#0.1}), it is still stored as
 0.3333333 (chopped off after 12 or however many decimal digits) inside
 the calculator's memory.  When this inexact number is converted back
@@ -18888,9 +18889,7 @@ Each possible value @expr{N} appears with equal 
probability.
 
 With no numeric prefix argument, the @kbd{k r} command takes its argument
 from the stack instead.  Once again, if this is a positive integer @expr{M}
-the result is a random integer less than @expr{M}.  However, note that
-while numeric prefix arguments are limited to six digits or so, an @expr{M}
-taken from the stack can be arbitrarily large.  If @expr{M} is negative,
+the result is a random integer less than @expr{M}.  If @expr{M} is negative,
 the result is a random integer in the range
 @texline @math{M < N \le 0}.
 @infoline @expr{M < N <= 0}.
@@ -32240,7 +32239,7 @@ as the value of a function.  You can use @code{return} 
anywhere
 inside the body of the function.
 @end itemize
 
-Non-integer numbers (and extremely large integers) cannot be included
+Non-integer numbers cannot be included
 directly into a @code{defmath} definition.  This is because the Lisp
 reader will fail to parse them long before @code{defmath} ever gets control.
 Instead, use the notation, @samp{:"3.1415"}.  In fact, any algebraic
@@ -32374,7 +32373,7 @@ This expands to the pair of definitions,
 
 @noindent
 where in this case the latter function would never really be used!  Note
-that since the Calculator stores small integers as plain Lisp integers,
+that since the Calculator stores integers as plain Lisp integers,
 the @code{math-add} function will work just as well as the native
 @code{+} even when the intent is to operate on native Lisp integers.
 
@@ -32643,8 +32642,8 @@ Like @samp{integer}, but the argument must be 
non-negative.
 
 @item fixnum
 @findex fixnum
-Like @samp{integer}, but the argument must fit into a native Lisp integer,
-which on most systems means less than 2^23 in absolute value.  The
+Like @samp{integer}, but the argument must fit into a native Lisp fixnum,
+which on most systems means less than 2^61 in absolute value.  The
 argument is converted into Lisp-integer form if necessary.
 
 @item float
@@ -32740,50 +32739,6 @@ Emacs Lisp function:
     count))
 @end smallexample
 
-If the input numbers are large, this function involves a fair amount
-of arithmetic.  A binary right shift is essentially a division by two;
-recall that Calc stores integers in decimal form so bit shifts must
-involve actual division.
-
-To gain a bit more efficiency, we could divide the integer into
-@var{n}-bit chunks, each of which can be handled quickly because
-they fit into Lisp integers.  It turns out that Calc's arithmetic
-routines are especially fast when dividing by an integer less than
-1000, so we can set @var{n = 9} bits and use repeated division by 512:
-
-@smallexample
-(defmath bcount ((natnum n))
-  (interactive 1 "bcnt")
-  (let ((count 0))
-    (while (not (fixnump n))
-      (let ((qr (idivmod n 512)))
-        (setq count (+ count (bcount-fixnum (cdr qr)))
-              n (car qr))))
-    (+ count (bcount-fixnum n))))
-
-(defun bcount-fixnum (n)
-  (let ((count 0))
-    (while (> n 0)
-      (setq count (+ count (logand n 1))
-            n (ash n -1)))
-    count))
-@end smallexample
-
-@noindent
-Note that the second function uses @code{defun}, not @code{defmath}.
-Because this function deals only with native Lisp integers (``fixnums''),
-it can use the actual Emacs @code{+} and related functions rather
-than the slower but more general Calc equivalents which @code{defmath}
-uses.
-
-The @code{idivmod} function does an integer division, returning both
-the quotient and the remainder at once.  Again, note that while it
-might seem that @samp{(logand n 511)} and @samp{(ash n -9)} are
-more efficient ways to split off the bottom nine bits of @code{n},
-actually they are less efficient because each operation is really
-a division by 512 in disguise; @code{idivmod} allows us to do the
-same thing with a single division by 512.
-
 @node Sine Example,  , Bit Counting Example, Example Definitions
 @subsubsection The Sine Function
 
@@ -33042,9 +32997,7 @@ in this case it would be easier to call the low-level 
@code{math-add}
 function in Calc, if you can remember its name.
 
 In particular, note that a plain Lisp integer is acceptable to Calc
-as a raw object.  (All Lisp integers are accepted on input, but
-integers of more than six decimal digits are converted to ``big-integer''
-form for output.  @xref{Data Type Formats}.)
+as a raw object.
 
 When it comes time to display the object, just use @samp{(calc-eval a)}
 to format it as a string.
@@ -33308,31 +33261,11 @@ you can't prove this file will already be loaded.
 @subsubsection Data Type Formats
 
 @noindent
-Integers are stored in either of two ways, depending on their magnitude.
-Integers less than one million in absolute value are stored as standard
-Lisp integers.  This is the only storage format for Calc data objects
-which is not a Lisp list.
-
-Large integers are stored as lists of the form @samp{(bigpos @var{d0}
-@var{d1} @var{d2} @dots{})} for sufficiently large positive integers
-(where ``sufficiently large'' depends on the machine), or
-@samp{(bigneg @var{d0} @var{d1} @var{d2} @dots{})} for negative
-integers.  Each @var{d} is a base-@expr{10^n} ``digit'' (where again,
-@expr{n} depends on the machine), a Lisp integer from 0 to
-99@dots{}9.  The least significant digit is @var{d0}; the last digit,
-@var{dn}, which is always nonzero, is the most significant digit.  For
-example, the integer @mathit{-12345678} might be stored as
-@samp{(bigneg 678 345 12)}.
-
-The distinction between small and large integers is entirely hidden from
-the user.  In @code{defmath} definitions, the Lisp predicate @code{integerp}
-returns true for either kind of integer, and in general both big and small
-integers are accepted anywhere the word ``integer'' is used in this manual.
-If the distinction must be made, native Lisp integers are called @dfn{fixnums}
-and large integers are called @dfn{bignums}.
+Integers are stored as standard Lisp integers.  This is the only
+storage format for Calc data objects which is not a Lisp list.
 
 Fractions are stored as a list of the form, @samp{(frac @var{n} @var{d})}
-where @var{n} is an integer (big or small) numerator, @var{d} is an
+where @var{n} is an integer numerator, @var{d} is an
 integer denominator greater than one, and @var{n} and @var{d} are relatively
 prime.  Note that fractions where @var{d} is one are automatically converted
 to plain integers by all math routines; fractions where @var{d} is negative
@@ -33341,7 +33274,7 @@ are normalized by negating the numerator and 
denominator.
 Floating-point numbers are stored in the form, @samp{(float @var{mant}
 @var{exp})}, where @var{mant} (the ``mantissa'') is an integer less than
 @samp{10^@var{p}} in absolute value (@var{p} represents the current
-precision), and @var{exp} (the ``exponent'') is a fixnum.  The value of
+precision), and @var{exp} (the ``exponent'') is an integer.  The value of
 the float is @samp{@var{mant} * 10^@var{exp}}.  For example, the number
 @mathit{-3.14} is stored as @samp{(float -314 -2) = -314*10^-2}.  Other 
constraints
 are that the number 0.0 is always stored as @samp{(float 0 0)}, and,
@@ -33736,7 +33669,7 @@ Returns true if @var{x} is an integer of any size.
 @end defun
 
 @defun fixnump x
-Returns true if @var{x} is a native Lisp integer.
+Returns true if @var{x} is a native Lisp fixnum.
 @end defun
 
 @defun natnump x
@@ -33744,7 +33677,7 @@ Returns true if @var{x} is a nonnegative integer of any 
size.
 @end defun
 
 @defun fixnatnump x
-Returns true if @var{x} is a nonnegative Lisp integer.
+Returns true if @var{x} is a nonnegative Lisp fixnum.
 @end defun
 
 @defun num-integerp x
@@ -33899,7 +33832,7 @@ converted to @samp{(math-equal x y)}.
 
 @defun equal-int x n
 Returns true if @var{x} and @var{n} are numerically equal, where @var{n}
-is a fixnum which is not a multiple of 10.  This will automatically be
+is an integer which is not a multiple of 10.  This will automatically be
 used by @code{defmath} in place of the more general @code{math-equal}
 whenever possible.
 @end defun
@@ -33980,12 +33913,8 @@ respectively, instead.
 
 @defun normalize val
 (Full form: @code{math-normalize}.)
-Reduce the value @var{val} to standard form.  For example, if @var{val}
-is a fixnum, it will be converted to a bignum if it is too large, and
-if @var{val} is a bignum it will be normalized by clipping off trailing
-(i.e., most-significant) zero digits and converting to a fixnum if it is
-small.  All the various data types are similarly converted to their standard
-forms.  Variables are left alone, but function calls are actually evaluated
+Reduce the value @var{val} to standard form.
+Variables are left alone, but function calls are actually evaluated
 in formulas.  For example, normalizing @samp{(+ 2 (calcFunc-abs -4))} will
 return 6.
 
@@ -34098,9 +34027,9 @@ integer rather than truncating.
 @end defun
 
 @defun fixnum n
-Return the integer @var{n} as a fixnum, i.e., a native Lisp integer.
-If @var{n} is outside the permissible range for Lisp integers (usually
-24 binary bits) the result is undefined.
+Return the integer @var{n} as a fixnum, i.e., a small Lisp integer.
+If @var{n} is outside the permissible range for Lisp fixnums (usually
+62 binary bits) the result is undefined.
 @end defun
 
 @defun sqr x
diff --git a/doc/misc/efaq-w32.texi b/doc/misc/efaq-w32.texi
index 2abde2c..6eff88b 100644
--- a/doc/misc/efaq-w32.texi
+++ b/doc/misc/efaq-w32.texi
@@ -370,11 +370,10 @@ On Windows, the @file{.emacs} file may be called 
@file{_emacs} for
 backward compatibility with DOS and FAT filesystems where filenames
 could not start with a dot.  Some users prefer to continue using such
 a name due to historical problems various Windows tools had in the
-past with file names that begin with a dot.  In Emacs 22 and later,
-the init file may also be called @file{.emacs.d/init.el}.  Many of the
-other files that are created by lisp packages are now stored in the
-@file{.emacs.d} directory too, so this keeps all your Emacs related
-files in one place.
+past with file names that begin with a dot.  The init file may also be
+called @file{.emacs.d/init.el}.  Many of the other files that are
+created by Lisp packages are stored in the @file{.emacs.d} directory
+too, which keeps all your Emacs related files in one place.
 
 All the files mentioned above should go in your @env{HOME} directory.
 The @env{HOME} directory is determined by following the steps below:
diff --git a/doc/misc/efaq.texi b/doc/misc/efaq.texi
index f26ae63..53a3af4 100644
--- a/doc/misc/efaq.texi
+++ b/doc/misc/efaq.texi
@@ -323,8 +323,8 @@ Free Software Foundation, and related organizations.
 
 @menu
 * Real meaning of copyleft::
-* Guidelines for newsgroup postings::
-* Newsgroup archives::
+* Guidelines for mailing list postings::
+* Mailing list archives::
 * Reporting bugs::
 * Unsubscribing from Emacs lists::
 * Contacting the FSF::
@@ -343,9 +343,10 @@ There has never been a copyright infringement case 
involving the GPL to
 set any precedents.  Although legal actions have been brought against
 companies for violating the terms of the GPL, so far all have been
 settled out of court (in favor of the plaintiffs).  Please take any
-discussion regarding this issue to the newsgroup
-@uref{news:gnu.misc.discuss}, which was created to hold the extensive
-flame wars on the subject.
+discussion regarding this issue to
+@uref{https://lists.gnu.org/mailman/listinfo/gnu-misc-discuss, the
+gnu-misc-discuss mailing list}, which was created to hold the
+extensive flame wars on the subject.
 
 RMS writes:
 
@@ -359,49 +360,60 @@ distribute any version of Emacs or a related program, and 
give the
 recipients the same freedom that you enjoyed.
 @end quotation
 
-@node Guidelines for newsgroup postings
-@section  What are appropriate messages for the various Emacs newsgroups?
+@node Guidelines for mailing list postings
+@section  What are appropriate messages for the various Emacs mailing lists?
 @cindex Newsgroups, appropriate messages for
 @cindex GNU newsgroups, appropriate messages for
+@cindex GNU mailing lists, appropriate messages for
 @cindex Usenet groups, appropriate messages for
 @cindex Mailing lists, appropriate messages for
-@cindex Posting messages to newsgroups
+@cindex Posting messages to mailing lists
 
 @cindex GNU mailing lists
 The Emacs mailing lists are described at
 @uref{https://savannah.gnu.org/mail/?group=emacs, the Emacs Savannah
-page}. Some of them are gatewayed to newsgroups.
-
-The newsgroup @uref{news:comp.emacs} is for discussion of Emacs programs
-in general.  The newsgroup @uref{news:gnu.emacs.help} is specifically
-for GNU Emacs.  It therefore makes no sense to cross-post to both
-groups, since only one can be appropriate to any question.
-
-Messages advocating ``non-free'' software are considered unacceptable on
-any of the @code{gnu.*} newsgroups except for @uref{news:gnu.misc.discuss},
-which was created to hold the extensive flame-wars on the subject.
-``Non-free'' software includes any software for which the end user can't
-freely modify the source code and exchange enhancements.  Be careful to
-remove the @code{gnu.*} groups from the @samp{Newsgroups:} line when
-posting a followup that recommends such software.
-
-@uref{news:gnu.emacs.bug} is a place where bug reports appear, but avoid
-posting bug reports to this newsgroup directly (@pxref{Reporting bugs}).
-
-@node Newsgroup archives
-@section Where can I get old postings to @uref{news:gnu.emacs.help} and other 
GNU groups?
-@cindex Archived postings from @code{gnu.emacs.help}
-@cindex Usenet archives for GNU groups
-@cindex Old Usenet postings for GNU groups
+page}.
+
+Messages advocating ``non-free'' software are considered unacceptable
+on any of the GNU mailing lists, except for
+@url{https://lists.gnu.org/mailman/listinfo/gnu-misc-discuss, the
+gnu-misc-discuss mailing list} which was created to hold the extensive
+flame-wars on the subject.
+
+``Non-free'' software includes any software for which the end user
+can't freely modify the source code and exchange enhancements.  Be
+careful to remove any GNU mailing lists from @samp{Cc:} when posting a
+reply that recommends such software.
+
+@url{https://lists.gnu.org/mailman/listinfo/bug-gnu-emacs, The
+bug-gnu-emacs list} is a place where bug reports appear, but we
+recommend using the commands @kbd{M-x report-emacs-bug} or @kbd{M-x
+submit-emacs-patch} if at all possible (@pxref{Reporting bugs}).
+
+Some GNU mailing lists are gatewayed to (Usenet) newsgroups.
+For example, sending an email to
+@url{https://lists.gnu.org/mailman/listinfo/bug-gnu-emacs, The
+bug-gnu-emacs list} has the effect of posting on the newsgroup
+@uref{news:gnu.emacs.help}).
+
+Finally, we recommend reading the
+@url{https://www.gnu.org/philosophy/kind-communication.html, GNU Kind
+Communications Guidelines} before posting to any GNU lists or
+newsgroups.
+
+@node Mailing list archives
+@section Where can I read archives for @code{help-gnu-emacs} and other GNU 
lists?
+@cindex Archived postings from @code{help-gnu-emacs}
+@cindex Old mailing list posts for GNU lists
+@cindex Mailing list archives for GNU lists
 
 The FSF has maintained archives of all of the GNU mailing lists for many
 years, although there may be some unintentional gaps in coverage.  The
 archive can be browsed over the web at
 @uref{https://lists.gnu.org/r/, the GNU mail archive}.
 
-Web-based Usenet search services, such as
-@uref{https://groups.google.com/groups/dir?q=gnu&;, Google}, also
-archive the @code{gnu.*} groups.
+Some web-based Usenet search services also archive the @code{gnu.*}
+newsgroups.
 
 @node Reporting bugs
 @section Where should I report bugs and other problems with Emacs?
@@ -414,39 +426,25 @@ The correct way to report Emacs bugs is to use the command
 @kbd{M-x report-emacs-bug}.  It sets up a mail buffer with the
 essential information and the correct e-mail address,
 @email{bug-gnu-emacs@@gnu.org}.
-Anything sent there also appears in the
-newsgroup @uref{news:gnu.emacs.bug}, but please use e-mail instead of
-news to submit the bug report.  This ensures a reliable return address
-so you can be contacted for further details.
 
 Be sure to read the ``Bugs'' section of the Emacs manual before reporting
 a bug!  The manual describes in detail how to submit a useful bug
 report (@pxref{Bugs, , Reporting Bugs, emacs, The GNU Emacs Manual}).
 (@xref{Emacs manual}, if you don't know how to read the manual.)
 
-RMS says:
-
-@quotation
 Sending bug reports to
-@url{https://lists.gnu.org/mailman/listinfo/help-gnu-emacs,
-the help-gnu-emacs mailing list}
-(which has the effect of posting on @uref{news:gnu.emacs.help}) is
-undesirable because it takes the time of an unnecessarily large group
-of people, most of whom are just users and have no idea how to fix
-these problem.
-@url{https://lists.gnu.org/mailman/listinfo/bug-gnu-emacs, The
-bug-gnu-emacs list} reaches a much smaller group of people who are
+@url{https://lists.gnu.org/mailman/listinfo/help-gnu-emacs, the
+help-gnu-emacs mailing list} is undesirable because it takes the time
+of an unnecessarily large group of people, most of whom are just users
+and have no idea how to fix these
+problem.  @url{https://lists.gnu.org/mailman/listinfo/bug-gnu-emacs,
+The bug-gnu-emacs list} reaches a much smaller group of people who are
 more likely to know what to do and have expressed a wish to receive
 more messages about Emacs than the others.
-@end quotation
-
-RMS says it is sometimes fine to post to @uref{news:gnu.emacs.help}:
 
-@quotation
 If you have reported a bug and you don't hear about a possible fix,
 then after a suitable delay (such as a week) it is okay to post on
-@code{gnu.emacs.help} asking if anyone can help you.
-@end quotation
+@code{help-gnu-emacs@@gnu.org} asking if anyone can help you.
 
 If you are unsure whether you have found a bug, consider the following
 non-exhaustive list, courtesy of RMS:
@@ -458,6 +456,11 @@ is a bug.  If Lisp code does not do what the documentation 
says it
 does, that is a bug.
 @end quotation
 
+Anything sent to @email{bug-gnu-emacs@@gnu.org} also appears in the
+newsgroup @uref{news:gnu.emacs.bug}, but please use e-mail instead of
+news to submit the bug report.  This ensures a reliable return address
+so you can be contacted for further details.
+
 @node Unsubscribing from Emacs lists
 @section  How do I unsubscribe from a mailing list?
 @cindex Unsubscribing from GNU mailing lists
@@ -3526,10 +3529,8 @@ installing any nonfree software, we recommend for your 
freedom's sake
 that you stay away from it.
 
 The @uref{https://lists.gnu.org/mailman/listinfo/gnu-emacs-sources,
-GNU Emacs sources mailing list}, which is gatewayed to the
-@uref{news:gnu.emacs.sources, Emacs sources newsgroup} (although the
-connection between the two can be unreliable) is an official place
-where people can post or announce their extensions to Emacs.
+GNU Emacs sources mailing list} is an official place where people can
+post or announce their extensions to Emacs.
 
 The @uref{https://emacswiki.org, Emacs Wiki} contains pointers to some
 additional extensions.  @uref{https://wikemacs.org, WikEmacs} is an
diff --git a/doc/misc/forms.texi b/doc/misc/forms.texi
index 3d7ac96..15fcd97 100644
--- a/doc/misc/forms.texi
+++ b/doc/misc/forms.texi
@@ -6,6 +6,7 @@
 @setfilename ../../info/forms.info
 @settitle Forms Mode User's Manual
 @include docstyle.texi
+@include emacsver.texi
 @syncodeindex vr cp
 @syncodeindex fn cp
 @syncodeindex ky cp
@@ -47,7 +48,7 @@ modify this GNU manual.''
 @sp 4
 @center Forms-Mode version 2
 @sp 1
-@center for GNU Emacs 22.1
+@center for GNU Emacs @value{EMACSVER}
 @sp 1
 @center April 2007
 @sp 5
diff --git a/doc/misc/gnus-faq.texi b/doc/misc/gnus-faq.texi
index 4c29976..d3db940 100644
--- a/doc/misc/gnus-faq.texi
+++ b/doc/misc/gnus-faq.texi
@@ -160,13 +160,7 @@ Where and how to get Gnus?
 
 @subsubheading Answer
 
-Gnus is released independent from releases of Emacs.  Therefore, the
-version bundled with Emacs might not be up to date (e.g., Gnus 5.9
-bundled with Emacs 21 is outdated).
-You can get the latest released version of Gnus from
-@uref{https://www.gnus.org/dist/gnus.tar.gz}
-or from
-@uref{https://ftp.gnus.org/pub/gnus/gnus.tar.gz}.
+Gnus is bundled with Emacs.
 
 @node FAQ 1-4
 @subsubheading Question 1.4
@@ -1941,13 +1935,13 @@ when you're online.
 
 Let's talk about Unix systems first: For the news part,
 the easiest solution is a small nntp server like
-@uref{http://www.leafnode.org/, Leafnode} or
+@uref{https://www.leafnode.org/, Leafnode} or
 @uref{http://patrik.iki.fi/sn/, sn},
 of course you can also install a full featured news
 server like
 @uref{https://www.isc.org/othersoftware/, inn}.
 Then you want to fetch your Mail, popular choices
-are @uref{http://www.fetchmail.info/, fetchmail}
+are @uref{https://www.fetchmail.info/, fetchmail}
 and @uref{http://pyropus.ca/software/getmail/, getmail}.
 You should tell those to write the mail to your disk and
 Gnus to read it from there. Last but not least the mail
diff --git a/doc/misc/gnus.texi b/doc/misc/gnus.texi
index 5a79cbc..b6553c8 100644
--- a/doc/misc/gnus.texi
+++ b/doc/misc/gnus.texi
@@ -815,7 +815,7 @@ Various
 * Undo::                        Some actions can be undone.
 * Predicate Specifiers::        Specifying predicates.
 * Moderation::                  What to do if you're a moderator.
-* Image Enhancements::          Modern versions of Emacs can display images.
+* Image Enhancements::          Emacs can display images.
 * Fuzzy Matching::              What's the big fuzz?
 * Thwarting Email Spam::        Simple ways to avoid unsolicited commercial 
email.
 * Spam Package::                A package for filtering and processing spam.
@@ -16269,7 +16269,6 @@ Translate all @samp{@key{TAB}} characters into 
@samp{@key{SPC}} characters.
 
 @item nnmail-ignore-broken-references
 @findex nnmail-ignore-broken-references
-@c @findex nnmail-fix-eudora-headers
 @cindex Eudora
 @cindex Pegasus
 Some mail user agents (e.g., Eudora and Pegasus) produce broken
@@ -16359,9 +16358,8 @@ If you start using any of the mail back ends, they have 
the annoying
 habit of assuming that you want to read mail with them.  This might not
 be unreasonable, but it might not be what you want.
 
-If you set @code{mail-sources} and @code{nnmail-spool-file} to
-@code{nil}, none of the back ends will ever attempt to read incoming
-mail, which should help.
+If you set @code{mail-sources} to @code{nil}, none of the back ends
+will ever attempt to read incoming mail, which should help.
 
 @vindex nnbabyl-get-new-mail
 @vindex nnmbox-get-new-mail
@@ -19357,6 +19355,9 @@ and dormant.  If @code{nil} (which is the default), 
only read articles
 are eligible for expiry, and unread, ticked and dormant articles will
 be kept indefinitely.
 
+The last (i.e., newest) article in a group will normally not be
+expired (due to internal book-keeping reasons).
+
 If you find that some articles eligible for expiry are never expired,
 perhaps some Gnus Agent files are corrupted.  There's are special
 commands, @code{gnus-agent-regenerate} and
@@ -22504,7 +22505,7 @@ to you, using @kbd{G b u} and updating the group will 
usually fix this.
 * Predicate Specifiers::        Specifying predicates.
 * Moderation::                  What to do if you're a moderator.
 * Fetching a Group::            Starting Gnus just to read a group.
-* Image Enhancements::          Modern versions of Emacs can display images.
+* Image Enhancements::          Emacs can display images.
 * Fuzzy Matching::              What's the big fuzz?
 * Thwarting Email Spam::        Simple ways to avoid unsolicited commercial 
email.
 * Spam Package::                A package for filtering and processing spam.
@@ -23667,9 +23668,8 @@ It takes the group name as a parameter.
 @node Image Enhancements
 @section Image Enhancements
 
-Emacs 21@footnote{Emacs 21 on MS Windows doesn't
-support images, Emacs 22 does.} and up are able to display pictures and
-stuff, so Gnus has taken advantage of that.
+Emacs is able to display pictures and stuff, so Gnus has taken
+advantage of that.
 
 @menu
 * X-Face::                      Display a funky, teensy black-and-white image.
diff --git a/doc/misc/message.texi b/doc/misc/message.texi
index be6c9a4..1497c71 100644
--- a/doc/misc/message.texi
+++ b/doc/misc/message.texi
@@ -540,6 +540,7 @@ better than you do.
 @node System Mailer Setup
 @section System Mailer Setup
 @cindex mailto:
+@cindex System Mailer
 
 Emacs can be set up as the system mailer, so that Emacs is opened when
 you click on @samp{mailto:} links in other programs.
@@ -548,10 +549,11 @@ How this is done varies from system to system, but 
commonly there's a
 way to set the default application for a @acronym{MIME} type, and the
 relevant type here is @samp{x-scheme-handler/mailto;}.
 
-The application to start should be @samp{"emacs -f message-mailto %u"}.
+The application to start should be @w{@samp{emacs -f message-mailto %u}}.
 This will start Emacs, and then run the @code{message-mailto}
 command.  It will parse the given @acronym{URL}, and set up a Message
-buffer with the given parameters.
+buffer with the given parameters.  If you prefer to use emacsclient,
+use @w{@samp{emacsclient -e '(message-mailto "%u")'}} as the application.
 
 For instance, @samp{mailto:larsi@@gnus.org?subject=This+is+a+test}
 will open a Message buffer with the @samp{To:} header filled in with
diff --git a/doc/misc/modus-themes.org b/doc/misc/modus-themes.org
new file mode 100644
index 0000000..9764a34
--- /dev/null
+++ b/doc/misc/modus-themes.org
@@ -0,0 +1,3300 @@
+#+title: Modus themes for GNU Emacs
+#+author: Protesilaos Stavrou
+#+email: info@protesilaos.com
+#+language: en
+#+options: ':t toc:nil author:t email:t
+
+#+macro: stable-version 1.2.3
+#+macro: release-date 2021-03-05
+#+macro: development-version 1.3.0-dev
+#+macro: export-date (eval (format-time-string "%F %R %z" (current-time)))
+#+macro: file @@texinfo:@file{@@$1@@texinfo:}@@
+#+macro: space @@texinfo:@: @@
+#+macro: kbd @@texinfo:@kbd{@@$1@@texinfo:}@@
+
+#+texinfo_filename: modus-themes.info
+#+texinfo_dir_category: Emacs misc features
+#+texinfo_dir_title: Modus Themes: (modus-themes)
+#+texinfo_dir_desc: Highly accessible themes (WCAG AAA)
+#+texinfo_header: @set MAINTAINERSITE @uref{https://protesilaos.com,maintainer 
webpage}
+#+texinfo_header: @set MAINTAINER Protesilaos Stavrou
+#+texinfo_header: @set MAINTAINEREMAIL @email{info@protesilaos.com}
+#+texinfo_header: @set MAINTAINERCONTACT 
@uref{mailto:info@protesilaos.com,contact the maintainer}
+
+#+texinfo: @insertcopying
+
+This manual, written by Protesilaos Stavrou, describes the customization
+options for the ~modus-operandi~ and ~modus-vivendi~ themes, and provides
+every other piece of information pertinent to them.
+
+The documentation furnished herein corresponds to stable version
+{{{stable-version}}}, released on {{{release-date}}}.  Any reference to a newer
+feature which does not yet form part of the latest tagged commit, is
+explicitly marked as such.
+
+Current development target is {{{development-version}}}.  This manual was
+built on {{{export-date}}}.
+
+#+toc: headlines 8 insert TOC here, with eight headline levels
+
+* COPYING
+:properties:
+:copying: t
+:custom_id: h:b14c3fcb-13dd-4144-9d92-2c58b3ed16d3
+:end:
+
+Copyright (C) 2020-2021  Free Software Foundation, Inc.
+
+#+begin_quote
+Permission is granted to copy, distribute and/or modify this
+document under the terms of the GNU Free Documentation License,
+Version 1.3 or any later version published by the Free Software
+Foundation; with no Invariant Sections, with no Front-Cover Texts,
+and with no Back-Cover Texts.
+#+end_quote
+
+* Overview
+:properties:
+:custom_id: h:f0f3dbcb-602d-40cf-b918-8f929c441baf
+:end:
+
+The Modus themes are designed for accessible readability.  They conform
+with the highest standard for color contrast between any given
+combination of background and foreground values.  This corresponds to
+the WCAG AAA standard, which specifies a minimum rate of distance in
+relative luminance of 7:1.
+
+Modus Operandi (~modus-operandi~) is a light theme, while Modus Vivendi
+(~modus-vivendi~) is dark.  Each theme's color palette is designed to meet
+the needs of the numerous interfaces that are possible in the Emacs
+computing environment.
+
+The overarching objective of this project is to always offer accessible
+color combinations.  There shall never be a compromise on this
+principle.  If there arises an inescapable trade-off between readability
+and stylistic considerations, we will always opt for the former.
+
+To ensure that users have a consistently accessible experience, the
+themes strive to achieve as close to full face coverage as possible
+([[#h:a9c8f29d-7f72-4b54-b74b-ddefe15d6a19][Face coverage]]).
+
+Starting with version 0.12.0 and onwards, the themes are built into GNU
+Emacs.
+
+** How do the themes look like
+:properties:
+:custom_id: h:69b92089-069c-4ba1-9d94-cc3415fc4f87
+:end:
+#+cindex: Screenshots
+
+Check the web page with [[https://protesilaos.com/modus-themes-pictures/][the 
screen shots]].  There are lots of scenarios
+on display that draw attention to details and important aspects in the
+design of the themes.  They also showcase the numerous customization
+options.
+
+[[#h:bf1c82f2-46c7-4eb2-ad00-dd11fdd8b53f][Customization options]].
+
+** Learn about the latest changes
+:properties:
+:custom_id: h:2cc37c36-6c1a-48b2-a010-1050b270ee18
+:end:
+#+cindex: Changelog
+
+Please refer to the [[https://protesilaos.com/modus-themes-changelog][web page 
with the change log]].  It is comprehensive
+and covers everything that goes into every tagged release of the themes.
+
+* Installation
+:properties:
+:custom_id: h:1af85373-7f81-4c35-af25-afcef490c111
+:end:
+
+The Modus themes are distributed with Emacs starting with version 28.1.
+On older versions of Emacs, they can be installed using Emacs' package
+manager or manually from their code repository.  There also exist
+packages for distributions of GNU/Linux.
+
+** Install manually from source
+:properties:
+:custom_id: h:da3414b7-1426-46b8-8e76-47b845b76fd0
+:end:
+
+In the following example, we are assuming that your Emacs files are
+stored in =~/.emacs.d= and that you want to place the Modus themes in
+=~/.emacs.d/modus-themes=.
+
+1. Get the source and store it in the desired path by running the
+   following in the command line shell:
+
+: $ git clone https://gitlab.com/protesilaos/modus-themes.git 
~/.emacs.d/modus-themes
+
+2. Add that path to your known Elisp libraries' list, by placing this
+   snippet of Emacs Lisp in your init file (e.g. {{{file(init.el)}}}):
+
+#+begin_src emacs-lisp
+(add-to-list 'load-path "~/.emacs.d/modus-themes")
+#+end_src
+
+The themes are now ready to be used: 
[[#h:3f3c3728-1b34-437d-9d0c-b110f5b161a9][Enable and load]].
+
+** Install from the archives
+:properties:
+:custom_id: h:c4b10085-149f-43e2-bd4d-347f33aee054
+:end:
+
+The =modus-themes= package is available from the GNU ELPA archive, which
+is configured by default.
+
+Prior to querying any package archive, make sure to have updated the
+index, with {{{kbd(M-x package-refresh-contents)}}}.  Then all you need to do
+is type {{{kbd(M-x package-install)}}} and specify the ~modus-themes~.
+
+Note that older versions of the themes used to be distributed as
+standalone packages.  This practice has been discontinued starting with
+version 1.0.0 of this project.
+
+Once installed, the themes are ready to be used: 
[[#h:3f3c3728-1b34-437d-9d0c-b110f5b161a9][Enable and load]].
+
+** Install on GNU/Linux
+:properties:
+:custom_id: h:da640eb1-95dd-4e86-bb4e-1027b27885f0
+:end:
+
+The themes are also available from the archives of some distributions of
+GNU/Linux.  These should correspond to a tagged release rather than
+building directly from the latest Git commit.  It all depends on the
+distro's packaging policies.
+
+*** Debian 11 Bullseye
+:properties:
+:custom_id: h:7e570360-9ee6-4bc5-8c04-9dc11418a3e4
+:end:
+
+The themes are part of Debian 11 Bullseye.  Get them with:
+
+#+begin_src sh
+sudo apt install elpa-modus-themes
+#+end_src
+
+They are now ready to be used: 
[[#h:3f3c3728-1b34-437d-9d0c-b110f5b161a9][Enable and load]].
+
+*** GNU Guix
+:properties:
+:custom_id: h:a4ca52cd-869f-46a5-9e16-4d9665f5b88e
+:end:
+
+Users of Guix can get the themes with this command:
+
+#+begin_src sh
+guix package -i emacs-modus-themes
+#+end_src
+
+They are now ready to be used: 
[[#h:3f3c3728-1b34-437d-9d0c-b110f5b161a9][Enable and load]].
+
+* Enable and load
+:properties:
+:custom_id: h:3f3c3728-1b34-437d-9d0c-b110f5b161a9
+:end:
+#+findex: modus-themes-load-themes
+#+findex: modus-themes-toggle
+#+findex: modus-themes-load-operandi
+#+findex: modus-themes-load-vivendi
+#+cindex: Essential configuration
+#+vindex: modus-themes-after-load-theme-hook
+
+Users of the built-in themes can load and automatically enable the theme
+of their preference by adding either form to their init file:
+
+#+begin_src emacs-lisp
+(load-theme 'modus-operandi)            ; Light theme
+(load-theme 'modus-vivendi)             ; Dark theme
+#+end_src
+
+This is all one needs.
+
+Users of packaged variants of the themes must add a few more lines to
+ensure that everything works as intended.  First, one has to require the
+main library before loading either theme:
+
+#+begin_src emacs-lisp
+(require 'modus-themes)
+#+end_src
+
+Then it is recommended to load the individual theme files with the
+helper function ~modus-themes-load-themes~:
+
+#+begin_src emacs-lisp
+;; Load the theme files before enabling a theme (else you get an error).
+(modus-themes-load-themes)
+#+end_src
+
+Once the libraries that define the themes are enabled, one can activate
+a theme with either of the following expressions:
+
+#+begin_src emacs-lisp
+(modus-themes-load-operandi)            ; Light theme
+;; OR
+(modus-themes-load-vivendi)             ; Dark theme
+#+end_src
+
+Changes to the available customization options must always be evaluated
+before loading a theme 
([[#h:bf1c82f2-46c7-4eb2-ad00-dd11fdd8b53f][Customization Options]]).  This is 
how a basic
+setup could look like:
+
+#+begin_src emacs-lisp
+(require 'modus-themes)
+
+;; Your customisations here.  For example:
+(setq modus-themes-bold-constructs t
+      modus-themes-mode-line '3d)
+
+;; Load the theme files before enabling a theme (else you get an error).
+(modus-themes-load-themes)
+
+;; Enable the theme of your preference:
+(modus-themes-load-operandi)
+
+;; Optionally add a key binding for the toggle between the themes:
+(define-key global-map (kbd "<f5>") #'modus-themes-toggle)
+#+end_src
+
+[[#h:e979734c-a9e1-4373-9365-0f2cd36107b8][Sample configuration for 
use-package]].
+
+With those granted, bear in mind a couple of technical points on
+~modus-themes-load-operandi~ and ~modus-themes-load-vivendi~, as well as
+~modus-themes-toggle~ which relies on them:
+
+1. Those functions call ~load-theme~.  Some users prefer to opt for
+   ~enable-theme~ instead 
([[#h:e68560b3-7fb0-42bc-a151-e015948f8a35][Differences between loading and 
enabling]]).
+
+2. The functions will run the ~modus-themes-after-load-theme-hook~ as
+   their final step.  This can be employed for bespoke configurations
+   ([[#h:f4651d55-8c07-46aa-b52b-bed1e53463bb][Advanced customization 
(do-it-yourself)]]).  Experienced users may not
+   wish to rely on such a hook and the functions that run it: they may
+   prefer a custom solution ([[#h:86f6906b-f090-46cc-9816-1fe8aeb38776][A 
theme-agnostic hook for theme loading]]).
+
+** Sample configuration for use-package
+:properties:
+:custom_id: h:e979734c-a9e1-4373-9365-0f2cd36107b8
+:end:
+#+cindex: use-package configuration
+
+It is common for Emacs users to rely on ~use-package~ for declaring
+package configurations in their setup.  We use this as an example:
+
+#+begin_src emacs-lisp
+(use-package modus-themes
+  :ensure                         ; omit this to use the built-in themes
+  :init
+  ;; Add all your customizations prior to loading the themes
+  (setq modus-themes-slanted-constructs t
+        modus-themes-bold-constructs nil)
+
+  ;; Load the theme files before enabling a theme (else you get an error).
+  (modus-themes-load-themes)
+  :config
+  ;; Load the theme of your choice:
+  (modus-themes-load-operandi) ;; OR (modus-themes-load-vivendi)
+  :bind ("<f5>" . modus-themes-toggle))
+#+end_src
+
+[[#h:e68560b3-7fb0-42bc-a151-e015948f8a35][Differences between loading and 
enabling]].
+
+Note: make sure not to customize the variable ~custom-theme-load-path~
+or ~custom-theme-directory~ after the themes' package declaration.  That
+will lead to failures in loading the files.  If either or both of those
+variables need to be changed, their values should be defined before the
+package declaration of the themes.
+
+** Differences between loading and enabling
+:properties:
+:custom_id: h:e68560b3-7fb0-42bc-a151-e015948f8a35
+:end:
+#+cindex: load-theme VS enable-theme
+
+The reason we recommend ~load-theme~ instead of the other option of
+~enable-theme~ is that the former does a kind of "reset" on the face
+specs.  It quite literally loads (or re-loads) the theme.  Whereas the
+latter simply puts an already loaded theme at the top of the list of
+enabled items, re-using whatever state was last loaded.
+
+As such, ~load-theme~ reads all customizations that may happen during
+any given Emacs session: even after the initial setup of a theme.
+Examples are calls to ~custom-set-faces~, as well as new values assigned
+to the options the Modus themes provide 
([[#h:bf1c82f2-46c7-4eb2-ad00-dd11fdd8b53f][Customization Options]]).
+
+Our tests show that ~enable-theme~ does not read such variables anew, so
+it might appear to the unsuspecting user that the themes are somehow
+broken whenever they try to assign a new value to a customization option
+or some face.
+
+This "reset" that ~load-theme~ conducts does, however, come at the cost
+of being somewhat slower than ~enable-theme~.  Users who have a stable
+setup and who seldom update their variables during a given Emacs
+session, are better off using something like this:
+
+#+begin_src emacs-lisp
+(require 'modus-themes)
+(load-theme 'modus-operandi t t)
+(load-theme 'modus-vivendi t t)
+
+(enable-theme 'modus-operandi) ;; OR (enable-theme 'modus-vivendi)
+#+end_src
+
+[[#h:e979734c-a9e1-4373-9365-0f2cd36107b8][Sample configuration for 
use-package]].
+
+With the above granted, other sections of the manual discuss how to
+configure custom faces, where ~load-theme~ is expected, though
+~enable-theme~ could still apply in stable setups:
+
+[[#h:1487c631-f4fe-490d-8d58-d72ffa3bd474][Case-by-case face specs using the 
themes' palette]].
+
+[[#h:51ba3547-b8c8-40d6-ba5a-4586477fd4ae][Face specs at scale using the 
themes' palette]].
+
+* Customization Options
+:properties:
+:custom_id: h:bf1c82f2-46c7-4eb2-ad00-dd11fdd8b53f
+:end:
+
+The Modus themes are highly configurable, though they should work well
+without any further tweaks.  By default, all customization options are
+set to nil.
+
+Remember that all customization options must be evaluated before loading
+a theme ([[#h:3f3c3728-1b34-437d-9d0c-b110f5b161a9][Enable and load]]).
+
+** Option for more bold constructs
+:properties:
+:alt_title: Bold constructs
+:description: Toggle bold constructs in code
+:custom_id: h:b25714f6-0fbe-41f6-89b5-6912d304091e
+:end:
+#+vindex: modus-themes-bold-constructs
+
+Symbol: ~modus-themes-bold-constructs~
+
+Possible values:
+
+1. =nil= (default)
+2. =t=
+
+The default is to use a bold typographic weight only when it is
+required.
+
+With a non-nil value (=t=) display several syntactic constructs in bold
+weight.  This concerns keywords and other important aspects of code
+syntax.  It also affects certain mode line indicators and command-line
+prompts.
+
+** Option for more slanted constructs
+:properties:
+:alt_title: Slanted constructs
+:description: Toggle slanted constructs (italics) in code
+:custom_id: h:977c900d-0d6d-4dbb-82d9-c2aae69543d6
+:end:
+#+vindex: modus-themes-slanted-constructs
+
+Symbol: ~modus-themes-slanted-constructs~
+
+Possible values:
+
+1. =nil= (default)
+2. =t=
+
+The default is to not use slanted text (italics) unless it is absolutely
+necessary.
+
+With a non-nil value (=t=) choose to render more faces in slanted text.
+This typically affects documentation strings and code comments.
+
+** Option for syntax highlighting
+:properties:
+:alt_title: Syntax styles
+:description: Choose the overall aesthetic of code syntax
+:custom_id: h:c119d7b2-fcd4-4e44-890e-5e25733d5e52
+:end:
+#+vindex: modus-themes-syntax
+
+Symbol: ~modus-themes-syntax~
+
+Possible values:
+
+1. =nil= (default)
+2. ~faint~
+3. ~yellow-comments~
+4. ~green-strings~
+5. ~yellow-comments-green-strings~
+6. ~alt-syntax~
+7. ~alt-syntax-yellow-comments~
+8. ~faint-yellow-comments~
+
+The default style (nil) for code syntax highlighting is a balanced
+combination of colors on the cyan-blue-magenta side of the spectrum.
+There is little to no use of greens, yellows, or reds, except when it is
+necessary.
+
+Option ~faint~ is like the default in terms of the choice of palette but
+applies desaturated color values.
+
+Option ~yellow-comments~ adds a yellow tint to comments.  The rest of the
+syntax is the same as the default.
+
+Option ~green-strings~ replaces the blue/cyan/cold color variants in
+strings with greener alternatives.  The rest of the syntax remains the
+same.
+
+Option ~yellow-comments-green-strings~ combines yellow comments with green
+strings and the rest of the default syntax highlighting style.
+
+Option ~alt-syntax~ expands the active spectrum by applying color
+combinations with more contrasting hues between them.  Expect to find
+red and green variants in addition to cyan, blue, magenta.
+
+Option ~alt-syntax-yellow-comments~ combines ~alt-syntax~ with
+~yellow-comments~.
+
+Option ~faint-yellow-comments~ combines the ~faint~ style with
+~yellow-comments~.
+
+** Option for no font mixing
+:properties:
+:alt_title: No mixed fonts
+:description: Toggle mixing of font families
+:custom_id: h:115e6c23-ee35-4a16-8cef-e2fcbb08e28b
+:end:
+#+vindex: modus-themes-no-mixed-fonts
+
+Symbol: ~modus-themes-no-mixed-fonts~
+
+Possible values:
+
+1. =nil= (default)
+2. =t=
+
+By default, the themes configure some spacing-sensitive faces like Org
+tables and code blocks to always inherit from the ~fixed-pitch~ face.
+This is to ensure that those constructs remain monospaced even when
+users opt for a mode that remaps typeface families, such as the built-in
+{{{kbd(M-x variable-pitch-mode)}}}.  Otherwise the layout would appear
+broken, due to how spacing is done.  To disable this behaviour, set the
+option to =t=.
+
+Users may prefer to use another package for handling mixed typeface
+configurations, rather than letting the theme do it, perhaps because a
+purpose-specific package has extra functionality.  Two possible options
+are ~org-variable-pitch~ and ~mixed-pitch~.
+
+[[#h:defcf4fc-8fa8-4c29-b12e-7119582cc929][Font configurations for Org (and 
others)]].
+
+** Option for links
+:properties:
+:alt_title: Link styles
+:description: Choose among several styles, with or without underline
+:custom_id: h:c119d7b2-fcd4-4e44-890e-5e25733d5e52
+:end:
+#+vindex: modus-themes-links
+
+Symbol: ~modus-themes-links~
+
+Possible values:
+
+1. =nil= (default)
+2. ~faint~
+3. ~neutral-underline~
+4. ~faint-neutral-underline~
+5. ~no-underline~
+6. ~underline-only~
+7. ~neutral-underline-only~
+
+The default style (nil) for links is to apply an underline and a
+saturated color to the affected text.  The color of the two is the same,
+which makes the link fairly prominent.
+
+Option ~faint~ follows the same approach as the default, but uses less
+intense colors.
+
+Option ~neutral-underline~ changes the underline's color to a subtle gray,
+while retaining the default text color.
+
+Option ~faint-neutral-underline~ combines a desaturated text color with a
+subtle gray underline.
+
+Option ~no-underline~ removes link underlines altogether, while retaining
+their original fairly vivid color.
+
+Option ~underline-only~ applies a prominent underline while making the
+affected text colorless (it uses the same foreground as the theme's
+default).
+
+Option ~neutral-underline-only~ makes the text colorless while using a
+subtle gray underline below it.
+
+NOTE: The placement of the underline, i.e. its proximity to the affected
+text, is controlled by the built-in ~x-underline-at-descent-line~,
+~x-use-underline-position-properties~, ~underline-minimum-offset~.  Please
+refer to their documentation strings.
+
+** Option for command prompt styles
+:properties:
+:alt_title: Command prompts
+:description: Choose among plain, subtle, or intense prompts
+:custom_id: h:db5a9a7c-2928-4a28-b0f0-6f2b9bd52ba1
+:end:
+#+vindex: modus-themes-prompts
+
+Symbol: ~modus-themes-prompts~
+
+Possible values:
+
+1. =nil= (default)
+2. ~subtle-accented~ (~subtle~ exists for backward compatibility)
+3. ~intense-accented~ (~intense~ exists for backward compatibility)
+4. ~subtle-gray~
+5. ~intense-gray~
+
+The default does not use any background for minibuffer and command line
+prompts.  It relies exclusively on an accented foreground color.
+
+Options ~subtle-accented~ and ~intense-accented~ will change both the
+background and the foreground values to use accented color combinations
+that follow the hue of the default styles' foreground (e.g. the default
+minibuffer prompt is cyan text, so these combinations will involved a
+cyan background and an appropriate cyan foreground).  The difference
+between the two is that the latter has a more pronounced/noticeable
+effect than the former.
+
+Options ~subtle-gray~, ~intense-gray~ are like their accented counterparts,
+except they use grayscale values.
+
+** Option for mode line presentation
+:properties:
+:alt_title: Mode line
+:description: Choose among several styles, with or without borders
+:custom_id: h:27943af6-d950-42d0-bc23-106e43f50a24
+:end:
+#+vindex: modus-themes-mode-line
+
+Symbol: ~modus-themes-mode-line~
+
+Possible values:
+
+1. =nil= (default)
+2. ~3d~
+3. ~moody~
+4. ~borderless~
+5. ~borderless-3d~
+6. ~borderless-moody~
+
+The default produces a two-dimensional effect both for the active and
+inactive modelines.  The differences between the two are limited to
+distinct shades of grayscale values, with the active being more intense
+than the inactive.
+
+Option ~3d~ will make the active modeline look like a three-dimensional
+rectangle.  Inactive modelines remain 2D, though they are slightly toned
+down relative to the default.  This aesthetic is virtually the same as
+what you get when you run Emacs without any customizations (=emacs -Q= on
+the command line).
+
+While ~moody~ removes all box effects from the modelines and applies
+underline and overline properties instead.  It also tones down a bit the
+inactive modelines.  This is meant to optimize things for use with the
+[[https://github.com/tarsius/moody][moody package]] (hereinafter referred to 
as "Moody"), though it can work
+fine even without it.
+
+The ~borderless~ option uses the same colors as the default (nil value),
+but removes the border effect.  This is done by making the box property
+use the same color as the background, effectively blending the two and
+creating some padding.
+
+The ~borderless-3d~ and ~borderless-moody~ approximate the ~3d~ and ~moody~
+options respectively, while removing the borders.  However, to ensure
+that the inactive modelines remain visible, they apply a slightly more
+prominent background to them than what their counterparts do (same
+inactive background as with the default).
+
+Note that Moody does not expose any faces that the themes could style
+directly.  Instead it re-purposes existing ones to render its tabs and
+ribbons.  As such, there may be cases where the contrast ratio falls
+below the 7:1 target that the themes conform with (WCAG AAA).  To hedge
+against this, we configure a fallback foreground for the ~moody~ option,
+which will come into effect when the background of the modeline changes
+to something less accessible, such as Moody ribbons (read the doc string
+of ~set-face-attribute~, specifically ~:distant-foreground~).  This fallback
+is activated when Emacs determines that the background and foreground of
+the given construct are too close to each other in terms of color
+distance.  In effect, users would need to experiment with the variable
+~face-near-same-color-threshold~ to trigger the effect.  We find that a
+value of =45000= will suffice, contrary to the default =30000=.  Do not set
+the value too high, because that would have the adverse effect of always
+overriding the default color (which has been carefully designed to be
+highly accessible).
+
+Furthermore, because Moody expects an underline and overline instead of
+a box style, it is advised you include this in your setup:
+
+#+begin_src emacs-lisp
+(setq x-underline-at-descent-line t)
+#+end_src
+
+** Option for completion framework aesthetics
+:properties:
+:alt_title: Completion UIs
+:description: Choose among standard, moderate, or opinionated looks
+:custom_id: h:f1c20c02-7b34-4c35-9c65-99170efb2882
+:end:
+#+vindex: modus-themes-completions
+
+Symbol: ~modus-themes-completions~
+
+Possible values:
+
+1. =nil= (default)
+2. ~moderate~
+3. ~opinionated~
+
+This is a special option that has different effects depending on the
+completion UI.  The interfaces can be grouped in two categories, based
+on their default aesthetics: (i) those that only or mostly use
+foreground colors for their interaction model, and (ii) those that
+combine background and foreground values for some of their metaphors.
+The former category encompasses Icomplete, Ido, Selectrum as well as
+pattern matching styles like Orderless and Flx.  The latter covers Helm,
+Ivy, and similar.
+
+A value of =nil= will respect the metaphors of each completion framework.
+
+Option ~moderate~ applies a combination of background and foreground that
+is fairly subtle.  For Icomplete and friends this constitutes a
+departure from their default aesthetics, however the difference is
+small.  While Helm, Ivy et al appear slightly different than their
+original looks, as they are toned down a bit.
+
+Option ~opinionated~ uses color combinations that refashion the completion
+UI.  For the Icomplete camp this means that intense background and
+foreground combinations are used: in effect their looks emulate those of
+Helm, Ivy and co. in their original style.  Whereas the other group of
+packages will revert to an even more nuanced aesthetic with some
+additional changes to the choice of hues.
+
+To appreciate the scope of this customization option, you should spend
+some time with every one of the =nil= (default), ~moderate~, and ~opinionated~
+possibilities.
+
+** Option for fringe visibility
+:properties:
+:alt_title: Fringes
+:description: Choose among invisible, subtle, or intense fringe styles
+:custom_id: h:1983c3fc-74f6-44f3-b917-967c403bebae
+:end:
+#+vindex: modus-themes-fringes
+
+Symbol: ~modus-themes-fringes~
+
+Possible values:
+
+1. =nil= (default)
+2. ~subtle~
+3. ~intense~
+
+The default is to use the same color as that of the main background,
+meaning that the fringes are not obvious though they still occupy the
+space given to them by ~fringe-mode~.
+
+Options ~subtle~ and ~intense~ apply a gray background, making the fringes
+visible.  The difference between the two is one of degree, as their
+names imply.
+
+** Option for language checkers
+:properties:
+:alt_title: Language checkers
+:description: Control the style of language checkers/linters
+:custom_id: h:4b13743a-8ebf-4d2c-a043-cceba10b1eb4
+:end:
+#+vindex: modus-themes-lang-checkers
+
+Symbol: ~modus-themes-lang-checkers~
+
+Possible values:
+
+1. =nil= (default)
+2. ~subtle-foreground~
+3. ~intense-foreground~
+4. ~straight-underline~
+5. ~subtle-foreground-straight-underline~
+6. ~intense-foreground-straight-underline~
+7. ~colored-background~
+
+Nil (the default) applies a color-coded underline to the affected text,
+while it leaves the original foreground in tact.  If the display spec
+where Emacs runs in has support for it (e.g. Emacs GUI), the underline's
+style is that of a wave, otherwise it is a straight line.
+
+Options ~subtle-foreground~ and ~intense-foreground~ follow the same
+color-coding pattern and wavy underline of the default, while extending
+it with a corresponding foreground value for the affected text.  The
+difference between the two options is one of degree, as their names
+suggest.
+
+Option ~straight-underline~ is like the default but always applies a
+straight line under the affected text.  Same principle for
+~subtle-foreground-straight-underline~ and its counterpart
+~intense-foreground-straight-underline~.
+
+Option ~colored-background~ uses a straight underline, a tinted
+background, and a suitable foreground.  All are color-coded.  This is
+the most intense combination of face properties.
+
+The present variable affects packages and/or face groups such as those
+of =flyspell=, =flymake=, =flycheck=, ~artbollocks-mode~, and ~writegood-mode~.
+
+NOTE: The placement of the straight underline, though not the wave
+style, is controlled by the built-in ~x-underline-at-descent-line~,
+~x-use-underline-position-properties~, ~underline-minimum-offset~.  Please
+refer to their documentation strings.
+
+** Option for line highlighting (hl-line-mode)
+:properties:
+:alt_title: Line highlighting
+:description: Toggle intense style for current line highlighting
+:custom_id: h:1dba1cfe-d079-4c13-a810-f768e8789177
+:end:
+#+vindex: modus-themes-intense-hl-line
+
+Symbol: ~modus-themes-intense-hl-line~
+
+Possible values:
+
+1. =nil= (default)
+2. =t=
+
+The default is to use a subtle gray background for ~hl-line-mode~ and its
+global equivalent.
+
+With a non-nil value (=t=) use a more prominent background color instead.
+
+This affects several packages that enable ~hl-line-mode~, such as =elfeed=
+and =mu4e=.
+
+** Option for line numbers (display-line-numbers-mode)
+:properties:
+:alt_title: Line numbers
+:description: Toggle subtle style for line numbers
+:custom_id: h:8c4a6230-2e43-4aa2-a631-3b7179392e09
+:end:
+#+vindex: modus-themes-subtle-line-numbers
+
+Symbol: ~modus-themes-subtle-line-numbers~
+
+Possible value:
+
+1. =nil= (default)
+2. =t=
+
+The default style for ~display-line-numbers-mode~ and its global variant
+is to apply a subtle gray background to the line numbers.  The current
+line has a more pronounced background and foreground combination to
+bring more attention to itself.
+
+Similarly, the faces for ~display-line-numbers-major-tick~ and its
+counterpart ~display-line-numbers-minor-tick~ use appropriate styles that
+involve a bespoke background and foreground combination.
+
+With a non-nil value (=t=), line numbers have no background of their own.
+Instead they retain the primary background of the theme, blending with
+the rest of the buffer.  Foreground values for all relevant faces are
+updated to accommodate this aesthetic.
+
+** Option for parenthesis matching (show-paren-mode)
+:properties:
+:alt_title: Matching parentheses
+:description: Choose between various styles for matching delimiters/parentheses
+:custom_id: h:e66a7e4d-a512-4bc7-9f86-fbbb5923bf37
+:end:
+#+vindex: modus-themes-paren-match
+
+Symbol: ~modus-themes-paren-match~
+
+Possible values:
+
+1. =nil= (default)
+2. ~subtle-bold~
+3. ~intense~
+4. ~intense-bold~
+
+Nil means to use a subtle tinted background color for the matching
+delimiters.
+
+Option ~intense~ applies a saturated background color.
+
+Option ~subtle-bold~ is the same as the default, but also makes use of
+bold typographic weight (inherits the ~bold~ face).
+
+Option ~intense-bold~ is the same as ~intense~, while it also uses a bold
+weight.
+
+This customization variable affects tools such as the built-in
+~show-paren-mode~ and the =smartparens= package.
+
+** Option for active region
+:properties:
+:alt_title: Active region
+:description: Choose between various styles for the active region
+:custom_id: h:60798063-b4ad-45ea-b9a7-ff7b5c0ab74c
+:end:
+#+vindex: modus-themes-region
+
+Symbol: ~modus-themes-region~
+
+Possible values:
+
+1. =nil= (default)
+2. ~no-extend~
+3. ~bg-only~
+4. ~bg-only-no-extend~
+
+Nil means to only use a prominent gray background with a neutral
+foreground.  The foreground overrides all syntax highlighting.  The
+region extends to the edge of the window.
+
+Option ~no-extend~ preserves the default aesthetic but prevents the region
+from extending to the edge of the window.
+
+Option ~bg-only~ applies a faint tinted background that is distinct from
+all others used in the theme, while it does not override any existing
+colors.  It extends to the edge of the window.
+
+Option ~bg-only-no-extend~ is a combination of the ~bg-only~ and ~no-extend~
+options.
+
+** Option for diff buffer looks
+:properties:
+:alt_title: Diffs
+:description: Choose among intense, desaturated, or text-only diffs
+:custom_id: h:ea7ac54f-5827-49bd-b09f-62424b3b6427
+:end:
+#+vindex: modus-themes-diffs
+
+Symbol: ~modus-themes-diffs~
+
+Possible values:
+
+1. =nil= (default)
+2. ~desaturated~
+3. ~fg-only~
+4. ~bg-only~
+5. ~deuteranopia~
+
+By default the themes apply rich coloration to the output of diffs, such
+as those of ~diff-mode~, ~ediff~, ~smerge-mode~, and Magit.  These are
+color combinations of an accented background and foreground so that, for
+example, added lines have a pronounced green background with an
+appropriate shade of green for the affected text.  Word-wise or
+"refined" changes follow this pattern but use different shades of those
+colors to remain distinct.
+
+Option ~desaturated~ tones down all relevant color values.  It still
+combines an accented background with an appropriate foreground, yet its
+overall impression is fairly subtle.  Refined changes are a bit more
+intense to fulfil their intended function, though still less saturated
+than default.
+
+Option ~fg-only~ will remove most accented backgrounds and instead rely
+on color-coded text to denote changes.  For instance, added lines use a
+green foreground, while their background is the same as the rest of the
+buffer.  Word-wise highlights still use a background value which is,
+nonetheless, more subtle than its default equivalent.
+
+Option ~bg-only~ applies color-coded backgrounds but does not override
+any syntax highlighting that may be present.  This makes it suitable for
+use with a non-nil value for ~diff-font-lock-syntax~ (which is the
+default for ~diff-mode~ buffers in Emacs 27 or higher).
+
+Option ~deuteranopia~ optimizes for red-green color deficiency.  It
+replaces all instances of green with blue variants.  This is to ensure
+that indicators for "removed" and "added" states are not mistaken for
+each other.
+
+Concerning Magit, an extra set of tweaks are introduced for the effect
+of highlighting the current diff hunk, so as to remain aligned with the
+overall experience of that mode.  Expect changes that are consistent
+with the overall intent of the aforementioned.  Note, however, that the
+~bg-only~ option will not deliver the intended results in Magit diffs
+because no syntax highlighting is used there (last checked with Magit
+version 20201116.1057, though upstream has a plan to eventually support
+such a feature---this entry shall be updated accordingly).
+
+** Option for org-mode block styles
+:properties:
+:alt_title: Org mode blocks
+:description: Choose among plain, grayscale, or rainbow styles
+:custom_id: h:b7e328c0-3034-4db7-9cdf-d5ba12081ca2
+:end:
+#+vindex: modus-themes-org-blocks
+
+Symbol: ~modus-themes-org-blocks~
+
+Possible values:
+
+1. =nil= (default)
+2. ~grayscale~
+3. ~rainbow~
+
+The default is to use the same background as the rest of the buffer for
+the contents of the block.
+
+Option ~grayscale~ applies a subtle neutral gray background to the block's
+contents.  It will also extend to the edge of the window the background
+of the "begin" and "end" block delimiter lines (only relevant for Emacs
+versions >= 27 where the 'extend' keyword is part of the face
+specifications).
+
+Option ~rainbow~ uses an accented background for the contents of the
+block.  The exact color will depend on the programming language and is
+controlled by the ~org-src-block-faces~ variable.  This is most suitable
+for users who work on literate programming documents that mix and match
+several languages.
+
+Note that the "rainbow" blocks may require you to also reload the
+major-mode so that the colors are applied consistently throughout: use
+{{{kbd(M-x org-mode)}}} or {{{kbd(M-x org-mode-restart)}}} to refresh the 
buffer.
+Or start typing in each code block (inefficient at scale, but it still
+works).
+
+** Option for org-habit graph styles
+:properties:
+:alt_title: Org agenda habits
+:description: Choose among standard, simplified, or traffic light styles
+:custom_id: h:b7e328c0-3034-4db7-9cdf-d5ba12081ca2
+:end:
+#+vindex: modus-themes-org-habit
+
+Symbol: ~modus-themes-org-habit~
+
+Possible values:
+
+1. =nil= (default)
+2. ~simplified~
+3. ~traffic-light~
+
+The default is meant to conform with the original aesthetic of
+=org-habit=.  It employs all four color codes that correspond to the
+org-habit states---clear, ready, alert, and overdue---while
+distinguishing between their present and future variants.  This results
+in a total of eight colors in use: red, yellow, green, blue, in tinted
+and shaded versions.  They cover the full set of information provided by
+the =org-habit= consistency graph.
+
+Option ~simplified~ is like the default except that it removes the
+dichotomy between current and future variants by applying uniform
+color-coded values.  It applies a total of four colors: red, yellow,
+green, blue.  They produce a simplified consistency graph that is more
+legible (or less "busy") than the default.  The intent is to shift focus
+towards the distinction between the four states of a habit task, rather
+than each state's present/future outlook.
+
+Option ~traffic-light~ further reduces the available colors to red,
+yellow, and green.  As in ~simplified~, present and future variants appear
+uniformly, but differently from it, the 'clear' state is rendered in a
+green hue, instead of the original blue.  This is meant to capture the
+use-case where a habit task being "too early" is less important than it
+being "too late".  The difference between ready and clear states is
+attenuated by painting both of them using shades of green.  This option
+thus highlights the alert and overdue states.
+
+** Option for the headings' overall style
+:properties:
+:alt_title: Heading styles
+:description: Choose among several styles, also per heading level
+:custom_id: h:271eff19-97aa-4090-9415-a6463c2f9ae1
+:end:
+#+vindex: modus-themes-headings
+
+This is defined as an alist and, therefore, uses a different approach
+than other customization options documented in this manual.
+
+Symbol: ~modus-themes-headings~
+
+Possible values, which can be specified for each heading level (examples
+further below):
+
++ nil (default fallback option---covers all heading levels)
++ =t= (default style for a single heading, when the fallback differs)
++ ~no-bold~
++ ~line~
++ ~line-no-bold~
++ ~rainbow~
++ ~rainbow-line~
++ ~rainbow-line-no-bold~
++ ~highlight~
++ ~highlight-no-bold~
++ ~rainbow-highlight~
++ ~rainbow-highlight-no-bold~
++ ~section~
++ ~section-no-bold~
++ ~rainbow-section~
++ ~rainbow-section-no-bold~
++ ~no-color~
++ ~no-color-no-bold~
+
+To control faces per level from 1-8, use something like this:
+
+#+begin_src emacs-lisp
+(setq modus-themes-headings
+      '((1 . section)
+        (2 . section-no-bold)
+        (3 . rainbow-line)
+        (t . rainbow-line-no-bold)))
+#+end_src
+
+The above uses the ~section~ value for heading levels 1, ~section-no-bold~
+for headings 2, ~rainbow-line~ for 3.  All other levels fall back to
+~rainbow-line-no-bold~.
+
+To set a uniform value for all heading levels, use this pattern:
+
+#+begin_src emacs-lisp
+;; A given style for every heading
+(setq modus-themes-headings
+      '((t . section)))
+
+;; Default aesthetic for every heading
+(setq modus-themes-headings
+      '())
+#+end_src
+
+The default style for headings uses a fairly desaturated foreground
+value in combination with bold typographic weight.  To specify this
+style for a given level N, assuming you wish to have another fallback
+option, just specify the value =t= like this:
+
+#+begin_src emacs-lisp
+(setq modus-themes-headings
+      '((1 . t)
+        (2 . line)
+        (t . rainbow-line-no-bold)))
+#+end_src
+
+A description of all other possible styles beyond the default:
+
++ ~no-bold~ retains the default text color while removing the bold
+  typographic weight.
+
++ ~line~ is the same as the default plus an overline across the
+  heading's length.
+
++ ~line-no-bold~ is the same as ~line~ without bold weight.
+
++ ~rainbow~ uses a more colorful foreground in combination with bold
+  typographic weight.
+
++ ~rainbow-line~ is the same as ~rainbow~ plus an overline.
+
++ ~rainbow-line-no-bold~ is the same as ~rainbow-line~ without the bold
+  weight.
+
++ ~highlight~ retains the default style of a fairly desaturated
+  foreground combined with a bold weight and adds to it a subtle
+  accented background.
+
++ ~highlight-no-bold~ is the same as ~highlight~ without a bold weight.
+
++ ~rainbow-highlight~ is the same as ~highlight~ but with a more
+  colorful foreground.
+
++ ~rainbow-highlight-no-bold~ is the same as ~rainbow-highlight~ without
+  a bold weight.
+
++ ~section~ retains the default looks and adds to them both an overline
+  and a slightly accented background.  It is, in effect, a combination
+  of the ~line~ and ~highlight~ values.
+
++ ~section-no-bold~ is the same as ~section~ without a bold weight.
+
++ ~rainbow-section~ is the same as ~section~ but with a more colorful
+  foreground.
+
++ ~rainbow-section-no-bold~ is the same as ~rainbow-section~ without a
+  bold weight.
+
++ ~no-color~ does not apply any color to the heading, meaning that it
+  uses the foreground of the ~default~ face.  It still renders the text
+  with a bold typographic weight.
+
++ ~no-color-no-bold~ is like ~no-color~ but without the bold weight.
+
+** Option for scaled headings
+:properties:
+:alt_title: Scaled headings
+:description: Toggle scaling of headings
+:custom_id: h:075eb022-37a6-41a4-a040-cc189f6bfa1f
+:end:
+#+vindex: modus-themes-scale-headings
+
+Symbol: ~modus-themes-scale-headings~
+
+Possible values:
+
+1. =nil= (default)
+2. =t=
+
+The default is to use the same size for headings and paragraph text.
+
+With a non-nil value (=t=) make headings larger in height relative to the
+main text.  This is noticeable in modes like Org, Markdown, and Info.
+
+*** Control the scale of headings
+:properties:
+:alt_title: Scaled heading sizes
+:description: Specify rate of increase for scaled headings
+:custom_id: h:6868baa1-beba-45ed-baa5-5fd68322ccb3
+:end:
+
+In addition to the toggle for enabling scaled headings, users can also
+specify a number of their own.
+
++ If it is a floating point, say, =1.5=, it is interpreted as a multiple
+  of the base font size.  This is the recommended method, because it
+  will always adapt to changes in the base font size, such as while
+  using the ~text-scale-adjust~ command.
+
++ If it is an integer, it is read as an absolute font height that is
+  1/10 of the typographic point size.  Thus a value of =18pt= must be
+  expressed as =180=.  Setting an absolute value is discouraged, as it
+  will break the layout in cases where the base font size must change,
+  such as with the ~text-scale-adjust~ command 
([[#h:defcf4fc-8fa8-4c29-b12e-7119582cc929][Font configurations]]).
+  While we discourage using absolute values, we still provide for this
+  option for users who do not need to perform text-scaling operations or
+  who are content with whatever discrepancies in height.
+
+Below are the variables in their default values, using the floating
+point paradigm.  The numbers are very conservative, but one is free to
+change them to their liking, such as =1.2=, =1.4=, =1.6=, =1.8=, =2.0=---or 
use a
+resource for finding a consistent scale:
+
+#+begin_src emacs-lisp
+(setq modus-themes-scale-1 1.05
+      modus-themes-scale-2 1.1
+      modus-themes-scale-3 1.15
+      modus-themes-scale-4 1.2
+      modus-themes-scale-5 1.3)
+#+end_src
+
+As for the application of that scale, the variables that range from
+~modus-themes-scale-1~ up to ~modus-themes-scale-4~ apply to regular
+headings within the context of the given major mode.  The former is the
+smallest, while the latter is the largest.  "Regular headings" are those
+that have a standard syntax for their scale, such as Org mode's eight
+levels of asterisks or Markdown's six columns.
+
+Whereas ~modus-themes-scale-5~ is applied to special headings that do not
+conform with the aforementioned syntax, yet which are expected to be
+larger than the largest value on that implied scale.  Put concretely,
+Org's =#+title= meta datum is not part of the eight levels of headings in
+an Org file, yet is supposed to signify the primary header.  Similarly,
+the Org Agenda's structure headings are not part of a recognisable scale
+and so they also get ~modus-themes-scale-5~.
+
+Users who wish to maintain scaled headings for the normal syntax while
+preventing special headings from standing out, can assign a value of =1.0=
+to ~modus-themes-scale-5~ to make it the same as body text (or whatever
+value would render it indistinguishable from the desired point of
+reference).
+
+Note that in earlier versions of Org, scaling would only increase the
+size of the heading, but not of keywords that were added to it, like
+"TODO".  The issue has been fixed upstream:
+<https://protesilaos.com/codelog/2020-09-24-org-headings-adapt/>.
+
+** Option for variable-pitch font in UI elements
+:properties:
+:alt_title: UI typeface
+:description: Toggle the use of variable-pitch across the User Interface
+:custom_id: h:16cf666c-5e65-424c-a855-7ea8a4a1fcac
+:end:
+#+vindex: modus-themes-variable-pitch-ui
+
+Symbol: ~modus-themes-variable-pitch-ui~
+
+Possible values:
+
+1. =nil= (default)
+2. =t=
+
+This option concerns User Interface elements that are under the direct
+control of Emacs.  In particular: the mode line, header line, tab bar,
+and tab line.
+
+The default is to use the same font as the rest of Emacs, which usually
+is a monospaced family.
+
+With a non-nil value (=t=) apply a proportionately spaced typeface.  This
+is done by assigning the ~variable-pitch~ face to the relevant items.
+
+[[#h:defcf4fc-8fa8-4c29-b12e-7119582cc929][Font configurations for Org and 
others]].
+
+** Option for variable-pitch font in headings
+:properties:
+:alt_title: Headings' typeface
+:description: Toggle the use of variable-pitch in headings
+:custom_id: h:97caca76-fa13-456c-aef1-a2aa165ea274
+:end:
+#+vindex: modus-themes-variable-pitch-headings
+
+Symbol: ~modus-themes-variable-pitch-headings~
+
+Possible values:
+
+1. =nil= (default)
+2. =t=
+
+The default is to use the main font family, which typically is
+monospaced.
+
+With a non-nil value (=t=) apply a proportionately spaced typeface, else
+"variable-pitch", to headings (such as in Org mode).
+
+[[#h:defcf4fc-8fa8-4c29-b12e-7119582cc929][Font configurations for Org and 
others]].
+
+* Advanced customization (do-it-yourself)
+:properties:
+:custom_id: h:f4651d55-8c07-46aa-b52b-bed1e53463bb
+:end:
+
+Unlike the predefined customization options which follow a clear pattern
+of allowing the user to quickly specify their preference, the themes
+also provide a more flexible, albeit difficult, mechanism to control
+things with precision 
([[#h:bf1c82f2-46c7-4eb2-ad00-dd11fdd8b53f][Customization Options]]).
+
+This section is of interest only to users who are prepared to maintain
+their own local tweaks and who are willing to deal with any possible
+incompatibilities between versioned releases of the themes.  As such,
+they are labelled as "do-it-yourself" or "DIY".
+
+** Per-theme customization settings (DIY)
+:properties:
+:custom_id: h:a897b302-8e10-4a26-beab-3caaee1e1193
+:end:
+
+If you prefer to maintain different customization options between the
+two themes, it is best you write your own functions that first set those
+options and then load the relevant theme.  The following code does
+exactly that by simply differentiating the two themes on the choice of
+bold constructs in code syntax (enabled for one, disabled for the
+other).
+
+#+begin_src emacs-lisp
+(defun my-demo-modus-operandi ()
+  (interactive)
+  (setq modus-themes-bold-constructs t) ; ENABLE bold
+  (modus-themes-load-operandi))
+
+(defun my-demo-modus-vivendi ()
+  (interactive)
+  (setq modus-themes-bold-constructs nil) ; DISABLE bold
+  (modus-themes-load-vivendi))
+
+(defun my-demo-modus-themes-toggle ()
+  (if (eq (car custom-enabled-themes) 'modus-operandi)
+      (my-demo-modus-vivendi)
+    (my-demo-modus-operandi)))
+#+end_src
+
+Then assign ~my-demo-modus-themes-toggle~ to a key instead of the
+equivalent the themes provide.
+
+For a more elaborate design, it is better to inspect the source code of
+~modus-themes-toggle~ and relevant functions.
+
+** Case-by-case face specs using the themes' palette (DIY)
+:properties:
+:custom_id: h:1487c631-f4fe-490d-8d58-d72ffa3bd474
+:end:
+#+findex: modus-themes-color
+#+findex: modus-themes-color-alts
+#+cindex: Extracting individual colors
+
+This section is about tweaking individual faces.  If you plan to do
+things at scale, consult the next section: 
[[#h:51ba3547-b8c8-40d6-ba5a-4586477fd4ae][Set multiple faces]].
+
+We already covered in previous sections how to toggle between the themes
+and how to configure options prior to loading.  We also explained that
+some of the functions made available to users will fire up a hook that
+can be used to pass tweaks in the post-theme-load phase.
+
+Now assume you wish to change a single face, say, the ~cursor~.  And you
+would like to get the standard "blue" color value of the active Modus
+theme, whether it is Modus Operandi or Modus Vivendi.  To do that, you
+can use the ~modus-themes-color~ function.  It accepts a symbol that is
+associated with a color in ~modus-themes-operandi-colors~ and
+~modus-themes-vivendi-colors~.  Like this:
+
+#+begin_src emacs-lisp
+(modus-themes-color 'blue)
+#+end_src
+
+The function always extracts the color value of the active Modus theme.
+
+#+begin_src emacs-lisp
+(progn
+  (load-theme 'modus-operandi t)
+  (modus-themes-color 'blue))           ; "#0031a9" for `modus-operandi'
+
+(progn
+  (load-theme 'modus-vivendi t)
+  (modus-themes-color 'blue))           ; "#2fafff" for `modus-vivendi'
+#+end_src
+
+Do {{{kbd(C-h v)}}} on the aforementioned variables to check all the available
+symbols that can be passed to this function.
+
+With that granted, let us expand the example to actually change the
+~cursor~ face's background property.  We employ the built-in function of
+~set-face-attribute~:
+
+#+begin_src emacs-lisp
+(set-face-attribute 'cursor nil :background (modus-themes-color 'blue))
+#+end_src
+
+If you evaluate this form, your cursor will become blue.  But if you
+change themes, such as with ~modus-themes-toggle~, your edits will be
+lost, because the newly loaded theme will override the =:background=
+attribute you had assigned to that face.
+
+For such changes to persist, we need to make them after loading the
+theme.  So we rely on ~modus-themes-after-load-theme-hook~, which gets
+called from ~modus-themes-load-operandi~, ~modus-themes-load-vivendi~, as
+well as the command ~modus-themes-toggle~.  Here is a sample function that
+tweaks two faces and then gets added to the hook:
+
+#+begin_src emacs-lisp
+(defun my-modus-themes-custom-faces ()
+  (set-face-attribute 'cursor nil :background (modus-themes-color 'blue))
+  (set-face-attribute 'font-lock-type-face nil :foreground (modus-themes-color 
'magenta-alt)))
+
+(add-hook 'modus-themes-after-load-theme-hook #'my-modus-themes-custom-faces)
+#+end_src
+
+[[#h:86f6906b-f090-46cc-9816-1fe8aeb38776][A theme-agnostic hook for theme 
loading]].
+
+Using this principle, it is possible to override the styles of faces
+without having to find color values for each case.
+
+Another application is to control the precise weight for bold
+constructs.  This is particularly useful if your typeface has several
+variants such as "heavy", "extrabold", "semibold".  All you have to do
+is edit the ~bold~ face.  For example:
+
+#+begin_src emacs-lisp
+(set-face-attribute 'bold nil :weight 'semibold)
+#+end_src
+
+Remember to use the custom function and hook combo we demonstrated
+above.  Because the themes do not hard-wire a specific weight, this
+simple form is enough to change the weight of all bold constructs
+throughout the interface.
+
+Finally, there are cases where you want to tweak colors though wish to
+apply different ones to each theme, say, a blue hue for Modus Operandi
+and a shade of red for Modus Vivendi.  To this end, we provide
+~modus-themes-color-alts~ as a convenience function to save you from the
+trouble of writing separate wrappers for each theme.  It still returns a
+single value by querying either of ~modus-themes-operandi-colors~ and
+~modus-themes-vivendi-colors~, only here you pass the two keys you want,
+first for ~modus-operandi~ then ~modus-vivendi~.
+
+Take the previous example with the ~cursor~ face:
+
+#+begin_src emacs-lisp
+;; Blue for `modus-operandi' and red for `modus-vivendi'
+(set-face-attribute 'cursor nil :background (modus-themes-color-alts 'blue 
'red))
+#+end_src
+
+** Face specs at scale using the themes' palette (DIY)
+:properties:
+:custom_id: h:51ba3547-b8c8-40d6-ba5a-4586477fd4ae
+:end:
+#+findex: modus-themes-with-colors
+#+cindex: Extracting colors en masse
+
+The examples here are for large scale operations.  For simple, one-off
+tweaks, you may prefer the approach documented in the previous section
+([[#h:1487c631-f4fe-490d-8d58-d72ffa3bd474][Case-by-case face specs using the 
themes' palette]]).
+
+The ~modus-themes-with-colors~ macro lets you retrieve multiple color
+values by employing the backquote/backtick and comma notation.  The
+values are stored in the alists ~modus-themes-operandi-colors~ and
+~modus-themes-vivendi-colors~, while the macro always queries that of the
+active Modus theme.
+
+Here is an abstract example that just returns a list of color values
+while ~modus-operandi~ is enabled:
+
+#+begin_src emacs-lisp
+(modus-themes-with-colors
+  (list fg-main
+        blue-faint
+        magenta
+        magenta-alt-other
+        cyan-alt-other
+        fg-special-cold
+        blue-alt
+        magenta-faint
+        cyan
+        fg-main
+        green-faint
+        red-alt-faint
+        blue-alt-faint
+        fg-special-warm
+        cyan-alt
+        blue))
+;; =>
+;; ("#000000" "#002f88" "#721045" "#5317ac"
+;;  "#005a5f" "#093060" "#2544bb" "#752f50"
+;;  "#00538b" "#000000" "#104410" "#702f00"
+;;  "#003f78" "#5d3026" "#30517f" "#0031a9")
+#+end_src
+
+Getting a list of colors may have its applications, though what you are
+most likely interested in is how to use those variables to configure
+several faces at once.  To do so we can rely on the built-in
+~custom-set-faces~ function, which sets face specifications for the
+special =user= theme.  That "theme" gets applied on top of regular themes
+like ~modus-operandi~ and ~modus-vivendi~.
+
+This is how it works:
+
+#+begin_src emacs-lisp
+(modus-themes-with-colors
+  (custom-set-faces
+   `(cursor ((,class :background ,blue)))
+   `(mode-line ((,class :background ,yellow-nuanced-bg
+                        :foreground ,yellow-nuanced-fg)))
+   `(mode-line-inactive ((,class :background ,blue-nuanced-bg
+                                 :foreground ,blue-nuanced-fg)))))
+#+end_src
+
+The above snippet will immediately refashion the faces it names once it
+is evaluated.  However, if you switch between the Modus themes, say,
+from ~modus-operandi~ to ~modus-vivendi~, the colors will not get updated to
+match those of the new theme.  To make things work across the themes, we
+need to employ the same technique we discussed in the previous section,
+namely, to pass our changes at the post-theme-load phase via a hook.
+
+The themes provide the ~modus-themes-after-load-theme-hook~, which gets
+called from ~modus-themes-load-operandi~, ~modus-themes-load-vivendi~, as
+well as the command ~modus-themes-toggle~.  With this knowledge, you can
+wrap the macro in a function and then assign that function to the hook.
+Thus:
+
+#+begin_src emacs-lisp
+(defun my-modus-themes-custom-faces ()
+  (modus-themes-with-colors
+    (custom-set-faces
+     `(cursor ((,class :background ,blue)))
+     `(mode-line ((,class :background ,yellow-nuanced-bg
+                          :foreground ,yellow-nuanced-fg)))
+     `(mode-line-inactive ((,class :background ,blue-nuanced-bg
+                                   :foreground ,blue-nuanced-fg))))))
+
+(add-hook 'modus-themes-after-load-theme-hook #'my-modus-themes-custom-faces)
+#+end_src
+
+[[#h:86f6906b-f090-46cc-9816-1fe8aeb38776][A theme-agnostic hook for theme 
loading]].
+
+To discover the faces defined by all loaded libraries, you may do
+{{{kbd(M-x list-faces-display)}}}.  Be warned that when you =:inherit= a face
+you are introducing an implicit dependency, so try to avoid doing so for
+libraries other than the built-in {{{file(faces.el)}}} (or at least understand
+that things may break if you inherit from a yet-to-be-loaded face).
+
+Also bear in mind that these examples are meant to work with the Modus
+themes.  If you are cycling between multiple themes you may encounter
+unforeseen issues, such as the colors of the Modus themes being applied
+to a non-Modus item.
+
+Finally, note that you can still use other functions where those make
+sense.  For example, the ~modus-themes-color-alts~ that was discussed in
+the previous section.  Adapt the above example like this:
+
+#+begin_src emacs-lisp
+...
+(modus-themes-with-colors
+  (custom-set-faces
+   `(cursor ((,class :background ,(modus-themes-color-alts 'blue 'green))))
+   ...))
+#+end_src
+
+** Override colors (DIY)
+:properties:
+:custom_id: h:307d95dd-8dbd-4ece-a543-10ae86f155a6
+:end:
+#+vindex: modus-themes-operandi-color-overrides
+#+vindex: modus-themes-vivendi-color-overrides
+#+cindex: Change a theme's colors
+
+The themes provide a mechanism for overriding their color values.  This
+is controlled by the variables ~modus-themes-operandi-color-overrides~ and
+~modus-themes-vivendi-color-overrides~, which are alists that should
+mirror a subset of the associations in ~modus-themes-operandi-colors~ and
+~modus-themes-vivendi-colors~ respectively.  As with all customisations,
+overriding must be done before loading the affected theme.
+
+Let us approach the present topic one step at a time.  Here is a
+simplified excerpt of the default palette for Modus Operandi with some
+basic background values that apply to buffers and the mode line
+(remember to inspect the actual value to find out all the associations
+that can be overridden):
+
+#+begin_src emacs-lisp
+(defconst modus-themes-colors-operandi
+  '((bg-main . "#ffffff")
+    (bg-dim . "#f8f8f8")
+    (bg-alt . "#f0f0f0")
+    (bg-active . "#d7d7d7")
+    (bg-inactive . "#efefef")))
+#+end_src
+
+As one can tell, we bind a key to a hexadecimal RGB color value.  Now
+say we wish to override those specific values and have our changes
+propagate to all faces that use those keys.  We could write something
+like this, which adds a subtle ochre tint:
+
+#+begin_src emacs-lisp
+(setq modus-themes-operandi-color-overrides
+      '((bg-main . "#fefcf4")
+        (bg-dim . "#faf6ef")
+        (bg-alt . "#f7efe5")
+        (bg-active . "#e8dfd1")
+        (bg-inactive . "#f6ece5")))
+#+end_src
+
+Once this is evaluated, any subsequent loading of ~modus-operandi~ will
+use those values instead of the defaults.  No further intervention is
+required.
+
+To reset the changes, we apply this and reload the theme:
+
+#+begin_src emacs-lisp
+(setq modus-themes-operandi-color-overrides nil)
+#+end_src
+
+Users who wish to leverage such a mechanism can opt to implement it
+on-demand by means of a global minor mode.  The following snippet covers
+both themes and expands to some more assosiations in the palette:
+
+#+begin_src emacs-lisp
+(define-minor-mode my-modus-themes-tinted
+  "Tweak some Modus themes colors."
+  :init-value nil
+  :global t
+  (if my-modus-themes-tinted
+      (setq modus-themes-operandi-color-overrides
+            '((bg-main . "#fefcf4")
+              (bg-dim . "#faf6ef")
+              (bg-alt . "#f7efe5")
+              (bg-hl-line . "#f4f0e3")
+              (bg-active . "#e8dfd1")
+              (bg-inactive . "#f6ece5")
+              (bg-region . "#c6bab1")
+              (bg-header . "#ede3e0")
+              (bg-tab-bar . "#dcd3d3")
+              (bg-tab-active . "#fdf6eb")
+              (bg-tab-inactive . "#c8bab8")
+              (fg-unfocused . "#55556f"))
+            modus-themes-vivendi-color-overrides
+            '((bg-main . "#100b17")
+              (bg-dim . "#161129")
+              (bg-alt . "#181732")
+              (bg-hl-line . "#191628")
+              (bg-active . "#282e46")
+              (bg-inactive . "#1a1e39")
+              (bg-region . "#393a53")
+              (bg-header . "#202037")
+              (bg-tab-bar . "#262b41")
+              (bg-tab-active . "#120f18")
+              (bg-tab-inactive . "#3a3a5a")
+              (fg-unfocused . "#9a9aab")))
+    (setq modus-themes-operandi-color-overrides nil
+          modus-themes-vivendi-color-overrides nil)))
+#+end_src
+
+With this in place, one can invoke {{{kbd(M-x my-modus-themes-tinted)}}} and
+then load the Modus theme of their choice.  The new palette subset will
+come into effect: subtle ochre tints for Modus Operandi and night sky
+shades for Modus Vivendi.  Switching between the two themes, such as
+with {{{kbd(M-x modus-themes-toggle)}}} will also use the overrides.
+
+Given that this is a user-level customisation, one is free to implement
+whatever color values they desire, even if the possible combinations
+fall below the minimum 7:1 contrast ratio that governs the design of the
+themes (the WCAG AAA legibility standard).  Preferences aside, it is
+advised to inspect the source code of ~modus-themes-operandi-colors~ and
+~modus-themes-vivendi-colors~ to read the inline commentary: it explains
+what the intended use of each palette subset is.
+
+Furthermore, users may benefit from the ~modus-themes-contrast~ function
+that we provide: [[#h:02e25930-e71a-493d-828a-8907fc80f874][test color 
combinations]].  It measures the contrast
+ratio between two color values, so it can help in overriding the palette
+(or a subset thereof) without making the end result inaccessible.
+
+** Font configurations for Org and others (DIY)
+:properties:
+:custom_id: h:defcf4fc-8fa8-4c29-b12e-7119582cc929
+:end:
+#+cindex: Font configurations
+
+The themes are designed to cope well with mixed font configurations.
+
+[[#h:115e6c23-ee35-4a16-8cef-e2fcbb08e28b][Option for no font mixing]].
+
+This mostly concerns ~org-mode~ and ~markdown-mode~, though expect to find
+it elsewhere like in ~Info-mode~.
+
+In practice it means that the user can safely opt for a more
+prose-friendly proportionately spaced typeface as their default, while
+letting spacing-sensitive elements like tables and inline code always
+use a monospaced font, by inheriting from the ~fixed-pitch~ face.
+
+Users can try the built-in {{{kbd(M-x variable-pitch-mode)}}} to see the
+effect in action.
+
+To make everything use your desired font families, you need to configure
+the ~variable-pitch~ (proportional spacing) and ~fixed-pitch~ (monospaced)
+faces respectively.  It may also be convenient to set your main typeface
+by configuring the ~default~ face the same way.
+
+Put something like this in your initialization file (also consider
+reading the doc string of ~set-face-attribute~):
+
+#+begin_src emacs-lisp
+;; Main typeface
+(set-face-attribute 'default nil :family "DejaVu Sans Mono" :height 110)
+
+;; Proportionately spaced typeface
+(set-face-attribute 'variable-pitch nil :family "DejaVu Serif" :height 1.0)
+
+;; Monospaced typeface
+(set-face-attribute 'fixed-pitch nil :family "DejaVu Sans Mono" :height 1.0)
+#+end_src
+
+Note the differences in the =:height= property.  The =default= face must
+specify an absolute value, which is the point size × 10.  So if you want
+to use a font at point size =11=, you set the height to =110=.[fn:: =:height=
+values do not need to be rounded to multiples of ten: the likes of =115=
+are perfectly valid—some typefaces will change to account for those
+finer increments.]  Whereas every other face must have a value that is
+relative to the default, represented as a floating point (if you use an
+integer, then that means an absolute height).  This is of paramount
+importance: it ensures that all fonts can scale gracefully when using
+something like the ~text-scale-adjust~ command which only operates on the
+base font size (i.e. the ~default~ face's absolute height).
+
+** Custom Org user faces (DIY)
+:properties:
+:custom_id: h:89f0678d-c5c3-4a57-a526-668b2bb2d7ad
+:end:
+#+cindex: Org extra faces
+
+Users of ~org-mode~ have the option to configure various keywords and
+priority cookies to better match their workflow.  User options are
+~org-todo-keyword-faces~ and ~org-priority-faces~.
+
+As those are meant to be custom faces, it is futile to have the themes
+guess what each user wants to use, which keywords to target, and so on.
+Instead, we can provide guidelines on how to customize things to one's
+liking with the intent of retaining the overall aesthetic of the themes.
+
+Please bear in mind that the end result of those is not controlled by
+the active Modus theme but by how Org maps faces to its constructs.
+Editing those while ~org-mode~ is active requires re-initialization of the
+mode with {{{kbd(M-x org-mode-restart)}}} for changes to take effect.
+
+Let us assume you wish to visually differentiate your keywords.  You
+have something like this:
+
+#+begin_src emacs-lisp
+(setq org-todo-keywords
+      '((sequence "TODO(t)" "|" "DONE(D)" "CANCEL(C)")
+        (sequence "MEET(m)" "|" "MET(M)")
+        (sequence "STUDY(s)" "|" "STUDIED(S)")
+        (sequence "WRITE(w)" "|" "WROTE(W)")))
+#+end_src
+
+You could then use a variant of the following to inherit from a face
+that uses the styles you want and also to preserve the properties
+applied by the ~org-todo~ face:
+
+#+begin_src emacs-lisp
+(setq org-todo-keyword-faces
+      '(("MEET" . '(font-lock-preprocessor-face org-todo))
+        ("STUDY" . '(font-lock-variable-name-face org-todo))
+        ("WRITE" . '(font-lock-type-face org-todo))))
+#+end_src
+
+This will refashion the keywords you specify, while letting the other
+items in ~org-todo-keywords~ use their original styles (which are defined
+in the ~org-todo~ and ~org-done~ faces).
+
+If you want back the defaults, try specifying just the ~org-todo~ face:
+
+#+begin_src emacs-lisp
+(setq org-todo-keyword-faces
+      '(("MEET" . org-todo)
+        ("STUDY" . org-todo)
+        ("WRITE" . org-todo)))
+#+end_src
+
+When you inherit from multiple faces, you need to quote the list as
+shown further above.  The order is important: the last item is applied
+over the previous ones.  If you do not want to blend multiple faces, you
+do not need a quoted list.  A pattern of =keyword . face= will suffice.
+
+Both approaches can be used simultaneously, as illustrated in this
+configuration of the priority cookies:
+
+#+begin_src emacs-lisp
+(setq org-priority-faces
+      '((?A . '(org-scheduled-today org-priority))
+        (?B . org-priority)
+        (?C . '(shadow org-priority))))
+#+end_src
+
+To find all the faces that are loaded in your current Emacs session, use
+{{{kbd(M-x list-faces-display)}}}.  Try {{{kbd(M-x describe-variable)}}} as 
well and
+then specify the name of each of those Org variables demonstrated above.
+Their documentation strings will offer you further guidance.
+
+Recall that the themes let you retrieve a color from their palette.  Do
+it if you plan to control face attributes.
+
+[[#h:1487c631-f4fe-490d-8d58-d72ffa3bd474][Custom face specs using the themes' 
palette]].
+
+[[#h:02e25930-e71a-493d-828a-8907fc80f874][Check color combinations]].
+
+** Measure color contrast (DIY)
+:properties:
+:custom_id: h:02e25930-e71a-493d-828a-8907fc80f874
+:end:
+#+findex: modus-themes-contrast
+#+findex: modus-themes-wcag-formula
+#+cindex: Color contrast
+
+The themes provide the functions ~modus-themes-wcag-formula~ and
+~modus-themes-contrast~.  The former is a direct implementation of the
+WCAG formula: <https://www.w3.org/TR/WCAG20-TECHS/G18.html>.  It
+calculates the relative luminance of a color value that is expressed in
+hexadecimal RGB notation.  While the latter function is just a
+convenient wrapper for comparing the relative luminance between two
+colors.
+
+In practice, one needs to work only with ~modus-themes-contrast~.  It
+accepts two color values and returns their contrast ratio.  Values range
+from 1 to 21 (lowest to highest).  The themes are designed to always be
+equal or higher than 7 for each combination of background and foreground
+that they use (this is the WCAG AAA standard---the most demanding of its
+kind).
+
+A couple of examples (rounded numbers):
+
+#+begin_src emacs-lisp
+;; Pure white with pure green
+(modus-themes-contrast "#ffffff" "#00ff00")
+;; => 1.37
+;; That is an outright inaccessible combo
+
+;; Pure black with pure green
+(modus-themes-contrast "#000000" "#00ff00")
+;; => 15.3
+;; That is is a highly accessible combo
+#+end_src
+
+It does not matter which color value comes first.  The ratio is always
+the same.
+
+If one does not wish to read all the decimal points, it is possible to
+try something like this:
+
+#+begin_src emacs-lisp
+(format "%0.2f" (modus-themes-contrast "#000000" "#00ff00"))
+#+end_src
+
+While it is fine to perform such calculations on a case-by-case basis,
+it is preferable to implement formulas and tables for more demanding
+tasks.  Such instruments are provided by ~org-mode~ or ~orgtbl-mode~, both
+of which are built into Emacs.  Below is such a table that derives the
+contrast ratio of all colors in the first column (pure red, green, blue)
+relative to the color specified in the first row of the second column
+(pure white) and rounds the results:
+
+#+begin_example
+|         | #ffffff |
+|---------+---------|
+| #ff0000 |    4.00 |
+| #00ff00 |    1.37 |
+| #0000ff |    8.59 |
+#+tblfm: $2='(modus-themes-contrast $1 @1$2);%0.2f
+#+end_example
+
+To measure color contrast one needs to start from a known value.  This
+typically is the background.  The Modus themes define an expanded
+palette in large part because certain colors are only meant to be used
+in combination with some others.  Consult the source code for the
+minutia and relevant commentary.
+
+Such knowledge may prove valuable while attempting to override some of
+the themes' colors: [[#h:307d95dd-8dbd-4ece-a543-10ae86f155a6][Override 
colors]].
+
+** Load theme depending on time of day
+:properties:
+:custom_id: h:1d1ef4b4-8600-4a09-993c-6de3af0ddd26
+:end:
+
+While we do provide ~modus-themes-toggle~ to manually switch between the
+themes, users may also set up their system to perform such a task
+automatically at sunrise and sunset.
+
+This can be accomplished by specifying the coordinates of one's location
+using the built-in {{{file(solar.el)}}} and then configuring the =circadian=
+package:
+
+#+begin_src emacs-lisp
+(use-package solar                      ; built-in
+  :config
+  (setq calendar-latitude 35.17
+        calendar-longitude 33.36))
+
+(use-package circadian                  ; you need to install this
+  :ensure
+  :after solar
+  (setq circadian-themes '((:sunrise . modus-operandi)
+                           (:sunset  . modus-vivendi)))
+  (circadian-setup))
+#+end_src
+
+** A theme-agnostic hook for theme loading (DIY)
+:properties:
+:custom_id: h:86f6906b-f090-46cc-9816-1fe8aeb38776
+:end:
+
+The themes are designed with the intent to be useful to Emacs users of
+varying skill levels, from beginners to experts.  This means that we try
+to make things easier by not expecting anyone reading this document to
+be proficient in Emacs Lisp or programming in general.
+
+Such a case is with the use of the ~modus-themes-after-load-theme-hook~,
+which runs after ~modus-themes-toggle~, ~modus-themes-load-operandi~, or
+~modus-themes-load-vivendi~ is evaluated.  We recommend using that hook
+for advanced customizations, because (1) we know for sure that it is
+available once the themes are loaded, and (2) anyone consulting this
+manual, especially the sections on enabling and loading the themes, will
+be in a good position to benefit from that hook.
+
+Advanced users who have a need to switch between the Modus themes and
+other items will find that such a hook does not meet their requirements:
+it only works with the Modus themes and only with the aforementioned
+functions.
+
+A theme-agnostic setup can be configured thus:
+
+#+begin_src emacs-lisp
+(defvar after-enable-theme-hook nil
+   "Normal hook run after enabling a theme.")
+
+(defun run-after-enable-theme-hook (&rest _args)
+   "Run `after-enable-theme-hook'."
+   (run-hooks 'after-enable-theme-hook))
+
+(advice-add 'enable-theme :after #'run-after-enable-theme-hook)
+#+end_src
+
+This creates the ~after-enable-theme-hook~ and makes it run after each
+call to ~enable-theme~, which means that it will work for all themes and
+also has the benefit that it does not depend on functions such as
+~modus-themes-toggle~ and the others mentioned above.  ~enable-theme~ is
+called internally by ~load-theme~, so the hook works everywhere.
+
+Now this specific piece of Elisp may be simple for experienced users,
+but it is not easy to read for newcomers, including the author of the
+Modus themes for the first several months of their time as an Emacs
+user.  Hence our hesitation to recommend it as part of the standard
+setup of the Modus themes (it is generally a good idea to understand
+what the implications are of advising a function).
+
+* Face coverage
+:properties:
+:custom_id: h:a9c8f29d-7f72-4b54-b74b-ddefe15d6a19
+:end:
+
+The Modus themes try to provide as close to full face coverage as
+possible.  This is necessary to ensure a consistently accessible reading
+experience across all available interfaces.
+
+** Full support for packages or face groups
+:properties:
+:alt_title: Supported packages
+:description: Full list of covered face groups
+:custom_id: h:60ed4275-60d6-49f8-9287-9a64e54bea0e
+:end:
+#+cindex: Explicitly supported packages
+
+This list will always be updated to reflect the current state of the
+project.  The idea is to offer an overview of the known status of all
+affected face groups.  The items with an appended asterisk =*= tend to
+have lots of extensions, so the "full support" may not be 100% true…
+
++ ace-window
++ ag
++ alert
++ all-the-icons
++ annotate
++ anzu
++ apropos
++ apt-sources-list
++ artbollocks-mode
++ auctex and TeX
++ auto-dim-other-buffers
++ avy
++ awesome-tray
++ bbdb
++ binder
++ bm
++ bongo
++ boon
++ breakpoint (provided by the built-in {{{file(gdb-mi.el)}}} library)
++ buffer-expose
++ calendar and diary
++ calfw
++ centaur-tabs
++ cfrs
++ change-log and log-view (such as ~vc-print-log~, ~vc-print-root-log~)
++ cider
++ circe
++ color-rg
++ column-enforce-mode
++ company-mode*
++ company-posframe
++ compilation-mode
++ completions
++ consult
++ counsel*
++ counsel-css
++ counsel-notmuch
++ counsel-org-capture-string
++ cov
++ cperl-mode
++ csv-mode
++ ctrlf
++ custom (what you get with {{{kbd(M-x customize)}}})
++ dap-mode
++ dashboard (emacs-dashboard)
++ deadgrep
++ debbugs
++ define-word
++ deft
++ dictionary
++ diff-hl
++ diff-mode
++ dim-autoload
++ dir-treeview
++ dired
++ dired-async
++ dired-git
++ dired-git-info
++ dired-narrow
++ dired-subtree
++ diredc
++ diredfl
++ diredp (dired+)
++ disk-usage
++ display-fill-column-indicator-mode
++ doom-modeline
++ dynamic-ruler
++ easy-jekyll
++ easy-kill
++ ebdb
++ ediff
++ eglot
++ el-search
++ eldoc-box
++ elfeed
++ elfeed-score
++ emms
++ enhanced-ruby-mode
++ epa
++ equake
++ erc
++ eros
++ ert
++ eshell
++ eshell-fringe-status
++ eshell-git-prompt
++ eshell-prompt-extras (epe)
++ eshell-syntax-highlighting
++ evil* (evil-mode)
++ evil-goggles
++ evil-snipe
++ evil-visual-mark-mode
++ eww
++ exwm
++ eyebrowse
++ fancy-dabbrev
++ flycheck
++ flycheck-color-mode-line
++ flycheck-indicator
++ flycheck-posframe
++ flymake
++ flyspell
++ flyspell-correct
++ flx
++ freeze-it
++ frog-menu
++ focus
++ fold-this
++ font-lock (generic syntax highlighting)
++ forge
++ fountain (fountain-mode)
++ geiser
++ git-commit
++ git-gutter (and variants)
++ git-lens
++ git-rebase
++ git-timemachine
++ git-walktree
++ gnus
++ golden-ratio-scroll-screen
++ helm*
++ helm-ls-git
++ helm-switch-shell
++ helm-xref
++ helpful
++ highlight-blocks
++ highlight-defined
++ highlight-escape-sequences (~hes-mode~)
++ highlight-indentation
++ highlight-numbers
++ highlight-symbol
++ highlight-tail
++ highlight-thing
++ hl-defined
++ hl-fill-column
++ hl-line-mode
++ hl-todo
++ hydra
++ hyperlist
++ ibuffer
++ icomplete
++ icomplete-vertical
++ ido-mode
++ iedit
++ iflipb
++ imenu-list
++ indium
++ info
++ info-colors
++ interaction-log
++ ioccur
++ isearch, occur, etc.
++ isl (isearch-light)
++ ivy*
++ ivy-posframe
++ jira (org-jira)
++ journalctl-mode
++ js2-mode
++ julia
++ jupyter
++ kaocha-runner
++ keycast
++ line numbers (~display-line-numbers-mode~ and global variant)
++ lsp-mode
++ lsp-ui
++ macrostep
++ magit
++ magit-imerge
++ make-mode
++ man
++ marginalia
++ markdown-mode
++ markup-faces (~adoc-mode~)
++ mentor
++ messages
++ minibuffer-line
++ minimap
++ mmm-mode
++ modeline
++ mood-line
++ moody
++ mpdel
++ mu4e
++ mu4e-conversation
++ multiple-cursors
++ neotree
++ no-emoji
++ notmuch
++ num3-mode
++ nxml-mode
++ objed
++ orderless
++ org*
++ org-journal
++ org-noter
++ org-pomodoro
++ org-recur
++ org-roam
++ org-superstar
++ org-table-sticky-header
++ org-tree-slide
++ org-treescope
++ origami
++ outline-mode
++ outline-minor-faces
++ package (what you get with {{{kbd(M-x list-packages)}}})
++ page-break-lines
++ paradox
++ paren-face
++ parrot
++ pass
++ pdf-tools
++ persp-mode
++ perspective
++ phi-grep
++ phi-search
++ pkgbuild-mode
++ pomidor
++ popup
++ powerline
++ powerline-evil
++ prism ([[#h:a94272e0-99da-4149-9e80-11a7e67a2cf2][Note for prism.el]])
++ proced
++ prodigy
++ quick-peek
++ racket-mode
++ rainbow-blocks
++ rainbow-identifiers
++ rainbow-delimiters
++ rcirc
++ recursion-indicator
++ regexp-builder (also known as ~re-builder~)
++ rg (rg.el)
++ ripgrep
++ rmail
++ ruler-mode
++ sallet
++ selectrum
++ selectrum-prescient
++ semantic
++ sesman
++ shell-script-mode
++ shortdoc
++ show-paren-mode
++ shr
++ side-notes
++ sieve-mode
++ skewer-mode
++ smart-mode-line
++ smartparens
++ smerge
++ solaire
++ spaceline
++ speedbar
++ spell-fu
++ spray
++ stripes
++ suggest
++ switch-window
++ swiper
++ swoop
++ sx
++ symbol-overlay
++ syslog-mode
++ table (built-in table.el)
++ telephone-line
++ terraform-mode
++ term
++ tomatinho
++ transient (pop-up windows such as Magit's)
++ trashed
++ treemacs
++ tty-menu
++ tuareg
++ typescript
++ undo-tree
++ vc (built-in mode line status for version control)
++ vc-annotate (the out put of {{{kbd(C-x v g)}}})
++ vdiff
++ vimish-fold
++ visible-mark
++ visual-regexp
++ volatile-highlights
++ vterm
++ wcheck-mode
++ web-mode
++ wgrep
++ which-function-mode
++ which-key
++ whitespace-mode
++ window-divider-mode
++ winum
++ writegood-mode
++ woman
++ xah-elisp-mode
++ xref
++ xterm-color (and ansi-colors)
++ yaml-mode
++ yasnippet
++ ztree
+
+Plus many other miscellaneous faces that are provided by the upstream
+GNU Emacs distribution.
+
+** Indirectly covered packages
+:properties:
+:custom_id: h:2cb359c7-3a84-4262-bab3-dcdc1d0034d7
+:end:
+#+cindex: Implicitly supported packages
+
+These do not require any extra styles because they are configured to
+inherit from some basic faces.  Please confirm.
+
++ edit-indirect
++ evil-owl
++ fortran-mode
++ goggles
++ i3wm-config-mode
++ perl-mode
++ php-mode
++ rjsx-mode
++ swift-mode
++ tab-bar-echo-area
+
+* Notes for individual packages
+:properties:
+:custom_id: h:4c4d901a-84d7-4f20-bd99-0808c2b06eba
+:end:
+
+This section covers information that may be of interest to users of
+individual packages.
+
+** Note for display-fill-column-indicator-mode
+:properties:
+:custom_id: h:2a602816-bc1b-45bf-9675-4cbbd7bf6cab
+:end:
+
+While designing the style for ~display-fill-column-indicator-mode~, we
+stayed close to the mode's defaults: to apply a subtle foreground color
+to the ~fill-column-indicator~ face, which blends well with the rest of
+theme and is consistent with the role of that mode.  This is to not
+upset the expectations of users.
+
+Nevertheless, ~display-fill-column-indicator-mode~ has some known
+limitations pertaining to its choice of using typographic characters to
+draw its indicator.  What should be a continuous vertical line might
+appear as a series of dashes in certain contexts or under specific
+conditions: a non-default value for ~line-spacing~, scaled and/or
+variable-pitch headings have been observed to cause this effect.
+
+Given that we cannot control such factors, it may be better for affected
+users to deviate from the default style of the ~fill-column-indicator~
+face.  Instead of setting a foreground color, one could use a background
+and have the foreground be indistinguishable from it.  For example:
+
+#+begin_src emacs-lisp
+(modus-themes-with-colors
+  (custom-set-faces
+   `(fill-column-indicator ((,class :background ,bg-inactive
+                                    :foreground ,bg-inactive)))))
+#+end_src
+
+[[#h:51ba3547-b8c8-40d6-ba5a-4586477fd4ae][Face specs at scale using the 
themes' palette]].
+
+** Note for mmm-mode.el background colors
+:properties:
+:custom_id: h:99cf0d6c-e478-4e26-9932-3bf3427d13f6
+:end:
+
+The faces used by {{{file(mmm-mode.el)}}} are expected to have a colorful
+background, while they should not touch any foreground value.  The idea
+is that they must not interfere with existing fontification.  Those
+background colors need to be distinct from each other, such as an
+unambiguous red juxtaposed with a clear blue.
+
+While this design may be internally consistent with the raison d'être of
+that library, it inevitably produces inaccessible color combinations.
+
+There are two competing goals at play:
+
+1. Legibility of the text, understood as the contrast ratio between the
+   background and the foreground.
+
+2. Semantic precision of each face which entails faithfulness to
+   color-coding of the underlying background.
+
+As the Modus themes are designed with the express purpose of conforming
+with the first point, we have to forgo the apparent color-coding of the
+background elements.  Instead we use subtle colors that do not undermine
+the legibility of the affected text while they still offer a sense of
+added context.
+
+Users who might prefer to fall below the minimum 7:1 contrast ratio in
+relative luminance (the accessibility target we conform with), can opt
+to configure the relevant faces on their own.
+
+[[#h:51ba3547-b8c8-40d6-ba5a-4586477fd4ae][Face specs at scale using the 
themes' palette]].
+
+This example uses more vivid background colors, though it comes at the
+very high cost of degraded legibility.
+
+#+begin_src emacs-lisp
+(modus-themes-with-colors
+  (custom-set-faces
+   `(mmm-cleanup-submode-face ((,class :background ,yellow-refine-bg)))
+   `(mmm-code-submode-face ((,class :background ,bg-active)))
+   `(mmm-comment-submode-face ((,class :background ,blue-refine-bg)))
+   `(mmm-declaration-submode-face ((,class :background ,cyan-refine-bg)))
+   `(mmm-default-submode-face ((,class :background ,bg-alt)))
+   `(mmm-init-submode-face ((,class :background ,magenta-refine-bg)))
+   `(mmm-output-submode-face ((,class :background ,red-refine-bg)))
+   `(mmm-special-submode-face ((,class :background ,green-refine-bg)))))
+#+end_src
+
+** Note for prism.el
+:properties:
+:alt_title: Note for prism
+:custom_id: h:a94272e0-99da-4149-9e80-11a7e67a2cf2
+:end:
+
+This package by Adam Porter, aka "alphapapa" or "github-alphapapa",
+implements an alternative to the typical coloration of code.  Instead of
+highlighting the syntactic constructs, it applies color to different
+levels of depth in the code structure.
+
+As {{{file(prism.el)}}} offers a broad range of customisations, we cannot
+style it directly at the theme level: that would run contrary to the
+spirit of the package.  Instead, we may offer preset color schemes.
+Those should offer a starting point for users to adapt to their needs.
+
+In the following code snippets, we employ the ~modus-themes-with-colors~
+macro: [[#h:51ba3547-b8c8-40d6-ba5a-4586477fd4ae][Face specs at scale using 
the themes' palette]].
+
+These are the minimum recommended settings with 16 colors:
+
+#+begin_src emacs-lisp
+(setq prism-num-faces 16)
+
+(prism-set-colors
+  :desaturations '(0) ; do not change---may lower the contrast ratio
+  :lightens '(0)      ; same
+  :colors (modus-themes-with-colors
+            (list fg-main
+                  magenta
+                  cyan-alt-other
+                  magenta-alt-other
+                  blue
+                  magenta-alt
+                  cyan-alt
+                  red-alt-other
+                  green
+                  fg-main
+                  cyan
+                  yellow
+                  blue-alt
+                  red-alt
+                  green-alt-other
+                  fg-special-warm)))
+#+end_src
+
+With 8 colors:
+
+#+begin_src emacs-lisp
+(setq prism-num-faces 8)
+
+(prism-set-colors
+  :desaturations '(0) ; do not change---may lower the contrast ratio
+  :lightens '(0)      ; same
+  :colors (modus-themes-with-colors
+            (list fg-special-cold
+                  magenta
+                  magenta-alt-other
+                  cyan-alt-other
+                  fg-main
+                  blue-alt
+                  red-alt-other
+                  cyan)))
+#+end_src
+
+And this is with 4 colors, which produces results that are the closest
+to the themes' default aesthetic:
+
+#+begin_src emacs-lisp
+(setq prism-num-faces 4)
+
+(prism-set-colors
+  :desaturations '(0) ; do not change---may lower the contrast ratio
+  :lightens '(0)      ; same
+  :colors (modus-themes-with-colors
+            (list fg-main
+                  cyan-alt-other
+                  magenta-alt-other
+                  magenta)))
+#+end_src
+
+If you need to apply desaturation and lightening, you can use what the
+{{{file(prism.el)}}} documentation recommends, like this (adapting to the
+examples with the 4, 8, 16 colors):
+
+#+begin_src emacs-lisp
+(prism-set-colors
+  :desaturations (cl-loop for i from 0 below 16 collect (* i 2.5))
+  :lightens (cl-loop for i from 0 below 16 collect (* i 2.5))
+  :colors (modus-themes-with-colors
+            (list fg-main
+                  cyan-alt-other
+                  magenta-alt-other
+                  magenta)))
+#+end_src
+
+** Note on company-mode overlay pop-up
+:properties:
+:custom_id: h:20cef8c4-d11f-4053-8b2c-2872925780b1
+:end:
+
+By default, the ~company-mode~ pop-up that lists completion candidates is
+drawn using an overlay.  This creates alignment issues every time it is
+placed above a piece of text that has a different height than the
+default.
+
+The solution recommended by the project's maintainer is to use an
+alternative front-end for drawing the pop-up which draws child frames
+instead of overlays.[fn::
+https://github.com/company-mode/company-mode/issues/1010][fn::
+https://github.com/tumashu/company-posframe/]
+
+** Note for ERC escaped color sequences
+:properties:
+:custom_id: h:98bdf319-1e32-4469-8a01-771200fba65c
+:end:
+
+The built-in IRC client ~erc~ has the ability to colorise any text using
+escape sequences that start with =^C= (inserted with {{{kbd(C-q C-c)}}}) and 
are
+followed by a number for the foreground and background.[fn:: This page
+explains the basics, though it is not specific to Emacs:
+https://www.mirc.com/colors.html] Possible numbers are 0-15, with the
+first entry being the foreground and the second the background,
+separated by a comma.  Like this =^C1,6=.  The minimum setup is this:
+
+#+begin_src emacs-lisp
+(add-to-list 'erc-modules 'irccontrols)
+(setq erc-interpret-controls-p t
+      erc-interpret-mirc-color t)
+#+end_src
+
+As this allows users the chance to make arbitrary combinations, it is
+impossible to guarantee a consistently high contrast ratio.  All we can
+we do is provide guidance on the combinations that satisfy the
+accessibility standard of the themes:
+
++ Modus Operandi :: Use foreground color 1 for all backgrounds from
+  2-15.  Like so: {{{kbd(C-q C-c1,N)}}} where =N= is the background.
+
++ Modus Vivendi :: Use foreground color 0 for all backgrounds from
+  2-13.  Use foreground =1= for backgrounds 14, 15.
+
+Colors 0 and 1 are white and black respectively.  So combine them
+together, if you must.
+
+** Note for powerline or spaceline
+:properties:
+:custom_id: h:9130a8ba-d8e3-41be-a58b-3cb1eb7b6d17
+:end:
+
+Both Powerline and Spaceline package users will likely need to use the
+command ~powerline-reset~ whenever they make changes to their themes
+and/or modeline setup.
+
+** Note on SHR colors
+:properties:
+:custom_id: h:4cc767dc-ffef-4c5c-9f10-82eb7b8921bf
+:end:
+
+Emacs' HTML rendering library ({{{file(shr.el)}}}) may need explicit
+configuration to respect the theme's colors instead of whatever
+specifications the webpage provides.
+
+Consult {{{kbd(C-h v shr-use-colors)}}}.
+
+** Note for Helm grep
+:properties:
+:custom_id: h:d28879a2-8e4b-4525-986e-14c0f873d229
+:end:
+
+There is one face from the Helm package that is meant to highlight the
+matches of a grep or grep-like command (=ag= or =ripgrep=).  It is
+~helm-grep-match~.  However, this face can only apply when the user does
+not pass =--color=always= as a command-line option for their command.
+
+Here is the docstring for that face, which is defined in the
+{{{file(helm-grep.el)}}} library (you can always visit the source code with
+{{{kbd(M-x find-library)}}}).
+
+#+begin_quote
+Face used to highlight grep matches.  Have no effect when grep backend
+use "--color="
+#+end_quote
+
+The user must either remove =--color= from the flags passed to the grep
+function, or explicitly use =--color=never= (or equivalent).  Helm
+provides user-facing customization options for controlling the grep
+function's parameters, such as ~helm-grep-default-command~ and
+~helm-grep-git-grep-command~.
+
+When =--color=always= is in effect, the grep output will use red text in
+bold letter forms to present the matching part in the list of
+candidates.  That style still meets the contrast ratio target of >= 7:1
+(accessibility standard WCAG AAA), because it draws the reference to
+ANSI color number 1 (red) from the already-supported array of
+~ansi-color-names-vector~.
+
+** Note on vc-annotate-background-mode
+:properties:
+:custom_id: h:5095cbd1-e17a-419c-93e8-951c186362a3
+:end:
+
+Due to the unique way ~vc-annotate~ ({{{kbd(C-x v g)}}}) applies colors, 
support
+for its background mode (~vc-annotate-background-mode~) is disabled at the
+theme level.
+
+Normally, such a drastic measure should not belong in a theme: assuming
+the user's preferences is bad practice.  However, it has been deemed
+necessary in the interest of preserving color contrast accessibility
+while still supporting a useful built-in tool.
+
+If there actually is a way to avoid such a course of action, without
+prejudice to the accessibility standard of this project, then please
+report as much or send patches 
([[#h:9c3cd842-14b7-44d7-84b2-a5c8bc3fc3b1][Contributing]]).
+
+** Note on pdf-tools link hints
+:properties:
+:custom_id: h:2659d13e-b1a5-416c-9a89-7c3ce3a76574
+:end:
+
+Hints are drawn by [[https://imagemagick.org/][ImageMagick]], not Emacs, i.e., 
ImageMagick doesn't
+know about the hint face unless you tell ImageMagick about it. By
+default, only the foreground and background color attributes are
+passed. The below snippet adds to those the various font attributes.  As
+it queries various faces, specifically ~pdf-links-read-link~ and the faces
+it inherits, it needs to be added to your initialization file after
+you've customized any faces.
+
+#+begin_src emacs-lisp
+(use-package pdf-links
+  :config
+  (let ((spec
+         (apply #'append
+                (mapcar
+                 (lambda (name)
+                   (list name
+                         (face-attribute 'pdf-links-read-link
+                                         name nil 'default)))
+                 '(:family :width :weight :slant)))))
+    (setq pdf-links-read-link-convert-commands
+          `("-density"    "96"
+            "-family"     ,(plist-get spec :family)
+            "-stretch"    ,(let* ((width (plist-get spec :width))
+                                  (name (symbol-name width)))
+                             (replace-regexp-in-string "-" ""
+                                                       (capitalize name)))
+            "-weight"     ,(pcase (plist-get spec :weight)
+                             ('ultra-light "Thin")
+                             ('extra-light "ExtraLight")
+                             ('light       "Light")
+                             ('semi-bold   "SemiBold")
+                             ('bold        "Bold")
+                             ('extra-bold  "ExtraBold")
+                             ('ultra-bold  "Black")
+                             (_weight      "Normal"))
+            "-style"      ,(pcase (plist-get spec :slant)
+                             ('italic  "Italic")
+                             ('oblique "Oblique")
+                             (_slant   "Normal"))
+            "-pointsize"  "%P"
+            "-undercolor" "%f"
+            "-fill"       "%b"
+            "-draw"       "text %X,%Y '%c'"))))
+#+end_src
+
+* Contributing
+:properties:
+:custom_id: h:9c3cd842-14b7-44d7-84b2-a5c8bc3fc3b1
+:end:
+
+This section documents the canonical sources of the themes and the ways
+in which you can contribute to their ongoing development.
+
+** Sources of the themes
+:properties:
+:custom_id: h:89504f1c-c9a1-4bd9-ab39-78fd0eddb47c
+:end:
+#+cindex: Sources of the themes
+
+The ~modus-operandi~ and ~modus-vivendi~ themes are built into Emacs.
+Currently they are in Emacs' git main branch (trunk), which is tracking
+the next development release target.
+
+The source code of the themes is 
[[https://gitlab.com/protesilaos/modus-themes/][available on Gitlab]], for the 
time
+being.  A [[https://github.com/protesilaos/modus-themes/][mirror on Github]] 
is also on offer.
+
+An HTML version of this manual is provided as an extension of the
+[[https://protesilaos.com/modus-themes/][author's personal website]] (does not 
rely on any non-free code).
+
+** Issues you can help with
+:properties:
+:custom_id: h:6536c8d5-3f98-43ab-a787-b94120e735e8
+:end:
+#+cindex: Contributing
+
+A few tasks you can help with:
+
++ Suggest refinements to packages that are covered.
++ Report packages not covered thus far.
++ Report bugs, inconsistencies, shortcomings.
++ Help expand the documentation of covered-but-not-styled packages.
++ Suggest refinements to the color palette.
++ Help expand this document or any other piece of documentation.
++ Merge requests for code refinements.
+
+[[#h:111773e2-f26f-4b68-8c4f-9794ca6b9633][Patches require copyright 
assignment to the FSF]].
+
+It is preferable that your feedback includes some screenshots, GIFs, or
+short videos, as well as further instructions to reproduce a given
+setup.  Though this is not a requirement.
+
+Whatever you do, bear in mind the overarching objective of the Modus
+themes: to keep a contrast ratio that is greater or equal to 7:1 between
+background and foreground colors.  If a compromise is ever necessary
+between aesthetics and accessibility, it shall always be made in the
+interest of the latter.
+
+** Patches require copyright assignment to the FSF
+:properties:
+:custom_id: h:111773e2-f26f-4b68-8c4f-9794ca6b9633
+:end:
+
+Code contributions are most welcome.  For any major edit (more than 15
+lines, or so, in aggregate per person), you need to make a copyright
+assignment to the Free Software Foundation.  This is necessary because
+the themes are part of the upstream Emacs distribution: the FSF must at
+all times be in a position to enforce the GNU General Public License.
+
+Copyright assignment is a simple process.  Check the request form below
+(please adapt it accordingly).  You must write an email to the address
+mentioned in the form and then wait for the FSF to send you a legal
+agreement.  Sign the document and file it back to them.  This could all
+happen via email and take about a week.  You are encouraged to go
+through this process.  You only need to do it once.  It will allow you
+to make contributions to Emacs in general.
+
+#+begin_example text
+Please email the following information to assign@gnu.org, and we
+will send you the assignment form for your past and future changes.
+
+Please use your full legal name (in ASCII characters) as the subject
+line of the message.
+----------------------------------------------------------------------
+REQUEST: SEND FORM FOR PAST AND FUTURE CHANGES
+
+[What is the name of the program or package you're contributing to?]
+
+GNU Emacs
+
+[Did you copy any files or text written by someone else in these changes?
+Even if that material is free software, we need to know about it.]
+
+Copied a few snippets from the same files I edited.  Their author,
+Protesilaos Stavrou, has already assigned copyright to the Free Software
+Foundation.
+
+[Do you have an employer who might have a basis to claim to own
+your changes?  Do you attend a school which might make such a claim?]
+
+
+[For the copyright registration, what country are you a citizen of?]
+
+
+[What year were you born?]
+
+
+[Please write your email address here.]
+
+
+[Please write your postal address here.]
+
+
+
+
+
+[Which files have you changed so far, and which new files have you written
+so far?]
+
+#+end_example
+
+* Acknowledgements
+:properties:
+:custom_id: h:95c3da23-217f-404e-b5f3-56c75760ebcf
+:end:
+#+cindex: Contributors
+
+The Modus themes are a collective effort.  Every bit of work matters.
+
++ Author/maintainer :: Protesilaos Stavrou.
+
++ Contributions to code or documentation :: Anders Johansson, Basil
+  L.{{{space()}}} Contovounesios, Carlo Zancanaro, Eli Zaretskii, Kostadin
+  Ninev, Madhavan Krishnan, Markus Beppler, Matthew Stevenson, Nicolas
+  De Jaeghere, Shreyas Ragavan, Stefan Kangas, Vincent Murphy, Xinglu
+  Chen.
+
++ Ideas and user feedback :: Aaron Jensen, Adam Spiers, Adrian Manea,
+  Alex Griffin, Alex Peitsinis, Alexey Shmalko, Alok Singh, Anders
+  Johansson, André Alexandre Gomes, Arif Rezai, Basil L.{{{space()}}}
+  Contovounesios, Burgess Chang, Christian Tietze, Christopher Dimech,
+  Damien Cassou, Daniel Mendler, Dario Gjorgjevski, David Edmondson,
+  Davor Rotim, Divan Santana, Gerry Agbobada, Gianluca Recchia, Gustavo
+  Barros, Hörmetjan Yiltiz, Ilja Kocken, Iris Garcia, Jeremy Friesen,
+  John Haman, Joshua O'Connor, Kevin Fleming, Kostadin Ninev, Len Trigg,
+  Manuel Uberti, Mark Burton, Markus Beppler, Michael Goldenberg, Morgan
+  Smith, Murilo Pereira, Nicolas De Jaeghere, Paul Poloskov, Pete
+  Kazmier, Peter Wu, Philip K., Pierre Téchoueyres, Roman Rudakov, Ryan
+  Phillips, Sam Kleinman, Shreyas Ragavan, Simon Pugnet, Tassilo Horn,
+  Thibaut Verron, Trey Merkley, Togan Muftuoglu, Toon Claes, Uri Sharf,
+  Utkarsh Singh, Vincent Foley.  As well as users: Ben, CsBigDataHub1,
+  Emacs Contrib, Eugene, Fourchaux, Fredrik, Moesasji, Nick, TheBlob42,
+  bepolymathe, doolio, fleimgruber, iSeeU, jixiuf, okamsn.
+
++ Packaging :: Basil L.{{{space()}}} Contovounesios, Eli Zaretskii, Glenn
+  Morris, Mauro Aranda, Richard Stallman, Stefan Kangas (core Emacs),
+  Stefan Monnier (GNU Elpa), André Alexandre Gomes, Dimakakos Dimos,
+  Morgan Smith, Nicolas Goaziou (Guix), Dhavan Vaidya (Debian).
+
++ Inspiration for certain features :: Bozhidar Batsov (zenburn-theme),
+  Fabrice Niessen (leuven-theme).
+
+Special thanks, in no particular order, to Manuel Uberti and Omar
+Antolín Camarena for their long time contributions and insightful
+commentary.
+
+* Meta
+:properties:
+:custom_id: h:13752581-4378-478c-af17-165b6e76bc1b
+:end:
+#+cindex: Development notes
+
+If you are curious about the principles that govern the development of
+this project read the essay 
[[https://protesilaos.com/codelog/2020-03-17-design-modus-themes-emacs/][On the 
design of the Modus themes]]
+(2020-03-17).
+
+Here are some more publications for those interested in the kind of work
+that goes into this project (sometimes the commits also include details
+of this sort):
+
++ 
[[https://protesilaos.com/codelog/2020-05-10-modus-operandi-palette-review/][Modus
 Operandi theme subtle palette review]] (2020-05-10)
++ 
[[https://protesilaos.com/codelog/2020-06-13-modus-vivendi-palette-review/][Modus
 Vivendi theme subtle palette review]] (2020-06-13)
++ 
[[https://protesilaos.com/codelog/2020-07-04-modus-themes-faint-colours/][Modus 
themes: new "faint syntax" option]] (2020-07-04)
++ 
[[https://protesilaos.com/codelog/2020-07-08-modus-themes-nuanced-colours/][Modus
 themes: major review of "nuanced" colours]] (2020-07-08)
++ 
[[https://protesilaos.com/codelog/2020-09-14-modus-themes-review-blues/][Modus 
themes: review of blue colours]] (2020-09-14)
++ 
[[https://protesilaos.com/codelog/2020-12-27-modus-themes-review-rainbow-delimiters/][Modus
 themes: review rainbow-delimiters faces]] (2020-12-27)
++ 
[[https://protesilaos.com/codelog/2021-01-11-modus-themes-review-select-faint-colours/][Modus
 themes: review of select "faint" colours]] (2021-01-11)
++ 
[[https://protesilaos.com/codelog/2021-02-25-modus-themes-diffs-deuteranopia/][The
 Modus themes now cover deuteranopia in diffs]] (2021-02-25)
+
+And here are the canonical sources of this project's documentation:
+
++ Manual :: <https://protesilaos.com/modus-themes>
++ Change Log :: <https://protesilaos.com/modus-themes-changelog>
++ Screenshots :: <https://protesilaos.com/modus-themes-pictures>
+
+* GNU Free Documentation License
+:properties:
+:appendix: t
+:custom_id: h:3077c3d2-7f90-4228-8f0a-73124f4026f6
+:end:
+
+#+texinfo: @include doclicense.texi
+
+#+begin_export html
+
+                GNU Free Documentation License
+                 Version 1.3, 3 November 2008
+
+
+ Copyright (C) 2000, 2001, 2002, 2007, 2008 Free Software Foundation, Inc.
+     <https://fsf.org/>
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+0. PREAMBLE
+
+The purpose of this License is to make a manual, textbook, or other
+functional and useful document "free" in the sense of freedom: to
+assure everyone the effective freedom to copy and redistribute it,
+with or without modifying it, either commercially or noncommercially.
+Secondarily, this License preserves for the author and publisher a way
+to get credit for their work, while not being considered responsible
+for modifications made by others.
+
+This License is a kind of "copyleft", which means that derivative
+works of the document must themselves be free in the same sense.  It
+complements the GNU General Public License, which is a copyleft
+license designed for free software.
+
+We have designed this License in order to use it for manuals for free
+software, because free software needs free documentation: a free
+program should come with manuals providing the same freedoms that the
+software does.  But this License is not limited to software manuals;
+it can be used for any textual work, regardless of subject matter or
+whether it is published as a printed book.  We recommend this License
+principally for works whose purpose is instruction or reference.
+
+
+1. APPLICABILITY AND DEFINITIONS
+
+This License applies to any manual or other work, in any medium, that
+contains a notice placed by the copyright holder saying it can be
+distributed under the terms of this License.  Such a notice grants a
+world-wide, royalty-free license, unlimited in duration, to use that
+work under the conditions stated herein.  The "Document", below,
+refers to any such manual or work.  Any member of the public is a
+licensee, and is addressed as "you".  You accept the license if you
+copy, modify or distribute the work in a way requiring permission
+under copyright law.
+
+A "Modified Version" of the Document means any work containing the
+Document or a portion of it, either copied verbatim, or with
+modifications and/or translated into another language.
+
+A "Secondary Section" is a named appendix or a front-matter section of
+the Document that deals exclusively with the relationship of the
+publishers or authors of the Document to the Document's overall
+subject (or to related matters) and contains nothing that could fall
+directly within that overall subject.  (Thus, if the Document is in
+part a textbook of mathematics, a Secondary Section may not explain
+any mathematics.)  The relationship could be a matter of historical
+connection with the subject or with related matters, or of legal,
+commercial, philosophical, ethical or political position regarding
+them.
+
+The "Invariant Sections" are certain Secondary Sections whose titles
+are designated, as being those of Invariant Sections, in the notice
+that says that the Document is released under this License.  If a
+section does not fit the above definition of Secondary then it is not
+allowed to be designated as Invariant.  The Document may contain zero
+Invariant Sections.  If the Document does not identify any Invariant
+Sections then there are none.
+
+The "Cover Texts" are certain short passages of text that are listed,
+as Front-Cover Texts or Back-Cover Texts, in the notice that says that
+the Document is released under this License.  A Front-Cover Text may
+be at most 5 words, and a Back-Cover Text may be at most 25 words.
+
+A "Transparent" copy of the Document means a machine-readable copy,
+represented in a format whose specification is available to the
+general public, that is suitable for revising the document
+straightforwardly with generic text editors or (for images composed of
+pixels) generic paint programs or (for drawings) some widely available
+drawing editor, and that is suitable for input to text formatters or
+for automatic translation to a variety of formats suitable for input
+to text formatters.  A copy made in an otherwise Transparent file
+format whose markup, or absence of markup, has been arranged to thwart
+or discourage subsequent modification by readers is not Transparent.
+An image format is not Transparent if used for any substantial amount
+of text.  A copy that is not "Transparent" is called "Opaque".
+
+Examples of suitable formats for Transparent copies include plain
+ASCII without markup, Texinfo input format, LaTeX input format, SGML
+or XML using a publicly available DTD, and standard-conforming simple
+HTML, PostScript or PDF designed for human modification.  Examples of
+transparent image formats include PNG, XCF and JPG.  Opaque formats
+include proprietary formats that can be read and edited only by
+proprietary word processors, SGML or XML for which the DTD and/or
+processing tools are not generally available, and the
+machine-generated HTML, PostScript or PDF produced by some word
+processors for output purposes only.
+
+The "Title Page" means, for a printed book, the title page itself,
+plus such following pages as are needed to hold, legibly, the material
+this License requires to appear in the title page.  For works in
+formats which do not have any title page as such, "Title Page" means
+the text near the most prominent appearance of the work's title,
+preceding the beginning of the body of the text.
+
+The "publisher" means any person or entity that distributes copies of
+the Document to the public.
+
+A section "Entitled XYZ" means a named subunit of the Document whose
+title either is precisely XYZ or contains XYZ in parentheses following
+text that translates XYZ in another language.  (Here XYZ stands for a
+specific section name mentioned below, such as "Acknowledgements",
+"Dedications", "Endorsements", or "History".)  To "Preserve the Title"
+of such a section when you modify the Document means that it remains a
+section "Entitled XYZ" according to this definition.
+
+The Document may include Warranty Disclaimers next to the notice which
+states that this License applies to the Document.  These Warranty
+Disclaimers are considered to be included by reference in this
+License, but only as regards disclaiming warranties: any other
+implication that these Warranty Disclaimers may have is void and has
+no effect on the meaning of this License.
+
+2. VERBATIM COPYING
+
+You may copy and distribute the Document in any medium, either
+commercially or noncommercially, provided that this License, the
+copyright notices, and the license notice saying this License applies
+to the Document are reproduced in all copies, and that you add no
+other conditions whatsoever to those of this License.  You may not use
+technical measures to obstruct or control the reading or further
+copying of the copies you make or distribute.  However, you may accept
+compensation in exchange for copies.  If you distribute a large enough
+number of copies you must also follow the conditions in section 3.
+
+You may also lend copies, under the same conditions stated above, and
+you may publicly display copies.
+
+
+3. COPYING IN QUANTITY
+
+If you publish printed copies (or copies in media that commonly have
+printed covers) of the Document, numbering more than 100, and the
+Document's license notice requires Cover Texts, you must enclose the
+copies in covers that carry, clearly and legibly, all these Cover
+Texts: Front-Cover Texts on the front cover, and Back-Cover Texts on
+the back cover.  Both covers must also clearly and legibly identify
+you as the publisher of these copies.  The front cover must present
+the full title with all words of the title equally prominent and
+visible.  You may add other material on the covers in addition.
+Copying with changes limited to the covers, as long as they preserve
+the title of the Document and satisfy these conditions, can be treated
+as verbatim copying in other respects.
+
+If the required texts for either cover are too voluminous to fit
+legibly, you should put the first ones listed (as many as fit
+reasonably) on the actual cover, and continue the rest onto adjacent
+pages.
+
+If you publish or distribute Opaque copies of the Document numbering
+more than 100, you must either include a machine-readable Transparent
+copy along with each Opaque copy, or state in or with each Opaque copy
+a computer-network location from which the general network-using
+public has access to download using public-standard network protocols
+a complete Transparent copy of the Document, free of added material.
+If you use the latter option, you must take reasonably prudent steps,
+when you begin distribution of Opaque copies in quantity, to ensure
+that this Transparent copy will remain thus accessible at the stated
+location until at least one year after the last time you distribute an
+Opaque copy (directly or through your agents or retailers) of that
+edition to the public.
+
+It is requested, but not required, that you contact the authors of the
+Document well before redistributing any large number of copies, to
+give them a chance to provide you with an updated version of the
+Document.
+
+
+4. MODIFICATIONS
+
+You may copy and distribute a Modified Version of the Document under
+the conditions of sections 2 and 3 above, provided that you release
+the Modified Version under precisely this License, with the Modified
+Version filling the role of the Document, thus licensing distribution
+and modification of the Modified Version to whoever possesses a copy
+of it.  In addition, you must do these things in the Modified Version:
+
+A. Use in the Title Page (and on the covers, if any) a title distinct
+   from that of the Document, and from those of previous versions
+   (which should, if there were any, be listed in the History section
+   of the Document).  You may use the same title as a previous version
+   if the original publisher of that version gives permission.
+B. List on the Title Page, as authors, one or more persons or entities
+   responsible for authorship of the modifications in the Modified
+   Version, together with at least five of the principal authors of the
+   Document (all of its principal authors, if it has fewer than five),
+   unless they release you from this requirement.
+C. State on the Title page the name of the publisher of the
+   Modified Version, as the publisher.
+D. Preserve all the copyright notices of the Document.
+E. Add an appropriate copyright notice for your modifications
+   adjacent to the other copyright notices.
+F. Include, immediately after the copyright notices, a license notice
+   giving the public permission to use the Modified Version under the
+   terms of this License, in the form shown in the Addendum below.
+G. Preserve in that license notice the full lists of Invariant Sections
+   and required Cover Texts given in the Document's license notice.
+H. Include an unaltered copy of this License.
+I. Preserve the section Entitled "History", Preserve its Title, and add
+   to it an item stating at least the title, year, new authors, and
+   publisher of the Modified Version as given on the Title Page.  If
+   there is no section Entitled "History" in the Document, create one
+   stating the title, year, authors, and publisher of the Document as
+   given on its Title Page, then add an item describing the Modified
+   Version as stated in the previous sentence.
+J. Preserve the network location, if any, given in the Document for
+   public access to a Transparent copy of the Document, and likewise
+   the network locations given in the Document for previous versions
+   it was based on.  These may be placed in the "History" section.
+   You may omit a network location for a work that was published at
+   least four years before the Document itself, or if the original
+   publisher of the version it refers to gives permission.
+K. For any section Entitled "Acknowledgements" or "Dedications",
+   Preserve the Title of the section, and preserve in the section all
+   the substance and tone of each of the contributor acknowledgements
+   and/or dedications given therein.
+L. Preserve all the Invariant Sections of the Document,
+   unaltered in their text and in their titles.  Section numbers
+   or the equivalent are not considered part of the section titles.
+M. Delete any section Entitled "Endorsements".  Such a section
+   may not be included in the Modified Version.
+N. Do not retitle any existing section to be Entitled "Endorsements"
+   or to conflict in title with any Invariant Section.
+O. Preserve any Warranty Disclaimers.
+
+If the Modified Version includes new front-matter sections or
+appendices that qualify as Secondary Sections and contain no material
+copied from the Document, you may at your option designate some or all
+of these sections as invariant.  To do this, add their titles to the
+list of Invariant Sections in the Modified Version's license notice.
+These titles must be distinct from any other section titles.
+
+You may add a section Entitled "Endorsements", provided it contains
+nothing but endorsements of your Modified Version by various
+parties--for example, statements of peer review or that the text has
+been approved by an organization as the authoritative definition of a
+standard.
+
+You may add a passage of up to five words as a Front-Cover Text, and a
+passage of up to 25 words as a Back-Cover Text, to the end of the list
+of Cover Texts in the Modified Version.  Only one passage of
+Front-Cover Text and one of Back-Cover Text may be added by (or
+through arrangements made by) any one entity.  If the Document already
+includes a cover text for the same cover, previously added by you or
+by arrangement made by the same entity you are acting on behalf of,
+you may not add another; but you may replace the old one, on explicit
+permission from the previous publisher that added the old one.
+
+The author(s) and publisher(s) of the Document do not by this License
+give permission to use their names for publicity for or to assert or
+imply endorsement of any Modified Version.
+
+
+5. COMBINING DOCUMENTS
+
+You may combine the Document with other documents released under this
+License, under the terms defined in section 4 above for modified
+versions, provided that you include in the combination all of the
+Invariant Sections of all of the original documents, unmodified, and
+list them all as Invariant Sections of your combined work in its
+license notice, and that you preserve all their Warranty Disclaimers.
+
+The combined work need only contain one copy of this License, and
+multiple identical Invariant Sections may be replaced with a single
+copy.  If there are multiple Invariant Sections with the same name but
+different contents, make the title of each such section unique by
+adding at the end of it, in parentheses, the name of the original
+author or publisher of that section if known, or else a unique number.
+Make the same adjustment to the section titles in the list of
+Invariant Sections in the license notice of the combined work.
+
+In the combination, you must combine any sections Entitled "History"
+in the various original documents, forming one section Entitled
+"History"; likewise combine any sections Entitled "Acknowledgements",
+and any sections Entitled "Dedications".  You must delete all sections
+Entitled "Endorsements".
+
+
+6. COLLECTIONS OF DOCUMENTS
+
+You may make a collection consisting of the Document and other
+documents released under this License, and replace the individual
+copies of this License in the various documents with a single copy
+that is included in the collection, provided that you follow the rules
+of this License for verbatim copying of each of the documents in all
+other respects.
+
+You may extract a single document from such a collection, and
+distribute it individually under this License, provided you insert a
+copy of this License into the extracted document, and follow this
+License in all other respects regarding verbatim copying of that
+document.
+
+
+7. AGGREGATION WITH INDEPENDENT WORKS
+
+A compilation of the Document or its derivatives with other separate
+and independent documents or works, in or on a volume of a storage or
+distribution medium, is called an "aggregate" if the copyright
+resulting from the compilation is not used to limit the legal rights
+of the compilation's users beyond what the individual works permit.
+When the Document is included in an aggregate, this License does not
+apply to the other works in the aggregate which are not themselves
+derivative works of the Document.
+
+If the Cover Text requirement of section 3 is applicable to these
+copies of the Document, then if the Document is less than one half of
+the entire aggregate, the Document's Cover Texts may be placed on
+covers that bracket the Document within the aggregate, or the
+electronic equivalent of covers if the Document is in electronic form.
+Otherwise they must appear on printed covers that bracket the whole
+aggregate.
+
+
+8. TRANSLATION
+
+Translation is considered a kind of modification, so you may
+distribute translations of the Document under the terms of section 4.
+Replacing Invariant Sections with translations requires special
+permission from their copyright holders, but you may include
+translations of some or all Invariant Sections in addition to the
+original versions of these Invariant Sections.  You may include a
+translation of this License, and all the license notices in the
+Document, and any Warranty Disclaimers, provided that you also include
+the original English version of this License and the original versions
+of those notices and disclaimers.  In case of a disagreement between
+the translation and the original version of this License or a notice
+or disclaimer, the original version will prevail.
+
+If a section in the Document is Entitled "Acknowledgements",
+"Dedications", or "History", the requirement (section 4) to Preserve
+its Title (section 1) will typically require changing the actual
+title.
+
+
+9. TERMINATION
+
+You may not copy, modify, sublicense, or distribute the Document
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense, or distribute it is void, and
+will automatically terminate your rights under this License.
+
+However, if you cease all violation of this License, then your license
+from a particular copyright holder is reinstated (a) provisionally,
+unless and until the copyright holder explicitly and finally
+terminates your license, and (b) permanently, if the copyright holder
+fails to notify you of the violation by some reasonable means prior to
+60 days after the cessation.
+
+Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+
+Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License.  If your rights have been terminated and not permanently
+reinstated, receipt of a copy of some or all of the same material does
+not give you any rights to use it.
+
+
+10. FUTURE REVISIONS OF THIS LICENSE
+
+The Free Software Foundation may publish new, revised versions of the
+GNU Free Documentation License from time to time.  Such new versions
+will be similar in spirit to the present version, but may differ in
+detail to address new problems or concerns.  See
+https://www.gnu.org/licenses/.
+
+Each version of the License is given a distinguishing version number.
+If the Document specifies that a particular numbered version of this
+License "or any later version" applies to it, you have the option of
+following the terms and conditions either of that specified version or
+of any later version that has been published (not as a draft) by the
+Free Software Foundation.  If the Document does not specify a version
+number of this License, you may choose any version ever published (not
+as a draft) by the Free Software Foundation.  If the Document
+specifies that a proxy can decide which future versions of this
+License can be used, that proxy's public statement of acceptance of a
+version permanently authorizes you to choose that version for the
+Document.
+
+11. RELICENSING
+
+"Massive Multiauthor Collaboration Site" (or "MMC Site") means any
+World Wide Web server that publishes copyrightable works and also
+provides prominent facilities for anybody to edit those works.  A
+public wiki that anybody can edit is an example of such a server.  A
+"Massive Multiauthor Collaboration" (or "MMC") contained in the site
+means any set of copyrightable works thus published on the MMC site.
+
+"CC-BY-SA" means the Creative Commons Attribution-Share Alike 3.0
+license published by Creative Commons Corporation, a not-for-profit
+corporation with a principal place of business in San Francisco,
+California, as well as future copyleft versions of that license
+published by that same organization.
+
+"Incorporate" means to publish or republish a Document, in whole or in
+part, as part of another Document.
+
+An MMC is "eligible for relicensing" if it is licensed under this
+License, and if all works that were first published under this License
+somewhere other than this MMC, and subsequently incorporated in whole or
+in part into the MMC, (1) had no cover texts or invariant sections, and
+(2) were thus incorporated prior to November 1, 2008.
+
+The operator of an MMC Site may republish an MMC contained in the site
+under CC-BY-SA on the same site at any time before August 1, 2009,
+provided the MMC is eligible for relicensing.
+
+
+ADDENDUM: How to use this License for your documents
+
+To use this License in a document you have written, include a copy of
+the License in the document and put the following copyright and
+license notices just after the title page:
+
+    Copyright (c)  YEAR  YOUR NAME.
+    Permission is granted to copy, distribute and/or modify this document
+    under the terms of the GNU Free Documentation License, Version 1.3
+    or any later version published by the Free Software Foundation;
+    with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts.
+    A copy of the license is included in the section entitled "GNU
+    Free Documentation License".
+
+If you have Invariant Sections, Front-Cover Texts and Back-Cover Texts,
+replace the "with...Texts." line with this:
+
+    with the Invariant Sections being LIST THEIR TITLES, with the
+    Front-Cover Texts being LIST, and with the Back-Cover Texts being LIST.
+
+If you have Invariant Sections without Cover Texts, or some other
+combination of the three, merge those two alternatives to suit the
+situation.
+
+If your document contains nontrivial examples of program code, we
+recommend releasing these examples in parallel under your choice of
+free software license, such as the GNU General Public License,
+to permit their use in free software.
+#+end_export
+
+#+html: <!--
+
+* Indices
+:properties:
+:custom_id: h:55104b26-8e94-46cf-9975-43ea00316489
+:end:
+
+** Function index
+:properties:
+:index: fn
+:custom_id: h:6bec5005-529c-4521-ae05-3d990baffb5b
+:end:
+
+** Variable index
+:properties:
+:index: vr
+:custom_id: h:16ad8df6-b015-40a9-9259-03d4f7a23ee4
+:end:
+
+** Concept index
+:properties:
+:index: cp
+:custom_id: h:6aa7a656-884b-4c39-b759-087e412eec13
+:end:
+
+#+html: -->
diff --git a/doc/misc/modus-themes.texi b/doc/misc/modus-themes.texi
deleted file mode 100644
index b16aece..0000000
--- a/doc/misc/modus-themes.texi
+++ /dev/null
@@ -1,2834 +0,0 @@
-\input texinfo    @c -*- texinfo -*-
-@c %**start of header
-@setfilename ../../info/modus-themes.info
-@settitle Modus themes for GNU Emacs
-@include docstyle.texi
-@documentencoding UTF-8
-@documentlanguage en
-@c %**end of header
-
-@include emacsver.texi
-
-@dircategory Emacs misc features
-@direntry
-* Modus Themes: (modus-themes). Highly accessible themes (WCAG AAA).
-@end direntry
-
-@finalout
-@titlepage
-@title Modus themes for GNU Emacs
-@author Protesilaos Stavrou (@email{info@@protesilaos.com})
-@end titlepage
-
-@ifnottex
-@node Top
-@top Modus themes for GNU Emacs
-
-This manual, written by Protesilaos Stavrou, describes the customization
-options for the @samp{modus-operandi} and @samp{modus-vivendi} themes, and 
provides
-every other piece of information pertinent to them.
-
-The documentation furnished herein corresponds to version 0.13.0,
-released on 2020-10-08.  Any reference to a newer feature which does
-not yet form part of the latest tagged commit, is explicitly marked as
-such.
-
-Copyright (C) 2020--2021 Free Software Foundation, Inc.
-
-@quotation
-Permission is granted to copy, distribute and/or modify this
-document under the terms of the GNU Free Documentation License,
-Version 1.3 or any later version published by the Free Software
-Foundation; with no Invariant Sections, with no Front-Cover Texts,
-and with no Back-Cover Texts.
-
-@end quotation
-
-@end ifnottex
-
-@menu
-* Overview::
-* Installation::
-* Enable and load::
-* Customization Options::
-* Advanced customization (do-it-yourself)::
-* Face coverage::
-* Notes for individual packages::
-* Contributing::
-* Acknowledgements::
-* Meta::
-* External projects (ports)::
-* GNU Free Documentation License::
-
-@detailmenu
---- The Detailed Node Listing ---
-
-Overview
-
-* How do the themes look like::
-* Learn about the latest changes::
-
-Installation
-
-* Install from the archives::
-* Install on GNU/Linux::
-
-Install on GNU/Linux
-
-* Debian 11 Bullseye::
-* GNU Guix::
-
-Enable and load
-
-* Load automatically::
-* Load at a given time or at sunset/sunrise::
-* Toggle between the themes on demand::
-* Configure options prior to loading::
-
-Customization Options
-
-* Bold constructs::              Toggle bold constructs in code
-* Slanted constructs::           Toggle slanted constructs (italics) in code
-* Syntax highlighting::          Toggle subtle coloration in programming modes
-* No mixed fonts::               Toggle mixing of font families
-* Link underline::               Toggle underlined text in links
-* Command prompts::              Choose among plain, subtle, or intense prompts
-* Mode line::                    Choose among plain, three-dimension, or 
moody-compliant styles
-* Completion UIs::               Choose among standard, moderate, or 
opinionated looks
-* Fringes::                      Choose among plain, subtle, or intense fringe 
visibility
-* Line highlighting::            Toggle intense style for current line 
highlighting
-* Matching parentheses::         Toggle intense style for matching 
delimiters/parentheses
-* Diffs::                        Choose among intense, desaturated, or 
text-only diffs
-* Org mode blocks::              Choose among plain, greyscale, or rainbow 
styles
-* Heading styles::               Choose among several styles, also per heading 
level
-* Scaled headings::              Toggle scaling of headings
-* Headings' font::               Toggle proportionately spaced fonts in 
headings
-
-Scaled headings
-
-* Scaled heading sizes::         Specify rate of increase for scaled headings
-
-Advanced customization (do-it-yourself)
-
-* Tweak colors (DIY)::           Declare your own palette overrides
-* Font configs (DIY)::           Optimise for mixed typeface buffers
-* Org user faces (DIY)::         Extend styles for org-mode keywords and 
priorities
-
-Face coverage
-
-* Supported packages::           Full list of covered face groups
-* Covered indirectly::
-* Will NOT be supported::
-
-Notes for individual packages
-
-* Note on company-mode overlay pop-up::
-* Note for ERC escaped color sequences::
-* Note for powerline or spaceline::
-* Note on shr colors::
-* Note for Helm grep::
-* Note on vc-annotate-background-mode::
-
-Contributing
-
-* Sources of the themes::
-* Issues you can help with::
-* Merge requests::               Legal considerations for code patches
-
-@end detailmenu
-@end menu
-
-@node Overview
-@chapter Overview
-
-The Modus themes are designed for accessible readability.  They conform
-with the highest standard for color contrast between any given
-combination of background and foreground values.  This corresponds to
-the WCAG AAA standard, which specifies a minimum rate of distance in
-relative luminance of 7:1.
-
-Modus Operandi (@samp{modus-operandi}) is a light theme, while Modus Vivendi
-(@samp{modus-vivendi}) is dark.  Each theme's color palette is designed to
-meet the needs of the numerous interfaces that are possible in the Emacs
-computing environment.
-
-The overarching objective of this project is to always offer accessible
-color combinations.  There shall never be a compromise on this
-principle.  If there arises an inescapable trade-off between readability
-and stylistic considerations, we will always opt for the former.
-
-To ensure that users have a consistently accessible experience, the
-themes strive to achieve as close to full face coverage as possible
-(see @ref{Face coverage}).
-
-Starting with version 0.12.0 and onwards, the themes are built into GNU
-Emacs (current version is 0.13.0).
-
-@menu
-* How do the themes look like::
-* Learn about the latest changes::
-@end menu
-
-@node How do the themes look like
-@section How do the themes look like
-
-Check the web page with @uref{https://protesilaos.com/modus-themes-pictures/, 
the screen shots}.  There are lots of scenarios on
-display that draw attention to details and important aspects in the
-design of the themes.  They also showcase the numerous customization
-options.
-
-@xref{Customization Options}.
-
-@node Learn about the latest changes
-@section Learn about the latest changes
-
-Please refer to the @uref{https://protesilaos.com/modus-themes-changelog, web 
page with the change log}.  It is comprehensive
-and covers everything that goes into every tagged release of the themes.
-
-@node Installation
-@chapter Installation
-
-The Modus themes are distributed with Emacs starting with version 28.1.
-On older versions of Emacs, they can be installed using Emacs' package
-manager or manually from their code repository.
-
-Modus Operandi (light theme) and Modus Vivendi (dark) are normally
-distributed as standalone packages in Emacs-specific archives.  There
-also exist packages for GNU/Linux distributions.
-
-@menu
-* Install from the archives::
-* Install on GNU/Linux::
-@end menu
-
-@node Install from the archives
-@section Install from the archives
-
-@samp{modus-operandi-theme} and @samp{modus-vivendi-theme} are
-available from the GNU ELPA archive, which is configured by default.
-
-Prior to querying any package archive, make sure to have updated the
-index, with @samp{M-x package-refresh-contents}.  Then all you need to do is
-type @samp{M-x package-install} and specify the theme of your choice.
-
-@node Install on GNU/Linux
-@section Install on GNU/Linux
-
-The themes are also available from the archives of some GNU/Linux
-distributions.  These should correspond to a tagged release rather than
-building directly from the latest Git commit.  It all depends on the
-distro's packaging policies.
-
-@menu
-* Debian 11 Bullseye::
-* GNU Guix::
-@end menu
-
-@node Debian 11 Bullseye
-@subsection Debian 11 Bullseye
-
-The two themes are distributed as a single package for Debian and its
-derivatives.  Currently in the unstable and testing suites and should be
-available in time for Debian 11 Bullseye (next stable).
-
-Get them with:
-
-@example
-sudo apt install elpa-modus-themes
-@end example
-
-@node GNU Guix
-@subsection GNU Guix
-
-Users of either the Guix System (the distro) or just Guix (the package
-manager) can get each theme as a standalone package.
-
-@example
-guix package -i emacs-modus-operandi-theme
-@end example
-
-And/or:
-
-@example
-guix package -i emacs-modus-vivendi-theme
-@end example
-
-@node Enable and load
-@chapter Enable and load
-
-This section documents how to load the theme of your choice and how to
-further control its initialization.  It also includes some sample code
-snippets that could help you in the task, especially if you intend to
-use both Modus Operandi and Modus Vivendi.
-
-@menu
-* Load automatically::
-* Load at a given time or at sunset/sunrise::
-* Toggle between the themes on demand::
-* Configure options prior to loading::
-@end menu
-
-@node Load automatically
-@section Load automatically
-
-A simple way to load the theme from your Emacs initialization file is to
-include either of the following expressions:
-
-@lisp
-(load-theme 'modus-operandi t)          ; Light theme
-(load-theme 'modus-vivendi t)           ; Dark theme
-@end lisp
-
-Make sure to remove any other theme that is being loaded, otherwise you
-might run into unexpected issues.
-
-Note that you can always @samp{M-x disable-theme} and specify an item.  The
-command does exactly what its name suggests.  To deactivate all enabled
-themes at once, in case you have multiple of them enabled, you may
-evaluate the expression:
-
-@lisp
-(mapc #'disable-theme custom-enabled-themes)
-@end lisp
-
-@node Load at a given time or at sunset/sunrise
-@section Load at a given time or at sunset/sunrise
-
-It is possible to schedule a time during the day at or after which a
-given theme will be loaded.@footnote{Contributed on Reddit by user @samp{b3n}
-@uref{https://www.reddit.com/r/emacs/comments/gdtqov/weekly_tipstricketc_thread/fq9186h/}.}
-
-@lisp
-;; Light for the day
-(load-theme 'modus-operandi t t)
-(run-at-time "05:00" (* 60 60 24)
-             (lambda ()
-               (enable-theme 'modus-operandi)))
-
-;; Dark for the night
-(load-theme 'modus-vivendi t t)
-(run-at-time "21:00" (* 60 60 24)
-             (lambda ()
-               (enable-theme 'modus-vivendi)))
-@end lisp
-
-A modified version of the above technique is to use the sunrise and
-sunset as references, instead of specifying a fixed hour 
value.@footnote{Contributed directly by André Alexandre Gomes 
@uref{https://gitlab.com/aadcg}.}
-If you set @samp{calendar-latitude} and @samp{calendar-longitude} (defined in 
the
-built-in @samp{solar.el} library---read it with @samp{M-x find-library}), you 
can
-automatically switch between both themes at the appropriate time-of-day.
-Note that @emph{those calendar variables need to be set before loading the
-themes}.
-
-@lisp
-;; Define coordinates
-(setq calendar-latitude 35.17
-      calendar-longitude 33.36)
-
-;; Light at sunrise
-(load-theme 'modus-operandi t t)
-(run-at-time (nth 1 (split-string (sunrise-sunset)))
-             (* 60 60 24)
-             (lambda ()
-               (enable-theme 'modus-operandi)))
-
-;; Dark at sunset
-(load-theme 'modus-vivendi t t)
-(run-at-time (nth 4 (split-string (sunrise-sunset)))
-             (* 60 60 24)
-             (lambda ()
-               (enable-theme 'modus-vivendi)))
-@end lisp
-
-For the sake of completeness, the @samp{load-theme} call in these snippets is
-slightly different than the one shown in @ref{Load automatically}, because it
-does not enable the theme directly: the subsequent @samp{enable-theme} does
-that when needed.
-
-@node Toggle between the themes on demand
-@section Toggle between the themes on demand
-
-With both themes available, it is possible to design a simple command to
-switch between them on demand.
-
-@lisp
-(defun modus-themes-toggle ()
-  "Toggle between `modus-operandi' and `modus-vivendi' themes."
-  (interactive)
-  (if (eq (car custom-enabled-themes) 'modus-operandi)
-      (progn
-        (disable-theme 'modus-operandi)
-        (load-theme 'modus-vivendi t))
-    (disable-theme 'modus-vivendi)
-    (load-theme 'modus-operandi t)))
-@end lisp
-
-You could use @samp{(mapc #'disable-theme custom-enabled-themes)} instead of
-disabling a single target, but you get the idea.
-
-@node Configure options prior to loading
-@section Configure options prior to loading
-
-If you plan to use both themes and wish to apply styles consistently
-(see @ref{Customization Options}), you could define wrapper functions around
-the standard @samp{load-theme} command.  These extend the simple function we
-presented in @ref{Toggle between the themes on demand}.
-
-Here is a comprehensive setup (the values assigned to the variables are
-just for the sake of this demonstration):@footnote{The @samp{defmacro} and 
@samp{dolist}
-method were contributed on Reddit by user @samp{b3n},
-@uref{https://www.reddit.com/r/emacs/comments/gqsz8u/weekly_tipstricketc_thread/fsfakhg/}.}
-
-@lisp
-(defmacro modus-themes-format-sexp (sexp &rest objects)
-  `(eval (read (format ,(format "%S" sexp) ,@@objects))))
-
-(dolist (theme '("operandi" "vivendi"))
-  (modus-themes-format-sexp
-   (defun modus-%1$s-theme-load ()
-     (setq modus-%1$s-theme-slanted-constructs t
-           modus-%1$s-theme-bold-constructs t
-           modus-%1$s-theme-fringes 'subtle ; @{nil,'subtle,'intense@}
-           modus-%1$s-theme-mode-line '3d ; @{nil,'3d,'moody@}
-           modus-%1$s-theme-faint-syntax nil
-           modus-%1$s-theme-intense-hl-line nil
-           modus-%1$s-theme-intense-paren-match nil
-           modus-%1$s-theme-no-link-underline t
-           modus-%1$s-theme-no-mixed-fonts nil
-           modus-%1$s-theme-prompts nil ; @{nil,'subtle,'intense@}
-           modus-%1$s-theme-completions 'moderate ; 
@{nil,'moderate,'opinionated@}
-           modus-%1$s-theme-diffs nil ; @{nil,'desaturated,'fg-only@}
-           modus-%1$s-theme-org-blocks 'greyscale ; @{nil,'greyscale,'rainbow@}
-           modus-%1$s-theme-headings  ; Read further below in the manual for 
this one
-           '((1 . section)
-             (2 . line)
-             (t . rainbow-line-no-bold))
-           modus-%1$s-theme-variable-pitch-headings nil
-           modus-%1$s-theme-scale-headings t
-           modus-%1$s-theme-scale-1 1.1
-           modus-%1$s-theme-scale-2 1.15
-           modus-%1$s-theme-scale-3 1.21
-           modus-%1$s-theme-scale-4 1.27
-           modus-%1$s-theme-scale-5 1.33)
-     (load-theme 'modus-%1$s t))
-   theme))
-
-(defun modus-themes-toggle ()
-  "Toggle between `modus-operandi' and `modus-vivendi' themes."
-  (interactive)
-  (if (eq (car custom-enabled-themes) 'modus-operandi)
-      (progn
-        (disable-theme 'modus-operandi)
-        (modus-vivendi-theme-load))
-    (disable-theme 'modus-vivendi)
-    (modus-operandi-theme-load)))
-@end lisp
-
-@node Customization Options
-@chapter Customization Options
-
-The Modus themes are highly configurable, though they should work well
-without any further tweaks.
-
-By default, all customization options are set to @samp{nil}.
-
-All customization options need to be evaluated before loading their
-theme (@pxref{Enable and load}).
-
-@menu
-* Bold constructs::              Toggle bold constructs in code
-* Slanted constructs::           Toggle slanted constructs (italics) in code
-* Syntax highlighting::          Toggle subtle coloration in programming modes
-* No mixed fonts::               Toggle mixing of font families
-* Link underline::               Toggle underlined text in links
-* Command prompts::              Choose among plain, subtle, or intense prompts
-* Mode line::                    Choose among plain, three-dimension, or 
moody-compliant styles
-* Completion UIs::               Choose among standard, moderate, or 
opinionated looks
-* Fringes::                      Choose among plain, subtle, or intense fringe 
visibility
-* Line highlighting::            Toggle intense style for current line 
highlighting
-* Matching parentheses::         Toggle intense style for matching 
delimiters/parentheses
-* Diffs::                        Choose among intense, desaturated, or 
text-only diffs
-* Org mode blocks::              Choose among plain, greyscale, or rainbow 
styles
-* Heading styles::               Choose among several styles, also per heading 
level
-* Scaled headings::              Toggle scaling of headings
-* Headings' font::               Toggle proportionately spaced fonts in 
headings
-@end menu
-
-@node Bold constructs
-@section Option for more bold constructs
-
-Symbol names:
-
-@itemize
-@item
-@samp{modus-operandi-theme-bold-constructs}
-@item
-@samp{modus-vivendi-theme-bold-constructs}
-@end itemize
-
-Possible values:
-
-@enumerate
-@item
-@samp{nil} (default)
-@item
-@samp{t}
-@end enumerate
-
-Display several constructs in bold weight.  This concerns keywords and
-other important aspects of code syntax.  It also affects certain mode
-line indicators and command-line prompts.
-
-The default is to only use a bold weight when it is required.
-
-Additionally, and while not necessary, to define the precise weight for
-bold constructs, you can change the typographic intensity of the @samp{bold}
-face.  The standard is a bold weight.  It requires no further
-intervention.  Assuming though that your typeface of choice supports a
-``semibold'' weight, adding the following snippet to your init file should
-suffice.
-
-@lisp
-(set-face-attribute 'bold nil :weight 'semibold)
-@end lisp
-
-Note that if you are switching themes, you need to re-evaluate this
-expression after the new theme is loaded.
-
-@node Slanted constructs
-@section Option for more slanted constructs
-
-Symbol names:
-
-@itemize
-@item
-@samp{modus-operandi-theme-slanted-constructs}
-@item
-@samp{modus-vivendi-theme-slanted-constructs}
-@end itemize
-
-Possible values:
-
-@enumerate
-@item
-@samp{nil} (default)
-@item
-@samp{t}
-@end enumerate
-
-Choose to render more faces in slanted text (italics).  This typically
-affects documentation strings and code comments.
-
-The default is to not use italics unless it is absolutely necessary.
-
-@node Syntax highlighting
-@section Option for faint code syntax highlighting
-
-Symbol names:
-
-@itemize
-@item
-@samp{modus-operandi-theme-faint-syntax}
-@item
-@samp{modus-vivendi-theme-faint-syntax}
-@end itemize
-
-Possible values:
-
-@enumerate
-@item
-@samp{nil} (default)
-@item
-@samp{t}
-@end enumerate
-
-Use less saturated colors in programming modes for highlighting code
-syntax.  The default is to use saturated colors.
-
-This option essentially affects the font-lock faces, so it may also have
-implications in other places that are hard-wired to rely directly on
-them instead of specifying their own faces (which could inherit from
-font-lock if that is the intent).  The author is aware of @samp{vc-dir} as a
-case in point.
-
-@node No mixed fonts
-@section Option for no font mixing
-
-Symbol names:
-
-@itemize
-@item
-@samp{modus-operandi-theme-no-mixed-fonts}
-@item
-@samp{modus-vivendi-theme-no-mixed-fonts}
-@end itemize
-
-Possible values:
-
-@enumerate
-@item
-@samp{nil} (default)
-@item
-@samp{t}
-@end enumerate
-
-By default, the themes configure some spacing-sensitive faces, such as
-Org tables and code blocks, to always inherit from the @samp{fixed-pitch} face.
-This is to ensure that those constructs remain monospaced when users opt
-for something like the built-in @kbd{M-x variable-pitch-mode}.  Otherwise the
-layout would appear broken.  To disable this behaviour, set the option
-to @samp{t}.
-
-Users may prefer to use another package for handling mixed typeface
-configurations, rather than letting the theme do it, perhaps because a
-purpose-specific package has extra functionality.  Two possible options
-are @samp{org-variable-pitch} and @samp{mixed-pitch}.
-
-@node Link underline
-@section Option for no link underline
-
-Symbol names:
-
-@itemize
-@item
-@samp{modus-operandi-theme-no-link-underline}
-@item
-@samp{modus-vivendi-theme-no-link-underline}
-@end itemize
-
-Possible values:
-
-@enumerate
-@item
-@samp{nil} (default)
-@item
-@samp{t}
-@end enumerate
-
-Remove the underline effect from links, symbolic links, and buttons.
-The default is to apply an underline.
-
-@node Command prompts
-@section Option for command prompt styles
-
-Symbol names:
-
-@itemize
-@item
-@samp{modus-operandi-theme-prompts}
-@item
-@samp{modus-vivendi-theme-prompts}
-@end itemize
-
-Possible values:
-
-@enumerate
-@item
-@samp{nil} (default)
-@item
-@samp{subtle}
-@item
-@samp{intense}
-@end enumerate
-
-The symbols ``subtle'' and ``intense'' will apply a combination of accented
-background and foreground to the minibuffer and other REPL prompts (like
-@samp{M-x shell} and @samp{M-x eshell}).  The difference between the two is 
that the
-latter has a more pronounced/noticeable effect than the former.
-
-The default does not use any background for such prompts, while relying
-exclusively on an accented foreground color.
-
-@node Mode line
-@section Option for mode line presentation
-
-Symbol names:
-
-@itemize
-@item
-@samp{modus-operandi-theme-mode-line}
-@item
-@samp{modus-vivendi-theme-mode-line}
-@end itemize
-
-Possible values:
-
-@enumerate
-@item
-@samp{nil} (default)
-@item
-@samp{3d}
-@item
-@samp{moody}
-@end enumerate
-
-The default value (@samp{nil}) produces a two-dimensional effect both for the
-active and inactive modelines.  The differences between the two are
-limited to distinct shades of greyscale values, with the active being
-more intense than the inactive.
-
-A @samp{3d} symbol will make the active modeline look like a three-dimensional
-rectangle.  Inactive modelines remain 2D, though they are slightly toned
-down relative to the default.  This aesthetic is the same as what you
-get when you run Emacs without any customizations (@kbd{emacs -Q} on the
-command line).
-
-While @samp{moody} removes all box effects from the modelines and applies
-underline and overline properties instead.  It also tones down a bit the
-inactive modelines.  This is meant to optimize things for use with the
-@uref{https://github.com/tarsius/moody, moody package} (hereinafter referred 
to as ``Moody''), though it can work
-fine even without it.
-
-Note that Moody does not expose any faces that the themes could style
-directly.  Instead it re-purposes existing ones to render its tabs and
-ribbons.  As such, there may be cases where the contrast ratio falls
-below the 7:1 target that the themes conform with (WCAG AAA).  To hedge
-against this, we configure a fallback foreground for the @samp{moody} option,
-which will come into effect when the background of the modeline changes
-to something less accessible, such as Moody ribbons (read the doc string
-of @samp{set-face-attribute}, specifically @samp{:distant-foreground}).  This 
fallback
-comes into effect when Emacs determines that the background and
-foreground of the given construct are too close to each other in terms
-of color distance.  In effect, users would need to experiment with the
-variable @samp{face-near-same-color-threshold} to trigger the fallback color.
-We find that a value of @samp{45000} would suffice, contrary to the default
-@samp{30000}.  Do not set the value too high, because that would have the
-adverse effect of always overriding the default color (which has been
-carefully designed to be highly accessible).
-
-Furthermore, because Moody expects an underline and overline instead of
-a box style, it is recommended you also include this in your setup:
-
-@lisp
-(setq x-underline-at-descent-line t)
-@end lisp
-
-@node Completion UIs
-@section Option for completion framework aesthetics
-
-Symbol names:
-
-@itemize
-@item
-@samp{modus-operandi-theme-completions}
-@item
-@samp{modus-vivendi-theme-completions}
-@end itemize
-
-Possible values:
-
-@enumerate
-@item
-@samp{nil} (default)
-@item
-@samp{moderate}
-@item
-@samp{opinionated}
-@end enumerate
-
-This is a special option that has different effects depending on the
-completion UI@.  The interfaces can be grouped in two categories, based
-on their default aesthetics: (i) those that only or mostly use
-foreground colors for their interaction model, and (ii) those that
-combine background and foreground values for some of their metaphors.
-The former category encompasses Icomplete, Ido, Selectrum as well as
-pattern matching styles like Orderless and Flx.  The latter covers Helm,
-Ivy, and similar.
-
-A value of @samp{nil} will respect the metaphors of each completion framework.
-
-The symbol @samp{moderate} will apply a combination of background and
-foreground that is fairly subtle.  For Icomplete and friends this
-constitutes a departure from their default aesthetics, however the
-difference is small.  While Helm et al will appear slightly different
-than their original looks, as they are toned down a bit.
-
-The symbol @samp{opinionated} will apply color combinations that refashion the
-completion UI@.  For the Icomplete camp this means that intense
-background and foreground combinations are used: in effect their looks
-emulate those of Ivy and co. in their original style.  Whereas the other
-group of packages will revert to an even more nuanced aesthetic with
-some additional changes to the choice of hues.
-
-To appreciate the scope of this customization option, you should spend
-some time with every one of the @samp{nil} (default), @samp{moderate}, and 
@samp{opinionated}
-possibilities.
-
-@node Fringes
-@section Option for fringe visibility
-
-Symbol names:
-
-@itemize
-@item
-@samp{modus-operandi-theme-fringes}
-@item
-@samp{modus-vivendi-theme-fringes}
-@end itemize
-
-Possible values:
-
-@enumerate
-@item
-@samp{nil} (default)
-@item
-@samp{subtle}
-@item
-@samp{intense}
-@end enumerate
-
-The ``subtle'' symbol will apply a greyscale background that is visible,
-yet close enough to the main background color.  While the ``intense''
-symbol will use a more noticeable greyscale background.
-
-The default is to use the same color as that of the main background,
-meaning that the fringes are not obvious though they still occupy the
-space given to them by @samp{fringe-mode}.
-
-@node Line highlighting
-@section Option for line highlighting (hl-line-mode)
-
-Symbol names:
-
-@itemize
-@item
-@samp{modus-operandi-theme-intense-hl-line}
-@item
-@samp{modus-vivendi-theme-intense-hl-line}
-@end itemize
-
-Possible values:
-
-@enumerate
-@item
-@samp{nil} (default)
-@item
-@samp{t}
-@end enumerate
-
-Draw the current line of @samp{hl-line-mode} or its global equivalent in a more
-prominent background color.  This would also affect several packages
-that enable @samp{hl-line-mode}, such as @samp{elfeed} and @samp{mu4e}.
-
-The default is to use a more subtle gray.
-
-@node Matching parentheses
-@section Option for parenthesis matching (show-paren-mode)
-
-Symbol names:
-
-@itemize
-@item
-@samp{modus-operandi-theme-intense-paren-match}
-@item
-@samp{modus-vivendi-theme-intense-paren-match}
-@end itemize
-
-Possible values:
-
-@enumerate
-@item
-@samp{nil} (default)
-@item
-@samp{t}
-@end enumerate
-
-Apply a more intense background to the matching parentheses (or
-delimiters).  This affects tools such as the built-in @samp{show-paren-mode}.
-The default is to use a subtle warm color for the background of those
-overlays.
-
-@node Diffs
-@section Option for diff buffer looks
-
-Symbol names:
-
-@itemize
-@item
-@samp{modus-operandi-theme-diffs}
-@item
-@samp{modus-vivendi-theme-diffs}
-@end itemize
-
-Possible values:
-
-@enumerate
-@item
-@samp{nil} (default)
-@item
-@samp{desaturated}
-@item
-@samp{fg-only}
-@end enumerate
-
-By default the themes will apply richly colored backgrounds to the
-output of diffs, such as those of @samp{diff-mode}, @samp{ediff}, 
@samp{smerge-mode}, and
-@samp{magit}.  These are color combinations of an accented background and
-foreground so that, for example, added lines have a pronounced green
-background with an appropriate shade of green for the affected text.
-Word-wise or ``refined'' changes follow this pattern but use different
-shades of those colors to remain distinct.
-
-A @samp{desaturated} value tones down all relevant color values.  It still
-combines an accented background with an appropriate foreground, yet its
-overall impression is very subtle.  Refined changes are a bit more
-intense to fulfil their intended function, though still less saturated
-than default.
-
-While @samp{fg-only} will remove all accented backgrounds and instead rely on
-color-coded text to denote changes.  For instance, added lines use an
-intense green foreground, while their background is the same as the rest
-of the buffer.  Word-wise highlights still use a background value which
-is, nonetheless, more subtle than its default equivalent.
-
-Concerning @samp{magit}, an extra set of tweaks are introduced for the effect
-of highlighting the current diff hunk, so as to remain consistent with
-the overall experience of that mode.  Expect changes that are consistent
-with the overall intent of the aforementioned.
-
-@node Org mode blocks
-@section Option for org-mode block styles
-
-Symbol names:
-
-@itemize
-@item
-@samp{modus-operandi-theme-org-blocks}
-@item
-@samp{modus-vivendi-theme-org-blocks}
-@end itemize
-
-Possible values:
-
-@enumerate
-@item
-@samp{nil} (default)
-@item
-@samp{greyscale}
-@item
-@samp{rainbow}
-@end enumerate
-
-The default is to use the same background as the rest of the buffer for
-the contents of the block.
-
-A value of @samp{greyscale} will apply a subtle neutral gray background to the
-block's contents.  It will also extend to the edge of the window the
-background of the ``begin'' and ``end'' block delimiter lines (only relevant
-for Emacs versions >= 27 where the 'extend' keyword is recognised by
-@samp{set-face-attribute}).
-
-While @samp{rainbow} will instead use an accented background for the contents
-of the block.  The exact color will depend on the programming language
-and is controlled by the @samp{org-src-block-faces} variable (refer to the
-theme's source code for the current association list).  This is most
-suitable for users who work on literate programming documents that mix
-and match several languages.
-
-Note that the ``rainbow'' blocks may require you to also reload the
-major-mode so that the colors are applied properly: use @kbd{M-x org-mode} or
-@kbd{M-x org-mode-restart} to refresh the buffer.  Or start typing in each
-code block (inefficient at scale, but it still works).
-
-@node Heading styles
-@section Option for headings' overall style
-
-This is defined as an alist and, therefore, uses a different approach
-than other customization options documented in this manual.
-
-Symbol names:
-
-@itemize
-@item
-@samp{modus-operandi-theme-headings}
-@item
-@samp{modus-vivendi-theme-headings}
-@end itemize
-
-Possible values, which can be specified for each heading level (examples
-further below):
-
-@itemize
-@item
-nil (default fallback option---covers all heading levels)
-@item
-@samp{t} (default style for a single heading, when the fallback differs)
-@item
-@samp{no-bold}
-@item
-@samp{line}
-@item
-@samp{line-no-bold}
-@item
-@samp{rainbow}
-@item
-@samp{rainbow-line}
-@item
-@samp{rainbow-line-no-bold}
-@item
-@samp{highlight}
-@item
-@samp{highlight-no-bold}
-@item
-@samp{rainbow-highlight}
-@item
-@samp{rainbow-highlight-no-bold}
-@item
-@samp{section}
-@item
-@samp{section-no-bold}
-@item
-@samp{rainbow-section}
-@item
-@samp{rainbow-section-no-bold}
-@end itemize
-
-To control faces per level from 1-8, use something like this (same for
-@samp{modus-vivendi-theme-headings}):
-
-@lisp
-(setq modus-operandi-theme-headings
-      '((1 . section)
-        (2 . line)
-        (3 . highlight)
-        (t . rainbow-no-bold)))
-@end lisp
-
-The above uses the @samp{section} value for heading levels 1, the @samp{line} 
for
-headings 2, @samp{highlight} for 3.  All other levels fall back to
-@samp{rainbow-line-no-bold}.
-
-To set a uniform value for all heading levels, use this pattern:
-
-@lisp
-;; A given style for every heading
-(setq modus-operandi-theme-headings
-      '((t . rainbow-line-no-bold)))
-
-;; Default aesthetic for every heading
-(setq modus-operandi-theme-headings
-      '((t . nil)))
-@end lisp
-
-The default style for headings uses a fairly desaturated foreground
-value in combination with a bold typographic weight.  To specify this
-style for a given level N (assuming you wish to have another fallback
-option), just specify the value @samp{t} like this:
-
-@lisp
-(setq modus-operandi-theme-headings
-      '((1 . t)
-        (2 . line)
-        (t . rainbow-line-no-bold)))
-@end lisp
-
-A description of all other possible styles:
-
-@itemize
-@item
-@samp{no-bold} retains the default text color while removing the typographic
-weight.
-
-@item
-@samp{line} is the same as the default plus an overline over the heading.
-
-@item
-@samp{line-no-bold} is the same as @samp{line} without bold weight.
-
-@item
-@samp{rainbow} uses a more colorful foreground in combination with bold
-weight.
-
-@item
-@samp{rainbow-line} is the same as @samp{rainbow} plus an overline.
-
-@item
-@samp{rainbow-line-no-bold} is the same as @samp{rainbow-line} without the bold
-weight.
-
-@item
-@samp{highlight} retains the default style of a fairly desaturated foreground
-combined with a bold weight and adds to it a subtle accented
-background.
-
-@item
-@samp{highlight-no-bold} is the same as @samp{highlight} without a bold weight.
-
-@item
-@samp{rainbow-highlight} is the same as @samp{highlight} but with a more 
colorful
-foreground.
-
-@item
-@samp{rainbow-highlight-no-bold} is the same as @samp{rainbow-highlight} 
without a
-bold weight.
-
-@item
-@samp{section} retains the default looks and adds to them both an overline
-and a slightly accented background.  It is, in effect, a combination
-of the @samp{line} and @samp{highlight} values.
-
-@item
-@samp{section-no-bold} is the same as @samp{section} without a bold weight.
-
-@item
-@samp{rainbow-section} is the same as @samp{section} but with a more colorful
-foreground.
-
-@item
-@samp{rainbow-section-no-bold} is the same as @samp{rainbow-section} without a 
bold
-weight.``
-@end itemize
-
-@node Scaled headings
-@section Option for scaled headings
-
-Symbol names:
-
-@itemize
-@item
-@samp{modus-operandi-theme-scale-headings}
-@item
-@samp{modus-vivendi-theme-scale-headings}
-@end itemize
-
-Possible values:
-
-@enumerate
-@item
-@samp{nil} (default)
-@item
-@samp{t}
-@end enumerate
-
-Make headings larger in height relative to the main text.  This is
-noticeable in modes like Org.  The default is to use the same size for
-headings and body copy.
-
-@menu
-* Scaled heading sizes::         Specify rate of increase for scaled headings
-@end menu
-
-@node Scaled heading sizes
-@subsection Control the scale of headings
-
-In addition to toggles for enabling scaled headings, users can also
-specify a number of their own.
-
-@itemize
-@item
-If it is a floating point, say, @samp{1.5}, it is interpreted as a multiple
-of the base font size.  This is the recommended method.
-
-@item
-If it is an integer, it is read as an absolute font height.  The
-number is basically the point size multiplied by ten.  So if you want
-it to be @samp{18pt} you must pass @samp{180}.  Please understand that setting 
an
-absolute value is discouraged, as it will break the layout when you
-try to change font sizes with the built-in @samp{text-scale-adjust} command
-(see @ref{Font configs (DIY), , Font configurations}).
-@end itemize
-
-Below are the variables in their default values, using the floating
-point paradigm.  The numbers are very conservative, but you are free to
-change them to your liking, such as @samp{1.2}, @samp{1.4}, @samp{1.6}, 
@samp{1.8}, @samp{2.0}---or use a
-resource for finding a consistent scale:
-
-@lisp
-(setq modus-operandi-theme-scale-1 1.05
-      modus-operandi-theme-scale-2 1.1
-      modus-operandi-theme-scale-3 1.15
-      modus-operandi-theme-scale-4 1.2
-      modus-operandi-theme-scale-5 1.3)
-
-(setq modus-vivendi-theme-scale-1 1.05
-      modus-vivendi-theme-scale-2 1.1
-      modus-vivendi-theme-scale-3 1.15
-      modus-vivendi-theme-scale-4 1.2
-      modus-vivendi-theme-scale-5 1.3)
-@end lisp
-
-Note that in earlier versions of Org, scaling would only increase the
-size of the heading, but not of keywords that were added to it, like
-``TODO''.  The issue has been fixed upstream:
-@uref{https://protesilaos.com/codelog/2020-09-24-org-headings-adapt/}.
-
-@node Headings' font
-@section Option for variable-pitch font in headings
-
-Symbol names:
-
-@itemize
-@item
-@samp{modus-operandi-theme-variable-pitch-headings}
-@item
-@samp{modus-vivendi-theme-variable-pitch-headings}
-@end itemize
-
-Possible values:
-
-@enumerate
-@item
-@samp{nil} (default)
-@item
-@samp{t}
-@end enumerate
-
-Choose to apply a proportionately spaced, else ``variable-pitch'',
-typeface to headings (such as in Org mode).  The default is to use the
-main font family.
-
-@ref{Font configs (DIY), , Font configurations for Org (and others)}.
-
-@node Advanced customization (do-it-yourself)
-@chapter Advanced customization (do-it-yourself)
-
-Unlike the predefined customization options which follow a
-straightforward pattern of allowing the user to quickly specify their
-preference, the themes also provide a more flexible, albeit difficult,
-mechanism to control things with precision (see @ref{Customization Options}).
-
-This section is of interest only to users who are prepared to maintain
-their own local tweaks and who are willing to deal with any possible
-incompatibilities between versioned releases of the themes.  As such,
-they are labelled as ``do-it-yourself'' or ``DIY''.
-
-@menu
-* Tweak colors (DIY)::           Declare your own palette overrides
-* Font configs (DIY)::           Optimise for mixed typeface buffers
-* Org user faces (DIY)::         Extend styles for org-mode keywords and 
priorities
-@end menu
-
-@node Tweak colors (DIY)
-@section Full access to the themes' palette
-
-The variables are:
-
-@itemize
-@item
-@samp{modus-operandi-theme-override-colors-alist}
-@item
-@samp{modus-vivendi-theme-override-colors-alist}
-@end itemize
-
-Users can specify an association list that maps the names of color
-variables to hexadecimal RGB values (in the form of @samp{#RRGGBB}).  This
-means that it is possible to override the entire palette or subsets
-thereof (see the source code for the actual names and values).
-
-Example:
-
-@lisp
-;; Redefine the values of those three variables for the given theme
-(setq modus-vivendi-theme-override-colors-alist
-      '(("magenta" . "#ffaabb")
-        ("magenta-alt" . "#ee88ff")
-        ("magenta-alt-other" . "#bbaaff")))
-@end lisp
-
-If you want to be creative, you can define a minor mode that refashions
-the themes on demand.  The following is a minor mode that gets activated
-on demand.  We combine it with the function to switch between Modus
-Operandi and Modus Vivendi (@pxref{Toggle between the themes on demand}, for
-a basic command, and/or @pxref{Configure options prior to loading}, for a more
-comprehensive setup).
-
-@lisp
-(define-minor-mode modus-themes-alt-mode
-  "Override Modus themes' palette variables with custom values.
-
-This is intended as a proof-of-concept.  It is, nonetheless, a
-perfectly accessible alternative, conforming with the design
-principles of the Modus themes.  It still is not as good as the
-default colors."
-  :init-value nil
-  :global t
-  (if modus-themes-alt-mode
-      (setq modus-operandi-theme-override-colors-alist
-            '(("bg-main" . "#fefcf4")
-              ("bg-dim" . "#faf6ef")
-              ("bg-alt" . "#f7efe5")
-              ("bg-hl-line" . "#f4f0e3")
-              ("bg-active" . "#e8dfd1")
-              ("bg-inactive" . "#f6ece5")
-              ("bg-region" . "#c6bab1")
-              ("bg-header" . "#ede3e0")
-              ("bg-tab-bar" . "#dcd3d3")
-              ("bg-tab-active" . "#fdf6eb")
-              ("bg-tab-inactive" . "#c8bab8")
-              ("fg-unfocused" . "#55556f"))
-            modus-vivendi-theme-override-colors-alist
-            '(("bg-main" . "#100b17")
-              ("bg-dim" . "#161129")
-              ("bg-alt" . "#181732")
-              ("bg-hl-line" . "#191628")
-              ("bg-active" . "#282e46")
-              ("bg-inactive" . "#1a1e39")
-              ("bg-region" . "#393a53")
-              ("bg-header" . "#202037")
-              ("bg-tab-bar" . "#262b41")
-              ("bg-tab-active" . "#120f18")
-              ("bg-tab-inactive" . "#3a3a5a")
-              ("fg-unfocused" . "#9a9aab")))
-    (setq modus-operandi-theme-override-colors-alist nil
-          modus-vivendi-theme-override-colors-alist nil)))
-
-(defun modus-themes-toggle (&optional arg)
-  "Toggle between `modus-operandi' and `modus-vivendi' themes.
-
-With optional \\[universal-argument] prefix, enable
-`modus-themes-alt-mode' for the loaded theme."
-  (interactive "P")
-  (if arg
-      (modus-themes-alt-mode 1)
-    (modus-themes-alt-mode -1))
-  (if (eq (car custom-enabled-themes) 'modus-operandi)
-      (progn
-        (disable-theme 'modus-operandi)
-        (load-theme 'modus-vivendi t))
-    (disable-theme 'modus-vivendi)
-    (load-theme 'modus-operandi t)))
-@end lisp
-
-@printindex cp
-
-@node Font configs (DIY)
-@section Font configurations for Org (and others)
-
-The themes are designed to cope well with mixed font settings (@ref{No mixed 
fonts, , Option
-for no font mixing}).  Currently this applies to @samp{org-mode} and
-@samp{markdown-mode}.
-
-In practice it means that the user can safely opt for a more
-prose-friendly proportionately spaced typeface as their default, while
-letting spacing-sensitive elements like tables and inline code always
-use a monospaced font, by inheriting from the @samp{fixed-pitch} face.
-
-Users can try the built-in @kbd{M-x variable-pitch-mode} to see the effect in
-action.
-
-To make everything use your desired font families, you need to configure
-the @samp{variable-pitch} (proportional spacing) and @samp{fixed-pitch} 
(monospaced)
-faces respectively.  It may also be convenient to set your main typeface
-by configuring the @samp{default} face the same way.
-
-Put something like this in your initialization file (make sure to read
-the documentation of @samp{set-face-attribute}, with @kbd{M-x 
describe-function}):
-
-@lisp
-;; Main typeface
-(set-face-attribute 'default nil :family "DejaVu Sans Mono" :height 110)
-
-;; Proportionately spaced typeface
-(set-face-attribute 'variable-pitch nil :family "DejaVu Serif" :height 1.0)
-
-;; Monospaced typeface
-(set-face-attribute 'fixed-pitch nil :family "DejaVu Sans Mono" :height 1.0)
-@end lisp
-
-Note the differences in the @samp{:height} property.  The @samp{default} face 
must
-specify an absolute value, which is the point size × 10.  So if you want
-to use a font at point size @samp{11}, you set the height at 
@samp{110}.@footnote{@samp{:height}
-values do not need to be rounded to multiples of ten: the likes of @samp{115}
-are perfectly valid—some typefaces will change to account for those
-finer increments.}  Whereas every other face must have a value that is
-relative to the default, represented as a floating point (if you use an
-integer, say, @samp{15} then that means an absolute height).  This is of
-paramount importantance: it ensures that all fonts can scale gracefully
-when using something like the @samp{text-scale-adjust} command which only
-operates on the base font size (i.e. the @samp{default} face's absolute
-height).
-
-An alternative syntax for the @samp{default} face, is to pass all typeface
-parameters directly to a @samp{font} property.@footnote{Has the benefit of
-accepting @samp{fontconfig} parameters (GNU/Linux), such as @samp{"DejaVu Sans
-Mono-11:hintstyle=hintslight:autohint=false"}.
-@uref{https://www.freedesktop.org/software/fontconfig/fontconfig-user.html}}
-Note that here we use a standard point size:
-
-@lisp
-(set-face-attribute 'default nil :font "DejaVu Sans Mono-11")
-@end lisp
-
-Again, remember to only ever specify an absolute height for the @samp{default}.
-
-@printindex cp
-
-@node Org user faces (DIY)
-@section Org user faces (DIY)
-
-Users of @samp{org-mode} have the option to configure various keywords and
-priority cookies to better match their workflow.  User options are
-@samp{org-todo-keyword-faces} and @samp{org-priority-faces}.
-
-As those are meant to be custom faces, it would be futile to have the
-themes try to guess what each user would want to use, which keywords to
-target, and so on.  Instead, we can provide guidelines on how to
-customize things to one's liking with the intent of retaining the
-overall aesthetics of the theme.
-
-Please bear in mind that the end result of those is not controlled by
-the active theme but by how Org maps faces to its constructs.  Editing
-those while @samp{org-mode} is active requires @kbd{M-x org-mode-restart} for 
changes
-to take effect.
-
-Let us assume you wish to visually differentiate your keywords.  You
-have something like this:
-
-@lisp
-(setq org-todo-keywords
-      '((sequence "TODO(t)" "|" "DONE(D)" "CANCEL(C)")
-        (sequence "MEET(m)" "|" "MET(M)")
-        (sequence "STUDY(s)" "|" "STUDIED(S)")
-        (sequence "WRITE(w)" "|" "WROTE(W)")))
-@end lisp
-
-You could then use a variant of the following to inherit from a face
-that uses the styles you want and also to preserve the properties
-applied by the @samp{org-todo} face:
-
-@lisp
-(setq org-todo-keyword-faces
-      '(("MEET" . '(font-lock-preprocessor-face org-todo))
-        ("STUDY" . '(font-lock-variable-name-face org-todo))
-        ("WRITE" . '(font-lock-type-face org-todo))))
-@end lisp
-
-This will refashion the keywords you specify, while letting the other
-items in @samp{org-todo-keywords} use their original styles (which are defined
-in the @samp{org-todo} and @samp{org-done} faces).
-
-If you want back the defaults, try specifying just the @samp{org-todo} face:
-
-@lisp
-(setq org-todo-keyword-faces
-      '(("MEET" . org-todo)
-        ("STUDY" . org-todo)
-        ("WRITE" . org-todo)))
-@end lisp
-
-When you inherit from multiple faces, you need to quote the list as
-shown further above.  The order is important: the last item is applied
-over the previous ones.  If you do not want to blend multiple faces, you
-do not need a quoted list.  A pattern of @samp{keyword . face} would suffice.
-
-Both approaches can be used simultaneously, as illustrated in this
-configuration of the priority cookies:
-
-@lisp
-(setq org-priority-faces
-      '((?A . '(org-scheduled-today org-priority))
-        (?B . org-priority)
-        (?C . '(shadow org-priority))))
-@end lisp
-
-To find all the faces that are loaded in your current Emacs session, use
-@kbd{M-x list-faces-display}.  Also try @kbd{M-x describe-variable} and then 
specify
-the name of each of those Org variables demonstrated above.  Their
-documentation strings will offer you further guidance.
-
-Furthermore, consider reading the ``Notes for aspiring Emacs theme
-developers'', published on 2020-08-28 by me (Protesilaos Stavrou):
-@uref{https://protesilaos.com/codelog/2020-08-28-notes-emacs-theme-devs/}.
-
-@printindex cp
-
-@printindex cp
-
-@node Face coverage
-@chapter Face coverage
-
-Modus Operandi and Modus Vivendi try to provide as close to full face
-coverage as possible.  This is necessary to ensure a consistently
-accessible reading experience across all possible interfaces.
-
-@menu
-* Supported packages::           Full list of covered face groups
-* Covered indirectly::
-* Will NOT be supported::
-@end menu
-
-@node Supported packages
-@section Full support for packages or face groups
-
-This list will always be updated to reflect the current state of the
-project.  The idea is to offer an overview of the known status of all
-affected face groups.  The items with an appended asterisk @samp{*} tend to
-have lots of extensions, so the ``full support'' may not be 100% true…
-
-@itemize
-@item
-ace-window
-@item
-ag
-@item
-alert
-@item
-all-the-icons
-@item
-annotate
-@item
-anzu
-@item
-apropos
-@item
-apt-sources-list
-@item
-artbollocks-mode
-@item
-auctex and @TeX{}
-@item
-auto-dim-other-buffers
-@item
-avy
-@item
-awesome-tray
-@item
-binder
-@item
-bm
-@item
-bongo
-@item
-boon
-@item
-breakpoint (provided by the built-in @samp{gdb-mi.el} library)
-@item
-buffer-expose
-@item
-calendar and diary
-@item
-calfw
-@item
-centaur-tabs
-@item
-change-log and log-view (such as @samp{vc-print-log} and 
@samp{vc-print-root-log})
-@item
-cider
-@item
-circe
-@item
-color-rg
-@item
-column-enforce-mode
-@item
-company-mode*
-@item
-company-posframe
-@item
-compilation-mode
-@item
-completions
-@item
-counsel*
-@item
-counsel-css
-@item
-counsel-notmuch
-@item
-counsel-org-capture-string
-@item
-cov
-@item
-cperl-mode
-@item
-csv-mode
-@item
-ctrlf
-@item
-custom (@kbd{M-x customize})
-@item
-dap-mode
-@item
-dashboard (emacs-dashboard)
-@item
-deadgrep
-@item
-debbugs
-@item
-define-word
-@item
-deft
-@item
-dictionary
-@item
-diff-hl
-@item
-diff-mode
-@item
-dim-autoload
-@item
-dir-treeview
-@item
-dired
-@item
-dired-async
-@item
-dired-git
-@item
-dired-git-info
-@item
-dired-narrow
-@item
-dired-subtree
-@item
-diredfl
-@item
-disk-usage
-@item
-doom-modeline
-@item
-dynamic-ruler
-@item
-easy-jekyll
-@item
-easy-kill
-@item
-ebdb
-@item
-ediff
-@item
-eglot
-@item
-el-search
-@item
-eldoc-box
-@item
-elfeed
-@item
-elfeed-score
-@item
-emms
-@item
-enhanced-ruby-mode
-@item
-epa
-@item
-equake
-@item
-erc
-@item
-eros
-@item
-ert
-@item
-eshell
-@item
-eshell-fringe-status
-@item
-eshell-git-prompt
-@item
-eshell-prompt-extras (epe)
-@item
-eshell-syntax-highlighting
-@item
-evil* (evil-mode)
-@item
-evil-goggles
-@item
-evil-visual-mark-mode
-@item
-eww
-@item
-eyebrowse
-@item
-fancy-dabbrev
-@item
-flycheck
-@item
-flycheck-color-mode-line
-@item
-flycheck-indicator
-@item
-flycheck-posframe
-@item
-flymake
-@item
-flyspell
-@item
-flyspell-correct
-@item
-flx
-@item
-freeze-it
-@item
-frog-menu
-@item
-focus
-@item
-fold-this
-@item
-font-lock (generic syntax highlighting)
-@item
-forge
-@item
-fountain (fountain-mode)
-@item
-geiser
-@item
-git-commit
-@item
-git-gutter (and variants)
-@item
-git-lens
-@item
-git-rebase
-@item
-git-timemachine
-@item
-git-walktree
-@item
-gnus
-@item
-golden-ratio-scroll-screen
-@item
-helm*
-@item
-helm-ls-git
-@item
-helm-switch-shell
-@item
-helm-xref
-@item
-helpful
-@item
-highlight-blocks
-@item
-highlight-defined
-@item
-highlight-escape-sequences (@samp{hes-mode})
-@item
-highlight-indentation
-@item
-highlight-numbers
-@item
-highlight-symbol
-@item
-highlight-tail
-@item
-highlight-thing
-@item
-hl-defined
-@item
-hl-fill-column
-@item
-hl-line-mode
-@item
-hl-todo
-@item
-hydra
-@item
-hyperlist
-@item
-ibuffer
-@item
-icomplete
-@item
-icomplete-vertical
-@item
-ido-mode
-@item
-iedit
-@item
-iflipb
-@item
-imenu-list
-@item
-indium
-@item
-info
-@item
-info-colors
-@item
-interaction-log
-@item
-ioccur
-@item
-isearch, occur, etc.
-@item
-ivy*
-@item
-ivy-posframe
-@item
-jira (org-jira)
-@item
-journalctl-mode
-@item
-js2-mode
-@item
-julia
-@item
-jupyter
-@item
-kaocha-runner
-@item
-keycast
-@item
-line numbers (@samp{display-line-numbers-mode} and global variant)
-@item
-lsp-mode
-@item
-lsp-ui
-@item
-magit
-@item
-magit-imerge
-@item
-man
-@item
-markdown-mode
-@item
-markup-faces (@samp{adoc-mode})
-@item
-mentor
-@item
-messages
-@item
-minibuffer-line
-@item
-minimap
-@item
-modeline
-@item
-mood-line
-@item
-moody
-@item
-mpdel
-@item
-mu4e
-@item
-mu4e-conversation
-@item
-multiple-cursors
-@item
-neotree
-@item
-no-emoji
-@item
-notmuch
-@item
-num3-mode
-@item
-nxml-mode
-@item
-objed
-@item
-orderless
-@item
-org*
-@item
-org-journal
-@item
-org-noter
-@item
-org-pomodoro
-@item
-org-recur
-@item
-org-roam
-@item
-org-superstar
-@item
-org-table-sticky-header
-@item
-org-treescope
-@item
-origami
-@item
-outline-mode
-@item
-outline-minor-faces
-@item
-package (@kbd{M-x list-packages})
-@item
-page-break-lines
-@item
-paradox
-@item
-paren-face
-@item
-parrot
-@item
-pass
-@item
-persp-mode
-@item
-perspective
-@item
-phi-grep
-@item
-phi-search
-@item
-pkgbuild-mode
-@item
-pomidor
-@item
-powerline
-@item
-powerline-evil
-@item
-proced
-@item
-prodigy
-@item
-racket-mode
-@item
-rainbow-blocks
-@item
-rainbow-identifiers
-@item
-rainbow-delimiters
-@item
-rcirc
-@item
-regexp-builder (also known as @samp{re-builder})
-@item
-rg (rg.el)
-@item
-ripgrep
-@item
-rmail
-@item
-ruler-mode
-@item
-sallet
-@item
-selectrum
-@item
-semantic
-@item
-sesman
-@item
-shell-script-mode
-@item
-show-paren-mode
-@item
-side-notes
-@item
-skewer-mode
-@item
-smart-mode-line
-@item
-smartparens
-@item
-smerge
-@item
-spaceline
-@item
-speedbar
-@item
-spell-fu
-@item
-stripes
-@item
-suggest
-@item
-switch-window
-@item
-swiper
-@item
-swoop
-@item
-sx
-@item
-symbol-overlay
-@item
-syslog-mode
-@item
-table (built-in table.el)
-@item
-telephone-line
-@item
-term
-@item
-tomatinho
-@item
-transient (pop-up windows such as Magit's)
-@item
-trashed
-@item
-treemacs
-@item
-tty-menu
-@item
-tuareg
-@item
-typescript
-@item
-undo-tree
-@item
-vc (built-in mode line status for version control)
-@item
-vc-annotate (@kbd{C-x v g})
-@item
-vdiff
-@item
-vimish-fold
-@item
-visible-mark
-@item
-visual-regexp
-@item
-volatile-highlights
-@item
-vterm
-@item
-wcheck-mode
-@item
-web-mode
-@item
-wgrep
-@item
-which-function-mode
-@item
-which-key
-@item
-whitespace-mode
-@item
-window-divider-mode
-@item
-winum
-@item
-writegood-mode
-@item
-woman
-@item
-xah-elisp-mode
-@item
-xref
-@item
-xterm-color (and ansi-colors)
-@item
-yaml-mode
-@item
-yasnippet
-@item
-ztree
-@end itemize
-
-Plus many other miscellaneous faces that are provided by the upstream
-GNU Emacs distribution.
-
-@node Covered indirectly
-@section Covered indirectly
-
-These do not require any extra styles because they are configured to
-inherit from some basic faces.  Please confirm.
-
-@itemize
-@item
-edit-indirect
-@item
-evil-owl
-@item
-perl-mode
-@item
-php-mode
-@item
-rjsx-mode
-@item
-swift-mode
-@end itemize
-
-@node Will NOT be supported
-@section Will NOT be supported
-
-I have thus far identified a single package that does fit into the
-overarching objective of this project: 
@uref{https://github.com/hlissner/emacs-solaire-mode, solaire}.  It basically 
tries to
-cast a less intense background on the main file-visiting buffers, so
-that secondary elements like sidebars can have the default (pure
-white/black) background.
-
-I will only cover this package if it ever supports the inverse effect:
-less intense colors (but still accessible) for ancillary interfaces
-and the intended styles for the content you are actually working on.
-
-@node Notes for individual packages
-@chapter Notes for individual packages
-
-This section covers information that may be of interest to users of
-individual packages.
-
-@menu
-* Note on company-mode overlay pop-up::
-* Note for ERC escaped color sequences::
-* Note for powerline or spaceline::
-* Note on shr colors::
-* Note for Helm grep::
-* Note on vc-annotate-background-mode::
-@end menu
-
-@node Note on company-mode overlay pop-up
-@section Note on company-mode overlay pop-up
-
-By default, the @samp{company-mode} pop-up that lists completion candidates is
-drawn using an overlay.  This creates alignment issues every time it is
-placed above a piece of text that has a different height than the
-default.
-
-The solution recommended by the project's maintainer is to use an
-alternative front-end for drawing the pop-up which uses child frames
-instead of 
overlays.@footnote{@uref{https://github.com/company-mode/company-mode/issues/1010}}@footnote{@uref{https://github.com/tumashu/company-posframe/}}
-
-@node Note for ERC escaped color sequences
-@section Note for ERC escaped color sequences
-
-The built-in IRC client @samp{erc} has the ability to colorise any text using
-escape sequences that start with @samp{^C} (inserted with @samp{C-q C-c}) and 
are
-followed by a number for the foreground and background.@footnote{This page
-explains the basics, though it is not specific to Emacs:
-@uref{https://www.mirc.com/colors.html}} Possible numbers are 0-15, with the
-first entry being the foreground and the second the background,
-separated by a comma.  Like this @samp{^C1,6}.  The minimum setup is this:
-
-@lisp
-(add-to-list 'erc-modules 'irccontrols)
-(setq erc-interpret-controls-p t
-      erc-interpret-mirc-color t)
-@end lisp
-
-As this allows users to make arbitrary combinations, it is impossible to
-guarantee a consistently high contrast ratio.  All we can we do is
-provide guidance on the combinations that satisfy the accessibility
-standard of the themes:
-
-@table @asis
-@item Modus Operandi
-Use foreground color 1 for all backgrounds from
-2-15.  Like so: @samp{C-q C-c1,N} where @samp{N} is the background.
-
-@item Modus Vivendi
-Use foreground color 0 for all backgrounds from
-2-13.  Use foreground @samp{1} for backgrounds 14, 15.
-@end table
-
-Colors 0 and 1 are white and black respectively.  So combine them
-together, if you must.
-
-@node Note for powerline or spaceline
-@section Note for powerline or spaceline
-
-Both Powerline and Spaceline package users will likely need to use the
-command @samp{powerline-reset} whenever they make changes to their themes
-and/or modeline setup.
-
-@node Note on shr colors
-@section Note on shr colors
-
-Emacs' HTML rendering mechanism (@samp{shr}) may need explicit configuration to
-respect the theme's colors instead of whatever specifications the
-webpage provides.  Consult @kbd{C-h v shr-use-colors}.
-
-@node Note for Helm grep
-@section Note for Helm grep
-
-There is one face from the Helm package that is meant to highlight the
-matches of a grep or grep-like command (@samp{ag} or @samp{ripgrep}).  It is
-@samp{helm-grep-match}.  However, this face can only apply when the user does
-not pass @samp{--color=always} as a command-line option for their command.
-
-Here is the docstring for that face, which is defined in the
-@samp{helm-grep.el} library (view a library with @samp{M-x find-library}).
-
-@quotation
-Face used to highlight grep matches.  Have no effect when grep backend
-use ``--color=''
-
-@end quotation
-
-The user must either remove @samp{--color} from the flags passed to the grep
-function, or explicitly use @samp{--color=never} (or equivalent).  Helm
-provides user-facing customization options for controlling the grep
-function's parameters, such as @samp{helm-grep-default-command} and
-@samp{helm-grep-git-grep-command}.
-
-When @samp{--color=always} is in effect, the grep output will use red text in
-bold letter forms to present the matching part in the list of
-candidates.  That style still meets the contrast ratio target of >= 7:1
-(accessibility standard WCAG AAA), because it draws the reference to
-ANSI color number 1 (red) from the already-supported array of
-@samp{ansi-color-names-vector}.
-
-@node Note on vc-annotate-background-mode
-@section Note on vc-annotate-background-mode
-
-Due to the unique way @samp{vc-annotate} (@kbd{C-x v g}) applies colors, 
support for
-its background mode (@samp{vc-annotate-background-mode}) is disabled at the
-theme level.
-
-Normally, such a drastic measure should not belong in a theme: assuming
-the user's preferences is bad practice.  However, it has been deemed
-necessary in the interest of preserving color contrast accessibility
-while still supporting a useful built-in tool.
-
-If there actually is a way to avoid such a course of action, without
-prejudice to the accessibility standard of this project, then please
-report as much or send patches (see @ref{Contributing}).
-
-@node Contributing
-@chapter Contributing
-
-This section documents the canonical sources of the themes and the ways
-in which you can contribute to their ongoing development.
-
-@menu
-* Sources of the themes::
-* Issues you can help with::
-* Merge requests::               Legal considerations for code patches
-@end menu
-
-@node Sources of the themes
-@section Sources of the themes
-
-The @samp{modus-operandi} and @samp{modus-vivendi} themes are built into Emacs.
-Currently they are in the project's @samp{master} branch, which is tracking the
-next development release target.
-
-The source code of the themes is 
@uref{https://gitlab.com/protesilaos/modus-themes/, available on Gitlab}, for 
the time
-being.  A @uref{https://github.com/protesilaos/modus-themes/, mirror on 
Github} is also on offer.
-
-An HTML version of this manual is available as an extension to the
-@uref{https://protesilaos.com/modus-themes/, author's personal website} (does 
not rely on any non-free code).
-
-@node Issues you can help with
-@section Issues you can help with
-
-A few tasks you can help with:
-
-@itemize
-@item
-Suggest refinements to packages that are covered.
-@item
-Report packages not covered thus far.
-@item
-Report bugs, inconsistencies, shortcomings.
-@item
-Help expand the documentation of covered-but-not-styled packages.
-@item
-Suggest refinements to the color palette.
-@item
-Help expand this document or any other piece of documentation.
-@item
-Merge requests for code refinements.
-@end itemize
-
-@xref{Merge requests, , Patches require copyright assignment to the FSF}.
-
-It would be great if your feedback also includes some screenshots, GIFs,
-or short videos, as well as further instructions to reproduce a given
-setup.  Though this is not a requirement.
-
-Whatever you do, bear in mind the overarching objective of the Modus
-themes: to keep a contrast ratio that is greater or equal to 7:1 between
-background and foreground colors.  If a compromise is ever necessary
-between aesthetics and accessibility, it shall always be made in the
-interest of the latter.
-
-@node Merge requests
-@section Patches require copyright assignment to the FSF
-
-Code contributions are most welcome.  For any major edit (more than 15
-lines, or so, in aggregate per person), you need to make a copyright
-assignment to the Free Software Foundation.  This is necessary because
-the themes are part of the upstream Emacs distribution: the FSF must at
-all times be in a position to enforce the GNU General Public License.
-
-Copyright assignment is a simple process.  Check the request form below
-(please adapt it accordingly).  You must write an email to the address
-mentioned in the form and then wait for the FSF to send you a legal
-agreement.  Sign the document and file it back to them.  This could all
-happen via email and take about a week.  You are encouraged to go
-through this process.  You only need to do it once.  It will allow you
-to make contributions to Emacs in general.
-
-@example
-Please email the following information to assign@@gnu.org, and we
-will send you the assignment form for your past and future changes.
-
-Please use your full legal name (in ASCII characters) as the subject
-line of the message.
-----------------------------------------------------------------------
-REQUEST: SEND FORM FOR PAST AND FUTURE CHANGES
-
-[What is the name of the program or package you're contributing to?]
-
-GNU Emacs
-
-[Did you copy any files or text written by someone else in these changes?
-Even if that material is free software, we need to know about it.]
-
-Copied a few snippets from the same files I edited.  Their author,
-Protesilaos Stavrou, has already assigned copyright to the Free Software
-Foundation.
-
-[Do you have an employer who might have a basis to claim to own
-your changes?  Do you attend a school which might make such a claim?]
-
-
-[For the copyright registration, what country are you a citizen of?]
-
-
-[What year were you born?]
-
-
-[Please write your email address here.]
-
-
-[Please write your postal address here.]
-
-
-
-
-
-[Which files have you changed so far, and which new files have you written
-so far?]
-
-Changed a couple of themes that are part of the Emacs source code:
-
-./etc/themes/modus-operandi-theme.el
-./etc/themes/modus-vivendi-theme.el
-@end example
-
-@node Acknowledgements
-@chapter Acknowledgements
-
-The Modus themes are a collective effort.  Every contribution counts.
-
-@table @asis
-@item Author/maintainer
-Protesilaos Stavrou.
-
-@item Code contributions
-Anders Johansson, Basil L@. Contovounesios,
-Markus Beppler, Matthew Stevenson.
-
-@item Ideas and user feedback
-Aaron Jensen, Adam Spiers, Alex Griffin,
-Alex Peitsinis, Alexey Shmalko, Anders Johansson, André Alexandre
-Gomes, Arif Rezai, Basil L@. Contovounesios, Damien Cassou, Dario
-Gjorgjevski, David Edmondson, Davor Rotim, Divan Santana, Gerry
-Agbobada, Gianluca Recchia, Iris Garcia, Len Trigg, Manuel Uberti,
-Mark Burton, Markus Beppler, Michael Goldenberg, Murilo Pereira,
-Nicolas De Jaeghere, Pierre Téchoueyres, Roman Rudakov, Ryan Phillips,
-Shreyas Ragavan, Tassilo Horn, Thibaut Verron, Trey Merkley, Uri
-Sharf, Utkarsh Singh, Vincent Foley.  As well as users: Ben,
-Fourchaux, Fredrik, Moesasji, Nick, TheBlob42, dinko, doolio, jixiuf,
-okamsn, tycho garen.
-
-@item Packaging
-Dhavan Vaidya (Debian), Stefan Kangas (core Emacs),
-Stefan Monnier (GNU Elpa).
-
-@item Inspiration for certain features
-Fabrice Niessen (leuven-theme),
-Bozhidar Batsov (zenburn-theme).
-@end table
-
-@node Meta
-@chapter Meta
-
-If you are curious about the principles that govern the development of
-this project read the essay 
@uref{https://protesilaos.com/codelog/2020-03-17-design-modus-themes-emacs/, On 
the design of the Modus themes}
-(2020-03-17).
-
-Here are some more publications for those interested in the kind of work
-that goes into this project (sometimes the commits also include details
-of this sort):
-
-@itemize
-@item
-@uref{https://protesilaos.com/codelog/2020-05-10-modus-operandi-palette-review/,
 Modus Operandi theme subtle palette review} (2020-05-10)
-@item
-@uref{https://protesilaos.com/codelog/2020-06-13-modus-vivendi-palette-review/,
 Modus Vivendi theme subtle palette review} (2020-06-13)
-@item
-@uref{https://protesilaos.com/codelog/2020-07-04-modus-themes-faint-colours/, 
Modus themes: new ``faint syntax'' option} (2020-07-04)
-@item
-@uref{https://protesilaos.com/codelog/2020-07-08-modus-themes-nuanced-colours/,
 Modus themes: major review of ``nuanced'' colours} (2020-07-08)
-@item
-@uref{https://protesilaos.com/codelog/2020-09-14-modus-themes-review-blues/, 
Modus themes: review of blue colours} (2020-09-14)
-@end itemize
-
-And here are the canonical sources for this project's documentation:
-
-@table @asis
-@item Manual
-@uref{https://protesilaos.com/modus-themes}
-@item Change Log
-@uref{https://protesilaos.com/modus-themes-changelog}
-@item Screenshots
-@uref{https://protesilaos.com/modus-themes-pictures}
-@end table
-
-@node External projects (ports)
-@chapter External projects (ports)
-
-The present section documents projects that extend the scope of the
-Modus themes.  The following list will be updated whenever relevant
-information is brought to my attention.  If you already have or intend
-to produce such a port, feel welcome @uref{https://protesilaos.com/contact, to 
contact me}.
-
-@table @asis
-@item Modus exporter
-This is @uref{https://github.com/polaris64/modus-exporter, an Elisp library 
written by Simon Pugnet}.
-Licensed under the terms of the GNU General Public License.  It is
-meant to capture the color values of the active Modus theme (Operandi
-or Vivendi) and output it as a valid theme for some other application.
-@end table
-
-@node GNU Free Documentation License
-@appendix GNU Free Documentation License
-
-@example
-                GNU Free Documentation License
-                 Version 1.3, 3 November 2008
-
-
- Copyright (C) 2000, 2001, 2002, 2007, 2008 Free Software Foundation, Inc.
-     <https://fsf.org/>
- Everyone is permitted to copy and distribute verbatim copies
- of this license document, but changing it is not allowed.
-
-0. PREAMBLE
-
-The purpose of this License is to make a manual, textbook, or other
-functional and useful document "free" in the sense of freedom: to
-assure everyone the effective freedom to copy and redistribute it,
-with or without modifying it, either commercially or noncommercially.
-Secondarily, this License preserves for the author and publisher a way
-to get credit for their work, while not being considered responsible
-for modifications made by others.
-
-This License is a kind of "copyleft", which means that derivative
-works of the document must themselves be free in the same sense.  It
-complements the GNU General Public License, which is a copyleft
-license designed for free software.
-
-We have designed this License in order to use it for manuals for free
-software, because free software needs free documentation: a free
-program should come with manuals providing the same freedoms that the
-software does.  But this License is not limited to software manuals;
-it can be used for any textual work, regardless of subject matter or
-whether it is published as a printed book.  We recommend this License
-principally for works whose purpose is instruction or reference.
-
-
-1. APPLICABILITY AND DEFINITIONS
-
-This License applies to any manual or other work, in any medium, that
-contains a notice placed by the copyright holder saying it can be
-distributed under the terms of this License.  Such a notice grants a
-world-wide, royalty-free license, unlimited in duration, to use that
-work under the conditions stated herein.  The "Document", below,
-refers to any such manual or work.  Any member of the public is a
-licensee, and is addressed as "you".  You accept the license if you
-copy, modify or distribute the work in a way requiring permission
-under copyright law.
-
-A "Modified Version" of the Document means any work containing the
-Document or a portion of it, either copied verbatim, or with
-modifications and/or translated into another language.
-
-A "Secondary Section" is a named appendix or a front-matter section of
-the Document that deals exclusively with the relationship of the
-publishers or authors of the Document to the Document's overall
-subject (or to related matters) and contains nothing that could fall
-directly within that overall subject.  (Thus, if the Document is in
-part a textbook of mathematics, a Secondary Section may not explain
-any mathematics.)  The relationship could be a matter of historical
-connection with the subject or with related matters, or of legal,
-commercial, philosophical, ethical or political position regarding
-them.
-
-The "Invariant Sections" are certain Secondary Sections whose titles
-are designated, as being those of Invariant Sections, in the notice
-that says that the Document is released under this License.  If a
-section does not fit the above definition of Secondary then it is not
-allowed to be designated as Invariant.  The Document may contain zero
-Invariant Sections.  If the Document does not identify any Invariant
-Sections then there are none.
-
-The "Cover Texts" are certain short passages of text that are listed,
-as Front-Cover Texts or Back-Cover Texts, in the notice that says that
-the Document is released under this License.  A Front-Cover Text may
-be at most 5 words, and a Back-Cover Text may be at most 25 words.
-
-A "Transparent" copy of the Document means a machine-readable copy,
-represented in a format whose specification is available to the
-general public, that is suitable for revising the document
-straightforwardly with generic text editors or (for images composed of
-pixels) generic paint programs or (for drawings) some widely available
-drawing editor, and that is suitable for input to text formatters or
-for automatic translation to a variety of formats suitable for input
-to text formatters.  A copy made in an otherwise Transparent file
-format whose markup, or absence of markup, has been arranged to thwart
-or discourage subsequent modification by readers is not Transparent.
-An image format is not Transparent if used for any substantial amount
-of text.  A copy that is not "Transparent" is called "Opaque".
-
-Examples of suitable formats for Transparent copies include plain
-ASCII without markup, Texinfo input format, LaTeX input format, SGML
-or XML using a publicly available DTD, and standard-conforming simple
-HTML, PostScript or PDF designed for human modification.  Examples of
-transparent image formats include PNG, XCF and JPG.  Opaque formats
-include proprietary formats that can be read and edited only by
-proprietary word processors, SGML or XML for which the DTD and/or
-processing tools are not generally available, and the
-machine-generated HTML, PostScript or PDF produced by some word
-processors for output purposes only.
-
-The "Title Page" means, for a printed book, the title page itself,
-plus such following pages as are needed to hold, legibly, the material
-this License requires to appear in the title page.  For works in
-formats which do not have any title page as such, "Title Page" means
-the text near the most prominent appearance of the work's title,
-preceding the beginning of the body of the text.
-
-The "publisher" means any person or entity that distributes copies of
-the Document to the public.
-
-A section "Entitled XYZ" means a named subunit of the Document whose
-title either is precisely XYZ or contains XYZ in parentheses following
-text that translates XYZ in another language.  (Here XYZ stands for a
-specific section name mentioned below, such as "Acknowledgements",
-"Dedications", "Endorsements", or "History".)  To "Preserve the Title"
-of such a section when you modify the Document means that it remains a
-section "Entitled XYZ" according to this definition.
-
-The Document may include Warranty Disclaimers next to the notice which
-states that this License applies to the Document.  These Warranty
-Disclaimers are considered to be included by reference in this
-License, but only as regards disclaiming warranties: any other
-implication that these Warranty Disclaimers may have is void and has
-no effect on the meaning of this License.
-
-2. VERBATIM COPYING
-
-You may copy and distribute the Document in any medium, either
-commercially or noncommercially, provided that this License, the
-copyright notices, and the license notice saying this License applies
-to the Document are reproduced in all copies, and that you add no
-other conditions whatsoever to those of this License.  You may not use
-technical measures to obstruct or control the reading or further
-copying of the copies you make or distribute.  However, you may accept
-compensation in exchange for copies.  If you distribute a large enough
-number of copies you must also follow the conditions in section 3.
-
-You may also lend copies, under the same conditions stated above, and
-you may publicly display copies.
-
-
-3. COPYING IN QUANTITY
-
-If you publish printed copies (or copies in media that commonly have
-printed covers) of the Document, numbering more than 100, and the
-Document's license notice requires Cover Texts, you must enclose the
-copies in covers that carry, clearly and legibly, all these Cover
-Texts: Front-Cover Texts on the front cover, and Back-Cover Texts on
-the back cover.  Both covers must also clearly and legibly identify
-you as the publisher of these copies.  The front cover must present
-the full title with all words of the title equally prominent and
-visible.  You may add other material on the covers in addition.
-Copying with changes limited to the covers, as long as they preserve
-the title of the Document and satisfy these conditions, can be treated
-as verbatim copying in other respects.
-
-If the required texts for either cover are too voluminous to fit
-legibly, you should put the first ones listed (as many as fit
-reasonably) on the actual cover, and continue the rest onto adjacent
-pages.
-
-If you publish or distribute Opaque copies of the Document numbering
-more than 100, you must either include a machine-readable Transparent
-copy along with each Opaque copy, or state in or with each Opaque copy
-a computer-network location from which the general network-using
-public has access to download using public-standard network protocols
-a complete Transparent copy of the Document, free of added material.
-If you use the latter option, you must take reasonably prudent steps,
-when you begin distribution of Opaque copies in quantity, to ensure
-that this Transparent copy will remain thus accessible at the stated
-location until at least one year after the last time you distribute an
-Opaque copy (directly or through your agents or retailers) of that
-edition to the public.
-
-It is requested, but not required, that you contact the authors of the
-Document well before redistributing any large number of copies, to
-give them a chance to provide you with an updated version of the
-Document.
-
-
-4. MODIFICATIONS
-
-You may copy and distribute a Modified Version of the Document under
-the conditions of sections 2 and 3 above, provided that you release
-the Modified Version under precisely this License, with the Modified
-Version filling the role of the Document, thus licensing distribution
-and modification of the Modified Version to whoever possesses a copy
-of it.  In addition, you must do these things in the Modified Version:
-
-A. Use in the Title Page (and on the covers, if any) a title distinct
-   from that of the Document, and from those of previous versions
-   (which should, if there were any, be listed in the History section
-   of the Document).  You may use the same title as a previous version
-   if the original publisher of that version gives permission.
-B. List on the Title Page, as authors, one or more persons or entities
-   responsible for authorship of the modifications in the Modified
-   Version, together with at least five of the principal authors of the
-   Document (all of its principal authors, if it has fewer than five),
-   unless they release you from this requirement.
-C. State on the Title page the name of the publisher of the
-   Modified Version, as the publisher.
-D. Preserve all the copyright notices of the Document.
-E. Add an appropriate copyright notice for your modifications
-   adjacent to the other copyright notices.
-F. Include, immediately after the copyright notices, a license notice
-   giving the public permission to use the Modified Version under the
-   terms of this License, in the form shown in the Addendum below.
-G. Preserve in that license notice the full lists of Invariant Sections
-   and required Cover Texts given in the Document's license notice.
-H. Include an unaltered copy of this License.
-I. Preserve the section Entitled "History", Preserve its Title, and add
-   to it an item stating at least the title, year, new authors, and
-   publisher of the Modified Version as given on the Title Page.  If
-   there is no section Entitled "History" in the Document, create one
-   stating the title, year, authors, and publisher of the Document as
-   given on its Title Page, then add an item describing the Modified
-   Version as stated in the previous sentence.
-J. Preserve the network location, if any, given in the Document for
-   public access to a Transparent copy of the Document, and likewise
-   the network locations given in the Document for previous versions
-   it was based on.  These may be placed in the "History" section.
-   You may omit a network location for a work that was published at
-   least four years before the Document itself, or if the original
-   publisher of the version it refers to gives permission.
-K. For any section Entitled "Acknowledgements" or "Dedications",
-   Preserve the Title of the section, and preserve in the section all
-   the substance and tone of each of the contributor acknowledgements
-   and/or dedications given therein.
-L. Preserve all the Invariant Sections of the Document,
-   unaltered in their text and in their titles.  Section numbers
-   or the equivalent are not considered part of the section titles.
-M. Delete any section Entitled "Endorsements".  Such a section
-   may not be included in the Modified Version.
-N. Do not retitle any existing section to be Entitled "Endorsements"
-   or to conflict in title with any Invariant Section.
-O. Preserve any Warranty Disclaimers.
-
-If the Modified Version includes new front-matter sections or
-appendices that qualify as Secondary Sections and contain no material
-copied from the Document, you may at your option designate some or all
-of these sections as invariant.  To do this, add their titles to the
-list of Invariant Sections in the Modified Version's license notice.
-These titles must be distinct from any other section titles.
-
-You may add a section Entitled "Endorsements", provided it contains
-nothing but endorsements of your Modified Version by various
-parties--for example, statements of peer review or that the text has
-been approved by an organization as the authoritative definition of a
-standard.
-
-You may add a passage of up to five words as a Front-Cover Text, and a
-passage of up to 25 words as a Back-Cover Text, to the end of the list
-of Cover Texts in the Modified Version.  Only one passage of
-Front-Cover Text and one of Back-Cover Text may be added by (or
-through arrangements made by) any one entity.  If the Document already
-includes a cover text for the same cover, previously added by you or
-by arrangement made by the same entity you are acting on behalf of,
-you may not add another; but you may replace the old one, on explicit
-permission from the previous publisher that added the old one.
-
-The author(s) and publisher(s) of the Document do not by this License
-give permission to use their names for publicity for or to assert or
-imply endorsement of any Modified Version.
-
-
-5. COMBINING DOCUMENTS
-
-You may combine the Document with other documents released under this
-License, under the terms defined in section 4 above for modified
-versions, provided that you include in the combination all of the
-Invariant Sections of all of the original documents, unmodified, and
-list them all as Invariant Sections of your combined work in its
-license notice, and that you preserve all their Warranty Disclaimers.
-
-The combined work need only contain one copy of this License, and
-multiple identical Invariant Sections may be replaced with a single
-copy.  If there are multiple Invariant Sections with the same name but
-different contents, make the title of each such section unique by
-adding at the end of it, in parentheses, the name of the original
-author or publisher of that section if known, or else a unique number.
-Make the same adjustment to the section titles in the list of
-Invariant Sections in the license notice of the combined work.
-
-In the combination, you must combine any sections Entitled "History"
-in the various original documents, forming one section Entitled
-"History"; likewise combine any sections Entitled "Acknowledgements",
-and any sections Entitled "Dedications".  You must delete all sections
-Entitled "Endorsements".
-
-
-6. COLLECTIONS OF DOCUMENTS
-
-You may make a collection consisting of the Document and other
-documents released under this License, and replace the individual
-copies of this License in the various documents with a single copy
-that is included in the collection, provided that you follow the rules
-of this License for verbatim copying of each of the documents in all
-other respects.
-
-You may extract a single document from such a collection, and
-distribute it individually under this License, provided you insert a
-copy of this License into the extracted document, and follow this
-License in all other respects regarding verbatim copying of that
-document.
-
-
-7. AGGREGATION WITH INDEPENDENT WORKS
-
-A compilation of the Document or its derivatives with other separate
-and independent documents or works, in or on a volume of a storage or
-distribution medium, is called an "aggregate" if the copyright
-resulting from the compilation is not used to limit the legal rights
-of the compilation's users beyond what the individual works permit.
-When the Document is included in an aggregate, this License does not
-apply to the other works in the aggregate which are not themselves
-derivative works of the Document.
-
-If the Cover Text requirement of section 3 is applicable to these
-copies of the Document, then if the Document is less than one half of
-the entire aggregate, the Document's Cover Texts may be placed on
-covers that bracket the Document within the aggregate, or the
-electronic equivalent of covers if the Document is in electronic form.
-Otherwise they must appear on printed covers that bracket the whole
-aggregate.
-
-
-8. TRANSLATION
-
-Translation is considered a kind of modification, so you may
-distribute translations of the Document under the terms of section 4.
-Replacing Invariant Sections with translations requires special
-permission from their copyright holders, but you may include
-translations of some or all Invariant Sections in addition to the
-original versions of these Invariant Sections.  You may include a
-translation of this License, and all the license notices in the
-Document, and any Warranty Disclaimers, provided that you also include
-the original English version of this License and the original versions
-of those notices and disclaimers.  In case of a disagreement between
-the translation and the original version of this License or a notice
-or disclaimer, the original version will prevail.
-
-If a section in the Document is Entitled "Acknowledgements",
-"Dedications", or "History", the requirement (section 4) to Preserve
-its Title (section 1) will typically require changing the actual
-title.
-
-
-9. TERMINATION
-
-You may not copy, modify, sublicense, or distribute the Document
-except as expressly provided under this License.  Any attempt
-otherwise to copy, modify, sublicense, or distribute it is void, and
-will automatically terminate your rights under this License.
-
-However, if you cease all violation of this License, then your license
-from a particular copyright holder is reinstated (a) provisionally,
-unless and until the copyright holder explicitly and finally
-terminates your license, and (b) permanently, if the copyright holder
-fails to notify you of the violation by some reasonable means prior to
-60 days after the cessation.
-
-Moreover, your license from a particular copyright holder is
-reinstated permanently if the copyright holder notifies you of the
-violation by some reasonable means, this is the first time you have
-received notice of violation of this License (for any work) from that
-copyright holder, and you cure the violation prior to 30 days after
-your receipt of the notice.
-
-Termination of your rights under this section does not terminate the
-licenses of parties who have received copies or rights from you under
-this License.  If your rights have been terminated and not permanently
-reinstated, receipt of a copy of some or all of the same material does
-not give you any rights to use it.
-
-
-10. FUTURE REVISIONS OF THIS LICENSE
-
-The Free Software Foundation may publish new, revised versions of the
-GNU Free Documentation License from time to time.  Such new versions
-will be similar in spirit to the present version, but may differ in
-detail to address new problems or concerns.  See
-https://www.gnu.org/licenses/.
-
-Each version of the License is given a distinguishing version number.
-If the Document specifies that a particular numbered version of this
-License "or any later version" applies to it, you have the option of
-following the terms and conditions either of that specified version or
-of any later version that has been published (not as a draft) by the
-Free Software Foundation.  If the Document does not specify a version
-number of this License, you may choose any version ever published (not
-as a draft) by the Free Software Foundation.  If the Document
-specifies that a proxy can decide which future versions of this
-License can be used, that proxy's public statement of acceptance of a
-version permanently authorizes you to choose that version for the
-Document.
-
-11. RELICENSING
-
-"Massive Multiauthor Collaboration Site" (or "MMC Site") means any
-World Wide Web server that publishes copyrightable works and also
-provides prominent facilities for anybody to edit those works.  A
-public wiki that anybody can edit is an example of such a server.  A
-"Massive Multiauthor Collaboration" (or "MMC") contained in the site
-means any set of copyrightable works thus published on the MMC site.
-
-"CC-BY-SA" means the Creative Commons Attribution-Share Alike 3.0
-license published by Creative Commons Corporation, a not-for-profit
-corporation with a principal place of business in San Francisco,
-California, as well as future copyleft versions of that license
-published by that same organization.
-
-"Incorporate" means to publish or republish a Document, in whole or in
-part, as part of another Document.
-
-An MMC is "eligible for relicensing" if it is licensed under this
-License, and if all works that were first published under this License
-somewhere other than this MMC, and subsequently incorporated in whole or
-in part into the MMC, (1) had no cover texts or invariant sections, and
-(2) were thus incorporated prior to November 1, 2008.
-
-The operator of an MMC Site may republish an MMC contained in the site
-under CC-BY-SA on the same site at any time before August 1, 2009,
-provided the MMC is eligible for relicensing.
-
-
-ADDENDUM: How to use this License for your documents
-
-To use this License in a document you have written, include a copy of
-the License in the document and put the following copyright and
-license notices just after the title page:
-
-    Copyright (c)  YEAR  YOUR NAME.
-    Permission is granted to copy, distribute and/or modify this document
-    under the terms of the GNU Free Documentation License, Version 1.3
-    or any later version published by the Free Software Foundation;
-    with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts.
-    A copy of the license is included in the section entitled "GNU
-    Free Documentation License".
-
-If you have Invariant Sections, Front-Cover Texts and Back-Cover Texts,
-replace the "with...Texts." line with this:
-
-    with the Invariant Sections being LIST THEIR TITLES, with the
-    Front-Cover Texts being LIST, and with the Back-Cover Texts being LIST.
-
-If you have Invariant Sections without Cover Texts, or some other
-combination of the three, merge those two alternatives to suit the
-situation.
-
-If your document contains nontrivial examples of program code, we
-recommend releasing these examples in parallel under your choice of
-free software license, such as the GNU General Public License,
-to permit their use in free software.
-@end example
-
-@bye
diff --git a/doc/misc/nxml-mode.texi b/doc/misc/nxml-mode.texi
index 3671ac8..4ca223d 100644
--- a/doc/misc/nxml-mode.texi
+++ b/doc/misc/nxml-mode.texi
@@ -82,7 +82,7 @@ documents.
 To get validation and schema-sensitive editing, you need a RELAX NG Compact
 Syntax (RNC) schema for your document (@pxref{Locating a schema}).  The
 @file{etc/schema} directory includes some schemas for popular document
-types.  See @url{http://relaxng.org/} for more information on RELAX NG@.
+types.  See @url{https://relaxng.org/} for more information on RELAX NG@.
 You can use the @samp{Trang} program from
 @url{http://www.thaiopensource.com/relaxng/trang.html} to
 automatically create RNC schemas.  This program can:
diff --git a/doc/misc/octave-mode.texi b/doc/misc/octave-mode.texi
index 1adc268..e330606 100644
--- a/doc/misc/octave-mode.texi
+++ b/doc/misc/octave-mode.texi
@@ -83,9 +83,12 @@ addition to the standard Emacs commands.
 @kindex C-M-j
 @findex octave-indent-new-comment-line
 @vindex octave-continuation-string
+@vindex octave-string-continuation-marker
 Break Octave line at point, continuing comment if within one.  Insert
 @code{octave-continuation-string} before breaking the line unless
-inside a list.  Signal an error if within a single-quoted string.
+inside a list.  If within a double-quoted string, insert
+@code{octave-string-continuation-marker} instead.  Signal an error if
+within a single-quoted string.
 
 @item C-c ;
 @kindex C-c ;
diff --git a/doc/misc/org-setup.org b/doc/misc/org-setup.org
new file mode 100644
index 0000000..d0392f1
--- /dev/null
+++ b/doc/misc/org-setup.org
@@ -0,0 +1,53 @@
+# SETUPFILE for Org manual
+
+# Copyright (C) 2021 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/>.
+
+# XXX: We cannot use TODO keyword as a node starts with "TODO".
+#+todo: REVIEW FIXME | DONE
+#+property: header-args :eval no
+#+startup: overview nologdone
+
+# Use proper quote and backtick for code sections in PDF output
+# Cf. Texinfo manual 14.2
+#+texinfo_header: @set txicodequoteundirected
+#+texinfo_header: @set txicodequotebacktick
+
+# Contact Info
+#+texinfo_header: @set MAINTAINERSITE @uref{https://orgmode.org,maintainers 
webpage}
+#+texinfo_header: @set MAINTAINER Bastien Guerry
+#+texinfo_header: @set MAINTAINEREMAIL @email{bzg@gnu.org}
+#+texinfo_header: @set MAINTAINERCONTACT @uref{mailto:bzg@gnu.org,contact the 
maintainer}
+
+#+options: H:4 num:t toc:t author:t \n:nil ::t |:t ^:nil -:t f:t *:t <:t e:t 
':t
+#+options: d:nil todo:nil pri:nil tags:not-in-toc stat:nil broken-links:mark
+#+select_tags: export
+#+exclude_tags: noexport
+
+#+macro: cite @@texinfo:@cite{@@$1@@texinfo:}@@
+#+macro: var @@texinfo:@var{@@$1@@texinfo:}@@
+
+# The "version" macro extracts "Version" keyword from "org.el".  It
+# returns major.minor version number.  This is sufficient since bugfix
+# releases are not expected to add features and therefore imply manual
+# modifications.
+#+macro: version (eval (with-current-buffer (find-file-noselect 
"../../lisp/org/org.el") (org-with-point-at 1 (if (re-search-forward "Version: 
+\\([0-9.]+\\)" nil t) (mapconcat #'identity (cl-subseq (split-string 
(match-string-no-properties 1) "\\.") 0 2) ".") (error "Missing \"Version\" 
keyword in \"org.el\"")))))
+
+# The "kbd" macro turns KBD into @kbd{KBD}.  Additionally, it
+# encloses case-sensitive special keys (SPC, RET...) within @key{...}.
+#+macro: kbd (eval (let ((case-fold-search nil) (regexp (regexp-opt '("SPC" 
"RET" "LFD" "TAB" "BS" "ESC" "DELETE" "SHIFT" "Ctrl" "Meta" "Alt" "Cmd" "Super" 
"UP" "LEFT" "RIGHT" "DOWN") 'words))) (format 
"@@texinfo:@kbd{@@%s@@texinfo:}@@" (replace-regexp-in-string regexp 
"@@texinfo:@key{@@\\&@@texinfo:}@@" $1 t))))
+
diff --git a/doc/misc/org.org b/doc/misc/org.org
new file mode 100644
index 0000000..f072b5e
--- /dev/null
+++ b/doc/misc/org.org
@@ -0,0 +1,21904 @@
+#+title: The Org Manual
+#+subtitle:  Release {{{version}}}
+#+author:    The Org Mode Developers
+#+language:  en
+
+
+#+texinfo: @insertcopying
+
+* Introduction
+:PROPERTIES:
+:DESCRIPTION: Getting started.
+:END:
+#+cindex: introduction
+
+** Summary
+:PROPERTIES:
+:DESCRIPTION: Brief summary of what Org does.
+:END:
+#+cindex: summary
+
+Org is a mode for keeping notes, maintaining TODO lists, and project
+planning with a fast and effective plain-text markup language.  It
+also is an authoring system with unique support for literate
+programming and reproducible research.
+
+Org is implemented on top of Outline mode, which makes it possible to
+keep the content of large files well structured.  Visibility cycling
+and structure editing help to work with the tree.  Tables are easily
+created with a built-in table editor.  Plain text URL-like links
+connect to websites, emails, Usenet messages, BBDB entries, and any
+files related to the projects.
+
+Org develops organizational tasks around notes files that contain
+lists or information about projects as plain text.  Project planning
+and task management make use of metadata which is part of an outline
+node.  Based on this data, specific entries can be extracted in
+queries and create dynamic /agenda views/ that also integrate the
+Emacs calendar and diary.  Org can be used to implement many different
+project planning schemes, such as David Allen's GTD system.
+
+Org files can serve as a single source authoring system with export to
+many different formats such as HTML, LaTeX, Open Document, and
+Markdown.  New export backends can be derived from existing ones, or
+defined from scratch.
+
+Org files can include source code blocks, which makes Org uniquely
+suited for authoring technical documents with code examples.  Org
+source code blocks are fully functional; they can be evaluated in
+place and their results can be captured in the file.  This makes it
+possible to create a single file reproducible research compendium.
+
+Org keeps simple things simple.  When first fired up, it should feel
+like a straightforward, easy to use outliner.  Complexity is not
+imposed, but a large amount of functionality is available when needed.
+Org is a toolbox.  Many users actually run only a---very
+personal---fraction of Org's capabilities, and know that there is more
+whenever they need it.
+
+All of this is achieved with strictly plain text files, the most
+portable and future-proof file format.  Org runs in Emacs.  Emacs is
+one of the most widely ported programs, so that Org mode is available
+on every major platform.
+
+#+cindex: FAQ
+There is a website for Org which provides links to the newest version
+of Org, as well as additional information, frequently asked questions
+(FAQ), links to tutorials, etc.  This page is located at
+[[https://orgmode.org]].
+
+#+cindex: print edition
+An earlier version (7.3) of this manual is available as a 
[[http://www.network-theory.co.uk/org/manual/][paperback
+book from Network Theory Ltd.]].
+
+** Installation
+:PROPERTIES:
+:DESCRIPTION: Installing Org.
+:END:
+#+cindex: installation
+
+Org is included in all recent distributions of GNU Emacs, so you
+probably do not need to install it.  Most users will simply activate
+Org and begin exploring its many features.
+
+If, for one reason or another, you want to install Org on top of this
+pre-packaged version, there are three ways to do it:
+
+- by using the Emacs package system;
+- by downloading Org as an archive; or
+- by using Org's git repository.
+
+We *strongly recommend* sticking to a single installation method.
+
+*** Using Emacs packaging system
+:PROPERTIES:
+:UNNUMBERED: notoc
+:END:
+
+Recent Emacs distributions include a packaging system which lets you
+install Elisp libraries.  You can install Org from the "package menu",
+with {{{kbd(M-x list-packages)}}}.  See [[info:emacs::Package Menu][Package 
Menu]].
+
+#+attr_texinfo: :tag Important
+#+begin_quote
+You need to do this in a session where no =.org= file has been
+visited, i.e., where no Org built-in function have been loaded.
+Otherwise autoload Org functions will mess up the installation.
+#+end_quote
+
+If you want to use Org's package repository, check out the 
[[https://orgmode.org/elpa.html][Org ELPA
+page]].
+
+*** Downloading Org as an archive
+:PROPERTIES:
+:UNNUMBERED: notoc
+:END:
+
+You can download Org latest release from [[https://orgmode.org/][Org's 
website]].  In this case,
+make sure you set the load path correctly in your Emacs init file:
+
+#+begin_src emacs-lisp
+(add-to-list 'load-path "~/path/to/orgdir/lisp")
+#+end_src
+
+The downloaded archive contains contributed libraries that are not
+included in Emacs.  If you want to use them, add the =contrib/=
+directory to your load path:
+
+#+begin_src emacs-lisp
+(add-to-list 'load-path "~/path/to/orgdir/contrib/lisp" t)
+#+end_src
+
+Optionally, you can compile the files and/or install them in your
+system.  Run =make help= to list compilation and installation options.
+
+*** Using Org's git repository
+:PROPERTIES:
+:UNNUMBERED: notoc
+:END:
+
+You can clone Org's repository and install Org like this:
+
+#+begin_example
+$ cd ~/src/
+$ git clone https://code.orgmode.org/bzg/org-mode.git
+$ cd org-mode/
+$ make autoloads
+#+end_example
+
+Note that in this case, =make autoloads= is mandatory: it defines
+Org's version in =org-version.el= and Org's autoloads in
+=org-loaddefs.el=.
+
+Remember to add the correct load path as described in the method
+above.
+
+You can also compile with =make=, generate the documentation with
+=make doc=, create a local configuration with =make config= and
+install Org with =make install=.  Please run =make help= to get the
+list of compilation/installation options.
+
+For more detailed explanations on Org's build system, please check the
+Org Build System page on 
[[https://orgmode.org/worg/dev/org-build-system.html][Worg]].
+
+** Activation
+:PROPERTIES:
+:DESCRIPTION: How to activate Org for certain buffers.
+:END:
+#+cindex: activation
+#+cindex: autoload
+#+cindex: ELPA
+#+cindex: global key bindings
+#+cindex: key bindings, global
+
+Org mode buffers need Font Lock to be turned on: this is the default
+in Emacs[fn:1].
+
+There are compatibility issues between Org mode and some other Elisp
+packages (see [[*Packages that conflict with Org mode]]).  Please take the
+time to check the list.
+
+#+findex: org-agenda
+#+findex: org-capture
+#+findex: org-store-link
+For a better experience, the three Org commands ~org-store-link~,
+~org-capture~ and ~org-agenda~ ought to be accessible anywhere in
+Emacs, not just in Org buffers.  To that effect, you need to bind them
+to globally available keys, like the ones reserved for users (see
+[[info:elisp::Key Binding Conventions]]).  Here are suggested bindings,
+please modify the keys to your own liking.
+
+#+begin_src emacs-lisp
+(global-set-key (kbd "C-c l") 'org-store-link)
+(global-set-key (kbd "C-c a") 'org-agenda)
+(global-set-key (kbd "C-c c") 'org-capture)
+#+end_src
+
+#+cindex: Org mode, turning on
+Files with the =.org= extension use Org mode by default.  To turn on
+Org mode in a file that does not have the extension =.org=, make the
+first line of a file look like this:
+
+: MY PROJECTS    -*- mode: org; -*-
+
+#+vindex: org-insert-mode-line-in-empty-file
+#+texinfo: @noindent
+which selects Org mode for this buffer no matter what the file's name
+is.  See also the variable ~org-insert-mode-line-in-empty-file~.
+
+Many commands in Org work on the region if the region is /active/.  To
+make use of this, you need to have Transient Mark mode turned on,
+which is the default.  If you do not like it, you can create an active
+region by using the mouse to select a region, or pressing
+{{{kbd(C-SPC)}}} twice before moving point.
+
+** Feedback
+:PROPERTIES:
+:DESCRIPTION: Bug reports, ideas, patches, etc.
+:END:
+#+cindex: feedback
+#+cindex: bug reports
+#+cindex: reporting a bug
+#+cindex: maintainer
+#+cindex: author
+
+If you find problems with Org, or if you have questions, remarks, or
+ideas about it, please send an email to the Org mailing list
+[[mailto:emacs-orgmode@gnu.org]].  You can subscribe to the list 
[[https://lists.gnu.org/mailman/listinfo/emacs-orgmode][from this
+web page]].  If you are not a member of the mailing list, your mail will
+be passed to the list after a moderator has approved it[fn:2].  We ask
+you to read and respect the 
[[https://www.gnu.org/philosophy/kind-communication.html][GNU Kind 
Communications Guidelines]] when
+sending messages on this mailing list.
+
+#+findex: org-version
+#+findex: org-submit-bug-report
+For bug reports, please first try to reproduce the bug with the latest
+version of Org available---if you are running an outdated version, it
+is quite possible that the bug has been fixed already.  If the bug
+persists, prepare a report and provide as much information as
+possible, including the version information of Emacs ({{{kbd(M-x
+emacs-version)}}}) and Org ({{{kbd(M-x org-version)}}}), as well as
+the Org related setup in the Emacs init file.  The easiest way to do
+this is to use the command
+
+: M-x org-submit-bug-report <RET>
+
+#+texinfo: @noindent
+which puts all this information into an Emacs mail buffer so that you
+only need to add your description.  If you are not sending the Email
+from within Emacs, please copy and paste the content into your Email
+program.
+
+Sometimes you might face a problem due to an error in your Emacs or
+Org mode setup.  Before reporting a bug, it is very helpful to start
+Emacs with minimal customizations and reproduce the problem.  Doing so
+often helps you determine if the problem is with your customization or
+with Org mode itself.  You can start a typical minimal session with
+a command like the example below.
+
+: $ emacs -Q -l /path/to/minimal-org.el
+
+However if you are using Org mode as distributed with Emacs, a minimal
+setup is not necessary.  In that case it is sufficient to start Emacs
+as =emacs -Q=.  The =minimal-org.el= setup file can have contents as
+shown below.
+
+#+begin_src emacs-lisp
+;;; Minimal setup to load latest `org-mode'.
+
+;; Activate debugging.
+(setq debug-on-error t
+      debug-on-signal nil
+      debug-on-quit nil)
+
+;; Add latest Org mode to load path.
+(add-to-list 'load-path (expand-file-name "/path/to/org-mode/lisp"))
+(add-to-list 'load-path (expand-file-name "/path/to/org-mode/contrib/lisp" t))
+#+end_src
+
+If an error occurs, a "backtrace" can be very useful---see below on
+how to create one.  Often a small example file helps, along with clear
+information about:
+
+1. What exactly did you do?
+2. What did you expect to happen?
+3. What happened instead?
+
+Thank you for helping to improve this program.
+
+*** How to create a useful backtrace
+:PROPERTIES:
+:UNNUMBERED: notoc
+:END:
+
+#+cindex: backtrace of an error
+If working with Org produces an error with a message you do not
+understand, you may have hit a bug.  The best way to report this is by
+providing, in addition to what was mentioned above, a backtrace.  This
+is information from the built-in debugger about where and how the
+error occurred.  Here is how to produce a useful backtrace:
+
+1. Reload uncompiled versions of all Org mode Lisp files.  The
+   backtrace contains much more information if it is produced with
+   uncompiled code.  To do this, use
+
+   : C-u M-x org-reload <RET>
+
+   #+texinfo: @noindent
+   or, from the menu: Org \rarr Refresh/Reload \rarr Reload Org uncompiled.
+
+2. Then, activate the debugger:
+
+   : M-x toggle-debug-on-error <RET>
+
+   #+texinfo: @noindent
+   or, from the menu: Options \rarr Enter Debugger on Error.
+
+3. Do whatever you have to do to hit the error.  Do not forget to
+   document the steps you take.
+
+4. When you hit the error, a =*Backtrace*= buffer appears on the
+   screen.  Save this buffer to a file---for example using {{{kbd(C-x
+   C-w)}}}---and attach it to your bug report.
+
+** Typesetting Conventions Used in this Manual
+:PROPERTIES:
+:DESCRIPTION: Typesetting conventions used in this manual.
+:ALT_TITLE: Conventions
+:END:
+
+*** TODO keywords, tags, properties, etc.
+:PROPERTIES:
+:UNNUMBERED: notoc
+:END:
+
+Org uses various syntactical elements: TODO keywords, tags, property
+names, keywords, blocks, etc.  In this manual we use the following
+conventions:
+
+#+attr_texinfo: :sep ,
+- =TODO=, =WAITING= ::
+
+  TODO keywords are written with all capitals, even if they are
+  user-defined.
+
+- =boss=, =ARCHIVE= ::
+
+  Tags are case-sensitive.  User-defined tags are written in
+  lowercase; built-in tags with special meaning are written as they
+  should appear in the document, usually with all capitals.
+
+- =Release=, =PRIORITY= ::
+
+  User-defined properties are capitalized; built-in properties with
+  special meaning are written with all capitals.
+
+- =TITLE=, =BEGIN= ... =END= ::
+
+  Keywords and blocks are written in uppercase to enhance their
+  readability, but you can use lowercase in your Org files.
+
+*** Key bindings and commands
+:PROPERTIES:
+:UNNUMBERED: notoc
+:END:
+
+The manual lists both the keys and the corresponding commands for
+accessing a functionality.  Org mode often uses the same key for
+different functions, depending on context.  The command that is bound
+to such keys has a generic name, like ~org-metaright~.  In the manual
+we will, wherever possible, give the function that is internally
+called by the generic command.  For example, in the chapter on
+document structure, {{{kbd(M-RIGHT)}}} will be listed to call
+~org-do-demote~, while in the chapter on tables, it will be listed to
+call ~org-table-move-column-right~.
+
+* Document Structure
+:PROPERTIES:
+:DESCRIPTION: A tree works like your brain.
+:END:
+
+#+cindex: document structure
+#+cindex: structure of document
+Org is an outliner.  Outlines allow a document to be organized in
+a hierarchical structure, which, least for me, is the best
+representation of notes and thoughts.  An overview of this structure
+is achieved by folding, i.e., hiding large parts of the document to
+show only the general document structure and the parts currently being
+worked on.  Org greatly simplifies the use of outlines by compressing
+the entire show and hide functionalities into a single command,
+~org-cycle~, which is bound to the {{{kbd(TAB)}}} key.
+
+** Headlines
+:PROPERTIES:
+:DESCRIPTION: How to typeset Org tree headlines.
+:END:
+#+cindex: headlines
+#+cindex: outline tree
+#+vindex: org-special-ctrl-a/e
+#+vindex: org-special-ctrl-k
+#+vindex: org-ctrl-k-protect-subtree
+
+Headlines define the structure of an outline tree.  Org headlines
+start on the left margin[fn:3] with one or more stars followed by
+a space.  For example:
+
+#+begin_example
+,* Top level headline
+,** Second level
+,*** Third level
+    some text
+,*** Third level
+    more text
+,* Another top level headline
+#+end_example
+
+#+vindex: org-footnote-section
+The name defined in ~org-footnote-section~ is reserved.  Do not use it
+as a title for your own headings.
+
+Some people find the many stars too noisy and would prefer an outline
+that has whitespace followed by a single star as headline starters.
+This can be achieved using a Org Indent minor mode.  See [[*A Cleaner
+Outline View]] for more information.
+
+Headlines are not numbered.  However, you may want to dynamically
+number some, or all, of them.  See [[*Dynamic Headline Numbering]].
+
+#+vindex: org-cycle-separator-lines
+An empty line after the end of a subtree is considered part of it and
+is hidden when the subtree is folded.  However, if you leave at least
+two empty lines, one empty line remains visible after folding the
+subtree, in order to structure the collapsed view.  See the variable
+~org-cycle-separator-lines~ to modify this behavior.
+
+** Visibility Cycling
+:PROPERTIES:
+:DESCRIPTION: Show and hide, much simplified.
+:END:
+#+cindex: cycling, visibility
+#+cindex: visibility cycling
+#+cindex: trees, visibility
+#+cindex: show hidden text
+#+cindex: hide text
+
+*** Global and local cycling
+:PROPERTIES:
+:DESCRIPTION: Cycling through various visibility states.
+:END:
+#+cindex: subtree visibility states
+#+cindex: subtree cycling
+#+cindex: folded, subtree visibility state
+#+cindex: children, subtree visibility state
+#+cindex: subtree, subtree visibility state
+
+Outlines make it possible to hide parts of the text in the buffer.
+Org uses just two commands, bound to {{{kbd(TAB)}}} and
+{{{kbd(S-TAB)}}} to change the visibility in the buffer.
+
+#+attr_texinfo: :sep ,
+- {{{kbd(TAB)}}} (~org-cycle~) ::
+
+  #+kindex: TAB
+  #+findex: org-cycle
+  /Subtree cycling/: Rotate current subtree among the states
+
+  #+begin_example
+  ,-> FOLDED -> CHILDREN -> SUBTREE --.
+  '-----------------------------------'
+  #+end_example
+
+  #+vindex: org-cycle-emulate-tab
+  Point must be on a headline for this to work[fn:4].
+
+- {{{kbd(S-TAB)}}} (~org-global-cycle~), {{{kbd(C-u TAB)}}} ::
+
+  #+cindex: global visibility states
+  #+cindex: global cycling
+  #+cindex: overview, global visibility state
+  #+cindex: contents, global visibility state
+  #+cindex: show all, global visibility state
+  #+kindex: C-u TAB
+  #+kindex: S-TAB
+  #+findex: org-global-cycle
+  /Global cycling/: Rotate the entire buffer among the states
+
+  #+begin_example
+  ,-> OVERVIEW -> CONTENTS -> SHOW ALL --.
+  '--------------------------------------'
+  #+end_example
+
+  When {{{kbd(S-TAB)}}} is called with a numeric prefix argument
+  {{{var(N)}}}, view contents only up to headlines of level
+  {{{var(N)}}}.
+
+  Note that inside tables (see [[*Tables]]), {{{kbd(S-TAB)}}} jumps to the
+  previous field instead.
+
+  #+vindex: org-cycle-global-at-bob
+  You can run global cycling using {{{kbd(TAB)}}} only if point is at
+  the very beginning of the buffer, but not on a headline, and
+  ~org-cycle-global-at-bob~ is set to a non-~nil~ value.
+
+- {{{kbd(C-u C-u TAB)}}} (~org-set-startup-visibility~) ::
+
+  #+cindex: startup visibility
+  #+kindex: C-u C-u TAB
+  #+findex: org-set-startup-visibility
+  Switch back to the startup visibility of the buffer (see [[*Initial
+  visibility]]).
+
+- {{{kbd(C-u C-u C-u TAB)}}} (~outline-show-all~) ::
+
+  #+cindex: show all, command
+  #+kindex: C-u C-u C-u TAB
+  #+findex: outline-show-all
+  Show all, including drawers.
+
+- {{{kbd(C-c C-r)}}} (~org-reveal~) ::
+
+  #+cindex: revealing context
+  #+kindex: C-c C-r
+  #+findex: org-reveal
+  Reveal context around point, showing the current entry, the
+  following heading and the hierarchy above.  It is useful for working
+  near a location that has been exposed by a sparse tree command (see
+  [[*Sparse Trees]]) or an agenda command (see [[*Commands in the Agenda
+  Buffer]]).  With a prefix argument, show, on each level, all sibling
+  headings.  With a double prefix argument, also show the entire
+  subtree of the parent.
+
+- {{{kbd(C-c C-k)}}} (~outline-show-branches~) ::
+
+  #+cindex: show branches, command
+  #+kindex: C-c C-k
+  #+findex: outline-show-branches
+  Expose all the headings of the subtree, but not their bodies.
+
+- {{{kbd(C-c TAB)}}} (~outline-show-children~) ::
+
+  #+cindex: show children, command
+  #+kindex: C-c TAB
+  #+findex: outline-show-children
+  Expose all direct children of the subtree.  With a numeric prefix
+  argument {{{var(N)}}}, expose all children down to level
+  {{{var(N)}}}.
+
+- {{{kbd(C-c C-x b)}}} (~org-tree-to-indirect-buffer~) ::
+
+  #+kindex: C-c C-x b
+  #+findex: org-tree-to-indirect-buffer
+  Show the current subtree in an indirect buffer[fn:5].  With
+  a numeric prefix argument {{{var(N)}}}, go up to level {{{var(N)}}}
+  and then take that tree.  If {{{var(N)}}} is negative then go up
+  that many levels.  With a {{{kbd(C-u)}}} prefix, do not remove the
+  previously used indirect buffer.
+
+- {{{kbd(C-c C-x v)}}} (~org-copy-visible~) ::
+
+  #+kindex: C-c C-x v
+  #+findex: org-copy-visible
+  Copy the /visible/ text in the region into the kill ring.
+
+*** Initial visibility
+:PROPERTIES:
+:DESCRIPTION: Setting the initial visibility state.
+:END:
+
+#+vindex: org-startup-folded
+When Emacs first visits an Org file, the global state is set to
+~showeverything~, i.e., all file content is visible[fn:6].  This can
+be configured through the variable ~org-startup-folded~, or on
+a per-file basis by adding one of the following lines anywhere in the
+buffer:
+
+#+cindex: @samp{STARTUP}, keyword
+#+begin_example
+,#+STARTUP: overview
+,#+STARTUP: content
+,#+STARTUP: showall
+,#+STARTUP: showeverything
+#+end_example
+
+#+cindex: @samp{VISIBILITY}, property
+Furthermore, any entries with a =VISIBILITY= property (see [[*Properties
+and Columns]]) get their visibility adapted accordingly.  Allowed values
+for this property are =folded=, =children=, =content=, and =all=.
+
+- {{{kbd(C-u C-u TAB)}}} (~org-set-startup-visibility~) ::
+
+  #+kindex: C-u C-u TAB
+  #+findex: org-set-startup-visibility
+  Switch back to the startup visibility of the buffer, i.e., whatever
+  is requested by startup options and =VISIBILITY= properties in
+  individual entries.
+
+*** Catching invisible edits
+:PROPERTIES:
+:DESCRIPTION: Preventing mistakes when editing invisible parts.
+:END:
+#+cindex: edits, catching invisible
+
+#+vindex: org-catch-invisible-edits
+Sometimes you may inadvertently edit an invisible part of the buffer
+and be confused on what has been edited and how to undo the mistake.
+Setting ~org-catch-invisible-edits~ to non-~nil~ helps preventing
+this.  See the docstring of this option on how Org should catch
+invisible edits and process them.
+
+** Motion
+:PROPERTIES:
+:DESCRIPTION: Jumping to other headlines.
+:END:
+#+cindex: motion, between headlines
+#+cindex: jumping, to headlines
+#+cindex: headline navigation
+
+The following commands jump to other headlines in the buffer.
+
+- {{{kbd(C-c C-n)}}} (~org-next-visible-heading~) ::
+
+  #+kindex: C-c C-n
+  #+findex: org-next-visible-heading
+  Next heading.
+
+- {{{kbd(C-c C-p)}}} (~org-previous-visible-heading~) ::
+
+  #+kindex: C-c C-p
+  #+findex: org-previous-visible-heading
+  Previous heading.
+
+- {{{kbd(C-c C-f)}}} (~org-forward-heading-same-level~) ::
+
+  #+kindex: C-c C-f
+  #+findex: org-forward-heading-same-level
+  Next heading same level.
+
+- {{{kbd(C-c C-b)}}} (~org-backward-heading-same-level~) ::
+
+  #+kindex: C-c C-b
+  #+findex: org-backward-heading-same-level
+  Previous heading same level.
+
+- {{{kbd(C-c C-u)}}} (~outline-up-heading~) ::
+
+  #+kindex: C-c C-u
+  #+findex: outline-up-heading
+  Backward to higher level heading.
+
+- {{{kbd(C-c C-j)}}} (~org-goto~) ::
+
+  #+kindex: C-c C-j
+  #+findex: org-goto
+  #+vindex: org-goto-auto-isearch
+  Jump to a different place without changing the current outline
+  visibility.  Shows the document structure in a temporary buffer,
+  where you can use the following keys to find your destination:
+
+  #+attr_texinfo: :columns 0.3 0.7
+  | {{{kbd(TAB)}}}                  | Cycle visibility.               |
+  | {{{kbd(DOWN)}}} / {{{kbd(UP)}}} | Next/previous visible headline. |
+  | {{{kbd(RET)}}}                  | Select this location.           |
+  | {{{kbd(/)}}}                    | Do a Sparse-tree search         |
+
+  #+texinfo: @noindent
+  The following keys work if you turn off ~org-goto-auto-isearch~
+
+  #+attr_texinfo: :columns 0.3 0.7
+  | {{{kbd(n)}}} / {{{kbd(p)}}}   | Next/previous visible headline.    |
+  | {{{kbd(f)}}} / {{{kbd(b)}}}   | Next/previous headline same level. |
+  | {{{kbd(u)}}}                  | One level up.                      |
+  | {{{kbd(0)}}} ... {{{kbd(9)}}} | Digit argument.                    |
+  | {{{kbd(q)}}}                  | Quit.                              |
+
+  #+vindex: org-goto-interface
+  #+texinfo: @noindent
+  See also the variable ~org-goto-interface~.
+
+** Structure Editing
+:PROPERTIES:
+:DESCRIPTION: Changing sequence and level of headlines.
+:END:
+#+cindex: structure editing
+#+cindex: headline, promotion and demotion
+#+cindex: promotion, of subtrees
+#+cindex: demotion, of subtrees
+#+cindex: subtree, cut and paste
+#+cindex: pasting, of subtrees
+#+cindex: cutting, of subtrees
+#+cindex: copying, of subtrees
+#+cindex: sorting, of subtrees
+#+cindex: subtrees, cut and paste
+
+#+attr_texinfo: :sep ,
+- {{{kbd(M-RET)}}} (~org-meta-return~) ::
+
+  #+kindex: M-RET
+  #+findex: org-meta-return
+  #+vindex: org-M-RET-may-split-line
+  Insert a new heading, item or row.
+
+  If the command is used at the /beginning/ of a line, and if there is
+  a heading or a plain list item (see [[*Plain Lists]]) at point, the new
+  heading/item is created /before/ the current line.  When used at the
+  beginning of a regular line of text, turn that line into a heading.
+
+  When this command is used in the middle of a line, the line is split
+  and the rest of the line becomes the new item or headline.  If you
+  do not want the line to be split, customize
+  ~org-M-RET-may-split-line~.
+
+  Calling the command with a {{{kbd(C-u)}}} prefix unconditionally
+  inserts a new heading at the end of the current subtree, thus
+  preserving its contents.  With a double {{{kbd(C-u C-u)}}} prefix,
+  the new heading is created at the end of the parent subtree instead.
+
+- {{{kbd(C-RET)}}} (~org-insert-heading-respect-content~) ::
+
+  #+kindex: C-RET
+  #+findex: org-insert-heading-respect-content
+  Insert a new heading at the end of the current subtree.
+
+- {{{kbd(M-S-RET)}}} (~org-insert-todo-heading~) ::
+
+  #+kindex: M-S-RET
+  #+findex: org-insert-todo-heading
+  #+vindex: org-treat-insert-todo-heading-as-state-change
+  Insert new TODO entry with same level as current heading.  See also
+  the variable ~org-treat-insert-todo-heading-as-state-change~.
+
+- {{{kbd(C-S-RET)}}} (~org-insert-todo-heading-respect-content~) ::
+
+  #+kindex: C-S-RET
+  #+findex: org-insert-todo-heading-respect-content
+  Insert new TODO entry with same level as current heading.  Like
+  {{{kbd(C-RET)}}}, the new headline is inserted after the current
+  subtree.
+
+- {{{kbd(TAB)}}} (~org-cycle~) ::
+
+  #+kindex: TAB
+  #+findex: org-cycle
+  In a new entry with no text yet, the first {{{kbd(TAB)}}} demotes
+  the entry to become a child of the previous one.  The next
+  {{{kbd(TAB)}}} makes it a parent, and so on, all the way to top
+  level.  Yet another {{{kbd(TAB)}}}, and you are back to the initial
+  level.
+
+- {{{kbd(M-LEFT)}}} (~org-do-promote~), {{{kbd(M-RIGHT)}}} (~org-do-demote~) ::
+
+  #+kindex: M-LEFT
+  #+findex: org-do-promote
+  #+kindex: M-RIGHT
+  #+findex: org-do-demote
+  Promote or demote current heading by one level.
+
+  #+cindex: region, active
+  #+cindex: active region
+  #+cindex: transient mark mode
+  When there is an active region---i.e., when Transient Mark mode is
+  active---promotion and demotion work on all headlines in the region.
+  To select a region of headlines, it is best to place both point and
+  mark at the beginning of a line, mark at the beginning of the first
+  headline, and point at the line just after the last headline to
+  change.
+
+- {{{kbd(M-S-LEFT)}}} (~org-promote-subtree~) ::
+
+  #+kindex: M-S-LEFT
+  #+findex: org-promote-subtree
+  Promote the current subtree by one level.
+
+- {{{kbd(M-S-RIGHT)}}} (~org-demote-subtree~) ::
+
+  #+kindex: M-S-RIGHT
+  #+findex: org-demote-subtree
+  Demote the current subtree by one level.
+
+- {{{kbd(M-UP)}}} (~org-move-subtree-up~) ::
+
+  #+kindex: M-UP
+  #+findex: org-move-subtree-up
+  Move subtree up, i.e., swap with previous subtree of same level.
+
+- {{{kbd(M-DOWN)}}} (~org-move-subtree-down~) ::
+
+  #+kindex: M-DOWN
+  #+findex: org-move-subtree-down
+  Move subtree down, i.e., swap with next subtree of same level.
+
+- {{{kbd(C-c @)}}} (~org-mark-subtree~) ::
+
+  #+kindex: C-c @@
+  #+findex: org-mark-subtree
+  Mark the subtree at point.  Hitting repeatedly marks subsequent
+  subtrees of the same level as the marked subtree.
+
+- {{{kbd(C-c C-x C-w)}}} (~org-cut-subtree~) ::
+
+  #+kindex: C-c C-x C-w
+  #+findex: org-cut-subtree
+  Kill subtree, i.e., remove it from buffer but save in kill ring.
+  With a numeric prefix argument N, kill N sequential subtrees.
+
+- {{{kbd(C-c C-x M-w)}}} (~org-copy-subtree~) ::
+
+  #+kindex: C-c C-x M-w
+  #+findex: org-copy-subtree
+  Copy subtree to kill ring.  With a numeric prefix argument N, copy
+  the N sequential subtrees.
+
+- {{{kbd(C-c C-x C-y)}}} (~org-paste-subtree~) ::
+
+  #+kindex: C-c C-x C-y
+  #+findex: org-paste-subtree
+  Yank subtree from kill ring.  This does modify the level of the
+  subtree to make sure the tree fits in nicely at the yank position.
+  The yank level can also be specified with a numeric prefix argument,
+  or by yanking after a headline marker like =****=.
+
+- {{{kbd(C-y)}}} (~org-yank~) ::
+
+  #+kindex: C-y
+  #+findex: org-yank
+  #+vindex: org-yank-adjusted-subtrees
+  #+vindex: org-yank-folded-subtrees
+  Depending on the variables ~org-yank-adjusted-subtrees~ and
+  ~org-yank-folded-subtrees~, Org's internal ~yank~ command pastes
+  subtrees folded and in a clever way, using the same command as
+  {{{kbd(C-c C-x C-y)}}}.  With the default settings, no level
+  adjustment takes place, but the yanked tree is folded unless doing
+  so would swallow text previously visible.  Any prefix argument to
+  this command forces a normal ~yank~ to be executed, with the prefix
+  passed along.  A good way to force a normal yank is {{{kbd(C-u
+  C-y)}}}.  If you use ~yank-pop~ after a yank, it yanks previous kill
+  items plainly, without adjustment and folding.
+
+- {{{kbd(C-c C-x c)}}} (~org-clone-subtree-with-time-shift~) ::
+
+  #+kindex: C-c C-x c
+  #+findex: org-clone-subtree-with-time-shift
+  Clone a subtree by making a number of sibling copies of it.  You are
+  prompted for the number of copies to make, and you can also specify
+  if any timestamps in the entry should be shifted.  This can be
+  useful, for example, to create a number of tasks related to a series
+  of lectures to prepare.  For more details, see the docstring of the
+  command ~org-clone-subtree-with-time-shift~.
+
+- {{{kbd(C-c C-w)}}} (~org-refile~) ::
+
+  #+kindex: C-c C-w
+  #+findex: org-refile
+  Refile entry or region to a different location.  See [[*Refile and
+  Copy]].
+
+- {{{kbd(C-c ^)}}} (~org-sort~) ::
+
+  #+kindex: C-c ^
+  #+findex: org-sort
+  Sort same-level entries.  When there is an active region, all
+  entries in the region are sorted.  Otherwise the children of the
+  current headline are sorted.  The command prompts for the sorting
+  method, which can be alphabetically, numerically, by time---first
+  timestamp with active preferred, creation time, scheduled time,
+  deadline time---by priority, by TODO keyword---in the sequence the
+  keywords have been defined in the setup---or by the value of
+  a property.  Reverse sorting is possible as well.  You can also
+  supply your own function to extract the sorting key.  With
+  a {{{kbd(C-u)}}} prefix, sorting is case-sensitive.
+
+- {{{kbd(C-x n s)}}} (~org-narrow-to-subtree~) ::
+
+  #+kindex: C-x n s
+  #+findex: org-narrow-to-subtree
+  Narrow buffer to current subtree.
+
+- {{{kbd(C-x n b)}}} (~org-narrow-to-block~) ::
+
+  #+kindex: C-x n b
+  #+findex: org-narrow-to-block
+  Narrow buffer to current block.
+
+- {{{kbd(C-x n w)}}} (~widen~) ::
+
+  #+kindex: C-x n w
+  #+findex: widen
+  Widen buffer to remove narrowing.
+
+- {{{kbd(C-c *)}}} (~org-toggle-heading~) ::
+
+  #+kindex: C-c *
+  #+findex: org-toggle-heading
+  Turn a normal line or plain list item into a headline---so that it
+  becomes a subheading at its location.  Also turn a headline into
+  a normal line by removing the stars.  If there is an active region,
+  turn all lines in the region into headlines.  If the first line in
+  the region was an item, turn only the item lines into headlines.
+  Finally, if the first line is a headline, remove the stars from all
+  headlines in the region.
+
+Note that when point is inside a table (see [[*Tables]]), the Meta-Cursor
+keys have different functionality.
+
+** Sparse Trees
+:PROPERTIES:
+:DESCRIPTION: Matches embedded in context.
+:END:
+#+cindex: sparse trees
+#+cindex: trees, sparse
+#+cindex: folding, sparse trees
+#+cindex: occur, command
+
+#+vindex: org-show-context-detail
+An important feature of Org mode is the ability to construct /sparse
+trees/ for selected information in an outline tree, so that the entire
+document is folded as much as possible, but the selected information
+is made visible along with the headline structure above it[fn:7].
+Just try it out and you will see immediately how it works.
+
+Org mode contains several commands creating such trees, all these
+commands can be accessed through a dispatcher:
+
+- {{{kbd(C-c /)}}} (~org-sparse-tree~) ::
+
+  #+kindex: C-c /
+  #+findex: org-sparse-tree
+  This prompts for an extra key to select a sparse-tree creating
+  command.
+
+- {{{kbd(C-c / r)}}} or {{{kbd(C-c / /)}}} (~org-occur~) ::
+
+  #+kindex: C-c / r
+  #+kindex: C-c / /
+  #+findex: org-occur
+  #+vindex: org-remove-highlights-with-change
+  Prompts for a regexp and shows a sparse tree with all matches.  If
+  the match is in a headline, the headline is made visible.  If the
+  match is in the body of an entry, headline and body are made
+  visible.  In order to provide minimal context, also the full
+  hierarchy of headlines above the match is shown, as well as the
+  headline following the match.  Each match is also highlighted; the
+  highlights disappear when the buffer is changed by an editing
+  command, or by pressing {{{kbd(C-c C-c)}}}[fn:8].  When called with
+  a {{{kbd(C-u)}}} prefix argument, previous highlights are kept, so
+  several calls to this command can be stacked.
+
+- {{{kbd(M-g n)}}} or {{{kbd(M-g M-n)}}} (~next-error~) ::
+
+  #+kindex: M-g n
+  #+kindex: M-g M-n
+  #+findex: next-error
+  Jump to the next sparse tree match in this buffer.
+
+- {{{kbd(M-g p)}}} or {{{kbd(M-g M-p)}}} (~previous-error~) ::
+
+  #+kindex: M-g p
+  #+kindex: M-g M-p
+  #+findex: previous-error
+  Jump to the previous sparse tree match in this buffer.
+
+#+vindex: org-agenda-custom-commands
+For frequently used sparse trees of specific search strings, you can
+use the variable ~org-agenda-custom-commands~ to define fast keyboard
+access to specific sparse trees.  These commands will then be
+accessible through the agenda dispatcher (see [[*The Agenda Dispatcher]]).
+For example:
+
+#+begin_src emacs-lisp
+(setq org-agenda-custom-commands
+      '(("f" occur-tree "FIXME")))
+#+end_src
+
+#+texinfo: @noindent
+defines the key {{{kbd(f)}}} as a shortcut for creating a sparse tree
+matching the string =FIXME=.
+
+The other sparse tree commands select headings based on TODO keywords,
+tags, or properties and are discussed later in this manual.
+
+#+kindex: C-c C-e C-v
+#+cindex: printing sparse trees
+#+cindex: visible text, printing
+To print a sparse tree, you can use the Emacs command
+~ps-print-buffer-with-faces~ which does not print invisible parts of
+the document.  Or you can use the command {{{kbd(C-c C-e C-v)}}} to
+export only the visible part of the document and print the resulting
+file.
+
+** Plain Lists
+:PROPERTIES:
+:DESCRIPTION: Additional structure within an entry.
+:END:
+#+cindex: plain lists
+#+cindex: lists, plain
+#+cindex: lists, ordered
+#+cindex: ordered lists
+
+Within an entry of the outline tree, hand-formatted lists can provide
+additional structure.  They also provide a way to create lists of
+checkboxes (see [[*Checkboxes]]).  Org supports editing such lists, and
+every exporter (see [[*Exporting]]) can parse and format them.
+
+Org knows ordered lists, unordered lists, and description lists.
+
+#+attr_texinfo: :indic @bullet
+- /Unordered/ list items start with =-=, =+=, or =*=[fn:9] as bullets.
+
+-
+  #+vindex: org-plain-list-ordered-item-terminator
+  #+vindex: org-alphabetical-lists
+  /Ordered/ list items start with a numeral followed by either
+  a period or a right parenthesis[fn:10], such as =1.= or =1)=[fn:11]
+  If you want a list to start with a different value---e.g.,
+  20---start the text of the item with =[@20]=[fn:12].  Those
+  constructs can be used in any item of the list in order to enforce
+  a particular numbering.
+
+- /Description/ list items are unordered list items, and contain the
+  separator =::= to distinguish the description /term/ from the
+  description.
+
+Items belonging to the same list must have the same indentation on the
+first line.  In particular, if an ordered list reaches number =10.=,
+then the 2-digit numbers must be written left-aligned with the other
+numbers in the list.  An item ends before the next line that is less
+or equally indented than its bullet/number.
+
+A list ends whenever every item has ended, which means before any line
+less or equally indented than items at top level.  It also ends before
+two blank lines.  In that case, all items are closed.  Here is an
+example:
+
+#+begin_example
+,* Lord of the Rings
+My favorite scenes are (in this order)
+1. The attack of the Rohirrim
+2. Eowyn's fight with the witch king
+   + this was already my favorite scene in the book
+   + I really like Miranda Otto.
+3. Peter Jackson being shot by Legolas
+   - on DVD only
+   He makes a really funny face when it happens.
+But in the end, no individual scenes matter but the film as a whole.
+Important actors in this film are:
+- Elijah Wood :: He plays Frodo
+- Sean Astin :: He plays Sam, Frodo's friend.  I still remember him
+     very well from his role as Mikey Walsh in /The Goonies/.
+#+end_example
+
+Org supports these lists by tuning filling and wrapping commands to
+deal with them correctly, and by exporting them properly (see
+[[*Exporting]]).  Since indentation is what governs the structure of these
+lists, many structural constructs like =#+BEGIN_= blocks can be
+indented to signal that they belong to a particular item.
+
+#+vindex: org-list-demote-modify-bullet
+#+vindex: org-list-indent-offset
+If you find that using a different bullet for a sub-list---than that
+used for the current list-level---improves readability, customize the
+variable ~org-list-demote-modify-bullet~.  To get a greater difference
+of indentation between items and theirs sub-items, customize
+~org-list-indent-offset~.
+
+#+vindex: org-list-automatic-rules
+The following commands act on items when point is in the first line of
+an item---the line with the bullet or number.  Some of them imply the
+application of automatic rules to keep list structure intact.  If some
+of these actions get in your way, configure ~org-list-automatic-rules~
+to disable them individually.
+
+#+attr_texinfo: :sep ,
+- {{{kbd(TAB)}}} (~org-cycle~) ::
+
+  #+cindex: cycling, in plain lists
+  #+kindex: TAB
+  #+findex: org-cycle
+  #+vindex: org-cycle-include-plain-lists
+  Items can be folded just like headline levels.  Normally this works
+  only if point is on a plain list item.  For more details, see the
+  variable ~org-cycle-include-plain-lists~.  If this variable is set
+  to ~integrate~, plain list items are treated like low-level
+  headlines.  The level of an item is then given by the indentation of
+  the bullet/number.  Items are always subordinate to real headlines,
+  however; the hierarchies remain completely separated.  In a new item
+  with no text yet, the first {{{kbd(TAB)}}} demotes the item to
+  become a child of the previous one.  Subsequent {{{kbd(TAB)}}}s move
+  the item to meaningful levels in the list and eventually get it back
+  to its initial position.
+
+- {{{kbd(M-RET)}}} (~org-insert-heading~) ::
+
+  #+kindex: M-RET
+  #+findex: org-insert-heading
+  #+vindex: org-M-RET-may-split-line
+  Insert new item at current level.  With a prefix argument, force
+  a new heading (see [[*Structure Editing]]).  If this command is used in
+  the middle of an item, that item is /split/ in two, and the second
+  part becomes the new item[fn:13].  If this command is executed
+  /before item's body/, the new item is created /before/ the current
+  one.
+
+- {{{kbd(M-S-RET)}}} ::
+
+  #+kindex: M-S-RET
+  Insert a new item with a checkbox (see [[*Checkboxes]]).
+
+- {{{kbd(S-UP)}}}, {{{kbd(S-DOWN)}}} ::
+
+  #+kindex: S-UP
+  #+kindex: S-DOWN
+  #+cindex: shift-selection-mode
+  #+vindex: org-support-shift-select
+  #+vindex: org-list-use-circular-motion
+  Jump to the previous/next item in the current list, but only if
+  ~org-support-shift-select~ is off[fn:14].  If not, you can still use
+  paragraph jumping commands like {{{kbd(C-UP)}}} and
+  {{{kbd(C-DOWN)}}} to quite similar effect.
+
+- {{{kbd(M-UP)}}}, {{{kbd(M-DOWN)}}} ::
+
+  #+kindex: M-UP
+  #+kindex: M-DOWN
+  Move the item including subitems up/down[fn:15], i.e., swap with
+  previous/next item of same indentation.  If the list is ordered,
+  renumbering is automatic.
+
+- {{{kbd(M-LEFT)}}}, {{{kbd(M-RIGHT)}}} ::
+
+  #+kindex: M-LEFT
+  #+kindex: M-RIGHT
+  Decrease/increase the indentation of an item, leaving children
+  alone.
+
+- {{{kbd(M-S-LEFT)}}}, {{{kbd(M-S-RIGHT)}}} ::
+
+  #+kindex: M-S-LEFT
+  #+kindex: M-S-RIGHT
+  Decrease/increase the indentation of the item, including subitems.
+  Initially, the item tree is selected based on current indentation.
+  When these commands are executed several times in direct succession,
+  the initially selected region is used, even if the new indentation
+  would imply a different hierarchy.  To use the new hierarchy, break
+  the command chain by moving point.
+
+  As a special case, using this command on the very first item of
+  a list moves the whole list.  This behavior can be disabled by
+  configuring ~org-list-automatic-rules~.  The global indentation of
+  a list has no influence on the text /after/ the list.
+
+- {{{kbd(C-c C-c)}}} ::
+
+  #+kindex: C-c C-c
+  If there is a checkbox (see [[*Checkboxes]]) in the item line, toggle
+  the state of the checkbox.  In any case, verify bullets and
+  indentation consistency in the whole list.
+
+- {{{kbd(C-c -)}}} ::
+
+  #+kindex: C-c -
+  #+vindex: org-plain-list-ordered-item-terminator
+  Cycle the entire list level through the different itemize/enumerate
+  bullets (=-=, =+=, =*=, =1.=, =1)=) or a subset of them, depending
+  on ~org-plain-list-ordered-item-terminator~, the type of list, and
+  its indentation.  With a numeric prefix argument N, select the Nth
+  bullet from this list.  If there is an active region when calling
+  this, all lines are converted to list items.  With a prefix
+  argument, the selected text is changed into a single item.  If the
+  first line already was a list item, any item marker is removed from
+  the list.  Finally, even without an active region, a normal line is
+  converted into a list item.
+
+- {{{kbd(C-c *)}}} ::
+
+  #+kindex: C-c *
+  Turn a plain list item into a headline---so that it becomes
+  a subheading at its location.  See [[*Structure Editing]], for
+  a detailed explanation.
+
+- {{{kbd(C-c C-*)}}} ::
+
+  #+kindex: C-c C-*
+  Turn the whole plain list into a subtree of the current heading.
+  Checkboxes (see [[*Checkboxes]]) become =TODO=, respectively =DONE=,
+  keywords when unchecked, respectively checked.
+
+- {{{kbd(S-LEFT)}}}, {{{kbd(S-RIGHT)}}} ::
+
+  #+vindex: org-support-shift-select
+  #+kindex: S-LEFT
+  #+kindex: S-RIGHT
+  This command also cycles bullet styles when point is in on the
+  bullet or anywhere in an item line, details depending on
+  ~org-support-shift-select~.
+
+- {{{kbd(C-c ^)}}} ::
+
+  #+kindex: C-c ^
+  #+cindex: sorting, of plain list
+  Sort the plain list.  Prompt for the sorting method: numerically,
+  alphabetically, by time, or by custom function.
+
+** Drawers
+:PROPERTIES:
+:DESCRIPTION: Tucking stuff away.
+:END:
+#+cindex: drawers
+#+cindex: visibility cycling, drawers
+
+Sometimes you want to keep information associated with an entry, but
+you normally do not want to see it.  For this, Org mode has /drawers/.
+They can contain anything but a headline and another drawer.  Drawers
+look like this:
+
+#+begin_example
+,** This is a headline
+Still outside the drawer
+:DRAWERNAME:
+This is inside the drawer.
+:END:
+After the drawer.
+#+end_example
+
+#+kindex: C-c C-x d
+#+findex: org-insert-drawer
+You can interactively insert a drawer at point by calling
+~org-insert-drawer~, which is bound to {{{kbd(C-c C-x d)}}}.  With an
+active region, this command puts the region inside the drawer.  With
+a prefix argument, this command calls ~org-insert-property-drawer~,
+which creates a =PROPERTIES= drawer right below the current headline.
+Org mode uses this special drawer for storing properties (see
+[[*Properties and Columns]]).  You cannot use it for anything else.
+
+Completion over drawer keywords is also possible using
+{{{kbd(M-TAB)}}}[fn:16].
+
+Visibility cycling (see [[*Visibility Cycling]]) on the headline hides and
+shows the entry, but keep the drawer collapsed to a single line.  In
+order to look inside the drawer, you need to move point to the drawer
+line and press {{{kbd(TAB)}}} there.
+
+You can also arrange for state change notes (see [[Tracking TODO state
+changes]]) and clock times (see [[*Clocking Work Time]]) to be stored in
+a =LOGBOOK= drawer.  If you want to store a quick note there, in
+a similar way to state changes, use
+
+- {{{kbd(C-c C-z)}}} ::
+
+  #+kindex: C-c C-z
+  Add a time-stamped note to the =LOGBOOK= drawer.
+
+** Blocks
+:PROPERTIES:
+:DESCRIPTION: Folding blocks.
+:END:
+#+vindex: org-hide-block-startup
+#+cindex: blocks, folding
+
+Org mode uses =#+BEGIN= ... =#+END= blocks for various purposes from
+including source code examples (see [[*Literal Examples]]) to capturing
+time logging information (see [[*Clocking Work Time]]).  These blocks can
+be folded and unfolded by pressing {{{kbd(TAB)}}} in the =#+BEGIN=
+line.  You can also get all blocks folded at startup by configuring
+the variable ~org-hide-block-startup~ or on a per-file basis by using
+
+#+cindex: STARTUP, keyword
+#+begin_example
+,#+STARTUP: hideblocks
+,#+STARTUP: nohideblocks
+#+end_example
+
+* Tables
+:PROPERTIES:
+:DESCRIPTION: Pure magic for quick formatting.
+:END:
+#+cindex: tables
+#+cindex: editing tables
+
+Org comes with a fast and intuitive table editor.  Spreadsheet-like
+calculations are supported using the Emacs Calc package (see [[info:calc][GNU 
Emacs
+Calculator Manual]]).
+
+** Built-in Table Editor
+:PROPERTIES:
+:DESCRIPTION: Simple tables.
+:END:
+#+cindex: table editor, built-in
+
+#+cindex: header lines, in tables
+#+cindex: horizontal rule, in tables
+#+cindex: row separator, in tables
+#+cindex: table syntax
+Org makes it easy to format tables in plain ASCII.  Any line with =|=
+as the first non-whitespace character is considered part of a table.
+=|= is also the column separator[fn:17].  Moreover, a line starting
+with =|-= is a horizontal rule.  It separates rows explicitly.  Rows
+before the first horizontal rule are header lines.  A table might look
+like this:
+
+#+begin_example
+| Name  | Phone | Age |
+|-------+-------+-----|
+| Peter |  1234 |  17 |
+| Anna  |  4321 |  25 |
+#+end_example
+
+A table is re-aligned automatically each time you press
+{{{kbd(TAB)}}}, {{{kbd(RET)}}} or {{{kbd(C-c C-c)}}} inside the table.
+{{{kbd(TAB)}}} also moves to the next field---{{{kbd(RET)}}} to the
+next row---and creates new table rows at the end of the table or
+before horizontal lines.  The indentation of the table is set by the
+first line.  Horizontal rules are automatically expanded on every
+re-align to span the whole table width.  So, to create the above
+table, you would only type
+
+#+begin_example
+|Name|Phone|Age|
+|-
+#+end_example
+
+#+texinfo: @noindent
+and then press {{{kbd(TAB)}}} to align the table and start filling in
+fields.  Even faster would be to type =|Name|Phone|Age= followed by
+{{{kbd(C-c RET)}}}.
+
+When typing text into a field, Org treats {{{kbd(DEL)}}},
+{{{kbd(Backspace)}}}, and all character keys in a special way, so that
+inserting and deleting avoids shifting other fields.  Also, when
+typing /immediately/ after point was moved into a new field with
+{{{kbd(TAB)}}}, {{{kbd(S-TAB)}}} or {{{kbd(RET)}}}, the field is
+automatically made blank.  If this behavior is too unpredictable for
+you, configure the option ~org-table-auto-blank-field~.
+
+*** Creation and conversion
+:PROPERTIES:
+:UNNUMBERED: notoc
+:END:
+
+- {{{kbd(C-c |)}}} (~org-table-create-or-convert-from-region~) ::
+
+  #+kindex: C-c |
+  #+findex: org-table-create-or-convert-from-region
+  Convert the active region to table.  If every line contains at least
+  one {{{kbd(TAB)}}} character, the function assumes that the material
+  is tab separated.  If every line contains a comma, comma-separated
+  values (CSV) are assumed.  If not, lines are split at whitespace
+  into fields.  You can use a prefix argument to force a specific
+  separator: {{{kbd(C-u)}}} forces CSV, {{{kbd(C-u C-u)}}} forces
+  {{{kbd(TAB)}}}, {{{kbd(C-u C-u C-u)}}} prompts for a regular
+  expression to match the separator, and a numeric argument
+  N indicates that at least N consecutive spaces, or alternatively
+  a {{{kbd(TAB)}}} will be the separator.
+
+  If there is no active region, this command creates an empty Org
+  table.  But it is easier just to start typing, like {{{kbd(|
+  N a m e | P h o n e | A g e RET | - TAB)}}}.
+
+*** Re-aligning and field motion
+:PROPERTIES:
+:UNNUMBERED: notoc
+:END:
+
+- {{{kbd(C-c C-c)}}} (~org-table-align~) ::
+
+  #+kindex: C-c C-c
+  #+findex: org-table-align
+  Re-align the table without moving point.
+
+- {{{kbd(TAB)}}} (~org-table-next-field~) ::
+
+  #+kindex: TAB
+  #+findex: org-table-next-field
+  Re-align the table, move to the next field.  Creates a new row if
+  necessary.
+
+- {{{kbd(C-c SPC)}}} (~org-table-blank-field~) ::
+
+  #+kindex: C-c SPC
+  #+findex: org-table-blank-field
+  Blank the field at point.
+
+- {{{kbd(S-TAB)}}} (~org-table-previous-field~) ::
+
+  #+kindex: S-TAB
+  #+findex: org-table-previous-field
+  Re-align, move to previous field.
+
+- {{{kbd(RET)}}} (~org-table-next-row~) ::
+
+  #+kindex: RET
+  #+findex: org-table-next-row
+  Re-align the table and move down to next row.  Creates a new row if
+  necessary.  At the beginning or end of a line, {{{kbd(RET)}}} still
+  inserts a new line, so it can be used to split a table.
+
+- {{{kbd(M-a)}}} (~org-table-beginning-of-field~) ::
+
+  #+kindex: M-a
+  #+findex: org-table-beginning-of-field
+  Move to beginning of the current table field, or on to the previous
+  field.
+
+- {{{kbd(M-e)}}} (~org-table-end-of-field~) ::
+
+  #+kindex: M-e
+  #+findex: org-table-end-of-field
+  Move to end of the current table field, or on to the next field.
+
+*** Column and row editing
+:PROPERTIES:
+:UNNUMBERED: notoc
+:END:
+
+- {{{kbd(M-LEFT)}}} (~org-table-move-column-left~) ::
+
+  #+kindex: M-LEFT
+  #+findex: org-table-move-column-left
+  Move the current column left.
+
+- {{{kbd(M-RIGHT)}}} (~org-table-move-column-right~) ::
+
+  #+kindex: M-RIGHT
+  #+findex: org-table-move-column-right
+  Move the current column right.
+
+- {{{kbd(M-S-LEFT)}}} (~org-table-delete-column~) ::
+
+  #+kindex: M-S-LEFT
+  #+findex: org-table-delete-column
+  Kill the current column.
+
+- {{{kbd(M-S-RIGHT)}}} (~org-table-insert-column~) ::
+
+  #+kindex: M-S-RIGHT
+  #+findex: org-table-insert-column
+  Insert a new column at point position.  Move the recent column and
+  all cells to the right of this column to the right.
+
+- {{{kbd(M-UP)}}} (~org-table-move-row-up~) ::
+
+  #+kindex: M-UP
+  #+findex: org-table-move-row-up
+  Move the current row up.
+
+- {{{kbd(M-DOWN)}}} (~org-table-move-row-down~) ::
+
+  #+kindex: M-DOWN
+  #+findex: org-table-move-row-down
+  Move the current row down.
+
+- {{{kbd(M-S-UP)}}} (~org-table-kill-row~) ::
+
+  #+kindex: M-S-UP
+  #+findex: org-table-kill-row
+  Kill the current row or horizontal line.
+
+- {{{kbd(S-UP)}}} (~org-table-move-cell-up~) ::
+
+  #+kindex: S-UP
+  #+findex: org-table-move-cell-up
+  Move cell up by swapping with adjacent cell.
+
+- {{{kbd(S-DOWN)}}} (~org-table-move-cell-down~) ::
+
+  #+kindex: S-DOWN
+  #+findex: org-table-move-cell-down
+  Move cell down by swapping with adjacent cell.
+
+- {{{kbd(S-LEFT)}}} (~org-table-move-cell-left~) ::
+
+  #+kindex: S-LEFT
+  #+findex: org-table-move-cell-left
+  Move cell left by swapping with adjacent cell.
+
+- {{{kbd(S-RIGHT)}}} (~org-table-move-cell-right~) ::
+
+  #+kindex: S-RIGHT
+  #+findex: org-table-move-cell-right
+  Move cell right by swapping with adjacent cell.
+
+- {{{kbd(M-S-DOWN)}}} (~org-table-insert-row~) ::
+
+  #+kindex: M-S-DOWN
+  #+findex: org-table-insert-row
+  Insert a new row above the current row.  With a prefix argument, the
+  line is created below the current one.
+
+- {{{kbd(C-c -)}}} (~org-table-insert-hline~) ::
+
+  #+kindex: C-c -
+  #+findex: org-table-insert-hline
+  Insert a horizontal line below current row.  With a prefix argument,
+  the line is created above the current line.
+
+- {{{kbd(C-c RET)}}} (~org-table-hline-and-move~) ::
+
+  #+kindex: C-c RET
+  #+findex: org-table-hline-and-move
+  Insert a horizontal line below current row, and move point into the
+  row below that line.
+
+- {{{kbd(C-c ^)}}} (~org-table-sort-lines~) ::
+
+  #+kindex: C-c ^
+  #+findex: org-table-sort-lines
+  Sort the table lines in the region.  The position of point indicates
+  the column to be used for sorting, and the range of lines is the
+  range between the nearest horizontal separator lines, or the entire
+  table.  If point is before the first column, you are prompted for
+  the sorting column.  If there is an active region, the mark
+  specifies the first line and the sorting column, while point should
+  be in the last line to be included into the sorting.  The command
+  prompts for the sorting type, alphabetically, numerically, or by
+  time.  You can sort in normal or reverse order.  You can also supply
+  your own key extraction and comparison functions.  When called with
+  a prefix argument, alphabetic sorting is case-sensitive.
+
+*** Regions
+:PROPERTIES:
+:UNNUMBERED: notoc
+:END:
+
+- {{{kbd(C-c C-x M-w)}}} (~org-table-copy-region~) ::
+
+  #+kindex: C-c C-x M-w
+  #+findex: org-table-copy-region
+  Copy a rectangular region from a table to a special clipboard.
+  Point and mark determine edge fields of the rectangle.  If there is
+  no active region, copy just the current field.  The process ignores
+  horizontal separator lines.
+
+- {{{kbd(C-c C-x C-w)}}} (~org-table-cut-region~) ::
+
+  #+kindex: C-c C-x C-w
+  #+findex: org-table-cut-region
+  Copy a rectangular region from a table to a special clipboard, and
+  blank all fields in the rectangle.  So this is the "cut" operation.
+
+- {{{kbd(C-c C-x C-y)}}} (~org-table-paste-rectangle~) ::
+
+  #+kindex: C-c C-x C-y
+  #+findex: org-table-paste-rectangle
+  Paste a rectangular region into a table.  The upper left corner ends
+  up in the current field.  All involved fields are overwritten.  If
+  the rectangle does not fit into the present table, the table is
+  enlarged as needed.  The process ignores horizontal separator lines.
+
+- {{{kbd(M-RET)}}} (~org-table-wrap-region~) ::
+
+  #+kindex: M-RET
+  #+findex: org-table-wrap-region
+  Split the current field at point position and move the rest to the
+  line below.  If there is an active region, and both point and mark
+  are in the same column, the text in the column is wrapped to minimum
+  width for the given number of lines.  A numeric prefix argument may
+  be used to change the number of desired lines.  If there is no
+  region, but you specify a prefix argument, the current field is made
+  blank, and the content is appended to the field above.
+
+*** Calculations
+:PROPERTIES:
+:UNNUMBERED: notoc
+:END:
+
+#+cindex: formula, in tables
+#+cindex: calculations, in tables
+
+- {{{kbd(C-c +)}}} (~org-table-sum~) ::
+
+  #+kindex: C-c +
+  #+findex: org-table-sum
+  Sum the numbers in the current column, or in the rectangle defined
+  by the active region.  The result is shown in the echo area and can
+  be inserted with {{{kbd(C-y)}}}.
+
+- {{{kbd(S-RET)}}} (~org-table-copy-down~) ::
+
+  #+kindex: S-RET
+  #+findex: org-table-copy-down
+  #+vindex: org-table-copy-increment
+  When current field is empty, copy from first non-empty field above.
+  When not empty, copy current field down to next row and move point
+  along with it.
+
+  Depending on the variable ~org-table-copy-increment~, integer and
+  time stamp field values, and fields prefixed or suffixed with
+  a whole number, can be incremented during copy.  Also, a ~0~ prefix
+  argument temporarily disables the increment.
+
+  This key is also used by shift-selection and related modes (see
+  [[*Packages that conflict with Org mode]]).
+
+*** Miscellaneous
+:PROPERTIES:
+:UNNUMBERED: notoc
+:END:
+
+- {{{kbd(C-c `)}}} (~org-table-edit-field~) ::
+
+  #+kindex: C-c `
+  #+findex: org-table-edit-field
+  Edit the current field in a separate window.  This is useful for
+  fields that are not fully visible (see [[*Column Width and Alignment]]).
+  When called with a {{{kbd(C-u)}}} prefix, just make the full field
+  visible, so that it can be edited in place.  When called with two
+  {{{kbd(C-u)}}} prefixes, make the editor window follow point through
+  the table and always show the current field.  The follow mode exits
+  automatically when point leaves the table, or when you repeat this
+  command with {{{kbd(C-u C-u C-c `)}}}.
+
+- {{{kbd(M-x org-table-import)}}} ::
+
+  #+findex: org-table-import
+  Import a file as a table.  The table should be TAB or whitespace
+  separated.  Use, for example, to import a spreadsheet table or data
+  from a database, because these programs generally can write
+  TAB-separated text files.  This command works by inserting the file
+  into the buffer and then converting the region to a table.  Any
+  prefix argument is passed on to the converter, which uses it to
+  determine the separator.
+
+- {{{kbd(C-c |)}}} (~org-table-create-or-convert-from-region~) ::
+
+  #+kindex: C-c |
+  #+findex: org-table-create-or-convert-from-region
+  Tables can also be imported by pasting tabular text into the Org
+  buffer, selecting the pasted text with {{{kbd(C-x C-x)}}} and then
+  using the {{{kbd(C-c |)}}} command (see [[*Creation and conversion]]).
+
+- {{{kbd(M-x org-table-export)}}} ::
+
+  #+findex: org-table-export
+  #+vindex: org-table-export-default-format
+  Export the table, by default as a TAB-separated file.  Use for data
+  exchange with, for example, spreadsheet or database programs.  The
+  format used to export the file can be configured in the variable
+  ~org-table-export-default-format~.  You may also use properties
+  =TABLE_EXPORT_FILE= and =TABLE_EXPORT_FORMAT= to specify the file
+  name and the format for table export in a subtree.  Org supports
+  quite general formats for exported tables.  The exporter format is
+  the same as the format used by Orgtbl radio tables, see [[*Translator
+  functions]], for a detailed description.
+
+- {{{kbd(M-x org-table-header-line-mode)}}} ::
+
+  #+findex: org-table-header-line-mode
+  #+vindex: org-table-header-line-p
+  Turn on the display of the first data row of the table at point in
+  the window header line when this first row is not visible anymore in
+  the buffer.  You can activate this minor mode by default by setting
+  the option ~org-table-header-line-p~ to ~t~.
+
+- {{{kbd(M-x org-table-transpose-table-at-point)}}} ::
+
+  #+findex: org-table-transpose-table-at-point
+  Transpose the table at point and eliminate hlines.
+
+** Column Width and Alignment
+:PROPERTIES:
+:DESCRIPTION: Overrule the automatic settings.
+:END:
+#+cindex: narrow columns in tables
+#+cindex: alignment in tables
+
+The width of columns is automatically determined by the table editor.
+The alignment of a column is determined automatically from the
+fraction of number-like versus non-number fields in the column.
+
+#+vindex: org-table-automatic-realign
+Editing a field may modify alignment of the table.  Moving
+a contiguous row or column---i.e., using {{{kbd(TAB)}}} or
+{{{kbd(RET)}}}---automatically re-aligns it.  If you want to disable
+this behavior, set ~org-table-automatic-realign~ to ~nil~.  In any
+case, you can always align manually a table:
+
+- {{{kbd(C-c C-c)}}} (~org-table-align~) ::
+
+  #+kindex: C-c C-c
+  #+findex: org-table-align
+  Align the current table.
+
+#+vindex: org-startup-align-all-tables
+Setting the option ~org-startup-align-all-tables~ re-aligns all tables
+in a file upon visiting it.  You can also set this option on
+a per-file basis with:
+
+#+begin_example
+,#+STARTUP: align
+,#+STARTUP: noalign
+#+end_example
+
+Sometimes a single field or a few fields need to carry more text,
+leading to inconveniently wide columns.  Maybe you want to hide away
+several columns or display them with a fixed width, regardless of
+content, as shown in the following example.
+
+#+begin_example
+|---+---------------------+--------|           |---+-------…+…|
+|   | <6>                 |        |           |   | <6>   …|…|
+| 1 | one                 | some   |   ----\   | 1 | one   …|…|
+| 2 | two                 | boring |   ----/   | 2 | two   …|…|
+| 3 | This is a long text | column |           | 3 | This i…|…|
+|---+---------------------+--------|           |---+-------…+…|
+#+end_example
+
+To set the width of a column, one field anywhere in the column may
+contain just the string =<N>= where {{{var(N)}}} specifies the width
+as a number of characters.  You control displayed width of columns
+with the following tools:
+
+- {{{kbd(C-c TAB)}}} (~org-table-toggle-column-width~) ::
+
+  #+kindex: C-c TAB
+  #+findex: org-table-toggle-column-width
+  Shrink or expand current column.
+
+  If a width cookie specifies a width W for the column, shrinking it
+  displays the first W visible characters only.  Otherwise, the column
+  is shrunk to a single character.
+
+  When called before the first column or after the last one, ask for
+  a list of column ranges to operate on.
+
+- {{{kbd(C-u C-c TAB)}}} (~org-table-shrink~) ::
+
+  #+kindex: C-u C-c TAB
+  #+findex: org-table-shrink
+  Shrink all columns with a column width.  Expand the others.
+
+- {{{kbd(C-u C-u C-c TAB)}}} (~org-table-expand~) ::
+
+  #+kindex: C-u C-u C-c TAB
+  #+findex: org-table-expand
+  Expand all columns.
+
+To see the full text of a shrunk field, hold the mouse over it:
+a tool-tip window then shows the full contents of the field.
+Alternatively, {{{kbd(C-h .)}}} (~display-local-help~) reveals them,
+too.  For convenience, any change near the shrunk part of a column
+expands it.
+
+#+vindex: org-startup-shrink-all-tables
+Setting the option ~org-startup-shrink-all-tables~ shrinks all columns
+containing a width cookie in a file the moment it is visited.  You can
+also set this option on a per-file basis with:
+
+: #+STARTUP: shrink
+
+If you would like to overrule the automatic alignment of number-rich
+columns to the right and of string-rich columns to the left, you can
+use =<r>=, =<c>= or =<l>= in a similar fashion.  You may also combine
+alignment and field width like this: =<r10>=.
+
+Lines which only contain these formatting cookies are removed
+automatically upon exporting the document.
+
+** Column Groups
+:PROPERTIES:
+:DESCRIPTION: Grouping to trigger vertical lines.
+:END:
+#+cindex: grouping columns in tables
+
+When Org exports tables, it does so by default without vertical lines
+because that is visually more satisfying in general.  Occasionally
+however, vertical lines can be useful to structure a table into groups
+of columns, much like horizontal lines can do for groups of rows.  In
+order to specify column groups, you can use a special row where the
+first field contains only =/=.  The further fields can either contain
+=<= to indicate that this column should start a group, =>= to indicate
+the end of a column, or =<>= (no space between =<= and =>=) to make
+a column a group of its own.  Upon export, boundaries between column
+groups are marked with vertical lines.  Here is an example:
+
+#+begin_example
+| N | N^2 | N^3 | N^4 | sqrt(n) | sqrt[4](N) |
+|---+-----+-----+-----+---------+------------|
+| / |  <  |     |  >  |       < |          > |
+| 1 |  1  |  1  |  1  |       1 |          1 |
+| 2 |  4  |  8  | 16  |  1.4142 |     1.1892 |
+| 3 |  9  | 27  | 81  |  1.7321 |     1.3161 |
+|---+-----+-----+-----+---------+------------|
+,#+TBLFM: $2=$1^2::$3=$1^3::$4=$1^4::$5=sqrt($1)::$6=sqrt(sqrt(($1)))
+#+end_example
+
+It is also sufficient to just insert the column group starters after
+every vertical line you would like to have:
+
+#+begin_example
+| N | N^2 | N^3 | N^4 | sqrt(n) | sqrt[4](N) |
+|---+-----+-----+-----+---------+------------|
+| / | <   |     |     | <       |            |
+#+end_example
+
+** The Orgtbl Minor Mode
+:PROPERTIES:
+:DESCRIPTION: The table editor as minor mode.
+:ALT_TITLE: Orgtbl Mode
+:END:
+#+cindex: Orgtbl mode
+#+cindex: minor mode for tables
+
+#+findex: orgtbl-mode
+If you like the intuitive way the Org table editor works, you might
+also want to use it in other modes like Text mode or Mail mode.  The
+minor mode Orgtbl mode makes this possible.  You can always toggle the
+mode with {{{kbd(M-x orgtbl-mode)}}}.  To turn it on by default, for
+example in Message mode, use
+
+#+begin_src emacs-lisp
+(add-hook 'message-mode-hook 'turn-on-orgtbl)
+#+end_src
+
+Furthermore, with some special setup, it is possible to maintain
+tables in arbitrary syntax with Orgtbl mode.  For example, it is
+possible to construct LaTeX tables with the underlying ease and power
+of Orgtbl mode, including spreadsheet capabilities.  For details, see
+[[*Tables in Arbitrary Syntax]].
+
+** The Spreadsheet
+:PROPERTIES:
+:DESCRIPTION: The table editor has spreadsheet capabilities.
+:END:
+#+cindex: calculations, in tables
+#+cindex: spreadsheet capabilities
+#+cindex: Calc package
+
+The table editor makes use of the Emacs Calc package to implement
+spreadsheet-like capabilities.  It can also evaluate Emacs Lisp forms
+to derive fields from other fields.  While fully featured, Org's
+implementation is not identical to other spreadsheets.  For example,
+Org knows the concept of a /column formula/ that will be applied to
+all non-header fields in a column without having to copy the formula
+to each relevant field.  There is also a formula debugger, and a
+formula editor with features for highlighting fields in the table
+corresponding to the references at point in the formula, moving these
+references by arrow keys.
+
+*** References
+:PROPERTIES:
+:DESCRIPTION: How to refer to another field or range.
+:END:
+#+cindex: references
+
+To compute fields in the table from other fields, formulas must
+reference other fields or ranges.  In Org, fields can be referenced by
+name, by absolute coordinates, and by relative coordinates.  To find
+out what the coordinates of a field are, press {{{kbd(C-c ?)}}} in
+that field, or press {{{kbd(C-c })}}} to toggle the display of a grid.
+
+**** Field references
+:PROPERTIES:
+:UNNUMBERED: notoc
+:END:
+
+#+cindex: field references
+#+cindex: references, to fields
+Formulas can reference the value of another field in two ways.  Like
+in any other spreadsheet, you may reference fields with
+a letter/number combination like =B3=, meaning the second field in the
+third row.  However, Org prefers to use another, more general
+representation that looks like this:[fn:18]
+
+: @ROW$COLUMN
+
+Column specifications can be absolute like =$1=, =$2=, ..., =$N=, or
+relative to the current column, i.e., the column of the field which is
+being computed, like =$+1= or =$-2=.  =$<= and =$>= are immutable
+references to the first and last column, respectively, and you can use
+=$>>>= to indicate the third column from the right.
+
+The row specification only counts data lines and ignores horizontal
+separator lines, or "hlines".  Like with columns, you can use absolute
+row numbers =@1=, =@2=, ..., =@N=, and row numbers relative to the
+current row like =@+3= or =@-1=.  =@<= and =@>= are immutable
+references the first and last row in the table, respectively.  You may
+also specify the row relative to one of the hlines: =@I= refers to the
+first hline, =@II= to the second, etc.  =@-I= refers to the first such
+line above the current line, =@+I= to the first such line below the
+current line.  You can also write =@III+2= which is the second data
+line after the third hline in the table.
+
+=@0= and =$0= refer to the current row and column, respectively, i.e.,
+to the row/column for the field being computed.  Also, if you omit
+either the column or the row part of the reference, the current
+row/column is implied.
+
+Org's references with /unsigned/ numbers are fixed references in the
+sense that if you use the same reference in the formula for two
+different fields, the same field is referenced each time.  Org's
+references with /signed/ numbers are floating references because the
+same reference operator can reference different fields depending on
+the field being calculated by the formula.
+
+Here are a few examples:
+
+#+attr_texinfo: :columns 0.2 0.8
+| =@2$3=   | 2nd row, 3rd column (same as =C2=)                 |
+| =$5=     | column 5 in the current row (same as =E&=)         |
+| =@2=     | current column, row 2                              |
+| =@-1$-3= | field one row up, three columns to the left        |
+| =@-I$2=  | field just under hline above current row, column 2 |
+| =@>$5=   | field in the last row, in column 5                 |
+
+**** Range references
+:PROPERTIES:
+:UNNUMBERED: notoc
+:END:
+
+#+cindex: range references
+#+cindex: references, to ranges
+You may reference a rectangular range of fields by specifying two
+field references connected by two dots =..=.  The ends are included in
+the range.  If both fields are in the current row, you may simply use
+=$2..$7=, but if at least one field is in a different row, you need to
+use the general =@ROW$COLUMN= format at least for the first field,
+i.e., the reference must start with =@= in order to be interpreted
+correctly.  Examples:
+
+#+attr_texinfo: :columns 0.2 0.8
+| =$1..$3=      | first three fields in the current row                        
  |
+| =$P..$Q=      | range, using column names (see [[*Advanced features]])       
      |
+| =$<<<..$>>=   | start in third column, continue to the last but one          
  |
+| =@2$1..@4$3=  | nine fields between these two fields (same as =A2..C4=)      
  |
+| =@-1$-2..@-1= | 3 fields in the row above, starting from 2 columns on the 
left |
+| =@I..II=      | between first and second hline, short for =@I..@II=          
  |
+
+#+texinfo: @noindent
+Range references return a vector of values that can be fed into Calc
+vector functions.  Empty fields in ranges are normally suppressed, so
+that the vector contains only the non-empty fields.  For other options
+with the mode switches =E=, =N= and examples, see [[*Formula syntax for
+Calc]].
+
+**** Field coordinates in formulas
+:PROPERTIES:
+:UNNUMBERED: notoc
+:END:
+
+#+cindex: field coordinates
+#+cindex: coordinates, of field
+#+cindex: row, of field coordinates
+#+cindex: column, of field coordinates
+#+vindex: org-table-current-column
+#+vindex: org-table-current-dline
+One of the very first actions during evaluation of Calc formulas and
+Lisp formulas is to substitute =@#= and =$#= in the formula with the
+row or column number of the field where the current result will go to.
+The traditional Lisp formula equivalents are ~org-table-current-dline~
+and ~org-table-current-column~.  Examples:
+
+- =if(@# % 2, $#, string(""))= ::
+
+  Insert column number on odd rows, set field to empty on even rows.
+
+- =$2 = '(identity remote(FOO, @@#$1))= ::
+
+  Copy text or values of each row of column 1 of the table named
+  {{{var(FOO)}}} into column 2 of the current table.
+
+- =@3 = 2 * remote(FOO, @1$$#)= ::
+
+  Insert the doubled value of each column of row 1 of the table
+  named {{{var(FOO)}}} into row 3 of the current table.
+
+#+texinfo: @noindent
+For the second and third examples, table {{{var(FOO)}}} must have at
+least as many rows or columns as the current table.  Note that this is
+inefficient[fn:19] for large number of rows.
+
+**** Named references
+:PROPERTIES:
+:UNNUMBERED: notoc
+:END:
+#+cindex: named references
+#+cindex: references, named
+#+cindex: name, of column or field
+#+cindex: constants, in calculations
+#+cindex: @samp{CONSTANTS}, keyword
+#+vindex: org-table-formula-constants
+
+=$name= is interpreted as the name of a column, parameter or constant.
+Constants are defined globally through the variable
+~org-table-formula-constants~, and locally---for the file---through
+a line like this example:
+
+: #+CONSTANTS: c=299792458. pi=3.14 eps=2.4e-6
+
+#+vindex: constants-unit-system
+#+pindex: constants.el
+Also, properties (see [[*Properties and Columns]]) can be used as
+constants in table formulas: for a property =Xyz= use the name
+=$PROP_Xyz=, and the property will be searched in the current outline
+entry and in the hierarchy above it.  If you have the =constants.el=
+package, it will also be used to resolve constants, including natural
+constants like =$h= for Planck's constant, and units like =$km= for
+kilometers[fn:20].  Column names and parameters can be specified in
+special table lines.  These are described below, see [[*Advanced
+features]].  All names must start with a letter, and further consist
+of letters and numbers.
+
+**** Remote references
+:PROPERTIES:
+:UNNUMBERED: notoc
+:END:
+
+#+cindex: remote references
+#+cindex: references, remote
+#+cindex: references, to a different table
+#+cindex: name, of column or field
+#+cindex: @samp{NAME}, keyword
+You may also reference constants, fields and ranges from a different
+table, either in the current file or even in a different file.  The
+syntax is
+
+: remote(NAME,REF)
+
+#+texinfo: @noindent
+where {{{var(NAME)}}} can be the name of a table in the current file
+as set by a =#+NAME:= line before the table.  It can also be the ID of
+an entry, even in a different file, and the reference then refers to
+the first table in that entry.  {{{var(REF)}}} is an absolute field or
+range reference as described above for example =@3$3= or =$somename=,
+valid in the referenced table.
+
+#+cindex: table indirection
+When {{{var(NAME)}}} has the format =@ROW$COLUMN=, it is substituted
+with the name or ID found in this field of the current table.  For
+example =remote($1, @@>$2)= \Rightarrow =remote(year_2013, @@>$1)=.  The format
+=B3= is not supported because it can not be distinguished from a plain
+table name or ID.
+
+*** Formula syntax for Calc
+:PROPERTIES:
+:DESCRIPTION: Using Calc to compute stuff.
+:END:
+#+cindex: formula syntax, Calc
+#+cindex: syntax, of formulas
+
+A formula can be any algebraic expression understood by the Emacs Calc
+package.  Note that Calc has the non-standard convention that =/= has
+lower precedence than =*=, so that =a/b*c= is interpreted as
+=(a/(b*c))=.  Before evaluation by ~calc-eval~ (see [[info:calc#Calling Calc 
from Your Programs][Calling Calc from
+Your Lisp Programs]]), variable substitution takes place according to
+the rules described above.
+
+#+cindex: vectors, in table calculations
+The range vectors can be directly fed into the Calc vector functions
+like ~vmean~ and ~vsum~.
+
+#+cindex: format specifier, in spreadsheet
+#+cindex: mode, for Calc
+#+vindex: org-calc-default-modes
+A formula can contain an optional mode string after a semicolon.  This
+string consists of flags to influence Calc and other modes during
+execution.  By default, Org uses the standard Calc modes (precision
+12, angular units degrees, fraction and symbolic modes off).  The
+display format, however, has been changed to =(float 8)= to keep
+tables compact.  The default settings can be configured using the
+variable ~org-calc-default-modes~.
+
+- =p20= ::
+
+  Set the internal Calc calculation precision to 20 digits.
+
+- =n3=, =s3=, =e2=, =f4= ::
+
+  Normal, scientific, engineering or fixed format of the result of
+  Calc passed back to Org.  Calc formatting is unlimited in precision
+  as long as the Calc calculation precision is greater.
+
+- =D=, =R= ::
+
+  Degree and radian angle modes of Calc.
+
+- =F=, =S= ::
+
+  Fraction and symbolic modes of Calc.
+
+- =T=, =t=, =U= ::
+
+  Duration computations in Calc or Lisp, [[*Durations and time values]].
+
+- =E= ::
+
+  If and how to consider empty fields.  Without =E= empty fields in
+  range references are suppressed so that the Calc vector or Lisp list
+  contains only the non-empty fields.  With =E= the empty fields are
+  kept.  For empty fields in ranges or empty field references the
+  value =nan= (not a number) is used in Calc formulas and the empty
+  string is used for Lisp formulas.  Add =N= to use 0 instead for both
+  formula types.  For the value of a field the mode =N= has higher
+  precedence than =E=.
+
+- =N= ::
+
+  Interpret all fields as numbers, use 0 for non-numbers.  See the
+  next section to see how this is essential for computations with Lisp
+  formulas.  In Calc formulas it is used only occasionally because
+  there number strings are already interpreted as numbers without =N=.
+
+- =L= ::
+
+  Literal, for Lisp formulas only.  See the next section.
+
+Unless you use large integer numbers or high-precision calculation and
+display for floating point numbers you may alternatively provide
+a ~printf~ format specifier to reformat the Calc result after it has
+been passed back to Org instead of letting Calc already do the
+formatting[fn:21].  A few examples:
+
+| =$1+$2=            | Sum of first and second field                    |
+| =$1+$2;%.2f=       | Same, format result to two decimals              |
+| =exp($2)+exp($1)=  | Math functions can be used                       |
+| =$0;%.1f=          | Reformat current cell to 1 decimal               |
+| =($3-32)*5/9=      | Degrees F \to C conversion                         |
+| =$c/$1/$cm=        | Hz \to cm conversion, using =constants.el=         |
+| =tan($1);Dp3s1=    | Compute in degrees, precision 3, display SCI 1   |
+| =sin($1);Dp3%.1e=  | Same, but use ~printf~ specifier for display     |
+| =vmean($2..$7)=    | Compute column range mean, using vector function |
+| =vmean($2..$7);EN= | Same, but treat empty fields as 0                |
+| =taylor($3,x=7,2)= | Taylor series of $3, at x=7, second degree       |
+
+Calc also contains a complete set of logical operations (see 
[[info:calc#Logical Operations][Logical
+Operations]]).  For example
+
+- =if($1 < 20, teen, string(""))= ::
+
+  ="teen"= if age =$1= is less than 20, else the Org table result
+  field is set to empty with the empty string.
+
+- =if("$1" =​= "nan" || "$2" =​= "nan", string(""), $1 + $2); E f-1= ::
+
+  Sum of the first two columns.  When at least one of the input fields
+  is empty the Org table result field is set to empty.  =E= is
+  required to not convert empty fields to 0.  =f-1= is an optional
+  Calc format string similar to =%.1f= but leaves empty results empty.
+
+- =if(typeof(vmean($1..$7)) =​= 12, string(""), vmean($1..$7); E= ::
+
+  Mean value of a range unless there is any empty field.  Every field
+  in the range that is empty is replaced by =nan= which lets =vmean=
+  result in =nan=.  Then =typeof == 12= detects the =nan= from ~vmean~
+  and the Org table result field is set to empty.  Use this when the
+  sample set is expected to never have missing values.
+
+- =if("$1..$7" =​= "[]", string(""), vmean($1..$7))= ::
+
+  Mean value of a range with empty fields skipped.  Every field in the
+  range that is empty is skipped.  When all fields in the range are
+  empty the mean value is not defined and the Org table result field
+  is set to empty.  Use this when the sample set can have a variable
+  size.
+
+- =vmean($1..$7); EN= ::
+
+  To complete the example before: Mean value of a range with empty
+  fields counting as samples with value 0.  Use this only when
+  incomplete sample sets should be padded with 0 to the full size.
+
+You can add your own Calc functions defined in Emacs Lisp with
+~defmath~ and use them in formula syntax for Calc.
+
+*** Emacs Lisp forms as formulas
+:PROPERTIES:
+:DESCRIPTION: Writing formulas in Emacs Lisp.
+:ALT_TITLE: Formula syntax for Lisp
+:END:
+#+cindex: Lisp forms, as table formulas
+
+It is also possible to write a formula in Emacs Lisp.  This can be
+useful for string manipulation and control structures, if Calc's
+functionality is not enough.
+
+If a formula starts with a single-quote followed by an opening
+parenthesis, then it is evaluated as a Lisp form.  The evaluation
+should return either a string or a number.  Just as with Calc
+formulas, you can specify modes and a ~printf~ format after
+a semicolon.
+
+With Emacs Lisp forms, you need to be conscious about the way field
+references are interpolated into the form.  By default, a reference is
+interpolated as a Lisp string (in double-quotes) containing the field.
+If you provide the =N= mode switch, all referenced elements are
+numbers---non-number fields will be zero---and interpolated as Lisp
+numbers, without quotes.  If you provide the =L= flag, all fields are
+interpolated literally, without quotes.  For example, if you want a
+reference to be interpreted as a string by the Lisp form, enclose the
+reference operator itself in double-quotes, like ="$3"=.  Ranges are
+inserted as space-separated fields, so you can embed them in list or
+vector syntax.
+
+Here are a few examples---note how the =N= mode is used when we do
+computations in Lisp:
+
+- ='(concat (substring $1 1 2) (substring $1 0 1) (substring $1 2))= ::
+
+  Swap the first two characters of the content of column 1.
+
+- ='(+ $1 $2);N= ::
+
+  Add columns 1 and 2, equivalent to Calc's =$1+$2=.
+
+- ='(apply '+ '($1..$4));N= ::
+
+  Compute the sum of columns 1 to 4, like Calc's =vsum($1..$4)=.
+
+*** Durations and time values
+:PROPERTIES:
+:DESCRIPTION: How to compute durations and time values.
+:END:
+#+cindex: duration, computing
+#+cindex: time, computing
+#+vindex: org-table-duration-custom-format
+
+If you want to compute time values use the =T=, =t=, or =U= flag,
+either in Calc formulas or Elisp formulas:
+
+#+begin_example
+|  Task 1 |   Task 2 |    Total |
+|---------+----------+----------|
+|    2:12 |     1:47 | 03:59:00 |
+|    2:12 |     1:47 |    03:59 |
+| 3:02:20 | -2:07:00 |     0.92 |
+,#+TBLFM: @2$3=$1+$2;T::@3$3=$1+$2;U::@4$3=$1+$2;t
+#+end_example
+
+Input duration values must be of the form =HH:MM[:SS]=, where seconds
+are optional.  With the =T= flag, computed durations are displayed as
+=HH:MM:SS= (see the first formula above).  With the =U= flag, seconds
+are omitted so that the result is only =HH:MM= (see second formula
+above).  Zero-padding of the hours field depends upon the value of the
+variable ~org-table-duration-hour-zero-padding~.
+
+With the =t= flag, computed durations are displayed according to the
+value of the option ~org-table-duration-custom-format~, which defaults
+to ~hours~ and displays the result as a fraction of hours (see the
+third formula in the example above).
+
+Negative duration values can be manipulated as well, and integers are
+considered as seconds in addition and subtraction.
+
+*** Field and range formulas
+:PROPERTIES:
+:DESCRIPTION: Formula for specific (ranges of) fields.
+:END:
+#+cindex: field formula
+#+cindex: range formula
+#+cindex: formula, for individual table field
+#+cindex: formula, for range of fields
+
+To assign a formula to a particular field, type it directly into the
+field, preceded by =:==, for example =vsum(@II..III)=.  When you press
+{{{kbd(TAB)}}} or {{{kbd(RET)}}} or {{{kbd(C-c C-c)}}} with point
+still in the field, the formula is stored as the formula for this
+field, evaluated, and the current field is replaced with the result.
+
+#+cindex: @samp{TBLFM}, keyword
+Formulas are stored in a special =TBLFM= keyword located directly
+below the table.  If you type the equation in the fourth field of the
+third data line in the table, the formula looks like =@3$4=$1+$2=.
+When inserting/deleting/swapping column and rows with the appropriate
+commands, /absolute references/ (but not relative ones) in stored
+formulas are modified in order to still reference the same field.  To
+avoid this from happening, in particular in range references, anchor
+ranges at the table borders (using =@<=, =@>=, =$<=, =$>=), or at
+hlines using the =@I= notation.  Automatic adaptation of field
+references does not happen if you edit the table structure with normal
+editing commands---you must fix the formulas yourself.
+
+Instead of typing an equation into the field, you may also use the
+following command
+
+- {{{kbd(C-u C-c =)}}} (~org-table-eval-formula~) ::
+
+  #+kindex: C-u C-c =
+  #+findex: org-table-eval-formula
+  Install a new formula for the current field.  The command prompts
+  for a formula with default taken from the =TBLFM= keyword,
+  applies it to the current field, and stores it.
+
+The left-hand side of a formula can also be a special expression in
+order to assign the formula to a number of different fields.  There is
+no keyboard shortcut to enter such range formulas.  To add them, use
+the formula editor (see [[*Editing and debugging formulas]]) or edit
+the =TBLFM= keyword directly.
+
+- =$2== ::
+
+  Column formula, valid for the entire column.  This is so common that
+  Org treats these formulas in a special way, see [[*Column formulas]].
+
+- =@3== ::
+
+  Row formula, applies to all fields in the specified row.  =@>==
+  means the last row.
+
+- =@1$2..@4$3== ::
+
+  Range formula, applies to all fields in the given rectangular range.
+  This can also be used to assign a formula to some but not all fields
+  in a row.
+
+- =$NAME== ::
+
+  Named field, see [[*Advanced features]].
+
+*** Column formulas
+:PROPERTIES:
+:DESCRIPTION: Formulas valid for an entire column.
+:END:
+#+cindex: column formula
+#+cindex: formula, for table column
+
+When you assign a formula to a simple column reference like =$3==, the
+same formula is used in all fields of that column, with the following
+very convenient exceptions: (i) If the table contains horizontal
+separator hlines with rows above and below, everything before the
+first such hline is considered part of the table /header/ and is not
+modified by column formulas.  Therefore a header is mandatory when you
+use column formulas and want to add hlines to group rows, like for
+example to separate a total row at the bottom from the summand rows
+above.  (ii) Fields that already get a value from a field/range
+formula are left alone by column formulas.  These conditions make
+column formulas very easy to use.
+
+To assign a formula to a column, type it directly into any field in
+the column, preceded by an equal sign, like ==$1+$2=.  When you press
+{{{kbd(TAB)}}} or {{{kbd(RET)}}} or {{{kbd(C-c C-c)}}} with point
+still in the field, the formula is stored as the formula for the
+current column, evaluated and the current field replaced with the
+result.  If the field contains only ===, the previously stored formula
+for this column is used.  For each column, Org only remembers the most
+recently used formula.  In the =TBLFM= keyword, column formulas look
+like =$4=$1+$2=.  The left-hand side of a column formula can not be
+the name of column, it must be the numeric column reference or =$>=.
+
+Instead of typing an equation into the field, you may also use the
+following command:
+
+- {{{kbd(C-c =)}}} (~org-table-eval-formula~) ::
+
+  #+kindex: C-c =
+  #+findex: org-table-eval-formula
+  Install a new formula for the current column and replace current
+  field with the result of the formula.  The command prompts for
+  a formula, with default taken from the =TBLFM= keyword, applies it
+  to the current field and stores it.  With a numeric prefix argument,
+  e.g., {{{kbd(C-5 C-c =)}}}, the command applies it to that many
+  consecutive fields in the current column.
+
+*** Lookup functions
+:PROPERTIES:
+:DESCRIPTION: Lookup functions for searching tables.
+:END:
+#+cindex: lookup functions in tables
+#+cindex: table lookup functions
+
+Org has three predefined Emacs Lisp functions for lookups in tables.
+
+- =(org-lookup-first VAL S-LIST R-LIST &optional PREDICATE)= ::
+
+  #+findex: org-lookup-first
+  Searches for the first element {{{var(S)}}} in list
+  {{{var(S-LIST)}}} for which
+  #+begin_src emacs-lisp
+  (PREDICATE VAL S)
+  #+end_src
+  is non-~nil~; returns the value from the corresponding position in
+  list {{{var(R-LIST)}}}.  The default {{{var(PREDICATE)}}} is
+  ~equal~.  Note that the parameters {{{var(VAL)}}} and {{{var(S)}}}
+  are passed to {{{var(PREDICATE)}}} in the same order as the
+  corresponding parameters are in the call to ~org-lookup-first~,
+  where {{{var(VAL)}}} precedes {{{var(S-LIST)}}}.  If
+  {{{var(R-LIST)}}} is ~nil~, the matching element {{{var(S)}}} of
+  {{{var(S-LIST)}}} is returned.
+
+- =(org-lookup-last VAL S-LIST R-LIST &optional PREDICATE)= ::
+
+  #+findex: org-lookup-last
+  Similar to ~org-lookup-first~ above, but searches for the /last/
+  element for which {{{var(PREDICATE)}}} is non-~nil~.
+
+- =(org-lookup-all VAL S-LIST R-LIST &optional PREDICATE)= ::
+
+  #+findex: org-lookup-all
+  Similar to ~org-lookup-first~, but searches for /all/ elements for
+  which {{{var(PREDICATE)}}} is non-~nil~, and returns /all/
+  corresponding values.  This function can not be used by itself in
+  a formula, because it returns a list of values.  However, powerful
+  lookups can be built when this function is combined with other Emacs
+  Lisp functions.
+
+If the ranges used in these functions contain empty fields, the =E=
+mode for the formula should usually be specified: otherwise empty
+fields are not included in {{{var(S-LIST)}}} and/or {{{var(R-LIST)}}}
+which can, for example, result in an incorrect mapping from an element
+of {{{var(S-LIST)}}} to the corresponding element of
+{{{var(R-LIST)}}}.
+
+These three functions can be used to implement associative arrays,
+count matching cells, rank results, group data, etc.  For practical
+examples see [[https://orgmode.org/worg/org-tutorials/org-lookups.html][this 
tutorial on Worg]].
+
+*** Editing and debugging formulas
+:PROPERTIES:
+:DESCRIPTION: Fixing formulas.
+:END:
+#+cindex: formula editing
+#+cindex: editing, of table formulas
+
+#+vindex: org-table-use-standard-references
+You can edit individual formulas in the minibuffer or directly in the
+field.  Org can also prepare a special buffer with all active formulas
+of a table.  When offering a formula for editing, Org converts
+references to the standard format (like =B3= or =D&=) if possible.  If
+you prefer to only work with the internal format (like =@3$2= or
+=$4=), configure the variable ~org-table-use-standard-references~.
+
+- {{{kbd(C-c =)}}} or {{{kbd(C-u C-c =)}}} (~org-table-eval-formula~) ::
+
+  #+kindex: C-c =
+  #+kindex: C-u C-c =
+  #+findex: org-table-eval-formula
+  Edit the formula associated with the current column/field in the
+  minibuffer.  See [[*Column formulas]], and [[*Field and range formulas]].
+
+- {{{kbd(C-u C-u C-c =)}}} (~org-table-eval-formula~) ::
+
+  #+kindex: C-u C-u C-c =
+  #+findex: org-table-eval-formula
+  Re-insert the active formula (either a field formula, or a column
+  formula) into the current field, so that you can edit it directly in
+  the field.  The advantage over editing in the minibuffer is that you
+  can use the command {{{kbd(C-c ?)}}}.
+
+- {{{kbd(C-c ?)}}} (~org-table-field-info~) ::
+
+  #+kindex: C-c ?
+  #+findex: org-table-field-info
+  While editing a formula in a table field, highlight the field(s)
+  referenced by the reference at point position in the formula.
+
+- {{{kbd(C-c })}}} (~org-table-toggle-coordinate-overlays~) ::
+
+  #+kindex: C-c @}
+  #+findex: org-table-toggle-coordinate-overlays
+  Toggle the display of row and column numbers for a table, using
+  overlays.  These are updated each time the table is aligned; you can
+  force it with {{{kbd(C-c C-c)}}}.
+
+- {{{kbd(C-c {)}}} (~org-table-toggle-formula-debugger~) ::
+
+  #+kindex: C-c @{
+  #+findex: org-table-toggle-formula-debugger
+  Toggle the formula debugger on and off.  See below.
+
+- {{{kbd(C-c ')}}} (~org-table-edit-formulas~) ::
+
+  #+kindex: C-c '
+  #+findex: org-table-edit-formulas
+  Edit all formulas for the current table in a special buffer, where
+  the formulas are displayed one per line.  If the current field has
+  an active formula, point in the formula editor marks it.  While
+  inside the special buffer, Org automatically highlights any field or
+  range reference at point position.  You may edit, remove and add
+  formulas, and use the following commands:
+
+  - {{{kbd(C-c C-c)}}} or {{{kbd(C-x C-s)}}} (~org-table-fedit-finish~) ::
+
+    #+kindex: C-x C-s
+    #+kindex: C-c C-c
+    #+findex: org-table-fedit-finish
+    Exit the formula editor and store the modified formulas.  With
+    {{{kbd(C-u)}}} prefix, also apply the new formulas to the
+    entire table.
+
+  - {{{kbd(C-c C-q)}}} (~org-table-fedit-abort~) ::
+
+    #+kindex: C-c C-q
+    #+findex: org-table-fedit-abort
+    Exit the formula editor without installing changes.
+
+  - {{{kbd(C-c C-r)}}} (~org-table-fedit-toggle-ref-type~) ::
+
+    #+kindex: C-c C-r
+    #+findex: org-table-fedit-toggle-ref-type
+    Toggle all references in the formula editor between standard (like
+    =B3=) and internal (like =@3$2=).
+
+  - {{{kbd(TAB)}}} (~org-table-fedit-lisp-indent~) ::
+
+    #+kindex: TAB
+    #+findex: org-table-fedit-lisp-indent
+    Pretty-print or indent Lisp formula at point.  When in a line
+    containing a Lisp formula, format the formula according to Emacs
+    Lisp rules.  Another {{{kbd(TAB)}}} collapses the formula back
+    again.  In the open formula, {{{kbd(TAB)}}} re-indents just like
+    in Emacs Lisp mode.
+
+  - {{{kbd(M-TAB)}}} (~lisp-complete-symbol~) ::
+
+    #+kindex: M-TAB
+    #+findex: lisp-complete-symbol
+    Complete Lisp symbols, just like in Emacs Lisp mode.
+
+  - {{{kbd(S-UP)}}}, {{{kbd(S-DOWN)}}}, {{{kbd(S-LEFT)}}}, {{{kbd(S-RIGHT)}}} 
::
+
+    #+kindex: S-UP
+    #+kindex: S-DOWN
+    #+kindex: S-LEFT
+    #+kindex: S-RIGHT
+    #+findex: org-table-fedit-ref-up
+    #+findex: org-table-fedit-ref-down
+    #+findex: org-table-fedit-ref-left
+    #+findex: org-table-fedit-ref-right
+    Shift the reference at point.  For example, if the reference is
+    =B3= and you press {{{kbd(S-RIGHT)}}}, it becomes =C3=.  This also
+    works for relative references and for hline references.
+
+  - {{{kbd(M-S-UP)}}} (~org-table-fedit-line-up~) ::
+
+    #+kindex: M-S-UP
+    #+findex: org-table-fedit-line-up
+    Move the test line for column formulas up in the Org buffer.
+
+  - {{{kbd(M-S-DOWN)}}} (~org-table-fedit-line-down~) ::
+
+    #+kindex: M-S-DOWN
+    #+findex: org-table-fedit-line-down
+    Move the test line for column formulas down in the Org buffer.
+
+  - {{{kbd(M-UP)}}} (~org-table-fedit-scroll-up~) ::
+
+    #+kindex: M-UP
+    #+findex: org-table-fedit-scroll-up
+    Scroll up the window displaying the table.
+
+  - {{{kbd(M-DOWN)}}} (~org-table-fedit-scroll-down~) ::
+
+    #+kindex: M-DOWN
+    #+findex: org-table-fedit-scroll-down
+    Scroll down the window displaying the table.
+
+  - {{{kbd(C-c })}}} ::
+
+    #+kindex: C-c @}
+    #+findex: org-table-toggle-coordinate-overlays
+    Turn the coordinate grid in the table on and off.
+
+Making a table field blank does not remove the formula associated with
+the field, because that is stored in a different line---the =TBLFM=
+keyword line.  During the next recalculation, the field will be filled
+again.  To remove a formula from a field, you have to give an empty
+reply when prompted for the formula, or to edit the =TBLFM= keyword.
+
+#+kindex: C-c C-c
+You may edit the =TBLFM= keyword directly and re-apply the changed
+equations with {{{kbd(C-c C-c)}}} in that line or with the normal
+recalculation commands in the table.
+
+**** Using multiple =TBLFM= lines
+:PROPERTIES:
+:UNNUMBERED: notoc
+:END:
+#+cindex: multiple formula lines
+#+cindex: @samp{TBLFM} keywords, multiple
+#+cindex: @samp{TBLFM}, switching
+
+#+kindex: C-c C-c
+You may apply the formula temporarily.  This is useful when you want
+to switch the formula applied to the table.  Place multiple =TBLFM=
+keywords right after the table, and then press {{{kbd(C-c C-c)}}} on
+the formula to apply.  Here is an example:
+
+#+begin_example
+| x | y |
+|---+---|
+| 1 |   |
+| 2 |   |
+,#+TBLFM: $2=$1*1
+,#+TBLFM: $2=$1*2
+#+end_example
+
+#+texinfo: @noindent
+Pressing {{{kbd(C-c C-c)}}} in the line of =#+TBLFM: $2=$1*2= yields:
+
+#+begin_example
+| x | y |
+|---+---|
+| 1 | 2 |
+| 2 | 4 |
+,#+TBLFM: $2=$1*1
+,#+TBLFM: $2=$1*2
+#+end_example
+
+#+texinfo: @noindent
+If you recalculate this table, with {{{kbd(C-u C-c *)}}}, for example,
+you get the following result from applying only the first =TBLFM=
+keyword.
+
+#+begin_example
+| x | y |
+|---+---|
+| 1 | 1 |
+| 2 | 2 |
+,#+TBLFM: $2=$1*1
+,#+TBLFM: $2=$1*2
+#+end_example
+
+**** Debugging formulas
+:PROPERTIES:
+:UNNUMBERED: notoc
+:END:
+#+cindex: formula debugging
+#+cindex: debugging, of table formulas
+
+When the evaluation of a formula leads to an error, the field content
+becomes the string =#ERROR=.  If you would like to see what is going
+on during variable substitution and calculation in order to find
+a bug, turn on formula debugging in the Tbl menu and repeat the
+calculation, for example by pressing {{{kbd(C-u C-u C-c = RET)}}} in
+a field.  Detailed information are displayed.
+
+*** Updating the table
+:PROPERTIES:
+:DESCRIPTION: Recomputing all dependent fields.
+:END:
+#+cindex: recomputing table fields
+#+cindex: updating, table
+
+Recalculation of a table is normally not automatic, but needs to be
+triggered by a command.  To make recalculation at least
+semi-automatic, see [[*Advanced features]].
+
+In order to recalculate a line of a table or the entire table, use the
+following commands:
+
+- {{{kbd(C-c *)}}} (~org-table-recalculate~) ::
+
+  #+kindex: C-c *
+  #+findex: org-table-recalculate
+  Recalculate the current row by first applying the stored column
+  formulas from left to right, and all field/range formulas in the
+  current row.
+
+- {{{kbd(C-u C-c *)}}} or {{{kbd(C-u C-c C-c)}}} ::
+
+  #+kindex: C-u C-c *
+  #+kindex: C-u C-c C-c
+  Recompute the entire table, line by line.  Any lines before the
+  first hline are left alone, assuming that these are part of the
+  table header.
+
+- {{{kbd(C-u C-u C-c *)}}} or {{{kbd(C-u C-u C-c C-c)}}} (~org-table-iterate~) 
::
+
+  #+kindex: C-u C-u C-c *
+  #+kindex: C-u C-u C-c C-c
+  #+findex: org-table-iterate
+  Iterate the table by recomputing it until no further changes occur.
+  This may be necessary if some computed fields use the value of other
+  fields that are computed /later/ in the calculation sequence.
+
+- {{{kbd(M-x org-table-recalculate-buffer-tables)}}} ::
+
+  #+findex: org-table-recalculate-buffer-tables
+  Recompute all tables in the current buffer.
+
+- {{{kbd(M-x org-table-iterate-buffer-tables)}}} ::
+
+  #+findex: org-table-iterate-buffer-tables
+  Iterate all tables in the current buffer, in order to converge
+  table-to-table dependencies.
+
+*** Advanced features
+:PROPERTIES:
+:DESCRIPTION: Field and column names, automatic recalculation...
+:END:
+
+If you want the recalculation of fields to happen automatically, or if
+you want to be able to assign /names/[fn:22] to fields and columns,
+you need to reserve the first column of the table for special marking
+characters.
+
+- {{{kbd(C-#)}}} (~org-table-rotate-recalc-marks~) ::
+
+  #+kindex: C-#
+  #+findex: org-table-rotate-recalc-marks
+  Rotate the calculation mark in first column through the states =#=,
+  =*=, =!=, =$=.  When there is an active region, change all marks in
+  the region.
+
+Here is an example of a table that collects exam results of students
+and makes use of these features:
+
+#+begin_example
+|---+---------+--------+--------+--------+-------+------|
+|   | Student | Prob 1 | Prob 2 | Prob 3 | Total | Note |
+|---+---------+--------+--------+--------+-------+------|
+| ! |         |     P1 |     P2 |     P3 |   Tot |      |
+| # | Maximum |     10 |     15 |     25 |    50 | 10.0 |
+| ^ |         |     m1 |     m2 |     m3 |    mt |      |
+|---+---------+--------+--------+--------+-------+------|
+| # | Peter   |     10 |      8 |     23 |    41 |  8.2 |
+| # | Sam     |      2 |      4 |      3 |     9 |  1.8 |
+|---+---------+--------+--------+--------+-------+------|
+|   | Average |        |        |        |  25.0 |      |
+| ^ |         |        |        |        |    at |      |
+| $ | max=50  |        |        |        |       |      |
+|---+---------+--------+--------+--------+-------+------|
+,#+TBLFM: $6=vsum($P1..$P3)::$7=10*$Tot/$max;%.1f::$at=vmean(@-II..@-I);%.1f
+#+end_example
+
+#+attr_texinfo: :tag Important
+#+begin_quote
+Please note that for these special tables, recalculating the table
+with {{{kbd(C-u C-c *)}}} only affects rows that are marked =#= or
+=*=, and fields that have a formula assigned to the field itself.  The
+column formulas are not applied in rows with empty first field.
+#+end_quote
+
+#+cindex: marking characters, tables
+The marking characters have the following meaning:
+
+- =!= ::
+
+  The fields in this line define names for the columns, so that you
+  may refer to a column as =$Tot= instead of =$6=.
+
+- =^= ::
+
+  This row defines names for the fields /above/ the row.  With such
+  a definition, any formula in the table may use =$m1= to refer to the
+  value =10=.  Also, if you assign a formula to a names field, it is
+  stored as =$name = ...=.
+
+- =_= ::
+
+  Similar to =^=, but defines names for the fields in the row /below/.
+
+- =$= ::
+
+  Fields in this row can define /parameters/ for formulas.  For
+  example, if a field in a =$= row contains =max=50=, then formulas in
+  this table can refer to the value 50 using =$max=.  Parameters work
+  exactly like constants, only that they can be defined on a per-table
+  basis.
+
+- =#= ::
+
+  Fields in this row are automatically recalculated when pressing
+  {{{kbd(TAB)}}} or {{{kbd(RET)}}} or {{{kbd(S-TAB)}}} in this row.
+  Also, this row is selected for a global recalculation with
+  {{{kbd(C-u C-c *)}}}.  Unmarked lines are left alone by this
+  command.
+
+- =*= ::
+
+  Selects this line for global recalculation with {{{kbd(C-u C-c
+  *)}}}, but not for automatic recalculation.  Use this when automatic
+  recalculation slows down editing too much.
+
+- =/= ::
+
+  Do not export this line.  Useful for lines that contain the
+  narrowing =<N>= markers or column group markers.
+
+Finally, just to whet your appetite for what can be done with the
+fantastic Calc package, here is a table that computes the Taylor
+series of degree n at location x for a couple of functions.
+
+#+begin_example
+|---+-------------+---+-----+--------------------------------------|
+|   | Func        | n | x   | Result                               |
+|---+-------------+---+-----+--------------------------------------|
+| # | exp(x)      | 1 | x   | 1 + x                                |
+| # | exp(x)      | 2 | x   | 1 + x + x^2 / 2                      |
+| # | exp(x)      | 3 | x   | 1 + x + x^2 / 2 + x^3 / 6            |
+| # | x^2+sqrt(x) | 2 | x=0 | x*(0.5 / 0) + x^2 (2 - 0.25 / 0) / 2 |
+| # | x^2+sqrt(x) | 2 | x=1 | 2 + 2.5 x - 2.5 + 0.875 (x - 1)^2    |
+| * | tan(x)      | 3 | x   | 0.0175 x + 1.77e-6 x^3               |
+|---+-------------+---+-----+--------------------------------------|
+,#+TBLFM: $5=taylor($2,$4,$3);n3
+#+end_example
+
+** Org Plot
+:PROPERTIES:
+:DESCRIPTION: Plotting from Org tables.
+:END:
+#+cindex: graph, in tables
+#+cindex: plot tables using Gnuplot
+
+Org Plot can produce graphs of information stored in Org tables,
+either graphically or in ASCII art.
+
+*** Graphical plots using Gnuplot
+:PROPERTIES:
+:UNNUMBERED: notoc
+:END:
+
+#+cindex: @samp{PLOT}, keyword
+Org Plot can produce 2D and 3D graphs of information stored in Org
+tables using [[http://www.gnuplot.info/][Gnuplot]] and 
[[http://cars9.uchicago.edu/~ravel/software/gnuplot-mode.html][Gnuplot mode]].  
To see this in action, ensure
+that you have both Gnuplot and Gnuplot mode installed on your system,
+then call {{{kbd(C-c \quot g)}}} or {{{kbd(M-x org-plot/gnuplot)}}} on the
+following table.
+
+#+begin_example
+,#+PLOT: title:"Citas" ind:1 deps:(3) type:2d with:histograms set:"yrange [0:]"
+| Sede      | Max cites | H-index |
+|-----------+-----------+---------|
+| Chile     |    257.72 |   21.39 |
+| Leeds     |    165.77 |   19.68 |
+| Sao Paolo |     71.00 |   11.50 |
+| Stockholm |    134.19 |   14.33 |
+| Morelia   |    257.56 |   17.67 |
+#+end_example
+
+Notice that Org Plot is smart enough to apply the table's headers as
+labels.  Further control over the labels, type, content, and
+appearance of plots can be exercised through the =PLOT= keyword
+preceding a table.  See below for a complete list of Org Plot options.
+For more information and examples see the 
[[https://orgmode.org/worg/org-tutorials/org-plot.html][Org Plot tutorial]].
+
+**** Plot options
+:PROPERTIES:
+:UNNUMBERED: notoc
+:END:
+
+- =set= ::
+
+  Specify any Gnuplot option to be set when graphing.
+
+- =title= ::
+
+  Specify the title of the plot.
+
+- =ind= ::
+
+  Specify which column of the table to use as the =x= axis.
+
+- =deps= ::
+
+  Specify the columns to graph as a Lisp style list, surrounded by
+  parentheses and separated by spaces for example =dep:(3 4)= to graph
+  the third and fourth columns.  Defaults to graphing all other
+  columns aside from the =ind= column.
+
+- =type= ::
+
+  Specify whether the plot is =2d=, =3d=, or =grid=.
+
+- =with= ::
+
+  Specify a =with= option to be inserted for every column being
+  plotted, e.g., =lines=, =points=, =boxes=, =impulses=.  Defaults to
+  =lines=.
+
+- =file= ::
+
+  If you want to plot to a file, specify
+  ="path/to/desired/output-file"=.
+
+- =labels= ::
+
+  List of labels to be used for the =deps=.  Defaults to the column
+  headers if they exist.
+
+- =line= ::
+
+  Specify an entire line to be inserted in the Gnuplot script.
+
+- =map= ::
+
+  When plotting =3d= or =grid= types, set this to =t= to graph a flat
+  mapping rather than a =3d= slope.
+
+- =timefmt= ::
+
+  Specify format of Org mode timestamps as they will be parsed by
+  Gnuplot.  Defaults to =%Y-%m-%d-%H:%M:%S=.
+
+- =script= ::
+
+  If you want total control, you can specify a script file---place the
+  file name between double-quotes---which will be used to plot.
+  Before plotting, every instance of =$datafile= in the specified
+  script will be replaced with the path to the generated data file.
+  Note: even if you set this option, you may still want to specify the
+  plot type, as that can impact the content of the data file.
+
+*** ASCII bar plots
+:PROPERTIES:
+:UNNUMBERED: notoc
+:END:
+
+While point is on a column, typing {{{kbd(C-c " a)}}} or {{{kbd(M-x
+orgtbl-ascii-plot)}}} create a new column containing an ASCII-art bars
+plot.  The plot is implemented through a regular column formula.  When
+the source column changes, the bar plot may be updated by refreshing
+the table, for example typing {{{kbd(C-u C-c *)}}}.
+
+#+begin_example
+| Sede          | Max cites |              |
+|---------------+-----------+--------------|
+| Chile         |    257.72 | WWWWWWWWWWWW |
+| Leeds         |    165.77 | WWWWWWWh     |
+| Sao Paolo     |     71.00 | WWW;         |
+| Stockholm     |    134.19 | WWWWWW:      |
+| Morelia       |    257.56 | WWWWWWWWWWWH |
+| Rochefourchat |      0.00 |              |
+,#+TBLFM: $3='(orgtbl-ascii-draw $2 0.0 257.72 12)
+#+end_example
+
+The formula is an Elisp call.
+
+#+attr_texinfo: :options orgtbl-ascii-draw value min max &optional width
+#+begin_defun
+Draw an ASCII bar in a table.
+
+{{{var(VALUE)}}} is the value to plot.
+
+{{{var(MIN)}}} is the value displayed as an empty bar.  {{{var(MAX)}}}
+is the value filling all the {{{var(WIDTH)}}}.  Sources values outside
+this range are displayed as =too small= or =too large=.
+
+{{{var(WIDTH)}}} is the number of characters of the bar plot.  It
+defaults to =12=.
+#+end_defun
+
+* Hyperlinks
+:PROPERTIES:
+:DESCRIPTION: Notes in context.
+:END:
+#+cindex: hyperlinks
+
+Like HTML, Org provides support for links inside a file, external
+links to other files, Usenet articles, emails, and much more.
+
+** Link Format
+:PROPERTIES:
+:DESCRIPTION: How links in Org are formatted.
+:END:
+#+cindex: link format
+#+cindex: format, of links
+
+#+cindex: angle bracket links
+#+cindex: plain links
+Org recognizes plain URIs, possibly wrapped within angle
+brackets[fn:23], and activate them as clickable links.
+
+#+cindex: bracket links
+The general link format, however, looks like this:
+
+: [[LINK][DESCRIPTION]]
+
+#+texinfo: @noindent
+or alternatively
+
+: [[LINK]]
+
+#+cindex: escape syntax, for links
+#+cindex: backslashes, in links
+Some =\=, =[= and =]= characters in the {{{var(LINK)}}} part need to
+be "escaped", i.e., preceded by another =\= character.  More
+specifically, the following characters, and only them, must be
+escaped:
+
+1. all =[= and =]= characters,
+2. every =\= character preceding either =]= or =[=,
+3. every =\= character at the end of the link.
+
+#+findex: org-link-escape
+Functions inserting links (see [[*Handling Links]]) properly escape
+ambiguous characters.  You only need to bother about the rules above
+when inserting directly, or yanking, a URI within square brackets.
+When in doubt, you may use the function ~org-link-escape~, which turns
+a link string into its escaped form.
+
+Once a link in the buffer is complete, with all brackets present, Org
+changes the display so that =DESCRIPTION= is displayed instead of
+=[[LINK][DESCRIPTION]]= and =LINK= is displayed instead of =[[LINK]]=.
+Links are highlighted in the ~org-link~ face, which, by default, is an
+underlined face.
+
+You can directly edit the visible part of a link.  This can be either
+the {{{var(LINK)}}} part, if there is no description, or the
+{{{var(DESCRIPTION)}}} part otherwise.  To also edit the invisible
+{{{var(LINK)}}} part, use {{{kbd(C-c C-l)}}} with point on the link
+(see [[*Handling Links]]).
+
+If you place point at the beginning or just behind the end of the
+displayed text and press {{{kbd(BS)}}}, you remove
+the---invisible---bracket at that location[fn:24].  This makes the link
+incomplete and the internals are again displayed as plain text.
+Inserting the missing bracket hides the link internals again.  To show
+the internal structure of all links, use the menu: Org \rarr Hyperlinks \rarr
+Literal links.
+
+** Internal Links
+:PROPERTIES:
+:DESCRIPTION: Links to other places in the current file.
+:END:
+#+cindex: internal links
+#+cindex: links, internal
+
+A link that does not look like a URL---i.e., does not start with
+a known scheme or a file name---refers to the current document.  You
+can follow it with {{{kbd(C-c C-o)}}} when point is on the link, or
+with a mouse click (see [[*Handling Links]]).
+
+#+cindex: @samp{CUSTOM_ID}, property
+Org provides several refinements to internal navigation within
+a document.  Most notably, a construct like =[[#my-custom-id]]=
+specifically targets the entry with the =CUSTOM_ID= property set to
+=my-custom-id=.  Also, an internal link looking like =[[*Some
+section]]= points to a headline with the name =Some section=[fn:25].
+
+#+cindex: targets, for links
+When the link does not belong to any of the cases above, Org looks for
+a /dedicated target/: the same string in double angular brackets, like
+=<<My Target>>=.
+
+#+cindex: @samp{NAME}, keyword
+If no dedicated target exists, the link tries to match the exact name
+of an element within the buffer.  Naming is done, unsurprisingly, with
+the =NAME= keyword, which has to be put in the line before the element
+it refers to, as in the following example
+
+#+begin_example
+,#+NAME: My Target
+| a  | table      |
+|----+------------|
+| of | four cells |
+#+end_example
+
+#+vindex: org-link-search-must-match-exact-headline
+Ultimately, if none of the above succeeds, Org searches for a headline
+that is exactly the link text but may also include a TODO keyword and
+tags, or initiates a plain text search, according to the value of
+~org-link-search-must-match-exact-headline~.
+
+Note that you must make sure custom IDs, dedicated targets, and names
+are unique throughout the document.  Org provides a linter to assist
+you in the process, if needed.  See [[*Org Syntax]].
+
+During export, internal links are used to mark objects and assign them
+a number.  Marked objects are then referenced by links pointing to
+them.  In particular, links without a description appear as the number
+assigned to the marked object[fn:26].  In the following excerpt from
+an Org buffer
+
+#+begin_example
+1. one item
+2. <<target>>another item
+Here we refer to item [[target]].
+#+end_example
+
+#+texinfo: @noindent
+The last sentence will appear as =Here we refer to item 2= when
+exported.
+
+In non-Org files, the search looks for the words in the link text.  In
+the above example the search would be for =target=.
+
+Following a link pushes a mark onto Org's own mark ring.  You can
+return to the previous position with {{{kbd(C-c &)}}}.  Using this
+command several times in direct succession goes back to positions
+recorded earlier.
+
+** Radio Targets
+:PROPERTIES:
+:DESCRIPTION: Make targets trigger links in plain text.
+:END:
+#+cindex: radio targets
+#+cindex: targets, radio
+#+cindex: links, radio targets
+
+Org can automatically turn any occurrences of certain target names in
+normal text into a link.  So without explicitly creating a link, the
+text connects to the target radioing its position.  Radio targets are
+enclosed by triple angular brackets.  For example, a target =<<<My
+Target>>>= causes each occurrence of =my target= in normal text to
+become activated as a link.  The Org file is scanned automatically for
+radio targets only when the file is first loaded into Emacs.  To
+update the target list during editing, press {{{kbd(C-c C-c)}}} with
+point on or at a target.
+
+** External Links
+:PROPERTIES:
+:DESCRIPTION: URL-like links to the world.
+:END:
+#+cindex: links, external
+#+cindex: external links
+#+cindex: attachment links
+#+cindex: BBDB links
+#+cindex: Elisp links
+#+cindex: file links
+#+cindex: Gnus links
+#+cindex: Help links
+#+cindex: IRC links
+#+cindex: Info links
+#+cindex: MH-E links
+#+cindex: Rmail links
+#+cindex: shell links
+#+cindex: URL links
+#+cindex: Usenet links
+
+Org supports links to files, websites, Usenet and email messages, BBDB
+database entries and links to both IRC conversations and their logs.
+External links are URL-like locators.  They start with a short
+identifying string followed by a colon.  There can be no space after
+the colon.
+
+Here is the full set of built-in link types:
+
+- =file= ::
+
+   File links.  File name may be remote, absolute, or relative.
+
+   Additionally, you can specify a line number, or a text search.
+   In Org files, you may link to a headline name, a custom ID, or a
+   code reference instead.
+
+   As a special case, "file" prefix may be omitted if the file name
+   is complete, e.g., it starts with =./=, or =/=.
+
+- =attachment= ::
+
+  Same as file links but for files and folders attached to the current
+  node (see [[*Attachments]]).  Attachment links are intended to behave
+  exactly as file links but for files relative to the attachment
+  directory.
+
+- =bbdb= ::
+
+  Link to a BBDB record, with possible regexp completion.
+
+- =docview= ::
+
+  Link to a document opened with DocView mode.  You may specify a page
+  number.
+
+- =doi= ::
+
+  Link to an electronic resource, through its handle.
+
+- =elisp= ::
+
+  Execute an Elisp command upon activation.
+
+- =gnus=, =rmail=, =mhe= ::
+
+  Link to messages or folders from a given Emacs' MUA.
+
+- =help= ::
+
+  Display documentation of a symbol in =*Help*= buffer.
+
+- =http=, =https= ::
+
+  Web links.
+
+- =id= ::
+
+  Link to a specific headline by its ID property, in an Org file.
+
+- =info= ::
+
+  Link to an Info manual, or to a specific node.
+
+- =irc= ::
+
+  Link to an IRC channel.
+
+- =mailto= ::
+
+  Link to message composition.
+
+- =news= ::
+
+  Usenet links.
+
+- =shell= ::
+
+  Execute a shell command upon activation.
+
+The following table illustrates the link types above, along with their
+options:
+
+| Link Type  | Example                                                  |
+|------------+----------------------------------------------------------|
+| http       | =http://staff.science.uva.nl/c.dominik/=                 |
+| https      | =https://orgmode.org/=                                   |
+| doi        | =doi:10.1000/182=                                        |
+| file       | =file:/home/dominik/images/jupiter.jpg=                  |
+|            | =/home/dominik/images/jupiter.jpg= (same as above)       |
+|            | =file:papers/last.pdf=                                   |
+|            | =./papers/last.pdf= (same as above)                      |
+|            | =file:/ssh:me@some.where:papers/last.pdf= (remote)       |
+|            | =/ssh:me@some.where:papers/last.pdf= (same as above)     |
+|            | =file:sometextfile::NNN= (jump to line number)           |
+|            | =file:projects.org=                                      |
+|            | =file:projects.org::some words= (text search)[fn:27]     |
+|            | =file:projects.org::*task title= (headline search)       |
+|            | =file:projects.org::#custom-id= (headline search)        |
+| attachment | =attachment:projects.org=                                |
+|            | =attachment:projects.org::some words= (text search)      |
+| docview    | =docview:papers/last.pdf::NNN=                           |
+| id         | =id:B7423F4D-2E8A-471B-8810-C40F074717E9=                |
+| news       | =news:comp.emacs=                                        |
+| mailto     | =mailto:adent@galaxy.net=                                |
+| mhe        | =mhe:folder= (folder link)                               |
+|            | =mhe:folder#id= (message link)                           |
+| rmail      | =rmail:folder= (folder link)                             |
+|            | =rmail:folder#id= (message link)                         |
+| gnus       | =gnus:group= (group link)                                |
+|            | =gnus:group#id= (article link)                           |
+| bbdb       | =bbdb:R.*Stallman= (record with regexp)                  |
+| irc        | =irc:/irc.com/#emacs/bob=                                |
+| help       | =help:org-store-link=                                    |
+| info       | =info:org#External links=                                |
+| shell      | =shell:ls *.org=                                         |
+| elisp      | =elisp:(find-file "Elisp.org")= (Elisp form to evaluate) |
+|            | =elisp:org-agenda= (interactive Elisp command)           |
+
+#+cindex: VM links
+#+cindex: Wanderlust links
+On top of these built-in link types, additional ones are available
+through the =contrib/= directory (see [[*Installation]]).  For example,
+these links to VM or Wanderlust messages are available when you load
+the corresponding libraries from the =contrib/= directory:
+
+| =vm:folder=                            | VM folder link          |
+| =vm:folder#id=                         | VM message link         |
+| =vm://myself@some.where.org/folder#id= | VM on remote machine    |
+| =vm-imap:account:folder=               | VM IMAP folder link     |
+| =vm-imap:account:folder#id=            | VM IMAP message link    |
+| =wl:folder=                            | Wanderlust folder link  |
+| =wl:folder#id=                         | Wanderlust message link |
+
+For information on customizing Org to add new link types, see [[*Adding
+Hyperlink Types]].
+
+A link should be enclosed in double brackets and may contain
+descriptive text to be displayed instead of the URL (see [[*Link
+Format]]), for example:
+
+: [[https://www.gnu.org/software/emacs/][GNU Emacs]]
+
+If the description is a file name or URL that points to an image, HTML
+export (see [[*HTML Export]]) inlines the image as a clickable button.  If
+there is no description at all and the link points to an image, that
+image is inlined into the exported HTML file.
+
+#+cindex: square brackets, around links
+#+cindex: angular brackets, around links
+#+cindex: plain text external links
+Org also recognizes external links amid normal text and activates them
+as links.  If spaces must be part of the link (for example in
+=bbdb:R.*Stallman=), or if you need to remove ambiguities about the
+end of the link, enclose the link in square or angular brackets.
+
+** Handling Links
+:PROPERTIES:
+:DESCRIPTION: Creating, inserting and following.
+:END:
+#+cindex: links, handling
+
+Org provides methods to create a link in the correct syntax, to insert
+it into an Org file, and to follow the link.
+
+#+findex: org-store-link
+#+cindex: storing links
+The main function is ~org-store-link~, called with {{{kbd(M-x
+org-store-link)}}}.  Because of its importance, we suggest to bind it
+to a widely available key (see [[*Activation]]).  It stores a link to the
+current location.  The link is stored for later insertion into an Org
+buffer---see below.  The kind of link that is created depends on the
+current buffer:
+
+- /Org mode buffers/ ::
+
+  For Org files, if there is a =<<target>>= at point, the link points
+  to the target.  Otherwise it points to the current headline, which
+  is also the description[fn:28].
+
+  #+vindex: org-id-link-to-org-use-id
+  #+cindex: @samp{CUSTOM_ID}, property
+  #+cindex: @samp{ID}, property
+  If the headline has a =CUSTOM_ID= property, store a link to this
+  custom ID.  In addition or alternatively, depending on the value of
+  ~org-id-link-to-org-use-id~, create and/or use a globally unique
+  =ID= property for the link[fn:29].  So using this command in Org
+  buffers potentially creates two links: a human-readable link from
+  the custom ID, and one that is globally unique and works even if the
+  entry is moved from file to file.  Later, when inserting the link,
+  you need to decide which one to use.
+
+- /Email/News clients: VM, Rmail, Wanderlust, MH-E, Gnus/ ::
+
+  #+vindex: org-link-email-description-format
+  Pretty much all Emacs mail clients are supported.  The link points
+  to the current article, or, in some Gnus buffers, to the group.  The
+  description is constructed according to the variable
+  ~org-link-email-description-format~.  By default, it refers to the
+  addressee and the subject.
+
+- /Web browsers: W3, W3M and EWW/ ::
+
+  Here the link is the current URL, with the page title as the
+  description.
+
+- /Contacts: BBDB/ ::
+
+  Links created in a BBDB buffer point to the current entry.
+
+- /Chat: IRC/ ::
+
+  #+vindex: org-irc-links-to-logs
+  For IRC links, if the variable ~org-irc-link-to-logs~ is non-~nil~,
+  create a =file= style link to the relevant point in the logs for the
+  current conversation.  Otherwise store an =irc= style link to the
+  user/channel/server under the point.
+
+- /Other files/ ::
+
+  For any other file, the link points to the file, with a search
+  string (see [[*Search Options in File Links]]) pointing to the contents
+  of the current line.  If there is an active region, the selected
+  words form the basis of the search string.  You can write custom Lisp
+  functions to select the search string and perform the search for
+  particular file types (see [[*Custom Searches]]).
+
+  You can also define dedicated links to other files.  See [[*Adding
+  Hyperlink Types]].
+
+- /Agenda view/ ::
+
+  When point is in an agenda view, the created link points to the
+  entry referenced by the current line.
+
+From an Org buffer, the following commands create, navigate or, more
+generally, act on links.
+
+#+attr_texinfo: :sep ,
+- {{{kbd(C-c C-l)}}} (~org-insert-link~) ::
+
+  #+kindex: C-c C-l
+  #+findex: org-insert-link
+  #+cindex: link completion
+  #+cindex: completion, of links
+  #+cindex: inserting links
+  #+vindex: org-link-keep-stored-after-insertion
+  Insert a link[fn:30].  This prompts for a link to be inserted into
+  the buffer.  You can just type a link, using text for an internal
+  link, or one of the link type prefixes mentioned in the examples
+  above.  The link is inserted into the buffer, along with
+  a descriptive text[fn:31].  If some text was selected at this time,
+  it becomes the default description.
+
+  - /Inserting stored links/ ::
+
+    All links stored during the current session are part of the
+    history for this prompt, so you can access them with {{{kbd(UP)}}}
+    and {{{kbd(DOWN)}}} (or {{{kbd(M-p)}}}, {{{kbd(M-n)}}}).
+
+  - /Completion support/ ::
+
+    Completion with {{{kbd(TAB)}}} helps you to insert valid link
+    prefixes like =http= or =ftp=, including the prefixes defined
+    through link abbreviations (see [[*Link Abbreviations]]).  If you
+    press {{{kbd(RET)}}} after inserting only the prefix, Org offers
+    specific completion support for some link types[fn:32].  For
+    example, if you type {{{kbd(f i l e RET)}}}---alternative access:
+    {{{kbd(C-u C-c C-l)}}}, see below---Org offers file name
+    completion, and after {{{kbd(b b d b RET)}}} you can complete
+    contact names.
+
+- {{{kbd(C-u C-c C-l)}}} ::
+
+  #+cindex: file name completion
+  #+cindex: completion, of file names
+  #+kindex: C-u C-c C-l
+  When {{{kbd(C-c C-l)}}} is called with a {{{kbd(C-u)}}} prefix
+  argument, insert a link to a file.  You may use file name completion
+  to select the name of the file.  The path to the file is inserted
+  relative to the directory of the current Org file, if the linked
+  file is in the current directory or in a sub-directory of it, or if
+  the path is written relative to the current directory using =../=.
+  Otherwise an absolute path is used, if possible with =~/= for your
+  home directory.  You can force an absolute path with two
+  {{{kbd(C-u)}}} prefixes.
+
+- {{{kbd(C-c C-l)}}} (with point on existing link) ::
+
+  #+cindex: following links
+  When point is on an existing link, {{{kbd(C-c C-l)}}} allows you to
+  edit the link and description parts of the link.
+
+- {{{kbd(C-c C-o)}}} (~org-open-at-point~) ::
+
+  #+kindex: C-c C-o
+  #+findex: org-open-at-point
+  #+vindex: org-file-apps
+  Open link at point.  This launches a web browser for URL (using
+  ~browse-url-at-point~), run VM/MH-E/Wanderlust/Rmail/Gnus/BBDB for
+  the corresponding links, and execute the command in a shell link.
+  When point is on an internal link, this command runs the
+  corresponding search.  When point is on the tags part of a headline,
+  it creates the corresponding tags view (see [[*Matching tags and
+  properties]]).  If point is on a timestamp, it compiles the agenda for
+  that date.  Furthermore, it visits text and remote files in =file=
+  links with Emacs and select a suitable application for local
+  non-text files.  Classification of files is based on file extension
+  only.  See option ~org-file-apps~.  If you want to override the
+  default application and visit the file with Emacs, use
+  a {{{kbd(C-u)}}} prefix.  If you want to avoid opening in Emacs, use
+  a {{{kbd(C-u C-u)}}} prefix.
+
+  #+vindex: org-link-frame-setup
+  If point is on a headline, but not on a link, offer all links in the
+  headline and entry text.  If you want to setup the frame
+  configuration for following links, customize ~org-link-frame-setup~.
+
+- {{{kbd(RET)}}} ::
+
+  #+vindex: org-return-follows-link
+  #+kindex: RET
+  When ~org-return-follows-link~ is set, {{{kbd(RET)}}} also follows
+  the link at point.
+
+- {{{kbd(mouse-2)}}} or {{{kbd(mouse-1)}}} ::
+
+  #+kindex: mouse-2
+  #+kindex: mouse-1
+  On links, {{{kbd(mouse-1)}}} and {{{kbd(mouse-2)}}} opens the link
+  just as {{{kbd(C-c C-o)}}} does.
+
+- {{{kbd(mouse-3)}}} ::
+
+  #+vindex: org-link-use-indirect-buffer-for-internals
+  #+kindex: mouse-3
+  Like {{{kbd(mouse-2)}}}, but force file links to be opened with
+  Emacs, and internal links to be displayed in another window[fn:33].
+
+- {{{kbd(C-c %)}}} (~org-mark-ring-push~) ::
+
+  #+kindex: C-c %
+  #+findex: org-mark-ring-push
+  #+cindex: mark ring
+  Push the current position onto the Org mark ring, to be able to
+  return easily.  Commands following an internal link do this
+  automatically.
+
+- {{{kbd(C-c &)}}} (~org-mark-ring-goto~) ::
+
+  #+kindex: C-c &
+  #+findex: org-mark-ring-goto
+  #+cindex: links, returning to
+  Jump back to a recorded position.  A position is recorded by the
+  commands following internal links, and by {{{kbd(C-c %)}}}.  Using
+  this command several times in direct succession moves through a ring
+  of previously recorded positions.
+
+- {{{kbd(C-c C-x C-n)}}} (~org-next-link~), {{{kbd(C-c C-x C-p)}}} 
(~org-previous-link~) ::
+
+  #+kindex: C-c C-x C-p
+  #+findex: org-previous-link
+  #+kindex: C-c C-x C-n
+  #+findex: org-next-link
+  #+cindex: links, finding next/previous
+  Move forward/backward to the next link in the buffer.  At the limit
+  of the buffer, the search fails once, and then wraps around.  The
+  key bindings for this are really too long; you might want to bind
+  this also to {{{kbd(M-n)}}} and {{{kbd(M-p)}}}.
+
+  #+begin_src emacs-lisp
+  (with-eval-after-load 'org
+    (define-key org-mode-map (kbd "M-n") 'org-next-link)
+    (define-key org-mode-map (kbd "M-p") 'org-previous-link))
+  #+end_src
+
+** Using Links Outside Org
+:PROPERTIES:
+:DESCRIPTION: Linking from my C source code?
+:END:
+
+#+findex: org-insert-link-global
+#+findex: org-open-at-point-global
+You can insert and follow links that have Org syntax not only in Org,
+but in any Emacs buffer.  For this, Org provides two functions:
+~org-insert-link-global~ and ~org-open-at-point-global~.
+
+You might want to bind them to globally available keys.  See
+[[*Activation]] for some advice.
+
+** Link Abbreviations
+:PROPERTIES:
+:DESCRIPTION: Shortcuts for writing complex links.
+:END:
+#+cindex: link abbreviations
+#+cindex: abbreviation, links
+
+Long URL can be cumbersome to type, and often many similar links are
+needed in a document.  For this you can use link abbreviations.  An
+abbreviated link looks like this
+
+: [[linkword:tag][description]]
+
+#+texinfo: @noindent
+#+vindex: org-link-abbrev-alist
+where the tag is optional.  The /linkword/ must be a word, starting
+with a letter, followed by letters, numbers, =-=, and =_=.
+Abbreviations are resolved according to the information in the
+variable ~org-link-abbrev-alist~ that relates the linkwords to
+replacement text.  Here is an example:
+
+#+begin_src emacs-lisp
+(setq org-link-abbrev-alist
+      '(("bugzilla"        . "http://10.1.2.9/bugzilla/show_bug.cgi?id=";)
+        ("Nu Html Checker" . "https://validator.w3.org/nu/?doc=%h";) 
+       ("duckduckgo"      . "https://duckduckgo.com/?q=%s";)
+        ("omap"            . 
"http://nominatim.openstreetmap.org/search?q=%s&polygon=1";)
+        ("ads"             . 
"https://ui.adsabs.harvard.edu/search/q=%20author%3A\"%s\"";)))
+#+end_src
+
+If the replacement text contains the string =%s=, it is replaced with
+the tag.  Using =%h= instead of =%s= percent-encodes the tag (see the
+example above, where we need to encode the URL parameter).  Using
+=%(my-function)= passes the tag to a custom Lisp function, and replace
+it by the resulting string.
+
+If the replacement text do not contain any specifier, it is simply
+appended to the string in order to create the link.
+
+Instead of a string, you may also specify a Lisp function to create
+the link.  Such a function will be called with the tag as the only
+argument.
+
+With the above setting, you could link to a specific bug with
+=[[bugzilla:129]]=, search the web for =OrgMode= with =[[duckduckgo:OrgMode]]=,
+show the map location of the Free Software Foundation =[[gmap:51
+Franklin Street, Boston]]= or of Carsten office =[[omap:Science Park 904,
+Amsterdam, The Netherlands]]= and find out what the Org author is doing
+besides Emacs hacking with =[[ads:Dominik,C]]=.
+
+If you need special abbreviations just for a single Org buffer, you
+can define them in the file with
+
+#+cindex: @samp{LINK}, keyword
+#+begin_example
+,#+LINK: bugzilla  http://10.1.2.9/bugzilla/show_bug.cgi?id=
+,#+LINK: duckduckgo https://duckduckgo.com/?q=%s
+#+end_example
+
+In-buffer completion (see [[*Completion]]) can be used after =[= to
+complete link abbreviations.  You may also define a Lisp function that
+implements special (e.g., completion) support for inserting such a
+link with {{{kbd(C-c C-l)}}}.  Such a function should not accept any
+arguments, and should return the full link with a prefix.  You can set
+the link completion function like this:
+
+#+begin_src emacs-lisp
+(org-link-set-parameter "type" :complete #'some-completion-function)
+#+end_src
+
+** Search Options in File Links
+:PROPERTIES:
+:DESCRIPTION: Linking to a specific location.
+:ALT_TITLE: Search Options
+:END:
+#+cindex: search option in file links
+#+cindex: file links, searching
+#+cindex: attachment links, searching
+
+File links can contain additional information to make Emacs jump to a
+particular location in the file when following a link.  This can be a
+line number or a search option after a double colon[fn:34].  For
+example, when the command ~org-store-link~ creates a link (see
+[[*Handling Links]]) to a file, it encodes the words in the current line
+as a search string that can be used to find this line back later when
+following the link with {{{kbd(C-c C-o)}}}.
+
+Note that all search options apply for Attachment links in the same
+way that they apply for File links.
+
+Here is the syntax of the different ways to attach a search to a file
+link, together with explanations for each:
+
+#+begin_example
+[[file:~/code/main.c::255]]
+[[file:~/xx.org::My Target]]
+[[file:~/xx.org::*My Target]]
+[[file:~/xx.org::#my-custom-id]]
+[[file:~/xx.org::/regexp/]]
+[[attachment:main.c::255]]
+#+end_example
+
+- =255= ::
+
+  Jump to line 255.
+
+- =My Target= ::
+
+  Search for a link target =<<My Target>>=, or do a text search for
+  =my target=, similar to the search in internal links, see [[*Internal
+  Links]].  In HTML export (see [[*HTML Export]]), such a file link becomes
+  a HTML reference to the corresponding named anchor in the linked
+  file.
+
+- =*My Target= ::
+
+  In an Org file, restrict search to headlines.
+
+- =#my-custom-id= ::
+
+  Link to a heading with a =CUSTOM_ID= property
+
+- =/REGEXP/= ::
+
+  Do a regular expression search for {{{var(REGEXP)}}}.  This uses the
+  Emacs command ~occur~ to list all matches in a separate window.  If
+  the target file is in Org mode, ~org-occur~ is used to create
+  a sparse tree with the matches.
+
+As a degenerate case, a file link with an empty file name can be used
+to search the current file.  For example, =[[file:::find me]]= does
+a search for =find me= in the current file, just as =[[find me]]=
+would.
+
+** Custom Searches
+:PROPERTIES:
+:DESCRIPTION: When the default search is not enough.
+:END:
+#+cindex: custom search strings
+#+cindex: search strings, custom
+
+The default mechanism for creating search strings and for doing the
+actual search related to a file link may not work correctly in all
+cases.  For example, BibTeX database files have many entries like
+~year="1993"~ which would not result in good search strings, because
+the only unique identification for a BibTeX entry is the citation key.
+
+#+vindex: org-create-file-search-functions
+#+vindex: org-execute-file-search-functions
+If you come across such a problem, you can write custom functions to
+set the right search string for a particular file type, and to do the
+search for the string in the file.  Using ~add-hook~, these functions
+need to be added to the hook variables
+~org-create-file-search-functions~ and
+~org-execute-file-search-functions~.  See the docstring for these
+variables for more information.  Org actually uses this mechanism for
+BibTeX database files, and you can use the corresponding code as an
+implementation example.  See the file =ol-bibtex.el=.
+
+* TODO Items
+:PROPERTIES:
+:DESCRIPTION: Every tree branch can be a TODO item.
+:END:
+#+cindex: TODO items
+
+Org mode does not maintain TODO lists as separate documents[fn:35].
+Instead, TODO items are an integral part of the notes file, because
+TODO items usually come up while taking notes!  With Org mode, simply
+mark any entry in a tree as being a TODO item.  In this way,
+information is not duplicated, and the entire context from which the
+TODO item emerged is always present.
+
+Of course, this technique for managing TODO items scatters them
+throughout your notes file.  Org mode compensates for this by
+providing methods to give you an overview of all the things that you
+have to do.
+
+** Basic TODO Functionality
+:PROPERTIES:
+:DESCRIPTION: Marking and displaying TODO entries.
+:ALT_TITLE: TODO Basics
+:END:
+
+Any headline becomes a TODO item when it starts with the word =TODO=,
+for example:
+
+: *** TODO Write letter to Sam Fortune
+
+The most important commands to work with TODO entries are:
+
+- {{{kbd(C-c C-t)}}} (~org-todo~) ::
+
+  #+kindex: C-c C-t
+  #+cindex: cycling, of TODO states
+  Rotate the TODO state of the current item among
+
+  #+begin_example
+  ,-> (unmarked) -> TODO -> DONE --.
+  '--------------------------------'
+  #+end_example
+
+  If TODO keywords have fast access keys (see [[*Fast access to TODO
+  states]]), prompt for a TODO keyword through the fast selection
+  interface; this is the default behavior when
+  ~org-use-fast-todo-selection~ is non-~nil~.
+
+  The same state changing can also be done "remotely" from the agenda
+  buffer with the {{{kbd(t)}}} command key (see [[*Commands in the
+  Agenda Buffer]]).
+
+- {{{kbd(S-RIGHT)}}} {{{kbd(S-LEFT)}}} ::
+
+  #+kindex: S-RIGHT
+  #+kindex: S-LEFT
+  #+vindex: org-treat-S-cursor-todo-selection-as-state-change
+  Select the following/preceding TODO state, similar to cycling.
+  Useful mostly if more than two TODO states are possible (see
+  [[*Extended Use of TODO Keywords]]).  See also [[*Packages that conflict
+  with Org mode]], for a discussion of the interaction with
+  shift-selection.  See also the variable
+  ~org-treat-S-cursor-todo-selection-as-state-change~.
+
+- {{{kbd(C-c / t)}}} (~org-show-todo-tree~) ::
+
+  #+kindex: C-c / t
+  #+cindex: sparse tree, for TODO
+  #+vindex: org-todo-keywords
+  #+findex: org-show-todo-tree
+  View TODO items in a /sparse tree/ (see [[*Sparse Trees]]).  Folds the
+  entire buffer, but shows all TODO items---with not-DONE state---and
+  the headings hierarchy above them.  With a prefix argument, or by
+  using {{{kbd(C-c / T)}}}, search for a specific TODO.  You are
+  prompted for the keyword, and you can also give a list of keywords
+  like =KWD1|KWD2|...= to list entries that match any one of these
+  keywords.  With a numeric prefix argument N, show the tree for the
+  Nth keyword in the variable ~org-todo-keywords~.  With two prefix
+  arguments, find all TODO states, both un-done and done.
+
+- {{{kbd(M-x org-agenda t)}}} (~org-todo-list~) ::
+
+  #+kindex: t @r{(Agenda dispatcher)}
+  Show the global TODO list.  Collects the TODO items (with not-DONE
+  states) from all agenda files (see [[*Agenda Views]]) into a single
+  buffer.  The new buffer is in Org Agenda mode, which provides
+  commands to examine and manipulate the TODO entries from the new
+  buffer (see [[*Commands in the Agenda Buffer]]).  See [[*The global TODO
+  list]], for more information.
+
+- {{{kbd(S-M-RET)}}} (~org-insert-todo-heading~) ::
+
+  #+kindex: S-M-RET
+  #+findex: org-insert-todo-heading
+  Insert a new TODO entry below the current one.
+
+#+vindex: org-todo-state-tags-triggers
+Changing a TODO state can also trigger tag changes.  See the docstring
+of the option ~org-todo-state-tags-triggers~ for details.
+
+** Extended Use of TODO Keywords
+:PROPERTIES:
+:DESCRIPTION: Workflow and assignments.
+:ALT_TITLE: TODO Extensions
+:END:
+#+cindex: extended TODO keywords
+
+#+vindex: org-todo-keywords
+By default, marked TODO entries have one of only two states: TODO and
+DONE.  Org mode allows you to classify TODO items in more complex ways
+with /TODO keywords/ (stored in ~org-todo-keywords~).  With special
+setup, the TODO keyword system can work differently in different
+files.
+
+Note that /tags/ are another way to classify headlines in general and
+TODO items in particular (see [[*Tags]]).
+
+*** TODO keywords as workflow states
+:PROPERTIES:
+:DESCRIPTION: From TODO to DONE in steps.
+:ALT_TITLE: Workflow states
+:END:
+#+cindex: TODO workflow
+#+cindex: workflow states as TODO keywords
+
+You can use TODO keywords to indicate different, possibly /sequential/
+states in the process of working on an item, for example[fn:36]:
+
+#+begin_src emacs-lisp
+(setq org-todo-keywords
+      '((sequence "TODO" "FEEDBACK" "VERIFY" "|" "DONE" "DELEGATED")))
+#+end_src
+
+The vertical bar separates the TODO keywords (states that /need
+action/) from the DONE states (which need /no further action/).  If
+you do not provide the separator bar, the last state is used as the
+DONE state.
+
+#+cindex: completion, of TODO keywords
+With this setup, the command {{{kbd(C-c C-t)}}} cycles an entry from
+=TODO= to =FEEDBACK=, then to =VERIFY=, and finally to =DONE= and
+=DELEGATED=.  You may also use a numeric prefix argument to quickly
+select a specific state.  For example {{{kbd(C-3 C-c C-t)}}} changes
+the state immediately to =VERIFY=.  Or you can use {{{kbd(S-RIGHT)}}}
+and {{{kbd(S-LEFT)}}} to go forward and backward through the states.
+If you define many keywords, you can use in-buffer completion (see
+[[*Completion]]) or a special one-key selection scheme (see [[*Fast
+access to TODO states]]) to insert these words into the buffer.
+Changing a TODO state can be logged with a timestamp, see [[*Tracking
+TODO state changes]], for more information.
+
+*** TODO keywords as types
+:PROPERTIES:
+:DESCRIPTION: I do this, Fred does the rest.
+:ALT_TITLE: TODO types
+:END:
+#+cindex: TODO types
+#+cindex: names as TODO keywords
+#+cindex: types as TODO keywords
+
+The second possibility is to use TODO keywords to indicate different
+/types/ of action items.  For example, you might want to indicate that
+items are for "work" or "home".  Or, when you work with several people
+on a single project, you might want to assign action items directly to
+persons, by using their names as TODO keywords.  This type of
+functionality is actually much better served by using tags (see
+[[*Tags]]), so the TODO implementation is kept just for backward
+compatibility.
+
+Using TODO types, it would be set up like this:
+
+#+begin_src emacs-lisp
+(setq org-todo-keywords '((type "Fred" "Sara" "Lucy" "|" "DONE")))
+#+end_src
+
+In this case, different keywords do not indicate states, but
+rather different types.  So the normal work flow would be to assign
+a task to a person, and later to mark it DONE.  Org mode supports this
+style by adapting the workings of the command {{{kbd(C-c
+C-t)}}}[fn:37].  When used several times in succession, it still
+cycles through all names, in order to first select the right type for
+a task.  But when you return to the item after some time and execute
+{{{kbd(C-c C-t)}}} again, it will switch from any name directly to
+=DONE=.  Use prefix arguments or completion to quickly select
+a specific name.  You can also review the items of a specific TODO
+type in a sparse tree by using a numeric prefix to {{{kbd(C-c / t)}}}.
+For example, to see all things Lucy has to do, you would use
+{{{kbd(C-3 C-c / t)}}}.  To collect Lucy's items from all agenda files
+into a single buffer, you would use the numeric prefix argument as
+well when creating the global TODO list: {{{kbd(C-3 M-x org-agenda
+t)}}}.
+
+*** Multiple keyword sets in one file
+:PROPERTIES:
+:DESCRIPTION: Mixing it all, still finding your way.
+:ALT_TITLE: Multiple sets in one file
+:END:
+#+cindex: TODO keyword sets
+
+Sometimes you may want to use different sets of TODO keywords in
+parallel.  For example, you may want to have the basic TODO/DONE, but
+also a workflow for bug fixing, and a separate state indicating that
+an item has been canceled---so it is not DONE, but also does not
+require action.  Your setup would then look like this:
+
+#+begin_src emacs-lisp
+(setq org-todo-keywords
+      '((sequence "TODO" "|" "DONE")
+        (sequence "REPORT" "BUG" "KNOWNCAUSE" "|" "FIXED")
+        (sequence "|" "CANCELED")))
+#+end_src
+
+The keywords should all be different, this helps Org mode keep track
+of which subsequence should be used for a given entry.  In this setup,
+{{{kbd(C-c C-t)}}} only operates within a sub-sequence, so it switches
+from =DONE= to (nothing) to =TODO=, and from =FIXED= to (nothing) to
+=REPORT=.  Therefore you need a mechanism to initially select the
+correct sequence.  In addition to typing a keyword or using completion
+(see [[*Completion]]), you may also apply the following commands:
+
+#+attr_texinfo: :sep ,
+- {{{kbd(C-u C-u C-c C-t)}}}, {{{kbd(C-S-RIGHT)}}}, {{{kbd(C-S-LEFT)}}} ::
+
+  #+kindex: C-S-RIGHT
+  #+kindex: C-S-LEFT
+  #+kindex: C-u C-u C-c C-t
+  These keys jump from one TODO sub-sequence to the next.  In the
+  above example, {{{kbd(C-u C-u C-c C-t)}}} or {{{kbd(C-S-RIGHT)}}}
+  would jump from =TODO= or =DONE= to =REPORT=, and any of the words
+  in the second row to =CANCELED=.  Note that the {{{kbd(C-S-)}}} key
+  binding conflict with shift-selection (see [[*Packages that conflict
+  with Org mode]]).
+
+- {{{kbd(S-RIGHT)}}}, {{{kbd(S-LEFT)}}} ::
+
+  #+kindex: S-RIGHT
+  #+kindex: S-LEFT
+  {{{kbd(S-LEFT)}}} and {{{kbd(S-RIGHT)}}} walk through /all/ keywords
+  from all sub-sequences, so for example {{{kbd(S-RIGHT)}}} would
+  switch from =DONE= to =REPORT= in the example above.  For
+  a discussion of the interaction with shift-selection, see [[*Packages
+  that conflict with Org mode]].
+
+*** Fast access to TODO states
+:PROPERTIES:
+:DESCRIPTION: Single letter selection of state.
+:END:
+
+If you would like to quickly change an entry to an arbitrary TODO
+state instead of cycling through the states, you can set up keys for
+single-letter access to the states.  This is done by adding the
+selection character after each keyword, in parentheses[fn:38].  For
+example:
+
+#+begin_src emacs-lisp
+(setq org-todo-keywords
+      '((sequence "TODO(t)" "|" "DONE(d)")
+        (sequence "REPORT(r)" "BUG(b)" "KNOWNCAUSE(k)" "|" "FIXED(f)")
+        (sequence "|" "CANCELED(c)")))
+#+end_src
+
+#+vindex: org-fast-tag-selection-include-todo
+If you then press {{{kbd(C-c C-t)}}} followed by the selection key,
+the entry is switched to this state.  {{{kbd(SPC)}}} can be used to
+remove any TODO keyword from an entry[fn:39].
+
+*** Setting up keywords for individual files
+:PROPERTIES:
+:DESCRIPTION: Different files, different requirements.
+:ALT_TITLE: Per-file keywords
+:END:
+#+cindex: keyword options
+#+cindex: per-file keywords
+#+cindex: @samp{TODO}, keyword
+#+cindex: @samp{TYP_TODO}, keyword
+#+cindex: @samp{SEQ_TODO}, keyword
+
+It can be very useful to use different aspects of the TODO mechanism
+in different files.  For file-local settings, you need to add special
+lines to the file which set the keywords and interpretation for that
+file only.  For example, to set one of the two examples discussed
+above, you need one of the following lines, starting in column zero
+anywhere in the file:
+
+: #+TODO: TODO FEEDBACK VERIFY | DONE CANCELED
+
+You may also write =#+SEQ_TODO= to be explicit about the
+interpretation, but it means the same as =#+TODO=, or
+
+: #+TYP_TODO: Fred Sara Lucy Mike | DONE
+
+A setup for using several sets in parallel would be:
+
+#+begin_example
+,#+TODO: TODO | DONE
+,#+TODO: REPORT BUG KNOWNCAUSE | FIXED
+,#+TODO: | CANCELED
+#+end_example
+
+#+cindex: completion, of option keywords
+#+kindex: M-TAB
+To make sure you are using the correct keyword, type =#+= into the
+buffer and then use {{{kbd(M-TAB)}}} to complete it (see [[*Completion]]).
+
+#+cindex: DONE, final TODO keyword
+Remember that the keywords after the vertical bar---or the last
+keyword if no bar is there---must always mean that the item is DONE,
+although you may use a different word.  After changing one of these
+lines, use {{{kbd(C-c C-c)}}} with point still in the line to make the
+changes known to Org mode[fn:40].
+
+*** Faces for TODO keywords
+:PROPERTIES:
+:DESCRIPTION: Highlighting states.
+:END:
+#+cindex: faces, for TODO keywords
+
+#+vindex: org-todo, face
+#+vindex: org-done, face
+#+vindex: org-todo-keyword-faces
+Org mode highlights TODO keywords with special faces: ~org-todo~ for
+keywords indicating that an item still has to be acted upon, and
+~org-done~ for keywords indicating that an item is finished.  If you
+are using more than two different states, you might want to use
+special faces for some of them.  This can be done using the variable
+~org-todo-keyword-faces~.  For example:
+
+#+begin_src emacs-lisp
+(setq org-todo-keyword-faces
+      '(("TODO" . org-warning) ("STARTED" . "yellow")
+        ("CANCELED" . (:foreground "blue" :weight bold))))
+#+end_src
+
+#+vindex: org-faces-easy-properties
+While using a list with face properties as shown for =CANCELED=
+/should/ work, this does not always seem to be the case.  If
+necessary, define a special face and use that.  A string is
+interpreted as a color.  The variable ~org-faces-easy-properties~
+determines if that color is interpreted as a foreground or
+a background color.
+
+*** TODO dependencies
+:PROPERTIES:
+:DESCRIPTION: When one task needs to wait for others.
+:END:
+#+cindex: TODO dependencies
+#+cindex: dependencies, of TODO states
+
+#+vindex: org-enforce-todo-dependencies
+#+cindex: @samp{ORDERED}, property
+The structure of Org files---hierarchy and lists---makes it easy to
+define TODO dependencies.  Usually, a parent TODO task should not be
+marked as done until all TODO subtasks, or children tasks, are marked
+as done.  Sometimes there is a logical sequence to (sub)tasks, so that
+one subtask cannot be acted upon before all siblings above it have
+been marked as done.  If you customize the variable
+~org-enforce-todo-dependencies~, Org blocks entries from changing
+state to DONE while they have TODO children that are not DONE.
+Furthermore, if an entry has a property =ORDERED=, each of its TODO
+children is blocked until all earlier siblings are marked as done.
+Here is an example:
+
+#+begin_example
+,* TODO Blocked until (two) is done
+,** DONE one
+,** TODO two
+
+,* Parent
+:PROPERTIES:
+:ORDERED:  t
+:END:
+,** TODO a
+,** TODO b, needs to wait for (a)
+,** TODO c, needs to wait for (a) and (b)
+#+end_example
+
+#+cindex: TODO dependencies, @samp{NOBLOCKING}
+#+cindex: @samp{NOBLOCKING}, property
+You can ensure an entry is never blocked by using the =NOBLOCKING=
+property (see [[*Properties and Columns]]):
+
+#+begin_example
+,* This entry is never blocked
+:PROPERTIES:
+:NOBLOCKING: t
+:END:
+#+end_example
+
+- {{{kbd(C-c C-x o)}}} (~org-toggle-ordered-property~) ::
+
+  #+kindex: C-c C-x o
+  #+findex: org-toggle-ordered-property
+  #+vindex: org-track-ordered-property-with-tag
+  Toggle the =ORDERED= property of the current entry.  A property is
+  used for this behavior because this should be local to the current
+  entry, not inherited from entries above like a tag (see [[*Tags]]).
+  However, if you would like to /track/ the value of this property
+  with a tag for better visibility, customize the variable
+  ~org-track-ordered-property-with-tag~.
+
+- {{{kbd(C-u C-u C-u C-c C-t)}}} ::
+
+  #+kindex: C-u C-u C-u C-u C-c C-t
+  Change TODO state, regardless of any state blocking.
+
+#+vindex: org-agenda-dim-blocked-tasks
+If you set the variable ~org-agenda-dim-blocked-tasks~, TODO entries
+that cannot be marked as done because of unmarked children are shown
+in a dimmed font or even made invisible in agenda views (see [[*Agenda
+Views]]).
+
+#+cindex: checkboxes and TODO dependencies
+#+vindex: org-enforce-todo-dependencies
+You can also block changes of TODO states by using checkboxes (see
+[[*Checkboxes]]).  If you set the variable
+~org-enforce-todo-checkbox-dependencies~, an entry that has unchecked
+checkboxes is blocked from switching to DONE.
+
+If you need more complex dependency structures, for example
+dependencies between entries in different trees or files, check out
+the contributed module =org-depend.el=.
+
+** Progress Logging
+:PROPERTIES:
+:DESCRIPTION: Dates and notes for progress.
+:END:
+#+cindex: progress logging
+#+cindex: logging, of progress
+
+To record a timestamp and a note when changing a TODO state, call the
+command ~org-todo~ with a prefix argument.
+
+- {{{kbd(C-u C-c C-t)}}} (~org-todo~) ::
+
+  #+kindex: C-u C-c C-t
+  Prompt for a note and record a the time of the TODO state change.
+  The note is inserted as a list item below the headline, but can also
+  be placed into a drawer, see [[*Tracking TODO state changes]].
+
+If you want to be more systematic, Org mode can automatically record a
+timestamp and optionally a note when you mark a TODO item as DONE, or
+even each time you change the state of a TODO item.  This system is
+highly configurable, settings can be on a per-keyword basis and can be
+localized to a file or even a subtree.  For information on how to
+clock working time for a task, see [[*Clocking Work Time]].
+
+*** Closing items
+:PROPERTIES:
+:DESCRIPTION: When was this entry marked as done?
+:END:
+
+The most basic automatic logging is to keep track of /when/ a certain
+TODO item was marked as done.  This can be achieved with[fn:41]
+
+#+begin_src emacs-lisp
+(setq org-log-done 'time)
+#+end_src
+
+#+vindex: org-closed-keep-when-no-todo
+#+texinfo: @noindent
+Then each time you turn an entry from a TODO (not-done) state into any
+of the DONE states, a line =CLOSED: [timestamp]= is inserted just
+after the headline.  If you turn the entry back into a TODO item
+through further state cycling, that line is removed again.  If you
+turn the entry back to a non-TODO state (by pressing {{{kbd(C-c C-t
+SPC)}}} for example), that line is also removed, unless you set
+~org-closed-keep-when-no-todo~ to non-~nil~.  If you want to record
+a note along with the timestamp, use[fn:42]
+
+#+begin_src emacs-lisp
+(setq org-log-done 'note)
+#+end_src
+
+#+texinfo: @noindent
+You are then prompted for a note, and that note is stored below the
+entry with a =Closing Note= heading.
+
+*** Tracking TODO state changes
+:PROPERTIES:
+:DESCRIPTION: When did the status change?
+:END:
+#+cindex: drawer, for state change recording
+
+#+vindex: org-log-states-order-reversed
+#+vindex: org-log-into-drawer
+#+cindex: @samp{LOG_INTO_DRAWER}, property
+You might want to automatically keep track of when a state change
+occurred and maybe take a note about this change.  You can either
+record just a timestamp, or a time-stamped note.  These records are
+inserted after the headline as an itemized list, newest first[fn:43].
+When taking a lot of notes, you might want to get the notes out of the
+way into a drawer (see [[*Drawers]]).  Customize the variable
+~org-log-into-drawer~ to get this behavior---the recommended drawer
+for this is called =LOGBOOK=[fn:44].  You can also overrule the
+setting of this variable for a subtree by setting a =LOG_INTO_DRAWER=
+property.
+
+Since it is normally too much to record a note for every state, Org
+mode expects configuration on a per-keyword basis for this.  This is
+achieved by adding special markers =!= (for a timestamp) or =@= (for
+a note with timestamp) in parentheses after each keyword.  For
+example, with the setting
+
+#+begin_src emacs-lisp
+(setq org-todo-keywords
+      '((sequence "TODO(t)" "WAIT(w@/!)" "|" "DONE(d!)" "CANCELED(c@)")))
+#+end_src
+
+#+texinfo: @noindent
+To record a timestamp without a note for TODO keywords configured with
+=@=, just type {{{kbd(C-c C-c)}}} to enter a blank note when prompted.
+
+#+vindex: org-log-done
+You not only define global TODO keywords and fast access keys, but
+also request that a time is recorded when the entry is set to =DONE=,
+and that a note is recorded when switching to =WAIT= or
+=CANCELED=[fn:45].  The setting for =WAIT= is even more special: the
+=!= after the slash means that in addition to the note taken when
+entering the state, a timestamp should be recorded when /leaving/ the
+=WAIT= state, if and only if the /target/ state does not configure
+logging for entering it.  So it has no effect when switching from
+=WAIT= to =DONE=, because =DONE= is configured to record a timestamp
+only.  But when switching from =WAIT= back to =TODO=, the =/!= in the
+=WAIT= setting now triggers a timestamp even though =TODO= has no
+logging configured.
+
+You can use the exact same syntax for setting logging preferences local
+to a buffer:
+
+: #+TODO: TODO(t) WAIT(w@/!) | DONE(d!) CANCELED(c@)
+
+#+cindex: @samp{LOGGING}, property
+In order to define logging settings that are local to a subtree or
+a single item, define a =LOGGING= property in this entry.  Any
+non-empty =LOGGING= property resets all logging settings to ~nil~.
+You may then turn on logging for this specific tree using =STARTUP=
+keywords like =lognotedone= or =logrepeat=, as well as adding state
+specific settings like =TODO(!)=.  For example:
+
+#+begin_example
+,* TODO Log each state with only a time
+  :PROPERTIES:
+  :LOGGING: TODO(!) WAIT(!) DONE(!) CANCELED(!)
+  :END:
+,* TODO Only log when switching to WAIT, and when repeating
+  :PROPERTIES:
+  :LOGGING: WAIT(@) logrepeat
+  :END:
+,* TODO No logging at all
+  :PROPERTIES:
+  :LOGGING: nil
+  :END:
+#+end_example
+
+*** Tracking your habits
+:PROPERTIES:
+:DESCRIPTION: How consistent have you been?
+:END:
+#+cindex: habits
+#+cindex: @samp{STYLE}, property
+
+Org has the ability to track the consistency of a special category of
+TODO, called "habits."  To use habits, you have to enable the ~habits~
+module by customizing the variable ~org-modules~.
+
+A habit has the following properties:
+
+1. The habit is a TODO item, with a TODO keyword representing an open
+   state.
+
+2. The property =STYLE= is set to the value =habit= (see [[*Properties
+   and Columns]]).
+
+3. The TODO has a scheduled date, usually with a =.+= style repeat
+   interval.  A =++= style may be appropriate for habits with time
+   constraints, e.g., must be done on weekends, or a =+= style for an
+   unusual habit that can have a backlog, e.g., weekly reports.
+
+4. The TODO may also have minimum and maximum ranges specified by
+   using the syntax =.+2d/3d=, which says that you want to do the task
+   at least every three days, but at most every two days.
+
+5. State logging for the DONE state is enabled (see [[*Tracking TODO
+   state changes]]), in order for historical data to be represented in
+   the consistency graph.  If it is not enabled it is not an error,
+   but the consistency graphs are largely meaningless.
+
+To give you an idea of what the above rules look like in action, here's an
+actual habit with some history:
+
+#+begin_example
+,** TODO Shave
+   SCHEDULED: <2009-10-17 Sat .+2d/4d>
+   :PROPERTIES:
+   :STYLE:    habit
+   :LAST_REPEAT: [2009-10-19 Mon 00:36]
+   :END:
+   - State "DONE"       from "TODO"       [2009-10-15 Thu]
+   - State "DONE"       from "TODO"       [2009-10-12 Mon]
+   - State "DONE"       from "TODO"       [2009-10-10 Sat]
+   - State "DONE"       from "TODO"       [2009-10-04 Sun]
+   - State "DONE"       from "TODO"       [2009-10-02 Fri]
+   - State "DONE"       from "TODO"       [2009-09-29 Tue]
+   - State "DONE"       from "TODO"       [2009-09-25 Fri]
+   - State "DONE"       from "TODO"       [2009-09-19 Sat]
+   - State "DONE"       from "TODO"       [2009-09-16 Wed]
+   - State "DONE"       from "TODO"       [2009-09-12 Sat]
+#+end_example
+
+What this habit says is: I want to shave at most every 2 days---given
+by the =SCHEDULED= date and repeat interval---and at least every
+4 days.  If today is the 15th, then the habit first appears in the
+agenda (see [[*Agenda Views]]) on Oct 17, after the minimum of 2 days has
+elapsed, and will appear overdue on Oct 19, after four days have
+elapsed.
+
+What's really useful about habits is that they are displayed along
+with a consistency graph, to show how consistent you've been at
+getting that task done in the past.  This graph shows every day that
+the task was done over the past three weeks, with colors for each day.
+The colors used are:
+
+- Blue :: If the task was not to be done yet on that day.
+- Green :: If the task could have been done on that day.
+- Yellow :: If the task was going to be overdue the next day.
+- Red :: If the task was overdue on that day.
+
+In addition to coloring each day, the day is also marked with an
+asterisk if the task was actually done that day, and an exclamation
+mark to show where the current day falls in the graph.
+
+There are several configuration variables that can be used to change
+the way habits are displayed in the agenda.
+
+- ~org-habit-graph-column~ ::
+
+  #+vindex: org-habit-graph-column
+  The buffer column at which the consistency graph should be drawn.
+  This overwrites any text in that column, so it is a good idea to
+  keep your habits' titles brief and to the point.
+
+- ~org-habit-preceding-days~ ::
+
+  #+vindex: org-habit-preceding-days
+  The amount of history, in days before today, to appear in
+  consistency graphs.
+
+- ~org-habit-following-days~ ::
+
+  #+vindex: org-habit-following-days
+  The number of days after today that appear in consistency graphs.
+
+- ~org-habit-show-habits-only-for-today~ ::
+
+  #+vindex: org-habit-show-habits-only-for-today
+  If non-~nil~, only show habits in today's agenda view.  The default
+  value is ~t~.  Pressing {{{kbd(C-u K)}}} in the agenda toggles this
+  variable.
+
+Lastly, pressing {{{kbd(K)}}} in the agenda buffer causes habits to
+temporarily be disabled and do not appear at all.  Press {{{kbd(K)}}}
+again to bring them back.  They are also subject to tag filtering, if
+you have habits which should only be done in certain contexts, for
+example.
+
+** Priorities
+:PROPERTIES:
+:DESCRIPTION: Some things are more important than others.
+:END:
+#+cindex: priorities
+#+cindex: priority cookie
+
+If you use Org mode extensively, you may end up with enough TODO items
+that it starts to make sense to prioritize them.  Prioritizing can be
+done by placing a /priority cookie/ into the headline of a TODO item
+right after the TODO keyword, like this:
+
+: *** TODO [#A] Write letter to Sam Fortune
+
+#+vindex: org-priority-faces
+By default, Org mode supports three priorities: =A=, =B=, and =C=.
+=A= is the highest priority.  An entry without a cookie is treated as
+equivalent if it had priority =B=.  Priorities make a difference only
+for sorting in the agenda (see [[*Weekly/daily agenda]]).  Outside the
+agenda, they have no inherent meaning to Org mode.  The cookies are
+displayed with the face defined by the variable ~org-priority-faces~,
+which can be customized.
+
+You can also use numeric values for priorities, such as
+
+: *** TODO [#1] Write letter to Sam Fortune
+
+When using numeric priorities, you need to set ~org-priority-highest~,
+~org-priority-lowest~ and ~org-priority-default~ to integers, which
+must all be strictly inferior to 65.
+
+Priorities can be attached to any outline node; they do not need to be
+TODO items.
+
+#+attr_texinfo: :sep ;
+- {{{kbd(C-c \,)}}} (~org-priority~) ::
+
+  #+kindex: C-c ,
+  #+findex: org-priority
+  Set the priority of the current headline.  The command prompts for
+  a priority character =A=, =B= or =C=.  When you press {{{kbd(SPC)}}}
+  instead, the priority cookie, if one is set, is removed from the
+  headline.  The priorities can also be changed "remotely" from the
+  agenda buffer with the {{{kbd(\,)}}} command (see [[*Commands in the
+  Agenda Buffer]]).
+
+- {{{kbd(S-UP)}}} (~org-priority-up~); {{{kbd(S-DOWN)}}} (~org-priority-down~) 
::
+
+  #+kindex: S-UP
+  #+kindex: S-DOWN
+  #+findex: org-priority-up
+  #+findex: org-priority-down
+  #+vindex: org-priority-start-cycle-with-default
+  Increase/decrease the priority of the current headline[fn:46].  Note
+  that these keys are also used to modify timestamps (see [[*Creating
+  Timestamps]]).  See also [[*Packages that conflict with Org mode]], for
+  a discussion of the interaction with shift-selection.
+
+#+vindex: org-priority-highest
+#+vindex: org-priority-lowest
+#+vindex: org-priority-default
+You can change the range of allowed priorities by setting the
+variables ~org-priority-highest~, ~org-priority-lowest~, and
+~org-priority-default~.  For an individual buffer, you may set these
+values (highest, lowest, default) like this (please make sure that the
+highest priority is earlier in the alphabet than the lowest priority):
+
+#+cindex: @samp{PRIORITIES}, keyword
+: #+PRIORITIES: A C B
+
+Or, using numeric values:
+
+: #+PRIORITIES: 1 10 5
+
+** Breaking Down Tasks into Subtasks
+:PROPERTIES:
+:DESCRIPTION: Splitting a task into manageable pieces.
+:ALT_TITLE: Breaking Down Tasks
+:END:
+#+cindex: tasks, breaking down
+#+cindex: statistics, for TODO items
+
+#+vindex: org-agenda-todo-list-sublevels
+It is often advisable to break down large tasks into smaller,
+manageable subtasks.  You can do this by creating an outline tree
+below a TODO item, with detailed subtasks on the tree[fn:47].  To keep
+an overview of the fraction of subtasks that have already been marked
+as done, insert either =[/]= or =[%]= anywhere in the headline.  These
+cookies are updated each time the TODO status of a child changes, or
+when pressing {{{kbd(C-c C-c)}}} on the cookie.  For example:
+
+#+begin_example
+,* Organize Party [33%]
+,** TODO Call people [1/2]
+,*** TODO Peter
+,*** DONE Sarah
+,** TODO Buy food
+,** DONE Talk to neighbor
+#+end_example
+
+#+cindex: @samp{COOKIE_DATA}, property
+If a heading has both checkboxes and TODO children below it, the
+meaning of the statistics cookie become ambiguous.  Set the property
+=COOKIE_DATA= to either =checkbox= or =todo= to resolve this issue.
+
+#+vindex: org-hierarchical-todo-statistics
+If you would like to have the statistics cookie count any TODO entries
+in the subtree (not just direct children), configure the variable
+~org-hierarchical-todo-statistics~.  To do this for a single subtree,
+include the word =recursive= into the value of the =COOKIE_DATA=
+property.
+
+#+begin_example org
+,* Parent capturing statistics [2/20]
+  :PROPERTIES:
+  :COOKIE_DATA: todo recursive
+  :END:
+#+end_example
+
+If you would like a TODO entry to automatically change to DONE when
+all children are done, you can use the following setup:
+
+#+begin_src emacs-lisp
+(defun org-summary-todo (n-done n-not-done)
+  "Switch entry to DONE when all subentries are done, to TODO otherwise."
+  (let (org-log-done org-log-states)   ; turn off logging
+    (org-todo (if (= n-not-done 0) "DONE" "TODO"))))
+
+(add-hook 'org-after-todo-statistics-hook 'org-summary-todo)
+#+end_src
+
+Another possibility is the use of checkboxes to identify (a hierarchy
+of) a large number of subtasks (see [[*Checkboxes]]).
+
+** Checkboxes
+:PROPERTIES:
+:DESCRIPTION: Tick-off lists.
+:END:
+#+cindex: checkboxes
+
+#+vindex: org-list-automatic-rules
+Every item in a plain list[fn:48] (see [[*Plain Lists]]) can be made into
+a checkbox by starting it with the string =[ ]=.  This feature is
+similar to TODO items (see [[*TODO Items]]), but is more lightweight.
+Checkboxes are not included into the global TODO list, so they are
+often great to split a task into a number of simple steps.  Or you can
+use them in a shopping list.
+
+Here is an example of a checkbox list.
+
+#+begin_example
+,* TODO Organize party [2/4]
+  - [-] call people [1/3]
+    - [ ] Peter
+    - [X] Sarah
+    - [ ] Sam
+  - [X] order food
+  - [ ] think about what music to play
+  - [X] talk to the neighbors
+#+end_example
+
+Checkboxes work hierarchically, so if a checkbox item has children
+that are checkboxes, toggling one of the children checkboxes makes the
+parent checkbox reflect if none, some, or all of the children are
+checked.
+
+#+cindex: statistics, for checkboxes
+#+cindex: checkbox statistics
+#+cindex: @samp{COOKIE_DATA}, property
+#+vindex: org-hierarchical-checkbox-statistics
+The =[2/4]= and =[1/3]= in the first and second line are cookies
+indicating how many checkboxes present in this entry have been checked
+off, and the total number of checkboxes present.  This can give you an
+idea on how many checkboxes remain, even without opening a folded
+entry.  The cookies can be placed into a headline or into (the first
+line of) a plain list item.  Each cookie covers checkboxes of direct
+children structurally below the headline/item on which the cookie
+appears[fn:49].  You have to insert the cookie yourself by typing
+either =[/]= or =[%]=.  With =[/]= you get an =n out of m= result, as
+in the examples above.  With =[%]= you get information about the
+percentage of checkboxes checked (in the above example, this would be
+=[50%]= and =[33%]=, respectively).  In a headline, a cookie can count
+either checkboxes below the heading or TODO states of children, and it
+displays whatever was changed last.  Set the property =COOKIE_DATA= to
+either =checkbox= or =todo= to resolve this issue.
+
+#+cindex: blocking, of checkboxes
+#+cindex: checkbox blocking
+#+cindex: @samp{ORDERED}, property
+If the current outline node has an =ORDERED= property, checkboxes must
+be checked off in sequence, and an error is thrown if you try to check
+off a box while there are unchecked boxes above it.
+
+The following commands work with checkboxes:
+
+- {{{kbd(C-c C-c)}}} (~org-toggle-checkbox~) ::
+
+  #+kindex: C-c C-c
+  #+findex: org-toggle-checkbox
+  Toggle checkbox status or---with prefix argument---checkbox presence
+  at point.  With a single prefix argument, add an empty checkbox or
+  remove the current one[fn:50].  With a double prefix argument, set
+  it to =[-]=, which is considered to be an intermediate state.
+
+- {{{kbd(C-c C-x C-b)}}} (~org-toggle-checkbox~) ::
+
+  #+kindex: C-c C-x C-b
+  Toggle checkbox status or---with prefix argument---checkbox presence
+  at point.  With double prefix argument, set it to =[-]=, which is
+  considered to be an intermediate state.
+
+  - If there is an active region, toggle the first checkbox in the
+    region and set all remaining boxes to the same status as the
+    first.  With a prefix argument, add or remove the checkbox for all
+    items in the region.
+
+  - If point is in a headline, toggle checkboxes in the region between
+    this headline and the next---so /not/ the entire subtree.
+
+  - If there is no active region, just toggle the checkbox at point.
+
+- {{{kbd(C-c C-x C-r)}}} (~org-toggle-radio-button~) ::
+
+  #+kindex: C-c C-x C-r
+  #+findex: org-toggle-radio-button
+  #+cindex: radio button, checkbox as
+  Toggle checkbox status by using the checkbox of the item at point as
+  a radio button: when the checkbox is turned on, all other checkboxes
+  on the same level will be turned off.  With a universal prefix
+  argument, toggle the presence of the checkbox.  With a double prefix
+  argument, set it to =[-]=.
+
+  #+findex: org-list-checkbox-radio-mode
+  {{{kbd(C-c C-c)}}} can be told to consider checkboxes as radio buttons by
+  setting =#+ATTR_ORG: :radio t= right before the list or by calling
+  {{{kbd(M-x org-list-checkbox-radio-mode)}}} to activate this minor mode.
+
+- {{{kbd(M-S-RET)}}} (~org-insert-todo-heading~) ::
+
+  #+kindex: M-S-RET
+  #+findex: org-insert-todo-heading
+  Insert a new item with a checkbox.  This works only if point is
+  already in a plain list item (see [[*Plain Lists]]).
+
+- {{{kbd(C-c C-x o)}}} (~org-toggle-ordered-property~) ::
+
+  #+kindex: C-c C-x o
+  #+findex: org-toggle-ordered-property
+  #+vindex: org-track-ordered-property-with-tag
+  Toggle the =ORDERED= property of the entry, to toggle if checkboxes
+  must be checked off in sequence.  A property is used for this
+  behavior because this should be local to the current entry, not
+  inherited like a tag.  However, if you would like to /track/ the
+  value of this property with a tag for better visibility, customize
+  ~org-track-ordered-property-with-tag~.
+
+- {{{kbd(C-c #)}}} (~org-update-statistics-cookies~) ::
+
+  #+kindex: C-c #
+  #+findex: org-update-statistics-cookies
+  Update the statistics cookie in the current outline entry.  When
+  called with a {{{kbd(C-u)}}} prefix, update the entire file.
+  Checkbox statistic cookies are updated automatically if you toggle
+  checkboxes with {{{kbd(C-c C-c)}}} and make new ones with
+  {{{kbd(M-S-RET)}}}.  TODO statistics cookies update when changing
+  TODO states.  If you delete boxes/entries or add/change them by
+  hand, use this command to get things back into sync.
+
+* Tags
+:PROPERTIES:
+:DESCRIPTION: Tagging headlines and matching sets of tags.
+:END:
+#+cindex: tags
+#+cindex: headline tagging
+#+cindex: matching, tags
+#+cindex: sparse tree, tag based
+
+An excellent way to implement labels and contexts for
+cross-correlating information is to assign /tags/ to headlines.  Org
+mode has extensive support for tags.
+
+#+vindex: org-tag-faces
+Every headline can contain a list of tags; they occur at the end of
+the headline.  Tags are normal words containing letters, numbers, =_=,
+and =@=.  Tags must be preceded and followed by a single colon, e.g.,
+=:work:=.  Several tags can be specified, as in =:work:urgent:=.  Tags
+by default are in bold face with the same color as the headline.  You
+may specify special faces for specific tags using the variable
+~org-tag-faces~, in much the same way as you can for TODO keywords
+(see [[*Faces for TODO keywords]]).
+
+** Tag Inheritance
+:PROPERTIES:
+:DESCRIPTION: Tags use the tree structure of an outline.
+:END:
+#+cindex: tag inheritance
+#+cindex: inheritance, of tags
+#+cindex: sublevels, inclusion into tags match
+
+/Tags/ make use of the hierarchical structure of outline trees.  If
+a heading has a certain tag, all subheadings inherit the tag as well.
+For example, in the list
+
+#+begin_example
+,* Meeting with the French group      :work:
+,** Summary by Frank                  :boss:notes:
+,*** TODO Prepare slides for him      :action:
+#+end_example
+
+#+texinfo: @noindent
+the final heading has the tags =work=, =boss=, =notes=, and =action=
+even though the final heading is not explicitly marked with those
+tags.  You can also set tags that all entries in a file should inherit
+just as if these tags were defined in a hypothetical level zero that
+surrounds the entire file.  Use a line like this[fn:51]
+
+#+cindex: @samp{FILETAGS}, keyword
+: #+FILETAGS: :Peter:Boss:Secret:
+
+#+vindex: org-use-tag-inheritance
+#+vindex: org-tags-exclude-from-inheritance
+To limit tag inheritance to specific tags, or to turn it off entirely,
+use the variables ~org-use-tag-inheritance~ and
+~org-tags-exclude-from-inheritance~.
+
+#+vindex: org-tags-match-list-sublevels
+When a headline matches during a tags search while tag inheritance is
+turned on, all the sublevels in the same tree---for a simple match
+form---match as well[fn:52].  The list of matches may then become
+very long.  If you only want to see the first tags match in a subtree,
+configure the variable ~org-tags-match-list-sublevels~ (not
+recommended).
+
+#+vindex: org-agenda-use-tag-inheritance
+Tag inheritance is relevant when the agenda search tries to match
+a tag, either in the ~tags~ or ~tags-todo~ agenda types.  In other
+agenda types, ~org-use-tag-inheritance~ has no effect.  Still, you may
+want to have your tags correctly set in the agenda, so that tag
+filtering works fine, with inherited tags.  Set
+~org-agenda-use-tag-inheritance~ to control this: the default value
+includes all agenda types, but setting this to ~nil~ can really speed
+up agenda generation.
+
+** Setting Tags
+:PROPERTIES:
+:DESCRIPTION: How to assign tags to a headline.
+:END:
+#+cindex: setting tags
+#+cindex: tags, setting
+
+#+kindex: M-TAB
+Tags can simply be typed into the buffer at the end of a headline.
+After a colon, {{{kbd(M-TAB)}}} offers completion on tags.  There is
+also a special command for inserting tags:
+
+- {{{kbd(C-c C-q)}}} (~org-set-tags-command~) ::
+
+  #+kindex: C-c C-q
+  #+findex: org-set-tags-command
+  #+cindex: completion, of tags
+  #+vindex: org-tags-column
+  Enter new tags for the current headline.  Org mode either offers
+  completion or a special single-key interface for setting tags, see
+  below.  After pressing {{{kbd(RET)}}}, the tags are inserted and
+  aligned to ~org-tags-column~.  When called with a {{{kbd(C-u)}}}
+  prefix, all tags in the current buffer are aligned to that column,
+  just to make things look nice.  Tags are automatically realigned
+  after promotion, demotion, and TODO state changes (see [[*Basic TODO
+  Functionality]]).
+
+- {{{kbd(C-c C-c)}}} (~org-set-tags-command~) ::
+
+  #+kindex: C-c C-c
+  When point is in a headline, this does the same as {{{kbd(C-c
+  C-q)}}}.
+
+#+vindex: org-complete-tags-always-offer-all-agenda-tags
+#+vindex: org-tag-alist
+#+cindex: @samp{TAGS}, keyword
+Org supports tag insertion based on a /list of tags/.  By default this
+list is constructed dynamically, containing all tags currently used in
+the buffer[fn:53].  You may also globally specify a hard list of tags
+with the variable ~org-tag-alist~.  Finally you can set the default
+tags for a given file using the =TAGS= keyword, like
+
+#+begin_example
+,#+TAGS: @work @home @tennisclub
+,#+TAGS: laptop car pc sailboat
+#+end_example
+
+If you have globally defined your preferred set of tags using the
+variable ~org-tag-alist~, but would like to use a dynamic tag list in
+a specific file, add an empty =TAGS= keyword to that file:
+
+: #+TAGS:
+
+#+vindex: org-tag-persistent-alist
+If you have a preferred set of tags that you would like to use in
+every file, in addition to those defined on a per-file basis by =TAGS=
+keyword, then you may specify a list of tags with the variable
+~org-tag-persistent-alist~.  You may turn this off on a per-file basis
+by adding a =STARTUP= keyword to that file:
+
+: #+STARTUP: noptag
+
+By default Org mode uses the standard minibuffer completion facilities
+for entering tags.  However, it also implements another, quicker, tag
+selection method called /fast tag selection/.  This allows you to
+select and deselect tags with just a single key press.  For this to
+work well you should assign unique letters to most of your commonly
+used tags.  You can do this globally by configuring the variable
+~org-tag-alist~ in your Emacs init file.  For example, you may find
+the need to tag many items in different files with =@home=.  In this
+case you can set something like:
+
+#+begin_src emacs-lisp
+(setq org-tag-alist '(("@work" . ?w) ("@home" . ?h) ("laptop" . ?l)))
+#+end_src
+
+If the tag is only relevant to the file you are working on, then you
+can instead set the =TAGS= keyword as:
+
+: #+TAGS: @work(w)  @home(h)  @tennisclub(t)  laptop(l)  pc(p)
+
+The tags interface shows the available tags in a splash window.  If
+you want to start a new line after a specific tag, insert =\n= into
+the tag list
+
+: #+TAGS: @work(w) @home(h) @tennisclub(t) \n laptop(l) pc(p)
+
+#+texinfo: @noindent
+or write them in two lines:
+
+#+begin_example
+,#+TAGS: @work(w)  @home(h)  @tennisclub(t)
+,#+TAGS: laptop(l)  pc(p)
+#+end_example
+
+You can also group together tags that are mutually exclusive by using
+braces, as in:
+
+: #+TAGS: { @work(w)  @home(h)  @tennisclub(t) }  laptop(l)  pc(p)
+
+#+texinfo: @noindent
+you indicate that at most one of =@work=, =@home=, and =@tennisclub=
+should be selected.  Multiple such groups are allowed.
+
+Do not forget to press {{{kbd(C-c C-c)}}} with point in one of these
+lines to activate any changes.
+
+To set these mutually exclusive groups in the variable
+~org-tags-alist~, you must use the dummy tags ~:startgroup~ and
+~:endgroup~ instead of the braces.  Similarly, you can use ~:newline~
+to indicate a line break.  The previous example would be set globally
+by the following configuration:
+
+#+begin_src emacs-lisp
+(setq org-tag-alist '((:startgroup . nil)
+                      ("@work" . ?w) ("@home" . ?h)
+                      ("@tennisclub" . ?t)
+                      (:endgroup . nil)
+                      ("laptop" . ?l) ("pc" . ?p)))
+#+end_src
+
+If at least one tag has a selection key then pressing {{{kbd(C-c
+C-c)}}} automatically presents you with a special interface, listing
+inherited tags, the tags of the current headline, and a list of all
+valid tags with corresponding keys[fn:54].
+
+Pressing keys assigned to tags adds or removes them from the list of
+tags in the current line.  Selecting a tag in a group of mutually
+exclusive tags turns off any other tag from that group.
+
+In this interface, you can also use the following special keys:
+
+- {{{kbd(TAB)}}} ::
+
+  #+kindex: TAB
+  Enter a tag in the minibuffer, even if the tag is not in the
+  predefined list.  You can complete on all tags present in the
+  buffer.  You can also add several tags: just separate them with
+  a comma.
+
+- {{{kbd(SPC)}}} ::
+
+  #+kindex: SPC
+  Clear all tags for this line.
+
+- {{{kbd(RET)}}} ::
+
+  #+kindex: RET
+  Accept the modified set.
+
+- {{{kbd(C-g)}}} ::
+
+  #+kindex: C-g
+  Abort without installing changes.
+
+- {{{kbd(q)}}} ::
+
+  #+kindex: q
+  If {{{kbd(q)}}} is not assigned to a tag, it aborts like
+  {{{kbd(C-g)}}}.
+
+- {{{kbd(!)}}} ::
+
+  #+kindex: !
+  Turn off groups of mutually exclusive tags.  Use this to (as an
+  exception) assign several tags from such a group.
+
+- {{{kbd(C-c)}}} ::
+
+  #+kindex: C-c C-c
+  Toggle auto-exit after the next change (see below).  If you are
+  using expert mode, the first {{{kbd(C-c)}}} displays the selection
+  window.
+
+This method lets you assign tags to a headline with very few keys.
+With the above setup, you could clear the current tags and set
+=@home=, =laptop= and =pc= tags with just the following keys:
+{{{kbd(C-c C-c SPC h l p RET)}}}.  Switching from =@home= to =@work=
+would be done with {{{kbd(C-c C-c w RET)}}} or alternatively with
+{{{kbd(C-c C-c C-c w)}}}.  Adding the non-predefined tag =sarah= could
+be done with {{{kbd(C-c C-c TAB s a r a h RET)}}}.
+
+#+vindex: org-fast-tag-selection-single-key
+If you find that most of the time you need only a single key press to
+modify your list of tags, set the variable
+~org-fast-tag-selection-single-key~.  Then you no longer have to press
+{{{kbd(RET)}}} to exit fast tag selection---it exits after the first
+change.  If you then occasionally need more keys, press {{{kbd(C-c)}}}
+to turn off auto-exit for the current tag selection process (in
+effect: start selection with {{{kbd(C-c C-c C-c)}}} instead of
+{{{kbd(C-c C-c)}}}).  If you set the variable to the value ~expert~,
+the special window is not even shown for single-key tag selection, it
+comes up only when you press an extra {{{kbd(C-c)}}}.
+
+** Tag Hierarchy
+:PROPERTIES:
+:DESCRIPTION: Create a hierarchy of tags.
+:END:
+#+cindex: group tags
+#+cindex: tags, groups
+#+cindex: tags hierarchy
+
+Tags can be defined in hierarchies.  A tag can be defined as a /group
+tag/ for a set of other tags.  The group tag can be seen as the
+"broader term" for its set of tags.  Defining multiple group tags and
+nesting them creates a tag hierarchy.
+
+One use-case is to create a taxonomy of terms (tags) that can be used
+to classify nodes in a document or set of documents.
+
+When you search for a group tag, it return matches for all members in
+the group and its subgroups.  In an agenda view, filtering by a group
+tag displays or hide headlines tagged with at least one of the members
+of the group or any of its subgroups.  This makes tag searches and
+filters even more flexible.
+
+You can set group tags by using brackets and inserting a colon between
+the group tag and its related tags---beware that all whitespaces are
+mandatory so that Org can parse this line correctly:
+
+: #+TAGS: [ GTD : Control Persp ]
+
+In this example, =GTD= is the group tag and it is related to two other
+tags: =Control=, =Persp=.  Defining =Control= and =Persp= as group
+tags creates a hierarchy of tags:
+
+#+begin_example
+,#+TAGS: [ Control : Context Task ]
+,#+TAGS: [ Persp : Vision Goal AOF Project ]
+#+end_example
+
+That can conceptually be seen as a hierarchy of tags:
+
+- =GTD=
+  - =Persp=
+    - =Vision=
+    - =Goal=
+    - =AOF=
+    - =Project=
+  - =Control=
+    - =Context=
+    - =Task=
+
+You can use the ~:startgrouptag~, ~:grouptags~ and ~:endgrouptag~
+keyword directly when setting ~org-tag-alist~ directly:
+
+#+begin_src emacs-lisp
+(setq org-tag-alist '((:startgrouptag)
+                      ("GTD")
+                      (:grouptags)
+                      ("Control")
+                      ("Persp")
+                      (:endgrouptag)
+                      (:startgrouptag)
+                      ("Control")
+                      (:grouptags)
+                      ("Context")
+                      ("Task")
+                      (:endgrouptag)))
+#+end_src
+
+The tags in a group can be mutually exclusive if using the same group
+syntax as is used for grouping mutually exclusive tags together; using
+curly brackets.
+
+: #+TAGS: { Context : @Home @Work @Call }
+
+When setting ~org-tag-alist~ you can use ~:startgroup~ and ~:endgroup~
+instead of ~:startgrouptag~ and ~:endgrouptag~ to make the tags
+mutually exclusive.
+
+Furthermore, the members of a group tag can also be regular
+expressions, creating the possibility of a more dynamic and rule-based
+tag structure.  The regular expressions in the group must be specified
+within curly brackets.  Here is an expanded example:
+
+#+begin_example
+,#+TAGS: [ Vision : {V@.+} ]
+,#+TAGS: [ Goal : {G@.+} ]
+,#+TAGS: [ AOF : {AOF@.+} ]
+,#+TAGS: [ Project : {P@.+} ]
+#+end_example
+
+Searching for the tag =Project= now lists all tags also including
+regular expression matches for =P@.+=, and similarly for tag searches
+on =Vision=, =Goal= and =AOF=.  For example, this would work well for
+a project tagged with a common project-identifier, e.g.,
+=P@2014_OrgTags=.
+
+#+kindex: C-c C-x q
+#+findex: org-toggle-tags-groups
+#+vindex: org-group-tags
+If you want to ignore group tags temporarily, toggle group tags
+support with ~org-toggle-tags-groups~, bound to {{{kbd(C-c C-x q)}}}.
+If you want to disable tag groups completely, set ~org-group-tags~ to
+~nil~.
+
+** Tag Searches
+:PROPERTIES:
+:DESCRIPTION: Searching for combinations of tags.
+:END:
+#+cindex: tag searches
+#+cindex: searching for tags
+
+Once a system of tags has been set up, it can be used to collect
+related information into special lists.
+
+- {{{kbd(C-c / m)}}} or {{{kbd(C-c \)}}} (~org-match-sparse-tree~) ::
+
+  #+kindex: C-c / m
+  #+kindex: C-c \
+  #+findex: org-match-sparse-tree
+  Create a sparse tree with all headlines matching a tags search.
+  With a {{{kbd(C-u)}}} prefix argument, ignore headlines that are not
+  a TODO line.
+
+- {{{kbd(M-x org-agenda m)}}} (~org-tags-view~) ::
+
+  #+kindex: m @r{(Agenda dispatcher)}
+  #+findex: org-tags-view
+  Create a global list of tag matches from all agenda files.  See
+  [[*Matching tags and properties]].
+
+- {{{kbd(M-x org-agenda M)}}} (~org-tags-view~) ::
+
+  #+kindex: M @r{(Agenda dispatcher)}
+  #+vindex: org-tags-match-list-sublevels
+  Create a global list of tag matches from all agenda files, but check
+  only TODO items and force checking subitems (see the option
+  ~org-tags-match-list-sublevels~).
+
+These commands all prompt for a match string which allows basic
+Boolean logic like =+boss+urgent-project1=, to find entries with tags
+=boss= and =urgent=, but not =project1=, or =Kathy|Sally= to find
+entries which are tagged, like =Kathy= or =Sally=.  The full syntax of
+the search string is rich and allows also matching against TODO
+keywords, entry levels and properties.  For a complete description
+with many examples, see [[*Matching tags and properties]].
+
+* Properties and Columns
+:PROPERTIES:
+:DESCRIPTION: Storing information about an entry.
+:END:
+#+cindex: properties
+
+A property is a key-value pair associated with an entry.  Properties
+can be set so they are associated with a single entry, with every
+entry in a tree, or with the whole buffer.
+
+There are two main applications for properties in Org mode.  First,
+properties are like tags, but with a value.  Imagine maintaining
+a file where you document bugs and plan releases for a piece of
+software.  Instead of using tags like =release_1=, =release_2=, you
+can use a property, say =Release=, that in different subtrees has
+different values, such as =1.0= or =2.0=.  Second, you can use
+properties to implement (very basic) database capabilities in an Org
+buffer.  Imagine keeping track of your music CDs, where properties
+could be things such as the album, artist, date of release, number of
+tracks, and so on.
+
+Properties can be conveniently edited and viewed in column view (see
+[[*Column View]]).
+
+** Property Syntax
+:PROPERTIES:
+:DESCRIPTION: How properties are spelled out.
+:END:
+#+cindex: property syntax
+#+cindex: drawer, for properties
+
+Properties are key--value pairs.  When they are associated with
+a single entry or with a tree they need to be inserted into a special
+drawer (see [[*Drawers]]) with the name =PROPERTIES=, which has to be
+located right below a headline, and its planning line (see [[*Deadlines
+and Scheduling]]) when applicable.  Each property is specified on
+a single line, with the key---surrounded by colons---first, and the
+value after it.  Keys are case-insensitive.  Here is an example:
+
+#+begin_example
+,* CD collection
+,** Classic
+,*** Goldberg Variations
+    :PROPERTIES:
+    :Title:     Goldberg Variations
+    :Composer:  J.S. Bach
+    :Artist:    Glenn Gould
+    :Publisher: Deutsche Grammophon
+    :NDisks:    1
+    :END:
+#+end_example
+
+Depending on the value of ~org-use-property-inheritance~, a property
+set this way is associated either with a single entry, or with the
+sub-tree defined by the entry, see [[*Property Inheritance]].
+
+You may define the allowed values for a particular property =Xyz= by
+setting a property =Xyz_ALL=.  This special property is /inherited/,
+so if you set it in a level 1 entry, it applies to the entire tree.
+When allowed values are defined, setting the corresponding property
+becomes easier and is less prone to typing errors.  For the example
+with the CD collection, we can pre-define publishers and the number of
+disks in a box like this:
+
+#+begin_example
+,* CD collection
+  :PROPERTIES:
+  :NDisks_ALL:  1 2 3 4
+  :Publisher_ALL: "Deutsche Grammophon" Philips EMI
+  :END:
+#+end_example
+
+Properties can be inserted on buffer level.  That means they apply
+before the first headline and can be inherited by all entries in a
+file.  Property blocks defined before first headline needs to be
+located at the top of the buffer, allowing only comments above.
+
+Properties can also be defined using lines like:
+
+#+cindex: @samp{_ALL} suffix, in properties
+#+cindex: @samp{PROPERTY}, keyword
+: #+PROPERTY: NDisks_ALL 1 2 3 4
+
+#+cindex: @samp{+} suffix, in properties
+If you want to add to the value of an existing property, append a =+=
+to the property name.  The following results in the property =var=
+having the value =foo=1 bar=2=.
+
+#+begin_example
+,#+PROPERTY: var  foo=1
+,#+PROPERTY: var+ bar=2
+#+end_example
+
+It is also possible to add to the values of inherited properties.  The
+following results in the =Genres= property having the value =Classic
+Baroque= under the =Goldberg Variations= subtree.
+
+#+begin_example
+,* CD collection
+,** Classic
+    :PROPERTIES:
+    :Genres: Classic
+    :END:
+,*** Goldberg Variations
+    :PROPERTIES:
+    :Title:     Goldberg Variations
+    :Composer:  J.S. Bach
+    :Artist:    Glenn Gould
+    :Publisher: Deutsche Grammophon
+    :NDisks:    1
+    :Genres+:   Baroque
+    :END:
+#+end_example
+
+Note that a property can only have one entry per drawer.
+
+#+vindex: org-global-properties
+Property values set with the global variable ~org-global-properties~
+can be inherited by all entries in all Org files.
+
+The following commands help to work with properties:
+
+#+attr_texinfo: :sep ,
+- {{{kbd(M-TAB)}}} (~pcomplete~) ::
+
+  #+kindex: M-TAB
+  #+findex: pcomplete
+  After an initial colon in a line, complete property keys.  All keys
+  used in the current file are offered as possible completions.
+
+- {{{kbd(C-c C-x p)}}} (~org-set-property~) ::
+
+  #+kindex: C-c C-x p
+  #+findex: org-set-property
+  Set a property.  This prompts for a property name and a value.  If
+  necessary, the property drawer is created as well.
+
+- {{{kbd(C-u M-x org-insert-drawer)}}} ::
+
+  #+findex: org-insert-drawer
+  Insert a property drawer into the current entry.  The drawer is
+  inserted early in the entry, but after the lines with planning
+  information like deadlines.  If before first headline the drawer is
+  inserted at the top of the drawer after any potential comments.
+
+- {{{kbd(C-c C-c)}}} (~org-property-action~) ::
+
+  #+kindex: C-c C-c
+  #+findex: org-property-action
+  With point in a property drawer, this executes property commands.
+
+- {{{kbd(C-c C-c s)}}} (~org-set-property~) ::
+
+  #+kindex: C-c C-c s
+  #+findex: org-set-property
+  Set a property in the current entry.  Both the property and the
+  value can be inserted using completion.
+
+- {{{kbd(S-RIGHT)}}} (~org-property-next-allowed-values~),  {{{kbd(S-LEFT)}}} 
(~org-property-previous-allowed-value~) ::
+
+  #+kindex: S-RIGHT
+  #+kindex: S-LEFT
+  Switch property at point to the next/previous allowed value.
+
+- {{{kbd(C-c C-c d)}}} (~org-delete-property~) ::
+
+  #+kindex: C-c C-c d
+  #+findex: org-delete-property
+  Remove a property from the current entry.
+
+- {{{kbd(C-c C-c D)}}} (~org-delete-property-globally~) ::
+
+  #+kindex: C-c C-c D
+  #+findex: org-delete-property-globally
+  Globally remove a property, from all entries in the current file.
+
+- {{{kbd(C-c C-c c)}}} (~org-compute-property-at-point~) ::
+
+  #+kindex: C-c C-c c
+  #+findex: org-compute-property-at-point
+  Compute the property at point, using the operator and scope from the
+  nearest column format definition.
+
+** Special Properties
+:PROPERTIES:
+:DESCRIPTION: Access to other Org mode features.
+:END:
+#+cindex: properties, special
+
+Special properties provide an alternative access method to Org mode
+features, like the TODO state or the priority of an entry, discussed
+in the previous chapters.  This interface exists so that you can
+include these states in a column view (see [[*Column View]]), or to use
+them in queries.  The following property names are special and should
+not be used as keys in the properties drawer:
+
+#+cindex: @samp{ALLTAGS}, special property
+#+cindex: @samp{BLOCKED}, special property
+#+cindex: @samp{CLOCKSUM}, special property
+#+cindex: @samp{CLOCKSUM_T}, special property
+#+cindex: @samp{CLOSED}, special property
+#+cindex: @samp{DEADLINE}, special property
+#+cindex: @samp{FILE}, special property
+#+cindex: @samp{ITEM}, special property
+#+cindex: @samp{PRIORITY}, special property
+#+cindex: @samp{SCHEDULED}, special property
+#+cindex: @samp{TAGS}, special property
+#+cindex: @samp{TIMESTAMP}, special property
+#+cindex: @samp{TIMESTAMP_IA}, special property
+#+cindex: @samp{TODO}, special property
+| =ALLTAGS=      | All tags, including inherited ones.                         
   |
+| =BLOCKED=      | ~t~ if task is currently blocked by children or siblings.   
   |
+| =CATEGORY=     | The category of an entry.                                   
   |
+| =CLOCKSUM=     | The sum of CLOCK intervals in the subtree.  ~org-clock-sum~ 
   |
+|                | must be run first to compute the values in the current 
buffer. |
+| =CLOCKSUM_T=   | The sum of CLOCK intervals in the subtree for today.        
   |
+|                | ~org-clock-sum-today~ must be run first to compute the      
   |
+|                | values in the current buffer.                               
   |
+| =CLOSED=       | When was this entry closed?                                 
   |
+| =DEADLINE=     | The deadline timestamp.                                     
   |
+| =FILE=         | The filename the entry is located in.                       
   |
+| =ITEM=         | The headline of the entry.                                  
   |
+| =PRIORITY=     | The priority of the entry, a string with a single letter.   
   |
+| =SCHEDULED=    | The scheduling timestamp.                                   
   |
+| =TAGS=         | The tags defined directly in the headline.                  
   |
+| =TIMESTAMP=    | The first keyword-less timestamp in the entry.              
   |
+| =TIMESTAMP_IA= | The first inactive timestamp in the entry.                  
   |
+| =TODO=         | The TODO keyword of the entry.                              
   |
+
+** Property Searches
+:PROPERTIES:
+:DESCRIPTION: Matching property values.
+:END:
+#+cindex: properties, searching
+#+cindex: searching, of properties
+
+To create sparse trees and special lists with selection based on
+properties, the same commands are used as for tag searches (see [[*Tag
+Searches]]).
+
+- {{{kbd(C-c / m)}}} or {{{kbd(C-c \)}}} (~org-match-sparse-tree~) ::
+
+  #+kindex: C-c / m
+  #+kindex: C-c \
+  #+findex: org-match-sparse-tree
+  Create a sparse tree with all matching entries.  With
+  a {{{kbd(C-u)}}} prefix argument, ignore headlines that are not
+  a TODO line.
+
+- {{{kbd(M-x org-agenda m)}}} (~org-tags-view~) ::
+
+  #+kindex: m @r{(Agenda dispatcher)}
+  #+findex: org-tags-view
+  Create a global list of tag/property matches from all agenda files.
+
+- {{{kbd(M-x org-agenda M)}}} (~org-tags-view~) ::
+
+  #+kindex: M @r{(Agenda dispatcher)}
+  #+vindex: org-tags-match-list-sublevels
+  Create a global list of tag matches from all agenda files, but check
+  only TODO items and force checking of subitems (see the option
+  ~org-tags-match-list-sublevels~).
+
+The syntax for the search string is described in [[*Matching tags and
+properties]].
+
+There is also a special command for creating sparse trees based on a
+single property:
+
+- {{{kbd(C-c / p)}}} ::
+
+  #+kindex: C-c / p
+  Create a sparse tree based on the value of a property.  This first
+  prompts for the name of a property, and then for a value.  A sparse
+  tree is created with all entries that define this property with the
+  given value.  If you enclose the value in curly braces, it is
+  interpreted as a regular expression and matched against the property
+  values.
+
+** Property Inheritance
+:PROPERTIES:
+:DESCRIPTION: Passing values down a tree.
+:END:
+#+cindex: properties, inheritance
+#+cindex: inheritance, of properties
+
+#+vindex: org-use-property-inheritance
+The outline structure of Org documents lends itself to an inheritance
+model of properties: if the parent in a tree has a certain property,
+the children can inherit this property.  Org mode does not turn this
+on by default, because it can slow down property searches
+significantly and is often not needed.  However, if you find
+inheritance useful, you can turn it on by setting the variable
+~org-use-property-inheritance~.  It may be set to ~t~ to make all
+properties inherited from the parent, to a list of properties that
+should be inherited, or to a regular expression that matches inherited
+properties.  If a property has the value ~nil~, this is interpreted as
+an explicit un-define of the property, so that inheritance search
+stops at this value and returns ~nil~.
+
+Org mode has a few properties for which inheritance is hard-coded, at
+least for the special applications for which they are used:
+
+- ~COLUMNS~ ::
+
+  #+cindex: @samp{COLUMNS}, property
+  The =COLUMNS= property defines the format of column view (see
+  [[*Column View]]).  It is inherited in the sense that the level where
+  a =COLUMNS= property is defined is used as the starting point for
+  a column view table, independently of the location in the subtree
+  from where columns view is turned on.
+
+- ~CATEGORY~ ::
+
+  #+cindex: @samp{CATEGORY}, property
+  For agenda view, a category set through a =CATEGORY= property
+  applies to the entire subtree.
+
+- ~ARCHIVE~ ::
+
+  #+cindex: @samp{ARCHIVE}, property
+  For archiving, the =ARCHIVE= property may define the archive
+  location for the entire subtree (see [[*Moving a tree to an archive
+  file]]).
+
+- ~LOGGING~ ::
+
+  #+cindex: @samp{LOGGING}, property
+  The =LOGGING= property may define logging settings for an entry or
+  a subtree (see [[*Tracking TODO state changes]]).
+
+** Column View
+:PROPERTIES:
+:DESCRIPTION: Tabular viewing and editing.
+:END:
+
+A great way to view and edit properties in an outline tree is /column
+view/.  In column view, each outline node is turned into a table row.
+Columns in this table provide access to properties of the entries.
+Org mode implements columns by overlaying a tabular structure over the
+headline of each item.  While the headlines have been turned into
+a table row, you can still change the visibility of the outline tree.
+For example, you get a compact table by switching to "contents"
+view---{{{kbd(S-TAB)}}} {{{kbd(S-TAB)}}}, or simply {{{kbd(c)}}}
+while column view is active---but you can still open, read, and edit
+the entry below each headline.  Or, you can switch to column view
+after executing a sparse tree command and in this way get a table only
+for the selected items.  Column view also works in agenda buffers (see
+[[*Agenda Views]]) where queries have collected selected items, possibly
+from a number of files.
+
+*** Defining columns
+:PROPERTIES:
+:DESCRIPTION: The COLUMNS format property.
+:END:
+#+cindex: column view, for properties
+#+cindex: properties, column view
+
+Setting up a column view first requires defining the columns.  This is
+done by defining a column format line.
+
+**** Scope of column definitions
+:PROPERTIES:
+:DESCRIPTION: Where defined, where valid?
+:END:
+
+To specify a format that only applies to a specific tree, add
+a =COLUMNS= property to the top node of that tree, for example:
+
+#+begin_example
+,** Top node for columns view
+   :PROPERTIES:
+   :COLUMNS: %25ITEM %TAGS %PRIORITY %TODO
+   :END:
+#+end_example
+
+A =COLUMNS= property within a property drawer before first headline
+will apply to the entire file.  As an addition to property drawers,
+keywords can also be defined for an entire file using a line like:
+
+#+cindex: @samp{COLUMNS}, keyword
+: #+COLUMNS: %25ITEM %TAGS %PRIORITY %TODO
+
+If a =COLUMNS= property is present in an entry, it defines columns for
+the entry itself, and for the entire subtree below it.  Since the
+column definition is part of the hierarchical structure of the
+document, you can define columns on level 1 that are general enough
+for all sublevels, and more specific columns further down, when you
+edit a deeper part of the tree.
+
+**** Column attributes
+:PROPERTIES:
+:DESCRIPTION: Appearance and content of a column.
+:END:
+
+A column definition sets the attributes of a column.  The general
+definition looks like this:
+
+: %[WIDTH]PROPERTY[(TITLE)][{SUMMARY-TYPE}]
+
+#+texinfo: @noindent
+Except for the percent sign and the property name, all items are
+optional.  The individual parts have the following meaning:
+
+- {{{var(WIDTH)}}} ::
+
+  An integer specifying the width of the column in characters.  If
+  omitted, the width is determined automatically.
+
+- {{{var(PROPERTY)}}} ::
+
+  The property that should be edited in this column.  Special
+  properties representing meta data are allowed here as well (see
+  [[*Special Properties]]).
+
+- {{{var(TITLE)}}} ::
+
+  The header text for the column.  If omitted, the property name is
+  used.
+
+- {{{var(SUMMARY-TYPE)}}} ::
+
+  The summary type.  If specified, the column values for parent nodes
+  are computed from the children[fn:55].
+
+  Supported summary types are:
+
+  | =+=      | Sum numbers in this column.                           |
+  | =+;%.1f= | Like =+=, but format result with =%.1f=.              |
+  | =$=      | Currency, short for =+;%.2f=.                         |
+  | =min=    | Smallest number in column.                            |
+  | =max=    | Largest number.                                       |
+  | =mean=   | Arithmetic mean of numbers.                           |
+  | =X=      | Checkbox status, =[X]= if all children are =[X]=.     |
+  | =X/=     | Checkbox status, =[n/m]=.                             |
+  | =X%=     | Checkbox status, =[n%]=.                              |
+  | =:=      | Sum times, HH:MM, plain numbers are minutes.          |
+  | =:min=   | Smallest time value in column.                        |
+  | =:max=   | Largest time value.                                   |
+  | =:mean=  | Arithmetic mean of time values.                       |
+  | =@min=   | Minimum age[fn:56] (in days/hours/mins/seconds).      |
+  | =@max=   | Maximum age (in days/hours/mins/seconds).             |
+  | =@mean=  | Arithmetic mean of ages (in days/hours/mins/seconds). |
+  | =est+=   | Add low-high estimates.                               |
+
+  #+vindex: org-columns-summary-types
+  You can also define custom summary types by setting
+  ~org-columns-summary-types~.
+
+The =est+= summary type requires further explanation.  It is used for
+combining estimates, expressed as low-high ranges.  For example,
+instead of estimating a particular task will take 5 days, you might
+estimate it as 5--6 days if you're fairly confident you know how much
+work is required, or 1--10 days if you do not really know what needs
+to be done.  Both ranges average at 5.5 days, but the first represents
+a more predictable delivery.
+
+When combining a set of such estimates, simply adding the lows and
+highs produces an unrealistically wide result.  Instead, =est+= adds
+the statistical mean and variance of the subtasks, generating a final
+estimate from the sum.  For example, suppose you had ten tasks, each
+of which was estimated at 0.5 to 2 days of work.  Straight addition
+produces an estimate of 5 to 20 days, representing what to expect if
+everything goes either extremely well or extremely poorly.  In
+contrast, =est+= estimates the full job more realistically, at 10--15
+days.
+
+Here is an example for a complete columns definition, along with
+allowed values[fn:57].
+
+#+begin_example
+:COLUMNS:  %25ITEM %9Approved(Approved?){X} %Owner %11Status \
+                   %10Time_Estimate{:} %CLOCKSUM %CLOCKSUM_T
+:Owner_ALL:    Tammy Mark Karl Lisa Don
+:Status_ALL:   "In progress" "Not started yet" "Finished" ""
+:Approved_ALL: "[ ]" "[X]"
+#+end_example
+
+#+texinfo: @noindent
+The first column, =%25ITEM=, means the first 25 characters of the item
+itself, i.e., of the headline.  You probably always should start the
+column definition with the =ITEM= specifier.  The other specifiers
+create columns =Owner= with a list of names as allowed values, for
+=Status= with four different possible values, and for a checkbox field
+=Approved=.  When no width is given after the =%= character, the
+column is exactly as wide as it needs to be in order to fully display
+all values.  The =Approved= column does have a modified title
+(=Approved?=, with a question mark).  Summaries are created for the
+=Time_Estimate= column by adding time duration expressions like HH:MM,
+and for the =Approved= column, by providing an =[X]= status if all
+children have been checked.  The =CLOCKSUM= and =CLOCKSUM_T= columns
+are special, they lists the sums of CLOCK intervals in the subtree,
+either for all clocks or just for today.
+
+*** Using column view
+:PROPERTIES:
+:DESCRIPTION: How to create and use column view.
+:END:
+
+**** Turning column view on or off
+:PROPERTIES:
+:UNNUMBERED: notoc
+:END:
+
+- {{{kbd(C-c C-x C-c)}}} (~org-columns~) ::
+
+  #+kindex: C-c C-x C-c
+  #+vindex: org-columns
+  #+vindex: org-columns-default-format
+  Turn on column view.  If point is before the first headline in the
+  file, column view is turned on for the entire file, using the
+  =#+COLUMNS= definition.  If point is somewhere inside the outline,
+  this command searches the hierarchy, up from point, for a =COLUMNS=
+  property that defines a format.  When one is found, the column view
+  table is established for the tree starting at the entry that
+  contains the =COLUMNS= property.  If no such property is found, the
+  format is taken from the =#+COLUMNS= line or from the variable
+  ~org-columns-default-format~, and column view is established for the
+  current entry and its subtree.
+
+- {{{kbd(r)}}} or {{{kbd(g)}}} on a columns view line (~org-columns-redo~) ::
+
+  #+kindex: r
+  #+kindex: g
+  #+findex: org-columns-redo
+  Recreate the column view, to include recent changes made in the
+  buffer.
+
+- {{{kbd(C-c C-c)}}} or {{{kbd(q)}}} on a columns view line 
(~org-columns-quit~) ::
+
+  #+kindex: q
+  #+kindex: C-c C-c
+  #+findex: org-columns-quit
+  Exit column view.
+
+**** Editing values
+:PROPERTIES:
+:UNNUMBERED: notoc
+:END:
+
+#+attr_texinfo: :sep and
+- {{{kbd(LEFT)}}}, {{{kbd(RIGHT)}}}, {{{kbd(UP)}}}, {{{kbd(DOWN)}}} ::
+
+  Move through the column view from field to field.
+
+- {{{kbd(1..9\,0)}}} ::
+
+  #+kindex: 1..9,0
+  Directly select the Nth allowed value, {{{kbd(0)}}} selects the
+  10th value.
+
+- {{{kbd(n)}}} or {{{kbd(S-RIGHT)}}} (~org-columns-next-allowed-value~) and 
{{{kbd(p)}}} or {{{kbd(S-LEFT)}}} (~org-columns-previous-allowed-value~) ::
+
+  #+kindex: n
+  #+kindex: S-RIGHT
+  #+kindex: p
+  #+kindex: S-LEFT
+  #+findex: org-columns-next-allowed-value
+  #+findex: org-columns-previous-allowed-value
+  Switch to the next/previous allowed value of the field.  For this,
+  you have to have specified allowed values for a property.
+
+- {{{kbd(e)}}} (~org-columns-edit-value~) ::
+
+  #+kindex: e
+  #+findex: org-columns-edit-value
+  Edit the property at point.  For the special properties, this
+  invokes the same interface that you normally use to change that
+  property.  For example, the tag completion or fast selection
+  interface pops up when editing a =TAGS= property.
+
+- {{{kbd(C-c C-c)}}} (~org-columns-toggle-or-columns-quit~) ::
+
+  #+kindex: C-c C-c
+  #+findex: org-columns-toggle-or-columns-quit
+  When there is a checkbox at point, toggle it.  Else exit column
+  view.
+
+- {{{kbd(v)}}} (~org-columns-show-value~) ::
+
+  #+kindex: v
+  #+findex: org-columns-show-value
+  View the full value of this property.  This is useful if the width
+  of the column is smaller than that of the value.
+
+- {{{kbd(a)}}} (~org-columns-edit-allowed~) ::
+
+  #+kindex: a
+  #+findex: org-columns-edit-allowed
+  Edit the list of allowed values for this property.  If the list is
+  found in the hierarchy, the modified values is stored there.  If no
+  list is found, the new value is stored in the first entry that is
+  part of the current column view.
+
+**** Modifying column view on-the-fly
+:PROPERTIES:
+:UNNUMBERED: notoc
+:END:
+
+#+attr_texinfo: :sep and
+- {{{kbd(<)}}} (~org-columns-narrow~) and {{{kbd(>)}}} (~org-columns-widen~) ::
+
+  #+kindex: <
+  #+kindex: >
+  #+findex: org-columns-narrow
+  #+findex: org-columns-widen
+  Make the column narrower/wider by one character.
+
+- {{{kbd(S-M-RIGHT)}}} (~org-columns-new~) ::
+
+  #+kindex: S-M-RIGHT
+  #+findex: org-columns-new
+  Insert a new column, to the left of the current column.
+
+- {{{kbd(S-M-LEFT)}}} (~org-columns-delete~) ::
+
+  #+kindex: S-M-LEFT
+  #+findex: org-columns-delete
+  Delete the current column.
+
+*** Capturing column view
+:PROPERTIES:
+:DESCRIPTION: A dynamic block for column view.
+:END:
+
+Since column view is just an overlay over a buffer, it cannot be
+exported or printed directly.  If you want to capture a column view,
+use a =columnview= dynamic block (see [[*Dynamic Blocks]]).  The frame of
+this block looks like this:
+
+#+cindex: @samp{BEGIN columnview}
+#+begin_example
+,* The column view
+,#+BEGIN: columnview :hlines 1 :id "label"
+
+,#+END:
+#+end_example
+
+This dynamic block has the following parameters:
+
+- =:id= ::
+
+  This is the most important parameter.  Column view is a feature that
+  is often localized to a certain (sub)tree, and the capture block
+  might be at a different location in the file.  To identify the tree
+  whose view to capture, you can use four values:
+
+  - =local= ::
+
+    Use the tree in which the capture block is located.
+
+  - =global= ::
+
+    Make a global view, including all headings in the file.
+
+  - =file:FILENAME= ::
+
+    Run column view at the top of the {{{var(FILENAME)}}} file.
+
+  - =LABEL= ::
+
+    #+cindex: @samp{ID}, property
+    Call column view in the tree that has an =ID= property with the
+    value {{{var(LABEL)}}}.  You can use {{{kbd(M-x org-id-copy)}}} to
+    create a globally unique ID for the current entry and copy it to
+    the kill-ring.
+
+- =:match= ::
+
+  When set to a string, use this as a tags/property match filter to
+  select only a subset of the headlines in the scope set by the ~:id~
+  parameter.
+
+
+- =:hlines= ::
+
+  When ~t~, insert an hline after every line.  When a number N, insert
+  an hline before each headline with level ~<= N~.
+
+- =:vlines= ::
+
+  When non-~nil~, force column groups to get vertical lines.
+
+- =:maxlevel= ::
+
+  When set to a number, do not capture entries below this level.
+
+- =:skip-empty-rows= ::
+
+  When non-~nil~, skip rows where the only non-empty specifier of
+  the column view is =ITEM=.
+
+- =:exclude-tags= ::
+
+  List of tags to exclude from column view table: entries with these
+  tags will be excluded from the column view.
+
+- =:indent= ::
+
+  When non-~nil~, indent each =ITEM= field according to its level.
+
+- =:format= ::
+
+  Specify a column attribute (see [[*Column attributes]]) for the dynamic
+  block.
+
+The following commands insert or update the dynamic block:
+
+- ~org-columns-insert-dblock~ ::
+
+  #+kindex: C-c C-x x
+  #+findex: org-columns-insert-dblock
+  Insert a dynamic block capturing a column view.  Prompt for the
+  scope or ID of the view.
+
+  This command can be invoked by calling
+  ~org-dynamic-block-insert-dblock~ ({{{kbd(C-c C-x x)}}}) and
+  selecting "columnview" (see [[*Dynamic Blocks]]).
+
+- {{{kbd(C-c C-c)}}} {{{kbd(C-c C-x C-u)}}} (~org-dblock-update~) ::
+
+  #+kindex: C-c C-c
+  #+kindex: C-c C-x C-u
+  #+findex: org-dblock-update
+  Update dynamic block at point.  point needs to be in the =#+BEGIN=
+  line of the dynamic block.
+
+- {{{kbd(C-u C-c C-x C-u)}}} (~org-update-all-dblocks~) ::
+
+  #+kindex: C-u C-c C-x C-u
+  Update all dynamic blocks (see [[*Dynamic Blocks]]).  This is useful if
+  you have several clock table blocks, column-capturing blocks or
+  other dynamic blocks in a buffer.
+
+You can add formulas to the column view table and you may add plotting
+instructions in front of the table---these survive an update of the
+block.  If there is a =TBLFM= keyword after the table, the table is
+recalculated automatically after an update.
+
+An alternative way to capture and process property values into a table
+is provided by Eric Schulte's =org-collector.el=, which is
+a contributed package[fn:58].  It provides a general API to collect
+properties from entries in a certain scope, and arbitrary Lisp
+expressions to process these values before inserting them into a table
+or a dynamic block.
+
+* Dates and Times
+:PROPERTIES:
+:DESCRIPTION: Making items useful for planning.
+:END:
+#+cindex: dates
+#+cindex: times
+#+cindex: timestamp
+#+cindex: date stamp
+
+To assist project planning, TODO items can be labeled with a date
+and/or a time.  The specially formatted string carrying the date and
+time information is called a /timestamp/ in Org mode.  This may be
+a little confusing because timestamp is often used as indicating when
+something was created or last changed.  However, in Org mode this term
+is used in a much wider sense.
+
+** Timestamps
+:PROPERTIES:
+:DESCRIPTION: Assigning a time to a tree entry.
+:END:
+#+cindex: timestamps
+#+cindex: ranges, time
+#+cindex: date stamps
+#+cindex: deadlines
+#+cindex: scheduling
+
+A timestamp is a specification of a date (possibly with a time or
+a range of times) in a special format, either =<2003-09-16 Tue>= or
+=<2003-09-16 Tue 09:39>= or =<2003-09-16 Tue 12:00-12:30>=[fn:59].
+A timestamp can appear anywhere in the headline or body of an Org tree
+entry.  Its presence causes entries to be shown on specific dates in
+the agenda (see [[*Weekly/daily agenda]]).  We distinguish:
+
+- Plain timestamp; Event; Appointment ::
+
+  #+cindex: timestamp
+  #+cindex: appointment
+  A simple timestamp just assigns a date/time to an item.  This is
+  just like writing down an appointment or event in a paper agenda.
+  In the agenda display, the headline of an entry associated with
+  a plain timestamp is shown exactly on that date.
+
+  #+begin_example
+  ,* Meet Peter at the movies
+    <2006-11-01 Wed 19:15>
+  ,* Discussion on climate change
+    <2006-11-02 Thu 20:00-22:00>
+  #+end_example
+
+- Timestamp with repeater interval ::
+
+  #+cindex: timestamp, with repeater interval
+  A timestamp may contain a /repeater interval/, indicating that it
+  applies not only on the given date, but again and again after
+  a certain interval of N days (d), weeks (w), months (m), or years
+  (y).  The following shows up in the agenda every Wednesday:
+
+  #+begin_example
+  ,* Pick up Sam at school
+    <2007-05-16 Wed 12:30 +1w>
+  #+end_example
+
+- Diary-style expression entries ::
+
+  #+cindex: diary style timestamps
+  #+cindex: sexp timestamps
+  For more complex date specifications, Org mode supports using the
+  special expression diary entries implemented in the Emacs Calendar
+  package[fn:60].  For example, with optional time:
+
+  #+begin_example
+  ,* 22:00-23:00 The nerd meeting on every 2nd Thursday of the month
+    <%%(diary-float t 4 2)>
+  #+end_example
+
+- Time/Date range ::
+
+  #+cindex: timerange
+  #+cindex: date range
+  Two timestamps connected by =--= denote a range.  The headline is
+  shown on the first and last day of the range, and on any dates that
+  are displayed and fall in the range.  Here is an example:
+
+  #+begin_example
+  ,** Meeting in Amsterdam
+     <2004-08-23 Mon>--<2004-08-26 Thu>
+  #+end_example
+
+- Inactive timestamp ::
+
+  #+cindex: timestamp, inactive
+  #+cindex: inactive timestamp
+  Just like a plain timestamp, but with square brackets instead of
+  angular ones.  These timestamps are inactive in the sense that they
+  do /not/ trigger an entry to show up in the agenda.
+
+  #+begin_example
+  ,* Gillian comes late for the fifth time
+    [2006-11-01 Wed]
+  #+end_example
+
+** Creating Timestamps
+:PROPERTIES:
+:DESCRIPTION: Commands to insert timestamps.
+:END:
+
+For Org mode to recognize timestamps, they need to be in the specific
+format.  All commands listed below produce timestamps in the correct
+format.
+
+#+attr_texinfo: :sep ,
+- {{{kbd(C-c .)}}} (~org-time-stamp~) ::
+
+  #+kindex: C-c .
+  #+findex: org-time-stamp
+  Prompt for a date and insert a corresponding timestamp.  When point
+  is at an existing timestamp in the buffer, the command is used to
+  modify this timestamp instead of inserting a new one.  When this
+  command is used twice in succession, a time range is inserted.
+
+  #+kindex: C-u C-c .
+  #+vindex: org-time-stamp-rounding-minutes
+  When called with a prefix argument, use the alternative format which
+  contains date and time.  The default time can be rounded to
+  multiples of 5 minutes.  See the option
+  ~org-time-stamp-rounding-minutes~.
+
+  #+kindex: C-u C-u C-c .
+  With two prefix arguments, insert an active timestamp with the
+  current time without prompting.
+
+- {{{kbd(C-c !)}}} (~org-time-stamp-inactive~) ::
+
+  #+kindex: C-c !
+  #+kindex: C-u C-c !
+  #+kindex: C-u C-u C-c !
+  #+findex: org-time-stamp-inactive
+  Like {{{kbd(C-c .)}}}, but insert an inactive timestamp that does
+  not cause an agenda entry.
+
+- {{{kbd(C-c C-c)}}} ::
+
+  #+kindex: C-c C-c
+  Normalize timestamp, insert or fix day name if missing or wrong.
+
+- {{{kbd(C-c <)}}} (~org-date-from-calendar~) ::
+
+  #+kindex: C-c <
+  #+findex: org-date-from-calendar
+  Insert a timestamp corresponding to point date in the calendar.
+
+- {{{kbd(C-c >)}}} (~org-goto-calendar~) ::
+
+  #+kindex: C-c >
+  #+findex: org-goto-calendar
+  Access the Emacs calendar for the current date.  If there is
+  a timestamp in the current line, go to the corresponding date
+  instead.
+
+- {{{kbd(C-c C-o)}}} (~org-open-at-point~) ::
+
+  #+kindex: C-c C-o
+  #+findex: org-open-at-point
+  Access the agenda for the date given by the timestamp or -range at
+  point (see [[*Weekly/daily agenda]]).
+
+- {{{kbd(S-LEFT)}}} (~org-timestamp-down-day~), {{{kbd(S-RIGHT)}}} 
(~org-timestamp-up-day~) ::
+
+  #+kindex: S-LEFT
+  #+kindex: S-RIGHT
+  #+findex: org-timestamp-down-day
+  #+findex: org-timestamp-up-day
+  Change date at point by one day.  These key bindings conflict with
+  shift-selection and related modes (see [[*Packages that conflict with
+  Org mode]]).
+
+- {{{kbd(S-UP)}}} (~org-timestamp-up~), {{{kbd(S-DOWN)}}} 
(~org-timestamp-down~) ::
+
+  #+kindex: S-UP
+  #+kindex: S-DOWN
+  On the beginning or enclosing bracket of a timestamp, change its
+  type.  Within a timestamp, change the item under point.  Point can
+  be on a year, month, day, hour or minute.  When the timestamp
+  contains a time range like =15:30-16:30=, modifying the first time
+  also shifts the second, shifting the time block with constant
+  length.  To change the length, modify the second time.  Note that if
+  point is in a headline and not at a timestamp, these same keys
+  modify the priority of an item (see [[*Priorities]]).  The key bindings
+  also conflict with shift-selection and related modes (see [[*Packages
+  that conflict with Org mode]]).
+
+- {{{kbd(C-c C-y)}}} (~org-evaluate-time-range~) ::
+
+  #+kindex: C-c C-y
+  #+findex: org-evaluate-time-range
+  #+cindex: evaluate time range
+  Evaluate a time range by computing the difference between start and
+  end.  With a prefix argument, insert result after the time range (in
+  a table: into the following column).
+
+*** The date/time prompt
+:PROPERTIES:
+:DESCRIPTION: How Org mode helps you enter dates and times.
+:END:
+#+cindex: date, reading in minibuffer
+#+cindex: time, reading in minibuffer
+
+#+vindex: org-read-date-prefer-future
+When Org mode prompts for a date/time, the default is shown in default
+date/time format, and the prompt therefore seems to ask for a specific
+format.  But it in fact accepts date/time information in a variety of
+formats.  Generally, the information should start at the beginning of
+the string.  Org mode finds whatever information is in there and
+derives anything you have not specified from the /default date and
+time/.  The default is usually the current date and time, but when
+modifying an existing timestamp, or when entering the second stamp of
+a range, it is taken from the stamp in the buffer.  When filling in
+information, Org mode assumes that most of the time you want to enter
+a date in the future: if you omit the month/year and the given
+day/month is /before/ today, it assumes that you mean a future
+date[fn:61].  If the date has been automatically shifted into the
+future, the time prompt shows this with =(=>F)=.
+
+For example, let's assume that today is *June 13, 2006*.  Here is how
+various inputs are interpreted, the items filled in by Org mode are in
+*bold*.
+
+| =3-2-5=        | \rArr{} 2003-02-05                              |
+| =2/5/3=        | \rArr{} 2003-02-05                              |
+| =14=           | \rArr{} *2006*-*06*-14                          |
+| =12=           | \rArr{} *2006*-*07*-12                          |
+| =2/5=          | \rArr{} *2007*-02-05                            |
+| =Fri=          | \rArr{} nearest Friday (default date or later)  |
+| =sep 15=       | \rArr{} *2006*-09-15                            |
+| =feb 15=       | \rArr{} *2007*-02-15                            |
+| =sep 12 9=     | \rArr{} 2009-09-12                              |
+| =12:45=        | \rArr{} *2006*-*06*-*13* 12:45                  |
+| =22 sept 0:34= | \rArr{} *2006*-09-22 0:34                       |
+| =w4=           | \rArr{} ISO week for of the current year *2006* |
+| =2012 w4 fri=  | \rArr{} Friday of ISO week 4 in 2012            |
+| =2012-w04-5=   | \rArr{} Same as above                           |
+
+Furthermore you can specify a relative date by giving, as the /first/
+thing in the input: a plus/minus sign, a number and a letter---=h=,
+=d=, =w=, =m= or =y=---to indicate a change in hours, days, weeks,
+months, or years.  With =h= the date is relative to the current time,
+with the other letters and a single plus or minus, the date is
+relative to today at 00:00.  With a double plus or minus, it is
+relative to the default date.  If instead of a single letter, you use
+the abbreviation of day name, the date is the Nth such day, e.g.:
+
+| =+0=    | \rArr{} today                       |
+| =.=     | \rArr{} today                       |
+| =+2h=   | \rArr{} two hours from now          |
+| =+4d=   | \rArr{} four days from today        |
+| =+4=    | \rArr{} same as +4d                 |
+| =+2w=   | \rArr{} two weeks from today        |
+| =++5=   | \rArr{} five days from default date |
+| =+2tue= | \rArr{} second Tuesday from now     |
+
+#+vindex: parse-time-months
+#+vindex: parse-time-weekdays
+The function understands English month and weekday abbreviations.  If
+you want to use un-abbreviated names and/or other languages, configure
+the variables ~parse-time-months~ and ~parse-time-weekdays~.
+
+#+vindex: org-read-date-force-compatible-dates
+Not all dates can be represented in a given Emacs implementation.  By
+default Org mode forces dates into the compatibility range 1970--2037
+which works on all Emacs implementations.  If you want to use dates
+outside of this range, read the docstring of the variable
+~org-read-date-force-compatible-dates~.
+
+You can specify a time range by giving start and end times or by
+giving a start time and a duration (in HH:MM format).  Use one or two
+dash(es) as the separator in the former case and use =+= as the
+separator in the latter case, e.g.:
+
+| =11am-1:15pm=  | \rArr{} 11:00-13:15   |
+| =11am--1:15pm= | \rArr{} same as above |
+| =11am+2:15=    | \rArr{} same as above |
+
+#+cindex: calendar, for selecting date
+#+vindex: org-popup-calendar-for-date-prompt
+Parallel to the minibuffer prompt, a calendar is popped up[fn:62].
+When you exit the date prompt, either by clicking on a date in the
+calendar, or by pressing {{{kbd(RET)}}}, the date selected in the
+calendar is combined with the information entered at the prompt.  You
+can control the calendar fully from the minibuffer:
+
+#+kindex: <
+#+kindex: >
+#+kindex: M-v
+#+kindex: C-v
+#+kindex: mouse-1
+#+kindex: S-RIGHT
+#+kindex: S-LEFT
+#+kindex: S-DOWN
+#+kindex: S-UP
+#+kindex: M-S-RIGHT
+#+kindex: M-S-LEFT
+#+kindex: RET
+#+kindex: .
+#+kindex: C-.
+#+attr_texinfo: :columns 0.25 0.55
+| {{{kbd(RET)}}}       | Choose date at point in calendar.      |
+| {{{kbd(mouse-1)}}}   | Select date by clicking on it.         |
+| {{{kbd(S-RIGHT)}}}   | One day forward.                       |
+| {{{kbd(S-LEFT)}}}    | One day backward.                      |
+| {{{kbd(S-DOWN)}}}    | One week forward.                      |
+| {{{kbd(S-UP)}}}      | One week backward.                     |
+| {{{kbd(M-S-RIGHT)}}} | One month forward.                     |
+| {{{kbd(M-S-LEFT)}}}  | One month backward.                    |
+| {{{kbd(>)}}}         | Scroll calendar forward by one month.  |
+| {{{kbd(<)}}}         | Scroll calendar backward by one month. |
+| {{{kbd(M-v)}}}       | Scroll calendar forward by 3 months.   |
+| {{{kbd(C-v)}}}       | Scroll calendar backward by 3 months.  |
+| {{{kbd(C-.)}}}       | Select today's date[fn:63]             |
+
+#+vindex: org-read-date-display-live
+The actions of the date/time prompt may seem complex, but I assure you
+they will grow on you, and you will start getting annoyed by pretty
+much any other way of entering a date/time out there.  To help you
+understand what is going on, the current interpretation of your input
+is displayed live in the minibuffer[fn:64].
+
+*** Custom time format
+:PROPERTIES:
+:DESCRIPTION: Making dates look different.
+:END:
+#+cindex: custom date/time format
+#+cindex: time format, custom
+#+cindex: date format, custom
+
+#+vindex: org-display-custom-times
+#+vindex: org-time-stamp-custom-formats
+Org mode uses the standard ISO notation for dates and times as it is
+defined in ISO 8601.  If you cannot get used to this and require
+another representation of date and time to keep you happy, you can get
+it by customizing the variables ~org-display-custom-times~ and
+~org-time-stamp-custom-formats~.
+
+- {{{kbd(C-c C-x C-t)}}} (~org-toggle-time-stamp-overlays~) ::
+
+  #+kindex: C-c C-x C-t
+  #+findex: org-toggle-time-stamp-overlays
+  Toggle the display of custom formats for dates and times.
+
+Org mode needs the default format for scanning, so the custom
+date/time format does not /replace/ the default format.  Instead, it
+is put /over/ the default format using text properties.  This has the
+following consequences:
+
+- You cannot place point onto a timestamp anymore, only before or
+  after.
+
+- The {{{kbd(S-UP)}}} and {{{kbd(S-DOWN)}}} keys can no longer be used
+  to adjust each component of a timestamp.  If point is at the
+  beginning of the stamp, {{{kbd(S-UP)}}} and {{{kbd(S-DOWN)}}} change
+  the stamp by one day, just like {{{kbd(S-LEFT)}}}
+  {{{kbd(S-RIGHT)}}}.  At the end of the stamp, change the time by one
+  minute.
+
+- If the timestamp contains a range of clock times or a repeater,
+  these are not overlaid, but remain in the buffer as they were.
+
+- When you delete a timestamp character-by-character, it only
+  disappears from the buffer after /all/ (invisible) characters
+  belonging to the ISO timestamp have been removed.
+
+- If the custom timestamp format is longer than the default and you
+  are using dates in tables, table alignment will be messed up.  If
+  the custom format is shorter, things do work as expected.
+
+** Deadlines and Scheduling
+:PROPERTIES:
+:DESCRIPTION: Planning your work.
+:END:
+
+A timestamp may be preceded by special keywords to facilitate
+planning.  Both the timestamp and the keyword have to be positioned
+immediately after the task they refer to.
+
+- =DEADLINE= ::
+
+  #+cindex: @samp{DEADLINE} marker
+  Meaning: the task---most likely a TODO item, though not
+  necessarily---is supposed to be finished on that date.
+
+  #+vindex: org-deadline-warning-days
+  On the deadline date, the task is listed in the agenda.  In
+  addition, the agenda for /today/ carries a warning about the
+  approaching or missed deadline, starting ~org-deadline-warning-days~
+  before the due date, and continuing until the entry is marked as
+  done.  An example:
+
+  #+begin_example
+  ,*** TODO write article about the Earth for the Guide
+      DEADLINE: <2004-02-29 Sun>
+      The editor in charge is [[bbdb:Ford Prefect]]
+  #+end_example
+
+  #+vindex: org-agenda-skip-deadline-prewarning-if-scheduled
+  You can specify a different lead time for warnings for a specific
+  deadlines using the following syntax.  Here is an example with
+  a warning period of 5 days =DEADLINE: <2004-02-29 Sun -5d>=.  This
+  warning is deactivated if the task gets scheduled and you set
+  ~org-agenda-skip-deadline-prewarning-if-scheduled~ to ~t~.
+
+- =SCHEDULED= ::
+
+  #+cindex: @samp{SCHEDULED} marker
+  Meaning: you are planning to start working on that task on the given
+  date.
+
+  #+vindex: org-agenda-skip-scheduled-if-done
+  The headline is listed under the given date[fn:65].  In addition,
+  a reminder that the scheduled date has passed is present in the
+  compilation for /today/, until the entry is marked as done, i.e.,
+  the task is automatically forwarded until completed.
+
+  #+begin_example
+  ,*** TODO Call Trillian for a date on New Years Eve.
+      SCHEDULED: <2004-12-25 Sat>
+  #+end_example
+
+  #+vindex: org-scheduled-delay-days
+  #+vindex: org-agenda-skip-scheduled-delay-if-deadline
+  If you want to /delay/ the display of this task in the agenda, use
+  =SCHEDULED: <2004-12-25 Sat -2d>=: the task is still scheduled on
+  the 25th but will appear two days later.  In case the task contains
+  a repeater, the delay is considered to affect all occurrences; if
+  you want the delay to only affect the first scheduled occurrence of
+  the task, use =--2d= instead.  See ~org-scheduled-delay-days~ and
+  ~org-agenda-skip-scheduled-delay-if-deadline~ for details on how to
+  control this globally or per agenda.
+
+  #+attr_texinfo: :tag Important
+  #+begin_quote
+  Scheduling an item in Org mode should /not/ be understood in the
+  same way that we understand /scheduling a meeting/.  Setting a date
+  for a meeting is just a simple appointment, you should mark this
+  entry with a simple plain timestamp, to get this item shown on the
+  date where it applies.  This is a frequent misunderstanding by Org
+  users.  In Org mode, /scheduling/ means setting a date when you want
+  to start working on an action item.
+  #+end_quote
+
+You may use timestamps with repeaters in scheduling and deadline
+entries.  Org mode issues early and late warnings based on the
+assumption that the timestamp represents the /nearest instance/ of the
+repeater.  However, the use of diary expression entries like
+
+: <%%(diary-float t 42)>
+
+#+texinfo: @noindent
+in scheduling and deadline timestamps is limited.  Org mode does not
+know enough about the internals of each function to issue early and
+late warnings.  However, it shows the item on each day where the
+expression entry matches.
+
+*** Inserting deadlines or schedules
+:PROPERTIES:
+:DESCRIPTION: Planning items.
+:ALT_TITLE: Inserting deadline/schedule
+:END:
+
+The following commands allow you to quickly insert a deadline or to
+schedule an item:[fn:66]
+
+- {{{kbd(C-c C-d)}}} (~org-deadline~) ::
+
+  #+kindex: C-c C-d
+  #+findex: org-deadline
+  #+vindex: org-log-redeadline
+  Insert =DEADLINE= keyword along with a stamp.  The insertion happens
+  in the line directly following the headline.  Remove any =CLOSED=
+  timestamp .  When called with a prefix argument, also remove any
+  existing deadline from the entry.  Depending on the variable
+  ~org-log-redeadline~, take a note when changing an existing
+  deadline[fn:67].
+
+- {{{kbd(C-c C-s)}}} (~org-schedule~) ::
+
+  #+kindex: C-c C-s
+  #+findex: org-schedule
+  #+vindex: org-log-reschedule
+  Insert =SCHEDULED= keyword along with a stamp.  The insertion
+  happens in the line directly following the headline.  Remove any
+  =CLOSED= timestamp.  When called with a prefix argument, also remove
+  the scheduling date from the entry.  Depending on the variable
+  ~org-log-reschedule~, take a note when changing an existing
+  scheduling time[fn:68].
+
+- {{{kbd(C-c / d)}}} (~org-check-deadlines~) ::
+
+  #+kindex: C-c / d
+  #+findex: org-check-deadlines
+  #+cindex: sparse tree, for deadlines
+  #+vindex: org-deadline-warning-days
+  Create a sparse tree with all deadlines that are either past-due, or
+  which will become due within ~org-deadline-warning-days~.  With
+  {{{kbd(C-u)}}} prefix, show all deadlines in the file.  With
+  a numeric prefix, check that many days.  For example, {{{kbd(C-1 C-c
+  / d)}}} shows all deadlines due tomorrow.
+
+- {{{kbd(C-c / b)}}} (~org-check-before-date~) ::
+
+  #+kindex: C-c / b
+  #+findex: org-check-before-date
+  Sparse tree for deadlines and scheduled items before a given date.
+
+- {{{kbd(C-c / a)}}} (~org-check-after-date~) ::
+
+  #+kindex: C-c / a
+  #+findex: org-check-after-date
+  Sparse tree for deadlines and scheduled items after a given date.
+
+Note that ~org-schedule~ and ~org-deadline~ supports setting the date
+by indicating a relative time e.g., =+1d= sets the date to the next
+day after today, and =--1w= sets the date to the previous week before
+any current timestamp.
+
+*** Repeated tasks
+:PROPERTIES:
+:DESCRIPTION: Items that show up again and again.
+:END:
+#+cindex: tasks, repeated
+#+cindex: repeated tasks
+
+Some tasks need to be repeated again and again.  Org mode helps to
+organize such tasks using a so-called repeater in a =DEADLINE=,
+=SCHEDULED=, or plain timestamps[fn:69].  In the following example:
+
+#+begin_example
+,** TODO Pay the rent
+   DEADLINE: <2005-10-01 Sat +1m>
+#+end_example
+
+#+texinfo: @noindent
+the =+1m= is a repeater; the intended interpretation is that the task
+has a deadline on =<2005-10-01>= and repeats itself every (one) month
+starting from that time.  You can use yearly, monthly, weekly, daily
+and hourly repeat cookies by using the =y=, =m=, =w=, =d= and =h=
+letters.  If you need both a repeater and a special warning period in
+a deadline entry, the repeater should come first and the warning
+period last
+
+: DEADLINE: <2005-10-01 Sat +1m -3d>
+
+#+vindex: org-todo-repeat-to-state
+Deadlines and scheduled items produce entries in the agenda when they
+are over-due, so it is important to be able to mark such an entry as
+done once you have done so.  When you mark a =DEADLINE= or
+a =SCHEDULED= with the TODO keyword =DONE=, it no longer produces
+entries in the agenda.  The problem with this is, however, is that
+then also the /next/ instance of the repeated entry will not be
+active.  Org mode deals with this in the following way: when you try
+to mark such an entry as done, using {{{kbd(C-c C-t)}}}, it shifts the
+base date of the repeating timestamp by the repeater interval, and
+immediately sets the entry state back to TODO[fn:70].  In the example
+above, setting the state to =DONE= would actually switch the date like
+this:
+
+#+begin_example
+,** TODO Pay the rent
+   DEADLINE: <2005-11-01 Tue +1m>
+#+end_example
+
+To mark a task with a repeater as DONE, use {{{kbd(C-- 1 C-c C-t)}}},
+i.e., ~org-todo~ with a numeric prefix argument of =-1=.
+
+#+vindex: org-log-repeat
+A timestamp[fn:71] is added under the deadline, to keep a record that
+you actually acted on the previous instance of this deadline.
+
+As a consequence of shifting the base date, this entry is no longer
+visible in the agenda when checking past dates, but all future
+instances will be visible.
+
+With the =+1m= cookie, the date shift is always exactly one month.  So
+if you have not paid the rent for three months, marking this entry
+DONE still keeps it as an overdue deadline.  Depending on the task,
+this may not be the best way to handle it.  For example, if you forgot
+to call your father for 3 weeks, it does not make sense to call him
+3 times in a single day to make up for it.  Finally, there are tasks,
+like changing batteries, which should always repeat a certain time
+/after/ the last time you did it.  For these tasks, Org mode has
+special repeaters =++= and =.+=.  For example:
+
+#+begin_example
+,** TODO Call Father
+   DEADLINE: <2008-02-10 Sun ++1w>
+   Marking this DONE shifts the date by at least one week, but also
+   by as many weeks as it takes to get this date into the future.
+   However, it stays on a Sunday, even if you called and marked it
+   done on Saturday.
+
+,** TODO Empty kitchen trash
+   DEADLINE: <2008-02-08 Fri 20:00 ++1d>
+   Marking this DONE shifts the date by at least one day, and also
+   by as many days as it takes to get the timestamp into the future.
+   Since there is a time in the timestamp, the next deadline in the
+   future will be on today's date if you complete the task before
+   20:00.
+
+,** TODO Check the batteries in the smoke detectors
+   DEADLINE: <2005-11-01 Tue .+1m>
+   Marking this DONE shifts the date to one month after today.
+
+,** TODO Wash my hands
+   DEADLINE: <2019-04-05 08:00 Sun .+1h>
+   Marking this DONE shifts the date to exactly one hour from now.
+#+end_example
+
+#+vindex: org-agenda-skip-scheduled-if-deadline-is-shown
+You may have both scheduling and deadline information for a specific
+task.  If the repeater is set for the scheduling information only, you
+probably want the repeater to be ignored after the deadline.  If so,
+set the variable ~org-agenda-skip-scheduled-if-deadline-is-shown~ to
+~repeated-after-deadline~.  However, any scheduling information
+without a repeater is no longer relevant once the task is done, and
+thus, removed upon repeating the task.  If you want both scheduling
+and deadline information to repeat after the same interval, set the
+same repeater for both timestamps.
+
+An alternative to using a repeater is to create a number of copies of
+a task subtree, with dates shifted in each copy.  The command
+{{{kbd(C-c C-x c)}}} was created for this purpose; it is described in
+[[*Structure Editing]].
+
+** Clocking Work Time
+:PROPERTIES:
+:DESCRIPTION: Tracking how long you spend on a task.
+:END:
+#+cindex: clocking time
+#+cindex: time clocking
+
+Org mode allows you to clock the time you spend on specific tasks in
+a project.  When you start working on an item, you can start the
+clock.  When you stop working on that task, or when you mark the task
+done, the clock is stopped and the corresponding time interval is
+recorded.  It also computes the total time spent on each
+subtree[fn:72] of a project.  And it remembers a history or tasks
+recently clocked, so that you can jump quickly between a number of
+tasks absorbing your time.
+
+To save the clock history across Emacs sessions, use:
+
+#+begin_src emacs-lisp
+(setq org-clock-persist 'history)
+(org-clock-persistence-insinuate)
+#+end_src
+
+#+vindex: org-clock-persist
+When you clock into a new task after resuming Emacs, the incomplete
+clock[fn:73] is retrieved (see [[*Resolving idle time]]) and you are
+prompted about what to do with it.
+
+*** Clocking commands
+:PROPERTIES:
+:DESCRIPTION: Starting and stopping a clock.
+:END:
+
+#+attr_texinfo: :sep ,
+- {{{kbd(C-c C-x C-i)}}} (~org-clock-in~) ::
+
+  #+kindex: C-c C-x C-i
+  #+findex: org-clock-in
+  #+vindex: org-clock-into-drawer
+  #+vindex: org-clock-continuously
+  #+cindex: @samp{LOG_INTO_DRAWER}, property
+  Start the clock on the current item (clock-in).  This inserts the
+  =CLOCK= keyword together with a timestamp.  If this is not the first
+  clocking of this item, the multiple =CLOCK= lines are wrapped into
+  a =LOGBOOK= drawer (see also the variable ~org-clock-into-drawer~).
+  You can also overrule the setting of this variable for a subtree by
+  setting a =CLOCK_INTO_DRAWER= or =LOG_INTO_DRAWER= property.  When
+  called with a {{{kbd(C-u)}}} prefix argument, select the task from
+  a list of recently clocked tasks.  With two {{{kbd(C-u C-u)}}}
+  prefixes, clock into the task at point and mark it as the default
+  task; the default task is always be available with letter
+  {{{kbd(d)}}} when selecting a clocking task.  With three {{{kbd(C-u
+  C-u C-u)}}} prefixes, force continuous clocking by starting the
+  clock when the last clock stopped.
+
+  #+cindex: @samp{CLOCK_MODELINE_TOTAL}, property
+  #+cindex: @samp{LAST_REPEAT}, property
+  #+vindex: org-clock-mode-line-total
+  #+vindex: org-clock-in-prepare-hook
+  While the clock is running, Org shows the current clocking time in
+  the mode line, along with the title of the task.  The clock time
+  shown is all time ever clocked for this task and its children.  If
+  the task has an effort estimate (see [[*Effort Estimates]]), the mode
+  line displays the current clocking time against it[fn:74].  If the
+  task is a repeating one (see [[*Repeated tasks]]), show only the time
+  since the last reset of the task[fn:75].  You can exercise more
+  control over show time with the =CLOCK_MODELINE_TOTAL= property.  It
+  may have the values =current= to show only the current clocking
+  instance, =today= to show all time clocked on this tasks today---see
+  also the variable ~org-extend-today-until~, ~all~ to include all
+  time, or ~auto~ which is the default[fn:76].  Clicking with
+  {{{kbd(mouse-1)}}} onto the mode line entry pops up a menu with
+  clocking options.
+
+- {{{kbd(C-c C-x C-o)}}} (~org-clock-out~) ::
+
+  #+kindex: C-c C-x C-o
+  #+findex: org-clock-out
+  #+vindex: org-log-note-clock-out
+  Stop the clock (clock-out).  This inserts another timestamp at the
+  same location where the clock was last started.  It also directly
+  computes the resulting time in inserts it after the time range as
+  ==>HH:MM=.  See the variable ~org-log-note-clock-out~ for the
+  possibility to record an additional note together with the clock-out
+  timestamp[fn:77].
+
+- {{{kbd(C-c C-x C-x)}}} (~org-clock-in-last~) ::
+
+  #+kindex: C-c C-x C-x
+  #+findex: org-clock-in-last
+  #+vindex: org-clock-continuously
+  Re-clock the last clocked task.  With one {{{kbd(C-u)}}} prefix
+  argument, select the task from the clock history.  With two
+  {{{kbd(C-u)}}} prefixes, force continuous clocking by starting the
+  clock when the last clock stopped.
+
+- {{{kbd(C-c C-x C-e)}}} (~org-clock-modify-effort-estimate~) ::
+
+  #+kindex: C-c C-x C-e
+  #+findex: org-clock-modify-effort-estimate
+  Update the effort estimate for the current clock task.
+
+- {{{kbd(C-c C-c)}}} or {{{kbd(C-c C-y)}}} (~org-evaluate-time-range~) ::
+
+  #+kindex: C-c C-c
+  #+kindex: C-c C-y
+  #+findex: org-evaluate-time-range
+  Recompute the time interval after changing one of the timestamps.
+  This is only necessary if you edit the timestamps directly.  If you
+  change them with {{{kbd(S-<cursor>)}}} keys, the update is
+  automatic.
+
+- {{{kbd(C-S-UP)}}} (~org-clock-timestamps-up~), {{{kbd(C-S-DOWN)}}} 
(~org-clock-timestamps-down~) ::
+
+  #+kindex: C-S-UP
+  #+findex: org-clock-timestamps-up
+  #+kindex: C-S-DOWN
+  #+findex: org-clock-timestamps-down
+  On CLOCK log lines, increase/decrease both timestamps so that the
+  clock duration keeps the same value.
+
+- {{{kbd(S-M-UP)}}} (~org-timestamp-up~), {{{kbd(S-M-DOWN)}}} 
(~org-timestamp-down~) ::
+
+  #+kindex: S-M-UP
+  #+findex: org-clock-timestamp-up
+  #+kindex: S-M-DOWN
+  #+findex: org-clock-timestamp-down
+  On =CLOCK= log lines, increase/decrease the timestamp at point and
+  the one of the previous, or the next, clock timestamp by the same
+  duration.  For example, if you hit {{{kbd(S-M-UP)}}} to increase
+  a clocked-out timestamp by five minutes, then the clocked-in
+  timestamp of the next clock is increased by five minutes.
+
+- {{{kbd(C-c C-t)}}} (~org-todo~) ::
+
+  #+kindex: C-c C-t
+  #+findex: org-todo
+  Changing the TODO state of an item to DONE automatically stops the
+  clock if it is running in this same item.
+
+- {{{kbd(C-c C-x C-q)}}} (~org-clock-cancel~) ::
+
+  #+kindex: C-c C-x C-q
+  #+findex: org-clock-cancel
+  Cancel the current clock.  This is useful if a clock was started by
+  mistake, or if you ended up working on something else.
+
+- {{{kbd(C-c C-x C-j)}}} (~org-clock-goto~) ::
+
+  #+kindex: C-c C-x C-j
+  #+findex: or-clock-goto
+  Jump to the headline of the currently clocked in task.  With
+  a {{{kbd(C-u)}}} prefix argument, select the target task from a list
+  of recently clocked tasks.
+
+- {{{kbd(C-c C-x C-d)}}} (~org-clock-display~) ::
+
+  #+kindex: C-c C-x C-d
+  #+findex: org-clock-display
+  #+vindex: org-remove-highlights-with-change
+  Display time summaries for each subtree in the current buffer.  This
+  puts overlays at the end of each headline, showing the total time
+  recorded under that heading, including the time of any subheadings.
+  You can use visibility cycling to study the tree, but the overlays
+  disappear when you change the buffer (see variable
+  ~org-remove-highlights-with-change~) or press {{{kbd(C-c C-c)}}}.
+
+The {{{kbd(l)}}} key may be used in the agenda (see [[*Weekly/daily
+agenda]]) to show which tasks have been worked on or closed during
+a day.
+
+*Important:* note that both ~org-clock-out~ and ~org-clock-in-last~
+can have a global keybinding and do not modify the window disposition.
+
+*** The clock table
+:PROPERTIES:
+:DESCRIPTION: Detailed reports.
+:END:
+#+cindex: clocktable, dynamic block
+#+cindex: report, of clocked time
+
+Org mode can produce quite complex reports based on the time clocking
+information.  Such a report is called a /clock table/, because it is
+formatted as one or several Org tables.
+
+#+attr_texinfo: :sep ,
+- ~org-clock-report~ ::
+
+  #+kindex: C-c C-x x
+  #+findex: org-clock-report
+  Insert or update a clock table.  When called with a prefix argument,
+  jump to the first clock table in the current document and update it.
+  The clock table includes archived trees.
+
+  This command can be invoked by calling
+  ~org-dynamic-block-insert-dblock~ ({{{kbd(C-c C-x x)}}}) and
+  selecting "clocktable" (see [[*Dynamic Blocks]]).
+
+- {{{kbd(C-c C-c)}}} or {{{kbd(C-c C-x C-u)}}} (~org-dblock-update~) ::
+
+  #+kindex: C-c C-c
+  #+kindex: C-c C-x C-u
+  #+findex: org-dblock-update
+  Update dynamic block at point.  Point needs to be in the =BEGIN=
+  line of the dynamic block.
+
+- {{{kbd(C-u C-c C-x C-u)}}} ::
+
+  #+kindex: C-u C-c C-x C-u
+  Update all dynamic blocks (see [[*Dynamic Blocks]]).  This is useful if
+  you have several clock table blocks in a buffer.
+
+- {{{kbd(S-LEFT)}}}, {{{kbd(S-RIGHT)}}} (~org-clocktable-try-shift~) ::
+
+  #+kindex: S-LEFT
+  #+kindex: S-RIGHT
+  #+findex: org-clocktable-try-shift
+  Shift the current =:block= interval and update the table.  Point
+  needs to be in the =#+BEGIN: clocktable= line for this command.  If
+  =:block= is =today=, it is shifted to =today-1=, etc.
+
+Here is an example of the frame for a clock table as it is inserted
+into the buffer by ~org-clock-report~:
+
+#+cindex: @samp{BEGIN clocktable}
+#+begin_example
+,#+BEGIN: clocktable :maxlevel 2 :emphasize nil :scope file
+,#+END: clocktable
+#+end_example
+
+#+vindex: org-clocktable-defaults
+The =#+BEGIN= line contains options to define the scope, structure,
+and formatting of the report.  Defaults for all these options can be
+configured in the variable ~org-clocktable-defaults~.
+
+First there are options that determine which clock entries are to
+be selected:
+
+- =:maxlevel= ::
+
+  Maximum level depth to which times are listed in the table.  Clocks
+  at deeper levels are summed into the upper level.
+
+- =:scope= ::
+
+  The scope to consider.  This can be any of the following:
+
+  | =nil=                  | the current buffer or narrowed region             
                  |
+  | =file=                 | the full current buffer                           
                  |
+  | =subtree=              | the subtree where the clocktable is located       
                  |
+  | =treeN=                | the surrounding level N tree, for example =tree3= 
                  |
+  | =tree=                 | the surrounding level 1 tree                      
                  |
+  | =agenda=               | all agenda files                                  
                  |
+  | =("file" ...)=         | scan these files                                  
                  |
+  | =FUNCTION=             | scan files returned by calling 
{{{var(FUNCTION)}}} with no argument |
+  | =file-with-archives=   | current file and its archives                     
                  |
+  | =agenda-with-archives= | all agenda files, including archives              
                  |
+
+- =:block= ::
+
+  The time block to consider.  This block is specified either
+  absolutely, or relative to the current time and may be any of these
+  formats:
+
+  | =2007-12-31=                            | New year eve 2007     |
+  | =2007-12=                               | December 2007         |
+  | =2007-W50=                              | ISO-week 50 in 2007   |
+  | =2007-Q2=                               | 2nd quarter in 2007   |
+  | =2007=                                  | the year 2007         |
+  | =today=, =yesterday=, =today-N=         | a relative day        |
+  | =thisweek=, =lastweek=, =thisweek-N=    | a relative week       |
+  | =thismonth=, =lastmonth=, =thismonth-N= | a relative month      |
+  | =thisyear=, =lastyear=, =thisyear-N=    | a relative year       |
+  | =untilnow=[fn:78]                       | all clocked time ever |
+
+  #+vindex: org-clock-display-default-range
+  When this option is not set, Org falls back to the value in
+  ~org-clock-display-default-range~, which defaults to the current
+  year.
+
+  Use {{{kbd(S-LEFT)}}} or {{{kbd(S-RIGHT)}}} to shift the time
+  interval.
+
+- =:tstart= ::
+
+  A time string specifying when to start considering times.  Relative
+  times like ="<-2w>"= can also be used.  See [[*Matching tags and
+  properties]] for relative time syntax.
+
+- =:tend= ::
+
+  A time string specifying when to stop considering times.  Relative
+  times like ="<now>"= can also be used.  See [[*Matching tags and
+  properties]] for relative time syntax.
+
+- =:wstart= ::
+
+  The starting day of the week.  The default is 1 for Monday.
+
+- =:mstart= ::
+
+  The starting day of the month.  The default is 1 for the first.
+
+- =:step= ::
+
+  Set to =day=, =week=, =semimonth=, =month=, or =year= to split the
+  table into chunks.  To use this, either =:block=, or =:tstart= and
+  =:tend= are required.
+
+- =:stepskip0= ::
+
+  When non-~nil~, do not show steps that have zero time.
+
+- =:fileskip0= ::
+
+  When non-~nil~, do not show table sections from files which did not
+  contribute.
+
+- =:match= ::
+
+  A tags match to select entries that should contribute.  See
+  [[*Matching tags and properties]] for the match syntax.
+
+#+findex: org-clocktable-write-default
+Then there are options that determine the formatting of the table.
+There options are interpreted by the function
+~org-clocktable-write-default~, but you can specify your own function
+using the =:formatter= parameter.
+
+- =:emphasize= ::
+
+  When non-~nil~, emphasize level one and level two items.
+
+- =:lang= ::
+
+  Language[fn:79] to use for descriptive cells like "Task".
+
+- =:link= ::
+
+  Link the item headlines in the table to their origins.
+
+- =:narrow= ::
+
+  An integer to limit the width of the headline column in the Org
+  table.  If you write it like =50!=, then the headline is also
+  shortened in export.
+
+- =:indent= ::
+
+  Indent each headline field according to its level.
+
+- =:hidefiles= ::
+
+  Hide the file column when multiple files are used to produce the
+  table.
+
+- =:tcolumns= ::
+
+  Number of columns to be used for times.  If this is smaller than
+  =:maxlevel=, lower levels are lumped into one column.
+
+- =:level= ::
+
+  Should a level number column be included?
+
+- =:sort= ::
+
+  A cons cell containing the column to sort and a sorting type.  E.g.,
+  =:sort (1 . ?a)= sorts the first column alphabetically.
+
+- =:compact= ::
+
+  Abbreviation for =:level nil :indent t :narrow 40! :tcolumns 1=.
+  All are overwritten except if there is an explicit =:narrow=.
+
+- =:timestamp= ::
+
+  A timestamp for the entry, when available.  Look for =SCHEDULED=,
+  =DEADLINE=, =TIMESTAMP= and =TIMESTAMP_IA= special properties (see
+  [[*Special Properties]]), in this order.
+
+- =:tags= ::
+
+  When this flag is non-~nil~, show the headline's tags.
+
+- =:properties= ::
+
+  List of properties shown in the table.  Each property gets its own
+  column.
+
+- =:inherit-props= ::
+
+  When this flag is non-~nil~, the values for =:properties= are
+  inherited.
+
+- =:formula= ::
+
+  Content of a =TBLFM= keyword to be added and evaluated.  As
+  a special case, =:formula %= adds a column with % time.  If you do
+  not specify a formula here, any existing formula below the clock
+  table survives updates and is evaluated.
+
+- =:formatter= ::
+
+  A function to format clock data and insert it into the buffer.
+
+To get a clock summary of the current level 1 tree, for the current
+day, you could write:
+
+#+begin_example
+,#+BEGIN: clocktable :maxlevel 2 :block today :scope tree1 :link t
+,#+END: clocktable
+#+end_example
+
+#+texinfo: @noindent
+To use a specific time range you could write[fn:80]
+
+#+begin_example
+,#+BEGIN: clocktable :tstart "<2006-08-10 Thu 10:00>"
+                    :tend "<2006-08-10 Thu 12:00>"
+,#+END: clocktable
+#+end_example
+
+#+texinfo: @noindent
+A range starting a week ago and ending right now could be written as
+
+#+begin_example
+,#+BEGIN: clocktable :tstart "<-1w>" :tend "<now>"
+,#+END: clocktable
+#+end_example
+
+#+texinfo: @noindent
+A summary of the current subtree with % times would be
+
+#+begin_example
+,#+BEGIN: clocktable :scope subtree :link t :formula %
+,#+END: clocktable
+#+end_example
+
+#+texinfo: @noindent
+A horizontally compact representation of everything clocked during
+last week would be
+
+#+begin_example
+,#+BEGIN: clocktable :scope agenda :block lastweek :compact t
+,#+END: clocktable
+#+end_example
+
+*** Resolving idle time and continuous clocking
+:PROPERTIES:
+:DESCRIPTION: Resolving time when you've been idle.
+:ALT_TITLE: Resolving idle time
+:END:
+
+**** Resolving idle time
+:PROPERTIES:
+:UNNUMBERED: notoc
+:END:
+
+#+cindex: resolve idle time
+#+cindex: idle, resolve, dangling
+
+If you clock in on a work item, and then walk away from your
+computer---perhaps to take a phone call---you often need to
+"resolve" the time you were away by either subtracting it from the
+current clock, or applying it to another one.
+
+#+vindex: org-clock-idle-time
+#+vindex: org-clock-x11idle-program-name
+By customizing the variable ~org-clock-idle-time~ to some integer,
+such as 10 or 15, Emacs can alert you when you get back to your
+computer after being idle for that many minutes[fn:81], and ask what
+you want to do with the idle time.  There will be a question waiting
+for you when you get back, indicating how much idle time has passed
+constantly updated with the current amount, as well as a set of
+choices to correct the discrepancy:
+
+- {{{kbd(k)}}} ::
+
+  #+kindex: k
+  To keep some or all of the minutes and stay clocked in, press
+  {{{kbd(k)}}}.  Org asks how many of the minutes to keep.  Press
+  {{{kbd(RET)}}} to keep them all, effectively changing nothing, or
+  enter a number to keep that many minutes.
+
+- {{{kbd(K)}}} ::
+
+  #+kindex: K
+  If you use the shift key and press {{{kbd(K)}}}, it keeps however
+  many minutes you request and then immediately clock out of that
+  task.  If you keep all of the minutes, this is the same as just
+  clocking out of the current task.
+
+- {{{kbd(s)}}} ::
+
+  #+kindex: s
+  To keep none of the minutes, use {{{kbd(s)}}} to subtract all the
+  away time from the clock, and then check back in from the moment you
+  returned.
+
+- {{{kbd(S)}}} ::
+
+  #+kindex: S
+  To keep none of the minutes and just clock out at the start of the
+  away time, use the shift key and press {{{kbd(S)}}}.  Remember that
+  using shift always leave you clocked out, no matter which option you
+  choose.
+
+- {{{kbd(C)}}} ::
+
+  #+kindex: C
+  To cancel the clock altogether, use {{{kbd(C)}}}.  Note that if
+  instead of canceling you subtract the away time, and the resulting
+  clock amount is less than a minute, the clock is still canceled
+  rather than cluttering up the log with an empty entry.
+
+What if you subtracted those away minutes from the current clock, and
+now want to apply them to a new clock?  Simply clock in to any task
+immediately after the subtraction.  Org will notice that you have
+subtracted time "on the books", so to speak, and will ask if you want
+to apply those minutes to the next task you clock in on.
+
+There is one other instance when this clock resolution magic occurs.
+Say you were clocked in and hacking away, and suddenly your cat chased
+a mouse who scared a hamster that crashed into your UPS's power
+button!  You suddenly lose all your buffers, but thanks to auto-save
+you still have your recent Org mode changes, including your last clock
+in.
+
+If you restart Emacs and clock into any task, Org will notice that you
+have a dangling clock which was never clocked out from your last
+session.  Using that clock's starting time as the beginning of the
+unaccounted-for period, Org will ask how you want to resolve that
+time.  The logic and behavior is identical to dealing with away time
+due to idleness; it is just happening due to a recovery event rather
+than a set amount of idle time.
+
+You can also check all the files visited by your Org agenda for
+dangling clocks at any time using {{{kbd(M-x org-resolve-clocks
+RET)}}} (or {{{kbd(C-c C-x C-z)}}}).
+
+**** Continuous clocking
+:PROPERTIES:
+:UNNUMBERED: notoc
+:END:
+#+cindex: continuous clocking
+
+#+vindex: org-clock-continuously
+You may want to start clocking from the time when you clocked out the
+previous task.  To enable this systematically, set
+~org-clock-continuously~ to non-~nil~.  Each time you clock in, Org
+retrieves the clock-out time of the last clocked entry for this
+session, and start the new clock from there.
+
+If you only want this from time to time, use three universal prefix
+arguments with ~org-clock-in~ and two {{{kbd(C-u C-u)}}} with
+~org-clock-in-last~.
+
+**** Clocking out automatically after some idle time
+:PROPERTIES:
+:UNNUMBERED: notoc
+:END:
+#+cindex: auto clocking out after idle time
+
+#+vindex: org-clock-auto-clockout-timer
+When you often forget to clock out before being idle and you don't
+want to manually set the clocking time to take into account, you can
+set ~org-clock-auto-clockout-timer~ to a number of seconds and add
+=(org-clock-auto-clockout-insinuate)= to your =.emacs= file.
+
+When the clock is running and Emacs is idle for more than this number
+of seconds, the clock will be clocked out automatically.
+
+Use =M-x org-clock-toggle-auto-clockout RET= to temporarily turn this
+on or off.
+
+** Effort Estimates
+:PROPERTIES:
+:DESCRIPTION: Planning work effort in advance.
+:END:
+#+cindex: effort estimates
+#+cindex: @samp{EFFORT}, property
+#+vindex: org-effort-property
+
+If you want to plan your work in a very detailed way, or if you need
+to produce offers with quotations of the estimated work effort, you
+may want to assign effort estimates to entries.  If you are also
+clocking your work, you may later want to compare the planned effort
+with the actual working time, a great way to improve planning
+estimates.
+
+Effort estimates are stored in a special property =EFFORT=.  Multiple
+formats are supported, such as =3:12=, =1:23:45=, or =1d3h5min=; see
+the file =org-duration.el= for more detailed information about the
+format.
+
+You can set the effort for an entry with the following commands:
+
+- {{{kbd(C-c C-x e)}}}  (~org-set-effort~) ::
+
+  #+kindex: C-c C-x e
+  #+findex: org-set-effort
+  Set the effort estimate for the current entry.  With a prefix
+  argument, set it to the next allowed value---see below.  This
+  command is also accessible from the agenda with the {{{kbd(e)}}}
+  key.
+
+- {{{kbd(C-c C-x C-e)}}} (~org-clock-modify-effort-estimate~) ::
+
+  #+kindex: C-c C-x C-e
+  #+findex: org-clock-modify-effort-estimate
+  Modify the effort estimate of the item currently being clocked.
+
+Clearly the best way to work with effort estimates is through column
+view (see [[*Column View]]).  You should start by setting up discrete
+values for effort estimates, and a =COLUMNS= format that displays
+these values together with clock sums---if you want to clock your
+time.  For a specific buffer you can use:
+
+#+begin_example
+,#+PROPERTY: Effort_ALL 0 0:10 0:30 1:00 2:00 3:00 4:00 5:00 6:00 7:00
+,#+COLUMNS: %40ITEM(Task) %17Effort(Estimated Effort){:} %CLOCKSUM
+#+end_example
+
+#+texinfo: @noindent
+#+vindex: org-global-properties
+#+vindex: org-columns-default-format
+or, even better, you can set up these values globally by customizing
+the variables ~org-global-properties~ and
+~org-columns-default-format~.  In particular if you want to use this
+setup also in the agenda, a global setup may be advised.
+
+The way to assign estimates to individual items is then to switch to
+column mode, and to use {{{kbd(S-RIGHT)}}} and {{{kbd(S-LEFT)}}} to
+change the value.  The values you enter are immediately summed up in
+the hierarchy.  In the column next to it, any clocked time is
+displayed.
+
+#+vindex: org-agenda-columns-add-appointments-to-effort-sum
+If you switch to column view in the daily/weekly agenda, the effort
+column summarizes the estimated work effort for each day[fn:82], and
+you can use this to find space in your schedule.  To get an overview
+of the entire part of the day that is committed, you can set the
+option ~org-agenda-columns-add-appointments-to-effort-sum~.  The
+appointments on a day that take place over a specified time interval
+are then also added to the load estimate of the day.
+
+Effort estimates can be used in secondary agenda filtering that is
+triggered with the {{{kbd(/)}}} key in the agenda (see [[*Commands in
+the Agenda Buffer]]).  If you have these estimates defined consistently,
+two or three key presses narrow down the list to stuff that fits into
+an available time slot.
+
+** Taking Notes with a Relative Timer
+:PROPERTIES:
+:DESCRIPTION: Notes with a running timer.
+:ALT_TITLE: Timers
+:END:
+#+cindex: relative timer
+#+cindex: countdown timer
+
+Org provides two types of timers.  There is a relative timer that
+counts up, which can be useful when taking notes during, for example,
+a meeting or a video viewing.  There is also a countdown timer.
+
+The relative and countdown are started with separate commands.
+
+- {{{kbd(C-c C-x 0)}}} (~org-timer-start~) ::
+
+  #+kindex: C-c C-x 0
+  #+findex: org-timer-start
+  Start or reset the relative timer.  By default, the timer is set
+  to 0.  When called with a {{{kbd(C-u)}}} prefix, prompt the user for
+  a starting offset.  If there is a timer string at point, this is
+  taken as the default, providing a convenient way to restart taking
+  notes after a break in the process.  When called with a double
+  prefix argument {{{kbd(C-u C-u)}}}, change all timer strings in the
+  active region by a certain amount.  This can be used to fix timer
+  strings if the timer was not started at exactly the right moment.
+
+- {{{kbd(C-c C-x ;)}}} (~org-timer-set-timer~) ::
+
+  #+kindex: C-c C-x ;
+  #+findex: org-timer-set-timer
+  #+vindex: org-timer-default-timer
+  Start a countdown timer.  The user is prompted for a duration.
+  ~org-timer-default-timer~ sets the default countdown value.  Giving
+  a numeric prefix argument overrides this default value.  This
+  command is available as {{{kbd(;)}}} in agenda buffers.
+
+Once started, relative and countdown timers are controlled with the
+same commands.
+
+- {{{kbd(C-c C-x .)}}} (~org-timer~) ::
+
+  #+kindex: C-c C-x .
+  #+findex: org-timer
+  Insert a relative time into the buffer.  The first time you use
+  this, the timer starts.  Using a prefix argument restarts it.
+
+- {{{kbd(C-c C-x -)}}} (~org-timer-item~) ::
+
+  #+kindex: C-c C-x -
+  #+findex: org-timer-item
+  Insert a description list item with the current relative time.  With
+  a prefix argument, first reset the timer to 0.
+
+- {{{kbd(M-RET)}}} (~org-insert-heading~) ::
+
+  #+kindex: M-RET
+  #+findex: org-insert-heading
+  Once the timer list is started, you can also use {{{kbd(M-RET)}}} to
+  insert new timer items.
+
+- {{{kbd(C-c C-x \,)}}} (~org-timer-pause-or-continue~) ::
+
+  #+kindex: C-c C-x ,
+  #+findex: org-timer-pause-or-continue
+  Pause the timer, or continue it if it is already paused.
+
+- {{{kbd(C-c C-x _)}}} (~org-timer-stop~) ::
+
+  #+kindex: C-c C-x _
+  #+findex: org-timer-stop
+  Stop the timer.  After this, you can only start a new timer, not
+  continue the old one.  This command also removes the timer from the
+  mode line.
+
+* Refiling and Archiving
+:PROPERTIES:
+:DESCRIPTION: Moving and copying information with ease.
+:END:
+#+cindex: refiling notes
+#+cindex: copying notes
+#+cindex: archiving
+
+Once information is in the system, it may need to be moved around.
+Org provides Refile, Copy and Archive commands for this.  Refile and
+Copy helps with moving and copying outlines.  Archiving helps to keep
+the system compact and fast.
+
+** Refile and Copy
+:PROPERTIES:
+:DESCRIPTION: Moving/copying a tree from one place to another.
+:END:
+#+cindex: refiling notes
+#+cindex: copying notes
+
+When reviewing the captured data, you may want to refile or to copy
+some of the entries into a different list, for example into a project.
+Cutting, finding the right location, and then pasting the note is
+cumbersome.  To simplify this process, you can use the following
+special command:
+
+- {{{kbd(C-c C-w)}}} (~org-refile~) ::
+
+  #+kindex: C-c C-w
+  #+findex: org-refile
+  #+vindex: org-reverse-note-order
+  #+vindex: org-refile-targets
+  #+vindex: org-refile-use-outline-path
+  #+vindex: org-outline-path-complete-in-steps
+  #+vindex: org-refile-allow-creating-parent-nodes
+  #+vindex: org-log-refile
+  Refile the entry or region at point.  This command offers possible
+  locations for refiling the entry and lets you select one with
+  completion.  The item (or all items in the region) is filed below
+  the target heading as a subitem.  Depending on
+  ~org-reverse-note-order~, it is either the first or last subitem.
+
+  By default, all level 1 headlines in the current buffer are
+  considered to be targets, but you can have more complex definitions
+  across a number of files.  See the variable ~org-refile-targets~ for
+  details.  If you would like to select a location via
+  a file-path-like completion along the outline path, see the
+  variables ~org-refile-use-outline-path~ and
+  ~org-outline-path-complete-in-steps~.  If you would like to be able
+  to create new nodes as new parents for refiling on the fly, check
+  the variable ~org-refile-allow-creating-parent-nodes~.  When the
+  variable ~org-log-refile~[fn:83] is set, a timestamp or a note is
+  recorded whenever an entry is refiled.
+
+- {{{kbd(C-u C-c C-w)}}} ::
+
+  #+kindex: C-u C-c C-w
+  Use the refile interface to jump to a heading.
+
+- {{{kbd(C-u C-u C-c C-w)}}} (~org-refile-goto-last-stored~) ::
+
+  #+kindex: C-u C-u C-c C-w
+  #+findex: org-refile-goto-last-stored
+  Jump to the location where ~org-refile~ last moved a tree to.
+
+- {{{kbd(C-2 C-c C-w)}}} ::
+
+  #+kindex: C-2 C-c C-w
+  Refile as the child of the item currently being clocked.
+
+- {{{kbd(C-3 C-c C-w)}}} ::
+
+  #+kindex: C-3 C-c C-w
+  #+vindex: org-refile-keep
+  Refile and keep the entry in place.  Also see ~org-refile-keep~ to
+  make this the default behavior, and beware that this may result in
+  duplicated =ID= properties.
+
+- {{{kbd(C-0 C-c C-w)}}} or {{{kbd(C-u C-u C-u C-c C-w)}}} 
(~org-refile-cache-clear~) ::
+
+  #+kindex: C-u C-u C-u C-c C-w
+  #+kindex: C-0 C-c C-w
+  #+findex: org-refile-cache-clear
+  #+vindex: org-refile-use-cache
+  Clear the target cache.  Caching of refile targets can be turned on
+  by setting ~org-refile-use-cache~.  To make the command see new
+  possible targets, you have to clear the cache with this command.
+
+- {{{kbd(C-c M-w)}}} (~org-refile-copy~) ::
+
+  #+kindex: C-c M-w
+  #+findex: org-refile-copy
+  Copying works like refiling, except that the original note is not
+  deleted.
+
+** Archiving
+:PROPERTIES:
+:DESCRIPTION: What to do with finished products.
+:END:
+#+cindex: archiving
+
+When a project represented by a (sub)tree is finished, you may want to
+move the tree out of the way and to stop it from contributing to the
+agenda.  Archiving is important to keep your working files compact and
+global searches like the construction of agenda views fast.
+
+- {{{kbd(C-c C-x C-a)}}} (~org-archive-subtree-default~) ::
+
+  #+kindex: C-c C-x C-a
+  #+findex: org-archive-subtree-default
+  #+vindex: org-archive-default-command
+  Archive the current entry using the command specified in the
+  variable ~org-archive-default-command~.
+
+*** Moving a tree to an archive file
+:PROPERTIES:
+:DESCRIPTION: Moving a tree to an archive file.
+:ALT_TITLE: Moving subtrees
+:END:
+#+cindex: external archiving
+
+The most common archiving action is to move a project tree to another
+file, the archive file.
+
+- {{{kbd(C-c C-x C-s)}}} or short {{{kbd(C-c $)}}} (~org-archive-subtree~) ::
+
+  #+kindex: C-c C-x C-s
+  #+kindex: C-c $
+  #+findex: org-archive-subtree
+  #+vindex: org-archive-location
+  Archive the subtree starting at point position to the location given
+  by ~org-archive-location~.
+
+- {{{kbd(C-u C-c C-x C-s)}}} ::
+
+  #+kindex: C-u C-c C-x C-s
+  Check if any direct children of the current headline could be moved
+  to the archive.  To do this, check each subtree for open TODO
+  entries.  If none is found, the command offers to move it to the
+  archive location.  If point is /not/ on a headline when this command
+  is invoked, check level 1 trees.
+
+- {{{kbd(C-u C-u C-c C-x C-s)}}} ::
+
+  #+kindex: C-u C-u C-c C-x C-s
+  As above, but check subtree for timestamps instead of TODO entries.
+  The command offers to archive the subtree if it /does/ contain
+  a timestamp, and that timestamp is in the past.
+
+#+cindex: archive locations
+The default archive location is a file in the same directory as the
+current file, with the name derived by appending =_archive= to the
+current file name.  You can also choose what heading to file archived
+items under, with the possibility to add them to a datetree in a file.
+For information and examples on how to specify the file and the
+heading, see the documentation string of the variable
+~org-archive-location~.
+
+There is also an in-buffer option for setting this variable, for
+example:
+
+#+cindex: @samp{ARCHIVE}, keyword
+: #+ARCHIVE: %s_done::
+
+#+cindex: ARCHIVE, property
+If you would like to have a special archive location for a single
+entry or a (sub)tree, give the entry an =ARCHIVE= property with the
+location as the value (see [[*Properties and Columns]]).
+
+#+vindex: org-archive-save-context-info
+When a subtree is moved, it receives a number of special properties
+that record context information like the file from where the entry
+came, its outline path the archiving time etc.  Configure the variable
+~org-archive-save-context-info~ to adjust the amount of information
+added.
+
+#+vindex: org-archive-subtree-save-file-p
+When ~org-archive-subtree-save-file-p~ is non-~nil~, save the target
+archive buffer.
+
+*** Internal archiving
+:PROPERTIES:
+:DESCRIPTION: Switch off a tree but keep it in the file.
+:END:
+
+#+cindex: @samp{ARCHIVE}, tag
+If you want to just switch off---for agenda views---certain subtrees
+without moving them to a different file, you can use the =ARCHIVE=
+tag.
+
+A headline that is marked with the =ARCHIVE= tag (see [[*Tags]]) stays at
+its location in the outline tree, but behaves in the following way:
+
+-
+  #+vindex: org-cycle-open-archived-trees
+  It does not open when you attempt to do so with a visibility cycling
+  command (see [[*Visibility Cycling]]).  You can force cycling archived
+  subtrees with {{{kbd(C-TAB)}}}, or by setting the option
+  ~org-cycle-open-archived-trees~.  Also normal outline commands, like
+  ~outline-show-all~, open archived subtrees.
+
+-
+  #+vindex: org-sparse-tree-open-archived-trees
+  During sparse tree construction (see [[*Sparse Trees]]), matches in
+  archived subtrees are not exposed, unless you configure the option
+  ~org-sparse-tree-open-archived-trees~.
+
+-
+  #+vindex: org-agenda-skip-archived-trees
+  During agenda view construction (see [[*Agenda Views]]), the content of
+  archived trees is ignored unless you configure the option
+  ~org-agenda-skip-archived-trees~, in which case these trees are
+  always included.  In the agenda you can press {{{kbd(v a)}}} to get
+  archives temporarily included.
+
+-
+  #+vindex: org-export-with-archived-trees
+  Archived trees are not exported (see [[*Exporting]]), only the headline
+  is.  Configure the details using the variable
+  ~org-export-with-archived-trees~.
+
+-
+  #+vindex: org-columns-skip-archived-trees
+  Archived trees are excluded from column view unless the variable
+  ~org-columns-skip-archived-trees~ is configured to ~nil~.
+
+The following commands help manage the =ARCHIVE= tag:
+
+- {{{kbd(C-c C-x a)}}} (~org-toggle-archive-tag~) ::
+
+  #+kindex: C-c C-x a
+  #+findex: org-toggle-archive-tag
+  Toggle the archive tag for the current headline.  When the tag is
+  set, the headline changes to a shadowed face, and the subtree below
+  it is hidden.
+
+- {{{kbd(C-u C-c C-x a)}}} ::
+
+  #+kindex: C-u C-c C-x a
+  Check if any direct children of the current headline should be
+  archived.  To do this, check each subtree for open TODO entries.  If
+  none is found, the command offers to set the =ARCHIVE= tag for the
+  child.  If point is /not/ on a headline when this command is
+  invoked, check the level 1 trees.
+
+- {{{kbd(C-c C-TAB)}}} (~org-force-cycle-archived~) ::
+
+  #+kindex: C-TAB
+  Cycle a tree even if it is tagged with =ARCHIVE=.
+
+- {{{kbd(C-c C-x A)}}} (~org-archive-to-archive-sibling~) ::
+
+  #+kindex: C-c C-x A
+  #+findex: org-archive-to-archive-sibling
+  Move the current entry to the /Archive Sibling/.  This is a sibling
+  of the entry with the heading =Archive= and the archive tag.  The
+  entry becomes a child of that sibling and in this way retains a lot
+  of its original context, including inherited tags and approximate
+  position in the outline.
+
+* Capture and Attachments
+:PROPERTIES:
+:DESCRIPTION: Dealing with external data.
+:END:
+#+cindex: capture
+#+cindex: attachments
+#+cindex: RSS feeds
+#+cindex: Atom feeds
+#+cindex: protocols, for external access
+
+An important part of any organization system is the ability to quickly
+capture new ideas and tasks, and to associate reference material with
+them.  Org does this using a process called /capture/.  It also can
+store files related to a task (/attachments/) in a special directory.
+Finally, it can parse RSS feeds for information.  To learn how to let
+external programs (for example a web browser) trigger Org to capture
+material, see [[*Protocols for External Access]].
+
+** Capture
+:PROPERTIES:
+:DESCRIPTION: Capturing new stuff.
+:END:
+#+cindex: capture
+
+Capture lets you quickly store notes with little interruption of your
+work flow.  Org's method for capturing new items is heavily inspired
+by John Wiegley's excellent Remember package.
+
+*** Setting up capture
+:PROPERTIES:
+:DESCRIPTION: Where notes will be stored.
+:END:
+
+The following customization sets a default target file for notes.
+
+#+vindex: org-default-notes-file
+#+begin_src emacs-lisp
+(setq org-default-notes-file (concat org-directory "/notes.org"))
+#+end_src
+
+You may also define a global key for capturing new material (see
+[[*Activation]]).
+
+*** Using capture
+:PROPERTIES:
+:DESCRIPTION: Commands to invoke and terminate capture.
+:END:
+
+- {{{kbd(M-x org-capture)}}} (~org-capture~) ::
+
+  #+findex: org-capture
+  #+cindex: date tree
+  Display the capture templates menu.  If you have templates defined
+  (see [[*Capture templates]]), it offers these templates for selection or
+  use a new Org outline node as the default template.  It inserts the
+  template into the target file and switch to an indirect buffer
+  narrowed to this new node.  You may then insert the information you
+  want.
+
+- {{{kbd(C-c C-c)}}} (~org-capture-finalize~) ::
+
+  #+kindex: C-c C-c @r{(Capture buffer)}
+  #+findex: org-capture-finalize
+  Once you have finished entering information into the capture buffer,
+  {{{kbd(C-c C-c)}}} returns you to the window configuration before
+  the capture process, so that you can resume your work without
+  further distraction.  When called with a prefix argument, finalize
+  and then jump to the captured item.
+
+- {{{kbd(C-c C-w)}}} (~org-capture-refile~) ::
+
+  #+kindex: C-c C-w @r{(Capture buffer)}
+  #+findex: org-capture-refile
+  Finalize the capture process by refiling the note to a different
+  place (see [[*Refile and Copy]]).  Please realize that this is a normal
+  refiling command that will be executed---so point position at the
+  moment you run this command is important.  If you have inserted
+  a tree with a parent and children, first move point back to the
+  parent.  Any prefix argument given to this command is passed on to
+  the ~org-refile~ command.
+
+- {{{kbd(C-c C-k)}}} (~org-capture-kill~) ::
+
+  #+kindex: C-c C-k @r{(Capture buffer)}
+  #+findex: org-capture-kill
+  Abort the capture process and return to the previous state.
+
+#+kindex: k c @r{(Agenda)}
+You can also call ~org-capture~ in a special way from the agenda,
+using the {{{kbd(k c)}}} key combination.  With this access, any
+timestamps inserted by the selected capture template defaults to the
+date at point in the agenda, rather than to the current date.
+
+To find the locations of the last stored capture, use ~org-capture~
+with prefix commands:
+
+- {{{kbd(C-u M-x org-capture)}}} ::
+
+  Visit the target location of a capture template.  You get to select
+  the template in the usual way.
+
+- {{{kbd(C-u C-u M-x org-capture)}}} ::
+
+  Visit the last stored capture item in its buffer.
+
+#+vindex: org-capture-bookmark
+#+vindex: org-capture-last-stored
+You can also jump to the bookmark ~org-capture-last-stored~, which is
+automatically created unless you set ~org-capture-bookmark~ to ~nil~.
+
+To insert the capture at point in an Org buffer, call ~org-capture~
+with a {{{kbd(C-0)}}} prefix argument.
+
+*** Capture templates
+:PROPERTIES:
+:DESCRIPTION: Define the outline of different note types.
+:END:
+#+cindex: templates, for Capture
+
+You can use templates for different types of capture items, and for
+different target locations.  The easiest way to create such templates
+is through the customize interface.
+
+- {{{kbd(C)}}} ::
+
+  #+kindex: C @r{(Capture menu}
+  #+vindex: org-capture-templates
+  Customize the variable ~org-capture-templates~.
+
+Before we give the formal description of template definitions, let's
+look at an example.  Say you would like to use one template to create
+general TODO entries, and you want to put these entries under the
+heading =Tasks= in your file =~/org/gtd.org=.  Also, a date tree in
+the file =journal.org= should capture journal entries.  A possible
+configuration would look like:
+
+#+begin_src emacs-lisp
+(setq org-capture-templates
+      '(("t" "Todo" entry (file+headline "~/org/gtd.org" "Tasks")
+         "* TODO %?\n  %i\n  %a")
+        ("j" "Journal" entry (file+datetree "~/org/journal.org")
+         "* %?\nEntered on %U\n  %i\n  %a")))
+#+end_src
+
+If you then press {{{kbd(t)}}} from the capture menu, Org will prepare
+the template for you like this:
+
+#+begin_example
+,* TODO
+  [[file:LINK TO WHERE YOU INITIATED CAPTURE]]
+#+end_example
+
+#+texinfo: @noindent
+During expansion of the template, =%a= has been replaced by a link to
+the location from where you called the capture command.  This can be
+extremely useful for deriving tasks from emails, for example.  You
+fill in the task definition, press {{{kbd(C-c C-c)}}} and Org returns
+you to the same place where you started the capture process.
+
+To define special keys to capture to a particular template without
+going through the interactive template selection, you can create your
+key binding like this:
+
+#+begin_src emacs-lisp
+(define-key global-map (kbd "C-c x")
+  (lambda () (interactive) (org-capture nil "x")))
+#+end_src
+
+**** Template elements
+:PROPERTIES:
+:DESCRIPTION: What is needed for a complete template entry.
+:END:
+
+Now lets look at the elements of a template definition.  Each entry in
+~org-capture-templates~ is a list with the following items:
+
+- keys ::
+
+  The keys that selects the template, as a string, characters only,
+  for example ="a"=, for a template to be selected with a single key,
+  or ="bt"= for selection with two keys.  When using several keys,
+  keys using the same prefix key must be sequential in the list and
+  preceded by a 2-element entry explaining the prefix key, for
+  example:
+
+  #+begin_src emacs-lisp
+  ("b" "Templates for marking stuff to buy")
+  #+end_src
+
+  If you do not define a template for the {{{kbd(C)}}} key, this key
+  opens the Customize buffer for this complex variable.
+
+- description ::
+
+  A short string describing the template, shown during selection.
+
+- type ::
+
+  The type of entry, a symbol.  Valid values are:
+
+  - ~entry~ ::
+
+    An Org mode node, with a headline.  Will be filed as the child of
+    the target entry or as a top-level entry.  The target file should
+    be an Org file.
+
+  - ~item~ ::
+
+    A plain list item, placed in the first plain list at the target
+    location.  Again the target file should be an Org file.
+
+  - ~checkitem~ ::
+
+    A checkbox item.  This only differs from the plain list item by
+    the default template.
+
+  - ~table-line~ ::
+
+    A new line in the first table at the target location.  Where
+    exactly the line will be inserted depends on the properties
+    ~:prepend~ and ~:table-line-pos~ (see below).
+
+  - ~plain~ ::
+
+    Text to be inserted as it is.
+
+- target ::
+
+  #+vindex: org-default-notes-file
+  #+vindex: org-directory
+  Specification of where the captured item should be placed.  In Org
+  files, targets usually define a node.  Entries will become children
+  of this node.  Other types will be added to the table or list in the
+  body of this node.  Most target specifications contain a file name.
+  If that file name is the empty string, it defaults to
+  ~org-default-notes-file~.  A file can also be given as a variable or
+  as a function called with no argument.  When an absolute path is not
+  specified for a target, it is taken as relative to ~org-directory~.
+
+  Valid values are:
+
+  - =(file "path/to/file")= ::
+
+    Text will be placed at the beginning or end of that file.
+
+  - =(id "id of existing org entry")= ::
+
+    Filing as child of this entry, or in the body of the entry.
+
+  - =(file+headline "filename" "node headline")= ::
+
+    Fast configuration if the target heading is unique in the file.
+
+  - =(file+olp "filename" "Level 1 heading" "Level 2" ...)= ::
+
+    For non-unique headings, the full path is safer.
+
+  - =(file+regexp "filename" "regexp to find location")= ::
+
+    Use a regular expression to position point.
+
+  - =(file+olp+datetree "filename" [ "Level 1 heading" ...])= ::
+
+    This target[fn:84] creates a heading in a date tree[fn:85] for
+    today's date.  If the optional outline path is given, the tree
+    will be built under the node it is pointing to, instead of at top
+    level.  Check out the ~:time-prompt~ and ~:tree-type~ properties
+    below for additional options.
+
+  - =(file+function "filename" function-finding-location)= ::
+
+    A function to find the right location in the file.
+
+  - =(clock)= ::
+
+    File to the entry that is currently being clocked.
+
+  - =(function function-finding-location)= ::
+
+    Most general way: write your own function which both visits the
+    file and moves point to the right location.
+
+- template ::
+
+  The template for creating the capture item.  If you leave this
+  empty, an appropriate default template will be used.  Otherwise this
+  is a string with escape codes, which will be replaced depending on
+  time and context of the capture call.  You may also get this
+  template string from a file[fn:86], or dynamically, from a function
+  using either syntax:
+
+  : (file "/path/to/template-file")
+  : (function FUNCTION-RETURNING-THE-TEMPLATE)
+
+- properties ::
+
+  The rest of the entry is a property list of additional options.
+  Recognized properties are:
+
+  - ~:prepend~ ::
+
+    Normally new captured information will be appended at the target
+    location (last child, last table line, last list item, ...).
+    Setting this property changes that.
+
+  - ~:immediate-finish~ ::
+
+    When set, do not offer to edit the information, just file it away
+    immediately.  This makes sense if the template only needs
+    information that can be added automatically.
+
+  - ~:jump-to-captured~ ::
+
+    When set, jump to the captured entry when finished.
+
+  - ~:empty-lines~ ::
+
+    Set this to the number of lines to insert before and after the new
+    item.  Default 0, and the only other common value is 1.
+
+  - ~:empty-lines-after~ ::
+
+    Set this to the number of lines that should be inserted after the
+    new item.  Overrides ~:empty-lines~ for the number of lines
+    inserted after.
+
+  - ~:empty-lines-before~ ::
+
+    Set this to the number of lines that should be inserted before the
+    new item.  Overrides ~:empty-lines~ for the number lines inserted
+    before.
+
+  - ~:clock-in~ ::
+
+    Start the clock in this item.
+
+  - ~:clock-keep~ ::
+
+    Keep the clock running when filing the captured entry.
+
+  - ~:clock-resume~ ::
+
+    If starting the capture interrupted a clock, restart that clock
+    when finished with the capture.  Note that ~:clock-keep~ has
+    precedence over ~:clock-resume~.  When setting both to non-~nil~,
+    the current clock will run and the previous one will not be
+    resumed.
+
+  - ~:time-prompt~ ::
+
+    Prompt for a date/time to be used for date/week trees and when
+    filling the template.  Without this property, capture uses the
+    current date and time.  Even if this property has not been set,
+    you can force the same behavior by calling ~org-capture~ with
+    a {{{kbd(C-1)}}} prefix argument.
+
+  - ~:tree-type~ ::
+
+    Use ~week~ to make a week tree instead of the month-day tree,
+    i.e., place the headings for each day under a heading with the
+    current ISO week.  Use ~month~ to group entries by month
+    only.  Default is to group entries by day.
+
+  - ~:unnarrowed~ ::
+
+    Do not narrow the target buffer, simply show the full buffer.
+    Default is to narrow it so that you only see the new material.
+
+  - ~:table-line-pos~ ::
+
+    Specification of the location in the table where the new line
+    should be inserted.  It should be a string like =II-3= meaning
+    that the new line should become the third line before the second
+    horizontal separator line.
+
+  - ~:kill-buffer~ ::
+
+    If the target file was not yet visited when capture was invoked,
+    kill the buffer again after capture is completed.
+
+  - ~:no-save~ ::
+
+    Do not save the target file after finishing the capture.
+
+**** Template expansion
+:PROPERTIES:
+:DESCRIPTION: Filling in information about time and context.
+:END:
+
+In the template itself, special "%-escapes"[fn:87] allow dynamic
+insertion of content.  The templates are expanded in the order given
+here:
+
+- =%[FILE]= ::
+
+  Insert the contents of the file given by {{{var(FILE)}}}.
+
+- =%(EXP)= ::
+
+  Evaluate Elisp expression {{{var(EXP)}}} and replace it with the
+  result.  The {{{var(EXP)}}} form must return a string.  Only
+  placeholders pre-existing within the template, or introduced with
+  =%[file]=, are expanded this way.  Since this happens after
+  expanding non-interactive "%-escapes", those can be used to fill the
+  expression.
+
+- =%<FORMAT>= ::
+
+  The result of format-time-string on the {{{var(FORMAT)}}}
+  specification.
+
+- =%t= ::
+
+  Timestamp, date only.
+
+- =%T= ::
+
+  Timestamp, with date and time.
+
+- =%u=, =%U= ::
+
+  Like =%t=, =%T= above, but inactive timestamps.
+
+- =%i= ::
+
+  Initial content, the region when capture is called while the region
+  is active.  If there is text before =%i= on the same line, such as
+  indentation, and =%i= is not inside a =%(exp)= form, that prefix is
+  added before every line in the inserted text.
+
+- =%a= ::
+
+  Annotation, normally the link created with ~org-store-link~.
+
+- =%A= ::
+
+  Like =%a=, but prompt for the description part.
+
+- =%l= ::
+
+  Like =%a=, but only insert the literal link.
+
+- =%c= ::
+
+  Current kill ring head.
+
+- =%x= ::
+
+  Content of the X clipboard.
+
+- =%k= ::
+
+  Title of the currently clocked task.
+
+- =%K= ::
+
+  Link to the currently clocked task.
+
+- =%n= ::
+
+  User name (taken from ~user-full-name~).
+
+- =%f= ::
+
+  File visited by current buffer when org-capture was called.
+
+- =%F= ::
+
+  Full path of the file or directory visited by current buffer.
+
+- =%:keyword= ::
+
+  Specific information for certain link types, see below.
+
+- =%^g= ::
+
+  Prompt for tags, with completion on tags in target file.
+
+- =%^G= ::
+
+  Prompt for tags, with completion all tags in all agenda files.
+
+- =%^t= ::
+
+  Like =%t=, but prompt for date.  Similarly =%^T=, =%^u=, =%^U=.  You
+  may define a prompt like =%^{Birthday}t=.
+
+- =%^C= ::
+
+  Interactive selection of which kill or clip to use.
+
+- =%^L= ::
+
+  Like =%^C=, but insert as link.
+
+- =%^{PROP}p= ::
+
+  Prompt the user for a value for property {{{var(PROP)}}}.
+
+- =%^{PROMPT}= ::
+
+  Prompt the user for a string and replace this sequence with it.  You
+  may specify a default value and a completion table with
+  =%^{prompt|default|completion2|completion3...}=.  The arrow keys
+  access a prompt-specific history.
+
+- =%\N= ::
+
+  Insert the text entered at the {{{var(N)}}}th =%^{PROMPT}=, where
+  {{{var(N)}}} is a number, starting from 1.
+
+- =%?= ::
+
+  After completing the template, position point here.
+
+#+vindex: org-store-link-props
+For specific link types, the following keywords are defined[fn:88]:
+
+#+vindex: org-link-from-user-regexp
+| Link type    | Available keywords                                       |
+|--------------+----------------------------------------------------------|
+| bbdb         | =%:name=, =%:company=                                    |
+| irc          | =%:server=, =%:port=, =%:nick=                           |
+| mh, rmail    | =%:type=, =%:subject=, =%:message-id=                    |
+|              | =%:from=, =%:fromname=, =%:fromaddress=                  |
+|              | =%:to=, =%:toname=, =%:toaddress=                        |
+|              | =%:date= (message date header field)                     |
+|              | =%:date-timestamp= (date as active timestamp)            |
+|              | =%:date-timestamp-inactive= (date as inactive timestamp) |
+|              | =%:fromto= (either "to NAME" or "from NAME")[fn:89]      |
+| gnus         | =%:group=, for messages also all email fields            |
+| w3, w3m      | =%:url=                                                  |
+| info         | =%:file=, =%:node=                                       |
+| calendar     | =%:date=                                                 |
+| org-protocol | =%:link=, =%:description=, =%:annotation=                |
+
+**** Templates in contexts
+:PROPERTIES:
+:DESCRIPTION: Only show a template in a specific context.
+:END:
+
+#+vindex: org-capture-templates-contexts
+To control whether a capture template should be accessible from
+a specific context, you can customize
+~org-capture-templates-contexts~.  Let's say, for example, that you
+have a capture template "p" for storing Gnus emails containing
+patches.  Then you would configure this option like this:
+
+#+begin_src emacs-lisp
+(setq org-capture-templates-contexts
+      '(("p" (in-mode . "message-mode"))))
+#+end_src
+
+You can also tell that the command key {{{kbd(p)}}} should refer to
+another template.  In that case, add this command key like this:
+
+#+begin_src emacs-lisp
+(setq org-capture-templates-contexts
+      '(("p" "q" (in-mode . "message-mode"))))
+#+end_src
+
+See the docstring of the variable for more information.
+
+** Attachments
+:PROPERTIES:
+:DESCRIPTION: Attach files to outlines.
+:END:
+#+cindex: attachments
+
+It is often useful to associate reference material with an outline
+node.  Small chunks of plain text can simply be stored in the subtree
+of a project.  Hyperlinks (see [[*Hyperlinks]]) can establish associations
+with files that live elsewhere on a local, or even remote, computer,
+like emails or source code files belonging to a project.
+
+Another method is /attachments/, which are files located in a
+directory belonging to an outline node.  Org uses directories either
+named by a unique ID of each entry, or by a =DIR= property.
+
+*** Attachment defaults and dispatcher
+:PROPERTIES:
+:DESCRIPTION: How to access attachment commands
+:END:
+
+By default, Org attach uses ID properties when adding attachments to
+outline nodes.  This makes working with attachments fully automated.
+There is no decision needed for folder-name or location.  ID-based
+directories are by default located in the =data/= directory, which
+lives in the same directory where your Org file lives[fn:90].
+
+When attachments are made using ~org-attach~ a default tag =ATTACH= is
+added to the node that gets the attachments.
+
+For more control over the setup, see [[*Attachment options]].
+
+The following commands deal with attachments:
+
+- {{{kbd(C-c C-a)}}} (~org-attach~) ::
+
+  #+kindex: C-c C-a
+  #+findex: org-attach
+  The dispatcher for commands related to the attachment system.  After
+  these keys, a list of commands is displayed and you must press an
+  additional key to select a command:
+
+  - {{{kbd(a)}}} (~org-attach-attach~) ::
+
+    #+kindex: C-c C-a a
+    #+findex: org-attach-attach
+    #+vindex: org-attach-method
+    Select a file and move it into the task's attachment directory.
+    The file is copied, moved, or linked, depending on
+    ~org-attach-method~.  Note that hard links are not supported on
+    all systems.
+
+  - {{{kbd(c)}}}/{{{kbd(m)}}}/{{{kbd(l)}}} ::
+
+    #+kindex: C-c C-a c
+    #+kindex: C-c C-a m
+    #+kindex: C-c C-a l
+    Attach a file using the copy/move/link method.  Note that hard
+    links are not supported on all systems.
+
+  - {{{kbd(b)}}} (~org-attach-buffer~) ::
+
+    #+kindex: C-c C-a b
+    #+findex: org-attach-buffer
+    Select a buffer and save it as a file in the task's attachment
+    directory.
+
+  - {{{kbd(n)}}} (~org-attach-new~) ::
+
+    #+kindex: C-c C-a n
+    #+findex: org-attach-new
+    Create a new attachment as an Emacs buffer.
+
+  - {{{kbd(z)}}} (~org-attach-sync~) ::
+
+    #+kindex: C-c C-a z
+    #+findex: org-attach-sync
+    Synchronize the current task with its attachment directory, in
+    case you added attachments yourself.
+
+  - {{{kbd(o)}}} (~org-attach-open~) ::
+
+    #+kindex: C-c C-a o
+    #+findex: org-attach-open
+    #+vindex: org-file-apps
+    Open current task's attachment.  If there is more than one, prompt
+    for a file name first.  Opening follows the rules set by
+    ~org-file-apps~.  For more details, see the information on
+    following hyperlinks (see [[*Handling Links]]).
+
+  - {{{kbd(O)}}} (~org-attach-open-in-emacs~) ::
+
+    #+kindex: C-c C-a O
+    #+findex: org-attach-open-in-emacs
+    Also open the attachment, but force opening the file in Emacs.
+
+  - {{{kbd(f)}}} (~org-attach-reveal~) ::
+
+    #+kindex: C-c C-a f
+    #+findex: org-attach-reveal
+    Open the current task's attachment directory.
+
+  - {{{kbd(F)}}} (~org-attach-reveal-in-emacs~) ::
+
+    #+kindex: C-c C-a F
+    #+findex: org-attach-reveal-in-emacs
+    Also open the directory, but force using Dired in Emacs.
+
+  - {{{kbd(d)}}} (~org-attach-delete-one~) ::
+
+    #+kindex: C-c C-a d
+    Select and delete a single attachment.
+
+  - {{{kbd(D)}}} (~org-attach-delete-all~) ::
+
+    #+kindex: C-c C-a D
+    Delete all of a task's attachments.  A safer way is to open the
+    directory in Dired and delete from there.
+
+  - {{{kbd(s)}}} (~org-attach-set-directory~) ::
+
+    #+kindex: C-c C-a s
+    #+cindex: @samp{DIR}, property
+    Set a specific directory as the entry's attachment directory.
+    This works by putting the directory path into the =DIR=
+    property.
+
+  - {{{kbd(S)}}} (~org-attach-unset-directory~) ::
+
+    #+kindex: C-c C-a S
+    #+cindex: @samp{DIR}, property
+    Remove the attachment directory.  This command removes the =DIR=
+    property and asks the user to either move content inside that
+    folder, if an =ID= property is set, delete the content, or to
+    leave the attachment directory as is but no longer attached to the
+    outline node.
+
+*** Attachment options
+:PROPERTIES:
+:DESCRIPTION: Configuring the attachment system
+:END:
+
+There are a couple of options for attachments that are worth
+mentioning.
+
+- ~org-attach-id-dir~ ::
+  #+vindex: org-attach-id-dir
+  The directory where attachments are stored when =ID= is used as
+  method.
+
+- ~org-attach-dir-relative~ ::
+  #+vindex: org-attach-dir-relative
+  When setting the =DIR= property on a node using {{{kbd(C-c C-a s)}}}
+  (~org-attach-set-directory~), absolute links are entered by default.
+  This option changes that to relative links.
+
+- ~org-attach-use-inheritance~ ::
+  #+vindex: org-attach-use-inheritance
+  By default folders attached to an outline node are inherited from
+  parents according to ~org-use-property-inheritance~.  If one instead
+  want to set inheritance specifically for Org attach that can be done
+  using ~org-attach-use-inheritance~.  Inheriting documents through
+  the node hierarchy makes a lot of sense in most cases.  Especially
+  when using attachment links (see [[*Attachment links]]).  The following
+  example shows one use case for attachment inheritance:
+
+  #+begin_example
+  ,* Chapter A ...
+    :PROPERTIES:
+    :DIR: Chapter A/
+    :END:
+  ,** Introduction
+  Some text
+
+  #+NAME: Image 1
+  [[attachment:image 1.jpg]]
+  #+end_example
+
+  Without inheritance one would not be able to resolve the link to
+  =image 1.jpg=, since the link is inside a sub-heading to =Chapter
+  A=.
+
+  Inheritance works the same way for both =ID= and =DIR= property.  If
+  both properties are defined on the same headline then =DIR= takes
+  precedence.  This is also true if inheritance is enabled.  If =DIR=
+  is inherited from a parent node in the outline, that property still
+  takes precedence over an =ID= property defined on the node itself.
+
+- ~org-attach-method~ ::
+  #+vindex: org-attach-method
+  When attaching files using the dispatcher {{{kbd(C-c C-a)}}} it
+  defaults to copying files.  The behavior can be changed by
+  customizing ~org-attach-method~.  Options are Copy, Move/Rename,
+  Hard link or Symbolic link.
+
+- ~org-attach-preferred-new-method~ ::
+  #+vindex: org-attach-preferred-new-method
+  This customization lets you choose the default way to attach to
+  nodes without existing =ID= and =DIR= property.  It defaults to ~id~
+  but can also be set to ~dir~, ~ask~ or ~nil~.
+
+- ~org-attach-archive-delete~ ::
+  #+vindex: org-attach-archive-delete
+  Configure this to determine if attachments should be deleted or not
+  when a subtree that has attachments is archived.
+
+- ~org-attach-auto-tag~ ::
+  #+vindex: org-attach-auto-tag
+  When attaching files to a heading it will be assigned a tag
+  according to what is set here.
+
+- ~org-attach-id-to-path-function-list~ ::
+  #+vindex: org-attach-id-to-path-function-list
+  When =ID= is used for attachments, the ID is parsed into a part of a
+  directory-path.  See ~org-attach-id-uuid-folder-format~ for the
+  default function.  Define a new one and add it as first element in
+  ~org-attach-id-to-path-function-list~ if you want the folder
+  structure in any other way.  All functions in this list will be
+  tried when resolving existing ID's into paths, to maintain backward
+  compatibility with existing folders in your system.
+
+- ~org-attach-store-link-p~ ::
+  #+vindex: org-attach-store-link-p
+  Stores a link to the file that is being attached.  The link is
+  stored in ~org-stored-links~ for later insertion with {{{kbd(C-c
+  C-l)}}} (see [[*Handling Links]]).  Depending on what option is set in
+  ~org-attach-store-link-p~, the link is stored to either the original
+  location as a file link, the attachment location as an attachment
+  link or to the attachment location as a file link.
+
+- ~org-attach-commands~ ::
+  #+vindex: org-attach-commands
+  List of all commands used in the attach dispatcher.
+
+- ~org-attach-expert~ ::
+  #+vindex: org-attach-expert
+  Do not show the splash buffer with the attach dispatcher when
+  ~org-attach-expert~ is set to non-~nil~.
+
+See customization group =Org Attach= if you want to change the
+default settings.
+
+*** Attachment links
+:PROPERTIES:
+:DESCRIPTION: Hyperlink access to attachments
+:END:
+
+Attached files and folders can be referenced using attachment links.
+This makes it easy to refer to the material added to an outline node.
+Especially if it was attached using the unique ID of the entry!
+
+#+begin_example
+,* TODO Some task
+  :PROPERTIES:
+  :ID:       95d50008-c12e-479f-a4f2-cc0238205319
+  :END:
+See attached document for more information: [[attachment:info.org]]
+#+end_example
+
+See [[*External Links]] for more information about these links.
+
+*** Automatic version-control with Git
+:PROPERTIES:
+:DESCRIPTION: Everything safely stored away
+:END:
+
+If the directory attached to an outline node is a Git repository, Org
+can be configured to automatically commit changes to that repository
+when it sees them.
+
+To make Org mode take care of versioning of attachments for you, add
+the following to your Emacs config:
+
+#+begin_src emacs-lisp
+  (require 'org-attach-git)
+#+end_src
+
+*** Attach from Dired
+:PROPERTIES:
+:DESCRIPTION: Using dired to select an attachment
+:END:
+#+cindex: attach from Dired
+#+findex: org-attach-dired-to-subtree
+
+It is possible to attach files to a subtree from a Dired buffer.  To
+use this feature, have one window in Dired mode containing the file(s)
+to be attached and another window with point in the subtree that shall
+get the attachments.  In the Dired window, with point on a file,
+{{{kbd(M-x org-attach-dired-to-subtree)}}} attaches the file to the
+subtree using the attachment method set by variable
+~org-attach-method~.  When files are marked in the Dired window then
+all marked files get attached.
+
+Add the following lines to the Emacs init file to have {{{kbd(C-c C-x
+a)}}} attach files in Dired buffers.
+
+#+begin_src emacs-lisp
+(add-hook 'dired-mode-hook
+          (lambda ()
+            (define-key dired-mode-map
+              (kbd "C-c C-x a")
+              #'org-attach-dired-to-subtree)))
+#+end_src
+
+The following code shows how to bind the previous command with
+a specific attachment method.
+
+#+begin_src emacs-lisp
+(add-hook 'dired-mode-hook
+          (lambda ()
+            (define-key dired-mode-map (kbd "C-c C-x c")
+              (lambda ()
+                (interactive)
+                (let ((org-attach-method 'cp))
+                  (call-interactively #'org-attach-dired-to-subtree))))))
+#+end_src
+
+** RSS Feeds
+:PROPERTIES:
+:DESCRIPTION: Getting input from RSS feeds.
+:END:
+#+cindex: RSS feeds
+#+cindex: Atom feeds
+
+Org can add and change entries based on information found in RSS feeds
+and Atom feeds.  You could use this to make a task out of each new
+podcast in a podcast feed.  Or you could use a phone-based
+note-creating service on the web to import tasks into Org.  To access
+feeds, configure the variable ~org-feed-alist~.  The docstring of this
+variable has detailed information.  With the following
+
+#+begin_src emacs-lisp
+(setq org-feed-alist
+      '(("Slashdot"
+         "http://rss.slashdot.org/Slashdot/slashdot";
+         "~/txt/org/feeds.org" "Slashdot Entries")))
+#+end_src
+
+#+texinfo: @noindent
+new items from the feed provided by =rss.slashdot.org= result in new
+entries in the file =~/org/feeds.org= under the heading =Slashdot
+Entries=, whenever the following command is used:
+
+- {{{kbd(C-c C-x g)}}} (~org-feed-update-all~) ::
+
+  #+kindex: C-c C-x g
+  Collect items from the feeds configured in ~org-feed-alist~ and act
+  upon them.
+
+- {{{kbd(C-c C-x G)}}} (~org-feed-goto-inbox~) ::
+
+  #+kindex: C-c C-x G
+  Prompt for a feed name and go to the inbox configured for this feed.
+
+Under the same headline, Org creates a drawer =FEEDSTATUS= in which it
+stores information about the status of items in the feed, to avoid
+adding the same item several times.
+
+For more information, including how to read atom feeds, see
+=org-feed.el= and the docstring of ~org-feed-alist~.
+
+* Agenda Views
+:PROPERTIES:
+:DESCRIPTION: Collecting information into views.
+:END:
+#+cindex: agenda views
+
+Due to the way Org works, TODO items, time-stamped items, and tagged
+headlines can be scattered throughout a file or even a number of
+files.  To get an overview of open action items, or of events that are
+important for a particular date, this information must be collected,
+sorted and displayed in an organized way.
+
+Org can select items based on various criteria and display them in
+a separate buffer.  Six different view types are provided:
+
+- an /agenda/ that is like a calendar and shows information for
+  specific dates,
+
+- a /TODO list/ that covers all unfinished action items,
+
+- a /match view/, showings headlines based on the tags, properties,
+  and TODO state associated with them,
+
+- a /text search view/ that shows all entries from multiple files that
+  contain specified keywords,
+
+- a /stuck projects view/ showing projects that currently do not move
+  along, and
+
+- /custom views/ that are special searches and combinations of
+  different views.
+
+The extracted information is displayed in a special /agenda buffer/.
+This buffer is read-only, but provides commands to visit the
+corresponding locations in the original Org files, and even to edit
+these files remotely.
+
+#+vindex: org-agenda-skip-comment-trees
+#+vindex: org-agenda-skip-archived-trees
+#+cindex: commented entries, in agenda views
+#+cindex: archived entries, in agenda views
+By default, the report ignores commented (see [[*Comment Lines]]) and
+archived (see [[*Internal archiving]]) entries.  You can override this by
+setting ~org-agenda-skip-comment-trees~ and
+~org-agenda-skip-archived-trees~ to ~nil~.
+
+#+vindex: org-agenda-window-setup
+#+vindex: org-agenda-restore-windows-after-quit
+Two variables control how the agenda buffer is displayed and whether
+the window configuration is restored when the agenda exits:
+~org-agenda-window-setup~ and ~org-agenda-restore-windows-after-quit~.
+
+** Agenda Files
+:PROPERTIES:
+:DESCRIPTION: Files being searched for agenda information.
+:END:
+#+cindex: agenda files
+#+cindex: files for agenda
+
+#+vindex: org-agenda-files
+The information to be shown is normally collected from all /agenda
+files/, the files listed in the variable ~org-agenda-files~[fn:91].
+If a directory is part of this list, all files with the extension
+=.org= in this directory are part of the list.
+
+Thus, even if you only work with a single Org file, that file should
+be put into the list[fn:92].  You can customize ~org-agenda-files~,
+but the easiest way to maintain it is through the following commands
+
+#+attr_texinfo: :sep and
+- {{{kbd(C-c [)}}} (~org-agenda-file-to-front~) ::
+
+  #+kindex: C-c [
+  #+findex: org-agenda-file-to-front
+  #+cindex: files, adding to agenda list
+  Add current file to the list of agenda files.  The file is added to
+  the front of the list.  If it was already in the list, it is moved
+  to the front.  With a prefix argument, file is added/moved to the
+  end.
+
+- {{{kbd(C-c ])}}} (~org-remove-file~) ::
+
+  #+kindex: C-c ]
+  #+findex: org-remove-file
+  Remove current file from the list of agenda files.
+
+- {{{kbd(C-')}}} and {{{kbd(C-\,)}}} (~org-cycle-agenda-files~) ::
+
+  #+kindex: C-'
+  #+kindex: C-,
+  #+findex: org-cycle-agenda-files
+  #+cindex: cycling, of agenda files
+  Cycle through agenda file list, visiting one file after the other.
+
+- {{{kbd(M-x org-switchb)}}} ::
+
+  #+findex: org-switchb
+  Command to use an Iswitchb-like interface to switch to and between
+  Org buffers.
+
+#+texinfo: @noindent
+The Org menu contains the current list of files and can be used to
+visit any of them.
+
+If you would like to focus the agenda temporarily on a file not in
+this list, or on just one file in the list, or even on only a subtree
+in a file, then this can be done in different ways.  For a single
+agenda command, you may press {{{kbd(<)}}} once or several times in
+the dispatcher (see [[*The Agenda Dispatcher]]).  To restrict the agenda
+scope for an extended period, use the following commands:
+
+- {{{kbd(C-c C-x <)}}} (~org-agenda-set-restriction-lock~) ::
+
+  #+kindex: C-c C-x <
+  #+findex: org-agenda-set-restriction-lock
+  Restrict the agenda to the current subtree.  If there already is
+  a restriction at point, remove it.  When called with a universal
+  prefix argument or with point before the first headline in a file,
+  set the agenda scope to the entire file.  This restriction remains
+  in effect until removed with {{{kbd(C-c C-x >)}}}, or by typing
+  either {{{kbd(<)}}} or {{{kbd(>)}}} in the agenda dispatcher.  If
+  there is a window displaying an agenda view, the new restriction
+  takes effect immediately.
+
+- {{{kbd(C-c C-x >)}}} (~org-agenda-remove-restriction-lock~) ::
+
+  #+kindex: C-c C-x >
+  #+findex: org-agenda-remove-restriction-lock
+  Remove the restriction created by {{{kbd(C-c C-x <)}}}.
+
+When working with Speedbar, you can use the following commands in the
+Speedbar frame:
+
+- {{{kbd(<)}}} (~org-speedbar-set-agenda-restriction~) ::
+
+  #+findex: org-speedbar-set-agenda-restriction
+  Restrict the agenda to the item---either an Org file or a subtree in
+  such a file---at point in the Speedbar frame.  If agenda is already
+  restricted there, remove the restriction.  If there is a window
+  displaying an agenda view, the new restriction takes effect
+  immediately.
+
+- {{{kbd(>)}}} (~org-agenda-remove-restriction-lock~) ::
+
+  #+findex: org-agenda-remove-restriction-lock
+  Remove the restriction.
+
+** The Agenda Dispatcher
+:PROPERTIES:
+:DESCRIPTION: Keyboard access to agenda views.
+:ALT_TITLE: Agenda Dispatcher
+:END:
+#+cindex: agenda dispatcher
+#+cindex: dispatching agenda commands
+
+The views are created through a dispatcher, accessible with {{{kbd(M-x
+org-agenda)}}}, or, better, bound to a global key (see [[*Activation]]).
+It displays a menu from which an additional letter is required to
+execute a command.  The dispatcher offers the following default
+commands:
+
+#+attr_texinfo: :sep ,
+- {{{kbd(a)}}} ::
+
+  Create the calendar-like agenda (see [[*Weekly/daily agenda]]).
+
+- {{{kbd(t)}}}, {{{kbd(T)}}} ::
+
+  Create a list of all TODO items (see [[*The global TODO list]]).
+
+- {{{kbd(m)}}}, {{{kbd(M)}}} ::
+
+  Create a list of headlines matching a given expression (see
+  [[*Matching tags and properties]]).
+
+- {{{kbd(s)}}} ::
+
+  #+kindex: s @r{(Agenda dispatcher)}
+  Create a list of entries selected by a boolean expression of
+  keywords and/or regular expressions that must or must not occur in
+  the entry.
+
+- {{{kbd(/)}}} ::
+
+  #+kindex: / @r{(Agenda dispatcher)}
+  #+vindex: org-agenda-text-search-extra-files
+  Search for a regular expression in all agenda files and additionally
+  in the files listed in ~org-agenda-text-search-extra-files~.  This
+  uses the Emacs command ~multi-occur~.  A prefix argument can be used
+  to specify the number of context lines for each match, default is
+  1.
+
+- {{{kbd(#)}}} ::
+
+  Create a list of stuck projects (see [[*Stuck projects]]).
+
+- {{{kbd(!)}}} ::
+
+  Configure the list of stuck projects (see [[*Stuck projects]]).
+
+- {{{kbd(<)}}} ::
+
+  #+kindex: < @r{(Agenda dispatcher)}
+  Restrict an agenda command to the current buffer[fn:93].  If
+  narrowing is in effect restrict to the narrowed part of the buffer.
+  After pressing {{{kbd(<)}}}, you still need to press the character
+  selecting the command.
+
+- {{{kbd(< <)}}} ::
+
+  #+kindex: < < @r{(Agenda dispatcher)}
+  If there is an active region, restrict the following agenda command
+  to the region.  Otherwise, restrict it to the current
+  subtree[fn:94].  After pressing {{{kbd(< <)}}}, you still need to
+  press the character selecting the command.
+
+- {{{kbd(*)}}} ::
+
+  #+kindex: * @r{(Agenda dispatcher)}
+  #+vindex: org-agenda-sticky
+  #+findex: org-toggle-sticky-agenda
+  Toggle sticky agenda views.  By default, Org maintains only a single
+  agenda buffer and rebuilds it each time you change the view, to make
+  sure everything is always up to date.  If you switch between views
+  often and the build time bothers you, you can turn on sticky agenda
+  buffers (make this the default by customizing the variable
+  ~org-agenda-sticky~).  With sticky agendas, the dispatcher only
+  switches to the selected view, you need to update it by hand with
+  {{{kbd(r)}}} or {{{kbd(g)}}}.  You can toggle sticky agenda view any
+  time with ~org-toggle-sticky-agenda~.
+
+You can also define custom commands that are accessible through the
+dispatcher, just like the default commands.  This includes the
+possibility to create extended agenda buffers that contain several
+blocks together, for example the weekly agenda, the global TODO list
+and a number of special tags matches.  See [[*Custom Agenda Views]].
+
+** The Built-in Agenda Views
+:PROPERTIES:
+:DESCRIPTION: What is available out of the box?
+:ALT_TITLE: Built-in Agenda Views
+:END:
+
+In this section we describe the built-in views.
+
+*** Weekly/daily agenda
+:PROPERTIES:
+:DESCRIPTION: The calendar page with current tasks.
+:END:
+#+cindex: agenda
+#+cindex: weekly agenda
+#+cindex: daily agenda
+
+The purpose of the weekly/daily /agenda/ is to act like a page of
+a paper agenda, showing all the tasks for the current week or day.
+
+- {{{kbd(M-x org-agenda a)}}} (~org-agenda-list~) ::
+
+  #+kindex: a @r{(Agenda dispatcher)}
+  #+findex: org-agenda-list
+  #+cindex: org-agenda, command
+  Compile an agenda for the current week from a list of Org files.
+  The agenda shows the entries for each day.  With a numeric prefix
+  argument[fn:95]---like {{{kbd(C-u 2 1 M-x org-agenda a)}}}---you may
+  set the number of days to be displayed.
+
+#+vindex: org-agenda-span
+#+vindex: org-agenda-start-day
+#+vindex: org-agenda-start-on-weekday
+The default number of days displayed in the agenda is set by the
+variable ~org-agenda-span~.  This variable can be set to any number of
+days you want to see by default in the agenda, or to a span name, such
+a ~day~, ~week~, ~month~ or ~year~.  For weekly agendas, the default
+is to start on the previous Monday (see
+~org-agenda-start-on-weekday~).  You can also set the start date using
+a date shift: =(setq org-agenda-start-day "+10d")= starts the agenda
+ten days from today in the future.
+
+Remote editing from the agenda buffer means, for example, that you can
+change the dates of deadlines and appointments from the agenda buffer.
+The commands available in the Agenda buffer are listed in [[*Commands in
+the Agenda Buffer]].
+
+**** Calendar/Diary integration
+:PROPERTIES:
+:UNNUMBERED: notoc
+:END:
+#+cindex: calendar integration
+#+cindex: diary integration
+
+Emacs contains the calendar and diary by Edward\nbsp{}M.\nbsp{}Reingold.  The
+calendar displays a three-month calendar with holidays from different
+countries and cultures.  The diary allows you to keep track of
+anniversaries, lunar phases, sunrise/set, recurrent appointments
+(weekly, monthly) and more.  In this way, it is quite complementary to
+Org.  It can be very useful to combine output from Org with the diary.
+
+In order to include entries from the Emacs diary into Org mode's
+agenda, you only need to customize the variable
+
+#+begin_src emacs-lisp
+(setq org-agenda-include-diary t)
+#+end_src
+
+#+texinfo: @noindent
+After that, everything happens automatically.  All diary entries
+including holidays, anniversaries, etc., are included in the agenda
+buffer created by Org mode.  {{{kbd(SPC)}}}, {{{kbd(TAB)}}}, and
+{{{kbd(RET)}}} can be used from the agenda buffer to jump to the diary
+file in order to edit existing diary entries.  The {{{kbd(i)}}}
+command to insert new entries for the current date works in the agenda
+buffer, as well as the commands {{{kbd(S)}}}, {{{kbd(M)}}}, and
+{{{kbd(C)}}} to display Sunrise/Sunset times, show lunar phases and to
+convert to other calendars, respectively.  {{{kbd(c)}}} can be used to
+switch back and forth between calendar and agenda.
+
+If you are using the diary only for expression entries and holidays,
+it is faster to not use the above setting, but instead to copy or even
+move the entries into an Org file.  Org mode evaluates diary-style
+expression entries, and does it faster because there is no overhead
+for first creating the diary display.  Note that the expression
+entries must start at the left margin, no whitespace is allowed before
+them, as seen in the following segment of an Org file:[fn:96]
+
+#+begin_example
+,* Holidays
+  :PROPERTIES:
+  :CATEGORY: Holiday
+  :END:
+%%(org-calendar-holiday)   ; special function for holiday names
+
+,* Birthdays
+  :PROPERTIES:
+  :CATEGORY: Ann
+  :END:
+%%(org-anniversary 1956  5 14) Arthur Dent is %d years old
+%%(org-anniversary 1869 10  2) Mahatma Gandhi would be %d years old
+#+end_example
+
+**** Anniversaries from BBDB
+:PROPERTIES:
+:UNNUMBERED: notoc
+:END:
+#+cindex: BBDB, anniversaries
+#+cindex: anniversaries, from BBDB
+
+#+findex: org-bbdb-anniversaries
+If you are using the Insidious Big Brother Database to store your
+contacts, you very likely prefer to store anniversaries in BBDB rather
+than in a separate Org or diary file.  Org supports this and can show
+BBDB anniversaries as part of the agenda.  All you need to do is to
+add the following to one of your agenda files:
+
+#+begin_example
+,* Anniversaries
+  :PROPERTIES:
+  :CATEGORY: Anniv
+  :END:
+%%(org-bbdb-anniversaries)
+#+end_example
+
+You can then go ahead and define anniversaries for a BBDB record.
+Basically, you need a field named =anniversary= for the BBDB record
+which contains the date in the format =YYYY-MM-DD= or =MM-DD=,
+followed by a space and the class of the anniversary (=birthday=,
+=wedding=, or a format string).  If you omit the class, it defaults to
+=birthday=.  Here are a few examples, the header for the file
+=ol-bbdb.el= contains more detailed information.
+
+#+begin_example
+1973-06-22
+06-22
+1955-08-02 wedding
+2008-04-14 %s released version 6.01 of Org mode, %d years ago
+#+end_example
+
+After a change to BBDB, or for the first agenda display during an
+Emacs session, the agenda display suffers a short delay as Org updates
+its hash with anniversaries.  However, from then on things will be
+very fast, much faster in fact than a long list of
+=%%(diary-anniversary)= entries in an Org or Diary file.
+
+#+findex: org-bbdb-anniversaries-future
+If you would like to see upcoming anniversaries with a bit of
+forewarning, you can use the following instead:
+
+#+begin_example
+,* Anniversaries
+  :PROPERTIES:
+  :CATEGORY: Anniv
+  :END:
+%%(org-bbdb-anniversaries-future 3)
+#+end_example
+
+That will give you three days' warning: on the anniversary date itself
+and the two days prior.  The argument is optional: if omitted, it
+defaults to 7.
+
+**** Appointment reminders
+:PROPERTIES:
+:UNNUMBERED: notoc
+:END:
+#+cindex: @file{appt.el}
+#+cindex: appointment reminders
+#+cindex: appointment
+#+cindex: reminders
+
+#+cindex: APPT_WARNTIME, keyword
+Org can interact with Emacs appointments notification facility.  To
+add the appointments of your agenda files, use the command
+~org-agenda-to-appt~.  This command lets you filter through the list
+of your appointments and add only those belonging to a specific
+category or matching a regular expression.  It also reads
+a =APPT_WARNTIME= property which overrides the value of
+~appt-message-warning-time~ for this appointment.  See the docstring
+for details.
+
+*** The global TODO list
+:PROPERTIES:
+:DESCRIPTION: All unfinished action items.
+:ALT_TITLE: Global TODO list
+:END:
+#+cindex: global TODO list
+#+cindex: TODO list, global
+
+The global TODO list contains all unfinished TODO items formatted and
+collected into a single place.
+
+- {{{kbd(M-x org-agenda t)}}} (~org-todo-list~) ::
+
+  #+kindex: t @r{(Agenda dispatcher)}
+  #+findex: org-todo-list
+  Show the global TODO list.  This collects the TODO items from all
+  agenda files (see [[*Agenda Views]]) into a single buffer.  By default,
+  this lists items with a state the is not a DONE state.  The buffer
+  is in Agenda mode, so there are commands to examine and manipulate
+  the TODO entries directly from that buffer (see [[*Commands in the
+  Agenda Buffer]]).
+
+- {{{kbd(M-x org-agenda T)}}} (~org-todo-list~) ::
+
+  #+kindex: T @r{(Agenda dispatcher)}
+  #+findex: org-todo-list
+  #+cindex: TODO keyword matching
+  #+vindex: org-todo-keywords
+  Like the above, but allows selection of a specific TODO keyword.
+  You can also do this by specifying a prefix argument to
+  {{{kbd(t)}}}.  You are prompted for a keyword, and you may also
+  specify several keywords by separating them with =|= as the boolean
+  OR operator.  With a numeric prefix, the Nth keyword in
+  ~org-todo-keywords~ is selected.
+
+  #+kindex: r
+  The {{{kbd(r)}}} key in the agenda buffer regenerates it, and you
+  can give a prefix argument to this command to change the selected
+  TODO keyword, for example {{{kbd(3 r)}}}.  If you often need
+  a search for a specific keyword, define a custom command for it (see
+  [[*The Agenda Dispatcher]]).
+
+  Matching specific TODO keywords can also be done as part of a tags
+  search (see [[*Tag Searches]]).
+
+Remote editing of TODO items means that you can change the state of
+a TODO entry with a single key press.  The commands available in the
+TODO list are described in [[*Commands in the Agenda Buffer]].
+
+#+cindex: sublevels, inclusion into TODO list
+Normally the global TODO list simply shows all headlines with TODO
+keywords.  This list can become very long.  There are two ways to keep
+it more compact:
+
+-
+  #+vindex: org-agenda-todo-ignore-scheduled
+  #+vindex: org-agenda-todo-ignore-deadlines
+  #+vindex: org-agenda-todo-ignore-timestamp
+  #+vindex: org-agenda-todo-ignore-with-date
+  Some people view a TODO item that has been /scheduled/ for execution
+  or have a /deadline/ (see [[*Timestamps]]) as no longer /open/.
+  Configure the variables ~org-agenda-todo-ignore-scheduled~ to
+  exclude some or all scheduled items from the global TODO list,
+  ~org-agenda-todo-ignore-deadlines~ to exclude some or all items with
+  a deadline set, ~org-agenda-todo-ignore-timestamp~ to exclude some
+  or all items with an active timestamp other than a DEADLINE or
+  a SCHEDULED timestamp and/or ~org-agenda-todo-ignore-with-date~ to
+  exclude items with at least one active timestamp.
+
+-
+  #+vindex: org-agenda-todo-list-sublevels
+  TODO items may have sublevels to break up the task into subtasks.
+  In such cases it may be enough to list only the highest level TODO
+  headline and omit the sublevels from the global list.  Configure the
+  variable ~org-agenda-todo-list-sublevels~ to get this behavior.
+
+*** Matching tags and properties
+:PROPERTIES:
+:DESCRIPTION: Structured information with fine-tuned search.
+:END:
+#+cindex: matching, of tags
+#+cindex: matching, of properties
+#+cindex: tags view
+#+cindex: match view
+
+If headlines in the agenda files are marked with /tags/ (see [[*Tags]]),
+or have properties (see [[*Properties and Columns]]), you can select
+headlines based on this metadata and collect them into an agenda
+buffer.  The match syntax described here also applies when creating
+sparse trees with {{{kbd(C-c / m)}}}.
+
+- {{{kbd(M-x org-agenda m)}}} (~org-tags-view~) ::
+
+  #+kindex: m @r{(Agenda dispatcher)}
+  #+findex: org-tags-view
+  Produce a list of all headlines that match a given set of tags.  The
+  command prompts for a selection criterion, which is a boolean logic
+  expression with tags, like =+work+urgent-withboss= or =work|home=
+  (see [[*Tags]]).  If you often need a specific search, define a custom
+  command for it (see [[*The Agenda Dispatcher]]).
+
+- {{{kbd(M-x org-agenda M)}}} (~org-tags-view~) ::
+
+  #+kindex: M @r{(Agenda dispatcher)}
+  #+findex: org-tags-view
+  #+vindex: org-tags-match-list-sublevels
+  #+vindex: org-agenda-tags-todo-honor-ignore-options
+  Like {{{kbd(m)}}}, but only select headlines that are also TODO
+  items and force checking subitems (see the variable
+  ~org-tags-match-list-sublevels~).  To exclude scheduled/deadline
+  items, see the variable ~org-agenda-tags-todo-honor-ignore-options~.
+  Matching specific TODO keywords together with a tags match is also
+  possible, see [[*Tag Searches]].
+
+The commands available in the tags list are described in [[*Commands in
+the Agenda Buffer]].
+
+#+cindex: boolean logic, for agenda searches
+A search string can use Boolean operators =&= for AND and =|= for OR.
+=&= binds more strongly than =|=.  Parentheses are currently not
+implemented.  Each element in the search is either a tag, a regular
+expression matching tags, or an expression like =PROPERTY OPERATOR
+VALUE= with a comparison operator, accessing a property value.  Each
+element may be preceded by =-= to select against it, and =+= is
+syntactic sugar for positive selection.  The AND operator =&= is
+optional when =+= or =-= is present.  Here are some examples, using
+only tags.
+
+- =+work-boss= ::
+
+  Select headlines tagged =work=, but discard those also tagged
+  =boss=.
+
+- =work|laptop= ::
+
+  Selects lines tagged =work= or =laptop=.
+
+- =work|laptop+night= ::
+
+  Like before, but require the =laptop= lines to be tagged also
+  =night=.
+
+#+cindex: regular expressions, with tags search
+Instead of a tag, you may also specify a regular expression enclosed
+in curly braces.  For example, =work+{^boss.*}= matches headlines that
+contain the tag =:work:= and any tag /starting/ with =boss=.
+
+#+cindex: group tags, as regular expressions
+Group tags (see [[*Tag Hierarchy]]) are expanded as regular expressions.
+E.g., if =work= is a group tag for the group =:work:lab:conf:=, then
+searching for =work= also searches for ={\(?:work\|lab\|conf\)}= and
+searching for =-work= searches for all headlines but those with one of
+the tags in the group (i.e., =-{\(?:work\|lab\|conf\)}=).
+
+#+cindex: TODO keyword matching, with tags search
+#+cindex: level, for tags/property match
+#+cindex: category, for tags/property match
+#+vindex: org-odd-levels-only
+You may also test for properties (see [[*Properties and Columns]]) at the
+same time as matching tags.  The properties may be real properties, or
+special properties that represent other metadata (see [[*Special
+Properties]]).  For example, the property =TODO= represents the TODO
+keyword of the entry.  Or, the property =LEVEL= represents the level
+of an entry.  So searching =+LEVEL=3+boss-TODO​="DONE"= lists all level
+three headlines that have the tag =boss= and are /not/ marked with the
+TODO keyword =DONE=.  In buffers with ~org-odd-levels-only~ set,
+=LEVEL= does not count the number of stars, but =LEVEL=2= corresponds
+to 3 stars etc.
+
+Here are more examples:
+
+- =work+TODO​="WAITING"= ::
+
+  Select =work=-tagged TODO lines with the specific TODO keyword
+  =WAITING=.
+
+- =work+TODO​="WAITING"|home+TODO​="WAITING"= ::
+
+  Waiting tasks both at work and at home.
+
+When matching properties, a number of different operators can be used
+to test the value of a property.  Here is a complex example:
+
+#+begin_example
++work-boss+PRIORITY="A"+Coffee="unlimited"+Effort<2
+         +With={Sarah|Denny}+SCHEDULED>="<2008-10-11>"
+#+end_example
+
+#+texinfo: @noindent
+The type of comparison depends on how the comparison value is written:
+
+- If the comparison value is a plain number, a numerical comparison is
+  done, and the allowed operators are =<=, ===, =>=, =<==, =>==, and
+  =<>=.
+
+- If the comparison value is enclosed in double-quotes, a string
+  comparison is done, and the same operators are allowed.
+
+- If the comparison value is enclosed in double-quotes /and/ angular
+  brackets (like =DEADLINE<​="<2008-12-24 18:30>"=), both values are
+  assumed to be date/time specifications in the standard Org way, and
+  the comparison is done accordingly.  Valid values also include
+  ="<now>"= for now (including time), ="<today>"=, and ="<tomorrow>"=
+  for these days at 0:00 hours, i.e., without a time specification.
+  You can also use strings like ="<+5d>"= or ="<-2m>"= with units =d=,
+  =w=, =m=, and =y= for day, week, month, and year, respectively.
+
+- If the comparison value is enclosed in curly braces, a regexp match
+  is performed, with === meaning that the regexp matches the property
+  value, and =<>= meaning that it does not match.
+
+So the search string in the example finds entries tagged =work= but
+not =boss=, which also have a priority value =A=, a =Coffee= property
+with the value =unlimited=, an =EFFORT= property that is numerically
+smaller than 2, a =With= property that is matched by the regular
+expression =Sarah|Denny=, and that are scheduled on or after October
+11, 2008.
+
+You can configure Org mode to use property inheritance during
+a search, but beware that this can slow down searches considerably.
+See [[*Property Inheritance]], for details.
+
+For backward compatibility, and also for typing speed, there is also
+a different way to test TODO states in a search.  For this, terminate
+the tags/property part of the search string (which may include several
+terms connected with =|=) with a =/= and then specify a Boolean
+expression just for TODO keywords.  The syntax is then similar to that
+for tags, but should be applied with care: for example, a positive
+selection on several TODO keywords cannot meaningfully be combined
+with boolean AND.  However, /negative selection/ combined with AND can
+be meaningful.  To make sure that only lines are checked that actually
+have any TODO keyword (resulting in a speed-up), use {{{kbd(M-x
+org-agenda M)}}}, or equivalently start the TODO part after the slash
+with =!=.  Using {{{kbd(M-x org-agenda M)}}} or =/!= does not match
+TODO keywords in a DONE state.  Examples:
+
+- =work/WAITING= ::
+
+  Same as =work+TODO​="WAITING"=.
+
+- =work/!-WAITING-NEXT= ::
+
+  Select =work=-tagged TODO lines that are neither =WAITING= nor
+  =NEXT=.
+
+- =work/!+WAITING|+NEXT= ::
+
+  Select =work=-tagged TODO lines that are either =WAITING= or =NEXT=.
+
+*** Search view
+:PROPERTIES:
+:DESCRIPTION: Find entries by searching for text.
+:END:
+#+cindex: search view
+#+cindex: text search
+#+cindex: searching, for text
+
+This agenda view is a general text search facility for Org mode
+entries.  It is particularly useful to find notes.
+
+- {{{kbd(M-x org-agenda s)}}} (~org-search-view~) ::
+
+  #+kindex: s @r{(Agenda dispatcher)}
+  #+findex: org-search-view
+  This is a special search that lets you select entries by matching
+  a substring or specific words using a boolean logic.
+
+For example, the search string =computer equipment= matches entries
+that contain =computer equipment= as a substring, even if the two
+words are separated by more space or a line break.
+
+Search view can also search for specific keywords in the entry, using
+Boolean logic.  The search string =+computer
++wifi -ethernet -{8\.11[bg]}= matches note entries that contain the
+keywords =computer= and =wifi=, but not the keyword =ethernet=, and
+which are also not matched by the regular expression =8\.11[bg]=,
+meaning to exclude both =8.11b= and =8.11g=.  The first =+= is
+necessary to turn on boolean search, other =+= characters are
+optional.  For more details, see the docstring of the command
+~org-search-view~.
+
+You can incrementally and conveniently adjust a boolean search from
+the agenda search view with the following keys
+
+#+attr_texinfo: :columns 0.1 0.6
+| {{{kbd([)}}} | Add a positive search word        |
+| {{{kbd(])}}} | Add a negative search word        |
+| {{{kbd({)}}} | Add a positive regular expression |
+| {{{kbd(})}}} | Add a negative regular expression |
+
+#+vindex: org-agenda-text-search-extra-files
+Note that in addition to the agenda files, this command also searches
+the files listed in ~org-agenda-text-search-extra-files~.
+
+*** Stuck projects
+:PROPERTIES:
+:DESCRIPTION: Find projects you need to review.
+:END:
+#+pindex: GTD, Getting Things Done
+
+If you are following a system like David Allen's GTD to organize your
+work, one of the "duties" you have is a regular review to make sure
+that all projects move along.  A /stuck/ project is a project that has
+no defined next actions, so it never shows up in the TODO lists Org
+mode produces.  During the review, you need to identify such projects
+and define next actions for them.
+
+- {{{kbd(M-x org-agenda #)}}} (~org-agenda-list-stuck-projects~) ::
+
+  #+kindex: # @r{(Agenda dispatcher)}
+  #+findex: org-agenda-list-stuck-projects
+  List projects that are stuck.
+
+- {{{kbd(M-x org-agenda !)}}} ::
+
+  #+kindex: ! @r{(Agenda dispatcher)}
+  #+vindex: org-stuck-projects
+  Customize the variable ~org-stuck-projects~ to define what a stuck
+  project is and how to find it.
+
+You almost certainly need to configure this view before it works for
+you.  The built-in default assumes that all your projects are level-2
+headlines, and that a project is not stuck if it has at least one
+entry marked with a TODO keyword =TODO= or =NEXT= or =NEXTACTION=.
+
+Let's assume that you, in your own way of using Org mode, identify
+projects with a tag =:PROJECT:=, and that you use a TODO keyword
+=MAYBE= to indicate a project that should not be considered yet.
+Let's further assume that the TODO keyword =DONE= marks finished
+projects, and that =NEXT= and =TODO= indicate next actions.  The tag
+=:@shop:= indicates shopping and is a next action even without the
+NEXT tag.  Finally, if the project contains the special word =IGNORE=
+anywhere, it should not be listed either.  In this case you would
+start by identifying eligible projects with a tags/TODO match (see
+[[*Tag Searches]]) =+PROJECT/-MAYBE-DONE=, and then check for =TODO=,
+=NEXT=, =@shop=, and =IGNORE= in the subtree to identify projects that
+are not stuck.  The correct customization for this is:
+
+#+begin_src emacs-lisp
+(setq org-stuck-projects
+      '("+PROJECT/-MAYBE-DONE" ("NEXT" "TODO") ("@shop")
+        "\\<IGNORE\\>"))
+#+end_src
+
+Note that if a project is identified as non-stuck, the subtree of this
+entry is searched for stuck projects.
+
+** Presentation and Sorting
+:PROPERTIES:
+:DESCRIPTION: How agenda items are prepared for display.
+:END:
+#+cindex: presentation, of agenda items
+
+#+vindex: org-agenda-prefix-format
+#+vindex: org-agenda-tags-column
+Before displaying items in an agenda view, Org mode visually prepares
+the items and sorts them.  Each item occupies a single line.  The line
+starts with a /prefix/ that contains the /category/ (see [[*Categories]])
+of the item and other important information.  You can customize in
+which column tags are displayed through ~org-agenda-tags-column~.  You
+can also customize the prefix using the option
+~org-agenda-prefix-format~.  This prefix is followed by a cleaned-up
+version of the outline headline associated with the item.
+
+*** Categories
+:PROPERTIES:
+:DESCRIPTION: Not all tasks are equal.
+:END:
+#+cindex: category
+#+cindex: @samp{CATEGORY}, keyword
+
+The category is a broad label assigned to each agenda item.  By
+default, the category is simply derived from the file name, but you
+can also specify it with a special line in the buffer, like
+this:
+
+: #+CATEGORY: Thesis
+
+#+cindex: @samp{CATEGORY}, property
+If you would like to have a special category for a single entry or
+a (sub)tree, give the entry a =CATEGORY= property with the special
+category you want to apply as the value.
+
+#+vindex: org-agenda-category-icon-alist
+The display in the agenda buffer looks best if the category is not
+longer than 10 characters.  You can set up icons for category by
+customizing the ~org-agenda-category-icon-alist~ variable.
+
+*** Time-of-day specifications
+:PROPERTIES:
+:DESCRIPTION: How the agenda knows the time.
+:END:
+#+cindex: time-of-day specification
+
+Org mode checks each agenda item for a time-of-day specification.  The
+time can be part of the timestamp that triggered inclusion into the
+agenda, for example
+
+: <2005-05-10 Tue 19:00>
+
+#+texinfo: @noindent
+Time ranges can be specified with two timestamps:
+
+: <2005-05-10 Tue 20:30>--<2005-05-10 Tue 22:15>
+
+#+vindex: org-agenda-search-headline-for-time
+In the headline of the entry itself, a time(range)---like =12:45= or
+a =8:30-1pm=---may also appear as plain text[fn:97].
+
+If the agenda integrates the Emacs diary (see [[*Weekly/daily agenda]]),
+time specifications in diary entries are recognized as well.
+
+For agenda display, Org mode extracts the time and displays it in
+a standard 24 hour format as part of the prefix.  The example times in
+the previous paragraphs would end up in the agenda like this:
+
+#+begin_example
+ 8:30-13:00 Arthur Dent lies in front of the bulldozer
+12:45...... Ford Prefect arrives and takes Arthur to the pub
+19:00...... The Vogon reads his poem
+20:30-22:15 Marvin escorts the Hitchhikers to the bridge
+#+end_example
+
+#+cindex: time grid
+If the agenda is in single-day mode, or for the display of today, the
+timed entries are embedded in a time grid, like
+
+#+begin_example
+ 8:00...... ------------------
+ 8:30-13:00 Arthur Dent lies in front of the bulldozer
+10:00...... ------------------
+12:00...... ------------------
+12:45...... Ford Prefect arrives and takes Arthur to the pub
+14:00...... ------------------
+16:00...... ------------------
+18:00...... ------------------
+19:00...... The Vogon reads his poem
+20:00...... ------------------
+20:30-22:15 Marvin escorts the Hitchhikers to the bridge
+#+end_example
+
+#+vindex: org-agenda-use-time-grid
+#+vindex: org-agenda-time-grid
+The time grid can be turned on and off with the variable
+~org-agenda-use-time-grid~, and can be configured with
+~org-agenda-time-grid~.
+
+*** Sorting of agenda items
+:PROPERTIES:
+:DESCRIPTION: The order of things.
+:END:
+#+cindex: sorting, of agenda items
+#+cindex: priorities, of agenda items
+
+Before being inserted into a view, the items are sorted.  How this is
+done depends on the type of view.
+
+-
+  #+vindex: org-agenda-files
+  For the daily/weekly agenda, the items for each day are sorted.  The
+  default order is to first collect all items containing an explicit
+  time-of-day specification.  These entries are shown at the beginning
+  of the list, as a /schedule/ for the day.  After that, items remain
+  grouped in categories, in the sequence given by ~org-agenda-files~.
+  Within each category, items are sorted by priority (see
+  [[*Priorities]]), which is composed of the base priority (2000 for
+  priority =A=, 1000 for =B=, and 0 for =C=), plus additional
+  increments for overdue scheduled or deadline items.
+
+- For the TODO list, items remain in the order of categories, but
+  within each category, sorting takes place according to priority (see
+  [[*Priorities]]).  The priority used for sorting derives from the
+  priority cookie, with additions depending on how close an item is to
+  its due or scheduled date.
+
+- For tags matches, items are not sorted at all, but just appear in
+  the sequence in which they are found in the agenda files.
+
+#+vindex: org-agenda-sorting-strategy
+Sorting can be customized using the variable
+~org-agenda-sorting-strategy~, and may also include criteria based on
+the estimated effort of an entry (see [[*Effort Estimates]]).
+
+*** Filtering/limiting agenda items
+:PROPERTIES:
+:DESCRIPTION: Dynamically narrow the agenda.
+:END:
+
+#+vindex: org-agenda-category-filter-preset
+#+vindex: org-agenda-tag-filter-preset
+#+vindex: org-agenda-effort-filter-preset
+#+vindex: org-agenda-regexp-filter-preset
+Agenda built-in or custom commands are statically defined.  Agenda
+filters and limits allow to flexibly narrow down the list of agenda
+entries.
+
+/Filters/ only change the visibility of items, are very fast and are
+mostly used interactively[fn:98].  You can switch quickly between
+different filters without having to recreate the agenda.  /Limits/ on
+the other hand take effect before the agenda buffer is populated, so
+they are mostly useful when defined as local variables within custom
+agenda commands.
+
+**** Filtering in the agenda
+:PROPERTIES:
+:UNNUMBERED: notoc
+:END:
+#+cindex: agenda filtering
+#+cindex: filtering entries, in agenda
+#+cindex: tag filtering, in agenda
+#+cindex: category filtering, in agenda
+#+cindex: top headline filtering, in agenda
+#+cindex: effort filtering, in agenda
+#+cindex: query editing, in agenda
+
+The general filtering command is ~org-agenda-filter~, bound to
+{{{kbd(/)}}}.  Before we introduce it, we describe commands for
+individual filter types.  All filtering commands handle prefix
+arguments in the same way:  A single {{{kbd(C-u)}}} prefix negates the
+filter, so it removes lines selected by the filter.  A double prefix
+adds the new filter condition to the one(s) already in place, so
+filter elements are accumulated.
+
+- {{{kbd(\)}}} (~org-agenda-filter-by-tag~) ::
+
+  #+findex: org-agenda-filter-by-tag
+  Filter the agenda view with respect to a tag.  You are prompted for
+  a tag selection letter; {{{kbd(SPC)}}} means any tag at all.
+  Pressing {{{kbd(TAB)}}} at that prompt offers completion to select a
+  tag, including any tags that do not have a selection character.  The
+  command then hides all entries that do not contain or inherit this
+  tag.  Pressing {{{kbd(+)}}} or {{{kbd(-)}}} at the prompt switches
+  between filtering for and against the next tag.  To clear the
+  filter, press {{{kbd(\)}}} twice (once to call the command again,
+  and once at the prompt).
+
+- {{{kbd(<)}}} (~org-agenda-filter-by-category~) ::
+
+  #+findex: org-agenda-filter-by-category
+  Filter by category of the line at point, and show only entries with
+  this category.  When called with a prefix argument, hide all entries
+  with the category at point.  To clear the filter, call this command
+  again by pressing {{{kbd(<)}}}.
+
+- {{{kbd(=)}}} (~org-agenda-filter-by-regexp~) ::
+
+  #+findex: org-agenda-filter-by-regexp
+  Filter the agenda view by a regular expression: only show agenda
+  entries matching the regular expression the user entered.  To clear
+  the filter, call the command again by pressing {{{kbd(=)}}}.
+
+- {{{kbd(_)}}} (~org-agenda-filter-by-effort~) ::
+
+  #+findex: org-agenda-filter-by-effort
+  Filter the agenda view with respect to effort estimates, so select
+  tasks that take the right amount of time.  You first need to set up
+  a list of efforts globally, for example
+
+  #+begin_src emacs-lisp
+  (setq org-global-properties
+        '(("Effort_ALL". "0 0:10 0:30 1:00 2:00 3:00 4:00")))
+  #+end_src
+
+  #+vindex: org-sort-agenda-noeffort-is-high
+  You can then filter for an effort by first typing an operator, one
+  of {{{kbd(<)}}}, {{{kbd(>)}}} and {{{kbd(=)}}}, and then the
+  one-digit index of an effort estimate in your array of allowed
+  values, where {{{kbd(0)}}} means the 10th value.  The filter then
+  restricts to entries with effort smaller-or-equal, equal, or
+  larger-or-equal than the selected value.  For application of the
+  operator, entries without a defined effort are treated according to
+  the value of ~org-sort-agenda-noeffort-is-high~.  To clear the
+  filter, press {{{kbd(_)}}} twice (once to call the command again,
+  and once at the first prompt).
+
+- {{{kbd(^)}}} (~org-agenda-filter-by-top-headline~) ::
+
+  #+findex: org-agenda-filter-by-top-headline
+  Filter the current agenda view and only display items that fall
+  under the same top-level headline as the current entry.  To clear
+  the filter, call this command again by pressing {{{kbd(^)}}}.
+
+- {{{kbd(/)}}} (~org-agenda-filter~) ::
+
+  #+findex: org-agenda-filter
+  This is the unified interface to four of the five filter methods
+  described above.  At the prompt, specify different filter elements
+  in a single string, with full completion support.  For example,
+
+  : +work-John+<0:10-/plot/
+
+  selects entries with category =work= and effort estimates below 10
+  minutes, and deselects entries with tag =John= or matching the
+  regexp =plot=.  You can leave =+= out if that does not lead to
+  ambiguities.  The sequence of elements is arbitrary.  The filter
+  syntax assumes that there is no overlap between categories and tags.
+  Otherwise, tags take priority.  If you reply to the prompt with the
+  empty string, all filtering is removed.  If a filter is specified,
+  it replaces all current filters.  But if you call the command with
+  a double prefix argument, or if you add an additional =+= (e.g.,
+  =++work=) to the front of the string, the new filter elements are
+  added to the active ones.  A single prefix argument applies the
+  entire filter in a negative sense.
+
+- {{{kbd(|)}}} (~org-agenda-filter-remove-all~) ::
+
+  Remove all filters in the current agenda view.
+
+**** Computed tag filtering
+:PROPERTIES:
+:UNNUMBERED: notoc
+:END:
+
+#+vindex: org-agenda-auto-exclude-function
+If the variable ~org-agenda-auto-exclude-function~ is set to
+a user-defined function, that function can select tags that should be
+used as a tag filter when requested.  The function will be called with
+lower-case versions of all tags represented in the current view.  The
+function should return ="-tag"= if the filter should remove
+entries with that tag, ="+tag"= if only entries with this tag should
+be kept, or =nil= if that tag is irrelevant.  For example, let's say
+you use a =Net= tag to identify tasks which need network access, an
+=Errand= tag for errands in town, and a =Call= tag for making phone
+calls.  You could auto-exclude these tags based on the availability of
+the Internet, and outside of business hours, with something like this:
+
+#+begin_src emacs-lisp
+(defun my-auto-exclude-fn (tag)
+  (when (cond ((string= tag "net")
+              (/= 0 (call-process "/sbin/ping" nil nil nil
+                                  "-c1" "-q" "-t1" "mail.gnu.org")))
+              ((member tag '("errand" "call"))
+              (let ((hr (nth 2 (decode-time))))
+                (or (< hr 8) (> hr 21)))))
+    (concat "-" tag)))
+
+(setq org-agenda-auto-exclude-function #'my-auto-exclude-fn)
+#+end_src
+
+You can apply this self-adapting filter by using a triple prefix
+argument to ~org-agenda-filter~, i.e.\nbsp{}press {{{kbd(C-u C-u C-u /)}}},
+or by pressing {{{kbd(RET)}}} in ~org-agenda-filter-by-tag~.
+
+**** Setting limits for the agenda
+:PROPERTIES:
+:UNNUMBERED: notoc
+:END:
+#+cindex: limits, in agenda
+
+Here is a list of options that you can set, either globally, or
+locally in your custom agenda views (see [[*Custom Agenda Views]]).
+
+- ~org-agenda-max-entries~ ::
+
+  #+vindex: org-agenda-max-entries
+  Limit the number of entries.
+
+- ~org-agenda-max-effort~ ::
+
+  #+vindex: org-agenda-max-effort
+  Limit the duration of accumulated efforts (as minutes).
+
+- ~org-agenda-max-todos~ ::
+
+  #+vindex: org-agenda-max-todos
+  Limit the number of entries with TODO keywords.
+
+- ~org-agenda-max-tags~ ::
+
+  #+vindex: org-agenda-max-tags
+  Limit the number of tagged entries.
+
+When set to a positive integer, each option excludes entries from
+other categories: for example, =(setq org-agenda-max-effort 100)=
+limits the agenda to 100 minutes of effort and exclude any entry that
+has no effort property.  If you want to include entries with no effort
+property, use a negative value for ~org-agenda-max-effort~.  One
+useful setup is to use ~org-agenda-max-entries~ locally in a custom
+command.  For example, this custom command displays the next five
+entries with a =NEXT= TODO keyword.
+
+#+begin_src emacs-lisp
+(setq org-agenda-custom-commands
+      '(("n" todo "NEXT"
+         ((org-agenda-max-entries 5)))))
+#+end_src
+
+Once you mark one of these five entry as DONE, rebuilding the agenda
+will again the next five entries again, including the first entry that
+was excluded so far.
+
+You can also dynamically set temporary limits, which are lost when
+rebuilding the agenda:
+
+- {{{kbd(~ )}}} (~org-agenda-limit-interactively~) ::
+
+  #+findex: org-agenda-limit-interactively
+  This prompts for the type of limit to apply and its value.
+
+** Commands in the Agenda Buffer
+:PROPERTIES:
+:DESCRIPTION: Remote editing of Org trees.
+:ALT_TITLE: Agenda Commands
+:END:
+#+cindex: commands, in agenda buffer
+
+Entries in the agenda buffer are linked back to the Org file or diary
+file where they originate.  You are not allowed to edit the agenda
+buffer itself, but commands are provided to show and jump to the
+original entry location, and to edit the Org files "remotely" from the
+agenda buffer.  In this way, all information is stored only once,
+removing the risk that your agenda and note files may diverge.
+
+Some commands can be executed with mouse clicks on agenda lines.  For
+the other commands, point needs to be in the desired line.
+
+*** Motion
+:PROPERTIES:
+:UNNUMBERED: notoc
+:END:
+#+cindex: motion commands in agenda
+
+- {{{kbd(n)}}} (~org-agenda-next-line~) ::
+
+  #+kindex: n
+  #+findex: org-agenda-next-line
+  Next line (same as {{{kbd(DOWN)}}} and {{{kbd(C-n)}}}).
+
+- {{{kbd(p)}}} (~org-agenda-previous-line~) ::
+
+  #+kindex: p
+  #+findex: org-agenda-previous-line
+  Previous line (same as {{{kbd(UP)}}} and {{{kbd(C-p)}}}).
+
+*** View/Go to Org file
+:PROPERTIES:
+:UNNUMBERED: notoc
+:END:
+#+cindex: view file commands in agenda
+
+- {{{kbd(SPC)}}} or {{{kbd(mouse-3)}}} (~org-agenda-show-and-scroll-up~) ::
+
+  #+kindex: SPC
+  #+kindex: mouse-3
+  #+findex: org-agenda-show-and-scroll-up
+  Display the original location of the item in another window.
+  With a prefix argument, make sure that drawers stay folded.
+
+- {{{kbd(L)}}} (~org-agenda-recenter~) ::
+
+  #+findex: org-agenda-recenter
+  Display original location and recenter that window.
+
+- {{{kbd(TAB)}}} or {{{kbd(mouse-2)}}} (~org-agenda-goto~) ::
+
+  #+kindex: TAB
+  #+kindex: mouse-2
+  #+findex: org-agenda-goto
+  Go to the original location of the item in another window.
+
+- {{{kbd(RET)}}} (~org-agenda-switch-to~) ::
+
+  #+kindex: RET
+  #+findex: org-agenda-switch-to
+  Go to the original location of the item and delete other windows.
+
+- {{{kbd(F)}}} (~org-agenda-follow-mode~) ::
+
+  #+kindex: F
+  #+findex: org-agenda-follow-mode
+  #+vindex: org-agenda-start-with-follow-mode
+  Toggle Follow mode.  In Follow mode, as you move point through the
+  agenda buffer, the other window always shows the corresponding
+  location in the Org file.  The initial setting for this mode in new
+  agenda buffers can be set with the variable
+  ~org-agenda-start-with-follow-mode~.
+
+- {{{kbd(C-c C-x b)}}} (~org-agenda-tree-to-indirect-buffer~) ::
+
+  #+kindex: C-c C-x b
+  #+findex: org-agenda-tree-to-indirect-buffer
+  Display the entire subtree of the current item in an indirect
+  buffer.  With a numeric prefix argument N, go up to level N and then
+  take that tree.  If N is negative, go up that many levels.  With
+  a {{{kbd(C-u)}}} prefix, do not remove the previously used indirect
+  buffer.
+
+- {{{kbd(C-c C-o)}}} (~org-agenda-open-link~) ::
+
+  #+kindex: C-c C-o
+  #+findex: org-agenda-open-link
+  Follow a link in the entry.  This offers a selection of any links in
+  the text belonging to the referenced Org node.  If there is only one
+  link, follow it without a selection prompt.
+
+*** Change display
+:PROPERTIES:
+:UNNUMBERED: notoc
+:END:
+#+cindex: change agenda display
+#+cindex: display changing, in agenda
+
+#+attr_texinfo: :sep ,
+- {{{kbd(A)}}} ::
+
+  #+kindex: A
+  Interactively select another agenda view and append it to the
+  current view.
+
+- {{{kbd(o)}}} ::
+
+  #+kindex: o
+  Delete other windows.
+
+- {{{kbd(v d)}}} or short {{{kbd(d)}}} (~org-agenda-day-view~) ::
+
+  #+kindex: v d
+  #+kindex: d
+  #+findex: org-agenda-day-view
+  Switch to day view.  When switching to day view, this setting
+  becomes the default for subsequent agenda refreshes.  A numeric
+  prefix argument may be used to jump directly to a specific day of
+  the year.  For example, {{{kbd(32 d)}}} jumps to February 1st.  When
+  setting day view, a year may be encoded in the prefix argument as
+  well.  For example, {{{kbd(200712 d)}}} jumps to January 12, 2007.
+  If such a year specification has only one or two digits, it is
+  expanded into one of the 30 next years or the last 69 years.
+
+- {{{kbd(v w)}}} or short {{{kbd(w)}}} (~org-agenda-week-view~) ::
+
+  #+kindex: v w
+  #+kindex: w
+  #+findex: org-agenda-week-view
+  Switch to week view.  When switching week view, this setting becomes
+  the default for subsequent agenda refreshes.  A numeric prefix
+  argument may be used to jump directly to a specific day of the ISO
+  week.  For example {{{kbd(9 w)}}} to ISO week number 9.  When
+  setting week view, a year may be encoded in the prefix argument as
+  well.  For example, {{{kbd(200712 w)}}} jumps to week 12 in 2007.
+  If such a year specification has only one or two digits, it is
+  expanded into one of the 30 next years or the last 69 years.
+
+- {{{kbd(v m)}}} (~org-agenda-month-view~) ::
+
+  #+kindex: v m
+  #+findex: org-agenda-month-view
+  Switch to month view.  Because month views are slow to create, they
+  do not become the default for subsequent agenda refreshes.
+  A numeric prefix argument may be used to jump directly to a specific
+  day of the month.  When setting month view, a year may be encoded in
+  the prefix argument as well.  For example, {{{kbd(200712 m)}}} jumps
+  to December, 2007.  If such a year specification has only one or two
+  digits, it is expanded into one of the 30 next years or the last 69
+  years.
+
+- {{{kbd(v y)}}} (~org-agenda-year-view~) ::
+
+  #+kindex: v y
+  #+findex: org-agenda-year-view
+  Switch to year view.  Because year views are slow to create, they do
+  not become the default for subsequent agenda refreshes.  A numeric
+  prefix argument may be used to jump directly to a specific day of
+  the year.
+
+- {{{kbd(v SPC)}}} (~org-agenda-reset-view~) ::
+
+  #+kindex: v SPC
+  #+findex: org-agenda-reset-view
+  #+vindex: org-agenda-span
+  Reset the current view to ~org-agenda-span~.
+
+- {{{kbd(f)}}} (~org-agenda-later~) ::
+
+  #+kindex: f
+  #+findex: org-agenda-later
+  Go forward in time to display the span following the current one.
+  For example, if the display covers a week, switch to the following
+  week.  With a prefix argument, repeat that many times.
+
+- {{{kbd(b)}}} (~org-agenda-earlier~) ::
+
+  #+kindex: b
+  #+findex: org-agenda-earlier
+  Go backward in time to display earlier dates.
+
+- {{{kbd(.)}}} (~org-agenda-goto-today~) ::
+
+  #+kindex: .
+  #+findex: org-agenda-goto-today
+  Go to today.
+
+- {{{kbd(j)}}} (~org-agenda-goto-date~) ::
+
+  #+kindex: j
+  #+findex: org-agenda-goto-date
+  Prompt for a date and go there.
+
+- {{{kbd(J)}}} (~org-agenda-clock-goto~) ::
+
+  #+kindex: J
+  #+findex: org-agenda-clock-goto
+  Go to the currently clocked-in task /in the agenda buffer/.
+
+- {{{kbd(D)}}} (~org-agenda-toggle-diary~) ::
+
+  #+kindex: D
+  #+findex: org-agenda-toggle-diary
+  Toggle the inclusion of diary entries.  See [[*Weekly/daily agenda]].
+
+- {{{kbd(v l)}}} or {{{kbd(v L)}}} or short {{{kbd(l)}}} 
(~org-agenda-log-mode~) ::
+
+  #+kindex: v l
+  #+kindex: l
+  #+kindex: v L
+  #+findex: org-agenda-log-mode
+  #+vindex: org-log-done
+  #+vindex: org-agenda-log-mode-items
+  Toggle Logbook mode.  In Logbook mode, entries that were marked as
+  done while logging was on (see the variable ~org-log-done~) are
+  shown in the agenda, as are entries that have been clocked on that
+  day.  You can configure the entry types that should be included in
+  log mode using the variable ~org-agenda-log-mode-items~.  When
+  called with a {{{kbd(C-u)}}} prefix argument, show all possible
+  logbook entries, including state changes.  When called with two
+  prefix arguments {{{kbd(C-u C-u)}}}, show only logging information,
+  nothing else.  {{{kbd(v L)}}} is equivalent to {{{kbd(C-u v l)}}}.
+
+- {{{kbd(v [)}}} or short {{{kbd([)}}} (~org-agenda-manipulate-query-add~) ::
+
+  #+kindex: v [
+  #+kindex: [
+  #+findex: org-agenda-manipulate-query-add
+  Include inactive timestamps into the current view.  Only for
+  weekly/daily agenda.
+
+- {{{kbd(v a)}}} (~org-agenda-archives-mode~) ::
+
+  #+kindex: v a
+  #+findex: org-agenda-archives-mode
+  Toggle Archives mode.  In Archives mode, trees that are archived
+  (see [[*Internal archiving]]) are also scanned when producing the
+  agenda.  To exit archives mode, press {{{kbd(v a)}}} again.
+
+- {{{kbd(v A)}}} ::
+
+  #+kindex: v A
+  Toggle Archives mode.  Include all archive files as well.
+
+- {{{kbd(v R)}}} or short {{{kbd(R)}}} (~org-agenda-clockreport-mode~) ::
+
+  #+kindex: v R
+  #+kindex: R
+  #+findex: org-agenda-clockreport-mode
+  #+vindex: org-agenda-start-with-clockreport-mode
+  #+vindex: org-clock-report-include-clocking-task
+  Toggle Clockreport mode.  In Clockreport mode, the daily/weekly
+  agenda always shows a table with the clocked times for the time span
+  and file scope covered by the current agenda view.  The initial
+  setting for this mode in new agenda buffers can be set with the
+  variable ~org-agenda-start-with-clockreport-mode~.  By using
+  a prefix argument when toggling this mode (i.e., {{{kbd(C-u R)}}}),
+  the clock table does not show contributions from entries that are
+  hidden by agenda filtering[fn:99].  See also the variable
+  ~org-clock-report-include-clocking-task~.
+
+- {{{kbd(v c)}}} ::
+
+  #+kindex: v c
+  #+vindex: org-agenda-clock-consistency-checks
+  Show overlapping clock entries, clocking gaps, and other clocking
+  problems in the current agenda range.  You can then visit clocking
+  lines and fix them manually.  See the variable
+  ~org-agenda-clock-consistency-checks~ for information on how to
+  customize the definition of what constituted a clocking problem.  To
+  return to normal agenda display, press {{{kbd(l)}}} to exit Logbook
+  mode.
+
+- {{{kbd(v E)}}} or short {{{kbd(E)}}} (~org-agenda-entry-text-mode~) ::
+
+  #+kindex: v E
+  #+kindex: E
+  #+findex: org-agenda-entry-text-mode
+  #+vindex: org-agenda-start-with-entry-text-mode
+  #+vindex: org-agenda-entry-text-maxlines
+  Toggle entry text mode.  In entry text mode, a number of lines from
+  the Org outline node referenced by an agenda line are displayed
+  below the line.  The maximum number of lines is given by the
+  variable ~org-agenda-entry-text-maxlines~.  Calling this command
+  with a numeric prefix argument temporarily modifies that number to
+  the prefix value.
+
+- {{{kbd(G)}}} (~org-agenda-toggle-time-grid~) ::
+
+  #+kindex: G
+  #+vindex: org-agenda-use-time-grid
+  #+vindex: org-agenda-time-grid
+  Toggle the time grid on and off.  See also the variables
+  ~org-agenda-use-time-grid~ and ~org-agenda-time-grid~.
+
+- {{{kbd(r)}}} (~org-agenda-redo~), {{{kbd(g)}}} ::
+
+  #+kindex: r
+  #+kindex: g
+  #+findex: org-agenda-redo
+  Recreate the agenda buffer, for example to reflect the changes after
+  modification of the timestamps of items with {{{kbd(S-LEFT)}}} and
+  {{{kbd(S-RIGHT)}}}.  When the buffer is the global TODO list,
+  a prefix argument is interpreted to create a selective list for
+  a specific TODO keyword.
+
+- {{{kbd(C-x C-s)}}} or short {{{kbd(s)}}} (~org-save-all-org-buffers~) ::
+
+  #+kindex: C-x C-s
+  #+findex: org-save-all-org-buffers
+  #+kindex: s
+  Save all Org buffers in the current Emacs session, and also the
+  locations of IDs.
+
+- {{{kbd(C-c C-x C-c)}}} (~org-agenda-columns~) ::
+
+  #+kindex: C-c C-x C-c
+  #+findex: org-agenda-columns
+  #+vindex: org-columns-default-format
+  Invoke column view (see [[*Column View]]) in the agenda buffer.  The
+  column view format is taken from the entry at point, or, if there is
+  no entry at point, from the first entry in the agenda view.  So
+  whatever the format for that entry would be in the original buffer
+  (taken from a property, from a =COLUMNS= keyword, or from the
+  default variable ~org-columns-default-format~) is used in the
+  agenda.
+
+- {{{kbd(C-c C-x >)}}} (~org-agenda-remove-restriction-lock~) ::
+
+  #+kindex: C-c C-x >
+  #+findex: org-agenda-remove-restriction-lock
+  Remove the restriction lock on the agenda, if it is currently
+  restricted to a file or subtree (see [[*Agenda Files]]).
+
+- {{{kbd(M-UP)}}} (~org-agenda-drag-line-backward~) ::
+
+  #+kindex: M-UP
+  #+findex: org-agenda-drag-line-backward
+  Drag the line at point backward one line.  With a numeric prefix
+  argument, drag backward by that many lines.
+
+  Moving agenda lines does not persist after an agenda refresh and
+  does not modify the contributing Org files.
+
+- {{{kbd(M-DOWN)}}} (~org-agenda-drag-line-forward~) ::
+
+  #+kindex: M-DOWN
+  #+findex: org-agenda-drag-line-forward
+  Drag the line at point forward one line.  With a numeric prefix
+  argument, drag forward by that many lines.
+
+*** Remote editing
+:PROPERTIES:
+:UNNUMBERED: notoc
+:END:
+#+cindex: remote editing, from agenda
+
+- {{{kbd(0--9)}}} ::
+
+  Digit argument.
+
+- {{{kbd(C-_)}}} (~org-agenda-undo~) ::
+
+  #+kindex: C-_
+  #+findex: org-agenda-undo
+  #+cindex: undoing remote-editing events
+  #+cindex: remote editing, undo
+  Undo a change due to a remote editing command.  The change is undone
+  both in the agenda buffer and in the remote buffer.
+
+- {{{kbd(t)}}} (~org-agenda-todo~) ::
+
+  #+kindex: t
+  #+findex: org-agenda-todo
+  Change the TODO state of the item, both in the agenda and in the
+  original Org file.  A prefix arg is passed through to the ~org-todo~
+  command, so for example a {{{kbd(C-u)}}} prefix are will trigger
+  taking a note to document the state change.
+
+- {{{kbd(C-S-RIGHT)}}} (~org-agenda-todo-nextset~) ::
+
+  #+kindex: C-S-RIGHT
+  #+findex: org-agenda-todo-nextset
+  Switch to the next set of TODO keywords.
+
+- {{{kbd(C-S-LEFT)}}}, ~org-agenda-todo-previousset~ ::
+
+  #+kindex: C-S-LEFT
+  Switch to the previous set of TODO keywords.
+
+- {{{kbd(C-k)}}} (~org-agenda-kill~) ::
+
+  #+kindex: C-k
+  #+findex: org-agenda-kill
+  #+vindex: org-agenda-confirm-kill
+  Delete the current agenda item along with the entire subtree
+  belonging to it in the original Org file.  If the text to be deleted
+  remotely is longer than one line, the kill needs to be confirmed by
+  the user.  See variable ~org-agenda-confirm-kill~.
+
+- {{{kbd(C-c C-w)}}} (~org-agenda-refile~) ::
+
+  #+kindex: C-c C-w
+  #+findex: org-agenda-refile
+  Refile the entry at point.
+
+- {{{kbd(C-c C-x C-a)}}} or short {{{kbd(a)}}} 
(~org-agenda-archive-default-with-confirmation~) ::
+
+  #+kindex: C-c C-x C-a
+  #+kindex: a
+  #+findex: org-agenda-archive-default-with-confirmation
+  #+vindex: org-archive-default-command
+  Archive the subtree corresponding to the entry at point using the
+  default archiving command set in ~org-archive-default-command~.
+  When using the {{{kbd(a)}}} key, confirmation is required.
+
+- {{{kbd(C-c C-x a)}}} (~org-agenda-toggle-archive-tag~) ::
+
+  #+kindex: C-c C-x a
+  #+findex: org-agenda-toggle-archive-tag
+  Toggle the archive tag (see [[*Internal archiving]]) for the current
+  headline.
+
+- {{{kbd(C-c C-x A)}}} (~org-agenda-archive-to-archive-sibling~) ::
+
+  #+kindex: C-c C-x A
+  #+findex: org-agenda-archive-to-archive-sibling
+  Move the subtree corresponding to the current entry to its /archive
+  sibling/.
+
+- {{{kbd(C-c C-x C-s)}}} or short {{{kbd($)}}} (~org-agenda-archive~) ::
+
+  #+kindex: C-c C-x C-s
+  #+kindex: $
+  #+findex: org-agenda-archive
+  Archive the subtree corresponding to the current headline.  This
+  means the entry is moved to the configured archive location, most
+  likely a different file.
+
+- {{{kbd(T)}}} (~org-agenda-show-tags~) ::
+
+  #+kindex: T
+  #+findex: org-agenda-show-tags
+  #+vindex: org-agenda-show-inherited-tags
+  Show all tags associated with the current item.  This is useful if
+  you have turned off ~org-agenda-show-inherited-tags~, but still want
+  to see all tags of a headline occasionally.
+
+- {{{kbd(:)}}} (~org-agenda-set-tags~) ::
+
+  #+kindex: :
+  #+findex: org-agenda-set-tags
+  Set tags for the current headline.  If there is an active region in
+  the agenda, change a tag for all headings in the region.
+
+- {{{kbd(\,)}}} (~org-agenda-priority~) ::
+
+  #+kindex: ,
+  #+findex: org-agenda-priority
+  Set the priority for the current item.  Org mode prompts for the
+  priority character.  If you reply with {{{kbd(SPC)}}}, the priority
+  cookie is removed from the entry.
+
+- {{{kbd(+)}}} or {{{kbd(S-UP)}}} (~org-agenda-priority-up~) ::
+
+  #+kindex: +
+  #+kindex: S-UP
+  #+findex: org-agenda-priority-up
+  Increase the priority of the current item.  The priority is changed
+  in the original buffer, but the agenda is not resorted.  Use the
+  {{{kbd(r)}}} key for this.
+
+- {{{kbd(-)}}} or {{{kbd(S-DOWN)}}} (~org-agenda-priority-down~) ::
+
+  #+kindex: -
+  #+kindex: S-DOWN
+  #+findex: org-agenda-priority-down
+  Decrease the priority of the current item.
+
+- {{{kbd(C-c C-x e)}}} or short {{{kbd(e)}}} (~org-agenda-set-effort~) ::
+
+  #+kindex: e
+  #+kindex: C-c C-x e
+  #+findex: org-agenda-set-effort
+  Set the effort property for the current item.
+
+- {{{kbd(C-c C-z)}}} or short {{{kbd(z)}}} (~org-agenda-add-note~) ::
+
+  #+kindex: z
+  #+kindex: C-c C-z
+  #+findex: org-agenda-add-note
+  #+vindex: org-log-into-drawer
+  Add a note to the entry.  This note is recorded, and then filed to
+  the same location where state change notes are put.  Depending on
+  ~org-log-into-drawer~, this may be inside a drawer.
+
+- {{{kbd(C-c C-a)}}} (~org-attach~) ::
+
+  #+kindex: C-c C-a
+  #+findex: org-attach
+  Dispatcher for all command related to attachments.
+
+- {{{kbd(C-c C-s)}}} (~org-agenda-schedule~) ::
+
+  #+kindex: C-c C-s
+  #+findex: org-agenda-schedule
+  Schedule this item.  With a prefix argument, remove the
+  scheduling timestamp
+
+- {{{kbd(C-c C-d)}}} (~org-agenda-deadline~) ::
+
+  #+kindex: C-c C-d
+  #+findex: org-agenda-deadline
+  Set a deadline for this item.  With a prefix argument, remove the
+  deadline.
+
+- {{{kbd(S-RIGHT)}}} (~org-agenda-do-date-later~) ::
+
+  #+kindex: S-RIGHT
+  #+findex: org-agenda-do-date-later
+  Change the timestamp associated with the current line by one day
+  into the future.  If the date is in the past, the first call to this
+  command moves it to today.  With a numeric prefix argument, change
+  it by that many days.  For example, {{{kbd(3 6 5 S-RIGHT)}}} changes
+  it by a year.  With a {{{kbd(C-u)}}} prefix, change the time by one
+  hour.  If you immediately repeat the command, it will continue to
+  change hours even without the prefix argument.  With a double
+  {{{kbd(C-u C-u)}}} prefix, do the same for changing minutes.  The
+  stamp is changed in the original Org file, but the change is not
+  directly reflected in the agenda buffer.  Use {{{kbd(r)}}} or
+  {{{kbd(g)}}} to update the buffer.
+
+- {{{kbd(S-LEFT)}}} (~org-agenda-do-date-earlier~) ::
+
+  #+kindex: S-LEFT
+  #+findex: org-agenda-do-date-earlier
+  Change the timestamp associated with the current line by one day
+  into the past.
+
+- {{{kbd(>)}}} (~org-agenda-date-prompt~) ::
+
+  #+kindex: >
+  #+findex: org-agenda-date-prompt
+  Change the timestamp associated with the current line.  The key
+  {{{kbd(>)}}} has been chosen, because it is the same as
+  {{{kbd(S-.)}}}  on my keyboard.
+
+- {{{kbd(I)}}} (~org-agenda-clock-in~) ::
+
+  #+kindex: I
+  #+findex: org-agenda-clock-in
+  Start the clock on the current item.  If a clock is running already,
+  it is stopped first.
+
+- {{{kbd(O)}}} (~org-agenda-clock-out~) ::
+
+  #+kindex: O
+  #+findex: org-agenda-clock-out
+  Stop the previously started clock.
+
+- {{{kbd(X)}}} (~org-agenda-clock-cancel~) ::
+
+  #+kindex: X
+  #+findex: org-agenda-clock-cancel
+  Cancel the currently running clock.
+
+- {{{kbd(J)}}} (~org-agenda-clock-goto~) ::
+
+  #+kindex: J
+  #+findex: org-agenda-clock-goto
+  Jump to the running clock in another window.
+
+- {{{kbd(k)}}} (~org-agenda-capture~) ::
+
+  #+kindex: k
+  #+findex: org-agenda-capture
+  #+cindex: capturing, from agenda
+  #+vindex: org-capture-use-agenda-date
+  Like ~org-capture~, but use the date at point as the default date
+  for the capture template.  See ~org-capture-use-agenda-date~ to make
+  this the default behavior of ~org-capture~.
+
+*** Bulk remote editing selected entries
+:PROPERTIES:
+:UNNUMBERED: notoc
+:END:
+#+cindex: remote editing, bulk, from agenda
+#+vindex: org-agenda-bulk-custom-functions
+
+- {{{kbd(m)}}} (~org-agenda-bulk-mark~) ::
+  #+kindex: m
+  #+findex: org-agenda-bulk-mark
+
+  Mark the entry at point for bulk action.  If there is an active
+  region in the agenda, mark the entries in the region.  With numeric
+  prefix argument, mark that many successive entries.
+
+- {{{kbd(*)}}} (~org-agenda-bulk-mark-all~) ::
+  #+kindex: *
+  #+findex: org-agenda-bulk-mark-all
+
+  Mark all visible agenda entries for bulk action.
+
+- {{{kbd(u)}}} (~org-agenda-bulk-unmark~) ::
+  #+kindex: u
+  #+findex: org-agenda-bulk-unmark
+
+  Unmark entry for bulk action.
+
+- {{{kbd(U)}}} (~org-agenda-bulk-remove-all-marks~) ::
+  #+kindex: U
+  #+findex: org-agenda-bulk-remove-all-marks
+
+  Unmark all marked entries for bulk action.
+
+- {{{kbd(M-m)}}} (~org-agenda-bulk-toggle~) ::
+  #+kindex: M-m
+  #+findex: org-agenda-bulk-toggle
+
+  Toggle mark of the entry at point for bulk action.
+
+- {{{kbd(M-*)}}} (~org-agenda-bulk-toggle-all~) ::
+  #+kindex: M-*
+  #+findex: org-agenda-bulk-toggle-all
+
+  Toggle mark of every entry for bulk action.
+
+- {{{kbd(%)}}} (~org-agenda-bulk-mark-regexp~) ::
+  #+kindex: %
+  #+findex: org-agenda-bulk-mark-regexp
+
+  Mark entries matching a regular expression for bulk action.
+
+- {{{kbd(B)}}} (~org-agenda-bulk-action~) ::
+  #+kindex: B
+  #+findex: org-agenda-bulk-action
+  #+vindex: org-agenda-bulk-persistent-marks
+
+  Bulk action: act on all marked entries in the agenda.  This prompts
+  for another key to select the action to be applied.  The prefix
+  argument to {{{kbd(B)}}} is passed through to the {{{kbd(s)}}} and
+  {{{kbd(d)}}} commands, to bulk-remove these special timestamps.  By
+  default, marks are removed after the bulk.  If you want them to
+  persist, set ~org-agenda-bulk-persistent-marks~ to ~t~ or hit
+  {{{kbd(p)}}} at the prompt.
+
+  - {{{kbd(p)}}} ::
+
+    Toggle persistent marks.
+
+  - {{{kbd($)}}} ::
+
+    Archive all selected entries.
+
+  - {{{kbd(A)}}} ::
+
+    Archive entries by moving them to their respective archive
+    siblings.
+
+  - {{{kbd(t)}}} ::
+
+    Change TODO state.  This prompts for a single TODO keyword and
+    changes the state of all selected entries, bypassing blocking and
+    suppressing logging notes---but not timestamps.
+
+  - {{{kbd(+)}}} ::
+
+    Add a tag to all selected entries.
+
+  - {{{kbd(-)}}} ::
+
+    Remove a tag from all selected entries.
+
+  - {{{kbd(s)}}} ::
+
+    Schedule all items to a new date.  To shift existing schedule
+    dates by a fixed number of days, use something starting with
+    double plus at the prompt, for example =++8d= or =++2w=.
+
+  - {{{kbd(d)}}} ::
+
+    Set deadline to a specific date.
+
+  - {{{kbd(r)}}} ::
+
+    Prompt for a single refile target and move all entries.  The
+    entries are no longer in the agenda; refresh ({{{kbd(g)}}}) to
+    bring them back.
+
+  - {{{kbd(S)}}} ::
+
+    Reschedule randomly into the coming N days.  N is prompted for.
+    With a prefix argument ({{{kbd(C-u B S)}}}), scatter only across
+    weekdays.
+
+  - {{{kbd(f)}}} ::
+
+    #+vindex: org-agenda-bulk-custom-functions
+    Apply a function[fn:100] to marked entries.  For example, the
+    function below sets the =CATEGORY= property of the entries to
+    =web=.
+
+    #+begin_src emacs-lisp
+    (defun set-category ()
+      (interactive "P")
+      (let ((marker (or (org-get-at-bol 'org-hd-marker)
+                        (org-agenda-error))))
+        (org-with-point-at marker
+          (org-back-to-heading t)
+          (org-set-property "CATEGORY" "web"))))
+    #+end_src
+
+*** Calendar commands
+:PROPERTIES:
+:UNNUMBERED: notoc
+:END:
+#+cindex: calendar commands, from agenda
+
+- {{{kbd(c)}}} (~org-agenda-goto-calendar~) ::
+
+  #+kindex: c
+  #+findex: org-agenda-goto-calendar
+  Open the Emacs calendar and go to the date at point in the agenda.
+
+- {{{kbd(c)}}} (~org-calendar-goto-agenda~) ::
+
+  #+kindex: c
+  #+findex: org-calendar-goto-agenda
+  When in the calendar, compute and show the Org agenda for the date
+  at point.
+
+- {{{kbd(i)}}} (~org-agenda-diary-entry~) ::
+  #+kindex: i
+  #+findex: org-agenda-diary-entry
+
+  #+cindex: diary entries, creating from agenda
+  Insert a new entry into the diary, using the date at point and (for
+  block entries) the date at the mark.  This adds to the Emacs diary
+  file[fn:101], in a way similar to the {{{kbd(i)}}} command in the
+  calendar.  The diary file pops up in another window, where you can
+  add the entry.
+
+  #+vindex: org-agenda-diary-file
+  If you configure ~org-agenda-diary-file~ to point to an Org file,
+  Org creates entries in that file instead.  Most entries are stored
+  in a date-based outline tree that will later make it easy to archive
+  appointments from previous months/years.  The tree is built under an
+  entry with a =DATE_TREE= property, or else with years as top-level
+  entries.  Emacs prompts you for the entry text---if you specify it,
+  the entry is created in ~org-agenda-diary-file~ without further
+  interaction.  If you directly press {{{kbd(RET)}}} at the prompt
+  without typing text, the target file is shown in another window for
+  you to finish the entry there.  See also the {{{kbd(k r)}}} command.
+
+- {{{kbd(M)}}} (~org-agenda-phases-of-moon~) ::
+
+  #+kindex: M
+  #+findex: org-agenda-phases-of-moon
+  Show the phases of the moon for the three months around current
+  date.
+
+- {{{kbd(S)}}} (~org-agenda-sunrise-sunset~) ::
+
+  #+kindex: S
+  #+findex: org-agenda-sunrise-sunset
+  Show sunrise and sunset times.  The geographical location must be
+  set with calendar variables, see the documentation for the Emacs
+  calendar.
+
+- {{{kbd(C)}}} (~org-agenda-convert-date~) ::
+
+  #+kindex: C
+  #+findex: org-agenda-convert-date
+  Convert the date at point into many other cultural and historic
+  calendars.
+
+- {{{kbd(H)}}} (~org-agenda-holidays~) ::
+
+  #+kindex: H
+  #+findex: org-agenda-holidays
+  Show holidays for three months around point date.
+
+*** Quit and exit
+:PROPERTIES:
+:UNNUMBERED: notoc
+:END:
+
+- {{{kbd(q)}}} (~org-agenda-quit~) ::
+  #+kindex: q
+  #+findex: org-agenda-quit
+
+  Quit agenda, remove the agenda buffer.
+
+- {{{kbd(x)}}} (~org-agenda-exit~) ::
+  #+kindex: x
+  #+findex: org-agenda-exit
+
+  #+cindex: agenda files, removing buffers
+  Exit agenda, remove the agenda buffer and all buffers loaded by
+  Emacs for the compilation of the agenda.  Buffers created by the
+  user to visit Org files are not removed.
+
+** Custom Agenda Views
+:PROPERTIES:
+:DESCRIPTION: Defining special searches and views.
+:END:
+#+cindex: custom agenda views
+#+cindex: agenda views, custom
+
+Custom agenda commands serve two purposes: to store and quickly access
+frequently used TODO and tags searches, and to create special
+composite agenda buffers.  Custom agenda commands are accessible
+through the dispatcher (see [[*The Agenda Dispatcher]]), just like the
+default commands.
+
+*** Storing searches
+:PROPERTIES:
+:DESCRIPTION: Type once, use often.
+:END:
+
+The first application of custom searches is the definition of keyboard
+shortcuts for frequently used searches, either creating an agenda
+buffer, or a sparse tree (the latter covering of course only the
+current buffer).
+
+#+kindex: C @r{(Agenda dispatcher)}
+#+vindex: org-agenda-custom-commands
+#+cindex: agenda views, main example
+#+cindex: agenda, as an agenda views
+#+cindex: agenda*, as an agenda views
+#+cindex: tags, as an agenda view
+#+cindex: todo, as an agenda view
+#+cindex: tags-todo
+#+cindex: todo-tree
+#+cindex: occur-tree
+#+cindex: tags-tree
+Custom commands are configured in the variable
+~org-agenda-custom-commands~.  You can customize this variable, for
+example by pressing {{{kbd(C)}}} from the agenda dispatcher (see [[*The
+Agenda Dispatcher]]).  You can also directly set it with Emacs Lisp in
+the Emacs init file.  The following example contains all valid agenda
+views:
+
+#+begin_src emacs-lisp
+(setq org-agenda-custom-commands
+      '(("x" agenda)
+        ("y" agenda*)
+        ("w" todo "WAITING")
+        ("W" todo-tree "WAITING")
+        ("u" tags "+boss-urgent")
+        ("v" tags-todo "+boss-urgent")
+        ("U" tags-tree "+boss-urgent")
+        ("f" occur-tree "\\<FIXME\\>")
+        ("h" . "HOME+Name tags searches") ;description for "h" prefix
+        ("hl" tags "+home+Lisa")
+        ("hp" tags "+home+Peter")
+        ("hk" tags "+home+Kim")))
+#+end_src
+
+The initial string in each entry defines the keys you have to press
+after the dispatcher command in order to access the command.  Usually
+this is just a single character, but if you have many similar
+commands, you can also define two-letter combinations where the first
+character is the same in several combinations and serves as a prefix
+key[fn:102].  The second parameter is the search type, followed by the
+string or regular expression to be used for the matching.  The example
+above will therefore define:
+
+- {{{kbd(x)}}} ::
+
+  as a global search for agenda entries planned[fn:103] this week/day.
+
+- {{{kbd(y)}}} ::
+
+  as the same search, but only for entries with an hour specification
+  like =[h]h:mm=---think of them as appointments.
+
+- {{{kbd(w)}}} ::
+
+  as a global search for TODO entries with =WAITING= as the TODO
+  keyword.
+
+- {{{kbd(W)}}} ::
+
+  as the same search, but only in the current buffer and displaying
+  the results as a sparse tree.
+
+- {{{kbd(u)}}} ::
+
+  as a global tags search for headlines tagged =boss= but not
+  =urgent=.
+
+- {{{kbd(v)}}} ::
+
+  The same search, but limiting it to headlines that are also TODO
+  items.
+
+- {{{kbd(U)}}} ::
+
+  as the same search, but only in the current buffer and displaying
+  the result as a sparse tree.
+
+- {{{kbd(f)}}} ::
+
+  to create a sparse tree (again, current buffer only) with all
+  entries containing the word =FIXME=.
+
+- {{{kbd(h)}}} ::
+
+  as a prefix command for a =HOME= tags search where you have to press
+  an additional key ({{{kbd(l)}}}, {{{kbd(p)}}} or {{{kbd(k)}}}) to
+  select a name (Lisa, Peter, or Kim) as additional tag to match.
+
+Note that ~*-tree~ agenda views need to be called from an Org buffer
+as they operate on the current buffer only.
+
+*** Block agenda
+:PROPERTIES:
+:DESCRIPTION: All the stuff you need in a single buffer.
+:END:
+#+cindex: block agenda
+#+cindex: agenda, with block views
+
+Another possibility is the construction of agenda views that comprise
+the results of /several/ commands, each of which creates a block in
+the agenda buffer.  The available commands include ~agenda~ for the
+daily or weekly agenda (as created with {{{kbd(a)}}}) , ~alltodo~ for
+the global TODO list (as constructed with {{{kbd(t)}}}), ~stuck~ for
+the list of stuck projects (as obtained with {{{kbd(#)}}}) and the
+matching commands discussed above: ~todo~, ~tags~, and ~tags-todo~.
+
+Here are two examples:
+
+#+begin_src emacs-lisp
+(setq org-agenda-custom-commands
+      '(("h" "Agenda and Home-related tasks"
+         ((agenda "")
+          (tags-todo "home")
+          (tags "garden")))
+        ("o" "Agenda and Office-related tasks"
+         ((agenda "")
+          (tags-todo "work")
+          (tags "office")))))
+#+end_src
+
+#+texinfo: @noindent
+This defines {{{kbd(h)}}} to create a multi-block view for stuff you
+need to attend to at home.  The resulting agenda buffer contains your
+agenda for the current week, all TODO items that carry the tag =home=,
+and also all lines tagged with =garden=.  Finally the command
+{{{kbd(o)}}} provides a similar view for office tasks.
+
+*** Setting options for custom commands
+:PROPERTIES:
+:DESCRIPTION: Changing the rules.
+:ALT_TITLE: Setting options
+:END:
+#+cindex: options, for custom agenda views
+
+#+vindex: org-agenda-custom-commands
+Org mode contains a number of variables regulating agenda construction
+and display.  The global variables define the behavior for all agenda
+commands, including the custom commands.  However, if you want to
+change some settings just for a single custom view, you can do so.
+Setting options requires inserting a list of variable names and values
+at the right spot in ~org-agenda-custom-commands~.  For example:
+
+#+begin_src emacs-lisp
+(setq org-agenda-custom-commands
+      '(("w" todo "WAITING"
+         ((org-agenda-sorting-strategy '(priority-down))
+          (org-agenda-prefix-format "  Mixed: ")))
+        ("U" tags-tree "+boss-urgent"
+         ((org-show-context-detail 'minimal)))
+        ("N" search ""
+         ((org-agenda-files '("~org/notes.org"))
+          (org-agenda-text-search-extra-files nil)))))
+#+end_src
+
+#+texinfo: @noindent
+Now the {{{kbd(w)}}} command sorts the collected entries only by
+priority, and the prefix format is modified to just say =Mixed:=
+instead of giving the category of the entry.  The sparse tags tree of
+{{{kbd(U)}}} now turns out ultra-compact, because neither the headline
+hierarchy above the match, nor the headline following the match are
+shown.  The command {{{kbd(N)}}} does a text search limited to only
+a single file.
+
+For command sets creating a block agenda, ~org-agenda-custom-commands~
+has two separate spots for setting options.  You can add options that
+should be valid for just a single command in the set, and options that
+should be valid for all commands in the set.  The former are just
+added to the command entry; the latter must come after the list of
+command entries.  Going back to the block agenda example (see [[*Block
+agenda]]), let's change the sorting strategy for the {{{kbd(h)}}}
+commands to ~priority-down~, but let's sort the results for =garden=
+tags query in the opposite order, ~priority-up~.  This would look like
+this:
+
+#+begin_src emacs-lisp
+(setq org-agenda-custom-commands
+      '(("h" "Agenda and Home-related tasks"
+         ((agenda)
+          (tags-todo "home")
+          (tags "garden"
+                ((org-agenda-sorting-strategy '(priority-up)))))
+         ((org-agenda-sorting-strategy '(priority-down))))
+        ("o" "Agenda and Office-related tasks"
+         ((agenda)
+          (tags-todo "work")
+          (tags "office")))))
+#+end_src
+
+As you see, the values and parentheses setting is a little complex.
+When in doubt, use the customize interface to set this variable---it
+fully supports its structure.  Just one caveat: when setting options
+in this interface, the /values/ are just Lisp expressions.  So if the
+value is a string, you need to add the double-quotes around the value
+yourself.
+
+#+vindex: org-agenda-custom-commands-contexts
+To control whether an agenda command should be accessible from
+a specific context, you can customize
+~org-agenda-custom-commands-contexts~.  Let's say for example that you
+have an agenda command {{{kbd(o)}}} displaying a view that you only
+need when reading emails.  Then you would configure this option like
+this:
+
+#+begin_src emacs-lisp
+(setq org-agenda-custom-commands-contexts
+      '(("o" (in-mode . "message-mode"))))
+#+end_src
+
+You can also tell that the command key {{{kbd(o)}}} should refer to
+another command key {{{kbd(r)}}}.  In that case, add this command key
+like this:
+
+#+begin_src emacs-lisp
+(setq org-agenda-custom-commands-contexts
+      '(("o" "r" (in-mode . "message-mode"))))
+#+end_src
+
+See the docstring of the variable for more information.
+
+** Exporting Agenda Views
+:PROPERTIES:
+:DESCRIPTION: Writing a view to a file.
+:END:
+#+cindex: agenda views, exporting
+
+If you are away from your computer, it can be very useful to have
+a printed version of some agenda views to carry around.  Org mode can
+export custom agenda views as plain text, HTML[fn:104], Postscript,
+PDF[fn:105], and iCalendar files.  If you want to do this only
+occasionally, use the following command:
+
+- {{{kbd(C-x C-w)}}} (~org-agenda-write~) ::
+  #+kindex: C-x C-w
+  #+findex: org-agenda-write
+  #+cindex: exporting agenda views
+  #+cindex: agenda views, exporting
+
+  #+vindex: org-agenda-exporter-settings
+  Write the agenda view to a file.
+
+If you need to export certain agenda views frequently, you can
+associate any custom agenda command with a list of output file
+names[fn:106].  Here is an example that first defines custom commands
+for the agenda and the global TODO list, together with a number of
+files to which to export them.  Then we define two block agenda
+commands and specify file names for them as well.  File names can be
+relative to the current working directory, or absolute.
+
+#+begin_src emacs-lisp
+(setq org-agenda-custom-commands
+      '(("X" agenda "" nil ("agenda.html" "agenda.ps"))
+        ("Y" alltodo "" nil ("todo.html" "todo.txt" "todo.ps"))
+        ("h" "Agenda and Home-related tasks"
+         ((agenda "")
+          (tags-todo "home")
+          (tags "garden"))
+         nil
+         ("~/views/home.html"))
+        ("o" "Agenda and Office-related tasks"
+         ((agenda)
+          (tags-todo "work")
+          (tags "office"))
+         nil
+         ("~/views/office.ps" "~/calendars/office.ics"))))
+#+end_src
+
+The extension of the file name determines the type of export.  If it
+is =.html=, Org mode uses the htmlize package to convert the buffer to
+HTML and save it to this file name.  If the extension is =.ps=,
+~ps-print-buffer-with-faces~ is used to produce Postscript output.  If
+the extension is =.ics=, iCalendar export is run export over all files
+that were used to construct the agenda, and limit the export to
+entries listed in the agenda.  Any other extension produces a plain
+ASCII file.
+
+The export files are /not/ created when you use one of those
+commands interactively because this might use too much overhead.
+Instead, there is a special command to produce /all/ specified
+files in one step:
+
+- {{{kbd(e)}}} (~org-store-agenda-views~) ::
+
+  #+kindex: e @r{(Agenda dispatcher)}
+  #+findex: org-store-agenda-views
+  Export all agenda views that have export file names associated with
+  them.
+
+You can use the options section of the custom agenda commands to also
+set options for the export commands.  For example:
+
+#+begin_src emacs-lisp
+(setq org-agenda-custom-commands
+      '(("X" agenda ""
+         ((ps-number-of-columns 2)
+          (ps-landscape-mode t)
+          (org-agenda-prefix-format " [ ] ")
+          (org-agenda-with-colors nil)
+          (org-agenda-remove-tags t))
+         ("theagenda.ps"))))
+#+end_src
+
+#+texinfo: @noindent
+#+vindex: org-agenda-exporter-settings
+This command sets two options for the Postscript exporter, to make it
+print in two columns in landscape format---the resulting page can be
+cut in two and then used in a paper agenda.  The remaining settings
+modify the agenda prefix to omit category and scheduling information,
+and instead include a checkbox to check off items.  We also remove the
+tags to make the lines compact, and we do not want to use colors for
+the black-and-white printer.  Settings specified in
+~org-agenda-exporter-settings~ also apply, e.g.,
+
+#+begin_src emacs-lisp
+(setq org-agenda-exporter-settings
+      '((ps-number-of-columns 2)
+        (ps-landscape-mode t)
+        (org-agenda-add-entry-text-maxlines 5)
+        (htmlize-output-type 'css)))
+#+end_src
+
+#+texinfo: @noindent
+but the settings in ~org-agenda-custom-commands~ take precedence.
+
+From the command line you may also use:
+
+#+begin_src shell
+emacs -eval (org-batch-store-agenda-views) -kill
+#+end_src
+
+#+texinfo: @noindent
+or, if you need to modify some parameters[fn:107]
+
+#+begin_src shell
+emacs -eval '(org-batch-store-agenda-views                      \
+              org-agenda-span (quote month)                     \
+              org-agenda-start-day "2007-11-01"                 \
+              org-agenda-include-diary nil                      \
+              org-agenda-files (quote ("~/org/project.org")))'  \
+      -kill
+#+end_src
+
+#+texinfo: @noindent
+which creates the agenda views restricted to the file
+=~/org/project.org=, without diary entries and with a 30-day extent.
+
+You can also extract agenda information in a way that allows further
+processing by other programs.  See [[*Extracting Agenda Information]], for
+more information.
+
+** Using Column View in the Agenda
+:PROPERTIES:
+:DESCRIPTION: Using column view for collected entries.
+:ALT_TITLE: Agenda Column View
+:END:
+#+cindex: column view, in agenda
+#+cindex: agenda, column view
+
+Column view (see [[*Column View]]) is normally used to view and edit
+properties embedded in the hierarchical structure of an Org file.  It
+can be quite useful to use column view also from the agenda, where
+entries are collected by certain criteria.
+
+- {{{kbd(C-c C-x C-c)}}} (~org-agenda-columns~) ::
+  #+kindex: C-c C-x C-c
+  #+findex: org-agenda-columns
+
+  Turn on column view in the agenda.
+
+To understand how to use this properly, it is important to realize
+that the entries in the agenda are no longer in their proper outline
+environment.  This causes the following issues:
+
+1.
+   #+vindex: org-columns-default-format-for-agenda
+   #+vindex: org-columns-default-format
+   Org needs to make a decision which columns format to use.  Since
+   the entries in the agenda are collected from different files, and
+   different files may have different columns formats, this is a
+   non-trivial problem.  Org first checks if
+   ~org-overriding-columns-format~ is currently set, and if so, takes
+   the format from there.  You should set this variable only in the
+   /local settings section/ of a custom agenda command (see [[*Custom
+   Agenda Views]]) to make it valid for that specific agenda view.  If
+   no such binding exists, it checks, in sequence,
+   ~org-columns-default-format-for-agenda~, the format associated with
+   the first item in the agenda (through a property or a =#+COLUMNS=
+   setting in that buffer) and finally ~org-columns-default-format~.
+
+2.
+   #+cindex: @samp{CLOCKSUM}, special property
+   If any of the columns has a summary type defined (see [[*Column
+   attributes]]), turning on column view in the agenda visits all
+   relevant agenda files and make sure that the computations of this
+   property are up to date.  This is also true for the special
+   =CLOCKSUM= property.  Org then sums the values displayed in the
+   agenda.  In the daily/weekly agenda, the sums cover a single day;
+   in all other views they cover the entire block.
+
+   It is important to realize that the agenda may show the same entry
+   /twice/---for example as scheduled and as a deadline---and it may
+   show two entries from the same hierarchy (for example a /parent/
+   and its /child/).  In these cases, the summation in the agenda
+   leads to incorrect results because some values count double.
+
+3. When the column view in the agenda shows the =CLOCKSUM= property,
+   that is always the entire clocked time for this item.  So even in
+   the daily/weekly agenda, the clocksum listed in column view may
+   originate from times outside the current view.  This has the
+   advantage that you can compare these values with a column listing
+   the planned total effort for a task---one of the major
+   applications for column view in the agenda.  If you want
+   information about clocked time in the displayed period use clock
+   table mode (press {{{kbd(R)}}} in the agenda).
+
+4.
+   #+cindex: @samp{CLOCKSUM_T}, special property
+   When the column view in the agenda shows the =CLOCKSUM_T= property,
+   that is always today's clocked time for this item.  So even in the
+   weekly agenda, the clocksum listed in column view only originates
+   from today.  This lets you compare the time you spent on a task for
+   today, with the time already spent---via =CLOCKSUM=---and with
+   the planned total effort for it.
+
+* Markup for Rich Contents
+:PROPERTIES:
+:DESCRIPTION: Compose beautiful documents.
+:END:
+
+Org is primarily about organizing and searching through your
+plain-text notes.  However, it also provides a lightweight yet robust
+markup language for rich text formatting and more.  For instance, you
+may want to center or emphasize text.  Or you may need to insert
+a formula or image in your writing.  Org offers syntax for all of this
+and more.  Used in conjunction with the export framework (see
+[[*Exporting]]), you can author beautiful documents in Org---like the fine
+manual you are currently reading.
+
+** Paragraphs
+:PROPERTIES:
+:DESCRIPTION: The basic unit of text.
+:END:
+
+#+cindex: paragraphs, markup rules
+Paragraphs are separated by at least one empty line.  If you need to
+enforce a line break within a paragraph, use =\\= at the end of
+a line.
+
+#+cindex: line breaks, markup rules
+To preserve the line breaks, indentation and blank lines in a region,
+but otherwise use normal formatting, you can use this construct, which
+can also be used to format poetry.
+
+#+cindex: @samp{BEGIN_VERSE}
+#+cindex: verse blocks
+#+begin_example
+,#+BEGIN_VERSE
+ Great clouds overhead
+ Tiny black birds rise and fall
+ Snow covers Emacs
+
+    ---AlexSchroeder
+,#+END_VERSE
+#+end_example
+
+When quoting a passage from another document, it is customary to
+format this as a paragraph that is indented on both the left and the
+right margin.  You can include quotations in Org documents like this:
+
+#+cindex: @samp{BEGIN_QUOTE}
+#+cindex: quote blocks
+#+begin_example
+,#+BEGIN_QUOTE
+Everything should be made as simple as possible,
+but not any simpler ---Albert Einstein
+,#+END_QUOTE
+#+end_example
+
+If you would like to center some text, do it like this:
+
+#+cindex: @samp{BEGIN_CENTER}
+#+cindex: center blocks
+#+begin_example
+,#+BEGIN_CENTER
+Everything should be made as simple as possible, \\
+but not any simpler
+,#+END_CENTER
+#+end_example
+
+** Emphasis and Monospace
+:PROPERTIES:
+:DESCRIPTION: Bold, italic, etc.
+:END:
+#+cindex: underlined text, markup rules
+#+cindex: bold text, markup rules
+#+cindex: italic text, markup rules
+#+cindex: verbatim text, markup rules
+#+cindex: code text, markup rules
+#+cindex: strike-through text, markup rules
+
+You can make words =*bold*=, =/italic/=, =_underlined_=, ==verbatim==
+and =~code~=, and, if you must, =+strike-through+=.  Text in the code
+and verbatim string is not processed for Org specific syntax; it is
+exported verbatim.
+
+#+vindex: org-fontify-emphasized-text
+To turn off fontification for marked up text, you can set
+~org-fontify-emphasized-text~ to ~nil~.  To narrow down the list of
+available markup syntax, you can customize ~org-emphasis-alist~.
+
+** Subscripts and Superscripts
+:PROPERTIES:
+:DESCRIPTION: Simple syntax for raising/lowering text.
+:END:
+#+cindex: subscript
+#+cindex: superscript
+
+=^= and =_= are used to indicate super- and subscripts.  To increase
+the readability of ASCII text, it is not necessary, but OK, to
+surround multi-character sub- and superscripts with curly braces.  For
+example
+
+#+begin_example
+The radius of the sun is R_sun = 6.96 x 10^8 m.  On the other hand,
+the radius of Alpha Centauri is R_{Alpha Centauri} = 1.28 x R_{sun}.
+#+end_example
+
+#+vindex: org-use-sub-superscripts
+If you write a text where the underscore is often used in a different
+context, Org's convention to always interpret these as subscripts can
+get in your way.  Configure the variable ~org-use-sub-superscripts~ to
+change this convention.  For example, when setting this variable to
+~{}~, =a_b= is not interpreted as a subscript, but =a_{b}= is.
+
+You can set ~org-use-sub-superscripts~ in a file using the export
+option =^:= (see [[*Export Settings][Export Settings]]).  For example, 
=#+OPTIONS: ^:{}=
+sets ~org-use-sub-superscripts~ to ~{}~ and limits super- and
+subscripts to the curly bracket notation.
+
+You can also toggle the visual display of super- and subscripts:
+
+- {{{kbd(C-c C-x \)}}} (~org-toggle-pretty-entities~) ::
+
+  #+kindex: C-c C-x \
+  #+findex: org-toggle-pretty-entities
+  This command formats sub- and superscripts in a WYSIWYM way.
+
+#+vindex: org-pretty-entities
+#+vindex: org-pretty-entities-include-sub-superscripts
+Set both ~org-pretty-entities~ and
+~org-pretty-entities-include-sub-superscripts~ to ~t~ to start with
+super- and subscripts /visually/ interpreted as specified by the
+option ~org-use-sub-superscripts~.
+
+** Special Symbols
+:PROPERTIES:
+:DESCRIPTION: Greek letters and other symbols.
+:END:
+#+cindex: math symbols
+#+cindex: special symbols
+#+cindex: entities
+
+You can use LaTeX-like syntax to insert special symbols---named
+entities---like =\alpha= to indicate the Greek letter, or =\to= to indicate
+an arrow.  Completion for these symbols is available, just type =\=
+and maybe a few letters, and press {{{kbd(M-TAB)}}} to see possible
+completions.  If you need such a symbol inside a word, terminate it
+with a pair of curly brackets.  For example
+
+#+begin_example
+Pro tip: Given a circle \Gamma of diameter d, the length of its
+circumference is \pi{}d.
+#+end_example
+
+#+findex: org-entities-help
+#+vindex: org-entities-user
+A large number of entities is provided, with names taken from both
+HTML and LaTeX; you can comfortably browse the complete list from
+a dedicated buffer using the command ~org-entities-help~.  It is also
+possible to provide your own special symbols in the variable
+~org-entities-user~.
+
+During export, these symbols are transformed into the native format of
+the exporter back-end.  Strings like =\alpha= are exported as =&alpha;= in
+the HTML output, and as =\(\alpha\)= in the LaTeX output.  Similarly, =\nbsp=
+becomes =&nbsp;= in HTML and =~= in LaTeX.
+
+#+cindex: special symbols, in-buffer display
+If you would like to see entities displayed as UTF-8 characters, use
+the following command[fn:108]:
+
+- {{{kbd(C-c C-x \)}}} (~org-toggle-pretty-entities~) ::
+  #+kindex: C-c C-x \
+  #+findex: org-toggle-pretty-entities
+
+  Toggle display of entities as UTF-8 characters.  This does not
+  change the buffer content which remains plain ASCII, but it overlays
+  the UTF-8 character for display purposes only.
+
+#+cindex: shy hyphen, special symbol
+#+cindex: dash, special symbol
+#+cindex: ellipsis, special symbol
+In addition to regular entities defined above, Org exports in
+a special way[fn:109] the following commonly used character
+combinations: =\-= is treated as a shy hyphen, =--= and =---= are
+converted into dashes, and =...= becomes a compact set of dots.
+
+** Embedded LaTeX
+:PROPERTIES:
+:DESCRIPTION: LaTeX can be freely used inside Org documents.
+:END:
+#+cindex: @TeX{} interpretation
+#+cindex: @LaTeX{} interpretation
+
+Plain ASCII is normally sufficient for almost all note taking.
+Exceptions include scientific notes, which often require mathematical
+symbols and the occasional formula.  LaTeX[fn:110] is widely used to
+typeset scientific documents.  Org mode supports embedding LaTeX code
+into its files, because many academics are used to writing and reading
+LaTeX source code, and because it can be readily processed to produce
+pretty output for a number of export back-ends.
+
+*** LaTeX fragments
+:PROPERTIES:
+:DESCRIPTION: Complex formulas made easy.
+:END:
+#+cindex: @LaTeX{} fragments
+
+#+vindex: org-format-latex-header
+Org mode can contain LaTeX math fragments, and it supports ways to
+process these for several export back-ends.  When exporting to LaTeX,
+the code is left as it is.  When exporting to HTML, Org can use either
+[[http://www.mathjax.org][MathJax]] (see [[*Math formatting in HTML export]]) 
or transcode the math
+into images (see [[*Previewing LaTeX fragments]]).
+
+LaTeX fragments do not need any special marking at all.  The following
+snippets are identified as LaTeX source code:
+
+- Environments of any kind[fn:111].  The only requirement is that the
+  =\begin= statement appears on a new line, preceded by only
+  whitespace.
+
+- Text within the usual LaTeX math delimiters.  To avoid conflicts
+  with currency specifications, single =$= characters are only
+  recognized as math delimiters if the enclosed text contains at most
+  two line breaks, is directly attached to the =$= characters with no
+  whitespace in between, and if the closing =$= is followed by
+  whitespace, punctuation or a dash.  For the other delimiters, there
+  is no such restriction, so when in doubt, use =\(...\)= as inline
+  math delimiters.
+
+#+texinfo: @noindent
+For example:
+
+#+begin_example
+\begin{equation}                        % arbitrary environments,
+x=\sqrt{b}                              % even tables, figures
+\end{equation}                          % etc
+
+If $a^2=b$ and \( b=2 \), then the solution must be
+either $$ a=+\sqrt{2} $$ or \[ a=-\sqrt{2} \].
+#+end_example
+
+#+vindex: org-export-with-latex
+LaTeX processing can be configured with the variable
+~org-export-with-latex~.  The default setting is ~t~ which means
+MathJax for HTML, and no processing for ASCII and LaTeX back-ends.
+You can also set this variable on a per-file basis using one of these
+lines:
+
+| =#+OPTIONS: tex:t=        | Do the right thing automatically (MathJax) |
+| =#+OPTIONS: tex:nil=      | Do not process LaTeX fragments at all      |
+| =#+OPTIONS: tex:verbatim= | Verbatim export, for jsMath or so          |
+
+*** Previewing LaTeX fragments
+:PROPERTIES:
+:DESCRIPTION: What will this snippet look like?
+:END:
+#+cindex: @LaTeX{} fragments, preview
+
+#+vindex: org-preview-latex-default-process
+If you have a working LaTeX installation and =dvipng=, =dvisvgm= or
+=convert= installed[fn:112], LaTeX fragments can be processed to
+produce images of the typeset expressions to be used for inclusion
+while exporting to HTML (see [[*LaTeX fragments]]), or for inline
+previewing within Org mode.
+
+#+vindex: org-format-latex-options
+#+vindex: org-format-latex-header
+You can customize the variables ~org-format-latex-options~ and
+~org-format-latex-header~ to influence some aspects of the preview.
+In particular, the ~:scale~ (and for HTML export, ~:html-scale~)
+property of the former can be used to adjust the size of the preview
+images.
+
+- {{{kbd(C-c C-x C-l)}}} (~org-latex-preview~) ::
+  #+kindex: C-c C-x C-l
+  #+findex: org-latex-preview
+
+  Produce a preview image of the LaTeX fragment at point and overlay
+  it over the source code.  If there is no fragment at point, process
+  all fragments in the current entry---between two headlines.
+
+  When called with a single prefix argument, clear all images in the
+  current entry.  Two prefix arguments produce a preview image for all
+  fragments in the buffer, while three of them clear all the images in
+  that buffer.
+
+#+vindex: org-startup-with-latex-preview
+You can turn on the previewing of all LaTeX fragments in a file with
+
+: #+STARTUP: latexpreview
+
+To disable it, simply use
+
+: #+STARTUP: nolatexpreview
+
+*** Using CDLaTeX to enter math
+:PROPERTIES:
+:DESCRIPTION: Speed up entering of formulas.
+:ALT_TITLE: CDLaTeX mode
+:END:
+#+cindex: CD@LaTeX{}
+
+CDLaTeX mode is a minor mode that is normally used in combination with
+a major LaTeX mode like AUCTeX in order to speed-up insertion of
+environments and math templates.  Inside Org mode, you can make use of
+some of the features of CDLaTeX mode.  You need to install
+=cdlatex.el= and =texmathp.el= (the latter comes also with AUCTeX)
+using [[https://melpa.org/][MELPA]] with the 
[[https://www.gnu.org/software/emacs/manual/html_node/emacs/Package-Installation.html][Emacs
 packaging system]] or alternatively from
+[[https://staff.fnwi.uva.nl/c.dominik/Tools/cdlatex/]].  Do not use
+CDLaTeX mode itself under Org mode, but use the special version Org
+CDLaTeX minor mode that comes as part of Org.  Turn it on for the
+current buffer with {{{kbd(M-x org-cdlatex-mode)}}}, or for all Org
+files with
+
+#+begin_src emacs-lisp
+(add-hook 'org-mode-hook 'turn-on-org-cdlatex)
+#+end_src
+
+When this mode is enabled, the following features are present (for
+more details see the documentation of CDLaTeX mode):
+
+#+attr_texinfo: :sep ,
+- {{{kbd(C-c {)}}} ::
+  #+kindex: C-c @{
+
+  Insert an environment template.
+
+- {{{kbd(TAB)}}} ::
+  #+kindex: TAB
+
+  The {{{kbd(TAB)}}} key expands the template if point is inside
+  a LaTeX fragment[fn:113].  For example, {{{kbd(TAB)}}} expands =fr=
+  to =\frac{}{}= and position point correctly inside the first brace.
+  Another {{{kbd(TAB)}}} gets you into the second brace.
+
+  Even outside fragments, {{{kbd(TAB)}}} expands environment
+  abbreviations at the beginning of a line.  For example, if you write
+  =equ= at the beginning of a line and press {{{kbd(TAB)}}}, this
+  abbreviation is expanded to an =equation= environment.  To get
+  a list of all abbreviations, type {{{kbd(M-x
+  cdlatex-command-help)}}}.
+
+- {{{kbd(^)}}}, {{{kbd(_)}}} ::
+  #+kindex: _
+  #+kindex: ^
+  #+vindex: cdlatex-simplify-sub-super-scripts
+
+  Pressing {{{kbd(_)}}} and {{{kbd(^)}}} inside a LaTeX fragment
+  inserts these characters together with a pair of braces.  If you use
+  {{{kbd(TAB)}}} to move out of the braces, and if the braces surround
+  only a single character or macro, they are removed again (depending
+  on the variable ~cdlatex-simplify-sub-super-scripts~).
+
+- {{{kbd(`)}}} ::
+  #+kindex: `
+
+  Pressing the backquote followed by a character inserts math macros,
+  also outside LaTeX fragments.  If you wait more than 1.5 seconds
+  after the backquote, a help window pops up.
+
+- {{{kbd(')}}} ::
+  #+kindex: '
+
+  Pressing the single-quote followed by another character modifies the
+  symbol before point with an accent or a font.  If you wait more than
+  1.5 seconds after the single-quote, a help window pops up.
+  Character modification works only inside LaTeX fragments; outside
+  the quote is normal.
+
+** Literal Examples
+:PROPERTIES:
+:DESCRIPTION: Source code examples with special formatting.
+:END:
+#+cindex: literal examples, markup rules
+#+cindex: code line references, markup rules
+
+You can include literal examples that should not be subjected to
+markup.  Such examples are typeset in monospace, so this is well
+suited for source code and similar examples.
+
+#+cindex: @samp{BEGIN_EXAMPLE}
+#+cindex: example block
+#+begin_example
+,#+BEGIN_EXAMPLE
+  Some example from a text file.
+,#+END_EXAMPLE
+#+end_example
+
+#+cindex: comma escape, in literal examples
+There is one limitation, however.  You must insert a comma right
+before lines starting with either =*=, =,*=, =#+= or =,#+=, as those
+may be interpreted as outlines nodes or some other special syntax.
+Org transparently strips these additional commas whenever it accesses
+the contents of the block.
+
+#+begin_example
+,#+BEGIN_EXAMPLE
+,,* I am no real headline
+,#+END_EXAMPLE
+#+end_example
+
+For simplicity when using small examples, you can also start the
+example lines with a colon followed by a space.  There may also be
+additional whitespace before the colon:
+
+#+begin_example
+Here is an example
+   : Some example from a text file.
+#+end_example
+
+#+cindex: formatting source code, markup rules
+#+vindex: org-latex-listings
+If the example is source code from a programming language, or any
+other text that can be marked up by Font Lock in Emacs, you can ask
+for the example to look like the fontified Emacs buffer[fn:114].  This
+is done with the code block, where you also need to specify the name
+of the major mode that should be used to fontify the example[fn:115],
+see [[*Structure Templates]] for shortcuts to easily insert code blocks.
+
+#+cindex: @samp{BEGIN_SRC}
+#+cindex: source block
+#+begin_example
+,#+BEGIN_SRC emacs-lisp
+  (defun org-xor (a b)
+    "Exclusive or."
+    (if a (not b) b))
+ ,#+END_SRC
+#+end_example
+
+Both in =example= and in =src= snippets, you can add a =-n= switch to
+the end of the =#+BEGIN= line, to get the lines of the example
+numbered.  The =-n= takes an optional numeric argument specifying the
+starting line number of the block.  If you use a =+n= switch, the
+numbering from the previous numbered snippet is continued in the
+current one.  The =+n= switch can also take a numeric argument.  This
+adds the value of the argument to the last line of the previous block
+to determine the starting line number.
+
+#+begin_example
+,#+BEGIN_SRC emacs-lisp -n 20
+  ;; This exports with line number 20.
+  (message "This is line 21")
+,#+END_SRC
+
+,#+BEGIN_SRC emacs-lisp +n 10
+  ;; This is listed as line 31.
+  (message "This is line 32")
+,#+END_SRC
+#+end_example
+
+In literal examples, Org interprets strings like =(ref:name)= as
+labels, and use them as targets for special hyperlinks like
+=[[(name)]]=---i.e., the reference name enclosed in single parenthesis.
+In HTML, hovering the mouse over such a link remote-highlights the
+corresponding code line, which is kind of cool.
+
+You can also add a =-r= switch which /removes/ the labels from the
+source code[fn:116].  With the =-n= switch, links to these references
+are labeled by the line numbers from the code listing.  Otherwise
+links use the labels with no parentheses.  Here is an example:
+
+#+begin_example -l "(dumb-reference:%s)"
+,#+BEGIN_SRC emacs-lisp -n -r
+  (save-excursion                 (ref:sc)
+     (goto-char (point-min))      (ref:jump)
+,#+END_SRC
+In line [[(sc)]] we remember the current position. [[(jump)][Line (jump)]]
+jumps to point-min.
+#+end_example
+
+#+cindex: indentation, in source blocks
+Source code and examples may be /indented/ in order to align nicely
+with the surrounding text, and in particular with plain list structure
+(see [[*Plain Lists]]).  By default, Org only retains the relative
+indentation between lines, e.g., when exporting the contents of the
+block.  However, you can use the =-i= switch to also preserve the
+global indentation, if it does matter.  See [[*Editing Source Code]].
+
+#+vindex: org-coderef-label-format
+If the syntax for the label format conflicts with the language syntax,
+use a =-l= switch to change the format, for example
+
+: #+BEGIN_SRC pascal -n -r -l "((%s))"
+
+#+texinfo: @noindent
+See also the variable ~org-coderef-label-format~.
+
+HTML export also allows examples to be published as text areas (see
+[[*Text areas in HTML export]]).
+
+Because the =#+BEGIN= ... =#+END= patterns need to be added so often,
+a shortcut is provided (see [[*Structure Templates]]).
+
+- {{{kbd(C-c ')}}} (~org-edit-special~) ::
+
+  #+kindex: C-c '
+  #+findex: org-edit-special
+  Edit the source code example at point in its native mode.  This
+  works by switching to a temporary buffer with the source code.  You
+  need to exit by pressing {{{kbd(C-c ')}}} again.  The edited version
+  then replaces the old version in the Org buffer.  Fixed-width
+  regions---where each line starts with a colon followed by
+  a space---are edited using Artist mode[fn:117] to allow creating
+  ASCII drawings easily.  Using this command in an empty line creates
+  a new fixed-width region.
+
+#+cindex: storing link, in a source code buffer
+Calling ~org-store-link~ (see [[*Handling Links]]) while editing a source
+code example in a temporary buffer created with {{{kbd(C-c ')}}}
+prompts for a label.  Make sure that it is unique in the current
+buffer, and insert it with the proper formatting like =(ref:label)= at
+the end of the current line.  Then the label is stored as a link
+=(label)=, for retrieval with {{{kbd(C-c C-l)}}}.
+
+** Images
+:PROPERTIES:
+:DESCRIPTION: Display an image.
+:END:
+
+#+cindex: inlining images
+#+cindex: images, markup rules
+An image is a link to an image file[fn:118] that does not have
+a description part, for example
+
+: ./img/cat.jpg
+
+If you wish to define a caption for the image (see [[*Captions]]) and
+maybe a label for internal cross references (see [[*Internal Links]]),
+make sure that the link is on a line by itself and precede it with
+=CAPTION= and =NAME= keywords as follows:
+
+#+begin_example
+,#+CAPTION: This is the caption for the next figure link (or table)
+,#+NAME:   fig:SED-HR4049
+[[./img/a.jpg]]
+#+end_example
+
+Such images can be displayed within the buffer with the following
+command:
+
+- {{{kbd(C-c C-x C-v)}}} (~org-toggle-inline-images~) ::
+
+  #+kindex: C-c C-x C-v
+  #+findex: org-toggle-inline-images
+  #+vindex: org-startup-with-inline-images
+  Toggle the inline display of linked images.  When called with
+  a prefix argument, also display images that do have a link
+  description.  You can ask for inline images to be displayed at
+  startup by configuring the variable
+  ~org-startup-with-inline-images~[fn:119].
+
+** Captions
+:PROPERTIES:
+:DESCRIPTION: Describe tables, images...
+:END:
+#+cindex: captions, markup rules
+#+cindex: @samp{CAPTION}, keyword
+
+You can assign a caption to a specific part of a document by inserting
+a =CAPTION= keyword immediately before it:
+
+#+begin_example
+,#+CAPTION: This is the caption for the next table (or link)
+| ... | ... |
+|-----+-----|
+#+end_example
+
+Optionally, the caption can take the form:
+
+: #+CAPTION[Short caption]: Longer caption.
+
+Even though images and tables are prominent examples of captioned
+structures, the same caption mechanism can apply to many
+others---e.g., LaTeX equations, source code blocks.  Depending on the
+export back-end, those may or may not be handled.
+
+** Horizontal Rules
+:PROPERTIES:
+:DESCRIPTION: Make a line.
+:END:
+
+#+cindex: horizontal rules, markup rules
+A line consisting of only dashes, and at least 5 of them, is exported
+as a horizontal line.
+
+** Creating Footnotes
+:PROPERTIES:
+:DESCRIPTION: Edit and read footnotes.
+:END:
+#+cindex: footnotes
+
+A footnote is started by a footnote marker in square brackets in
+column 0, no indentation allowed.  It ends at the next footnote
+definition, headline, or after two consecutive empty lines.  The
+footnote reference is simply the marker in square brackets, inside
+text.  Markers always start with =fn:=.  For example:
+
+#+begin_example
+The Org homepage[fn:1] now looks a lot better than it used to.
+...
+[fn:1] The link is: https://orgmode.org
+#+end_example
+
+Org mode extends the number-based syntax to /named/ footnotes and
+optional inline definition.  Here are the valid references:
+
+- =[fn:NAME]= ::
+
+  A named footnote reference, where {{{var(NAME)}}} is a unique
+  label word, or, for simplicity of automatic creation, a number.
+
+- =[fn:: This is the inline definition of this footnote]= ::
+
+  An anonymous footnote where the definition is given directly at the
+  reference point.
+
+- =[fn:NAME: a definition]= ::
+
+  An inline definition of a footnote, which also specifies a name for
+  the note.  Since Org allows multiple references to the same note,
+  you can then use =[fn:NAME]= to create additional references.
+
+#+vindex: org-footnote-auto-label
+Footnote labels can be created automatically, or you can create names
+yourself.  This is handled by the variable ~org-footnote-auto-label~
+and its corresponding =STARTUP= keywords.  See the docstring of that
+variable for details.
+
+The following command handles footnotes:
+
+- {{{kbd(C-c C-x f)}}} ::
+
+  The footnote action command.
+
+  #+kindex: C-c C-x f
+  When point is on a footnote reference, jump to the definition.  When
+  it is at a definition, jump to the---first---reference.
+
+  #+vindex: org-footnote-define-inline
+  #+vindex: org-footnote-section
+  Otherwise, create a new footnote.  Depending on the variable
+  ~org-footnote-define-inline~[fn:120], the definition is placed right
+  into the text as part of the reference, or separately into the
+  location determined by the variable ~org-footnote-section~.
+
+  When this command is called with a prefix argument, a menu of
+  additional options is offered:
+
+  #+attr_texinfo: :columns 0.1 0.9
+  | {{{kbd(s)}}} | Sort the footnote definitions by reference sequence.        
       |
+  | {{{kbd(r)}}} | Renumber the simple =fn:N= footnotes.                       
       |
+  | {{{kbd(S)}}} | Short for first {{{kbd(r)}}}, then {{{kbd(s)}}} action.     
       |
+  | {{{kbd(n)}}} | Rename all footnotes into a =fn:1= ... =fn:n= sequence.     
       |
+  | {{{kbd(d)}}} | Delete the footnote at point, including definition and 
references. |
+
+  #+vindex: org-footnote-auto-adjust
+  Depending on the variable ~org-footnote-auto-adjust~[fn:121],
+  renumbering and sorting footnotes can be automatic after each
+  insertion or deletion.
+
+- {{{kbd(C-c C-c)}}} ::
+
+  #+kindex: C-c C-c
+  If point is on a footnote reference, jump to the definition.  If it
+  is at the definition, jump back to the reference.  When called at
+  a footnote location with a prefix argument, offer the same menu as
+  {{{kbd(C-c C-x f)}}}.
+
+- {{{kbd(C-c C-o)}}} or {{{kbd(mouse-1/2)}}} ::
+
+  #+kindex: C-c C-o
+  #+kindex: mouse-1
+  #+kindex: mouse-2
+  Footnote labels are also links to the corresponding definition or
+  reference, and you can use the usual commands to follow these links.
+
+* Exporting
+:PROPERTIES:
+:DESCRIPTION: Sharing and publishing notes.
+:END:
+#+cindex: exporting
+
+At some point you might want to print your notes, publish them on the
+web, or share them with people not using Org.  Org can convert and
+export documents to a variety of other formats while retaining as much
+structure (see [[*Document Structure]]) and markup (see [[*Markup for Rich
+Contents]]) as possible.
+
+#+cindex: export back-end
+The libraries responsible for translating Org files to other formats
+are called /back-ends/.  Org ships with support for the following
+back-ends:
+
+- /ascii/ (ASCII format)
+- /beamer/ (LaTeX Beamer format)
+- /html/ (HTML format)
+- /icalendar/ (iCalendar format)
+- /latex/ (LaTeX format)
+- /md/ (Markdown format)
+- /odt/ (OpenDocument Text format)
+- /org/ (Org format)
+- /texinfo/ (Texinfo format)
+- /man/ (Man page format)
+
+Users can install libraries for additional formats from the Emacs
+packaging system.  For easy discovery, these packages have a common
+naming scheme: ~ox-NAME~, where {{{var(NAME)}}} is a format.  For
+example, ~ox-koma-letter~ for /koma-letter/ back-end.  More libraries
+can be found in the =contrib/= directory (see [[*Installation]]).
+
+#+vindex: org-export-backends
+Org only loads back-ends for the following formats by default: ASCII,
+HTML, iCalendar, LaTeX, and ODT.  Additional back-ends can be loaded
+in either of two ways: by configuring the ~org-export-backends~
+variable, or by requiring libraries in the Emacs init file.  For
+example, to load the Markdown back-end, add this to your Emacs config:
+
+#+begin_src emacs-lisp
+(require 'ox-md)
+#+end_src
+
+** The Export Dispatcher
+:PROPERTIES:
+:DESCRIPTION: The main interface.
+:END:
+#+cindex: dispatcher, for export commands
+#+cindex: export, dispatcher
+
+The export dispatcher is the main interface for Org's exports.
+A hierarchical menu presents the currently configured export formats.
+Options are shown as easy toggle switches on the same screen.
+
+#+vindex: org-export-dispatch-use-expert-ui
+Org also has a minimal prompt interface for the export dispatcher.
+When the variable ~org-export-dispatch-use-expert-ui~ is set to
+a non-~nil~ value, Org prompts in the minibuffer.  To switch back to
+the hierarchical menu, press {{{kbd(?)}}}.
+
+- {{{kbd(C-c C-e)}}} (~org-export~) ::
+  #+kindex: C-c C-e
+  #+findex: org-export
+
+  Invokes the export dispatcher interface.  The options show default
+  settings.  The {{{kbd(C-u)}}} prefix argument preserves options from
+  the previous export, including any sub-tree selections.
+
+Org exports the entire buffer by default.  If the Org buffer has an
+active region, then Org exports just that region.
+
+Within the dispatcher interface, the following key combinations can
+further alter what is exported, and how.
+
+- {{{kbd(C-a)}}} ::
+  #+kindex: C-c C-e C-a
+
+  Toggle asynchronous export.  Asynchronous export uses an external
+  Emacs process with a specially configured initialization file to
+  complete the exporting process in the background, without tying-up
+  Emacs.  This is particularly useful when exporting long documents.
+
+  Output from an asynchronous export is saved on the /export stack/.
+  To view this stack, call the export dispatcher with a double
+  {{{kbd(C-u)}}} prefix argument.  If already in the export dispatcher
+  menu, {{{kbd(&)}}} displays the stack.
+
+  #+vindex: org-export-in-background
+  You can make asynchronous export the default by setting
+  ~org-export-in-background~.
+
+  #+vindex: org-export-async-init-file
+  You can set the initialization file used by the background process
+  by setting ~org-export-async-init-file~.
+
+- {{{kbd(C-b)}}} ::
+  #+kindex: C-c C-e C-b
+
+  Toggle body-only export.  Useful for excluding headers and footers
+  in the export.  Affects only those back-end formats that have
+  sections like =<head>...</head>= in HTML.
+
+- {{{kbd(C-s)}}} ::
+  #+kindex: C-c C-e C-s
+
+  Toggle sub-tree export.  When turned on, Org exports only the
+  sub-tree starting from point position at the time the export
+  dispatcher was invoked.  Org uses the top heading of this sub-tree
+  as the document's title.  If point is not on a heading, Org uses the
+  nearest enclosing header.  If point is in the document preamble, Org
+  signals an error and aborts export.
+
+  #+vindex: org-export-initial-scope
+  To make sub-tree export the default, customize the variable
+  ~org-export-initial-scope~.
+
+- {{{kbd(C-v)}}} ::
+  #+kindex: C-c C-e C-v
+
+  Toggle visible-only export.  This is useful for exporting only
+  certain parts of an Org document by adjusting the visibility of
+  particular headings.
+
+** Export Settings
+:PROPERTIES:
+:DESCRIPTION: Common export settings.
+:END:
+#+cindex: options, for export
+#+cindex: Export, settings
+
+#+cindex: @samp{OPTIONS}, keyword
+Export options can be set: globally with variables; for an individual
+file by making variables buffer-local with in-buffer settings (see
+[[*Summary of In-Buffer Settings]]); by setting individual keywords or
+specifying them in compact form with the =OPTIONS= keyword; or for
+a tree by setting properties (see [[*Properties and Columns]]).  Options
+set at a specific level override options set at a more general level.
+
+#+cindex: @samp{SETUPFILE}, keyword
+In-buffer settings may appear anywhere in the file, either directly or
+indirectly through a file included using =#+SETUPFILE: filename or
+URL= syntax.  Option keyword sets tailored to a particular back-end
+can be inserted from the export dispatcher (see [[*The Export
+Dispatcher]]) using the =Insert template= command by pressing
+{{{kbd(#)}}}.  To insert keywords individually, a good way to make
+sure the keyword is correct is to type =#+= and then to use
+{{{kbd(M-TAB)}}}[fn:16] for completion.
+
+The export keywords available for every back-end, and their equivalent
+global variables, include:
+
+- =AUTHOR= ::
+
+  #+cindex: @samp{AUTHOR}, keyword
+  #+vindex: user-full-name
+  The document author (~user-full-name~).
+
+- =CREATOR= ::
+
+  #+cindex: @samp{CREATOR}, keyword
+  #+vindex: org-expot-creator-string
+  Entity responsible for output generation
+  (~org-export-creator-string~).
+
+- =DATE= ::
+
+  #+cindex: @samp{DATE}, keyword
+  #+vindex: org-export-date-timestamp-format
+  A date or a time-stamp[fn:122].
+
+- =EMAIL= ::
+
+  #+cindex: @samp{EMAIL}, keyword
+  #+vindex: user-mail-address
+  The email address (~user-mail-address~).
+
+- =LANGUAGE= ::
+
+  #+cindex: @samp{LANGUAGE}, keyword
+  #+vindex: org-export-default-language
+  Language to use for translating certain strings
+  (~org-export-default-language~).  With =#+LANGUAGE: fr=, for
+  example, Org translates =Table of contents= to the French =Table des
+  matières=[fn:123].
+
+- =SELECT_TAGS= ::
+
+  #+cindex: @samp{SELECT_TAGS}, keyword
+  #+vindex: org-export-select-tags
+  The default value is =("export")=.  When a tree is tagged with
+  =export= (~org-export-select-tags~), Org selects that tree and its
+  sub-trees for export.  Org excludes trees with =noexport= tags, see
+  below.  When selectively exporting files with =export= tags set, Org
+  does not export any text that appears before the first headline.
+
+- =EXCLUDE_TAGS= ::
+
+  #+cindex: @samp{EXCLUDE_TAGS}, keyword
+  #+vindex: org-export-exclude-tags
+  The default value is =("noexport")=.  When a tree is tagged with
+  =noexport= (~org-export-exclude-tags~), Org excludes that tree and
+  its sub-trees from export.  Entries tagged with =noexport= are
+  unconditionally excluded from the export, even if they have an
+  =export= tag.  Even if a sub-tree is not exported, Org executes any
+  code blocks contained there.
+
+- =TITLE= ::
+
+  #+cindex: @samp{TITLE}, keyword
+  #+cindex: document title
+  Org displays this title.  For long titles, use multiple =#+TITLE=
+  lines.
+
+- =EXPORT_FILE_NAME= ::
+
+  #+cindex: @samp{EXPORT_FILE_NAME}, keyword
+  The name of the output file to be generated.  Otherwise, Org
+  generates the file name based on the buffer name and the extension
+  based on the back-end format.
+
+The =OPTIONS= keyword is a compact form.  To configure multiple
+options, use several =OPTIONS= lines.  =OPTIONS= recognizes the
+following arguments.
+
+- ~'~ ::
+
+  #+vindex: org-export-with-smart-quotes
+  Toggle smart quotes (~org-export-with-smart-quotes~).  Depending on
+  the language used, when activated, Org treats pairs of double quotes
+  as primary quotes, pairs of single quotes as secondary quotes, and
+  single quote marks as apostrophes.
+
+- ~*~ ::
+
+  #+vindex: org-export-with-emphasize
+  Toggle emphasized text (~org-export-with-emphasize~).
+
+- ~-~ ::
+
+  #+vindex: org-export-with-special-strings
+  Toggle conversion of special strings
+  (~org-export-with-special-strings~).
+
+- ~:~ ::
+
+  #+vindex: org-export-with-fixed-width
+  Toggle fixed-width sections (~org-export-with-fixed-width~).
+
+- ~<~ ::
+
+  #+vindex: org-export-with-timestamps
+  Toggle inclusion of time/date active/inactive stamps
+  (~org-export-with-timestamps~).
+
+- ~\n~ ::
+
+  #+vindex: org-export-preserve-breaks
+  Toggles whether to preserve line breaks
+  (~org-export-preserve-breaks~).
+
+- ~^~ ::
+
+  #+vindex: org-export-with-sub-superscripts
+  Toggle TeX-like syntax for sub- and superscripts.  If you write
+  =^:{}=, =a_{b}= is interpreted, but the simple =a_b= is left as it
+  is (~org-export-with-sub-superscripts~).
+
+- ~arch~ ::
+
+  #+vindex: org-export-with-archived-trees
+  Configure how archived trees are exported.  When set to ~headline~,
+  the export process skips the contents and processes only the
+  headlines (~org-export-with-archived-trees~).
+
+- ~author~ ::
+
+  #+vindex: org-export-with-author
+  Toggle inclusion of author name into exported file
+  (~org-export-with-author~).
+
+- ~broken-links~ ::
+
+  #+vindex: org-export-with-broken-links
+  Toggles if Org should continue exporting upon finding a broken
+  internal link.  When set to ~mark~, Org clearly marks the problem
+  link in the output (~org-export-with-broken-links~).
+
+- ~c~ ::
+
+  #+vindex: org-export-with-clocks
+  Toggle inclusion of =CLOCK= keywords (~org-export-with-clocks~).
+
+- ~creator~ ::
+
+  #+vindex: org-export-with-creator
+  Toggle inclusion of creator information in the exported file
+  (~org-export-with-creator~).
+
+- ~d~ ::
+
+  #+vindex: org-export-with-drawers
+  Toggles inclusion of drawers, or list of drawers to include, or list
+  of drawers to exclude (~org-export-with-drawers~).
+
+- ~date~ ::
+
+  #+vindex: org-export-with-date
+  Toggle inclusion of a date into exported file
+  (~org-export-with-date~).
+
+- ~e~ ::
+
+  #+vindex: org-export-with-entities
+  Toggle inclusion of entities (~org-export-with-entities~).
+
+- ~email~ ::
+
+  #+vindex: org-export-with-email
+  Toggle inclusion of the author's e-mail into exported file
+  (~org-export-with-email~).
+
+- ~f~ ::
+
+  #+vindex: org-export-with-footnotes
+  Toggle the inclusion of footnotes (~org-export-with-footnotes~).
+
+- ~H~ ::
+
+  #+vindex: org-export-headline-levels
+  Set the number of headline levels for export
+  (~org-export-headline-levels~).  Below that level, headlines are
+  treated differently.  In most back-ends, they become list items.
+
+- ~inline~ ::
+
+  #+vindex: org-export-with-inlinetasks
+  Toggle inclusion of inlinetasks (~org-export-with-inlinetasks~).
+
+- ~num~ ::
+
+  #+vindex: org-export-with-section-numbers
+  #+cindex: @samp{UNNUMBERED}, property
+  Toggle section-numbers (~org-export-with-section-numbers~).  When
+  set to number N, Org numbers only those headlines at level N or
+  above.  Set =UNNUMBERED= property to non-~nil~ to disable numbering
+  of heading and subheadings entirely.  Moreover, when the value is
+  =notoc= the headline, and all its children, do not appear in the
+  table of contents either (see [[*Table of Contents]]).
+
+- ~p~ ::
+
+  #+vindex: org-export-with-planning
+  Toggle export of planning information (~org-export-with-planning~).
+  "Planning information" comes from lines located right after the
+  headline and contain any combination of these cookies: =SCHEDULED=,
+  =DEADLINE=, or =CLOSED=.
+
+- ~pri~ ::
+
+  #+vindex: org-export-with-priority
+  Toggle inclusion of priority cookies
+  (~org-export-with-priority~).
+
+- ~prop~ ::
+
+  #+vindex: org-export-with-properties
+  Toggle inclusion of property drawers, or list the properties to
+  include (~org-export-with-properties~).
+
+- ~stat~ ::
+
+  #+vindex: org-export-with-statistics-cookies
+  Toggle inclusion of statistics cookies
+  (~org-export-with-statistics-cookies~).
+
+- ~tags~ ::
+
+  #+vindex: org-export-with-tags
+  Toggle inclusion of tags, may also be ~not-in-toc~
+  (~org-export-with-tags~).
+
+- ~tasks~ ::
+
+  #+vindex: org-export-with-tasks
+  Toggle inclusion of tasks (TODO items); or ~nil~ to remove all
+  tasks; or ~todo~ to remove done tasks; or list the keywords to keep
+  (~org-export-with-tasks~).
+
+- ~tex~ ::
+
+  #+vindex: org-export-with-latex
+  ~nil~ does not export; ~t~ exports; ~verbatim~ keeps everything in
+  verbatim (~org-export-with-latex~).
+
+- ~timestamp~ ::
+
+  #+vindex: org-export-time-stamp-file
+  Toggle inclusion of the creation time in the exported file
+  (~org-export-time-stamp-file~).
+
+- ~title~ ::
+
+  #+vindex: org-export-with-title
+  Toggle inclusion of title (~org-export-with-title~).
+
+- ~toc~ ::
+
+  #+vindex: org-export-with-toc
+  Toggle inclusion of the table of contents, or set the level limit
+  (~org-export-with-toc~).
+
+- ~todo~ ::
+
+  #+vindex: org-export-with-todo-keywords
+  Toggle inclusion of TODO keywords into exported text
+  (~org-export-with-todo-keywords~).
+
+- ~|~ ::
+
+  #+vindex: org-export-with-tables
+  Toggle inclusion of tables (~org-export-with-tables~).
+
+When exporting sub-trees, special node properties can override the
+above keywords.  These properties have an =EXPORT_= prefix.  For
+example, =DATE= becomes, =EXPORT_DATE= when used for a specific
+sub-tree.  Except for =SETUPFILE=, all other keywords listed above
+have an =EXPORT_= equivalent.
+
+#+cindex: @samp{BIND}, keyword
+#+vindex: org-export-allow-bind-keywords
+If ~org-export-allow-bind-keywords~ is non-~nil~, Emacs variables can
+become buffer-local during export by using the =BIND= keyword.  Its
+syntax is =#+BIND: variable value=.  This is particularly useful for
+in-buffer settings that cannot be changed using keywords.
+
+** Table of Contents
+:PROPERTIES:
+:DESCRIPTION: The if and where of the table of contents.
+:END:
+#+cindex: table of contents
+#+cindex: list of tables
+#+cindex: list of listings
+
+#+cindex: @samp{toc}, in @samp{OPTIONS} keyword
+#+vindex: org-export-with-toc
+The table of contents includes all headlines in the document.  Its
+depth is therefore the same as the headline levels in the file.  If
+you need to use a different depth, or turn it off entirely, set the
+~org-export-with-toc~ variable accordingly.  You can achieve the same
+on a per file basis, using the following =toc= item in =OPTIONS=
+keyword:
+
+#+begin_example
+,#+OPTIONS: toc:2          (only include two levels in TOC)
+,#+OPTIONS: toc:nil        (no default TOC at all)
+#+end_example
+
+#+cindex: excluding entries from table of contents
+#+cindex: table of contents, exclude entries
+Org includes both numbered and unnumbered headlines in the table of
+contents[fn:124].  If you need to exclude an unnumbered headline,
+along with all its children, set the =UNNUMBERED= property to =notoc=
+value.
+
+#+begin_example
+,* Subtree not numbered, not in table of contents either
+  :PROPERTIES:
+  :UNNUMBERED: notoc
+  :END:
+#+end_example
+
+#+cindex: @samp{TOC}, keyword
+Org normally inserts the table of contents directly before the first
+headline of the file.  To move the table of contents to a different
+location, first turn off the default with ~org-export-with-toc~
+variable or with =#+OPTIONS: toc:nil=.  Then insert =#+TOC: headlines
+N= at the desired location(s).
+
+#+begin_example
+,#+OPTIONS: toc:nil
+...
+,#+TOC: headlines 2
+#+end_example
+
+To adjust the table of contents depth for a specific section of the
+Org document, append an additional =local= parameter.  This parameter
+becomes a relative depth for the current level.  The following example
+inserts a local table of contents, with direct children only.
+
+#+begin_example
+,* Section
+,#+TOC: headlines 1 local
+#+end_example
+
+Note that for this feature to work properly in LaTeX export, the Org
+file requires the inclusion of the titletoc package.  Because of
+compatibility issues, titletoc has to be loaded /before/ hyperref.
+Customize the ~org-latex-default-packages-alist~ variable.
+
+The following example inserts a table of contents that links to the
+children of the specified target.
+
+#+begin_example
+,* Target
+  :PROPERTIES:
+  :CUSTOM_ID: TargetSection
+  :END:
+,** Heading A
+,** Heading B
+,* Another section
+,#+TOC: headlines 1 :target #TargetSection
+#+end_example
+
+The =:target= attribute is supported in HTML, Markdown, ODT, and ASCII export.
+
+Use the =TOC= keyword to generate list of tables---respectively, all
+listings---with captions.
+
+#+begin_example
+,#+TOC: listings
+,#+TOC: tables
+#+end_example
+
+#+cindex: @samp{ALT_TITLE}, property
+Normally Org uses the headline for its entry in the table of contents.
+But with =ALT_TITLE= property, a different entry can be specified for
+the table of contents.
+
+** Include Files
+:PROPERTIES:
+:DESCRIPTION: Include additional files into a document.
+:END:
+#+cindex: include files, during export
+#+cindex: export, include files
+#+cindex: @samp{INCLUDE}, keyword
+
+During export, you can include the content of another file.  For
+example, to include your =.emacs= file, you could use:
+
+: #+INCLUDE: "~/.emacs" src emacs-lisp
+
+#+texinfo: @noindent
+The first parameter is the file name to include.  The optional second
+parameter specifies the block type: =example=, =export= or =src=.  The
+optional third parameter specifies the source code language to use for
+formatting the contents.  This is relevant to both =export= and =src=
+block types.
+
+If an included file is specified as having a markup language, Org
+neither checks for valid syntax nor changes the contents in any way.
+For example and source blocks, Org code-escapes the contents before
+inclusion.
+
+#+cindex: @samp{minlevel}, include
+If an included file is not specified as having any markup language,
+Org assumes it be in Org format and proceeds as usual with a few
+exceptions.  Org makes the footnote labels (see [[*Creating Footnotes]])
+in the included file local to that file.  The contents of the included
+file belong to the same structure---headline, item---containing the
+=INCLUDE= keyword.  In particular, headlines within the file become
+children of the current section.  That behavior can be changed by
+providing an additional keyword parameter, =:minlevel=.  It shifts the
+headlines in the included file to become the lowest level.  For
+example, this syntax makes the included file a sibling of the current
+top-level headline:
+
+: #+INCLUDE: "~/my-book/chapter2.org" :minlevel 1
+
+#+cindex: @samp{lines}, include
+Inclusion of only portions of files are specified using ranges
+parameter with =:lines= keyword.  The line at the upper end of the
+range will not be included.  The start and/or the end of the range may
+be omitted to use the obvious defaults.
+
+| =#+INCLUDE: "~/.emacs" :lines "5-10"= | Include lines 5 to 10, 10 excluded |
+| =#+INCLUDE: "~/.emacs" :lines "-10"=  | Include lines 1 to 10, 10 excluded |
+| =#+INCLUDE: "~/.emacs" :lines "10-"=  | Include lines from 10 to EOF       |
+
+Inclusions may specify a file-link to extract an object matched by
+~org-link-search~[fn:125] (see [[*Search Options in File Links]]).  The
+ranges for =:lines= keyword are relative to the requested element.
+Therefore,
+
+: #+INCLUDE: "./paper.org::*conclusion" :lines 1-20
+
+#+texinfo: @noindent
+includes the first 20 lines of the headline named =conclusion=.
+
+#+cindex: @samp{only-contents}, include
+To extract only the contents of the matched object, set
+=:only-contents= property to non-~nil~.  This omits any planning lines
+or property drawers.  For example, to include the body of the heading
+with the custom ID =theory=, you can use
+
+: #+INCLUDE: "./paper.org::#theory" :only-contents t
+
+The following command allows navigating to the included document:
+
+- {{{kbd(C-c ')}}} (~org-edit~special~) ::
+  #+kindex: C-c '
+  #+findex: org-edit-special
+
+  Visit the included file at point.
+
+** Macro Replacement
+:PROPERTIES:
+:DESCRIPTION: Use macros to create templates.
+:END:
+#+cindex: macro replacement, during export
+#+cindex: @samp{MACRO}, keyword
+
+#+vindex: org-export-global-macros
+Macros replace text snippets during export.  Macros are defined
+globally in ~org-export-global-macros~, or document-wise with the
+following syntax:
+
+: #+MACRO: name   replacement text; $1, $2 are arguments
+
+#+texinfo: @noindent
+which can be referenced using ={{{name(arg1, arg2)}}}=[fn:126].  For
+example
+
+#+begin_example
+,#+MACRO: poem Rose is $1, violet's $2. Life's ordered: Org assists you.
+{{{poem(red,blue)}}}
+#+end_example
+
+#+texinfo: @noindent
+becomes
+
+: Rose is red, violet's blue. Life's ordered: Org assists you.
+
+As a special case, Org parses any replacement text starting with
+=(eval= as an Emacs Lisp expression and evaluates it accordingly.
+Within such templates, arguments become strings.  Thus, the following
+macro
+
+: #+MACRO: gnustamp (eval (concat "GNU/" (capitalize $1)))
+
+#+texinfo: @noindent
+turns ={{{gnustamp(linux)}}}= into =GNU/Linux= during export.
+
+Org recognizes macro references in following Org markup areas:
+paragraphs, headlines, verse blocks, tables cells and lists.  Org also
+recognizes macro references in keywords, such as =CAPTION=, =TITLE=,
+=AUTHOR=, =DATE=, and for some back-end specific export options.
+
+Org comes with following pre-defined macros:
+
+#+attr_texinfo: :sep ;
+- ={{{keyword(NAME)}}}=; ={{{title}}}=; ={{{author}}}=; ={{{email}}}= ::
+
+  #+cindex: @samp{keyword}, macro
+  #+cindex: @samp{title}, macro
+  #+cindex: @samp{author}, macro
+  #+cindex: @samp{email}, macro
+  The =keyword= macro collects all values from {{{var(NAME)}}}
+  keywords throughout the buffer, separated with white space.
+  =title=, =author= and =email= macros are shortcuts for,
+  respectively, ={{{keyword(TITLE)}}}=, ={{{keyword(AUTHOR)}}}= and
+  ={{{keyword(EMAIL)}}}=.
+
+- ={{{date}}}=; ={{{date(FORMAT)}}}= ::
+
+  #+cindex: @samp{date}, macro
+  This macro refers to the =DATE= keyword.  {{{var(FORMAT)}}} is an
+  optional argument to the =date= macro that is used only if =DATE= is
+  a single timestamp.  {{{var(FORMAT)}}} should be a format string
+  understood by ~format-time-string~.
+
+- ={{{time(FORMAT)}}}=; ={{{modification-time(FORMAT, VC)}}}= ::
+
+  #+cindex: @samp{time}, macro
+  #+cindex: @samp{modification-time}, macro
+  These macros refer to the document's date and time of export and
+  date and time of modification.  {{{var(FORMAT)}}} is a string
+  understood by ~format-time-string~.  If the second argument to the
+  ~modification-time~ macro is non-~nil~, Org uses =vc.el= to retrieve
+  the document's modification time from the version control system.
+  Otherwise Org reads the file attributes.
+
+- ={{{input-file}}}= ::
+
+  #+cindex: @samp{input-file}, macro
+  This macro refers to the filename of the exported file.
+
+- ={{{property(PROPERTY-NAME)}}}=; ={{{property(PROPERTY-NAME, SEARCH 
OPTION)}}}= ::
+
+  #+cindex: @samp{property}, macro
+  This macro returns the value of property {{{var(PROPERTY-NAME)}}} in
+  the current entry.  If {{{var(SEARCH-OPTION)}}} (see [[*Search
+  Options in File Links]]) refers to a remote entry, use it instead.
+
+- ={{{n}}}=; ={{{n(NAME)}}}=; ={{{n(NAME, ACTION)}}}= ::
+
+  #+cindex: @samp{n}, macro
+  #+cindex: counter, macro
+  This macro implements custom counters by returning the number of
+  times the macro has been expanded so far while exporting the buffer.
+  You can create more than one counter using different {{{var(NAME)}}}
+  values.  If {{{var(ACTION)}}} is =-=, previous value of the counter
+  is held, i.e., the specified counter is not incremented.  If the
+  value is a number, the specified counter is set to that value.  If
+  it is any other non-empty string, the specified counter is reset
+  to 1.  You may leave {{{var(NAME)}}} empty to reset the default
+  counter.
+
+#+cindex: @samp{results}, macro
+Moreover, inline source blocks (see [[*Structure of Code Blocks]]) use the
+special =results= macro to mark their output.  As such, you are
+advised against re-defining it, unless you know what you are doing.
+
+#+vindex: org-hide-macro-markers
+The surrounding brackets can be made invisible by setting
+~org-hide-macro-markers~ to a non-~nil~ value.
+
+Org expands macros at the very beginning of the export process.
+
+** Comment Lines
+:PROPERTIES:
+:DESCRIPTION: What will not be exported.
+:END:
+#+cindex: exporting, not
+
+#+cindex: comment lines
+Lines starting with zero or more whitespace characters followed by one
+=#= and a whitespace are treated as comments and, as such, are not
+exported.
+
+#+cindex: @samp{BEGIN_COMMENT}
+#+cindex: comment block
+Likewise, regions surrounded by =#+BEGIN_COMMENT= ... =#+END_COMMENT=
+are not exported.
+
+#+cindex: comment trees
+Finally, a =COMMENT= keyword at the beginning of an entry, but after
+any other keyword or priority cookie, comments out the entire subtree.
+In this case, the subtree is not exported and no code block within it
+is executed either[fn:127].  The command below helps changing the
+comment status of a headline.
+
+- {{{kbd(C-c ;)}}} (~org-toggle-comment~) ::
+  #+kindex: C-c ;
+  #+findex: org-toggle-comment
+
+  Toggle the =COMMENT= keyword at the beginning of an entry.
+
+** ASCII/Latin-1/UTF-8 export
+:PROPERTIES:
+:DESCRIPTION: Exporting to flat files with encoding.
+:END:
+#+cindex: ASCII export
+#+cindex: Latin-1 export
+#+cindex: UTF-8 export
+
+ASCII export produces an output file containing only plain ASCII
+characters.  This is the simplest and most direct text output.  It
+does not contain any Org markup.  Latin-1 and UTF-8 export use
+additional characters and symbols available in these encoding
+standards.  All three of these export formats offer the most basic of
+text output for maximum portability.
+
+#+vindex: org-ascii-text-width
+On export, Org fills and justifies text according to the text width
+set in ~org-ascii-text-width~.
+
+#+vindex: org-ascii-links-to-notes
+Org exports links using a footnote-like style where the descriptive
+part is in the text and the link is in a note before the next heading.
+See the variable ~org-ascii-links-to-notes~ for details.
+
+*** ASCII export commands
+:PROPERTIES:
+:UNNUMBERED: notoc
+:END:
+
+#+attr_texinfo: :sep ,
+- {{{kbd(C-c C-e t a)}}} (~org-ascii-export-to-ascii~), {{{kbd(C-c C-e t 
l)}}}, {{{kbd(C-c C-e t u)}}} ::
+  #+kindex: C-c C-e t a
+  #+kindex: C-c C-e t l
+  #+kindex: C-c C-e t u
+  #+findex: org-ascii-export-to-ascii
+
+  Export as an ASCII file with a =.txt= extension.  For =myfile.org=,
+  Org exports to =myfile.txt=, overwriting without warning.  For
+  =myfile.txt=, Org exports to =myfile.txt.txt= in order to prevent
+  data loss.
+
+- {{{kbd(C-c C-e t A)}}} (~org-ascii-export-to-ascii~), {{{kbd(C-c C-e t 
L)}}}, {{{kbd(C-c C-e t U)}}} ::
+  #+kindex: C-c C-e t A
+  #+kindex: C-c C-e t L
+  #+kindex: C-c C-e t U
+  #+findex: org-ascii-export-as-ascii
+
+  Export to a temporary buffer.  Does not create a file.
+
+*** ASCII specific export settings
+:PROPERTIES:
+:UNNUMBERED: notoc
+:END:
+
+The ASCII export back-end has one extra keyword for customizing ASCII
+output.  Setting this keyword works similar to the general options
+(see [[*Export Settings]]).
+
+- =SUBTITLE= ::
+
+  #+cindex: @samp{SUBTITLE}, keyword
+  The document subtitle.  For long subtitles, use multiple
+  =#+SUBTITLE= lines in the Org file.  Org prints them on one
+  continuous line, wrapping into multiple lines if necessary.
+
+*** Header and sectioning structure
+:PROPERTIES:
+:UNNUMBERED: notoc
+:END:
+
+Org converts the first three outline levels into headlines for ASCII
+export.  The remaining levels are turned into lists.  To change this
+cut-off point where levels become lists, see [[*Export Settings]].
+
+*** Quoting ASCII text
+:PROPERTIES:
+:UNNUMBERED: notoc
+:END:
+
+To insert text within the Org file by the ASCII back-end, use one the
+following constructs, inline, keyword, or export block:
+
+#+cindex: @samp{ASCII}, keyword
+#+cindex: @samp{BEGIN_EXPORT ascii}
+#+begin_example
+Inline text @@ascii:and additional text@@ within a paragraph.
+
+,#+ASCII: Some text
+
+,#+BEGIN_EXPORT ascii
+Org exports text in this block only when using ASCII back-end.
+,#+END_EXPORT
+#+end_example
+
+*** ASCII specific attributes
+:PROPERTIES:
+:UNNUMBERED: notoc
+:END:
+#+cindex: @samp{ATTR_ASCII}, keyword
+#+cindex: horizontal rules, in ASCII export
+
+ASCII back-end recognizes only one attribute, =:width=, which
+specifies the width of a horizontal rule in number of characters.  The
+keyword and syntax for specifying widths is:
+
+#+begin_example
+,#+ATTR_ASCII: :width 10
+-----
+#+end_example
+
+*** ASCII special blocks
+:PROPERTIES:
+:UNNUMBERED: notoc
+:END:
+#+cindex: special blocks, in ASCII export
+#+cindex: @samp{BEGIN_JUSTIFYLEFT}
+#+cindex: @samp{BEGIN_JUSTIFYRIGHT}
+
+Besides =#+BEGIN_CENTER= blocks (see [[*Paragraphs]]), ASCII back-end has
+these two left and right justification blocks:
+
+#+begin_example
+,#+BEGIN_JUSTIFYLEFT
+It's just a jump to the left...
+,#+END_JUSTIFYLEFT
+
+,#+BEGIN_JUSTIFYRIGHT
+...and then a step to the right.
+,#+END_JUSTIFYRIGHT
+#+end_example
+
+** Beamer Export
+:PROPERTIES:
+:DESCRIPTION: Producing presentations and slides.
+:END:
+#+cindex: Beamer export
+
+Org uses Beamer export to convert an Org file tree structure into
+high-quality interactive slides for presentations.  Beamer is a LaTeX
+document class for creating presentations in PDF, HTML, and other
+popular display formats.
+
+*** Beamer export commands
+:PROPERTIES:
+:DESCRIPTION: For creating Beamer documents.
+:END:
+
+- {{{kbd(C-c C-e l b)}}} (~org-beamer-export-to-latex~) ::
+  #+kindex: C-c C-e l b
+  #+findex: org-beamer-export-to-latex
+
+  Export as LaTeX file with a =.tex= extension.  For =myfile.org=, Org
+  exports to =myfile.tex=, overwriting without warning.
+
+- {{{kbd(C-c C-e l B)}}} (~org-beamer-export-as-latex~) ::
+  #+kindex: C-c C-e l B
+  #+findex: org-beamer-export-as-latex
+
+  Export to a temporary buffer.  Does not create a file.
+
+- {{{kbd(C-c C-e l P)}}} (~org-beamer-export-to-pdf~) ::
+  #+kindex: C-c C-e l P
+  #+findex: org-beamer-export-to-pdf
+
+  Export as LaTeX file and then convert it to PDF format.
+
+- {{{kbd(C-c C-e l O)}}} ::
+  #+kindex: C-c C-e l O
+
+  Export as LaTeX file, convert it to PDF format, and then open the
+  PDF file.
+
+*** Beamer specific export settings
+:PROPERTIES:
+:DESCRIPTION: For customizing Beamer export.
+:END:
+
+Beamer export back-end has several additional keywords for customizing
+Beamer output.  These keywords work similar to the general options
+settings (see [[*Export Settings]]).
+
+- =BEAMER_THEME= ::
+
+  #+cindex: @samp{BEAMER_THEME}, keyword
+  #+vindex: org-beamer-theme
+  The Beamer layout theme (~org-beamer-theme~).  Use square brackets
+  for options.  For example:
+
+  : #+BEAMER_THEME: Rochester [height=20pt]
+
+- =BEAMER_FONT_THEME= ::
+
+  #+cindex: @samp{BEAMER_FONT_THEME}, keyword
+  The Beamer font theme.
+
+- =BEAMER_INNER_THEME= ::
+
+  #+cindex: @samp{BEAMER_INNER_THEME}, keyword
+  The Beamer inner theme.
+
+- =BEAMER_OUTER_THEME= ::
+
+  #+cindex: @samp{BEAMER_OUTER_THEME}, keyword
+  The Beamer outer theme.
+
+- =BEAMER_HEADER= ::
+
+  #+cindex: @samp{BEAMER_HEADER}, keyword
+  Arbitrary lines inserted in the preamble, just before the =hyperref=
+  settings.
+
+- =DESCRIPTION= ::
+
+  #+cindex: @samp{DESCRIPTION}, keyword
+  The document description.  For long descriptions, use multiple
+  =DESCRIPTION= keywords.  By default, =hyperref= inserts
+  =DESCRIPTION= as metadata.  Use ~org-latex-hyperref-template~ to
+  configure document metadata.  Use ~org-latex-title-command~ to
+  configure typesetting of description as part of front matter.
+
+- =KEYWORDS= ::
+
+  #+cindex: @samp{KEYWORDS}, keyword
+  The keywords for defining the contents of the document.  Use
+  multiple =KEYWORDS= lines if necessary.  By default, =hyperref=
+  inserts =KEYWORDS= as metadata.  Use ~org-latex-hyperref-template~
+  to configure document metadata.  Use ~org-latex-title-command~ to
+  configure typesetting of keywords as part of front matter.
+
+- =SUBTITLE= ::
+
+  #+cindex: @samp{SUBTITLE}, keyword
+  Document's subtitle.  For typesetting, use
+  ~org-beamer-subtitle-format~ string.  Use
+  ~org-latex-hyperref-template~ to configure document metadata.  Use
+  ~org-latex-title-command~ to configure typesetting of subtitle as
+  part of front matter.
+
+*** Frames and Blocks in Beamer
+:PROPERTIES:
+:DESCRIPTION: For composing Beamer slides.
+:END:
+
+Org transforms heading levels into Beamer's sectioning elements,
+frames and blocks.  Any Org tree with a not-too-deep-level nesting
+should in principle be exportable as a Beamer presentation.
+
+-
+  #+vindex: org-beamer-frame-level
+  Org headlines become Beamer frames when the heading level in Org is
+  equal to ~org-beamer-frame-level~ or =H= value in a =OPTIONS= line
+  (see [[*Export Settings]]).
+
+  #+cindex: @samp{BEAMER_ENV}, property
+  Org overrides headlines to frames conversion for the current tree of
+  an Org file if it encounters the =BEAMER_ENV= property set to
+  =frame= or =fullframe=.  Org ignores whatever
+  ~org-beamer-frame-level~ happens to be for that headline level in
+  the Org tree.  In Beamer terminology, a full frame is a frame
+  without its title.
+
+- Org exports a Beamer frame's objects as block environments.  Org can
+  enforce wrapping in special block types when =BEAMER_ENV= property
+  is set[fn:128].  For valid values see
+  ~org-beamer-environments-default~.  To add more values, see
+  ~org-beamer-environments-extra~.
+  #+vindex: org-beamer-environments-default
+  #+vindex: org-beamer-environments-extra
+
+-
+  #+cindex: @samp{BEAMER_REF}, property
+  If =BEAMER_ENV= is set to =appendix=, Org exports the entry as an
+  appendix.  When set to =note=, Org exports the entry as a note
+  within the frame or between frames, depending on the entry's heading
+  level.  When set to =noteNH=, Org exports the entry as a note
+  without its title.  When set to =againframe=, Org exports the entry
+  with =\againframe= command, which makes setting the =BEAMER_REF=
+  property mandatory because =\againframe= needs frame to resume.
+
+  When =ignoreheading= is set, Org export ignores the entry's headline
+  but not its content.  This is useful for inserting content between
+  frames.  It is also useful for properly closing a =column=
+  environment.  @end itemize
+
+  #+cindex: @samp{BEAMER_ACT}, property
+  #+cindex: @samp{BEAMER_OPT}, property
+  When =BEAMER_ACT= is set for a headline, Org export translates that
+  headline as an overlay or action specification.  When enclosed in
+  square brackets, Org export makes the overlay specification
+  a default.  Use =BEAMER_OPT= to set any options applicable to the
+  current Beamer frame or block.  The Beamer export back-end wraps
+  with appropriate angular or square brackets.  It also adds the
+  =fragile= option for any code that may require a verbatim block.
+
+  #+cindex: @samp{BEAMER_COL}, property
+  To create a column on the Beamer slide, use the =BEAMER_COL=
+  property for its headline in the Org file.  Set the value of
+  =BEAMER_COL= to a decimal number representing the fraction of the
+  total text width.  Beamer export uses this value to set the column's
+  width and fills the column with the contents of the Org entry.  If
+  the Org entry has no specific environment defined, Beamer export
+  ignores the heading.  If the Org entry has a defined environment,
+  Beamer export uses the heading as title.  Behind the scenes, Beamer
+  export automatically handles LaTeX column separations for contiguous
+  headlines.  To manually adjust them for any unique configurations
+  needs, use the =BEAMER_ENV= property.
+
+*** Beamer specific syntax
+:PROPERTIES:
+:DESCRIPTION: For using in Org documents.
+:END:
+
+Since Org's Beamer export back-end is an extension of the LaTeX
+back-end, it recognizes other LaTeX specific syntax---for example,
+=#+LATEX:= or =#+ATTR_LATEX:=.  See [[*LaTeX Export]], for details.
+
+Beamer export wraps the table of contents generated with =toc:t=
+=OPTION= keyword in a =frame= environment.  Beamer export does not
+wrap the table of contents generated with =TOC= keyword (see [[*Table of
+Contents]]).  Use square brackets for specifying options.
+
+: #+TOC: headlines [currentsection]
+
+Insert Beamer-specific code using the following constructs:
+
+#+cindex: @samp{BEAMER}, keyword
+#+cindex: @samp{BEGIN_EXPORT beamer}
+#+begin_example
+,#+BEAMER: \pause
+
+,#+BEGIN_EXPORT beamer
+  Only Beamer export back-end exports this.
+,#+END_BEAMER
+
+Text @@beamer:some code@@ within a paragraph.
+#+end_example
+
+Inline constructs, such as the last one above, are useful for adding
+overlay specifications to objects with ~bold~, ~item~, ~link~,
+~radio-target~ and ~target~ types.  Enclose the value in angular
+brackets and place the specification at the beginning of the object as
+shown in this example:
+
+:  A *@@beamer:<2->@@useful* feature
+
+#+cindex: @samp{ATTR_BEAMER}, keyword
+Beamer export recognizes the =ATTR_BEAMER= keyword with the following
+attributes from Beamer configurations: =:environment= for changing
+local Beamer environment, =:overlay= for specifying Beamer overlays in
+angular or square brackets, and =:options= for inserting optional
+arguments.
+
+#+begin_example
+,#+ATTR_BEAMER: :environment nonindentlist
+- item 1, not indented
+- item 2, not indented
+- item 3, not indented
+#+end_example
+
+#+begin_example
+,#+ATTR_BEAMER: :overlay <+->
+- item 1
+- item 2
+#+end_example
+
+#+begin_example
+,#+ATTR_BEAMER: :options [Lagrange]
+Let $G$ be a finite group, and let $H$ be
+a subgroup of $G$.  Then the order of $H$ divides the order of $G$.
+#+end_example
+
+*** Editing support
+:PROPERTIES:
+:DESCRIPTION: Editing support.
+:END:
+
+Org Beamer mode is a special minor mode for faster editing of Beamer
+documents.
+
+: #+STARTUP: beamer
+
+- {{{kbd(C-c C-b)}}} (~org-beamer-select-environment~) ::
+  #+kindex: C-c C-b
+  #+findex: org-beamer-select-environment
+
+  Org Beamer mode provides this key for quicker selections in Beamer
+  normal environments, and for selecting the =BEAMER_COL= property.
+
+*** A Beamer example
+:PROPERTIES:
+:DESCRIPTION: A complete presentation.
+:END:
+
+Here is an example of an Org document ready for Beamer export.
+
+#+begin_example
+,#+TITLE: Example Presentation
+,#+AUTHOR: Carsten Dominik
+,#+OPTIONS: H:2 toc:t num:t
+,#+LATEX_CLASS: beamer
+,#+LATEX_CLASS_OPTIONS: [presentation]
+,#+BEAMER_THEME: Madrid
+,#+COLUMNS: %45ITEM %10BEAMER_ENV(Env) %10BEAMER_ACT(Act) %4BEAMER_COL(Col)
+
+,* This is the first structural section
+
+,** Frame 1
+,*** Thanks to Eric Fraga                                           :B_block:
+    :PROPERTIES:
+    :BEAMER_COL: 0.48
+    :BEAMER_ENV: block
+    :END:
+    for the first viable Beamer setup in Org
+,*** Thanks to everyone else                                        :B_block:
+    :PROPERTIES:
+    :BEAMER_COL: 0.48
+    :BEAMER_ACT: <2->
+    :BEAMER_ENV: block
+    :END:
+    for contributing to the discussion
+,**** This will be formatted as a beamer note                       :B_note:
+     :PROPERTIES:
+     :BEAMER_env: note
+     :END:
+,** Frame 2 (where we will not use columns)
+,*** Request
+    Please test this stuff!
+#+end_example
+
+** HTML Export
+:PROPERTIES:
+:DESCRIPTION: Exporting to HTML.
+:END:
+#+cindex: HTML export
+
+Org mode contains an HTML exporter with extensive HTML formatting
+compatible with XHTML 1.0 strict standard.
+
+*** HTML export commands
+:PROPERTIES:
+:DESCRIPTION: Invoking HTML export.
+:END:
+
+- {{{kbd(C-c C-e h h)}}} (~org-html-export-to-html~) ::
+  #+kindex: C-c C-e h h
+  #+kindex: C-c C-e h o
+  #+findex: org-html-export-to-html
+
+  Export as HTML file with a =.html= extension.  For =myfile.org=, Org
+  exports to =myfile.html=, overwriting without warning.  {{{kbd{C-c
+  C-e h o)}}} exports to HTML and opens it in a web browser.
+
+- {{{kbd(C-c C-e h H)}}} (~org-html-export-as-html~) ::
+  #+kindex: C-c C-e h H
+  #+findex: org-html-export-as-html
+
+  Exports to a temporary buffer.  Does not create a file.
+
+*** HTML specific export settings
+:PROPERTIES:
+:DESCRIPTION: Settings for HTML export.
+:END:
+
+HTML export has a number of keywords, similar to the general options
+settings described in [[*Export Settings]].
+
+- =DESCRIPTION= ::
+
+  #+cindex: @samp{DESCRIPTION}, keyword
+  This is the document's description, which the HTML exporter inserts
+  it as a HTML meta tag in the HTML file.  For long descriptions, use
+  multiple =DESCRIPTION= lines.  The exporter takes care of wrapping
+  the lines properly.
+
+- =HTML_DOCTYPE= ::
+
+  #+cindex: @samp{HTML_DOCTYPE}, keyword
+  #+vindex: org-html-doctype
+  Specify the document type, for example: HTML5 (~org-html-doctype~).
+
+- =HTML_CONTAINER= ::
+
+  #+cindex: @samp{HTML_CONTAINER}, keyword
+  #+vindex: org-html-container-element
+  Specify the HTML container, such as =div=, for wrapping sections and
+  elements (~org-html-container-element~).
+
+- =HTML_LINK_HOME= ::
+
+  #+cindex: @samp{HTML_LINK_HOME}, keyword
+  #+vindex: org-html-link-home
+  The URL for home link (~org-html-link-home~).
+
+- =HTML_LINK_UP= ::
+
+  #+cindex: @samp{HTML_LINK_UP}, keyword
+  #+vindex: org-html-link-up
+  The URL for the up link of exported HTML pages (~org-html-link-up~).
+
+- =HTML_MATHJAX= ::
+
+  #+cindex: @samp{HTML_MATHJAX}, keyword
+  #+vindex: org-html-mathjax-options
+  Options for MathJax (~org-html-mathjax-options~).  MathJax is used
+  to typeset LaTeX math in HTML documents.  See [[*Math formatting in
+  HTML export]], for an example.
+
+- =HTML_HEAD= ::
+
+  #+cindex: @samp{HTML_HEAD}, keyword
+  #+vindex: org-html-head
+  Arbitrary lines for appending to the HTML document's head
+  (~org-html-head~).
+
+- =HTML_HEAD_EXTRA= ::
+
+  #+cindex: @samp{HTML_HEAD_EXTRA}, keyword
+  #+vindex: org-html-head-extra
+  More arbitrary lines for appending to the HTML document's head
+  (~org-html-head-extra~).
+
+- =KEYWORDS= ::
+
+  #+cindex: @samp{KEYWORDS}, keyword
+  Keywords to describe the document's content.  HTML exporter inserts
+  these keywords as HTML meta tags.  For long keywords, use multiple
+  =KEYWORDS= lines.
+
+- =LATEX_HEADER= ::
+
+  #+cindex: @samp{LATEX_HEADER}, keyword
+  Arbitrary lines for appending to the preamble; HTML exporter appends
+  when transcoding LaTeX fragments to images (see [[*Math formatting in
+  HTML export]]).
+
+- =SUBTITLE= ::
+
+  #+cindex: @samp{SUBTITLE}, keyword
+  The document's subtitle.  HTML exporter formats subtitle if document
+  type is =HTML5= and the CSS has a =subtitle= class.
+
+Some of these keywords are explained in more detail in the following
+sections of the manual.
+
+*** HTML doctypes
+:PROPERTIES:
+:DESCRIPTION: Exporting various (X)HTML flavors.
+:END:
+
+Org can export to various (X)HTML flavors.
+
+#+vindex: org-html-doctype
+#+vindex: org-html-doctype-alist
+Set the ~org-html-doctype~ variable for different (X)HTML variants.
+Depending on the variant, the HTML exporter adjusts the syntax of HTML
+conversion accordingly.  Org includes the following ready-made
+variants:
+
+- ~"html4-strict"~
+- ~"html4-transitional"~
+- ~"html4-frameset"~
+- ~"xhtml-strict"~
+- ~"xhtml-transitional"~
+- ~"xhtml-frameset"~
+- ~"xhtml-11"~
+- ~"html5"~
+- ~"xhtml5"~
+
+#+texinfo: @noindent
+See the variable ~org-html-doctype-alist~ for details.  The default is
+~"xhtml-strict"~.
+
+#+vindex: org-html-html5-fancy
+#+cindex: @samp{HTML5}, export new elements
+Org's HTML exporter does not by default enable new block elements
+introduced with the HTML5 standard.  To enable them, set
+~org-html-html5-fancy~ to non-~nil~.  Or use an =OPTIONS= line in the
+file to set =html5-fancy=.
+
+HTML5 documents can now have arbitrary =#+BEGIN= ... =#+END= blocks.
+For example:
+
+#+begin_example
+,#+BEGIN_aside
+  Lorem ipsum
+,#+END_aside
+#+end_example
+
+#+texinfo: @noindent
+exports to:
+
+#+begin_src html
+<aside>
+  <p>Lorem ipsum</p>
+</aside>
+#+end_src
+
+#+texinfo: @noindent
+while this:
+
+#+begin_example
+,#+ATTR_HTML: :controls controls :width 350
+,#+BEGIN_video
+,#+HTML: <source src="movie.mp4" type="video/mp4">
+,#+HTML: <source src="movie.ogg" type="video/ogg">
+Your browser does not support the video tag.
+,#+END_video
+#+end_example
+
+#+texinfo: @noindent
+exports to:
+
+#+begin_src html
+<video controls="controls" width="350">
+  <source src="movie.mp4" type="video/mp4">
+    <source src="movie.ogg" type="video/ogg">
+      <p>Your browser does not support the video tag.</p>
+</video>
+#+end_src
+
+#+vindex: org-html-html5-elements
+When special blocks do not have a corresponding HTML5 element, the
+HTML exporter reverts to standard translation (see
+~org-html-html5-elements~).  For example, =#+BEGIN_lederhosen= exports
+to ~<div class="lederhosen">~.
+
+Special blocks cannot have headlines.  For the HTML exporter to wrap
+the headline and its contents in ~<section>~ or ~<article>~ tags, set
+the =HTML_CONTAINER= property for the headline.
+
+*** HTML preamble and postamble
+:PROPERTIES:
+:DESCRIPTION: Inserting preamble and postamble.
+:END:
+#+vindex: org-html-preamble
+#+vindex: org-html-postamble
+#+vindex: org-html-preamble-format
+#+vindex: org-html-postamble-format
+#+vindex: org-html-validation-link
+#+vindex: org-export-creator-string
+#+vindex: org-export-time-stamp-file
+
+The HTML exporter has delineations for preamble and postamble.  The
+default value for ~org-html-preamble~ is ~t~, which makes the HTML
+exporter insert the preamble.  See the variable
+~org-html-preamble-format~ for the format string.
+
+Set ~org-html-preamble~ to a string to override the default format
+string.  If the string is a function, the HTML exporter expects the
+function to return a string upon execution.  The HTML exporter inserts
+this string in the preamble.  The HTML exporter does not insert
+a preamble if ~org-html-preamble~ is set ~nil~.
+
+The default value for ~org-html-postamble~ is ~auto~, which makes the
+HTML exporter build a postamble from looking up author's name, email
+address, creator's name, and date.  Set ~org-html-postamble~ to ~t~ to
+insert the postamble in the format specified in the
+~org-html-postamble-format~ variable.  The HTML exporter does not
+insert a postamble if ~org-html-postamble~ is set to ~nil~.
+
+*** Quoting HTML tags
+:PROPERTIES:
+:DESCRIPTION: Using direct HTML in Org files.
+:END:
+
+The HTML export back-end transforms =<= and =>= to =&lt;= and =&gt;=.
+To include raw HTML code in the Org file so the HTML export back-end
+can insert that HTML code in the output, use this inline syntax:
+=@@html:...@@=.  For example:
+
+: @@html:<b>@@bold text@@html:</b>@@
+
+#+cindex: @samp{HTML}, keyword
+#+cindex: @samp{BEGIN_EXPORT html}
+For larger raw HTML code blocks, use these HTML export code blocks:
+
+#+begin_example
+,#+HTML: Literal HTML code for export
+
+,#+BEGIN_EXPORT html
+  All lines between these markers are exported literally
+,#+END_EXPORT
+#+end_example
+
+*** Headlines in HTML export
+:PROPERTIES:
+:DESCRIPTION: Formatting headlines.
+:END:
+#+cindex: headlines, in HTML export
+
+Headlines are exported to =<h1>=, =<h2>=, etc.  Each headline gets the
+=id= attribute from =CUSTOM_ID= property, or a unique generated value,
+see [[*Internal Links]].
+
+#+vindex: org-html-self-link-headlines
+When ~org-html-self-link-headlines~ is set to a non-~nil~ value, the
+text of the headlines is also wrapped in =<a>= tags.  These tags have
+a =href= attribute making the headlines link to themselves.
+
+*** Links in HTML export
+:PROPERTIES:
+:DESCRIPTION: Inserting and formatting links.
+:END:
+#+cindex: links, in HTML export
+#+cindex: internal links, in HTML export
+#+cindex: external links, in HTML export
+
+The HTML export back-end transforms Org's internal links (see
+[[*Internal Links]]) to equivalent HTML links in the output.  The back-end
+similarly handles Org's automatic links created by radio targets (see
+[[*Radio Targets]]) similarly.  For Org links to external files, the
+back-end transforms the links to /relative/ paths.
+
+#+vindex: org-html-link-org-files-as-html
+For Org links to other =.org= files, the back-end automatically
+changes the file extension to =.html= and makes file paths relative.
+If the =.org= files have an equivalent =.html= version at the same
+location, then the converted links should work without any further
+manual intervention.  However, to disable this automatic path
+translation, set ~org-html-link-org-files-as-html~ to ~nil~.  When
+disabled, the HTML export back-end substitutes the ID-based links in
+the HTML output.  For more about linking files when publishing to
+a directory, see [[*Publishing links]].
+
+Org files can also have special directives to the HTML export
+back-end.  For example, by using =#+ATTR_HTML= lines to specify new
+format attributes to ~<a>~ or ~<img>~ tags.  This example shows
+changing the link's title and style:
+
+#+cindex: @samp{ATTR_HTML}, keyword
+#+begin_example
+,#+ATTR_HTML: :title The Org mode homepage :style color:red;
+[[https://orgmode.org]]
+#+end_example
+
+*** Tables in HTML export
+:PROPERTIES:
+:DESCRIPTION: How to modify the formatting of tables.
+:END:
+#+cindex: tables, in HTML
+#+vindex: org-export-html-table-tag
+
+The HTML export back-end uses ~org-html-table-default-attributes~ when
+exporting Org tables to HTML.  By default, the exporter does not draw
+frames and cell borders.  To change for this for a table, use the
+following lines before the table in the Org file:
+
+#+cindex: @samp{CAPTION}, keyword
+#+cindex: @samp{ATTR_HTML}, keyword
+#+begin_example
+,#+CAPTION: This is a table with lines around and between cells
+,#+ATTR_HTML: :border 2 :rules all :frame border
+#+end_example
+
+The HTML export back-end preserves column groupings in Org tables (see
+[[*Column Groups]]) when exporting to HTML.
+
+Additional options for customizing tables for HTML export.
+
+- ~org-html-table-align-individual-fields~ ::
+
+  #+vindex: org-html-table-align-individual-fields
+  Non-~nil~ attaches style attributes for alignment to each table
+  field.
+
+- ~org-html-table-caption-above~ ::
+
+  #+vindex: org-html-table-caption-above
+  Non-~nil~ places caption string at the beginning of the table.
+
+- ~org-html-table-data-tags~ ::
+
+  #+vindex: org-html-table-data-tags
+  Opening and ending tags for table data fields.
+
+- ~org-html-table-default-attributes~ ::
+
+  #+vindex: org-html-table-default-attributes
+  Default attributes and values for table tags.
+
+- ~org-html-table-header-tags~ ::
+
+  #+vindex: org-html-table-header-tags
+  Opening and ending tags for table's header fields.
+
+- ~org-html-table-row-tags~ ::
+
+  #+vindex: org-html-table-row-tags
+  Opening and ending tags for table rows.
+
+- ~org-html-table-use-header-tags-for-first-column~ ::
+
+  #+vindex: org-html-table-use-header-tags-for-first-column
+  Non-~nil~ formats column one in tables with header tags.
+
+*** Images in HTML export
+:PROPERTIES:
+:DESCRIPTION: How to insert figures into HTML output.
+:END:
+#+cindex: images, inline in HTML
+#+cindex: inlining images in HTML
+
+The HTML export back-end has features to convert Org image links to
+HTML inline images and HTML clickable image links.
+
+#+vindex: org-html-inline-images
+When the link in the Org file has no description, the HTML export
+back-end by default in-lines that image.  For example:
+=[[file:myimg.jpg]]= is in-lined, while =[[file:myimg.jpg][the image]]= links 
to the text,
+=the image=.  For more details, see the variable
+~org-html-inline-images~.
+
+On the other hand, if the description part of the Org link is itself
+another link, such as =file:= or =http:= URL pointing to an image, the
+HTML export back-end in-lines this image and links to the main image.
+This Org syntax enables the back-end to link low-resolution thumbnail
+to the high-resolution version of the image, as shown in this example:
+
+: [[file:highres.jpg][file:thumb.jpg]]
+
+To change attributes of in-lined images, use =#+ATTR_HTML= lines in
+the Org file.  This example shows realignment to right, and adds ~alt~
+and ~title~ attributes in support of text viewers and modern web
+accessibility standards.
+
+#+cindex: @samp{CAPTION}, keyword
+#+cindex: @samp{ATTR_HTML}, keyword
+#+begin_example
+,#+CAPTION: A black cat stalking a spider
+,#+ATTR_HTML: :alt cat/spider image :title Action! :align right
+[[./img/a.jpg]]
+#+end_example
+
+The HTML export back-end copies the =http= links from the Org file
+as-is.
+
+*** Math formatting in HTML export
+:PROPERTIES:
+:DESCRIPTION: Beautiful math also on the web.
+:END:
+#+cindex: MathJax
+#+cindex: dvipng
+#+cindex: dvisvgm
+#+cindex: ImageMagick
+
+#+vindex: org-html-mathjax-options~
+LaTeX math snippets (see [[*LaTeX fragments]]) can be displayed in two
+different ways on HTML pages.  The default is to use the 
[[http://www.mathjax.org][MathJax]],
+which should work out of the box with Org[fn:129][fn:130].  Some MathJax
+display options can be configured via ~org-html-mathjax-options~, or
+in the buffer.  For example, with the following settings,
+
+#+begin_example
+,#+HTML_MATHJAX: align: left indent: 5em tagside: left font: Neo-Euler
+,#+HTML_MATHJAX: cancel.js noErrors.js
+#+end_example
+
+#+texinfo: @noindent
+equation labels are displayed on the left margin and equations are
+five em from the left margin.  In addition, it loads the two MathJax
+extensions =cancel.js= and =noErrors.js=[fn:131].
+
+#+vindex: org-html-mathjax-template
+See the docstring of ~org-html-mathjax-options~ for all supported
+variables.  The MathJax template can be configure via
+~org-html-mathjax-template~.
+
+If you prefer, you can also request that LaTeX fragments are processed
+into small images that will be inserted into the browser page.  Before
+the availability of MathJax, this was the default method for Org
+files.  This method requires that the dvipng program, dvisvgm or
+ImageMagick suite is available on your system.  You can still get this
+processing with
+
+: #+OPTIONS: tex:dvipng
+
+: #+OPTIONS: tex:dvisvgm
+
+#+texinfo: @noindent
+or
+
+: #+OPTIONS: tex:imagemagick
+
+*** Text areas in HTML export
+:PROPERTIES:
+:DESCRIPTION: An alternate way to show an example.
+:END:
+
+#+cindex: text areas, in HTML
+Before Org mode's Babel, one popular approach to publishing code in
+HTML was by using =:textarea=.  The advantage of this approach was
+that copying and pasting was built into browsers with simple
+JavaScript commands.  Even editing before pasting was made simple.
+
+The HTML export back-end can create such text areas.  It requires an
+=#+ATTR_HTML= line as shown in the example below with the =:textarea=
+option.  This must be followed by either an example or a source code
+block.  Other Org block types do not honor the =:textarea= option.
+
+By default, the HTML export back-end creates a text area 80 characters
+wide and height just enough to fit the content.  Override these
+defaults with =:width= and =:height= options on the =#+ATTR_HTML=
+line.
+
+#+begin_example
+,#+ATTR_HTML: :textarea t :width 40
+,#+BEGIN_EXAMPLE
+  (defun org-xor (a b)
+     "Exclusive or."
+     (if a (not b) b))
+,#+END_EXAMPLE
+#+end_example
+
+*** CSS support
+:PROPERTIES:
+:DESCRIPTION: Changing the appearance of the output.
+:END:
+#+cindex: CSS, for HTML export
+#+cindex: HTML export, CSS
+
+#+vindex: org-export-html-todo-kwd-class-prefix
+#+vindex: org-export-html-tag-class-prefix
+You can modify the CSS style definitions for the exported file.  The
+HTML exporter assigns the following special CSS classes[fn:132] to
+appropriate parts of the document---your style specifications may
+change these, in addition to any of the standard classes like for
+headlines, tables, etc.
+
+| ~p.author~           | author information, including email                   
 |
+| ~p.date~             | publishing date                                       
 |
+| ~p.creator~          | creator info, about org mode version                  
 |
+| ~.title~             | document title                                        
 |
+| ~.subtitle~          | document subtitle                                     
 |
+| ~.todo~              | TODO keywords, all not-done states                    
 |
+| ~.done~              | the DONE keywords, all states that count as done      
 |
+| ~.WAITING~           | each TODO keyword also uses a class named after 
itself |
+| ~.timestamp~         | timestamp                                             
 |
+| ~.timestamp-kwd~     | keyword associated with a timestamp, like =SCHEDULED= 
 |
+| ~.timestamp-wrapper~ | span around keyword plus timestamp                    
 |
+| ~.tag~               | tag in a headline                                     
 |
+| ~._HOME~             | each tag uses itself as a class, "@" replaced by "_"  
 |
+| ~.target~            | target for links                                      
 |
+| ~.linenr~            | the line number in a code example                     
 |
+| ~.code-highlighted~  | for highlighting referenced code lines                
 |
+| ~div.outline-N~      | div for outline level N (headline plus text)          
 |
+| ~div.outline-text-N~ | extra div for text at outline level N                 
 |
+| ~.section-number-N~  | section number in headlines, different for each level 
 |
+| ~.figure-number~     | label like "Figure 1:"                                
 |
+| ~.table-number~      | label like "Table 1:"                                 
 |
+| ~.listing-number~    | label like "Listing 1:"                               
 |
+| ~div.figure~         | how to format an in-lined image                       
 |
+| ~pre.src~            | formatted source code                                 
 |
+| ~pre.example~        | normal example                                        
 |
+| ~p.verse~            | verse paragraph                                       
 |
+| ~div.footnotes~      | footnote section headline                             
 |
+| ~p.footnote~         | footnote definition paragraph, containing a footnote  
 |
+| ~.footref~           | a footnote reference number (always a <sup>)          
 |
+| ~.footnum~           | footnote number in footnote definition (always <sup>) 
 |
+| ~.org-svg~           | default class for a linked =.svg= image               
 |
+
+#+vindex: org-html-style-default
+#+vindex: org-html-head
+#+vindex: org-html-head-extra
+#+cindex: @samp{HTML_INCLUDE_STYLE}, keyword
+The HTML export back-end includes a compact default style in each
+exported HTML file.  To override the default style with another style,
+use these keywords in the Org file.  They will replace the global
+defaults the HTML exporter uses.
+
+#+cindex: @samp{HTML_HEAD}, keyword
+#+cindex: @samp{HTML_HEAD_EXTRA}, keyword
+#+begin_example
+,#+HTML_HEAD: <link rel="stylesheet" type="text/css" href="style1.css" />
+,#+HTML_HEAD_EXTRA: <link rel="alternate stylesheet" type="text/css" 
href="style2.css" />
+#+end_example
+
+#+vindex: org-html-head-include-default-style
+To just turn off the default style, customize
+~org-html-head-include-default-style~ variable, or use this option
+line in the Org file.
+
+#+cindex: @samp{html-style}, @samp{OPTIONS} item
+: #+OPTIONS: html-style:nil
+
+For longer style definitions, either use several =HTML_HEAD= and
+=HTML_HEAD_EXTRA= keywords, or use ~<style> ... </style>~ blocks
+around them.  Both of these approaches can avoid referring to an
+external file.
+
+#+cindex: @samp{HTML_CONTAINER_CLASS}, property
+#+cindex: @samp{HTML_HEADLINE_CLASS}, property
+In order to add styles to a sub-tree, use the =HTML_CONTAINER_CLASS=
+property to assign a class to the tree.  In order to specify CSS
+styles for a particular headline, you can use the ID specified in
+a =CUSTOM_ID= property.  You can also assign a specific class to
+a headline with the =HTML_HEADLINE_CLASS= property.
+
+Never change the ~org-html-style-default~ constant.  Instead use other
+simpler ways of customizing as described above.
+
+*** JavaScript supported display of web pages
+:PROPERTIES:
+:DESCRIPTION: Info and folding in a web browser.
+:ALT_TITLE: JavaScript support
+:END:
+
+Sebastian Rose has written a JavaScript program especially designed to
+allow two different ways of viewing HTML files created with Org.  One
+is an /Info/-like mode where each section is displayed separately and
+navigation can be done with the {{{kbd(n)}}} and {{{kbd(p)}}} keys, and some 
other
+keys as well, press {{{kbd(?)}}} for an overview of the available keys.  The
+second one has a /folding/ view, much like Org provides inside Emacs.
+The script is available at https://orgmode.org/org-info.js and the
+documentation at https://orgmode.org/worg/code/org-info-js/.  The
+script is hosted on https://orgmode.org, but for reliability, prefer
+installing it on your own web server.
+
+To use this program, just add this line to the Org file:
+
+#+cindex: @samp{INFOJS_OPT}, keyword
+: #+INFOJS_OPT: view:info toc:nil
+
+#+texinfo: @noindent
+The HTML header now has the code needed to automatically invoke the
+script.  For setting options, use the syntax from the above line for
+options described below:
+
+- =path:= ::
+
+  The path to the script.  The default is to grab the script from
+  [[https://orgmode.org/org-info.js]], but you might want to have a local
+  copy and use a path like =../scripts/org-info.js=.
+
+- =view:= ::
+
+  Initial view when the website is first shown.  Possible values are:
+
+  | =info=     | Info-like interface with one section per page          |
+  | =overview= | Folding interface, initially showing only top-level    |
+  | =content=  | Folding interface, starting with all headlines visible |
+  | =showall=  | Folding interface, all headlines and text visible      |
+
+- =sdepth:= ::
+
+  Maximum headline level still considered as an independent section
+  for info and folding modes.  The default is taken from
+  ~org-export-headline-levels~, i.e., the =H= switch in =OPTIONS=.  If
+  this is smaller than in ~org-export-headline-levels~, each
+  info/folding section can still contain child headlines.
+
+- =toc:= ::
+
+  Should the table of contents /initially/ be visible?  Even when
+  =nil=, you can always get to the "toc" with {{{kbd(i)}}}.
+
+- =tdepth:= ::
+
+  The depth of the table of contents.  The defaults are taken from the
+  variables ~org-export-headline-levels~ and ~org-export-with-toc~.
+
+- =ftoc:= ::
+
+  Does the CSS of the page specify a fixed position for the "toc"?  If
+  yes, the toc is displayed as a section.
+
+- =ltoc:= ::
+
+  Should there be short contents (children) in each section?  Make
+  this =above= if the section should be above initial text.
+
+- =mouse:= ::
+
+  Headings are highlighted when the mouse is over them.  Should be
+  =underline= (default) or a background color like =#cccccc=.
+
+- =buttons:= ::
+
+  Should view-toggle buttons be everywhere?  When =nil= (the default),
+  only one such button is present.
+
+#+vindex: org-infojs-options
+#+vindex: org-export-html-use-infojs
+You can choose default values for these options by customizing the
+variable ~org-infojs-options~.  If you always want to apply the script
+to your pages, configure the variable ~org-export-html-use-infojs~.
+
+** LaTeX Export
+:PROPERTIES:
+:DESCRIPTION: Exporting to @LaTeX{} and processing to PDF.
+:END:
+#+cindex: @LaTeX{} export
+#+cindex: PDF export
+
+The LaTeX export back-end can handle complex documents, incorporate
+standard or custom LaTeX document classes, generate documents using
+alternate LaTeX engines, and produce fully linked PDF files with
+indexes, bibliographies, and tables of contents, destined for
+interactive online viewing or high-quality print publication.
+
+While the details are covered in-depth in this section, here are some
+quick references to variables for the impatient: for engines, see
+~org-latex-compiler~; for build sequences, see
+~org-latex-pdf-process~; for packages, see
+~org-latex-default-packages-alist~ and ~org-latex-packages-alist~.
+
+An important note about the LaTeX export back-end: it is sensitive to
+blank lines in the Org document.  That's because LaTeX itself depends
+on blank lines to tell apart syntactical elements, such as paragraphs.
+
+*** LaTeX/PDF export commands
+:PROPERTIES:
+:DESCRIPTION: For producing @LaTeX{} and PDF documents.
+:END:
+
+- {{{kbd(C-c C-e l l)}}} (~org-latex-export-to-latex~) ::
+
+  #+kindex: C-c C-e l l
+  #+findex: org-latex-export-to-latex~
+  Export to a LaTeX file with a =.tex= extension.  For =myfile.org=,
+  Org exports to =myfile.tex=, overwriting without warning.
+
+- {{{kbd(C-c C-e l L)}}} (~org-latex-export-as-latex~) ::
+
+  #+kindex: C-c C-e l L
+  #+findex: org-latex-export-as-latex
+  Export to a temporary buffer.  Do not create a file.
+
+- {{{kbd(C-c C-e l p)}}} (~org-latex-export-to-pdf~) ::
+
+  #+kindex: C-c C-e l p
+  #+findex: org-latex-export-to-pdf
+  Export as LaTeX file and convert it to PDF file.
+
+- {{{kbd(C-c C-e l o)}}} ::
+
+  #+kindex: C-c C-e l o
+  Export as LaTeX file and convert it to PDF, then open the PDF using
+  the default viewer.
+
+- {{{kbd(M-x org-export-region-as-latex)}}} ::
+
+  Convert the region to LaTeX under the assumption that it was in Org
+  mode syntax before.  This is a global command that can be invoked in
+  any buffer.
+
+#+vindex: org-latex-compiler
+#+vindex: org-latex-bibtex-compiler
+#+vindex: org-latex-default-packages-alist
+#+cindex: pdflatex
+#+cindex: xelatex
+#+cindex: lualatex
+#+cindex: @samp{LATEX_COMPILER}, keyword
+The LaTeX export back-end can use any of these LaTeX engines:
+=pdflatex=, =xelatex=, and =lualatex=.  These engines compile LaTeX
+files with different compilers, packages, and output options.  The
+LaTeX export back-end finds the compiler version to use from
+~org-latex-compiler~ variable or the =#+LATEX_COMPILER= keyword in the
+Org file.  See the docstring for the
+~org-latex-default-packages-alist~ for loading packages with certain
+compilers.  Also see ~org-latex-bibtex-compiler~ to set the
+bibliography compiler[fn:133].
+
+*** LaTeX specific export settings
+:PROPERTIES:
+:DESCRIPTION: Unique to this @LaTeX{} back-end.
+:END:
+
+The LaTeX export back-end has several additional keywords for
+customizing LaTeX output.  Setting these keywords works similar to the
+general options (see [[*Export Settings]]).
+
+#+attr_texinfo: :sep ,
+- =DESCRIPTION= ::
+  #+cindex: @samp{DESCRIPTION}, keyword
+  #+vindex: org-latex-hyperref-template
+  #+vindex: org-latex-title-command
+  The document's description.  The description along with author name,
+  keywords, and related file metadata are inserted in the output file
+  by the hyperref package.  See ~org-latex-hyperref-template~ for
+  customizing metadata items.  See ~org-latex-title-command~ for
+  typesetting description into the document's front matter.  Use
+  multiple =DESCRIPTION= keywords for long descriptions.
+
+- =LANGUAGE= ::
+  #+cindex: @samp{LANGUAGE}, keyword
+  #+vindex: org-latex-packages-alist
+  In order to be effective, the =babel= or =polyglossia=
+  packages---according to the LaTeX compiler used---must be loaded
+  with the appropriate language as argument.  This can be accomplished
+  by modifying the ~org-latex-packages-alist~ variable, e.g., with the
+  following snippet:
+
+  #+begin_src emacs-lisp
+  (add-to-list 'org-latex-packages-alist
+               '("AUTO" "babel" t ("pdflatex")))
+  (add-to-list 'org-latex-packages-alist
+               '("AUTO" "polyglossia" t ("xelatex" "lualatex")))
+  #+end_src
+
+- =LATEX_CLASS= ::
+
+  #+cindex: @samp{LATEX_CLASS}, keyword
+  #+vindex: org-latex-default-class
+  #+vindex: org-latex-classes
+  This is LaTeX document class, such as /article/, /report/, /book/,
+  and so on, which contain predefined preamble and headline level
+  mapping that the LaTeX export back-end needs.  The back-end reads
+  the default class name from the ~org-latex-default-class~ variable.
+  Org has /article/ as the default class.  A valid default class must
+  be an element of ~org-latex-classes~.
+
+- =LATEX_CLASS_OPTIONS= ::
+
+  #+cindex: @samp{LATEX_CLASS_OPTIONS}, keyword
+  Options the LaTeX export back-end uses when calling the LaTeX
+  document class.
+
+- =LATEX_COMPILER= ::
+
+  #+cindex: @samp{LATEX_COMPILER}, keyword
+  #+vindex: org-latex-compiler
+  The compiler, such as =pdflatex=, =xelatex=, =lualatex=, for
+  producing the PDF.  See ~org-latex-compiler~.
+
+- =LATEX_HEADER=, =LATEX_HEADER_EXTRA= ::
+
+  #+cindex: @samp{LATEX_HEADER}, keyword
+  #+cindex: @samp{LATEX_HEADER_EXTRA}, keyword
+  #+vindex: org-latex-classes
+  Arbitrary lines to add to the document's preamble, before the
+  hyperref settings.  See ~org-latex-classes~ for adjusting the
+  structure and order of the LaTeX headers.
+
+- =KEYWORDS= ::
+
+  #+cindex: @samp{KEYWORDS}, keyword
+  #+vindex: org-latex-hyperref-template
+  #+vindex: org-latex-title-command
+  The keywords for the document.  The description along with author
+  name, keywords, and related file metadata are inserted in the output
+  file by the hyperref package.  See ~org-latex-hyperref-template~ for
+  customizing metadata items.  See ~org-latex-title-command~ for
+  typesetting description into the document's front matter.  Use
+  multiple =KEYWORDS= lines if necessary.
+
+- =SUBTITLE= ::
+
+  #+cindex: @samp{SUBTITLE}, keyword
+  #+vindex: org-latex-subtitle-separate
+  #+vindex: org-latex-subtitle-format
+  The document's subtitle.  It is typeset as per
+  ~org-latex-subtitle-format~.  If ~org-latex-subtitle-separate~ is
+  non-~nil~, it is typed outside of the ~\title~ macro.  See
+  ~org-latex-hyperref-template~ for customizing metadata items.  See
+  ~org-latex-title-command~ for typesetting description into the
+  document's front matter.
+
+The following sections have further details.
+
+*** LaTeX header and sectioning structure
+:PROPERTIES:
+:DESCRIPTION: Setting up the export file structure.
+:ALT_TITLE: LaTeX header and sectioning
+:END:
+#+cindex: @LaTeX{} class
+#+cindex: @LaTeX{} sectioning structure
+#+cindex: @LaTeX{} header
+#+cindex: header, for @LaTeX{} files
+#+cindex: sectioning structure, for @LaTeX{} export
+
+The LaTeX export back-end converts the first three of Org's outline
+levels into LaTeX headlines.  The remaining Org levels are exported as
+lists.  To change this globally for the cut-off point between levels
+and lists, (see [[*Export Settings]]).
+
+By default, the LaTeX export back-end uses the /article/ class.
+
+#+vindex: org-latex-default-class
+#+vindex: org-latex-classes
+#+vindex: org-latex-default-packages-alist
+#+vindex: org-latex-packages-alist
+To change the default class globally, edit ~org-latex-default-class~.
+To change the default class locally in an Org file, add option lines
+=#+LATEX_CLASS: myclass=.  To change the default class for just a part
+of the Org file, set a sub-tree property, =EXPORT_LATEX_CLASS=.  The
+class name entered here must be valid member of ~org-latex-classes~.
+This variable defines a header template for each class into which the
+exporter splices the values of ~org-latex-default-packages-alist~ and
+~org-latex-packages-alist~.  Use the same three variables to define
+custom sectioning or custom classes.
+
+#+cindex: @samp{LATEX_CLASS}, keyword
+#+cindex: @samp{LATEX_CLASS_OPTIONS}, keyword
+#+cindex: @samp{EXPORT_LATEX_CLASS}, property
+#+cindex: @samp{EXPORT_LATEX_CLASS_OPTIONS}, property
+The LaTeX export back-end sends the =LATEX_CLASS_OPTIONS= keyword and
+=EXPORT_LATEX_CLASS_OPTIONS= property as options to the LaTeX
+~\documentclass~ macro.  The options and the syntax for specifying
+them, including enclosing them in square brackets, follow LaTeX
+conventions.
+
+: #+LATEX_CLASS_OPTIONS: [a4paper,11pt,twoside,twocolumn]
+
+#+cindex: @samp{LATEX_HEADER}, keyword
+#+cindex: @samp{LATEX_HEADER_EXTRA}, keyword
+The LaTeX export back-end appends values from =LATEX_HEADER= and
+=LATEX_HEADER_EXTRA= keywords to the LaTeX header.  The docstring for
+~org-latex-classes~ explains in more detail.  Also note that LaTeX
+export back-end does not append =LATEX_HEADER_EXTRA= to the header
+when previewing LaTeX snippets (see [[*Previewing LaTeX fragments]]).
+
+A sample Org file with the above headers:
+
+#+begin_example
+,#+LATEX_CLASS: article
+,#+LATEX_CLASS_OPTIONS: [a4paper]
+,#+LATEX_HEADER: \usepackage{xyz}
+
+,* Headline 1
+  some text
+,* Headline 2
+  some more text
+#+end_example
+
+*** Quoting LaTeX code
+:PROPERTIES:
+:DESCRIPTION: Incorporating literal @LaTeX{} code.
+:END:
+
+The LaTeX export back-end can insert any arbitrary LaTeX code, see
+[[*Embedded LaTeX]].  There are three ways to embed such code in the Org
+file and they all use different quoting syntax.
+
+#+cindex: inline, in @LaTeX{} export
+Inserting in-line quoted with @ symbols:
+
+: Code embedded in-line @@latex:any arbitrary LaTeX code@@ in a paragraph.
+
+#+cindex: @samp{LATEX}, keyword
+Inserting as one or more keyword lines in the Org file:
+
+: #+LATEX: any arbitrary LaTeX code
+
+#+cindex: @samp{BEGIN_EXPORT latex}
+Inserting as an export block in the Org file, where the back-end
+exports any code between begin and end markers:
+
+#+begin_example
+,#+BEGIN_EXPORT latex
+  any arbitrary LaTeX code
+,#+END_EXPORT
+#+end_example
+
+*** Tables in LaTeX export
+:PROPERTIES:
+:DESCRIPTION: Options for exporting tables to @LaTeX{}.
+:END:
+#+cindex: tables, in @LaTeX{} export
+
+The LaTeX export back-end can pass several LaTeX attributes for table
+contents and layout.  Besides specifying a label (see [[*Internal Links]])
+and a caption (see [[*Captions]]), the other valid LaTeX attributes
+include:
+
+#+attr_texinfo: :sep ,
+- =:mode= ::
+
+  #+vindex: org-latex-default-table-mode
+  The LaTeX export back-end wraps the table differently depending on
+  the mode for accurate rendering of math symbols.  Mode is either
+  =table=, =math=, =inline-math= or =verbatim=.
+
+  For =math= or =inline-math= mode, LaTeX export back-end wraps the
+  table in a math environment, but every cell in it is exported as-is.
+  The LaTeX export back-end determines the default mode from
+  ~org-latex-default-table-mode~.  The LaTeX export back-end merges
+  contiguous tables in the same mode into a single environment.
+
+- =:environment= ::
+
+  #+vindex: org-latex-default-table-environment
+  Set the default LaTeX table environment for the LaTeX export
+  back-end to use when exporting Org tables.  Common LaTeX table
+  environments are provided by these packages: tabularx, longtable,
+  array, tabu, and bmatrix.  For packages, such as tabularx and tabu,
+  or any newer replacements, include them in the
+  ~org-latex-packages-alist~ variable so the LaTeX export back-end can
+  insert the appropriate load package headers in the converted LaTeX
+  file.  Look in the docstring for the ~org-latex-packages-alist~
+  variable for configuring these packages for LaTeX snippet previews,
+  if any.
+
+- =:caption= ::
+
+  Use =CAPTION= keyword to set a simple caption for a table (see
+  [[*Captions]]).  For custom captions, use =:caption= attribute, which
+  accepts raw LaTeX code.  =:caption= value overrides =CAPTION= value.
+
+- =:float=, =:placement= ::
+
+  The table environments by default are not floats in LaTeX.  To make
+  them floating objects use =:float= with one of the following
+  options: =sideways=, =multicolumn=, =t=, and =nil=.
+
+  LaTeX floats can also have additional layout =:placement=
+  attributes.  These are the usual =[h t b p ! H]= permissions
+  specified in square brackets.  Note that for =:float sideways=
+  tables, the LaTeX export back-end ignores =:placement= attributes.
+
+- =:align=, =:font=, =:width= ::
+
+  The LaTeX export back-end uses these attributes for regular tables
+  to set their alignments, fonts, and widths.
+
+- =:spread= ::
+
+  When =:spread= is non-~nil~, the LaTeX export back-end spreads or
+  shrinks the table by the =:width= for tabu and longtabu
+  environments.  =:spread= has no effect if =:width= is not set.
+
+- =:booktabs=, =:center=, =:rmlines= ::
+
+  #+vindex: org-latex-tables-booktabs
+  #+vindex: org-latex-tables-centered
+  All three commands are toggles.  =:booktabs= brings in modern
+  typesetting enhancements to regular tables.  The booktabs package
+  has to be loaded through ~org-latex-packages-alist~.  =:center= is
+  for centering the table.  =:rmlines= removes all but the very first
+  horizontal line made of ASCII characters from "table.el" tables
+  only.
+
+- =:math-prefix=, =:math-suffix=, =:math-arguments= ::
+
+  The LaTeX export back-end inserts =:math-prefix= string value in
+  a math environment before the table.  The LaTeX export back-end
+  inserts =:math-suffix= string value in a math environment after the
+  table.  The LaTeX export back-end inserts =:math-arguments= string
+  value between the macro name and the table's contents.
+  =:math-arguments= comes in use for matrix macros that require more
+  than one argument, such as =qbordermatrix=.
+
+LaTeX table attributes help formatting tables for a wide range of
+situations, such as matrix product or spanning multiple pages:
+
+#+begin_example
+,#+ATTR_LATEX: :environment longtable :align l|lp{3cm}r|l
+| ... | ... |
+| ... | ... |
+
+,#+ATTR_LATEX: :mode math :environment bmatrix :math-suffix \times
+| a | b |
+| c | d |
+,#+ATTR_LATEX: :mode math :environment bmatrix
+| 1 | 2 |
+| 3 | 4 |
+#+end_example
+
+Set the caption with the LaTeX command
+=\bicaption{HeadingA}{HeadingB}=:
+
+#+begin_example
+,#+ATTR_LATEX: :caption \bicaption{HeadingA}{HeadingB}
+| ... | ... |
+| ... | ... |
+#+end_example
+
+*** Images in LaTeX export
+:PROPERTIES:
+:DESCRIPTION: How to insert figures into @LaTeX{} output.
+:END:
+#+cindex: images, inline in LaTeX
+#+cindex: inlining images in LaTeX
+#+cindex: @samp{ATTR_LATEX}, keyword
+
+The LaTeX export back-end processes image links in Org files that do
+not have descriptions, such as these links =[[file:img.jpg]]= or
+=[[./img.jpg]]=, as direct image insertions in the final PDF output.  In
+the PDF, they are no longer links but actual images embedded on the
+page.  The LaTeX export back-end uses =\includegraphics= macro to
+insert the image.  But for TikZ (http://sourceforge.net/projects/pgf/)
+images, the back-end uses an ~\input~ macro wrapped within
+a ~tikzpicture~ environment.
+
+For specifying image =:width=, =:height=, =:scale= and other =:options=,
+use this syntax:
+
+#+begin_example
+,#+ATTR_LATEX: :width 5cm :options angle=90
+[[./img/sed-hr4049.pdf]]
+#+end_example
+
+A =:scale= attribute overrides both =:width= and =:height= attributes.
+
+For custom commands for captions, use the =:caption= attribute.  It
+overrides the default =#+CAPTION= value:
+
+#+begin_example
+,#+ATTR_LATEX: :caption \bicaption{HeadingA}{HeadingB}
+[[./img/sed-hr4049.pdf]]
+#+end_example
+
+When captions follow the method as described in [[*Captions]], the LaTeX
+export back-end wraps the picture in a floating =figure= environment.
+To float an image without specifying a caption, set the =:float=
+attribute to one of the following:
+
+- =t= ::
+
+  For a standard =figure= environment; used by default whenever an
+  image has a caption.
+
+- =multicolumn= ::
+
+  To span the image across multiple columns of a page; the back-end
+  wraps the image in a =figure*= environment.
+
+- =wrap= ::
+
+  For text to flow around the image on the right; the figure occupies
+  the left half of the page.
+
+- =sideways= ::
+
+  For a new page with the image sideways, rotated ninety degrees, in
+  a =sidewaysfigure= environment; overrides =:placement= setting.
+
+- =nil= ::
+
+  To avoid a =:float= even if using a caption.
+
+Use the =placement= attribute to modify a floating environment's
+placement.
+
+#+begin_example
+,#+ATTR_LATEX: :float wrap :width 0.38\textwidth :placement {r}{0.4\textwidth}
+[[./img/hst.png]]
+#+end_example
+
+#+vindex: org-latex-images-centered
+#+cindex: center image in LaTeX export
+#+cindex: image, centering in LaTeX export
+The LaTeX export back-end centers all images by default.  Setting
+=:center= to =nil= disables centering.  To disable centering globally,
+set ~org-latex-images-centered~ to =t=.
+
+Set the =:comment-include= attribute to non-~nil~ value for the LaTeX
+export back-end to comment out the =\includegraphics= macro.
+
+*** Plain lists in LaTeX export
+:PROPERTIES:
+:DESCRIPTION: Attributes specific to lists.
+:END:
+
+#+cindex: plain lists, in @LaTeX{} export
+#+cindex: @samp{ATTR_LATEX}, keyword
+The LaTeX export back-end accepts the =environment= and =options=
+attributes for plain lists.  Both attributes work together for
+customizing lists, as shown in the examples:
+
+#+begin_example
+,#+LATEX_HEADER: \usepackage[inline]{enumitem}
+Some ways to say "Hello":
+,#+ATTR_LATEX: :environment itemize*
+,#+ATTR_LATEX: :options [label={}, itemjoin={,}, itemjoin*={, and}]
+- Hola
+- Bonjour
+- Guten Tag.
+#+end_example
+
+Since LaTeX supports only four levels of nesting for lists, use an
+external package, such as =enumitem= in LaTeX, for levels deeper than
+four:
+
+#+begin_example
+,#+LATEX_HEADER: \usepackage{enumitem}
+,#+LATEX_HEADER: \renewlist{itemize}{itemize}{9}
+,#+LATEX_HEADER: \setlist[itemize]{label=$\circ$}
+- One
+  - Two
+    - Three
+      - Four
+        - Five
+#+end_example
+
+*** Source blocks in LaTeX export
+:PROPERTIES:
+:DESCRIPTION: Attributes specific to source code blocks.
+:END:
+#+cindex: source blocks, in @LaTeX{} export
+#+cindex: @samp{ATTR_LATEX}, keyword
+
+The LaTeX export back-end can make source code blocks into floating
+objects through the attributes =:float= and =:options=.  For =:float=:
+
+- =t= ::
+
+  Makes a source block float; by default floats any source block with
+  a caption.
+
+- =multicolumn= ::
+
+  Spans the source block across multiple columns of a page.
+
+- =nil= ::
+
+  Avoids a =:float= even if using a caption; useful for source code
+  blocks that may not fit on a page.
+
+#+begin_example
+,#+ATTR_LATEX: :float nil
+,#+BEGIN_SRC emacs-lisp
+  Lisp code that may not fit in a single page.
+,#+END_SRC
+#+end_example
+
+#+vindex: org-latex-listings-options
+#+vindex: org-latex-minted-options
+The LaTeX export back-end passes string values in =:options= to LaTeX
+packages for customization of that specific source block.  In the
+example below, the =:options= are set for Minted.  Minted is a source
+code highlighting LaTeX package with many configurable options.
+
+#+begin_example
+,#+ATTR_LATEX: :options commentstyle=\bfseries
+,#+BEGIN_SRC emacs-lisp
+  (defun Fib (n)
+    (if (< n 2) n (+ (Fib (- n 1)) (Fib (- n 2)))))
+,#+END_SRC
+#+end_example
+
+To apply similar configuration options for all source blocks in
+a file, use the ~org-latex-listings-options~ and
+~org-latex-minted-options~ variables.
+
+*** Example blocks in LaTeX export
+:PROPERTIES:
+:DESCRIPTION: Attributes specific to example blocks.
+:END:
+#+cindex: example blocks, in @LaTeX{} export
+#+cindex: verbatim blocks, in @LaTeX{} export
+#+cindex: @samp{ATTR_LATEX}, keyword
+
+The LaTeX export back-end wraps the contents of example blocks in
+a =verbatim= environment.  To change this behavior to use another
+environment globally, specify an appropriate export filter (see
+[[*Advanced Export Configuration]]).  To change this behavior to use
+another environment for each block, use the =:environment= parameter
+to specify a custom environment.
+
+#+begin_example
+,#+ATTR_LATEX: :environment myverbatim
+,#+BEGIN_EXAMPLE
+  This sentence is false.
+,#+END_EXAMPLE
+#+end_example
+
+*** Special blocks in LaTeX export
+:PROPERTIES:
+:DESCRIPTION: Attributes specific to special blocks.
+:END:
+
+#+cindex: special blocks, in @LaTeX{} export
+#+cindex: abstract, in @LaTeX{} export
+#+cindex: proof, in @LaTeX{} export
+#+cindex: @samp{ATTR_LATEX}, keyword
+
+For other special blocks in the Org file, the LaTeX export back-end
+makes a special environment of the same name.  The back-end also takes
+=:options=, if any, and appends as-is to that environment's opening
+string.  For example:
+
+#+begin_example
+,#+BEGIN_abstract
+  We demonstrate how to solve the Syracuse problem.
+,#+END_abstract
+
+,#+ATTR_LATEX: :options [Proof of important theorem]
+,#+BEGIN_proof
+  ...
+  Therefore, any even number greater than 2 is the sum of two primes.
+,#+END_proof
+#+end_example
+
+#+texinfo: @noindent
+exports to
+
+#+begin_example
+\begin{abstract}
+  We demonstrate how to solve the Syracuse problem.
+\end{abstract}
+
+\begin{proof}[Proof of important theorem]
+  ...
+  Therefore, any even number greater than 2 is the sum of two primes.
+\end{proof}
+#+end_example
+
+If you need to insert a specific caption command, use =:caption=
+attribute.  It overrides standard =CAPTION= value, if any.  For
+example:
+
+#+begin_example
+,#+ATTR_LATEX: :caption \MyCaption{HeadingA}
+,#+BEGIN_proof
+  ...
+,#+END_proof
+#+end_example
+
+*** Horizontal rules in LaTeX export
+:PROPERTIES:
+:DESCRIPTION: Attributes specific to horizontal rules.
+:END:
+#+cindex: horizontal rules, in @LaTeX{} export
+#+cindex: @samp{ATTR_LATEX}, keyword
+
+The LaTeX export back-end converts horizontal rules by the specified
+=:width= and =:thickness= attributes.  For example:
+
+#+begin_example
+,#+ATTR_LATEX: :width .6\textwidth :thickness 0.8pt
+-----
+#+end_example
+
+** Markdown Export
+:PROPERTIES:
+:DESCRIPTION: Exporting to Markdown.
+:END:
+#+cindex: Markdown export
+
+The Markdown export back-end, "md", converts an Org file to Markdown
+format, as defined at http://daringfireball.net/projects/markdown/.
+
+Since it is built on top of the HTML back-end (see [[*HTML Export]]), it
+converts every Org construct not defined in Markdown syntax, such as
+tables, to HTML.
+
+*** Markdown export commands
+:PROPERTIES:
+:UNNUMBERED: notoc
+:END:
+
+- {{{kbd(C-c C-e m m)}}} (~org-md-export-to-markdown~) ::
+
+  #+kindex: C-c C-c m m
+  #+findex: org-md-export-to-markdown
+  Export to a text file with Markdown syntax.  For =myfile.org=, Org
+  exports to =myfile.md=, overwritten without warning.
+
+- {{{kbd(C-c C-e m M)}}} (~org-md-export-as-markdown~) ::
+
+  #+kindex: C-c C-c m M
+  #+findex: org-md-export-as-markdown
+  Export to a temporary buffer.  Does not create a file.
+
+- {{{kbd(C-c C-e m o)}}} ::
+
+  #+kindex: C-c C-e m o
+  Export as a text file with Markdown syntax, then open it.
+
+*** Header and sectioning structure
+:PROPERTIES:
+:UNNUMBERED: notoc
+:END:
+
+#+vindex: org-md-headline-style
+Based on ~org-md-headline-style~, Markdown export can generate
+headlines of both /atx/ and /setext/ types.  /atx/ limits headline
+levels to two whereas /setext/ limits headline levels to six.  Beyond
+these limits, the export back-end converts headlines to lists.  To set
+a limit to a level before the absolute limit (see [[*Export Settings]]).
+
+** OpenDocument Text Export
+:PROPERTIES:
+:DESCRIPTION: Exporting to OpenDocument Text.
+:END:
+#+cindex: ODT
+#+cindex: OpenDocument
+#+cindex: export, OpenDocument
+#+cindex: LibreOffice
+
+The ODT export back-end handles creating of OpenDocument Text (ODT)
+format.  Documents created by this exporter use the
+{{{cite(OpenDocument-v1.2 specification)}}}[fn:134] and are compatible
+with LibreOffice 3.4.
+
+*** Pre-requisites for ODT export
+:PROPERTIES:
+:DESCRIPTION: Required packages.
+:END:
+#+cindex: zip
+
+The ODT export back-end relies on the zip program to create the final
+compressed ODT output.  Check if =zip= is locally available and
+executable.  Without it, export cannot finish.
+
+*** ODT export commands
+:PROPERTIES:
+:DESCRIPTION: Invoking export.
+:END:
+
+- {{{kbd(C-c C-e o o)}}} (~org-export-to-odt~) ::
+
+  #+kindex: C-c C-e o o
+  #+findex: org-export-to-odt
+  Export as OpenDocument Text file.
+
+  #+cindex: @samp{EXPORT_FILE_NAME}, property
+  #+vindex: org-odt-preferred-output-format
+
+  If ~org-odt-preferred-output-format~ is specified, the ODT export
+  back-end automatically converts the exported file to that format.
+
+  For =myfile.org=, Org exports to =myfile.odt=, overwriting without
+  warning.  The ODT export back-end exports a region only if a region
+  was active.
+
+  If the selected region is a single tree, the ODT export back-end
+  makes the tree head the document title.  Incidentally, {{{kbd(C-c
+  @)}}} selects the current sub-tree.  If the tree head entry has, or
+  inherits, an =EXPORT_FILE_NAME= property, the ODT export back-end
+  uses that for file name.
+
+- {{{kbd(C-c C-e o O)}}} ::
+
+  #+kindex: C-c C-e o O
+  Export as an OpenDocument Text file and open the resulting file.
+
+  #+vindex: org-export-odt-preferred-output-format
+  If ~org-export-odt-preferred-output-format~ is specified, open the
+  converted file instead.  See [[*Automatically exporting to other
+  formats]].
+
+*** ODT specific export settings
+:PROPERTIES:
+:DESCRIPTION: Configuration options.
+:END:
+
+The ODT export back-end has several additional keywords for
+customizing ODT output.  Setting these keywords works similar to the
+general options (see [[*Export Settings]]).
+
+- =DESCRIPTION= ::
+
+  #+cindex: @samp{DESCRIPTION}, keyword
+  This is the document's description, which the ODT export back-end
+  inserts as document metadata.  For long descriptions, use multiple
+  lines, prefixed with =DESCRIPTION=.
+
+- =KEYWORDS= ::
+
+  #+cindex: @samp{KEYWORDS}, keyword
+  The keywords for the document.  The ODT export back-end inserts the
+  description along with author name, keywords, and related file
+  metadata as metadata in the output file.  Use multiple =KEYWORDS= if
+  necessary.
+
+- =ODT_STYLES_FILE= ::
+
+  #+cindex: @samp{ODT_STYLES_FILE}, keyword
+  #+vindex: org-odt-styles-file
+  The ODT export back-end uses the ~org-odt-styles-file~ by default.
+  See [[*Applying custom styles]] for details.
+
+- =SUBTITLE= ::
+
+  #+cindex: @samp{SUBTITLE}, keyword
+  The document subtitle.
+
+*** Extending ODT export
+:PROPERTIES:
+:DESCRIPTION: Producing DOC, PDF files.
+:END:
+
+The ODT export back-end can produce documents in other formats besides
+ODT using a specialized ODT converter process.  Its common interface
+works with popular converters to produce formats such as =doc=, or
+convert a document from one format, say =csv=, to another format, say
+=xls=.
+
+#+cindex: @file{unoconv}
+#+vindex: org-odt-convert-process
+Customize ~org-odt-convert-process~ variable to point to =unoconv=,
+which is the ODT's preferred converter.  Working installations of
+LibreOffice would already have =unoconv= installed.  Alternatively,
+other converters may be substituted here.  See [[*Configuring
+a document converter]].
+
+**** Automatically exporting to other formats
+:PROPERTIES:
+:UNNUMBERED: notoc
+:END:
+
+#+vindex: org-odt-preferred-output-format
+If ODT format is just an intermediate step to get to other formats,
+such as =doc=, =docx=, =rtf=, or =pdf=, etc., then extend the ODT
+export back-end to directly produce that format.  Specify the final
+format in the ~org-odt-preferred-output-format~ variable.  This is one
+way to extend (see [[*ODT export commands]]).
+
+**** Converting between document formats
+:PROPERTIES:
+:UNNUMBERED: notoc
+:END:
+
+The Org export back-end is made to be inter-operable with a wide range
+of text document format converters.  Newer generation converters, such
+as LibreOffice and Pandoc, can handle hundreds of formats at once.
+Org provides a consistent interaction with whatever converter is
+installed.  Here are some generic commands:
+
+- {{{kbd(M-x org-odt-convert)}}} ::
+
+  #+findex: org-odt-convert
+  Convert an existing document from one format to another.  With
+  a prefix argument, opens the newly produced file.
+
+*** Applying custom styles
+:PROPERTIES:
+:DESCRIPTION: Styling the output.
+:END:
+#+cindex: styles, custom
+#+cindex: template, custom
+
+The ODT export back-end comes with many OpenDocument styles (see
+[[*Working with OpenDocument style files]]).  To expand or further
+customize these built-in style sheets, either edit the style sheets
+directly or generate them using an application such as LibreOffice.
+The example here shows creating a style using LibreOffice.
+
+**** Applying custom styles: the easy way
+:PROPERTIES:
+:UNNUMBERED: notoc
+:END:
+
+1. Create a sample =example.org= file with settings as shown below,
+   and export it to ODT format.
+
+   : #+OPTIONS: H:10 num:t
+
+2. Open the above =example.odt= using LibreOffice.  Use the /Stylist/
+   to locate the target styles, which typically have the "Org" prefix.
+   Open one, modify, and save as either OpenDocument Text (ODT) or
+   OpenDocument Template (OTT) file.
+
+3.
+   #+vindex: org-odt-styles-file
+   Customize the variable ~org-odt-styles-file~ and point it to the
+   newly created file.  For additional configuration options, see
+   [[x-overriding-factory-styles][Overriding factory styles]].
+
+   #+cindex: @samp{ODT_STYLES_FILE}, keyword
+   To apply an ODT style to a particular file, use the
+   =ODT_STYLES_FILE= keyword as shown in the example below:
+
+   : #+ODT_STYLES_FILE: "/path/to/example.ott"
+
+   #+texinfo: @noindent
+   or
+
+   : #+ODT_STYLES_FILE: ("/path/to/file.ott" ("styles.xml" "image/hdr.png"))
+
+**** Using third-party styles and templates
+:PROPERTIES:
+:UNNUMBERED: notoc
+:END:
+
+The ODT export back-end relies on many templates and style names.
+Using third-party styles and templates can lead to mismatches.
+Templates derived from built in ODT templates and styles seem to have
+fewer problems.
+
+*** Links in ODT export
+:PROPERTIES:
+:DESCRIPTION: Handling and formatting links.
+:END:
+#+cindex: links, in ODT export
+
+ODT exporter creates native cross-references for internal links.  It
+creates Internet-style links for all other links.
+
+A link with no description and pointing to a regular, un-itemized,
+outline heading is replaced with a cross-reference and section number
+of the heading.
+
+A =\ref{label}=-style reference to an image, table etc., is replaced
+with a cross-reference and sequence number of the labeled entity.  See
+[[*Labels and captions in ODT export]].
+
+*** Tables in ODT export
+:PROPERTIES:
+:DESCRIPTION: Org tables conversions.
+:END:
+
+#+cindex: tables, in ODT export
+
+The ODT export back-end handles native Org mode tables (see [[*Tables]])
+and simple =table.el= tables.  Complex =table.el= tables having column
+or row spans are not supported.  Such tables are stripped from the
+exported document.
+
+By default, the ODT export back-end exports a table with top and
+bottom frames and with ruled lines separating row and column groups
+(see [[*Column Groups]]).  All tables are typeset to occupy the same
+width.  The ODT export back-end honors any table alignments and
+relative widths for columns (see [[*Column Width and Alignment]]).
+
+Note that the ODT export back-end interprets column widths as weighted
+ratios, the default weight being 1.
+
+#+cindex: @samp{ATTR_ODT}, keyword
+Specifying =:rel-width= property on an =ATTR_ODT= line controls the
+width of the table.  For example:
+
+#+begin_example
+,#+ATTR_ODT: :rel-width 50
+| Area/Month    |   Jan |   Feb |   Mar |   Sum |
+|---------------+-------+-------+-------+-------|
+| /             |     < |       |       |     < |
+| <l13>         |  <r5> |  <r5> |  <r5> |  <r6> |
+| North America |     1 |    21 |   926 |   948 |
+| Middle East   |     6 |    75 |   844 |   925 |
+| Asia Pacific  |     9 |    27 |   790 |   826 |
+|---------------+-------+-------+-------+-------|
+| Sum           |    16 |   123 |  2560 |  2699 |
+#+end_example
+
+On export, the above table takes 50% of text width area.  The exporter
+sizes the columns in the ratio: 13:5:5:5:6.  The first column is
+left-aligned and rest of the columns, right-aligned.  Vertical rules
+separate the header and the last column.  Horizontal rules separate
+the header and the last row.
+
+For even more customization, create custom table styles and associate
+them with a table using the =ATTR_ODT= keyword.  See [[*Customizing
+tables in ODT export]].
+
+*** Images in ODT export
+:PROPERTIES:
+:DESCRIPTION: Inserting images.
+:END:
+#+cindex: images, embedding in ODT
+#+cindex: embedding images in ODT
+
+**** Embedding images
+:PROPERTIES:
+:UNNUMBERED: notoc
+:END:
+
+The ODT export back-end processes image links in Org files that do not
+have descriptions, such as these links =[[file:img.jpg]]= or =[[./img.jpg]]=,
+as direct image insertions in the final output.  Either of these
+examples works:
+
+: [[file:img.png]]
+
+: [[./img.png]]
+
+**** Embedding clickable images
+:PROPERTIES:
+:UNNUMBERED: notoc
+:END:
+
+For clickable images, provide a link whose description is another link
+to an image file.  For example, to embed an image
+=org-mode-unicorn.png= which when clicked jumps to https://orgmode.org
+website, do the following
+
+: [[https://orgmode.org][./org-mode-unicorn.png]]
+
+**** Sizing and scaling of embedded images
+:PROPERTIES:
+:UNNUMBERED: notoc
+:END:
+
+#+cindex: @samp{ATTR_ODT}, keyword
+
+Control the size and scale of the embedded images with the =ATTR_ODT=
+attribute.
+
+#+cindex: identify, ImageMagick
+#+vindex: org-odt-pixels-per-inch
+The ODT export back-end starts with establishing the size of the image
+in the final document.  The dimensions of this size are measured in
+centimeters.  The back-end then queries the image file for its
+dimensions measured in pixels.  For this measurement, the back-end
+relies on ImageMagick's identify program or Emacs ~create-image~ and
+~image-size~ API.  ImageMagick is the preferred choice for large file
+sizes or frequent batch operations.  The back-end then converts the
+pixel dimensions using ~org-odt-pixels-per-inch~ into the familiar 72
+dpi or 96 dpi.  The default value for this is in
+~display-pixels-per-inch~, which can be tweaked for better results
+based on the capabilities of the output device.  Here are some common
+image scaling operations:
+
+- Explicitly size the image ::
+
+  To embed =img.png= as a 10 cm x 10 cm image, do the following:
+
+  #+begin_example
+  ,#+ATTR_ODT: :width 10 :height 10
+  [[./img.png]]
+  #+end_example
+
+- Scale the image ::
+
+  To embed =img.png= at half its size, do the following:
+
+  #+begin_example
+  ,#+ATTR_ODT: :scale 0.5
+  [[./img.png]]
+  #+end_example
+
+- Scale the image to a specific width ::
+
+  To embed =img.png= with a width of 10 cm while retaining the
+  original height:width ratio, do the following:
+
+  #+begin_example
+  ,#+ATTR_ODT: :width 10
+  [[./img.png]]
+  #+end_example
+
+- Scale the image to a specific height ::
+
+  To embed =img.png= with a height of 10 cm while retaining the
+  original height:width ratio, do the following:
+
+  #+begin_example
+  ,#+ATTR_ODT: :height 10
+  [[./img.png]]
+  #+end_example
+
+**** Anchoring of images
+:PROPERTIES:
+:UNNUMBERED: notoc
+:END:
+
+#+cindex: @samp{ATTR_ODT}, keyword
+The ODT export back-end can anchor images to =as-char=, =paragraph=,
+or =page=.  Set the preferred anchor using the =:anchor= property of
+the =ATTR_ODT= line.
+
+To create an image that is anchored to a page:
+
+#+begin_example
+,#+ATTR_ODT: :anchor page
+[[./img.png]]
+#+end_example
+
+*** Math formatting in ODT export
+:PROPERTIES:
+:DESCRIPTION: Formatting @LaTeX{} fragments.
+:END:
+
+The ODT exporter has special support for handling math.
+
+**** LaTeX math snippets
+:PROPERTIES:
+:DESCRIPTION: Embedding in @LaTeX{} format.
+:END:
+
+LaTeX math snippets (see [[*LaTeX fragments]]) can be embedded in the ODT
+document in one of the following ways:
+
+- MathML ::
+
+  #+cindex: MathML
+  Add this line to the Org file.  This option is activated on
+  a per-file basis.
+
+  : #+OPTIONS: tex:t
+
+  With this option, LaTeX fragments are first converted into MathML
+  fragments using an external LaTeX-to-MathML converter program.  The
+  resulting MathML fragments are then embedded as an OpenDocument
+  Formula in the exported document.
+
+  #+vindex: org-latex-to-mathml-convert-command
+  #+vindex: org-latex-to-mathml-jar-file
+  You can specify the LaTeX-to-MathML converter by customizing the
+  variables ~org-latex-to-mathml-convert-command~ and
+  ~org-latex-to-mathml-jar-file~.
+
+  If you prefer to use MathToWeb[fn:135] as your converter, you can
+  configure the above variables as shown below.
+
+  #+begin_src emacs-lisp
+  (setq org-latex-to-mathml-convert-command
+        "java -jar %j -unicode -force -df %o %I"
+        org-latex-to-mathml-jar-file
+        "/path/to/mathtoweb.jar")
+  #+end_src
+
+  #+texinfo: @noindent
+  or, to use LaTeX​ML[fn:136] instead,
+
+  #+begin_src emacs-lisp
+  (setq org-latex-to-mathml-convert-command
+        "latexmlmath \"%i\" --presentationmathml=%o")
+  #+end_src
+
+  To quickly verify the reliability of the LaTeX-to-MathML
+  converter, use the following commands:
+
+  - {{{kbd(M-x org-export-as-odf)}}} ::
+
+    Convert a LaTeX math snippet to an OpenDocument formula (=.odf=)
+    file.
+
+  - {{{kbd(M-x org-export-as-odf-and-open)}}} ::
+
+    Convert a LaTeX math snippet to an OpenDocument formula (=.odf=)
+    file and open the formula file with the system-registered
+    application.
+
+- PNG images ::
+
+  #+cindex: dvipng
+  #+cindex: dvisvgm
+  #+cindex: ImageMagick
+  Add this line to the Org file.  This option is activated on
+  a per-file basis.
+
+  : #+OPTIONS: tex:dvipng
+
+  : #+OPTIONS: tex:dvisvgm
+
+  #+texinfo: @noindent
+  or
+
+  : #+OPTIONS: tex:imagemagick
+
+  Under this option, LaTeX fragments are processed into PNG or SVG
+  images and the resulting images are embedded in the exported
+  document.  This method requires dvipng program, dvisvgm or
+  ImageMagick programs.
+
+**** MathML and OpenDocument formula files
+:PROPERTIES:
+:DESCRIPTION: Embedding in native format.
+:END:
+
+When embedding LaTeX math snippets in ODT documents is not reliable,
+there is one more option to try.  Embed an equation by linking to its
+MathML (=.mml=) source or its OpenDocument formula (=.odf=) file as
+shown below:
+
+: [[./equation.mml]]
+
+#+texinfo: @noindent
+or
+
+: [[./equation.odf]]
+
+*** Labels and captions in ODT export
+:PROPERTIES:
+:DESCRIPTION: Rendering objects.
+:END:
+
+ODT format handles labeling and captioning of objects based on their
+types.  Inline images, tables, LaTeX fragments, and Math formulas are
+numbered and captioned separately.  Each object also gets a unique
+sequence number based on its order of first appearance in the Org
+file.  Each category has its own sequence.  A caption is just a label
+applied to these objects.
+
+#+begin_example
+,#+CAPTION: Bell curve
+,#+NAME:   fig:SED-HR4049
+[[./img/a.png]]
+#+end_example
+
+When rendered, it may show as follows in the exported document:
+
+: Figure 2: Bell curve
+
+#+vindex: org-odt-category-map-alist
+To modify the category component of the caption, customize the option
+~org-odt-category-map-alist~.  For example, to tag embedded images
+with the string "Illustration" instead of the default string "Figure",
+use the following setting:
+
+#+begin_src emacs-lisp
+(setq org-odt-category-map-alist
+      '(("__Figure__" "Illustration" "value" "Figure" 
org-odt--enumerable-image-p)))
+#+end_src
+
+With the above modification, the previous example changes to:
+
+: Illustration 2: Bell curve
+
+*** Literal examples in ODT export
+:PROPERTIES:
+:DESCRIPTION: For source code and example blocks.
+:END:
+
+The ODT export back-end supports literal examples (see [[*Literal
+Examples]]) with full fontification.  Internally, the ODT export
+back-end relies on =htmlfontify.el= to generate the style definitions
+needed for fancy listings.  The auto-generated styles get =OrgSrc=
+prefix and inherit colors from the faces used by Emacs Font Lock
+library for that source language.
+
+#+vindex: org-odt-fontify-srcblocks
+For custom fontification styles, customize the
+~org-odt-create-custom-styles-for-srcblocks~ option.
+
+#+vindex: org-odt-create-custom-styles-for-srcblocks
+To turn off fontification of literal examples, customize the
+~org-odt-fontify-srcblocks~ option.
+
+*** Advanced topics in ODT export
+:PROPERTIES:
+:DESCRIPTION: For power users.
+:END:
+
+The ODT export back-end has extensive features useful for power users
+and frequent uses of ODT formats.
+
+**** Configuring a document converter
+:PROPERTIES:
+:DESCRIPTION: Registering a document converter.
+:UNNUMBERED: notoc
+:END:
+#+cindex: convert
+#+cindex: doc, docx, rtf
+#+cindex: converter
+
+The ODT export back-end works with popular converters with little or
+no extra configuration.  See [[*Extending ODT export]].  The following is
+for unsupported converters or tweaking existing defaults.
+
+- Register the converter ::
+
+  #+vindex: org-export-odt-convert-processes
+  Add the name of the converter to the ~org-odt-convert-processes~
+  variable.  Note that it also requires how the converter is invoked
+  on the command line.  See the variable's docstring for details.
+
+- Configure its capabilities ::
+
+  #+vindex: org-export-odt-convert-capabilities
+  Specify which formats the converter can handle by customizing the
+  variable ~org-odt-convert-capabilities~.  Use the entry for the
+  default values in this variable for configuring the new converter.
+  Also see its docstring for details.
+
+- Choose the converter ::
+
+  #+vindex: org-export-odt-convert-process
+  Select the newly added converter as the preferred one by customizing
+  the option ~org-odt-convert-process~.
+
+**** Working with OpenDocument style files
+:PROPERTIES:
+:DESCRIPTION: Exploring internals.
+:UNNUMBERED: notoc
+:END:
+#+cindex: styles, custom
+#+cindex: template, custom
+
+This section explores the internals of the ODT exporter; the means by which
+it produces styled documents; the use of automatic and custom OpenDocument
+styles.
+
+The ODT exporter relies on two files for generating its output.  These
+files are bundled with the distribution under the directory pointed to
+by the variable ~org-odt-styles-dir~.  The two files are:
+
+- =OrgOdtStyles.xml= <<x-orgodtstyles-xml>> ::
+
+  This file contributes to the =styles.xml= file of the final ODT
+  document.  This file gets modified for the following purposes:
+
+  1. To control outline numbering based on user settings;
+
+  2. To add styles generated by =htmlfontify.el= for fontification of
+     code blocks.
+
+- =OrgOdtContentTemplate.xml= <<x-orgodtcontenttemplate-xml>> ::
+
+  This file contributes to the =content.xml= file of the final ODT
+  document.  The contents of the Org outline are inserted between the
+  =<office:text>= ... =</office:text>= elements of this file.
+
+  Apart from serving as a template file for the final =content.xml=,
+  the file serves the following purposes:
+
+  1. It contains automatic styles for formatting of tables which are
+     referenced by the exporter;
+
+  2. It contains =<text:sequence-decl>= ... =</text:sequence-decl>=
+     elements that control numbering of tables, images, equations, and
+     similar entities.
+
+<<x-overriding-factory-styles>> The following two variables control
+the location from where the ODT exporter picks up the custom styles
+and content template files.  Customize these variables to override the
+factory styles used by the exporter.
+
+- ~org-odt-styles-file~ ::
+
+  The ODT export back-end uses the file pointed to by this variable,
+  such as =styles.xml=, for the final output.  It can take one of the
+  following values:
+
+  - =FILE.xml= ::
+
+    Use this file instead of the default =styles.xml=
+
+  - =FILE.odt= or =FILE.ott= ::
+
+    Use the =styles.xml= contained in the specified OpenDocument
+    Text or Template file
+
+  - =FILE.odt= or =FILE.ott= and a subset of included files ::
+
+    Use the =styles.xml= contained in the specified OpenDocument Text
+    or Template file.  Additionally extract the specified member files
+    and embed those within the final ODT document.
+
+    Use this option if the =styles.xml= file references additional
+    files like header and footer images.
+
+  - ~nil~ ::
+
+    Use the default =styles.xml=.
+
+- ~org-odt-content-template-file~ ::
+
+  Use this variable to specify the blank =content.xml= used in the
+  final output.
+
+**** Creating one-off styles
+:PROPERTIES:
+:DESCRIPTION: Customizing styles, highlighting...
+:UNNUMBERED: notoc
+:END:
+
+The ODT export back-end can read embedded raw OpenDocument XML from
+the Org file.  Such direct formatting is useful for one-off instances.
+
+- Embedding ODT tags as part of regular text ::
+
+  Enclose OpenDocument syntax in =@@odt:...@@= for inline markup.  For
+  example, to highlight a region of text do the following:
+
+  #+begin_example
+  @@odt:<text:span text:style-name="Highlight">This is highlighted
+  text</text:span>@@.  But this is regular text.
+  #+end_example
+
+  *Hint:* To see the above example in action, edit the =styles.xml=
+  (see [[x-orgodtstyles-xml][Factory styles]]) and add a custom /Highlight/ 
style as shown
+  below:
+
+  #+begin_example
+  <style:style style:name="Highlight" style:family="text">
+    <style:text-properties fo:background-color="#ff0000"/>
+  </style:style>
+  #+end_example
+
+- Embedding a one-line OpenDocument XML ::
+
+  #+cindex: @samp{ODT}, keyword
+  The ODT export back-end can read one-liner options with =#+ODT:= in
+  the Org file.  For example, to force a page break:
+
+  #+begin_example
+  ,#+ODT: <text:p text:style-name="PageBreak"/>
+  #+end_example
+
+  *Hint:* To see the above example in action, edit your
+  =styles.xml= (see [[x-orgodtstyles-xml][Factory styles]]) and add a custom 
=PageBreak=
+  style as shown below.
+
+  #+begin_example
+  <style:style style:name="PageBreak" style:family="paragraph"
+               style:parent-style-name="Text_20_body">
+    <style:paragraph-properties fo:break-before="page"/>
+  </style:style>
+  #+end_example
+
+- Embedding a block of OpenDocument XML ::
+
+  The ODT export back-end can also read ODT export blocks for
+  OpenDocument XML.  Such blocks use the =#+BEGIN_EXPORT odt=
+  ... =#+END_EXPORT= constructs.
+
+  For example, to create a one-off paragraph that uses bold text, do
+  the following:
+
+  #+begin_example
+  ,#+BEGIN_EXPORT odt
+    <text:p text:style-name="Text_20_body_20_bold">
+    This paragraph is specially formatted and uses bold text.
+    </text:p>
+  ,#+END_EXPORT
+  #+end_example
+
+**** Customizing tables in ODT export
+:PROPERTIES:
+:DESCRIPTION: Defining table templates.
+:UNNUMBERED: notoc
+:END:
+#+cindex: tables, in ODT export
+#+cindex: @samp{ATTR_ODT}, keyword
+
+Override the default table format by specifying a custom table style
+with the =#+ATTR_ODT= line.  For a discussion on default formatting of
+tables, see [[*Tables in ODT export]].
+
+This feature closely mimics the way table templates are defined in the
+OpenDocument-v1.2 specification[fn:137].
+
+#+vindex: org-odt-table-styles
+For quick preview of this feature, install the settings below and export the
+table that follows:
+
+#+begin_src emacs-lisp
+(setq org-export-odt-table-styles
+      (append org-export-odt-table-styles
+              '(("TableWithHeaderRowAndColumn" "Custom"
+                 ((use-first-row-styles . t)
+                  (use-first-column-styles . t)))
+                ("TableWithFirstRowandLastRow" "Custom"
+                 ((use-first-row-styles . t)
+                  (use-last-row-styles . t))))))
+#+end_src
+
+#+begin_example
+,#+ATTR_ODT: :style TableWithHeaderRowAndColumn
+| Name  | Phone | Age |
+| Peter |  1234 |  17 |
+| Anna  |  4321 |  25 |
+#+end_example
+
+The example above used =Custom= template and installed two table
+styles =TableWithHeaderRowAndColumn= and
+=TableWithFirstRowandLastRow=.  *Important:* The OpenDocument styles
+needed for producing the above template were pre-defined.  They are
+available in the section marked =Custom Table Template= in
+=OrgOdtContentTemplate.xml= (see [[x-orgodtcontenttemplate-xml][Factory 
styles]]).  For adding new
+templates, define new styles there.
+
+To use this feature proceed as follows:
+
+1. Create a table template[fn:138].
+
+   A table template is set of =table-cell= and =paragraph= styles for
+   each of the following table cell categories:
+
+   - Body
+   - First column
+   - Last column
+   - First row
+   - Last row
+   - Even row
+   - Odd row
+   - Even column
+   - Odd Column
+
+   The names for the above styles must be chosen based on the name of
+   the table template using a well-defined convention.
+
+   The naming convention is better illustrated with an example.  For
+   a table template with the name =Custom=, the needed style names are
+   listed in the following table.
+
+   | Cell type    | Cell style                   | Paragraph style             
      |
+   
|--------------+------------------------------+-----------------------------------|
+   | Body         | =CustomTableCell=            | =CustomTableParagraph=      
      |
+   | First column | =CustomFirstColumnTableCell= | 
=CustomFirstColumnTableParagraph= |
+   | Last column  | =CustomLastColumnTableCell=  | 
=CustomLastColumnTableParagraph=  |
+   | First row    | =CustomFirstRowTableCell=    | 
=CustomFirstRowTableParagraph=    |
+   | Last row     | =CustomLastRowTableCell=     | 
=CustomLastRowTableParagraph=     |
+   | Even row     | =CustomEvenRowTableCell=     | 
=CustomEvenRowTableParagraph=     |
+   | Odd row      | =CustomOddRowTableCell=      | 
=CustomOddRowTableParagraph=      |
+   | Even column  | =CustomEvenColumnTableCell=  | 
=CustomEvenColumnTableParagraph=  |
+   | Odd column   | =CustomOddColumnTableCell=   | 
=CustomOddColumnTableParagraph=   |
+
+   To create a table template with the name =Custom=, define the above
+   styles in the =<office:automatic-styles>= ...
+   =</office:automatic-styles>= element of the content template file
+   (see [[x-orgodtcontenttemplate-xml][Factory styles]]).
+
+2. Define a table style[fn:139].
+
+   #+vindex: org-odt-table-styles
+   To define a table style, create an entry for the style in the
+   variable ~org-odt-table-styles~ and specify the following:
+
+   - the name of the table template created in step (1),
+   - the set of cell styles in that template that are to be activated.
+
+   For example, the entry below defines two different table styles
+   =TableWithHeaderRowAndColumn= and =TableWithFirstRowandLastRow=
+   based on the same template =Custom=.  The styles achieve their
+   intended effect by selectively activating the individual cell
+   styles in that template.
+
+   #+begin_src emacs-lisp
+   (setq org-export-odt-table-styles
+         (append org-export-odt-table-styles
+                 '(("TableWithHeaderRowAndColumn" "Custom"
+                    ((use-first-row-styles . t)
+                     (use-first-column-styles . t)))
+                   ("TableWithFirstRowandLastRow" "Custom"
+                    ((use-first-row-styles . t)
+                     (use-last-row-styles . t))))))
+   #+end_src
+
+3. Associate a table with the table style.
+
+   To do this, specify the table style created in step (2) as part of
+   the =ATTR_ODT= line as shown below.
+
+   #+begin_example
+   ,#+ATTR_ODT: :style TableWithHeaderRowAndColumn
+   | Name  | Phone | Age |
+   | Peter |  1234 |  17 |
+   | Anna  |  4321 |  25 |
+   #+end_example
+
+**** Validating OpenDocument XML
+:PROPERTIES:
+:DESCRIPTION: Debugging corrupted OpenDocument files.
+:UNNUMBERED: notoc
+:END:
+
+Sometimes ODT format files may not open due to =.odt= file corruption.
+To verify if such a file is corrupt, validate it against the
+OpenDocument Relax NG Compact (RNC) syntax schema.  But first the
+=.odt= files have to be decompressed using =zip=.  Note that =.odt=
+files are ZIP archives: [[info:emacs::File Archives]].  The contents of
+ODT files are in XML.  For general help with validation---and
+schema-sensitive editing---of XML files: [[info:nxml-mode::Introduction]].
+
+#+vindex: org-export-odt-schema-dir
+Customize ~org-odt-schema-dir~ to point to a directory with
+OpenDocument RNC files and the needed schema-locating rules.  The ODT
+export back-end takes care of updating the
+~rng-schema-locating-files~.
+
+** Org Export
+:PROPERTIES:
+:DESCRIPTION: Exporting to Org.
+:END:
+
+#+cindex: Org export
+/org/ export back-end creates a normalized version of the Org document
+in current buffer.  The exporter evaluates Babel code (see [[*Evaluating
+Code Blocks]]) and removes content specific to other back-ends.
+
+*** Org export commands
+:PROPERTIES:
+:UNNUMBERED: notoc
+:END:
+
+- {{{kbd(C-c C-e O o)}}} (~org-org-export-to-org~) ::
+
+  #+kindex: C-c C-e O o
+  #+findex: org-org-export-to-org
+  Export as an Org file with a =.org= extension.  For =myfile.org=,
+  Org exports to =myfile.org.org=, overwriting without warning.
+
+- {{{kbd(C-c C-e O v)}}} (~~) ::
+
+  #+kindex: C-c C-e O v
+  Export to an Org file, then open it.
+
+** Texinfo Export
+:PROPERTIES:
+:DESCRIPTION: Exporting to Texinfo.
+:END:
+
+*** Texinfo export commands
+:PROPERTIES:
+:DESCRIPTION: Invoking commands.
+:END:
+
+- {{{kbd(C-c C-e i t)}}} (~org-texinfo-export-to-texinfo~) ::
+
+  #+kindex: C-c C-e i t
+  #+findex: org-texinfo-export-to-texinfo
+  Export as a Texinfo file with =.texi= extension.  For =myfile.org=,
+  Org exports to =myfile.texi=, overwriting without warning.
+
+- {{{kbd(C-c C-e i i)}}} (~org-texinfo-export-to-info~) ::
+
+  #+kindex: C-c C-e i i
+  #+findex: org-texinfo-export-to-info
+  #+vindex: org-texinfo-info-process
+  Export to Texinfo format first and then process it to make an Info
+  file.  To generate other formats, such as DocBook, customize the
+  ~org-texinfo-info-process~ variable.
+
+*** Texinfo specific export settings
+:PROPERTIES:
+:DESCRIPTION: Setting the environment.
+:END:
+
+The Texinfo export back-end has several additional keywords for
+customizing Texinfo output.  Setting these keywords works similar to
+the general options (see [[*Export Settings]]).
+
+- =SUBTITLE= ::
+
+  #+cindex: @samp{SUBTITLE}, keyword
+  The document subtitle.
+
+- =SUBAUTHOR= ::
+
+  #+cindex: @samp{SUBAUTHOR}, keyword
+  Additional authors for the document.
+
+- =TEXINFO_FILENAME= ::
+
+  #+cindex: @samp{TEXINFO_FILENAME}, keyword
+  The Texinfo filename.
+
+- =TEXINFO_CLASS= ::
+
+  #+cindex: @samp{TEXINFO_CLASS}, keyword
+  #+vindex: org-texinfo-default-class
+  The default document class (~org-texinfo-default-class~), which must
+  be a member of ~org-texinfo-classes~.
+
+- =TEXINFO_HEADER= ::
+
+  #+cindex: @samp{TEXINFO_HEADER}, keyword
+  Arbitrary lines inserted at the end of the header.
+
+- =TEXINFO_POST_HEADER= ::
+
+  #+cindex: @samp{TEXINFO_POST_HEADER}, keyword
+  Arbitrary lines inserted after the end of the header.
+
+- =TEXINFO_DIR_CATEGORY= ::
+
+  #+cindex: @samp{TEXINFO_DIR_CATEGORY}, keyword
+  The directory category of the document.
+
+- =TEXINFO_DIR_TITLE= ::
+
+  #+cindex: @samp{TEXINFO_DIR_TITLE}, keyword
+  The directory title of the document.
+
+- =TEXINFO_DIR_DESC= ::
+
+  #+cindex: @samp{TEXINFO_DIR_DESC}, keyword
+  The directory description of the document.
+
+- =TEXINFO_PRINTED_TITLE= ::
+
+  #+cindex: @samp{TEXINFO_PRINTED_TITLE}, keyword
+  The printed title of the document.
+
+*** Texinfo file header
+:PROPERTIES:
+:DESCRIPTION: Generating the header.
+:END:
+
+#+cindex: @samp{TEXINFO_FILENAME}, keyword
+After creating the header for a Texinfo file, the Texinfo back-end
+automatically generates a name and destination path for the Info file.
+To override this default with a more sensible path and name, specify
+the =TEXINFO_FILENAME= keyword.
+
+#+vindex: org-texinfo-coding-system
+#+cindex: @samp{TEXINFO_HEADER}, keyword
+Along with the output's file name, the Texinfo header also contains
+language details (see [[*Export Settings]]) and encoding system as set in
+the ~org-texinfo-coding-system~ variable.  Insert =TEXINFO_HEADER=
+keywords for each additional command in the header, for example:
+
+: #+TEXINFO_HEADER: @synindex
+
+#+cindex: @samp{TEXINFO_CLASS}, keyword
+#+vindex: org-texinfo-classes
+Instead of repeatedly installing the same set of commands, define
+a class in ~org-texinfo-classes~ once, and then activate it in the
+document by setting the =TEXINFO_CLASS= keyword to that class.
+
+*** Texinfo title and copyright page
+:PROPERTIES:
+:DESCRIPTION: Creating preamble pages.
+:END:
+
+#+cindex: @samp{TEXINFO_PRINTED_TITLE}, keyword
+The default template for hard copy output has a title page with
+=TITLE= and =AUTHOR= keywords (see [[*Export Settings]]).  To replace the
+regular title with something different for the printed version, use
+the =TEXINFO_PRINTED_TITLE= and =SUBTITLE= keywords.  Both expect raw
+Texinfo code for setting their values.
+
+#+cindex: @samp{SUBAUTHOR}, keyword
+If one =AUTHOR= line is not sufficient, add multiple =SUBAUTHOR=
+keywords.  They have to be set in raw Texinfo code.
+
+#+begin_example
+,#+AUTHOR: Jane Smith
+,#+SUBAUTHOR: John Doe
+,#+TEXINFO_PRINTED_TITLE: This Long Title@@inlinefmt{tex,@*} Is Broken in 
@TeX{}
+#+end_example
+
+#+cindex: @samp{COPYING}, property
+Copying material is defined in a dedicated headline with a non-~nil~
+=COPYING= property.  The back-end inserts the contents within
+a =@copying= command at the beginning of the document.  The heading
+itself does not appear in the structure of the document.
+
+Copyright information is printed on the back of the title page.
+
+#+begin_example
+,* Legalese
+  :PROPERTIES:
+  :COPYING: t
+  :END:
+
+  This is a short example of a complete Texinfo file, version 1.0.
+
+  Copyright \copy 2016 Free Software Foundation, Inc.
+#+end_example
+
+*** Info directory file
+:PROPERTIES:
+:DESCRIPTION: Installing a manual in Info file hierarchy.
+:END:
+
+#+cindex: @samp{dir} file, in Texinfo export
+#+cindex: Info directory file, in Texinfo export
+#+cindex: @code{install-info}, in Texinfo export
+
+#+cindex: @samp{TEXINFO_DIR_CATEGORY}, keyword
+#+cindex: @samp{TEXINFO_DIR_TITLE}, keyword
+#+cindex: @samp{TEXINFO_DIR_DESC}, keyword
+The end result of the Texinfo export process is the creation of an
+Info file.  This Info file's metadata has variables for category,
+title, and description: =TEXINFO_DIR_CATEGORY=, =TEXINFO_DIR_TITLE=,
+and =TEXINFO_DIR_DESC= keywords that establish where in the Info
+hierarchy the file fits.
+
+Here is an example that writes to the Info directory file:
+
+#+begin_example
+,#+TEXINFO_DIR_CATEGORY: Emacs
+,#+TEXINFO_DIR_TITLE: Org Mode: (org)
+,#+TEXINFO_DIR_DESC: Outline-based notes management and organizer
+#+end_example
+
+*** Headings and sectioning structure
+:PROPERTIES:
+:DESCRIPTION: Building document structure.
+:END:
+
+#+vindex: org-texinfo-classes
+#+vindex: org-texinfo-default-class
+#+cindex: @samp{TEXINFO_CLASS}, keyword
+The Texinfo export back-end uses a pre-defined scheme to convert Org
+headlines to equivalent Texinfo structuring commands.  A scheme like
+this maps top-level headlines to numbered chapters tagged as
+~@chapter~ and lower-level headlines to unnumbered chapters tagged as
+~@unnumbered~.  To override such mappings to introduce ~@part~ or
+other Texinfo structuring commands, define a new class in
+~org-texinfo-classes~.  Activate the new class with the
+=TEXINFO_CLASS= keyword.  When no new class is defined and activated,
+the Texinfo export back-end defaults to the
+~org-texinfo-default-class~.
+
+If an Org headline's level has no associated Texinfo structuring
+command, or is below a certain threshold (see [[*Export Settings]]), then
+the Texinfo export back-end makes it into a list item.
+
+#+cindex: @samp{APPENDIX}, property
+The Texinfo export back-end makes any headline with a non-~nil~
+=APPENDIX= property into an appendix.  This happens independent of the
+Org headline level or the =TEXINFO_CLASS= keyword.
+
+#+cindex: @samp{ALT_TITLE}, property
+#+cindex: @samp{DESCRIPTION}, property
+The Texinfo export back-end creates a menu entry after the Org
+headline for each regular sectioning structure.  To override this with
+a shorter menu entry, use the =ALT_TITLE= property (see [[*Table of
+Contents]]).  Texinfo menu entries also have an option for a longer
+=DESCRIPTION= property.  Here's an example that uses both to override
+the default menu entry:
+
+#+begin_example
+,* Controlling Screen Display
+  :PROPERTIES:
+  :ALT_TITLE: Display
+  :DESCRIPTION: Controlling Screen Display
+  :END:
+#+end_example
+
+#+cindex: Top node, in Texinfo export
+The text before the first headline belongs to the /Top/ node, i.e.,
+the node in which a reader enters an Info manual.  As such, it is
+expected not to appear in printed output generated from the =.texi=
+file.  See [[info:texinfo::The Top Node]], for more information.
+
+*** Indices
+:PROPERTIES:
+:DESCRIPTION: Creating indices.
+:END:
+
+#+cindex: @samp{CINDEX}, keyword
+#+cindex: concept index, in Texinfo export
+#+cindex: @samp{FINDEX}, keyword
+#+cindex: function index, in Texinfo export
+#+cindex: @samp{KINDEX}, keyword
+#+cindex: keystroke index, in Texinfo export
+#+cindex: @samp{PINDEX}, keyword
+#+cindex: program index, in Texinfo export
+#+cindex: @samp{TINDEX}, keyword
+#+cindex: data type index, in Texinfo export
+#+cindex: @samp{VINDEX}, keyword
+#+cindex: variable index, in Texinfo export
+The Texinfo export back-end recognizes these indexing keywords if used
+in the Org file: =CINDEX=, =FINDEX=, =KINDEX=, =PINDEX=, =TINDEX= and
+=VINDEX=.  Write their value as verbatim Texinfo code; in particular,
+={=, =}= and =@= characters need to be escaped with =@= if they do not
+belong to a Texinfo command.
+
+: #+CINDEX: Defining indexing entries
+
+#+cindex: @samp{INDEX}, property
+For the back-end to generate an index entry for a headline, set the
+=INDEX= property to =cp= or =vr=.  These abbreviations come from
+Texinfo that stand for concept index and variable index.  The Texinfo
+manual has abbreviations for all other kinds of indexes.  The back-end
+exports the headline as an unnumbered chapter or section command, and
+then inserts the index after its contents.
+
+#+begin_example
+,* Concept Index
+  :PROPERTIES:
+  :INDEX: cp
+  :END:
+#+end_example
+
+*** Quoting Texinfo code
+:PROPERTIES:
+:DESCRIPTION: Incorporating literal Texinfo code.
+:END:
+
+Use any of the following three methods to insert or escape raw Texinfo
+code:
+
+#+cindex: @samp{TEXINFO}, keyword
+#+cindex: @samp{BEGIN_EXPORT texinfo}
+#+begin_example
+Richard @@texinfo:@sc{@@Stallman@@texinfo:}@@ commence' GNU.
+
+,#+TEXINFO: @need800
+This paragraph is preceded by...
+
+,#+BEGIN_EXPORT texinfo
+  @auindex Johnson, Mark
+  @auindex Lakoff, George
+,#+END_EXPORT
+#+end_example
+
+*** Plain lists in Texinfo export
+:PROPERTIES:
+:DESCRIPTION: List attributes.
+:END:
+
+#+cindex: @samp{ATTR_TEXINFO}, keyword
+#+cindex: two-column tables, in Texinfo export
+#+cindex: table-type, Texinfo attribute
+The Texinfo export back-end by default converts description lists in
+the Org file using the default command =@table=, which results in
+a table with two columns.  To change this behavior, set =:table-type=
+attribute to either =ftable= or =vtable= value.  For more information,
+see [[info:texinfo::Two-column Tables]].
+
+#+vindex: org-texinfo-table-default-markup
+#+cindex: indic, Texinfo attribute
+The Texinfo export back-end by default also applies a text highlight
+based on the defaults stored in ~org-texinfo-table-default-markup~.
+To override the default highlight command, specify another one with
+the =:indic= attribute.
+
+#+cindex: multiple items in Texinfo lists
+#+cindex: sep, Texinfo attribute
+Org syntax is limited to one entry per list item.  Nevertheless, the
+Texinfo export back-end can split that entry according to any text
+provided through the =:sep= attribute.  Each part then becomes a new
+entry in the first column of the table.
+
+The following example illustrates all the attributes above:
+
+#+begin_example
+,#+ATTR_TEXINFO: :table-type vtable :sep , :indic asis
+- foo, bar :: This is the common text for variables foo and bar.
+#+end_example
+
+#+texinfo: @noindent
+becomes
+
+#+begin_example
+@vtable @asis
+@item foo
+@itemx bar
+This is the common text for variables foo and bar.
+@end table
+#+end_example
+
+#+cindex: lettered lists, in Texinfo export
+#+cindex: enum, Texinfo attribute
+Ordered lists are numbered when exported to Texinfo format.  Such
+numbering obeys any counter (see [[*Plain Lists]]) in the first item of
+the list.  The =:enum= attribute also let you start the list at
+a specific number, or switch to a lettered list, as illustrated here
+
+#+begin_example
+#+ATTR_TEXINFO: :enum A
+1. Alpha
+2. Bravo
+3. Charlie
+#+end_example
+
+*** Tables in Texinfo export
+:PROPERTIES:
+:DESCRIPTION: Table attributes.
+:END:
+
+#+cindex: @samp{ATTR_TEXINFO}, keyword
+When exporting tables, the Texinfo export back-end uses the widest
+cell width in each column.  To override this and instead specify as
+fractions of line length, use the =:columns= attribute.  See example
+below.
+
+#+begin_example
+,#+ATTR_TEXINFO: :columns .5 .5
+| a cell | another cell |
+#+end_example
+
+*** Images in Texinfo export
+:PROPERTIES:
+:DESCRIPTION: Image attributes.
+:END:
+
+#+cindex: @samp{ATTR_TEXINFO}, keyword
+Insert a file link to the image in the Org file, and the Texinfo
+export back-end inserts the image.  These links must have the usual
+supported image extensions and no descriptions.  To scale the image,
+use =:width= and =:height= attributes.  For alternate text, use =:alt=
+and specify the text using Texinfo code, as shown in the example:
+
+#+begin_example
+,#+ATTR_TEXINFO: :width 1in :alt Alternate @i{text}
+[[ridt.pdf]]
+#+end_example
+
+*** Quotations in Texinfo export
+:PROPERTIES:
+:DESCRIPTION: Quote block attributes.
+:END:
+
+#+cindex: @samp{ATTR_TEXINFO}, keyword
+You can write the text of a quotation within a quote block (see
+[[*Paragraphs]]).  You may also emphasize some text at the beginning of
+the quotation with the =:tag= attribute.
+
+#+begin_example
+,#+ATTR_TEXINFO: :tag Warning
+,#+BEGIN_QUOTE
+Striking your thumb with a hammer may cause severe pain and discomfort.
+,#+END_QUOTE
+#+end_example
+
+To specify the author of the quotation, use the =:author= attribute.
+
+#+begin_example
+,#+ATTR_TEXINFO: :author King Arthur
+,#+BEGIN_QUOTE
+The Lady of the Lake, her arm clad in the purest shimmering samite,
+held aloft Excalibur from the bosom of the water, signifying by divine
+providence that I, Arthur, was to carry Excalibur. That is why I am
+your king.
+,#+END_QUOTE
+#+end_example
+
+*** Special blocks in Texinfo export
+:PROPERTIES:
+:DESCRIPTION: Special block attributes.
+:END:
+
+#+cindex: @samp{ATTR_TEXINFO}, keyword
+
+The Texinfo export back-end converts special blocks to commands with
+the same name.  It also adds any =:options= attributes to the end of
+the command, as shown in this example:
+
+#+begin_example
+,#+ATTR_TEXINFO: :options org-org-export-to-org ...
+,#+BEGIN_defun
+  A somewhat obsessive function name.
+,#+END_defun
+#+end_example
+
+#+texinfo: @noindent
+becomes
+
+#+begin_example
+@defun org-org-export-to-org ...
+  A somewhat obsessive function name.
+@end defun
+#+end_example
+
+*** A Texinfo example
+:PROPERTIES:
+:DESCRIPTION: Processing Org to Texinfo.
+:END:
+
+Here is a more detailed example Org file.  See
+[[info:texinfo::GNU Sample Texts]] for an equivalent example using
+Texinfo code.
+
+#+begin_example
+,#+TITLE: GNU Sample {{{version}}}
+,#+SUBTITLE: for version {{{version}}}, {{{updated}}}
+,#+AUTHOR: A.U. Thor
+,#+EMAIL: bug-sample@gnu.org
+
+,#+OPTIONS: ':t toc:t author:t email:t
+,#+LANGUAGE: en
+
+,#+MACRO: version 2.0
+,#+MACRO: updated last updated 4 March 2014
+
+,#+TEXINFO_FILENAME: sample.info
+,#+TEXINFO_HEADER: @syncodeindex pg cp
+
+,#+TEXINFO_DIR_CATEGORY: Texinfo documentation system
+,#+TEXINFO_DIR_TITLE: sample: (sample)
+,#+TEXINFO_DIR_DESC: Invoking sample
+
+,#+TEXINFO_PRINTED_TITLE: GNU Sample
+
+This manual is for GNU Sample (version {{{version}}},
+{{{updated}}}).
+
+,* Copying
+  :PROPERTIES:
+  :COPYING:  t
+  :END:
+
+  This manual is for GNU Sample (version {{{version}}},
+  {{{updated}}}), which is an example in the Texinfo documentation.
+
+  Copyright \copy 2016 Free Software Foundation, Inc.
+
+  ,#+BEGIN_QUOTE
+  Permission is granted to copy, distribute and/or modify this
+  document under the terms of the GNU Free Documentation License,
+  Version 1.3 or any later version published by the Free Software
+  Foundation; with no Invariant Sections, with no Front-Cover Texts,
+  and with no Back-Cover Texts.  A copy of the license is included in
+  the section entitled "GNU Free Documentation License".
+  ,#+END_QUOTE
+
+,* Invoking sample
+
+  ,#+PINDEX: sample
+  ,#+CINDEX: invoking @command{sample}
+
+  This is a sample manual.  There is no sample program to invoke, but
+  if there were, you could see its basic usage and command line
+  options here.
+
+,* GNU Free Documentation License
+  :PROPERTIES:
+  :APPENDIX: t
+  :END:
+
+  ,#+INCLUDE: fdl.org
+
+,* Index
+  :PROPERTIES:
+  :INDEX:    cp
+  :END:
+#+end_example
+
+** iCalendar Export
+:PROPERTIES:
+:DESCRIPTION: Exporting to iCalendar.
+:END:
+#+cindex: iCalendar export
+
+A large part of Org mode's interoperability success is its ability to
+easily export to or import from external applications.  The iCalendar
+export back-end takes calendar data from Org files and exports to the
+standard iCalendar format.
+
+#+vindex: org-icalendar-include-todo
+#+vindex: org-icalendar-use-deadline
+#+vindex: org-icalendar-use-scheduled
+The iCalendar export back-end can also incorporate TODO entries based
+on the configuration of the ~org-icalendar-include-todo~ variable.
+The back-end exports plain timestamps as =VEVENT=, TODO items as
+=VTODO=, and also create events from deadlines that are in non-TODO
+items.  The back-end uses the deadlines and scheduling dates in Org
+TODO items for setting the start and due dates for the iCalendar TODO
+entry.  Consult the ~org-icalendar-use-deadline~ and
+~org-icalendar-use-scheduled~ variables for more details.
+
+#+vindex: org-icalendar-categories
+#+vindex: org-icalendar-alarm-time
+For tags on the headline, the iCalendar export back-end makes them
+into iCalendar categories.  To tweak the inheritance of tags and TODO
+states, configure the variable ~org-icalendar-categories~.  To assign
+clock alarms based on time, configure the ~org-icalendar-alarm-time~
+variable.
+
+#+vindex: org-icalendar-store-UID
+#+cindex: @samp{ID}, property
+The iCalendar format standard requires globally unique identifier---or
+UID---for each entry.  The iCalendar export back-end creates UIDs
+during export.  To save a copy of the UID in the Org file set the
+variable ~org-icalendar-store-UID~.  The back-end looks for the =ID=
+property of the entry for re-using the same UID for subsequent
+exports.
+
+Since a single Org entry can result in multiple iCalendar
+entries---timestamp, deadline, scheduled item, or TODO item---Org adds
+prefixes to the UID, depending on which part of the Org entry
+triggered the creation of the iCalendar entry.  Prefixing ensures UIDs
+remains unique, yet enable synchronization programs trace the
+connections.
+
+- {{{kbd(C-c C-e c f)}}} (~org-icalendar-export-to-ics~) ::
+
+  #+kindex: C-c C-e c f
+  #+findex: org-icalendar-export-to-ics
+  Create iCalendar entries from the current Org buffer and store them
+  in the same directory, using a file extension =.ics=.
+
+- {{{kbd(C-c C-e c a)}}} (~org-icalendar-export-agenda-files~) ::
+
+  #+kindex: C-c C-e c a
+  #+findex: org-icalendar-export-agenda-files
+  Create iCalendar entries from Org files in ~org-agenda-files~ and
+  store in a separate iCalendar file for each Org file.
+
+- {{{kbd(C-c C-e c c)}}} (~org-icalendar-combine-agenda-files~) ::
+
+  #+kindex: C-c C-e c c
+  #+findex: org-icalendar-combine-agenda-files
+  #+vindex: org-icalendar-combined-agenda-file
+  Create a combined iCalendar file from Org files in
+  ~org-agenda-files~ and write it to
+  ~org-icalendar-combined-agenda-file~ file name.
+
+#+cindex: @samp{SUMMARY}, property
+#+cindex: @samp{DESCRIPTION}, property
+#+cindex: @samp{LOCATION}, property
+#+cindex: @samp{TIMEZONE}, property
+#+cindex: @samp{CLASS}, property
+The iCalendar export back-end includes =SUMMARY=, =DESCRIPTION=,
+=LOCATION=, =TIMEZONE= and =CLASS= properties from the Org entries
+when exporting.  To force the back-end to inherit the =LOCATION=,
+=TIMEZONE= and =CLASS= properties, configure the
+~org-use-property-inheritance~ variable.
+
+#+vindex: org-icalendar-include-body
+When Org entries do not have =SUMMARY=, =DESCRIPTION=, =LOCATION= and
+=CLASS= properties, the iCalendar export back-end derives the summary
+from the headline, and derives the description from the body of the
+Org item.  The ~org-icalendar-include-body~ variable limits the
+maximum number of characters of the content are turned into its
+description.
+
+The =TIMEZONE= property can be used to specify a per-entry time zone,
+and is applied to any entry with timestamp information.  Time zones
+should be specified as per the IANA time zone database format, e.g.,
+=Asia/Almaty=.  Alternately, the property value can be =UTC=, to force
+UTC time for this entry only.
+
+The =CLASS= property can be used to specify a per-entry visibility
+class or access restrictions, and is applied to any entry with class
+information.  The iCalendar standard defines three visibility classes:
+- =PUBLIC= :: The entry is publicly visible (this is the default).
+- =CONFIDENTIAL= :: Only a limited group of clients get access to the
+  event.
+- =PRIVATE= :: The entry can be retrieved only by its owner.
+The server should treat unknown class properties the same as
+=PRIVATE=.
+
+Exporting to iCalendar format depends in large part on the
+capabilities of the destination application.  Some are more lenient
+than others.  Consult the Org mode FAQ for advice on specific
+applications.
+
+** Other Built-in Back-ends
+:PROPERTIES:
+:DESCRIPTION: Exporting to a man page.
+:END:
+
+Other export back-ends included with Org are:
+
+- =ox-man.el=: Export to a man page.
+
+To activate such back-ends, either customize ~org-export-backends~ or
+load directly with =(require 'ox-man)=.  On successful load, the
+back-end adds new keys in the export dispatcher (see [[*The Export
+Dispatcher]]).
+
+Follow the comment section of such files, for example, =ox-man.el=,
+for usage and configuration details.
+
+** Advanced Export Configuration
+:PROPERTIES:
+:DESCRIPTION: Fine-tuning the export output.
+:END:
+
+*** Hooks
+:PROPERTIES:
+:UNNUMBERED: notoc
+:END:
+
+#+vindex: org-export-before-processing-hook
+#+vindex: org-export-before-parsing-hook
+The export process executes two hooks before the actual exporting
+begins.  The first hook, ~org-export-before-processing-hook~, runs
+before any expansions of macros, Babel code, and include keywords in
+the buffer.  The second hook, ~org-export-before-parsing-hook~, runs
+before the buffer is parsed.
+
+Functions added to these hooks are called with a single argument: the
+export back-end actually used, as a symbol.  You may use them for
+heavy duty structural modifications of the document.  For example, you
+can remove every headline in the buffer during export like this:
+
+#+begin_src emacs-lisp
+(defun my-headline-removal (backend)
+  "Remove all headlines in the current buffer.
+BACKEND is the export back-end being used, as a symbol."
+  (org-map-entries
+   (lambda () (delete-region (point) (line-beginning-position 2)))))
+
+(add-hook 'org-export-before-parsing-hook 'my-headline-removal)
+#+end_src
+
+*** Filters
+:PROPERTIES:
+:UNNUMBERED: notoc
+:END:
+
+#+cindex: Filters, exporting
+Filters are lists of functions to be applied to certain parts for
+a given back-end.  The output from the first function in the filter is
+passed on to the next function in the filter.  The final output is the
+output from the final function in the filter.
+
+The Org export process has many filter sets applicable to different
+types of objects, plain text, parse trees, export options, and final
+output formats.  The filters are named after the element type or
+object type: ~org-export-filter-TYPE-functions~, where {{{var(TYPE)}}}
+is the type targeted by the filter.  Valid types are:
+
+#+attr_texinfo: :columns 0.33 0.33 0.33
+| body                | bold               | babel-call       |
+| center-block        | clock              | code             |
+| diary-sexp          | drawer             | dynamic-block    |
+| entity              | example-block      | export-block     |
+| export-snippet      | final-output       | fixed-width      |
+| footnote-definition | footnote-reference | headline         |
+| horizontal-rule     | inline-babel-call  | inline-src-block |
+| inlinetask          | italic             | item             |
+| keyword             | latex-environment  | latex-fragment   |
+| line-break          | link               | node-property    |
+| options             | paragraph          | parse-tree       |
+| plain-list          | plain-text         | planning         |
+| property-drawer     | quote-block        | radio-target     |
+| section             | special-block      | src-block        |
+| statistics-cookie   | strike-through     | subscript        |
+| superscript         | table              | table-cell       |
+| table-row           | target             | timestamp        |
+| underline           | verbatim           | verse-block      |
+
+Here is an example filter that replaces non-breaking spaces ~ ~ in the
+Org buffer with =~= for the LaTeX back-end.
+
+#+begin_src emacs-lisp
+(defun my-latex-filter-nobreaks (text backend info)
+  "Ensure \" \" are properly handled in LaTeX export."
+  (when (org-export-derived-backend-p backend 'latex)
+    (replace-regexp-in-string " " "~" text)))
+
+(add-to-list 'org-export-filter-plain-text-functions
+             'my-latex-filter-nobreaks)
+#+end_src
+
+A filter requires three arguments: the code to be transformed, the
+name of the back-end, and some optional information about the export
+process.  The third argument can be safely ignored.  Note the use of
+~org-export-derived-backend-p~ predicate that tests for /latex/
+back-end or any other back-end, such as /beamer/, derived from
+/latex/.
+
+*** Defining filters for individual files
+:PROPERTIES:
+:UNNUMBERED: notoc
+:END:
+
+The Org export can filter not just for back-ends, but also for
+specific files through the =BIND= keyword.  Here is an example with
+two filters; one removes brackets from time stamps, and the other
+removes strike-through text.  The filter functions are defined in
+a code block in the same Org file, which is a handy location for
+debugging.
+
+#+begin_example
+,#+BIND: org-export-filter-timestamp-functions (tmp-f-timestamp)
+,#+BIND: org-export-filter-strike-through-functions (tmp-f-strike-through)
+,#+BEGIN_SRC emacs-lisp :exports results :results none
+  (defun tmp-f-timestamp (s backend info)
+    (replace-regexp-in-string "&[lg]t;\\|[][]" "" s))
+  (defun tmp-f-strike-through (s backend info) "")
+,#+END_SRC
+#+end_example
+
+*** Extending an existing back-end
+:PROPERTIES:
+:UNNUMBERED: notoc
+:END:
+
+Some parts of the conversion process can be extended for certain
+elements so as to introduce a new or revised translation.  That is how
+the HTML export back-end was extended to handle Markdown format.  The
+extensions work seamlessly so any aspect of filtering not done by the
+extended back-end is handled by the original back-end.  Of all the
+export customization in Org, extending is very powerful as it operates
+at the parser level.
+
+For this example, make the /ascii/ back-end display the language used
+in a source code block.  Also make it display only when some attribute
+is non-~nil~, like the following:
+
+: #+ATTR_ASCII: :language t
+
+Then extend ASCII back-end with a custom "my-ascii" back-end.
+
+#+begin_src emacs-lisp
+(defun my-ascii-src-block (src-block contents info)
+  "Transcode a SRC-BLOCK element from Org to ASCII.
+CONTENTS is nil.  INFO is a plist used as a communication
+channel."
+  (if (not (org-export-read-attribute :attr_ascii src-block :language))
+      (org-export-with-backend 'ascii src-block contents info)
+    (concat
+     (format ",--[ %s ]--\n%s`----"
+             (org-element-property :language src-block)
+             (replace-regexp-in-string
+              "^" "| "
+              (org-element-normalize-string
+               (org-export-format-code-default src-block info)))))))
+
+(org-export-define-derived-backend 'my-ascii 'ascii
+  :translate-alist '((src-block . my-ascii-src-block)))
+#+end_src
+
+The ~my-ascii-src-block~ function looks at the attribute above the
+current element.  If not true, hands over to /ascii/ back-end.  If
+true, which it is in this example, it creates a box around the code
+and leaves room for the inserting a string for language.  The last
+form creates the new back-end that springs to action only when
+translating ~src-block~ type elements.
+
+To use the newly defined back-end, evaluate the following from an Org
+buffer:
+
+#+begin_src emacs-lisp
+(org-export-to-buffer 'my-ascii "*Org MY-ASCII Export*")
+#+end_src
+
+Further steps to consider would be an interactive function,
+self-installing an item in the export dispatcher menu, and other
+user-friendly improvements.
+
+** Export in Foreign Buffers
+:PROPERTIES:
+:DESCRIPTION: Author tables and lists in Org syntax.
+:END:
+
+The export back-ends in Org often include commands to convert selected
+regions.  A convenient feature of this in-place conversion is that the
+exported output replaces the original source.  Here are such
+functions:
+
+- ~org-ascii-convert-region-to-ascii~ ::
+
+  #+findex: org-ascii-convert-region-to-ascii
+  Convert the selected region into ASCII.
+
+- ~org-ascii-convert-region-to-utf8~ ::
+
+  #+findex: org-ascii-convert-region-to-utf8
+  Convert the selected region into UTF-8.
+
+- ~org-html-convert-region-to-html~ ::
+
+  #+findex: org-html-convert-region-to-html
+  Convert the selected region into HTML.
+
+- ~org-latex-convert-region-to-latex~ ::
+
+  #+findex: org-latex-convert-region-to-latex
+  Convert the selected region into LaTeX.
+
+- ~org-texinfo-convert-region-to-texinfo~ ::
+
+  #+findex: org-texinfo-convert-region-to-texinfo
+  Convert the selected region into Texinfo.
+
+- ~org-md-convert-region-to-md~ ::
+
+  #+findex: org-md-convert-region-to-md
+  Convert the selected region into Markdown.
+
+In-place conversions are particularly handy for quick conversion of
+tables and lists in foreign buffers.  For example, in an HTML buffer,
+write a list in Org syntax, select it, and convert it to HTML with
+{{{kbd(M-x org-html-convert-region-to-html)}}}.
+
+*** Exporting to minimal HTML
+:PROPERTIES:
+:DESCRIPTION: Exporting HTML without CSS, Javascript, etc.
+:ALT_TITLE: Bare HTML
+:END:
+
+If you want to output a minimal HTML file, with no CSS, no Javascript,
+no preamble or postamble, here are the variable you would need to set:
+
+#+vindex: org-html-head
+#+vindex: org-html-head-extra
+#+vindex: org-html-head-include-default-style
+#+vindex: org-html-head-include-scripts
+#+vindex: org-html-preamble
+#+vindex: org-html-postamble
+#+vindex: org-html-use-infojs
+#+begin_src emacs-lisp
+(setq org-html-head ""
+      org-html-head-extra ""
+      org-html-head-include-default-style nil
+      org-html-head-include-scripts nil
+      org-html-preamble nil
+      org-html-postamble nil
+      org-html-use-infojs nil)
+#+end_src
+
+* Publishing
+:PROPERTIES:
+:DESCRIPTION: Create a web site of linked Org files.
+:END:
+#+cindex: publishing
+
+Org includes a publishing management system that allows you to
+configure automatic HTML conversion of /projects/ composed of
+interlinked Org files.  You can also configure Org to automatically
+upload your exported HTML pages and related attachments, such as
+images and source code files, to a web server.
+
+You can also use Org to convert files into PDF, or even combine HTML
+and PDF conversion so that files are available in both formats on the
+server.
+
+Publishing has been contributed to Org by David O'Toole.
+
+** Configuration
+:PROPERTIES:
+:DESCRIPTION: Defining projects.
+:END:
+Publishing needs significant configuration to specify files,
+destination and many other properties of a project.
+
+*** The variable ~org-publish-project-alist~
+:PROPERTIES:
+:DESCRIPTION: The central configuration variable.
+:ALT_TITLE: Project alist
+:END:
+#+cindex: projects, for publishing
+
+#+vindex: org-publish-project-alist
+Publishing is configured almost entirely through setting the value of
+one variable, called ~org-publish-project-alist~.  Each element of the
+list configures one project, and may be in one of the two following
+forms:
+
+#+begin_src emacs-lisp
+("project-name" :property value :property value ...)
+#+end_src
+
+#+texinfo: @noindent
+i.e., a well-formed property list with alternating keys and values,
+or:
+
+#+begin_src emacs-lisp
+("project-name" :components ("project-name" "project-name" ...))
+#+end_src
+
+In both cases, projects are configured by specifying property values.
+A project defines the set of files that are to be published, as well
+as the publishing configuration to use when publishing those files.
+When a project takes the second form listed above, the individual
+members of the ~:components~ property are taken to be sub-projects,
+which group together files requiring different publishing options.
+When you publish such a "meta-project", all the components are also
+published, in the sequence given.
+
+*** Sources and destinations for files
+:PROPERTIES:
+:DESCRIPTION: From here to there.
+:ALT_TITLE: Sources and destinations
+:END:
+#+cindex: directories, for publishing
+
+Most properties are optional, but some should always be set.  In
+particular, Org needs to know where to look for source files, and
+where to put published files.
+
+- ~:base-directory~ ::
+
+  Directory containing publishing source files.
+
+- ~:publishing-directory~ ::
+
+  Directory where output files are published.  You can directly
+  publish to a webserver using a file name syntax appropriate for the
+  Emacs tramp package.  Or you can publish to a local directory and
+  use external tools to upload your website (see [[*Uploading Files]]).
+
+- ~:preparation-function~ ::
+
+  Function or list of functions to be called before starting the
+  publishing process, for example, to run =make= for updating files to
+  be published.  Each preparation function is called with a single
+  argument, the project property list.
+
+- ~:completion-function~ ::
+
+  Function or list of functions called after finishing the publishing
+  process, for example, to change permissions of the resulting files.
+  Each completion function is called with a single argument, the
+  project property list.
+
+*** Selecting files
+:PROPERTIES:
+:DESCRIPTION: What files are part of the project?
+:END:
+#+cindex: files, selecting for publishing
+
+By default, all files with extension =.org= in the base directory are
+considered part of the project.  This can be modified by setting the
+following properties
+
+- ~:base-extension~ ::
+
+  Extension---without the dot---of source files.  This actually is
+  a regular expression.  Set this to the symbol ~any~ if you want to
+  get all files in ~:base-directory~, even without extension.
+
+- ~:exclude~ ::
+
+  Regular expression to match file names that should not be published,
+  even though they have been selected on the basis of their extension.
+
+- ~:include~ ::
+
+  List of files to be included regardless of ~:base-extension~ and
+  ~:exclude~.
+
+- ~:recursive~ ::
+
+  Non-~nil~ means, check base-directory recursively for files to
+  publish.
+
+*** Publishing action
+:PROPERTIES:
+:DESCRIPTION: Setting the function doing the publishing.
+:END:
+#+cindex: action, for publishing
+
+Publishing means that a file is copied to the destination directory
+and possibly transformed in the process.  The default transformation
+is to export Org files as HTML files, and this is done by the function
+~org-publish-org-to-html~ which calls the HTML exporter (see [[*HTML
+Export]]).  But you can also publish your content as PDF files using
+~org-publish-org-to-pdf~, or as ASCII, Texinfo, etc., using the
+corresponding functions.
+
+If you want to publish the Org file as an =.org= file but with
+/archived/, /commented/, and /tag-excluded/ trees removed, use
+~org-publish-org-to-org~.  This produces =file.org= and put it in the
+publishing directory.  If you want a htmlized version of this file,
+set the parameter ~:htmlized-source~ to ~t~.  It produces
+=file.org.html= in the publishing directory[fn:140].
+
+Other files like images only need to be copied to the publishing
+destination; for this you can use ~org-publish-attachment~.  For
+non-Org files, you always need to specify the publishing function:
+
+- ~:publishing-function~ ::
+
+  Function executing the publication of a file.  This may also be
+  a list of functions, which are all called in turn.
+
+- ~:htmlized-source~ ::
+
+  Non-~nil~ means, publish htmlized source.
+
+The function must accept three arguments: a property list containing
+at least a ~:publishing-directory~ property, the name of the file to
+be published, and the path to the publishing directory of the output
+file.  It should take the specified file, make the necessary
+transformation, if any, and place the result into the destination
+folder.
+
+*** Options for the exporters
+:PROPERTIES:
+:DESCRIPTION: Tweaking HTML/@LaTeX{} export.
+:ALT_TITLE: Publishing options
+:END:
+#+cindex: options, for publishing
+#+cindex: publishing options
+
+The property list can be used to set many export options for the HTML
+and LaTeX exporters.  In most cases, these properties correspond to
+user variables in Org.  The table below lists these properties along
+with the variable they belong to.  See the documentation string for
+the respective variable for details.
+
+#+vindex: org-publish-project-alist
+When a property is given a value in ~org-publish-project-alist~, its
+setting overrides the value of the corresponding user variable, if
+any, during publishing.  Options set within a file (see [[*Export
+Settings]]), however, override everything.
+
+**** Generic properties
+:PROPERTIES:
+:UNNUMBERED: notoc
+:END:
+
+| ~:archived-trees~       | ~org-export-with-archived-trees~   |
+| ~:exclude-tags~         | ~org-export-exclude-tags~          |
+| ~:headline-levels~      | ~org-export-headline-levels~       |
+| ~:language~             | ~org-export-default-language~      |
+| ~:preserve-breaks~      | ~org-export-preserve-breaks~       |
+| ~:section-numbers~      | ~org-export-with-section-numbers~  |
+| ~:select-tags~          | ~org-export-select-tags~           |
+| ~:with-author~          | ~org-export-with-author~           |
+| ~:with-broken-links~    | ~org-export-with-broken-links~     |
+| ~:with-clocks~          | ~org-export-with-clocks~           |
+| ~:with-creator~         | ~org-export-with-creator~          |
+| ~:with-date~            | ~org-export-with-date~             |
+| ~:with-drawers~         | ~org-export-with-drawers~          |
+| ~:with-email~           | ~org-export-with-email~            |
+| ~:with-emphasize~       | ~org-export-with-emphasize~        |
+| ~:with-fixed-width~     | ~org-export-with-fixed-width~      |
+| ~:with-footnotes~       | ~org-export-with-footnotes~        |
+| ~:with-latex~           | ~org-export-with-latex~            |
+| ~:with-planning~        | ~org-export-with-planning~         |
+| ~:with-priority~        | ~org-export-with-priority~         |
+| ~:with-properties~      | ~org-export-with-properties~       |
+| ~:with-special-strings~ | ~org-export-with-special-strings~  |
+| ~:with-sub-superscript~ | ~org-export-with-sub-superscripts~ |
+| ~:with-tables~          | ~org-export-with-tables~           |
+| ~:with-tags~            | ~org-export-with-tags~             |
+| ~:with-tasks~           | ~org-export-with-tasks~            |
+| ~:with-timestamps~      | ~org-export-with-timestamps~       |
+| ~:with-title~           | ~org-export-with-title~            |
+| ~:with-toc~             | ~org-export-with-toc~              |
+| ~:with-todo-keywords~   | ~org-export-with-todo-keywords~    |
+
+**** ASCII specific properties
+:PROPERTIES:
+:UNNUMBERED: notoc
+:END:
+
+| ~:ascii-bullets~                       | ~org-ascii-bullets~                 
      |
+| ~:ascii-caption-above~                 | ~org-ascii-caption-above~           
      |
+| ~:ascii-charset~                       | ~org-ascii-charset~                 
      |
+| ~:ascii-global-margin~                 | ~org-ascii-global-margin~           
      |
+| ~:ascii-format-drawer-function~        | ~org-ascii-format-drawer-function~  
      |
+| ~:ascii-format-inlinetask-function~    | 
~org-ascii-format-inlinetask-function~    |
+| ~:ascii-headline-spacing~              | ~org-ascii-headline-spacing~        
      |
+| ~:ascii-indented-line-width~           | ~org-ascii-indented-line-width~     
      |
+| ~:ascii-inlinetask-width~              | ~org-ascii-inlinetask-width~        
      |
+| ~:ascii-inner-margin~                  | ~org-ascii-inner-margin~            
      |
+| ~:ascii-links-to-notes~                | ~org-ascii-links-to-notes~          
      |
+| ~:ascii-list-margin~                   | ~org-ascii-list-margin~             
      |
+| ~:ascii-paragraph-spacing~             | ~org-ascii-paragraph-spacing~       
      |
+| ~:ascii-quote-margin~                  | ~org-ascii-quote-margin~            
      |
+| ~:ascii-table-keep-all-vertical-lines~ | 
~org-ascii-table-keep-all-vertical-lines~ |
+| ~:ascii-table-use-ascii-art~           | ~org-ascii-table-use-ascii-art~     
      |
+| ~:ascii-table-widen-columns~           | ~org-ascii-table-widen-columns~     
      |
+| ~:ascii-text-width~                    | ~org-ascii-text-width~              
      |
+| ~:ascii-underline~                     | ~org-ascii-underline~               
      |
+| ~:ascii-verbatim-format~               | ~org-ascii-verbatim-format~         
      |
+
+**** Beamer specific properties
+:PROPERTIES:
+:UNNUMBERED: notoc
+:END:
+
+| ~:beamer-theme~                 | ~org-beamer-theme~                 |
+| ~:beamer-column-view-format~    | ~org-beamer-column-view-format~    |
+| ~:beamer-environments-extra~    | ~org-beamer-environments-extra~    |
+| ~:beamer-frame-default-options~ | ~org-beamer-frame-default-options~ |
+| ~:beamer-outline-frame-options~ | ~org-beamer-outline-frame-options~ |
+| ~:beamer-outline-frame-title~   | ~org-beamer-outline-frame-title~   |
+| ~:beamer-subtitle-format~       | ~org-beamer-subtitle-format~       |
+
+**** HTML specific properties
+:PROPERTIES:
+:UNNUMBERED: notoc
+:END:
+
+| ~:html-allow-name-attribute-in-anchors~        | 
~org-html-allow-name-attribute-in-anchors~        |
+| ~:html-checkbox-type~                          | ~org-html-checkbox-type~    
                      |
+| ~:html-container~                              | 
~org-html-container-element~                      |
+| ~:html-divs~                                   | ~org-html-divs~             
                      |
+| ~:html-doctype~                                | ~org-html-doctype~          
                      |
+| ~:html-extension~                              | ~org-html-extension~        
                      |
+| ~:html-footnote-format~                        | ~org-html-footnote-format~  
                      |
+| ~:html-footnote-separator~                     | 
~org-html-footnote-separator~                     |
+| ~:html-footnotes-section~                      | 
~org-html-footnotes-section~                      |
+| ~:html-format-drawer-function~                 | 
~org-html-format-drawer-function~                 |
+| ~:html-format-headline-function~               | 
~org-html-format-headline-function~               |
+| ~:html-format-inlinetask-function~             | 
~org-html-format-inlinetask-function~             |
+| ~:html-head-extra~                             | ~org-html-head-extra~       
                      |
+| ~:html-head-include-default-style~             | 
~org-html-head-include-default-style~             |
+| ~:html-head-include-scripts~                   | 
~org-html-head-include-scripts~                   |
+| ~:html-head~                                   | ~org-html-head~             
                      |
+| ~:html-home/up-format~                         | ~org-html-home/up-format~   
                      |
+| ~:html-html5-fancy~                            | ~org-html-html5-fancy~      
                      |
+| ~:html-indent~                                 | ~org-html-indent~           
                      |
+| ~:html-infojs-options~                         | ~org-html-infojs-options~   
                      |
+| ~:html-infojs-template~                        | ~org-html-infojs-template~  
                      |
+| ~:html-inline-image-rules~                     | 
~org-html-inline-image-rules~                     |
+| ~:html-inline-images~                          | ~org-html-inline-images~    
                      |
+| ~:html-link-home~                              | ~org-html-link-home~        
                      |
+| ~:html-link-org-files-as-html~                 | 
~org-html-link-org-files-as-html~                 |
+| ~:html-link-up~                                | ~org-html-link-up~          
                      |
+| ~:html-link-use-abs-url~                       | ~org-html-link-use-abs-url~ 
                      |
+| ~:html-mathjax-options~                        | ~org-html-mathjax-options~  
                      |
+| ~:html-mathjax-template~                       | ~org-html-mathjax-template~ 
                      |
+| ~:html-equation-reference-format~              | 
~org-html-equation-reference-format~              |
+| ~:html-metadata-timestamp-format~              | 
~org-html-metadata-timestamp-format~              |
+| ~:html-postamble-format~                       | ~org-html-postamble-format~ 
                      |
+| ~:html-postamble~                              | ~org-html-postamble~        
                      |
+| ~:html-preamble-format~                        | ~org-html-preamble-format~  
                      |
+| ~:html-preamble~                               | ~org-html-preamble~         
                      |
+| ~:html-self-link-headlines~                    | 
~org-html-self-link-headlines~                    |
+| ~:html-table-align-individual-field~           | 
~de{org-html-table-align-individual-fields~       |
+| ~:html-table-attributes~                       | 
~org-html-table-default-attributes~               |
+| ~:html-table-caption-above~                    | 
~org-html-table-caption-above~                    |
+| ~:html-table-data-tags~                        | ~org-html-table-data-tags~  
                      |
+| ~:html-table-header-tags~                      | 
~org-html-table-header-tags~                      |
+| ~:html-table-row-tags~                         | ~org-html-table-row-tags~   
                      |
+| ~:html-table-use-header-tags-for-first-column~ | 
~org-html-table-use-header-tags-for-first-column~ |
+| ~:html-tag-class-prefix~                       | ~org-html-tag-class-prefix~ 
                      |
+| ~:html-text-markup-alist~                      | 
~org-html-text-markup-alist~                      |
+| ~:html-todo-kwd-class-prefix~                  | 
~org-html-todo-kwd-class-prefix~                  |
+| ~:html-toplevel-hlevel~                        | ~org-html-toplevel-hlevel~  
                      |
+| ~:html-use-infojs~                             | ~org-html-use-infojs~       
                      |
+| ~:html-validation-link~                        | ~org-html-validation-link~  
                      |
+| ~:html-viewport~                               | ~org-html-viewport~         
                      |
+| ~:html-wrap-src-lines~                         | ~org-html-wrap-src-lines~   
                      |
+| ~:html-xml-declaration~                        | ~org-html-xml-declaration~  
                      |
+
+**** LaTeX specific properties
+:PROPERTIES:
+:UNNUMBERED: notoc
+:END:
+
+| ~:latex-active-timestamp-format~       | ~org-latex-active-timestamp-format~ 
      |
+| ~:latex-caption-above~                 | ~org-latex-caption-above~           
      |
+| ~:latex-classes~                       | ~org-latex-classes~                 
      |
+| ~:latex-class~                         | ~org-latex-default-class~           
      |
+| ~:latex-compiler~                      | ~org-latex-compiler~                
      |
+| ~:latex-default-figure-position~       | ~org-latex-default-figure-position~ 
      |
+| ~:latex-default-table-environment~     | 
~org-latex-default-table-environment~     |
+| ~:latex-default-table-mode~            | ~org-latex-default-table-mode~      
      |
+| ~:latex-diary-timestamp-format~        | ~org-latex-diary-timestamp-format~  
      |
+| ~:latex-footnote-defined-format~       | ~org-latex-footnote-defined-format~ 
      |
+| ~:latex-footnote-separator~            | ~org-latex-footnote-separator~      
      |
+| ~:latex-format-drawer-function~        | ~org-latex-format-drawer-function~  
      |
+| ~:latex-format-headline-function~      | 
~org-latex-format-headline-function~      |
+| ~:latex-format-inlinetask-function~    | 
~org-latex-format-inlinetask-function~    |
+| ~:latex-hyperref-template~             | ~org-latex-hyperref-template~       
      |
+| ~:latex-image-default-height~          | ~org-latex-image-default-height~    
      |
+| ~:latex-image-default-option~          | ~org-latex-image-default-option~    
      |
+| ~:latex-image-default-width~           | ~org-latex-image-default-width~     
      |
+| ~:latex-images-centered~               | ~org-latex-images-centered~         
      |
+| ~:latex-inactive-timestamp-format~     | 
~org-latex-inactive-timestamp-format~     |
+| ~:latex-inline-image-rules~            | ~org-latex-inline-image-rules~      
      |
+| ~:latex-link-with-unknown-path-format~ | 
~org-latex-link-with-unknown-path-format~ |
+| ~:latex-listings-langs~                | ~org-latex-listings-langs~          
      |
+| ~:latex-listings-options~              | ~org-latex-listings-options~        
      |
+| ~:latex-listings~                      | ~org-latex-listings~                
      |
+| ~:latex-minted-langs~                  | ~org-latex-minted-langs~            
      |
+| ~:latex-minted-options~                | ~org-latex-minted-options~          
      |
+| ~:latex-prefer-user-labels~            | ~org-latex-prefer-user-labels~      
      |
+| ~:latex-subtitle-format~               | ~org-latex-subtitle-format~         
      |
+| ~:latex-subtitle-separate~             | ~org-latex-subtitle-separate~       
      |
+| ~:latex-table-scientific-notation~     | 
~org-latex-table-scientific-notation~     |
+| ~:latex-tables-booktabs~               | ~org-latex-tables-booktabs~         
      |
+| ~:latex-tables-centered~               | ~org-latex-tables-centered~         
      |
+| ~:latex-text-markup-alist~             | ~org-latex-text-markup-alist~       
      |
+| ~:latex-title-command~                 | ~org-latex-title-command~           
      |
+| ~:latex-toc-command~                   | ~org-latex-toc-command~             
      |
+
+**** Markdown specific properties
+:PROPERTIES:
+:UNNUMBERED: notoc
+:END:
+
+| ~:md-footnote-format~   | ~org-md-footnote-format~   |
+| ~:md-footnotes-section~ | ~org-md-footnotes-section~ |
+| ~:md-headline-style~    | ~org-md-headline-style~    |
+
+**** ODT specific properties
+:PROPERTIES:
+:UNNUMBERED: notoc
+:END:
+
+| ~:odt-content-template-file~      | ~org-odt-content-template-file~      |
+| ~:odt-display-outline-level~      | ~org-odt-display-outline-level~      |
+| ~:odt-fontify-srcblocks~          | ~org-odt-fontify-srcblocks~          |
+| ~:odt-format-drawer-function~     | ~org-odt-format-drawer-function~     |
+| ~:odt-format-headline-function~   | ~org-odt-format-headline-function~   |
+| ~:odt-format-inlinetask-function~ | ~org-odt-format-inlinetask-function~ |
+| ~:odt-inline-formula-rules~       | ~org-odt-inline-formula-rules~       |
+| ~:odt-inline-image-rules~         | ~org-odt-inline-image-rules~         |
+| ~:odt-pixels-per-inch~            | ~org-odt-pixels-per-inch~            |
+| ~:odt-styles-file~                | ~org-odt-styles-file~                |
+| ~:odt-table-styles~               | ~org-odt-table-styles~               |
+| ~:odt-use-date-fields~            | ~org-odt-use-date-fields~            |
+
+**** Texinfo specific properties
+:PROPERTIES:
+:UNNUMBERED: notoc
+:END:
+
+| ~:texinfo-active-timestamp-format~       | 
~org-texinfo-active-timestamp-format~       |
+| ~:texinfo-classes~                       | ~org-texinfo-classes~             
          |
+| ~:texinfo-class~                         | ~org-texinfo-default-class~       
          |
+| ~:texinfo-table-default-markup~          | 
~org-texinfo-table-default-markup~          |
+| ~:texinfo-diary-timestamp-format~        | 
~org-texinfo-diary-timestamp-format~        |
+| ~:texinfo-filename~                      | ~org-texinfo-filename~            
          |
+| ~:texinfo-format-drawer-function~        | 
~org-texinfo-format-drawer-function~        |
+| ~:texinfo-format-headline-function~      | 
~org-texinfo-format-headline-function~      |
+| ~:texinfo-format-inlinetask-function~    | 
~org-texinfo-format-inlinetask-function~    |
+| ~:texinfo-inactive-timestamp-format~     | 
~org-texinfo-inactive-timestamp-format~     |
+| ~:texinfo-link-with-unknown-path-format~ | 
~org-texinfo-link-with-unknown-path-format~ |
+| ~:texinfo-node-description-column~       | 
~org-texinfo-node-description-column~       |
+| ~:texinfo-table-scientific-notation~     | 
~org-texinfo-table-scientific-notation~     |
+| ~:texinfo-tables-verbatim~               | ~org-texinfo-tables-verbatim~     
          |
+| ~:texinfo-text-markup-alist~             | ~org-texinfo-text-markup-alist~   
          |
+
+*** Publishing links
+:PROPERTIES:
+:DESCRIPTION: Which links keep working after publishing?
+:END:
+#+cindex: links, publishing
+
+To create a link from one Org file to another, you would use something
+like =[[file:foo.org][The foo]]= or simply =[[file:foo.org]]= (see [[*External 
Links]]).  When
+published, this link becomes a link to =foo.html=.  You can thus
+interlink the pages of your "Org web" project and the links will work
+as expected when you publish them to HTML.  If you also publish the
+Org source file and want to link to it, use an =http= link instead of
+a =file:= link, because =file= links are converted to link to the
+corresponding =.html= file.
+
+You may also link to related files, such as images.  Provided you are
+careful with relative file names, and provided you have also
+configured Org to upload the related files, these links will work too.
+See [[*Example: complex publishing configuration]], for an example of this
+usage.
+
+Eventually, links between published documents can contain some search
+options (see [[*Search Options in File Links]]), which will be resolved to
+the appropriate location in the linked file.  For example, once
+published to HTML, the following links all point to a dedicated anchor
+in =foo.html=.
+
+#+begin_example
+[[file:foo.org::*heading]]
+[[file:foo.org::#custom-id]]
+[[file:foo.org::target]]
+#+end_example
+
+*** Generating a sitemap
+:PROPERTIES:
+:DESCRIPTION: Generating a list of all pages.
+:ALT_TITLE: Site map
+:END:
+#+cindex: sitemap, of published pages
+
+The following properties may be used to control publishing of
+a map of files for a given project.
+
+- ~:auto-sitemap~ ::
+
+  When non-~nil~, publish a sitemap during
+  ~org-publish-current-project~ or ~org-publish-all~.
+
+- ~:sitemap-filename~ ::
+
+  Filename for output of sitemap.  Defaults to =sitemap.org=, which
+  becomes =sitemap.html=.
+
+- ~:sitemap-title~ ::
+
+  Title of sitemap page.  Defaults to name of file.
+
+- ~:sitemap-format-entry~ ::
+
+  #+findex: org-publish-find-date
+  #+findex: org-publish-find-property
+  #+findex: org-publish-find-title
+  With this option one can tell how a site-map entry is formatted in
+  the site-map.  It is a function called with three arguments: the
+  file or directory name relative to base directory of the project,
+  the site-map style and the current project.  It is expected to
+  return a string.  Default value turns file names into links and use
+  document titles as descriptions.  For specific formatting needs, one
+  can use ~org-publish-find-date~, ~org-publish-find-title~ and
+  ~org-publish-find-property~, to retrieve additional information
+  about published documents.
+
+- ~:sitemap-function~ ::
+
+  Plug-in function to use for generation of the sitemap.  It is called
+  with two arguments: the title of the site-map and a representation
+  of the files and directories involved in the project as a nested
+  list, which can further be transformed using ~org-list-to-generic~,
+  ~org-list-to-subtree~ and alike.  Default value generates a plain
+  list of links to all files in the project.
+
+- ~:sitemap-sort-folders~ ::
+
+  Where folders should appear in the sitemap.  Set this to ~first~
+  (default) or ~last~ to display folders first or last, respectively.
+  When set to ~ignore~, folders are ignored altogether.  Any other
+  value mixes files and folders.  This variable has no effect when
+  site-map style is ~tree~.
+
+- ~:sitemap-sort-files~ ::
+
+  How the files are sorted in the site map.  Set this to
+  ~alphabetically~ (default), ~chronologically~ or
+  ~anti-chronologically~.  ~chronologically~ sorts the files with
+  older date first while ~anti-chronologically~ sorts the files with
+  newer date first.  ~alphabetically~ sorts the files alphabetically.
+  The date of a file is retrieved with ~org-publish-find-date~.
+
+- ~:sitemap-ignore-case~ ::
+
+  Should sorting be case-sensitive?  Default ~nil~.
+
+- ~:sitemap-file-entry-format~ ::
+
+  With this option one can tell how a sitemap's entry is formatted in
+  the sitemap.  This is a format string with some escape sequences:
+  ~%t~ stands for the title of the file, ~%a~ stands for the author of
+  the file and ~%d~ stands for the date of the file.  The date is
+  retrieved with the ~org-publish-find-date~ function and formatted
+  with ~org-publish-sitemap-date-format~.  Default ~%t~.
+
+- ~:sitemap-date-format~ ::
+
+  Format string for the ~format-time-string~ function that tells how
+  a sitemap entry's date is to be formatted.  This property bypasses
+  ~org-publish-sitemap-date-format~ which defaults to ~%Y-%m-%d~.
+
+*** Generating an index
+:PROPERTIES:
+:DESCRIPTION: An index that reaches across pages.
+:END:
+#+cindex: index, in a publishing project
+
+Org mode can generate an index across the files of a publishing project.
+
+- ~:makeindex~ ::
+
+  When non-~nil~, generate in index in the file =theindex.org= and
+  publish it as =theindex.html=.
+
+The file is created when first publishing a project with the
+~:makeindex~ set.  The file only contains a statement =#+INCLUDE:
+"theindex.inc"=.  You can then build around this include statement by
+adding a title, style information, etc.
+
+#+cindex: @samp{INDEX}, keyword
+Index entries are specified with =INDEX= keyword.  An entry that
+contains an exclamation mark creates a sub item.
+
+#+begin_example
+,*** Curriculum Vitae
+,#+INDEX: CV
+,#+INDEX: Application!CV
+#+end_example
+
+** Uploading Files
+:PROPERTIES:
+:DESCRIPTION: How to get files up on the server.
+:END:
+#+cindex: rsync
+#+cindex: unison
+
+For those people already utilizing third party sync tools such as
+Rsync or Unison, it might be preferable not to use the built-in remote
+publishing facilities of Org mode which rely heavily on Tramp.  Tramp,
+while very useful and powerful, tends not to be so efficient for
+multiple file transfer and has been known to cause problems under
+heavy usage.
+
+Specialized synchronization utilities offer several advantages.  In
+addition to timestamp comparison, they also do content and
+permissions/attribute checks.  For this reason you might prefer to
+publish your web to a local directory---possibly even /in place/ with
+your Org files---and then use Unison or Rsync to do the
+synchronization with the remote host.
+
+Since Unison, for example, can be configured as to which files to
+transfer to a certain remote destination, it can greatly simplify the
+project publishing definition.  Simply keep all files in the correct
+location, process your Org files with ~org-publish~ and let the
+synchronization tool do the rest.  You do not need, in this scenario,
+to include attachments such as JPG, CSS or PNG files in the project
+definition since the third-party tool syncs them.
+
+Publishing to a local directory is also much faster than to a remote
+one, so that you can afford more easily to republish entire projects.
+If you set ~org-publish-use-timestamps-flag~ to ~nil~, you gain the
+main benefit of re-including any changed external files such as source
+example files you might include with =INCLUDE= keyword.  The timestamp
+mechanism in Org is not smart enough to detect if included files have
+been modified.
+
+** Sample Configuration
+:PROPERTIES:
+:DESCRIPTION: Example projects.
+:END:
+
+Below we provide two example configurations.  The first one is
+a simple project publishing only a set of Org files.  The second
+example is more complex, with a multi-component project.
+
+*** Example: simple publishing configuration
+:PROPERTIES:
+:DESCRIPTION: One-component publishing.
+:ALT_TITLE: Simple example
+:END:
+
+This example publishes a set of Org files to the =public_html=
+directory on the local machine.
+
+#+begin_src emacs-lisp
+(setq org-publish-project-alist
+      '(("org"
+         :base-directory "~/org/"
+         :publishing-directory "~/public_html"
+         :section-numbers nil
+         :table-of-contents nil
+         :style "<link rel=\"stylesheet\"
+                href=\"../other/mystyle.css\"
+                type=\"text/css\"/>")))
+#+end_src
+
+*** Example: complex publishing configuration
+:PROPERTIES:
+:DESCRIPTION: A multi-component publishing example.
+:ALT_TITLE: Complex example
+:END:
+
+This more complicated example publishes an entire website, including
+Org files converted to HTML, image files, Emacs Lisp source code, and
+style sheets.  The publishing directory is remote and private files
+are excluded.
+
+To ensure that links are preserved, care should be taken to replicate
+your directory structure on the web server, and to use relative file
+paths.  For example, if your Org files are kept in =~/org/= and your
+publishable images in =~/images/=, you would link to an image with
+
+: file:../images/myimage.png
+
+On the web server, the relative path to the image should be the same.
+You can accomplish this by setting up an =images/= folder in the right
+place on the web server, and publishing images to it.
+
+#+begin_src emacs-lisp
+(setq org-publish-project-alist
+      '(("orgfiles"
+         :base-directory "~/org/"
+         :base-extension "org"
+         :publishing-directory "/ssh:user@host:~/html/notebook/"
+         :publishing-function org-html-publish-to-html
+         :exclude "PrivatePage.org" ;; regexp
+         :headline-levels 3
+         :section-numbers nil
+         :with-toc nil
+         :html-head "<link rel=\"stylesheet\"
+                  href=\"../other/mystyle.css\" type=\"text/css\"/>"
+         :html-preamble t)
+
+        ("images"
+         :base-directory "~/images/"
+         :base-extension "jpg\\|gif\\|png"
+         :publishing-directory "/ssh:user@host:~/html/images/"
+         :publishing-function org-publish-attachment)
+
+        ("other"
+         :base-directory "~/other/"
+         :base-extension "css\\|el"
+         :publishing-directory "/ssh:user@host:~/html/other/"
+         :publishing-function org-publish-attachment)
+        ("website" :components ("orgfiles" "images" "other"))))
+#+end_src
+
+** Triggering Publication
+:PROPERTIES:
+:DESCRIPTION: Publication commands.
+:END:
+
+Once properly configured, Org can publish with the following commands:
+
+- {{{kbd(C-c C-e P x)}}} (~org-publish~) ::
+
+  #+kindex: C-c C-e P x
+  #+findex: org-publish
+  Prompt for a specific project and publish all files that belong to
+  it.
+
+- {{{kbd(C-c C-e P p)}}} (~org-publish-current-project~) ::
+
+  #+kindex: C-c C-e P p
+  #+findex: org-publish-current-project
+  Publish the project containing the current file.
+
+- {{{kbd(C-c C-e P f)}}} (~org-publish-current-file~) ::
+
+  #+kindex: C-c C-e P f
+  #+findex: org-publish-current-file
+  Publish only the current file.
+
+- {{{kbd(C-c C-e P a)}}} (~org-publish-all~) ::
+
+  #+kindex: C-c C-e P a
+  #+findex: org-publish-all
+  Publish every project.
+
+#+vindex: org-publish-use-timestamps-flag
+Org uses timestamps to track when a file has changed.  The above
+functions normally only publish changed files.  You can override this
+and force publishing of all files by giving a prefix argument to any
+of the commands above, or by customizing the variable
+~org-publish-use-timestamps-flag~.  This may be necessary in
+particular if files include other files via =SETUPFILE= or =INCLUDE=
+keywords.
+
+* Working with Source Code
+:PROPERTIES:
+:DESCRIPTION: Export, evaluate, and tangle code blocks.
+:END:
+#+cindex: source code, working with
+
+Source code here refers to any plain text collection of computer
+instructions, possibly with comments, written using a human-readable
+programming language.  Org can manage source code in an Org document
+when the source code is identified with begin and end markers.
+Working with source code begins with identifying source code blocks.
+A source code block can be placed almost anywhere in an Org document;
+it is not restricted to the preamble or the end of the document.
+However, Org cannot manage a source code block if it is placed inside
+an Org comment or within a fixed width section.
+
+Here is an example source code block in the Emacs Lisp language:
+
+#+begin_example
+,#+BEGIN_SRC emacs-lisp
+  (defun org-xor (a b)
+     "Exclusive or."
+     (if a (not b) b))
+,#+END_SRC
+#+end_example
+
+Source code blocks are one of many Org block types, which also include
+"center", "comment", "dynamic", "example", "export", "quote",
+"special", and "verse".  This section pertains to blocks between
+=#+BEGIN_SRC= and =#+END_SRC=.
+
+Details of Org's facilities for working with source code are described
+in the following sections.
+
+** Features Overview
+:PROPERTIES:
+:DESCRIPTION: Enjoy the versatility of source blocks.
+:END:
+
+Org can manage the source code in the block delimited by =#+BEGIN_SRC=
+... =#+END_SRC= in several ways that can simplify housekeeping tasks
+essential to modern source code maintenance.  Org can edit, format,
+extract, export, and publish source code blocks.  Org can also compile
+and execute a source code block, then capture the results.  The Org
+mode literature sometimes refers to source code blocks as /live code/
+blocks because they can alter the content of the Org document or the
+material that it exports.  Users can control how live they want each
+source code block by tweaking the header arguments (see [[*Using Header
+Arguments]]) for compiling, execution, extraction, and exporting.
+
+For editing and formatting a source code block, Org uses an
+appropriate Emacs major mode that includes features specifically
+designed for source code in that language.
+
+Org can extract one or more source code blocks and write them to one
+or more source files---a process known as /tangling/ in literate
+programming terminology.
+
+For exporting and publishing, Org's back-ends can format a source code
+block appropriately, often with native syntax highlighting.
+
+For executing and compiling a source code block, the user can
+configure Org to select the appropriate compiler.  Org provides
+facilities to collect the result of the execution or compiler output,
+insert it into the Org document, and/or export it.  In addition to
+text results, Org can insert links to other data types, including
+audio, video, and graphics.  Org can also link a compiler error
+message to the appropriate line in the source code block.
+
+An important feature of Org's management of source code blocks is the
+ability to pass variables, functions, and results to one another using
+a common syntax for source code blocks in any language.  Although most
+literate programming facilities are restricted to one language or
+another, Org's language-agnostic approach lets the literate programmer
+match each programming task with the appropriate computer language and
+to mix them all together in a single Org document.  This
+interoperability among languages explains why Org's source code
+management facility was named /Org Babel/ by its originators, Eric
+Schulte and Dan Davison.
+
+Org mode fulfills the promise of easy verification and maintenance of
+publishing reproducible research by keeping text, data, code,
+configuration settings of the execution environment, the results of
+the execution, and associated narratives, claims, references, and
+internal and external links in a single Org document.
+
+** Structure of Code Blocks
+:PROPERTIES:
+:DESCRIPTION: Code block syntax described.
+:END:
+#+cindex: code block, structure
+#+cindex: source code, block structure
+#+cindex: @samp{NAME} keyword, in source blocks
+#+cindex: @samp{BEGIN_SRC}
+
+Org offers two ways to structure source code in Org documents: in
+a source code block, and directly inline.  Both specifications are
+shown below.
+
+A source code block conforms to this structure:
+
+#+begin_example
+,#+NAME: <name>
+,#+BEGIN_SRC <language> <switches> <header arguments>
+  <body>
+,#+END_SRC
+#+end_example
+
+Do not be put-off by having to remember the source block syntax.  Org
+mode offers a command for wrapping existing text in a block (see
+[[*Structure Templates]]).  Org also works with other completion systems
+in Emacs, some of which predate Org and have custom domain-specific
+languages for defining templates.  Regular use of templates reduces
+errors, increases accuracy, and maintains consistency.
+
+#+cindex: source code, inline
+An inline code block conforms to this structure:
+
+: src_<language>{<body>}
+
+#+texinfo: @noindent
+or
+
+: src_<language>[<header arguments>]{<body>}
+
+- =#+NAME: <name>= ::
+
+  Optional.  Names the source block so it can be called, like
+  a function, from other source blocks or inline code to evaluate or
+  to capture the results.  Code from other blocks, other files, and
+  from table formulas (see [[*The Spreadsheet]]) can use the name to
+  reference a source block.  This naming serves the same purpose as
+  naming Org tables.  Org mode requires unique names.  For duplicate
+  names, Org mode's behavior is undefined.
+
+- =#+BEGIN_SRC= ... =#+END_SRC= ::
+
+  Mandatory.  They mark the start and end of a block that Org
+  requires.  The =#+BEGIN_SRC= line takes additional arguments, as
+  described next.
+
+- =<language>= ::
+
+  #+cindex: language, in code blocks
+  Mandatory.  It is the identifier of the source code language in the
+  block.  See [[*Languages]], for identifiers of supported languages.
+
+- =<switches>= ::
+
+  #+cindex: switches, in code blocks
+  Optional.  Switches provide finer control of the code execution,
+  export, and format (see the discussion of switches in [[*Literal
+  Examples]]).
+
+- =<header arguments>= ::
+
+  #+cindex: header arguments, in code blocks
+  Optional.  Heading arguments control many aspects of evaluation,
+  export and tangling of code blocks (see [[*Using Header Arguments]]).
+  Using Org's properties feature, header arguments can be selectively
+  applied to the entire buffer or specific sub-trees of the Org
+  document.
+
+- =<body>= ::
+
+  Source code in the dialect of the specified language identifier.
+
+** Using Header Arguments
+:PROPERTIES:
+:DESCRIPTION: Different ways to set header arguments.
+:END:
+
+Org comes with many header arguments common to all languages.  New
+header arguments are added for specific languages as they become
+available for use in source code blocks.  A header argument is
+specified with an initial colon followed by the argument's name in
+lowercase.
+
+Since header arguments can be set in several ways, Org prioritizes
+them in case of overlaps or conflicts by giving local settings
+a higher priority.  Header values in function calls, for example,
+override header values from global defaults.
+
+*** System-wide header arguments
+:PROPERTIES:
+:UNNUMBERED: notoc
+:END:
+#+vindex: org-babel-default-header-args
+
+#+vindex: org-babel-default-header-args
+System-wide values of header arguments can be specified by customizing
+the ~org-babel-default-header-args~ variable, which defaults to the
+following values:
+
+#+begin_example
+:session    => "none"
+:results    => "replace"
+:exports    => "code"
+:cache      => "no"
+:noweb      => "no"
+#+end_example
+
+The example below sets =:noweb= header arguments to =yes=, which makes
+Org expand =:noweb= references by default.
+
+#+begin_src emacs-lisp
+(setq org-babel-default-header-args
+      (cons '(:noweb . "yes")
+            (assq-delete-all :noweb org-babel-default-header-args)))
+#+end_src
+
+#+cindex: language specific default header arguments
+#+cindex: default header arguments per language
+Each language can have separate default header arguments by
+customizing the variable ~org-babel-default-header-args:<LANG>~, where
+{{{var(<LANG>)}}} is the name of the language.  For details, see the
+language-specific online documentation at
+https://orgmode.org/worg/org-contrib/babel/.
+
+*** Header arguments in Org mode properties
+:PROPERTIES:
+:UNNUMBERED: notoc
+:END:
+
+For header arguments applicable to the buffer, use =PROPERTY= keyword
+anywhere in the Org file (see [[*Property Syntax]]).
+
+The following example makes all the R code blocks execute in the same
+session.  Setting =:results= to =silent= ignores the results of
+executions for all blocks, not just R code blocks; no results inserted
+for any block.
+
+#+begin_example
+,#+PROPERTY: header-args:R  :session *R*
+,#+PROPERTY: header-args    :results silent
+#+end_example
+
+#+vindex: org-use-property-inheritance
+Header arguments set through Org's property drawers (see [[*Property
+Syntax]]) apply at the sub-tree level on down.  Since these property
+drawers can appear anywhere in the file hierarchy, Org uses outermost
+call or source block to resolve the values.  Org ignores
+~org-use-property-inheritance~ setting.
+
+In this example, =:cache= defaults to =yes= for all code blocks in the
+sub-tree.
+
+#+begin_example
+,* sample header
+  :PROPERTIES:
+  :header-args:    :cache yes
+  :END:
+#+end_example
+
+#+kindex: C-c C-x p
+#+findex: org-set-property
+Properties defined through ~org-set-property~ function, bound to
+{{{kbd(C-c C-x p)}}}, apply to all active languages.  They override
+properties set in ~org-babel-default-header-args~.
+
+#+cindex: language specific header arguments properties
+#+cindex: header arguments per language
+Language-specific header arguments are also read from properties
+=header-args:<LANG>= where {{{var(<LANG>)}}} is the language
+identifier.  For example,
+
+#+begin_example
+,* Heading
+  :PROPERTIES:
+  :header-args:clojure:    :session *clojure-1*
+  :header-args:R:          :session *R*
+  :END:
+,** Subheading
+  :PROPERTIES:
+  :header-args:clojure:    :session *clojure-2*
+  :END:
+#+end_example
+
+#+texinfo: @noindent
+would force separate sessions for Clojure blocks in =Heading= and
+=Subheading=, but use the same session for all R blocks.  Blocks in
+=Subheading= inherit settings from =Heading=.
+
+*** Code block specific header arguments
+:PROPERTIES:
+:UNNUMBERED: notoc
+:END:
+
+Header arguments are most commonly set at the source code block level,
+on the =#+BEGIN_SRC= line.  Arguments set at this level take
+precedence over those set in the ~org-babel-default-header-args~
+variable, and also those set as header properties.
+
+In the following example, setting =:results= to =silent= makes it
+ignore results of the code execution.  Setting =:exports= to =code=
+exports only the body of the code block to HTML or LaTeX.
+
+#+begin_example
+,#+NAME: factorial
+,#+BEGIN_SRC haskell :results silent :exports code :var n=0
+  fac 0 = 1
+  fac n = n * fac (n-1)
+,#+END_SRC
+#+end_example
+
+The same header arguments in an inline code block:
+
+: src_haskell[:exports both]{fac 5}
+
+#+cindex: @samp{HEADER}, keyword
+Code block header arguments can span multiple lines using =#+HEADER:=
+on each line.  Note that Org currently accepts the plural spelling of
+=#+HEADER:= only as a convenience for backward-compatibility.  It may
+be removed at some point.
+
+Multi-line header arguments on an unnamed code block:
+
+#+begin_example
+,#+HEADER: :var data1=1
+,#+BEGIN_SRC emacs-lisp :var data2=2
+   (message "data1:%S, data2:%S" data1 data2)
+,#+END_SRC
+
+,#+RESULTS:
+: data1:1, data2:2
+#+end_example
+
+Multi-line header arguments on a named code block:
+
+#+begin_example
+,#+NAME: named-block
+,#+HEADER: :var data=2
+,#+BEGIN_SRC emacs-lisp
+  (message "data:%S" data)
+,#+END_SRC
+
+,#+RESULTS: named-block
+  : data:2
+#+end_example
+
+*** Header arguments in function calls
+:PROPERTIES:
+:UNNUMBERED: notoc
+:END:
+
+Header arguments in function calls are the most specific and override
+all other settings in case of an overlap.  They get the highest
+priority.  Two =#+CALL:= examples are shown below.  For the complete
+syntax of =CALL= keyword, see [[*Evaluating Code Blocks]].
+
+In this example, =:exports results= header argument is applied to the
+evaluation of the =#+CALL:= line.
+
+: #+CALL: factorial(n=5) :exports results
+
+In this example, =:session special= header argument is applied to the
+evaluation of =factorial= code block.
+
+: #+CALL: factorial[:session special](n=5)
+
+** Environment of a Code Block
+:PROPERTIES:
+:DESCRIPTION: Arguments, sessions, working directory...
+:END:
+
+*** Passing arguments
+:PROPERTIES:
+:UNNUMBERED: notoc
+:END:
+
+#+cindex: passing arguments to code blocks
+#+cindex: arguments, in code blocks
+#+cindex: @samp{var}, header argument
+Use =var= for passing arguments to source code blocks.  The specifics
+of variables in code blocks vary by the source language and are
+covered in the language-specific documentation.  The syntax for =var=,
+however, is the same for all languages.  This includes declaring
+a variable, and assigning a default value.
+
+The following syntax is used to pass arguments to code blocks using
+the =var= header argument.
+
+: :var NAME=ASSIGN
+
+#+texinfo: @noindent
+{{{var(NAME)}}} is the name of the variable bound in the code block
+body.  {{{var(ASSIGN)}}} is a literal value, such as a string,
+a number, a reference to a table, a list, a literal example, another
+code block---with or without arguments---or the results of evaluating
+a code block.
+
+Here are examples of passing values by reference:
+
+- table ::
+
+  A table named with a =NAME= keyword.
+
+  #+begin_example
+  ,#+NAME: example-table
+  | 1 |
+  | 2 |
+  | 3 |
+  | 4 |
+
+  ,#+NAME: table-length
+  ,#+BEGIN_SRC emacs-lisp :var table=example-table
+    (length table)
+  ,#+END_SRC
+
+  ,#+RESULTS: table-length
+  : 4
+  #+end_example
+
+  When passing a table, you can treat specially the row, or the
+  column, containing labels for the columns, or the rows, in the
+  table.
+
+  #+cindex: @samp{colnames}, header argument
+  The =colnames= header argument accepts =yes=, =no=, or =nil= values.
+  The default value is =nil=: if an input table has column
+  names---because the second row is a horizontal rule---then Org
+  removes the column names, processes the table, puts back the column
+  names, and then writes the table to the results block.  Using =yes=,
+  Org does the same to the first row, even if the initial table does
+  not contain any horizontal rule.  When set to =no=, Org does not
+  pre-process column names at all.
+
+  #+begin_example
+  ,#+NAME: less-cols
+  | a |
+  |---|
+  | b |
+  | c |
+
+  ,#+BEGIN_SRC python :var tab=less-cols :colnames nil
+    return [[val + '*' for val in row] for row in tab]
+  ,#+END_SRC
+
+  ,#+RESULTS:
+  | a  |
+  |----|
+  | b* |
+  | c* |
+  #+end_example
+
+  #+cindex: @samp{rownames}, header argument
+  Similarly, the =rownames= header argument can take two values: =yes=
+  or =no=.  When set to =yes=, Org removes the first column, processes
+  the table, puts back the first column, and then writes the table to
+  the results block.  The default is =no=, which means Org does not
+  pre-process the first column.  Note that Emacs Lisp code blocks
+  ignore =rownames= header argument because of the ease of
+  table-handling in Emacs.
+
+  #+begin_example
+  ,#+NAME: with-rownames
+  | one | 1 | 2 | 3 | 4 |  5 |
+  | two | 6 | 7 | 8 | 9 | 10 |
+
+  ,#+BEGIN_SRC python :var tab=with-rownames :rownames yes
+    return [[val + 10 for val in row] for row in tab]
+  ,#+END_SRC
+
+  ,#+RESULTS:
+  | one | 11 | 12 | 13 | 14 | 15 |
+  | two | 16 | 17 | 18 | 19 | 20 |
+  #+end_example
+
+- list ::
+
+  A simple named list.
+
+  #+begin_example
+  ,#+NAME: example-list
+  - simple
+    - not
+    - nested
+  - list
+
+  ,#+BEGIN_SRC emacs-lisp :var x=example-list
+    (print x)
+  ,#+END_SRC
+
+  ,#+RESULTS:
+  | simple | list |
+  #+end_example
+
+  Note that only the top level list items are passed along.  Nested
+  list items are ignored.
+
+- code block without arguments ::
+
+  A code block name, as assigned by =NAME= keyword from the example
+  above, optionally followed by parentheses.
+
+  #+begin_example
+  ,#+BEGIN_SRC emacs-lisp :var length=table-length()
+    (* 2 length)
+  ,#+END_SRC
+
+  ,#+RESULTS:
+  : 8
+  #+end_example
+
+- code block with arguments ::
+
+  A code block name, as assigned by =NAME= keyword, followed by
+  parentheses and optional arguments passed within the parentheses.
+
+  #+begin_example
+  ,#+NAME: double
+  ,#+BEGIN_SRC emacs-lisp :var input=8
+    (* 2 input)
+  ,#+END_SRC
+
+  ,#+RESULTS: double
+  : 16
+
+  ,#+NAME: squared
+  ,#+BEGIN_SRC emacs-lisp :var input=double(input=1)
+    (* input input)
+  ,#+END_SRC
+
+  ,#+RESULTS: squared
+  : 4
+  #+end_example
+
+- literal example ::
+
+  A literal example block named with a =NAME= keyword.
+
+  #+begin_example
+  ,#+NAME: literal-example
+  ,#+BEGIN_EXAMPLE
+    A literal example
+    on two lines
+  ,#+END_EXAMPLE
+
+  ,#+NAME: read-literal-example
+  ,#+BEGIN_SRC emacs-lisp :var x=literal-example
+    (concatenate #'string x " for you.")
+  ,#+END_SRC
+
+  ,#+RESULTS: read-literal-example
+  : A literal example
+  : on two lines for you.
+  #+end_example
+
+Indexing variable values enables referencing portions of a variable.
+Indexes are 0 based with negative values counting backwards from the
+end.  If an index is separated by commas then each subsequent section
+indexes as the next dimension.  Note that this indexing occurs
+/before/ other table-related header arguments are applied, such as
+=hlines=, =colnames= and =rownames=.  The following example assigns
+the last cell of the first row the table =example-table= to the
+variable =data=:
+
+#+begin_example
+,#+NAME: example-table
+| 1 | a |
+| 2 | b |
+| 3 | c |
+| 4 | d |
+
+,#+BEGIN_SRC emacs-lisp :var data=example-table[0,-1]
+  data
+,#+END_SRC
+
+,#+RESULTS:
+: a
+#+end_example
+
+Two integers separated by a colon reference a range of variable
+values.  In that case the entire inclusive range is referenced.  For
+example the following assigns the middle three rows of =example-table=
+to =data=.
+
+#+begin_example
+,#+NAME: example-table
+| 1 | a |
+| 2 | b |
+| 3 | c |
+| 4 | d |
+| 5 | 3 |
+
+,#+BEGIN_SRC emacs-lisp :var data=example-table[1:3]
+  data
+,#+END_SRC
+
+,#+RESULTS:
+| 2 | b |
+| 3 | c |
+| 4 | d |
+#+end_example
+
+To pick the entire range, use an empty index, or the single character
+=*=.  =0:-1= does the same thing.  Example below shows how to
+reference the first column only.
+
+#+begin_example
+,#+NAME: example-table
+| 1 | a |
+| 2 | b |
+| 3 | c |
+| 4 | d |
+
+,#+BEGIN_SRC emacs-lisp :var data=example-table[,0]
+  data
+,#+END_SRC
+
+,#+RESULTS:
+| 1 | 2 | 3 | 4 |
+#+end_example
+
+Index referencing can be used for tables and code blocks.  Index
+referencing can handle any number of dimensions.  Commas delimit
+multiple dimensions, as shown below.
+
+#+begin_example
+,#+NAME: 3D
+,#+BEGIN_SRC emacs-lisp
+  '(((1  2  3)  (4  5  6)  (7  8  9))
+    ((10 11 12) (13 14 15) (16 17 18))
+    ((19 20 21) (22 23 24) (25 26 27)))
+,#+END_SRC
+
+,#+BEGIN_SRC emacs-lisp :var data=3D[1,,1]
+  data
+,#+END_SRC
+
+,#+RESULTS:
+| 11 | 14 | 17 |
+#+end_example
+
+Note that row names and column names are not removed prior to variable
+indexing.  You need to take them into account, even when =colnames= or
+=rownames= header arguments remove them.
+
+Emacs lisp code can also set the values for variables.  To
+differentiate a value from Lisp code, Org interprets any value
+starting with =(=, =[=, ='= or =`= as Emacs Lisp code.  The result of
+evaluating that code is then assigned to the value of that variable.
+The following example shows how to reliably query and pass the file
+name of the Org mode buffer to a code block using headers.  We need
+reliability here because the file's name could change once the code in
+the block starts executing.
+
+#+begin_example
+,#+BEGIN_SRC sh :var filename=(buffer-file-name) :exports both
+  wc -w $filename
+,#+END_SRC
+#+end_example
+
+Note that values read from tables and lists are not mistakenly
+evaluated as Emacs Lisp code, as illustrated in the following example.
+
+#+begin_example
+,#+NAME: table
+| (a b c) |
+
+,#+HEADER: :var data=table[0,0]
+,#+BEGIN_SRC perl
+  $data
+,#+END_SRC
+
+,#+RESULTS:
+: (a b c)
+#+end_example
+
+*** Using sessions
+:PROPERTIES:
+:UNNUMBERED: notoc
+:END:
+
+#+cindex: using sessions in code blocks
+#+cindex: @samp{session}, header argument
+Two code blocks can share the same environment.  The =session= header
+argument is for running multiple source code blocks under one session.
+Org runs code blocks with the same session name in the same
+interpreter process.
+
+- =none= ::
+
+  Default.  Each code block gets a new interpreter process to execute.
+  The process terminates once the block is evaluated.
+
+- {{{var(STRING)}}} ::
+
+  Any string besides =none= turns that string into the name of that
+  session.  For example, =:session STRING= names it =STRING=.  If
+  =session= has no value, then the session name is derived from the
+  source language identifier.  Subsequent blocks with the same source
+  code language use the same session.  Depending on the language,
+  state variables, code from other blocks, and the overall interpreted
+  environment may be shared.  Some interpreted languages support
+  concurrent sessions when subsequent source code language blocks
+  change session names.
+
+Only languages that provide interactive evaluation can have session
+support.  Not all languages provide this support, such as C and ditaa.
+Even languages, such as Python and Haskell, that do support
+interactive evaluation impose limitations on allowable language
+constructs that can run interactively.  Org inherits those limitations
+for those code blocks running in a session.
+
+*** Choosing a working directory
+:PROPERTIES:
+:UNNUMBERED: notoc
+:END:
+
+#+cindex: working directory, in a code block
+#+cindex: @samp{dir}, header argument
+#+cindex: @samp{mkdirp}, header argument
+The =dir= header argument specifies the default directory during code
+block execution.  If it is absent, then the directory associated with
+the current buffer is used.  In other words, supplying =:dir
+DIRECTORY= temporarily has the same effect as changing the current
+directory with {{{kbd(M-x cd RET DIRECTORY)}}}, and then not setting
+=dir=.  Under the surface, =dir= simply sets the value of the Emacs
+variable ~default-directory~.  Setting =mkdirp= header argument to
+a non-~nil~ value creates the directory, if necessary.
+
+For example, to save the plot file in the =Work/= folder of the home
+directory---notice tilde is expanded:
+
+#+begin_example
+,#+BEGIN_SRC R :file myplot.png :dir ~/Work
+  matplot(matrix(rnorm(100), 10), type="l")
+,#+END_SRC
+#+end_example
+
+To evaluate the code block on a remote machine, supply a remote
+directory name using Tramp syntax.  For example:
+
+#+begin_example
+,#+BEGIN_SRC R :file plot.png :dir /scp:dand@yakuba.princeton.edu:
+  plot(1:10, main=system("hostname", intern=TRUE))
+,#+END_SRC
+#+end_example
+
+Org first captures the text results as usual for insertion in the Org
+file.  Then Org also inserts a link to the remote file, thanks to
+Emacs Tramp.  Org constructs the remote path to the file name from
+=dir= and ~default-directory~, as illustrated here:
+
+: [[file:/scp:dand@yakuba.princeton.edu:/home/dand/plot.png][plot.png]]
+
+When =dir= is used with =session=, Org sets the starting directory for
+a new session.  But Org does not alter the directory of an already
+existing session.
+
+Do not use =dir= with =:exports results= or with =:exports both= to
+avoid Org inserting incorrect links to remote files.  That is because
+Org does not expand ~default directory~ to avoid some underlying
+portability issues.
+
+*** Inserting headers and footers
+:PROPERTIES:
+:UNNUMBERED: notoc
+:END:
+
+#+cindex: headers, in code blocks
+#+cindex: footers, in code blocks
+#+cindex: @samp{prologue}, header argument
+The =prologue= header argument is for appending to the top of the code
+block for execution, like a reset instruction.  For example, you may
+use =:prologue "reset"= in a Gnuplot code block or, for every such
+block:
+
+#+begin_src emacs-lisp
+(add-to-list 'org-babel-default-header-args:gnuplot
+             '((:prologue . "reset")))
+
+#+end_src
+
+#+cindex: @samp{epilogue}, header argument
+Likewise, the value of the =epilogue= header argument is for appending
+to the end of the code block for execution.
+
+** Evaluating Code Blocks
+:PROPERTIES:
+:DESCRIPTION: Place results of evaluation in the Org buffer.
+:END:
+#+cindex: code block, evaluating
+#+cindex: source code, evaluating
+#+cindex: @samp{RESULTS}, keyword
+
+A note about security: With code evaluation comes the risk of harm.
+Org safeguards by prompting for user's permission before executing any
+code in the source block.  To customize this safeguard, or disable it,
+see [[*Code Evaluation and Security Issues]].
+
+*** How to evaluate source code
+:PROPERTIES:
+:UNNUMBERED: notoc
+:END:
+
+Org captures the results of the code block evaluation and inserts them
+in the Org file, right after the code block.  The insertion point is
+after a newline and the =RESULTS= keyword.  Org creates the =RESULTS=
+keyword if one is not already there.
+
+By default, Org enables only Emacs Lisp code blocks for execution.
+See [[*Languages]] to enable other languages.
+
+#+kindex: C-c C-c
+#+kindex: C-c C-v e
+#+findex: org-babel-execute-src-block
+Org provides many ways to execute code blocks.  {{{kbd(C-c C-c)}}} or
+{{{kbd(C-c C-v e)}}} with the point on a code block[fn:141] calls the
+~org-babel-execute-src-block~ function, which executes the code in the
+block, collects the results, and inserts them in the buffer.
+
+#+cindex: @samp{CALL}, keyword
+#+vindex: org-babel-inline-result-wrap
+By calling a named code block[fn:142] from an Org mode buffer or
+a table.  Org can call the named code blocks from the current Org mode
+buffer or from the "Library of Babel" (see [[*Library of Babel]]).
+
+The syntax for =CALL= keyword is:
+
+#+begin_example
+,#+CALL: <name>(<arguments>)
+,#+CALL: <name>[<inside header arguments>](<arguments>) <end header arguments>
+#+end_example
+
+The syntax for inline named code blocks is:
+
+#+begin_example
+... call_<name>(<arguments>) ...
+... call_<name>[<inside header arguments>](<arguments>)[<end header 
arguments>] ...
+#+end_example
+
+When inline syntax is used, the result is wrapped based on the
+variable ~org-babel-inline-result-wrap~, which by default is set to
+~"=%s="~ to produce verbatim text suitable for markup.
+
+- =<name>= ::
+
+  This is the name of the code block (see [[*Structure of Code Blocks]])
+  to be evaluated in the current document.  If the block is located in
+  another file, start =<name>= with the file name followed by
+  a colon.  For example, in order to execute a block named =clear-data=
+  in =file.org=, you can write the following:
+
+  : #+CALL: file.org:clear-data()
+
+- =<arguments>= ::
+
+  Org passes arguments to the code block using standard function call
+  syntax.  For example, a =#+CALL:= line that passes =4= to a code
+  block named =double=, which declares the header argument =:var n=2=,
+  would be written as:
+
+  : #+CALL: double(n=4)
+
+  #+texinfo: @noindent
+  Note how this function call syntax is different from the header
+  argument syntax.
+
+- =<inside header arguments>= ::
+
+  Org passes inside header arguments to the named code block using the
+  header argument syntax.  Inside header arguments apply to code block
+  evaluation.  For example, =[:results output]= collects results
+  printed to stdout during code execution of that block.  Note how
+  this header argument syntax is different from the function call
+  syntax.
+
+- =<end header arguments>= ::
+
+  End header arguments affect the results returned by the code block.
+  For example, =:results html= wraps the results in a =#+BEGIN_EXPORT
+  html= block before inserting the results in the Org buffer.
+
+*** Limit code block evaluation
+:PROPERTIES:
+:UNNUMBERED: notoc
+:END:
+
+#+cindex: @samp{eval}, header argument
+#+cindex: control code block evaluation
+The =eval= header argument can limit evaluation of specific code
+blocks and =CALL= keyword.  It is useful for protection against
+evaluating untrusted code blocks by prompting for a confirmation.
+
+- =never= or =no= ::
+
+  Org never evaluates the source code.
+
+- =query= ::
+
+  Org prompts the user for permission to evaluate the source code.
+
+- =never-export= or =no-export= ::
+
+  Org does not evaluate the source code when exporting, yet the user
+  can evaluate it interactively.
+
+- =query-export= ::
+
+  Org prompts the user for permission to evaluate the source code
+  during export.
+
+If =eval= header argument is not set, then Org determines whether to
+evaluate the source code from the ~org-confirm-babel-evaluate~
+variable (see [[*Code Evaluation and Security Issues]]).
+
+*** Cache results of evaluation
+:PROPERTIES:
+:UNNUMBERED: notoc
+:END:
+
+#+cindex: @samp{cache}, header argument
+#+cindex: cache results of code evaluation
+The =cache= header argument is for caching results of evaluating code
+blocks.  Caching results can avoid re-evaluating a code block that
+have not changed since the previous run.  To benefit from the cache
+and avoid redundant evaluations, the source block must have a result
+already present in the buffer, and neither the header
+arguments---including the value of =var= references---nor the text of
+the block itself has changed since the result was last computed.  This
+feature greatly helps avoid long-running calculations.  For some edge
+cases, however, the cached results may not be reliable.
+
+The caching feature is best for when code blocks are pure functions,
+that is functions that return the same value for the same input
+arguments (see [[*Environment of a Code Block]]), and that do not have
+side effects, and do not rely on external variables other than the
+input arguments.  Functions that depend on a timer, file system
+objects, and random number generators are clearly unsuitable for
+caching.
+
+A note of warning: when =cache= is used in a session, caching may
+cause unexpected results.
+
+When the caching mechanism tests for any source code changes, it does
+not expand noweb style references (see [[*Noweb Reference Syntax]]).
+
+The =cache= header argument can have one of two values: =yes= or =no=.
+
+- =no= ::
+
+  Default.  No caching of results; code block evaluated every time.
+
+- =yes= ::
+
+  Whether to run the code or return the cached results is determined
+  by comparing the SHA1 hash value of the combined code block and
+  arguments passed to it.  This hash value is packed on the
+  =#+RESULTS:= line from previous evaluation.  When hash values match,
+  Org does not evaluate the code block.  When hash values mismatch,
+  Org evaluates the code block, inserts the results, recalculates the
+  hash value, and updates =#+RESULTS:= line.
+
+In this example, both functions are cached.  But =caller= runs only if
+the result from =random= has changed since the last run.
+
+#+begin_example
+,#+NAME: random
+,#+BEGIN_SRC R :cache yes
+  runif(1)
+,#+END_SRC
+
+,#+RESULTS[a2a72cd647ad44515fab62e144796432793d68e1]: random
+0.4659510825295
+
+,#+NAME: caller
+,#+BEGIN_SRC emacs-lisp :var x=random :cache yes
+  x
+,#+END_SRC
+
+,#+RESULTS[bec9c8724e397d5df3b696502df3ed7892fc4f5f]: caller
+0.254227238707244
+#+end_example
+
+** Results of Evaluation
+:PROPERTIES:
+:DESCRIPTION: Choosing a results type, post-processing...
+:END:
+#+cindex: code block, results of evaluation
+#+cindex: source code, results of evaluation
+
+#+cindex: @samp{results}, header argument
+How Org handles results of a code block execution depends on many
+header arguments working together.  The primary determinant, however,
+is the =results= header argument.  It accepts four classes of options.
+Each code block can take only one option per class:
+
+- Collection ::
+
+  For how the results should be collected from the code block;
+
+- Type ::
+
+  For which type of result the code block will return; affects how Org
+  processes and inserts results in the Org buffer;
+
+- Format ::
+
+  For the result; affects how Org processes results;
+
+- Handling ::
+
+  For inserting results once they are properly formatted.
+
+*** Collection
+:PROPERTIES:
+:UNNUMBERED: notoc
+:END:
+
+Collection options specify the results.  Choose one of the options;
+they are mutually exclusive.
+
+- =value= ::
+
+  Default for most Babel libraries[fn:142].  Functional mode.  Org
+  gets the value by wrapping the code in a function definition in the
+  language of the source block.  That is why when using =:results
+  value=, code should execute like a function and return a value.  For
+  languages like Python, an explicit ~return~ statement is mandatory
+  when using =:results value=.  Result is the value returned by the
+  last statement in the code block.
+
+  When evaluating the code block in a session (see [[*Environment of
+  a Code Block]]), Org passes the code to an interpreter running as an
+  interactive Emacs inferior process.  Org gets the value from the
+  source code interpreter's last statement output.  Org has to use
+  language-specific methods to obtain the value.  For example, from
+  the variable ~_~ in Ruby, and the value of ~.Last.value~ in R.
+
+- =output= ::
+
+  Scripting mode.  Org passes the code to an external process running
+  the interpreter.  Org returns the contents of the standard output
+  stream as text results.
+
+  When using a session, Org passes the code to the interpreter running
+  as an interactive Emacs inferior process.  Org concatenates any text
+  output from the interpreter and returns the collection as a result.
+
+*** Type
+:PROPERTIES:
+:UNNUMBERED: notoc
+:END:
+
+Type tells what result types to expect from the execution of the code
+block.  Choose one of the options; they are mutually exclusive.  The
+default behavior is to automatically determine the result type.
+
+#+attr_texinfo: :sep ,
+- =table=, =vector= ::
+
+  Interpret the results as an Org table.  If the result is a single
+  value, create a table with one row and one column.  Usage example:
+  =:results value table=.
+
+  #+cindex: @samp{hlines}, header argument
+  In-between each table row or below the table headings, sometimes
+  results have horizontal lines, which are also known as "hlines".
+  The =hlines= argument with the default =no= value strips such lines
+  from the input table.  For most code, this is desirable, or else
+  those =hline= symbols raise unbound variable errors.  A =yes=
+  accepts such lines, as demonstrated in the following example.
+
+  #+begin_example
+  ,#+NAME: many-cols
+  | a | b | c |
+  |---+---+---|
+  | d | e | f |
+  |---+---+---|
+  | g | h | i |
+
+  ,#+NAME: no-hline
+  ,#+BEGIN_SRC python :var tab=many-cols :hlines no
+    return tab
+  ,#+END_SRC
+
+  ,#+RESULTS: no-hline
+  | a | b | c |
+  | d | e | f |
+  | g | h | i |
+
+  ,#+NAME: hlines
+  ,#+BEGIN_SRC python :var tab=many-cols :hlines yes
+    return tab
+  ,#+END_SRC
+
+  ,#+RESULTS: hlines
+  | a | b | c |
+  |---+---+---|
+  | d | e | f |
+  |---+---+---|
+  | g | h | i |
+  #+end_example
+
+- =list= ::
+
+  Interpret the results as an Org list.  If the result is a single
+  value, create a list of one element.
+
+- =scalar=, =verbatim= ::
+
+  Interpret literally and insert as quoted text.  Do not create
+  a table.  Usage example: =:results value verbatim=.
+
+- =file= ::
+
+  Interpret as a filename.  Save the results of execution of the code
+  block to that file, then insert a link to it.  You can control both
+  the filename and the description associated to the link.
+
+  #+cindex: @samp{file}, header argument
+  #+cindex: @samp{output-dir}, header argument
+  Org first tries to generate the filename from the value of the
+  =file= header argument and the directory specified using the
+  =output-dir= header arguments.  If =output-dir= is not specified,
+  Org assumes it is the current directory.
+
+  #+begin_example
+  ,#+BEGIN_SRC asymptote :results value file :file circle.pdf :output-dir img/
+    size(2cm);
+    draw(unitcircle);
+  ,#+END_SRC
+  #+end_example
+
+  #+cindex: @samp{file-ext}, header argument
+  If =file= header argument is missing, Org generates the base name of
+  the output file from the name of the code block, and its extension
+  from the =file-ext= header argument.  In that case, both the name
+  and the extension are mandatory.
+
+  #+begin_example
+  ,#+name: circle
+  ,#+BEGIN_SRC asymptote :results value file :file-ext pdf
+    size(2cm);
+    draw(unitcircle);
+  ,#+END_SRC
+  #+end_example
+
+  #+cindex: @samp{file-desc}, header argument
+  The =file-desc= header argument defines the description (see
+  [[*Link Format]]) for the link.  If =file-desc= is present but has no value,
+  the =file= value is used as the link description.  When this
+  argument is not present, the description is omitted.
+
+  #+cindex: @samp{sep}, header argument
+  By default, Org assumes that a table written to a file has
+  TAB-delimited output.  You can choose a different separator with
+  the =sep= header argument.
+
+  #+cindex: @samp{file-mode}, header argument
+  The =file-mode= header argument defines the file permissions.  To
+  make it executable, use =:file-mode (identity #o755)=.
+
+  #+begin_example
+  ,#+BEGIN_SRC shell :results file :file script.sh :file-mode (identity #o755)
+    echo "#!/bin/bash"
+    echo "echo Hello World"
+  ,#+END_SRC
+  #+end_example
+
+*** Format
+:PROPERTIES:
+:UNNUMBERED: notoc
+:END:
+
+Format pertains to the type of the result returned by the code block.
+Choose one of the options; they are mutually exclusive.  The default
+follows from the type specified above.
+
+#+attr_texinfo: :sep ,
+- =code= ::
+
+  Result enclosed in a code block.  Useful for parsing.  Usage
+  example: =:results value code=.
+
+- =drawer= ::
+
+  Result wrapped in a =RESULTS= drawer.  Useful for containing =raw=
+  or =org= results for later scripting and automated processing.
+  Usage example: =:results value drawer=.
+
+- =html= ::
+
+  Results enclosed in a =BEGIN_EXPORT html= block.  Usage example:
+  =:results value html=.
+
+- =latex= ::
+
+  Results enclosed in a =BEGIN_EXPORT latex= block.  Usage example:
+  =:results value latex=.
+
+- =link=, =graphics= ::
+
+  When used along with =file= type, the result is a link to the file
+  specified in =:file= header argument.  However, unlike plain =file=
+  type, nothing is written to the disk.  The block is used for its
+  side-effects only, as in the following example:
+
+  #+begin_example
+  ,#+begin_src shell :results file link :file "download.tar.gz"
+  wget -c "http://example.com/download.tar.gz";
+  ,#+end_src
+  #+end_example
+
+- =org= ::
+
+  Results enclosed in a =BEGIN_SRC org= block.  For comma-escape,
+  either {{{kbd(TAB)}}} in the block, or export the file.  Usage
+  example: =:results value org=.
+
+- =pp= ::
+
+  Result converted to pretty-print source code.  Enclosed in a code
+  block.  Languages supported: Emacs Lisp, Python, and Ruby.  Usage
+  example: =:results value pp=.
+
+- =raw= ::
+
+  Interpreted as raw Org mode.  Inserted directly into the buffer.
+  Aligned if it is a table.  Usage example: =:results value raw=.
+
+#+cindex: @samp{wrap}, header argument
+The =wrap= header argument unconditionally marks the results block by
+appending strings to =#+BEGIN_= and =#+END_=.  If no string is
+specified, Org wraps the results in a =#+BEGIN_results=
+... =#+END_results= block.  It takes precedent over the =results=
+value listed above.  E.g.,
+
+#+begin_example
+,#+BEGIN_SRC emacs-lisp :results html :wrap EXPORT markdown
+"<blink>Welcome back to the 90's</blink>"
+,#+END_SRC
+
+,#+RESULTS:
+,#+BEGIN_EXPORT markdown
+<blink>Welcome back to the 90's</blink>
+,#+END_EXPORT
+#+end_example
+
+*** Handling
+:PROPERTIES:
+:UNNUMBERED: notoc
+:END:
+
+Handling options after collecting the results.
+
+- =silent= ::
+
+  Do not insert results in the Org mode buffer, but echo them in the
+  minibuffer.  Usage example: =:results output silent=.
+
+- =replace= ::
+
+  Default.  Insert results in the Org buffer.  Remove previous
+  results.  Usage example: =:results output replace=.
+
+- =append= ::
+
+  Append results to the Org buffer.  Latest results are at the bottom.
+  Does not remove previous results.  Usage example: =:results output
+  append=.
+
+- =prepend= ::
+
+  Prepend results to the Org buffer.  Latest results are at the top.
+  Does not remove previous results.  Usage example: =:results output
+  prepend=.
+
+*** Post-processing
+:PROPERTIES:
+:UNNUMBERED: notoc
+:END:
+
+#+cindex: @samp{post}, header argument
+#+cindex: @samp{*this*}, in @samp{post} header argument
+The =post= header argument is for post-processing results from block
+evaluation.  When =post= has any value, Org binds the results to
+~*this*~ variable for easy passing to =var= header argument
+specifications (see [[*Environment of a Code Block]]).  That makes results
+available to other code blocks, or even for direct Emacs Lisp code
+execution.
+
+The following two examples illustrate =post= header argument in
+action.  The first one shows how to attach an =ATTR_LATEX= keyword
+using =post=.
+
+#+begin_example
+,#+NAME: attr_wrap
+,#+BEGIN_SRC sh :var data="" :var width="\\textwidth" :results output
+  echo "#+ATTR_LATEX: :width $width"
+  echo "$data"
+,#+END_SRC
+
+,#+HEADER: :file /tmp/it.png
+,#+BEGIN_SRC dot :post attr_wrap(width="5cm", data=*this*) :results drawer
+  digraph{
+          a -> b;
+          b -> c;
+          c -> a;
+  }
+,#+end_src
+
+,#+RESULTS:
+:RESULTS:
+,#+ATTR_LATEX :width 5cm
+[[file:/tmp/it.png]]
+:END:
+#+end_example
+
+The second example shows use of =colnames= header argument in =post=
+to pass data between code blocks.
+
+#+begin_example
+,#+NAME: round-tbl
+,#+BEGIN_SRC emacs-lisp :var tbl="" fmt="%.3f"
+  (mapcar (lambda (row)
+            (mapcar (lambda (cell)
+                      (if (numberp cell)
+                          (format fmt cell)
+                        cell))
+                    row))
+          tbl)
+,#+end_src
+
+,#+BEGIN_SRC R :colnames yes :post round-tbl[:colnames yes](*this*)
+  set.seed(42)
+  data.frame(foo=rnorm(1))
+,#+END_SRC
+
+,#+RESULTS:
+|   foo |
+|-------|
+| 1.371 |
+#+end_example
+
+** Exporting Code Blocks
+:PROPERTIES:
+:DESCRIPTION: Export contents and/or results.
+:END:
+#+cindex: code block, exporting
+#+cindex: source code, exporting
+
+It is possible to export the /code/ of code blocks, the /results/ of
+code block evaluation, /both/ the code and the results of code block
+evaluation, or /none/.  Org defaults to exporting /code/ for most
+languages.  For some languages, such as ditaa, Org defaults to
+/results/.  To export just the body of code blocks, see [[*Literal
+Examples]].  To selectively export sub-trees of an Org document, see
+[[*Exporting]].
+
+#+cindex: @samp{exports}, header argument
+The =exports= header argument is to specify if that part of the Org
+file is exported to, say, HTML or LaTeX formats.
+
+- =code= ::
+
+  The default.  The body of code is included into the exported file.
+  Example: =:exports code=.
+
+- =results= ::
+
+  The results of evaluation of the code is included in the exported
+  file.  Example: =:exports results=.
+
+- =both= ::
+
+  Both the code and results of evaluation are included in the exported
+  file.  Example: =:exports both=.
+
+- =none= ::
+
+  Neither the code nor the results of evaluation is included in the
+  exported file.  Whether the code is evaluated at all depends on
+  other options.  Example: =:exports none=.
+
+#+vindex: org-export-use-babel
+To stop Org from evaluating code blocks to speed exports, use the
+header argument =:eval never-export= (see [[*Evaluating Code Blocks]]).
+To stop Org from evaluating code blocks for greater security, set the
+~org-export-use-babel~ variable to ~nil~, but understand that header
+arguments will have no effect.
+
+Turning off evaluation comes in handy when batch processing.  For
+example, markup languages for wikis, which have a high risk of
+untrusted code.  Stopping code block evaluation also stops evaluation
+of all header arguments of the code block.  This may not be desirable
+in some circumstances.  So during export, to allow evaluation of just
+the header arguments but not any code evaluation in the source block,
+set =:eval never-export= (see [[*Evaluating Code Blocks]]).
+
+Org never evaluates code blocks in commented sub-trees when exporting
+(see [[*Comment Lines]]).  On the other hand, Org does evaluate code
+blocks in sub-trees excluded from export (see [[*Export Settings]]).
+
+** Extracting Source Code
+:PROPERTIES:
+:DESCRIPTION: Create pure source code files.
+:END:
+#+cindex: tangling
+#+cindex: source code, extracting
+#+cindex: code block, extracting source code
+
+Extracting source code from code blocks is a basic task in literate
+programming.  Org has features to make this easy.  In literate
+programming parlance, documents on creation are /woven/ with code and
+documentation, and on export, the code is tangled for execution by
+a computer.  Org facilitates weaving and tangling for producing,
+maintaining, sharing, and exporting literate programming documents.
+Org provides extensive customization options for extracting source
+code.
+
+When Org tangles code blocks, it expands, merges, and transforms them.
+Then Org recomposes them into one or more separate files, as
+configured through the options.  During this tangling process, Org
+expands variables in the source code, and resolves any noweb style
+references (see [[*Noweb Reference Syntax]]).
+
+*** Header arguments
+:PROPERTIES:
+:UNNUMBERED: notoc
+:END:
+
+#+cindex: @samp{tangle}, header argument
+The =tangle= header argument specifies if the code block is exported
+to source file(s).
+
+- =yes= ::
+
+  Export the code block to source file.  The file name for the source
+  file is derived from the name of the Org file, and the file
+  extension is derived from the source code language identifier.
+  Example: =:tangle yes=.
+
+- =no= ::
+
+  The default.  Do not extract the code in a source code file.
+  Example: =:tangle no=.
+
+- {{{var(FILENAME)}}} ::
+
+  Export the code block to source file whose file name is derived from
+  any string passed to the =tangle= header argument.  Org derives the
+  file name as being relative to the directory of the Org file's
+  location.  Example: =:tangle FILENAME=.
+
+#+cindex: @samp{mkdirp}, header argument
+The =mkdirp= header argument creates parent directories for tangled
+files if the directory does not exist.  A =yes= value enables
+directory creation whereas =no= inhibits it.
+
+#+cindex: @samp{comments}, header argument
+The =comments= header argument controls inserting comments into
+tangled files.  These are above and beyond whatever comments may
+already exist in the code block.
+
+- =no= ::
+
+  The default.  Do not insert any extra comments during tangling.
+
+- =link= ::
+
+  Wrap the code block in comments.  Include links pointing back to the
+  place in the Org file from where the code was tangled.
+
+- =yes= ::
+
+  Kept for backward compatibility; same as =link=.
+
+- =org= ::
+
+  Nearest headline text from Org file is inserted as comment.  The
+  exact text that is inserted is picked from the leading context of
+  the source block.
+
+- =both= ::
+
+  Includes both =link= and =org= options.
+
+- =noweb= ::
+
+  Includes =link= option, expands noweb references (see [[*Noweb
+  Reference Syntax]]), and wraps them in link comments inside the body
+  of the code block.
+
+#+cindex: @samp{padline}, header argument
+The =padline= header argument controls insertion of newlines to pad
+source code in the tangled file.
+
+- =yes= ::
+
+  Default.  Insert a newline before and after each code block in the
+  tangled file.
+
+- =no= ::
+
+  Do not insert newlines to pad the tangled code blocks.
+
+#+cindex: @samp{shebang}, header argument
+The =shebang= header argument can turn results into executable script
+files.  By setting it to a string value---for example, =:shebang
+"#!/bin/bash"=---Org inserts that string as the first line of the
+tangled file that the code block is extracted to.  Org then turns on
+the tangled file's executable permission.
+
+#+cindex: @samp{tangle-mode}, header argument
+The =tangle-mode= header argument specifies what permissions to set
+for tangled files by ~set-file-modes~.  For example, to make
+a read-only tangled file, use =:tangle-mode (identity #o444)=.  To
+make it executable, use =:tangle-mode (identity #o755)=.  It also
+overrides executable permission granted by =shebang=.  When multiple
+source code blocks tangle to a single file with different and
+conflicting =tangle-mode= header arguments, Org's behavior is
+undefined.
+
+#+cindex: @samp{no-expand}, header argument
+By default Org expands code blocks during tangling.  The =no-expand=
+header argument turns off such expansions.  Note that one side-effect
+of expansion by ~org-babel-expand-src-block~ also assigns values (see
+[[*Environment of a Code Block]]) to variables.  Expansions also replace
+noweb references with their targets (see [[*Noweb Reference Syntax]]).
+Some of these expansions may cause premature assignment, hence this
+option.  This option makes a difference only for tangling.  It has no
+effect when exporting since code blocks for execution have to be
+expanded anyway.
+
+*** Functions
+:PROPERTIES:
+:UNNUMBERED: notoc
+:END:
+
+- ~org-babel-tangle~ ::
+
+  #+findex: org-babel-tangle
+  #+kindex: C-c C-v t
+  Tangle the current file.  Bound to {{{kbd(C-c C-v t)}}}.
+
+  With prefix argument only tangle the current code block.
+
+- ~org-babel-tangle-file~ ::
+
+  #+findex: org-babel-tangle-file
+  #+kindex: C-c C-v f
+  Choose a file to tangle.  Bound to {{{kbd(C-c C-v f)}}}.
+
+*** Hooks
+:PROPERTIES:
+:UNNUMBERED: notoc
+:END:
+
+- ~org-babel-post-tangle-hook~ ::
+
+  #+vindex: org-babel-post-tangle-hook
+  This hook is run from within code files tangled by
+  ~org-babel-tangle~, making it suitable for post-processing,
+  compilation, and evaluation of code in the tangled files.
+
+*** Jumping between code and Org
+:PROPERTIES:
+:UNNUMBERED: notoc
+:END:
+
+#+findex: org-babel-tangle-jump-to-org
+Debuggers normally link errors and messages back to the source code.
+But for tangled files, we want to link back to the Org file, not to
+the tangled source file.  To make this extra jump, Org uses
+~org-babel-tangle-jump-to-org~ function with two additional source
+code block header arguments:
+
+1. Set =padline= to true---this is the default setting.
+2. Set =comments= to =link=, which makes Org insert links to the Org
+   file.
+
+** Languages
+:PROPERTIES:
+:DESCRIPTION: List of supported code block languages.
+:END:
+#+cindex: babel, languages
+#+cindex: source code, languages
+#+cindex: code block, languages
+
+Code blocks in the following languages are supported.
+
+#+attr_texinfo: :columns 0.25 0.25 0.25 0.20
+| Language   | Identifier    | Language       | Identifier   |
+|------------+---------------+----------------+--------------|
+| Asymptote  | =asymptote=   | Lisp           | =lisp=       |
+| Awk        | =awk=         | Lua            | =lua=        |
+| C          | =C=           | MATLAB         | =matlab=     |
+| C++        | =C++=[fn:143] | Mscgen         | =mscgen=     |
+| Clojure    | =clojure=     | Objective Caml | =ocaml=      |
+| CSS        | =css=         | Octave         | =octave=     |
+| D          | =D=[fn:144]   | Org mode       | =org=        |
+| ditaa      | =ditaa=       | Oz             | =oz=         |
+| Emacs Calc | =calc=        | Perl           | =perl=       |
+| Emacs Lisp | =emacs-lisp=  | Plantuml       | =plantuml=   |
+| Eshell     | =eshell=      | Processing.js  | =processing= |
+| Fortran    | =fortran=     | Python         | =python=     |
+| Gnuplot    | =gnuplot=     | R              | =R=          |
+| GNU Screen | =screen=      | Ruby           | =ruby=       |
+| Graphviz   | =dot=         | Sass           | =sass=       |
+| Haskell    | =haskell=     | Scheme         | =scheme=     |
+| Java       | =java=        | Sed            | =sed=        |
+| Javascript | =js=          | shell          | =sh=         |
+| LaTeX      | =latex=       | SQL            | =sql=        |
+| Ledger     | =ledger=      | SQLite         | =sqlite=     |
+| Lilypond   | =lilypond=    | Vala           | =vala=       |
+
+Additional documentation for some languages is at
+https://orgmode.org/worg/org-contrib/babel/languages.html.
+
+#+vindex: org-babel-load-languages
+By default, only Emacs Lisp is enabled for evaluation.  To enable or
+disable other languages, customize the ~org-babel-load-languages~
+variable either through the Emacs customization interface, or by
+adding code to the init file as shown next.
+
+In this example, evaluation is disabled for Emacs Lisp, and enabled
+for R.
+
+#+begin_src emacs-lisp
+(org-babel-do-load-languages
+ 'org-babel-load-languages
+ '((emacs-lisp . nil)
+   (R . t)))
+#+end_src
+
+Note that this is not the only way to enable a language.  Org also
+enables languages when loaded with ~require~ statement.  For example,
+the following enables execution of Clojure code blocks:
+
+#+begin_src emacs-lisp
+(require 'ob-clojure)
+#+end_src
+
+** Editing Source Code
+:PROPERTIES:
+:DESCRIPTION: Language major-mode editing.
+:END:
+#+cindex: code block, editing
+#+cindex: source code, editing
+
+#+kindex: C-c '
+Use {{{kbd(C-c ')}}} to edit the current code block.  It opens a new
+major mode edit buffer containing the body of the source code block,
+ready for any edits.  Use {{{kbd(C-c ')}}} again to close the buffer
+and return to the Org buffer.
+
+#+kindex: C-x C-s
+#+vindex: org-edit-src-auto-save-idle-delay
+#+cindex: auto-save, in code block editing
+{{{kbd(C-x C-s)}}} saves the buffer and updates the contents of the
+Org buffer.  Set ~org-edit-src-auto-save-idle-delay~ to save the base
+buffer after a certain idle delay time.  Set
+~org-edit-src-turn-on-auto-save~ to auto-save this buffer into
+a separate file using Auto-save mode.
+
+While editing the source code in the major mode, the Org Src minor
+mode remains active.  It provides these customization variables as
+described below.  For even more variables, look in the customization
+group ~org-edit-structure~.
+
+- ~org-src-lang-modes~ ::
+
+  #+vindex: org-src-lang-modes
+  If an Emacs major-mode named ~<LANG>-mode~ exists, where
+  {{{var(<LANG>)}}} is the language identifier from code block's
+  header line, then the edit buffer uses that major mode.  Use this
+  variable to arbitrarily map language identifiers to major modes.
+
+- ~org-src-window-setup~ ::
+
+  #+vindex: org-src-window-setup
+  For specifying Emacs window arrangement when the new edit buffer is
+  created.
+
+- ~org-src-preserve-indentation~ ::
+
+  #+cindex: indentation, in code blocks
+  #+vindex: org-src-preserve-indentation
+  Default is ~nil~.  Source code is indented.  This indentation
+  applies during export or tangling, and depending on the context, may
+  alter leading spaces and tabs.  When non-~nil~, source code is
+  aligned with the leftmost column.  No lines are modified during
+  export or tangling, which is very useful for white-space sensitive
+  languages, such as Python.
+
+- ~org-src-ask-before-returning-to-edit-buffer~ ::
+
+  #+vindex: org-src-ask-before-returning-to-edit-buffer
+  When ~nil~, Org returns to the edit buffer without further prompts.
+  The default prompts for a confirmation.
+
+#+vindex: org-src-fontify-natively
+#+vindex: org-src-block-faces
+Set ~org-src-fontify-natively~ to non-~nil~ to turn on native code
+fontification in the /Org/ buffer.  Fontification of code blocks can
+give visual separation of text and code on the display page.  To
+further customize the appearance of ~org-block~ for specific
+languages, customize ~org-src-block-faces~.  The following example
+shades the background of regular blocks, and colors source blocks only
+for Python and Emacs Lisp languages.
+
+#+begin_src emacs-lisp
+(require 'color)
+(set-face-attribute 'org-block nil :background
+                    (color-darken-name
+                     (face-attribute 'default :background) 3))
+
+(setq org-src-block-faces '(("emacs-lisp" (:background "#EEE2FF"))
+                            ("python" (:background "#E5FFB8"))))
+#+end_src
+
+** Noweb Reference Syntax
+:PROPERTIES:
+:DESCRIPTION: Literate programming in Org mode.
+:END:
+#+cindex: code block, noweb reference
+#+cindex: syntax, noweb
+#+cindex: source code, noweb reference
+
+#+cindex: @samp{noweb-ref}, header argument
+Source code blocks can include references to other source code blocks,
+using a noweb[fn:145] style syntax:
+
+: <<CODE-BLOCK-ID>>
+
+#+texinfo: @noindent
+where {{{var(CODE-BLOCK-ID)}}} refers to either the =NAME= of a single
+source code block, or a collection of one or more source code blocks
+sharing the same =noweb-ref= header argument (see [[*Using Header
+Arguments]]).  Org can replace such references with the source code of
+the block or blocks being referenced, or, in the case of a single
+source code block named with =NAME=, with the results of an evaluation
+of that block.
+
+#+cindex: @samp{noweb}, header argument
+The =noweb= header argument controls expansion of noweb syntax
+references.  Expansions occur when source code blocks are evaluated,
+tangled, or exported.
+
+- =no= ::
+
+  Default.  No expansion of noweb syntax references in the body of the
+  code when evaluating, tangling, or exporting.
+
+- =yes= ::
+
+  Expansion of noweb syntax references in the body of the code block
+  when evaluating, tangling, or exporting.
+
+- =tangle= ::
+
+  Expansion of noweb syntax references in the body of the code block
+  when tangling.  No expansion when evaluating or exporting.
+
+- =no-export= ::
+
+  Expansion of noweb syntax references in the body of the code block
+  when evaluating or tangling.  No expansion when exporting.
+
+- =strip-export= ::
+
+  Expansion of noweb syntax references in the body of the code block
+  when expanding prior to evaluating or tangling.  Removes noweb
+  syntax references when exporting.
+
+- =eval= ::
+
+  Expansion of noweb syntax references in the body of the code block
+  only before evaluating.
+
+In the most simple case, the contents of a single source block is
+inserted within other blocks.  Thus, in following example,
+
+#+begin_example
+,#+NAME: initialization
+,#+BEGIN_SRC emacs-lisp
+  (setq sentence "Never a foot too far, even.")
+,#+END_SRC
+
+,#+BEGIN_SRC emacs-lisp :noweb yes
+  <<initialization>>
+  (reverse sentence)
+,#+END_SRC
+#+end_example
+
+#+texinfo: @noindent
+the second code block is expanded as
+
+#+begin_example
+,#+BEGIN_SRC emacs-lisp :noweb yes
+  (setq sentence "Never a foot too far, even.")
+  (reverse sentence)
+,#+END_SRC
+#+end_example
+
+You may also include the contents of multiple blocks sharing a common
+=noweb-ref= header argument, which can be set at the file, sub-tree,
+or code block level.  In the example Org file shown next, the body of
+the source code in each block is extracted for concatenation to a pure
+code file when tangled.
+
+#+begin_example
+,#+BEGIN_SRC sh :tangle yes :noweb yes :shebang #!/bin/sh
+  <<fullest-disk>>
+,#+END_SRC
+,* the mount point of the fullest disk
+  :PROPERTIES:
+  :header-args: :noweb-ref fullest-disk
+  :END:
+
+,** query all mounted disks
+,#+BEGIN_SRC sh
+  df \
+,#+END_SRC
+
+,** strip the header row
+,#+BEGIN_SRC sh
+  |sed '1d' \
+,#+END_SRC
+
+,** output mount point of fullest disk
+,#+BEGIN_SRC sh
+  |awk '{if (u < +$5) {u = +$5; m = $6}} END {print m}'
+,#+END_SRC
+#+end_example
+
+#+cindex: @samp{noweb-sep}, header argument
+By default a newline separates each noweb reference concatenation.  To
+use a different separator, edit the =noweb-sep= header argument.
+
+Alternatively, Org can include the results of evaluation of a single
+code block rather than its body.  Evaluation occurs when parentheses,
+possibly including arguments, are appended to the code block name, as
+shown below.
+
+: <<NAME(optional arguments)>>
+
+Note that in this case, a code block name set by =NAME= keyword is
+required; the reference set by =noweb-ref= will not work when
+evaluation is desired.
+
+Here is an example that demonstrates how the exported content changes
+when noweb style references are used with parentheses versus without.
+Given:
+
+#+begin_example
+,#+NAME: some-code
+,#+BEGIN_SRC python :var num=0 :results output :exports none
+  print(num*10)
+,#+END_SRC
+#+end_example
+
+#+texinfo: @noindent
+this code block:
+
+#+begin_example
+,#+BEGIN_SRC text :noweb yes
+  <<some-code>>
+,#+END_SRC
+#+end_example
+
+#+texinfo: @noindent
+expands to:
+
+: print(num*10)
+
+Below, a similar noweb style reference is used, but with parentheses,
+while setting a variable =num= to 10:
+
+#+begin_example
+,#+BEGIN_SRC text :noweb yes
+  <<some-code(num=10)>>
+,#+END_SRC
+#+end_example
+
+#+texinfo: @noindent
+Note that the expansion now contains the results of the code block
+=some-code=, not the code block itself:
+
+: 100
+
+Noweb insertions honor prefix characters that appear before the noweb
+syntax reference.  This behavior is illustrated in the following
+example.  Because the =<<example>>= noweb reference appears behind the
+SQL comment syntax, each line of the expanded noweb reference is
+commented.  With:
+
+#+begin_example
+,#+NAME: example
+,#+BEGIN_SRC text
+  this is the
+  multi-line body of example
+,#+END_SRC
+#+end_example
+
+#+texinfo: @noindent
+this code block:
+
+#+begin_example
+,#+BEGIN_SRC sql :noweb yes
+ ---<<example>>
+,#+END_SRC
+#+end_example
+
+#+texinfo: @noindent
+expands to:
+
+#+begin_example
+,#+BEGIN_SRC sql :noweb yes
+ ---this is the
+ ---multi-line body of example
+,#+END_SRC
+#+end_example
+
+Since this change does not affect noweb replacement text without
+newlines in them, inline noweb references are acceptable.
+
+This feature can also be used for management of indentation in
+exported code snippets.  With:
+
+#+begin_example
+,#+NAME: if-true
+,#+BEGIN_SRC python :exports none
+  print('do things when true')
+,#+end_src
+
+,#+name: if-false
+,#+begin_src python :exports none
+  print('do things when false')
+,#+end_src
+#+end_example
+
+#+texinfo: @noindent
+this code block:
+
+#+begin_example
+,#+begin_src python :noweb yes :results output
+  if true:
+      <<if-true>>
+  else:
+      <<if-false>>
+,#+end_src
+#+end_example
+
+#+texinfo: @noindent
+expands to:
+
+#+begin_example
+if true:
+    print('do things when true')
+else:
+    print('do things when false')
+#+end_example
+
+When in doubt about the outcome of a source code block expansion, you
+can preview the results with the following command:
+
+- {{{kbd(C-c C-v v)}}} or {{{kbd(C-c C-v C-v)}}} 
(~org-babel-expand-src-block~) ::
+
+  #+findex: org-babel-expand-src-block
+  #+kindex: C-c C-v v
+  #+kindex: C-c C-v C-v
+  Expand the current source code block according to its header
+  arguments and pop open the results in a preview buffer.
+
+** Library of Babel
+:PROPERTIES:
+:DESCRIPTION: Use and contribute to a library of useful code blocks.
+:END:
+#+cindex: babel, library of
+#+cindex: source code, library
+#+cindex: code block, library
+
+The "Library of Babel" is a collection of code blocks.  Like
+a function library, these code blocks can be called from other Org
+files.  A collection of useful code blocks is available on 
[[https://orgmode.org/worg/library-of-babel.html][Worg]].  For
+remote code block evaluation syntax, see [[*Evaluating Code Blocks]].
+
+#+kindex: C-c C-v i
+#+findex: org-babel-lob-ingest
+For any user to add code to the library, first save the code in
+regular code blocks of an Org file, and then load the Org file with
+~org-babel-lob-ingest~, which is bound to {{{kbd(C-c C-v i)}}}.
+
+** Key bindings and Useful Functions
+:PROPERTIES:
+:DESCRIPTION: Work quickly with code blocks.
+:END:
+#+cindex: code block, key bindings
+
+Many common Org mode key sequences are re-bound depending on
+the context.
+
+Active key bindings in code blocks:
+
+#+kindex: C-c C-c
+#+findex: org-babel-execute-src-block
+#+kindex: C-c C-o
+#+findex: org-babel-open-src-block-result
+#+kindex: M-UP
+#+findex: org-babel-load-in-session
+#+kindex: M-DOWN
+#+findex: org-babel-pop-to-session
+#+attr_texinfo: :columns 0.2 0.55
+| Key binding        | Function                          |
+|--------------------+-----------------------------------|
+| {{{kbd(C-c C-c)}}} | ~org-babel-execute-src-block~     |
+| {{{kbd(C-c C-o)}}} | ~org-babel-open-src-block-result~ |
+| {{{kbd(M-UP)}}}    | ~org-babel-load-in-session~       |
+| {{{kbd(M-DOWN)}}}  | ~org-babel-pop-to-session~        |
+
+Active key bindings in Org mode buffer:
+
+#+kindex: C-c C-v p
+#+kindex: C-c C-v C-p
+#+kindex: C-c C-v n
+#+kindex: C-c C-v C-n
+#+kindex: C-c C-v e
+#+kindex: C-c C-v C-e
+#+kindex: C-c C-v o
+#+kindex: C-c C-v C-o
+#+kindex: C-c C-v v
+#+kindex: C-c C-v C-v
+#+kindex: C-c C-v u
+#+kindex: C-c C-v C-u
+#+kindex: C-c C-v g
+#+kindex: C-c C-v C-g
+#+kindex: C-c C-v r
+#+kindex: C-c C-v C-r
+#+kindex: C-c C-v b
+#+kindex: C-c C-v C-b
+#+kindex: C-c C-v s
+#+kindex: C-c C-v C-s
+#+kindex: C-c C-v d
+#+kindex: C-c C-v C-d
+#+kindex: C-c C-v t
+#+kindex: C-c C-v C-t
+#+kindex: C-c C-v f
+#+kindex: C-c C-v C-f
+#+kindex: C-c C-v c
+#+kindex: C-c C-v C-c
+#+kindex: C-c C-v j
+#+kindex: C-c C-v C-j
+#+kindex: C-c C-v l
+#+kindex: C-c C-v C-l
+#+kindex: C-c C-v i
+#+kindex: C-c C-v C-i
+#+kindex: C-c C-v I
+#+kindex: C-c C-v C-I
+#+kindex: C-c C-v z
+#+kindex: C-c C-v C-z
+#+kindex: C-c C-v a
+#+kindex: C-c C-v C-a
+#+kindex: C-c C-v h
+#+kindex: C-c C-v C-h
+#+kindex: C-c C-v x
+#+kindex: C-c C-v C-x
+#+findex: org-babel-previous-src-block
+#+findex: org-babel-next-src-block
+#+findex: org-babel-execute-maybe
+#+findex: org-babel-open-src-block-result
+#+findex: org-babel-expand-src-block
+#+findex: org-babel-goto-src-block-head
+#+findex: org-babel-goto-named-src-block
+#+findex: org-babel-goto-named-result
+#+findex: org-babel-execute-buffer
+#+findex: org-babel-execute-subtree
+#+findex: org-babel-demarcate-block
+#+findex: org-babel-tangle
+#+findex: org-babel-tangle-file
+#+findex: org-babel-check-src-block
+#+findex: org-babel-insert-header-arg
+#+findex: org-babel-load-in-session
+#+findex: org-babel-lob-ingest
+#+findex: org-babel-view-src-block-info
+#+findex: org-babel-switch-to-session-with-code
+#+findex: org-babel-sha1-hash
+#+findex: org-babel-describe-bindings
+#+findex: org-babel-do-key-sequence-in-edit-buffer
+#+attr_texinfo: :columns 0.45 0.55
+| Key binding                                    | Function                    
               |
+|------------------------------------------------+--------------------------------------------|
+| {{{kbd(C-c C-v p)}}} or {{{kbd(C-c C-v C-p)}}} | 
~org-babel-previous-src-block~             |
+| {{{kbd(C-c C-v n)}}} or {{{kbd(C-c C-v C-n)}}} | ~org-babel-next-src-block~  
               |
+| {{{kbd(C-c C-v e)}}} or {{{kbd(C-c C-v C-e)}}} | ~org-babel-execute-maybe~   
               |
+| {{{kbd(C-c C-v o)}}} or {{{kbd(C-c C-v C-o)}}} | 
~org-babel-open-src-block-result~          |
+| {{{kbd(C-c C-v v)}}} or {{{kbd(C-c C-v C-v)}}} | 
~org-babel-expand-src-block~               |
+| {{{kbd(C-c C-v u)}}} or {{{kbd(C-c C-v C-u)}}} | 
~org-babel-goto-src-block-head~            |
+| {{{kbd(C-c C-v g)}}} or {{{kbd(C-c C-v C-g)}}} | 
~org-babel-goto-named-src-block~           |
+| {{{kbd(C-c C-v r)}}} or {{{kbd(C-c C-v C-r)}}} | 
~org-babel-goto-named-result~              |
+| {{{kbd(C-c C-v b)}}} or {{{kbd(C-c C-v C-b)}}} | ~org-babel-execute-buffer~  
               |
+| {{{kbd(C-c C-v s)}}} or {{{kbd(C-c C-v C-s)}}} | ~org-babel-execute-subtree~ 
               |
+| {{{kbd(C-c C-v d)}}} or {{{kbd(C-c C-v C-d)}}} | ~org-babel-demarcate-block~ 
               |
+| {{{kbd(C-c C-v t)}}} or {{{kbd(C-c C-v C-t)}}} | ~org-babel-tangle~          
               |
+| {{{kbd(C-c C-v f)}}} or {{{kbd(C-c C-v C-f)}}} | ~org-babel-tangle-file~     
               |
+| {{{kbd(C-c C-v c)}}} or {{{kbd(C-c C-v C-c)}}} | ~org-babel-check-src-block~ 
               |
+| {{{kbd(C-c C-v j)}}} or {{{kbd(C-c C-v C-j)}}} | 
~org-babel-insert-header-arg~              |
+| {{{kbd(C-c C-v l)}}} or {{{kbd(C-c C-v C-l)}}} | ~org-babel-load-in-session~ 
               |
+| {{{kbd(C-c C-v i)}}} or {{{kbd(C-c C-v C-i)}}} | ~org-babel-lob-ingest~      
               |
+| {{{kbd(C-c C-v I)}}} or {{{kbd(C-c C-v C-I)}}} | 
~org-babel-view-src-block-info~            |
+| {{{kbd(C-c C-v z)}}} or {{{kbd(C-c C-v C-z)}}} | 
~org-babel-switch-to-session-with-code~    |
+| {{{kbd(C-c C-v a)}}} or {{{kbd(C-c C-v C-a)}}} | ~org-babel-sha1-hash~       
               |
+| {{{kbd(C-c C-v h)}}} or {{{kbd(C-c C-v C-h)}}} | 
~org-babel-describe-bindings~              |
+| {{{kbd(C-c C-v x)}}} or {{{kbd(C-c C-v C-x)}}} | 
~org-babel-do-key-sequence-in-edit-buffer~ |
+
+** Batch Execution
+:PROPERTIES:
+:DESCRIPTION: Call functions from the command line.
+:END:
+#+cindex: code block, batch execution
+#+cindex: source code, batch execution
+
+Org mode features, including working with source code facilities can
+be invoked from the command line.  This enables building shell scripts
+for batch processing, running automated system tasks, and expanding
+Org mode's usefulness.
+
+The sample script shows batch processing of multiple files using
+~org-babel-tangle~.
+
+#+begin_example
+#!/bin/sh
+# Tangle files with Org mode
+#
+emacs -Q --batch --eval "
+    (progn
+      (require 'ob-tangle)
+      (dolist (file command-line-args-left)
+        (with-current-buffer (find-file-noselect file)
+          (org-babel-tangle))))
+  " "$@"
+#+end_example
+
+* Miscellaneous
+:PROPERTIES:
+:DESCRIPTION: All the rest which did not fit elsewhere.
+:END:
+
+** Completion
+:PROPERTIES:
+:DESCRIPTION: @kbd{M-@key{TAB}} guesses completions.
+:END:
+#+cindex: completion, of @TeX{} symbols
+#+cindex: completion, of TODO keywords
+#+cindex: completion, of dictionary words
+#+cindex: completion, of option keywords
+#+cindex: completion, of tags
+#+cindex: completion, of property keys
+#+cindex: completion, of link abbreviations
+#+cindex: @TeX{} symbol completion
+#+cindex: TODO keywords completion
+#+cindex: dictionary word completion
+#+cindex: option keyword completion
+#+cindex: tag completion
+#+cindex: link abbreviations, completion of
+
+Org has in-buffer completions.  Unlike minibuffer completions, which
+are useful for quick command interactions, Org's in-buffer completions
+are more suitable for content creation in Org documents.  Type one or
+more letters and invoke the hot key to complete the text in-place.
+Depending on the context and the keys, Org offers different types of
+completions.  No minibuffer is involved.  Such mode-specific hot keys
+have become an integral part of Emacs and Org provides several
+shortcuts.
+
+- {{{kbd(M-TAB)}}} ::
+  #+kindex: M-TAB
+
+  Complete word at point.
+
+  - At the beginning of an empty headline, complete TODO keywords.
+
+  - After =\=, complete TeX symbols supported by the exporter.
+
+  - After =:= in a headline, complete tags.  Org deduces the list of
+    tags from the =TAGS= in-buffer option (see [[*Setting Tags]]), the
+    variable ~org-tag-alist~, or from all tags used in the current
+    buffer.
+
+  - After =:= and not in a headline, complete property keys.  The list
+    of keys is constructed dynamically from all keys used in the
+    current buffer.
+
+  - After =[[=, complete link abbreviations (see [[*Link Abbreviations]]).
+
+  - After =[[*=, complete headlines in the current buffer so that they
+    can be used in search links like: =[[*find this headline]]=
+
+  - After =#+=, complete the special keywords like =TYP_TODO= or
+    file-specific =OPTIONS=.  After option keyword is complete,
+    pressing {{{kbd(M-TAB)}}} again inserts example settings for this
+    keyword.
+
+  - After =STARTUP= keyword, complete startup items.
+
+  - When point is anywhere else, complete dictionary words using
+    Ispell.
+
+** Structure Templates
+:PROPERTIES:
+:DESCRIPTION: Quick insertion of structural elements.
+:END:
+#+cindex: template insertion
+#+cindex: insertion, of templates
+
+With just a few keystrokes, it is possible to insert empty structural
+blocks, such as =#+BEGIN_SRC= ... =#+END_SRC=, or to wrap existing
+text in such a block.
+
+- {{{kbd(C-c C-\,)}}} (~org-insert-structure-template~) ::
+
+  #+findex: org-insert-structure-template
+  #+kindex: C-c C-,
+  Prompt for a type of block structure, and insert the block at point.
+  If the region is active, it is wrapped in the block.  First prompts
+  the user for keys, which are used to look up a structure type from
+  the variable below.  If the key is {{{kbd(TAB)}}}, {{{kbd(RET)}}},
+  or {{{kbd(SPC)}}}, the user is prompted to enter a block type.
+
+#+vindex: org-structure-template-alist
+Available structure types are defined in
+~org-structure-template-alist~, see the docstring for adding or
+changing values.
+
+#+cindex: Tempo
+#+cindex: template expansion
+#+cindex: insertion, of templates
+#+vindex: org-tempo-keywords-alist
+Org Tempo expands snippets to structures defined in
+~org-structure-template-alist~ and ~org-tempo-keywords-alist~.  For
+example, {{{kbd(< s TAB)}}} creates a code block.  Enable it by
+customizing ~org-modules~ or add =(require 'org-tempo)= to your Emacs
+init file[fn:146].
+
+#+attr_texinfo: :columns 0.1 0.9
+| {{{kbd(a)}}} | =#+BEGIN_EXPORT ascii= ... =#+END_EXPORT= |
+| {{{kbd(c)}}} | =#+BEGIN_CENTER= ... =#+END_CENTER=       |
+| {{{kbd(C)}}} | =#+BEGIN_COMMENT= ... =#+END_COMMENT=     |
+| {{{kbd(e)}}} | =#+BEGIN_EXAMPLE= ... =#+END_EXAMPLE=     |
+| {{{kbd(E)}}} | =#+BEGIN_EXPORT= ... =#+END_EXPORT= |
+| {{{kbd(h)}}} | =#+BEGIN_EXPORT html= ... =#+END_EXPORT=  |
+| {{{kbd(l)}}} | =#+BEGIN_EXPORT latex= ... =#+END_EXPORT= |
+| {{{kbd(q)}}} | =#+BEGIN_QUOTE= ... =#+END_QUOTE=         |
+| {{{kbd(s)}}} | =#+BEGIN_SRC= ... =#+END_SRC=             |
+| {{{kbd(v)}}} | =#+BEGIN_VERSE= ... =#+END_VERSE=         |
+
+** Speed Keys
+:PROPERTIES:
+:DESCRIPTION: Electric commands at the beginning of a headline.
+:END:
+#+cindex: speed keys
+
+Single keystrokes can execute custom commands in an Org file when
+point is on a headline.  Without the extra burden of a meta or
+modifier key, Speed Keys can speed navigation or execute custom
+commands.  Besides faster navigation, Speed Keys may come in handy on
+small mobile devices that do not have full keyboards.  Speed Keys may
+also work on TTY devices known for their problems when entering Emacs
+key chords.
+
+#+vindex: org-use-speed-commands
+By default, Org has Speed Keys disabled.  To activate Speed Keys, set
+the variable ~org-use-speed-commands~ to a non-~nil~ value.  To
+trigger a Speed Key, point must be at the beginning of an Org
+headline, before any of the stars.
+
+#+vindex: org-speed-commands-user
+#+findex: org-speed-command-help
+Org comes with a pre-defined list of Speed Keys.  To add or modify
+Speed Keys, customize the variable, ~org-speed-commands-user~.  For
+more details, see the variable's docstring.  With Speed Keys
+activated, {{{kbd(M-x org-speed-command-help)}}}, or {{{kbd(?)}}} when
+point is at the beginning of an Org headline, shows currently active
+Speed Keys, including the user-defined ones.
+
+** A Cleaner Outline View
+:PROPERTIES:
+:DESCRIPTION: Getting rid of leading stars in the outline.
+:ALT_TITLE: Clean View
+:END:
+#+cindex: hiding leading stars
+#+cindex: dynamic indentation
+#+cindex: odd-levels-only outlines
+#+cindex: clean outline view
+
+Org's outline with stars and no indents can look cluttered for short
+documents.  For /book-like/ long documents, the effect is not as
+noticeable.  Org provides an alternate stars and indentation scheme,
+as shown on the right in the following table.  It displays only one
+star and indents text to line up with the heading:
+
+#+begin_example
+,* Top level headline             |    * Top level headline
+,** Second level                  |      * Second level
+,*** Third level                  |        * Third level
+some text                        |          some text
+,*** Third level                  |        * Third level
+more text                        |          more text
+,* Another top level headline     |    * Another top level headline
+#+end_example
+
+Org can achieve this in two ways, (1) by just displaying the buffer in
+this way without changing it, or (2) by actually indenting every line
+in the desired amount with hard spaces and hiding leading stars.
+
+*** Org Indent Mode
+
+#+cindex: Indent mode
+#+findex: org-indent-mode
+To display the buffer in the indented view, activate Org Indent minor
+mode, using {{{kbd(M-x org-indent-mode)}}}.  Text lines that are not
+headlines are prefixed with virtual spaces to vertically align with
+the headline text[fn:147].
+
+#+vindex: org-indent-indentation-per-level
+To make more horizontal space, the headlines are shifted by two
+characters.  Configure ~org-indent-indentation-per-level~ variable for
+a different number.
+
+#+vindex: org-indent-mode-turns-on-hiding-stars
+#+vindex: org-indent-mode-turns-off-org-adapt-indentation
+By default, Org Indent mode turns off ~org-adapt-indentation~ and does
+hide leading stars by locally setting ~org-hide-leading-stars~ to ~t~:
+only one star on each headline is visible, the rest are masked with
+the same font color as the background.  If you want to customize this
+default behavior, see ~org-indent-mode-turns-on-hiding-stars~ and
+~org-indent-mode-turns-off-org-adapt-indentation~.
+
+#+vindex: org-startup-indented
+To globally turn on Org Indent mode for all files, customize the
+variable ~org-startup-indented~.  To control it for individual files,
+use =STARTUP= keyword as follows:
+
+: #+STARTUP: indent
+: #+STARTUP: noindent
+
+*** Hard indentation
+
+It is possible to use hard spaces to achieve the indentation instead,
+if the bare ASCII file should have the indented look also outside
+Emacs[fn:148].  With Org's support, you have to indent all lines to
+line up with the outline headers.  You would use these
+settings[fn:149]:
+
+  #+begin_src emacs-lisp
+  (setq org-adapt-indentation t
+        org-hide-leading-stars t
+        org-odd-levels-only t)
+  #+end_src
+
+- /Indentation of text below headlines/ (~org-adapt-indentation~) ::
+
+  #+vindex: org-adapt-indentation
+  The first setting modifies paragraph filling, line wrapping, and
+  structure editing commands to preserving or adapting the indentation
+  as appropriate.
+
+- /Hiding leading stars/ (~org-hide-leading-stars~) ::
+
+  #+vindex: org-hide-leading-stars
+  #+vindex: org-hide, face
+  The second setting makes leading stars invisible by applying the
+  face ~org-hide~ to them.  For per-file preference, use these file
+  =STARTUP= options:
+
+  #+begin_example
+  ,#+STARTUP: hidestars
+  ,#+STARTUP: showstars
+  #+end_example
+
+- /Odd levels/ (~org-odd-levels-only~) ::
+
+  #+vindex: org-odd-levels-only
+  The third setting makes Org use only odd levels, 1, 3, 5, ..., in
+  the outline to create more indentation.  On a per-file level,
+  control this with:
+
+  #+begin_example
+  ,#+STARTUP: odd
+  ,#+STARTUP: oddeven
+  #+end_example
+
+  To convert a file between single and double stars layouts, use
+  {{{kbd(M-x org-convert-to-odd-levels)}}} and {{{kbd(M-x
+  org-convert-to-oddeven-levels)}}}.
+
+** Execute commands in the active region
+:PROPERTIES:
+:DESCRIPTION: Execute commands on multiple items in Org or agenda view.
+:END:
+
+#+vindex: org-loop-over-headlines-in-active-region
+When in an Org buffer and the region is active, some commands will
+apply to all the subtrees in the active region.  For example, hitting
+{{{kbd(C-c C-s)}}} when multiple headlines are within the active region will
+successively prompt you for a new schedule date and time.  To disable
+this, set the option ~org-loop-over-headlines-in-active-region~ to
+non-~t~, activate the region and run the command normally.
+
+#+vindex: org-agenda-loop-over-headlines-in-active-region
+~org-agenda-loop-over-headlines-in-active-region~ is the equivalent
+option of the agenda buffer, where you can also use [[*Bulk remote editing 
selected entries][bulk editing of
+selected entries]].
+
+Not all commands can loop in the active region and what subtrees or
+headlines are considered can be refined: see the docstrings of these
+options for more details.
+
+** Dynamic Headline Numbering
+:PROPERTIES:
+:DESCRIPTION: Display and update outline numbering.
+:END:
+
+#+cindex: Org Num mode
+#+cindex: number headlines
+The Org Num minor mode, toggled with {{{kbd(M-x org-num-mode)}}},
+displays outline numbering on top of headlines.  It also updates it
+automatically upon changes to the structure of the document.
+
+#+vindex: org-num-max-level
+#+vindex: org-num-skip-tags
+#+vindex: org-num-skip-commented
+#+vindex: org-num-skip-unnumbered
+By default, all headlines are numbered.  You can limit numbering to
+specific headlines according to their level, tags, =COMMENT= keyword,
+or =UNNUMBERED= property.  Set ~org-num-max-level~,
+~org-num-skip-tags~, ~org-num-skip-commented~,
+~org-num-skip-unnumbered~, or ~org-num-skip-footnotes~ accordingly.
+
+#+vindex: org-num-skip-footnotes
+If ~org-num-skip-footnotes~ is non-~nil~, footnotes sections (see
+[[*Creating Footnotes]]) are not numbered either.
+
+#+vindex: org-num-face
+#+vindex: org-num-format-function
+You can control how the numbering is displayed by setting
+~org-num-face~ and ~org-num-format-function~.
+
+#+vindex: org-startup-numerated
+You can also turn this mode globally for all Org files by setting the
+option ~org-startup-numerated~ to =t=, or locally on a file by using
+=#+startup: num=.
+
+** The Very Busy {{{kbd(C-c C-c)}}} Key
+:PROPERTIES:
+:DESCRIPTION: When in doubt, press @kbd{C-c C-c}.
+:END:
+#+kindex: C-c C-c
+#+cindex: @kbd{C-c C-c}, overview
+
+The {{{kbd(C-c C-c)}}} key in Org serves many purposes depending on
+the context.  It is probably the most over-worked, multi-purpose key
+combination in Org.  Its uses are well documented throughout this
+manual, but here is a consolidated list for easy reference.
+
+- If column view (see [[*Column View]]) is on, exit column view.
+
+- If any highlights shown in the buffer from the creation of a sparse
+  tree, or from clock display, remove such highlights.
+
+- If point is in one of the special =KEYWORD= lines, scan the buffer
+  for these lines and update the information.  Also reset the Org file
+  cache used to temporary store the contents of URLs used as values
+  for keywords like =SETUPFILE=.
+
+- If point is inside a table, realign the table.
+
+- If point is on a =TBLFM= keyword, re-apply the formulas to the
+  entire table.
+
+- If the current buffer is a capture buffer, close the note and file
+  it.  With a prefix argument, also jump to the target location after
+  saving the note.
+
+- If point is on a =<<<target>>>=, update radio targets and
+  corresponding links in this buffer.
+
+- If point is on a property line or at the start or end of a property
+  drawer, offer property commands.
+
+- If point is at a footnote reference, go to the corresponding
+  definition, and /vice versa/.
+
+- If point is on a statistics cookie, update it.
+
+- If point is in a plain list item with a checkbox, toggle the status
+  of the checkbox.
+
+- If point is on a numbered item in a plain list, renumber the ordered
+  list.
+
+- If point is on the =#+BEGIN= line of a dynamic block, the block is
+  updated.
+
+- If point is at a timestamp, fix the day name in the timestamp.
+
+** Summary of In-Buffer Settings
+:PROPERTIES:
+:DESCRIPTION: Overview of keywords.
+:ALT_TITLE: In-buffer Settings
+:END:
+#+cindex: in-buffer settings
+#+cindex: special keywords
+
+In-buffer settings start with =#+=, followed by a keyword, a colon,
+and then a word for each setting.  Org accepts multiple settings on
+the same line.  Org also accepts multiple lines for a keyword.  This
+manual describes these settings throughout.  A summary follows here.
+
+#+cindex: refresh set-up
+{{{kbd(C-c C-c)}}} activates any changes to the in-buffer settings.
+Closing and reopening the Org file in Emacs also activates the
+changes.
+
+#+attr_texinfo: :sep ,
+- =#+ARCHIVE: %s_done::= ::
+
+  #+cindex: @samp{ARCHIVE}, keyword
+  #+vindex: org-archive-location
+  Sets the archive location of the agenda file.  The corresponding
+  variable is ~org-archive-location~.
+
+- =#+CATEGORY= ::
+
+  #+cindex: @samp{CATEGORY}, keyword
+  Sets the category of the agenda file, which applies to the entire
+  document.
+
+- =#+COLUMNS: %25ITEM ...= ::
+
+  #+cindex: @samp{COLUMNS}, property
+  Set the default format for columns view.  This format applies when
+  columns view is invoked in locations where no =COLUMNS= property
+  applies.
+
+- =#+CONSTANTS: name1=value1 ...= ::
+
+  #+cindex: @samp{CONSTANTS}, keyword
+  #+vindex: org-table-formula-constants
+  #+vindex: org-table-formula
+  Set file-local values for constants that table formulas can use.
+  This line sets the local variable
+  ~org-table-formula-constants-local~.  The global version of this
+  variable is ~org-table-formula-constants~.
+
+- =#+FILETAGS: :tag1:tag2:tag3:= ::
+
+  #+cindex: @samp{FILETAGS}, keyword
+  Set tags that all entries in the file inherit from, including the
+  top-level entries.
+
+- =#+LINK: linkword replace= ::
+
+  #+cindex: @samp{LINK}, keyword
+  #+vindex: org-link-abbrev-alist
+  Each line specifies one abbreviation for one link.  Use multiple
+  =LINK= keywords for more, see [[*Link Abbreviations]].  The
+  corresponding variable is ~org-link-abbrev-alist~.
+
+- =#+PRIORITIES: highest lowest default= ::
+
+  #+cindex: @samp{PRIORITIES}, keyword
+  #+vindex: org-priority-highest
+  #+vindex: org-priority-lowest
+  #+vindex: org-priority-default
+  This line sets the limits and the default for the priorities.  All
+  three must be either letters A--Z or numbers 0--9.  The highest
+  priority must have a lower ASCII number than the lowest priority.
+
+- =#+PROPERTY: Property_Name Value= ::
+
+  #+cindex: @samp{PROPERTY}, keyword
+  This line sets a default inheritance value for entries in the
+  current buffer, most useful for specifying the allowed values of
+  a property.
+
+- =#+SETUPFILE: file= ::
+
+  #+cindex: @samp{SETUPFILE}, keyword
+  The setup file or a URL pointing to such file is for additional
+  in-buffer settings.  Org loads this file and parses it for any
+  settings in it only when Org opens the main file.  If URL is
+  specified, the contents are downloaded and stored in a temporary
+  file cache.  {{{kbd(C-c C-c)}}} on the settings line parses and
+  loads the file, and also resets the temporary file cache.  Org also
+  parses and loads the document during normal exporting process.  Org
+  parses the contents of this document as if it was included in the
+  buffer.  It can be another Org file.  To visit the file---not
+  a URL---use {{{kbd(C-c ')}}} while point is on the line with the
+  file name.
+
+- =#+STARTUP:= ::
+
+  #+cindex: @samp{STARTUP}, keyword
+  Startup options Org uses when first visiting a file.
+
+  #+vindex: org-startup-folded
+  The first set of options deals with the initial visibility of the
+  outline tree.  The corresponding variable for global default
+  settings is ~org-startup-folded~ with a default value of
+  ~showeverything~.
+
+  | =overview=       | Top-level headlines only.  |
+  | =content=        | All headlines.             |
+  | =showall=        | No folding on any entry.   |
+  | =showeverything= | Show even drawer contents. |
+
+  #+vindex: org-startup-indented
+  Dynamic virtual indentation is controlled by the variable
+  ~org-startup-indented~[fn:150].
+
+  | =indent=   | Start with Org Indent mode turned on.  |
+  | =noindent= | Start with Org Indent mode turned off. |
+
+  #+vindex: org-startup-numerated
+  Dynamic virtual numeration of headlines is controlled by the variable
+  ~org-startup-numerated~.
+
+  | =num=   | Start with Org num mode turned on.  |
+  | =nonum= | Start with Org num mode turned off. |
+
+  #+vindex: org-startup-align-all-tables
+  Aligns tables consistently upon visiting a file.  The
+  corresponding variable is ~org-startup-align-all-tables~ with
+  ~nil~ as default value.
+
+  | =align=   | Align all tables.               |
+  | =noalign= | Do not align tables on startup. |
+
+  #+vindex: org-startup-shrink-all-tables
+  Shrink table columns with a width cookie.  The corresponding
+  variable is ~org-startup-shrink-all-tables~ with ~nil~ as
+  default value.
+
+  #+vindex: org-startup-with-inline-images
+  When visiting a file, inline images can be automatically
+  displayed.  The corresponding variable is
+  ~org-startup-with-inline-images~, with a default value ~nil~ to
+  avoid delays when visiting a file.
+
+  | =inlineimages=   | Show inline images.                   |
+  | =noinlineimages= | Do not show inline images on startup. |
+
+  #+vindex: org-log-done
+  #+vindex: org-log-note-clock-out
+  #+vindex: org-log-repeat
+  Logging the closing and reopening of TODO items and clock
+  intervals can be configured using these options (see variables
+  ~org-log-done~, ~org-log-note-clock-out~, and ~org-log-repeat~).
+
+  | =logdone=            | Record a timestamp when an item is marked as done. |
+  | =lognotedone=        | Record timestamp and a note when DONE.             |
+  | =nologdone=          | Do not record when items are marked as done.       |
+  | =logrepeat=          | Record a time when reinstating a repeating item.   |
+  | =lognoterepeat=      | Record a note when reinstating a repeating item.   |
+  | =nologrepeat=        | Do not record when reinstating repeating item.     |
+  | =lognoteclock-out=   | Record a note when clocking out.                   |
+  | =nolognoteclock-out= | Do not record a note when clocking out.            |
+  | =logreschedule=      | Record a timestamp when scheduling time changes.   |
+  | =lognotereschedule=  | Record a note when scheduling time changes.        |
+  | =nologreschedule=    | Do not record when a scheduling date changes.      |
+  | =logredeadline=      | Record a timestamp when deadline changes.          |
+  | =lognoteredeadline=  | Record a note when deadline changes.               |
+  | =nologredeadline=    | Do not record when a deadline date changes.        |
+  | =logrefile=          | Record a timestamp when refiling.                  |
+  | =lognoterefile=      | Record a note when refiling.                       |
+  | =nologrefile=        | Do not record when refiling.                       |
+
+  #+vindex: org-hide-leading-stars
+  #+vindex: org-odd-levels-only
+  Here are the options for hiding leading stars in outline
+  headings, and for indenting outlines.  The corresponding
+  variables are ~org-hide-leading-stars~ and
+  ~org-odd-levels-only~, both with a default setting ~nil~
+  (meaning =showstars= and =oddeven=).
+
+  | =hidestars= | Make all but one of the stars starting a headline invisible. 
|
+  | =showstars= | Show all stars starting a headline.                          
|
+  | =indent=    | Virtual indentation according to outline level.              
|
+  | =noindent=  | No virtual indentation according to outline level.           
|
+  | =odd=       | Allow only odd outline levels (1, 3, ...).                   
|
+  | =oddeven=   | Allow all outline levels.                                    
|
+
+  #+vindex: org-put-time-stamp-overlays
+  #+vindex: org-time-stamp-overlay-formats
+  To turn on custom format overlays over timestamps (variables
+  ~org-put-time-stamp-overlays~ and
+  ~org-time-stamp-overlay-formats~), use:
+
+  | =customtime= | Overlay custom time format. |
+
+  #+vindex: constants-unit-system
+  The following options influence the table spreadsheet (variable
+  ~constants-unit-system~).
+
+  | =constcgs= | =constants.el= should use the c-g-s unit system. |
+  | =constSI=  | =constants.el= should use the SI unit system.    |
+
+  #+vindex: org-footnote-define-inline
+  #+vindex: org-footnote-auto-label
+  #+vindex: org-footnote-auto-adjust
+  To influence footnote settings, use the following keywords.  The
+  corresponding variables are ~org-footnote-define-inline~,
+  ~org-footnote-auto-label~, and ~org-footnote-auto-adjust~.
+
+  | =fninline=   | Define footnotes inline.                               |
+  | =fnnoinline= | Define footnotes in separate section.                  |
+  | =fnlocal=    | Define footnotes near first reference, but not inline. |
+  | =fnprompt=   | Prompt for footnote labels.                            |
+  | =fnauto=     | Create =[fn:1]=-like labels automatically (default).   |
+  | =fnconfirm=  | Offer automatic label for editing or confirmation.     |
+  | =fnadjust=   | Automatically renumber and sort footnotes.             |
+  | =nofnadjust= | Do not renumber and sort automatically.                |
+
+  #+vindex: org-hide-block-startup
+  To hide blocks on startup, use these keywords.  The
+  corresponding variable is ~org-hide-block-startup~.
+
+  | =hideblocks=   | Hide all begin/end blocks on startup. |
+  | =nohideblocks= | Do not hide blocks on startup.        |
+
+  #+vindex: org-pretty-entities
+  The display of entities as UTF-8 characters is governed by the
+  variable ~org-pretty-entities~ and the keywords
+
+  | =entitiespretty= | Show entities as UTF-8 characters where possible. |
+  | =entitiesplain=  | Leave entities plain.                             |
+
+- =#+TAGS: TAG1(c1) TAG2(c2)= ::
+
+  #+cindex: @samp{TAGS}, keyword
+  #+vindex: org-tag-alist
+  These lines (several such lines are allowed) specify the valid tags
+  in this file, and (potentially) the corresponding /fast tag
+  selection/ keys.  The corresponding variable is ~org-tag-alist~.
+
+- =#+TODO:=, =#+SEQ_TODO:=, =#+TYP_TODO:= ::
+
+  #+cindex: @samp{SEQ_TODO}, keyword
+  #+cindex: @samp{TODO}, keyword
+  #+cindex: @samp{TYP_TODO}, keyword
+  #+vindex: org-todo-keywords
+  These lines set the TODO keywords and their interpretation in the
+  current file.  The corresponding variable is ~org-todo-keywords~.
+
+** Org Syntax
+:PROPERTIES:
+:DESCRIPTION: Formal description of Org's syntax.
+:END:
+
+A reference document providing a formal description of Org's syntax is
+available as [[https://orgmode.org/worg/dev/org-syntax.html][a draft on 
Worg]], written and maintained by Nicolas
+Goaziou.  It defines Org's core internal concepts such as "headlines",
+"sections", "affiliated keywords", "(greater) elements" and "objects".
+Each part of an Org document belongs to one of the previous
+categories.
+
+To explore the abstract structure of an Org buffer, run this in
+a buffer:
+
+: M-: (org-element-parse-buffer) <RET>
+
+#+texinfo: @noindent
+It outputs a list containing the buffer's content represented as an
+abstract structure.  The export engine relies on the information
+stored in this list.  Most interactive commands---e.g., for structure
+editing---also rely on the syntactic meaning of the surrounding
+context.
+
+#+cindex: syntax checker
+#+cindex: linter
+#+findex: org-lint
+You can probe the syntax of your documents with the command
+
+: M-x org-lint <RET>
+
+#+texinfo: @noindent
+It runs a number of checks to find common mistakes.  It then displays
+their location in a dedicated buffer, along with a description and
+a "trust level", since false-positive are possible.  From there, you
+can operate on the reports with the following keys:
+
+#+attr_texinfo: :columns 0.22 0.78
+| {{{kbd(C-j)}}}, {{{kbd(TAB)}}} | Display the offending line                  
|
+| {{{kbd(RET)}}}                 | Move point to the offending line            
|
+| {{{kbd(g)}}}                   | Check the document again                    
|
+| {{{kbd(h)}}}                   | Hide all reports from the same checker      
|
+| {{{kbd(i)}}}                   | Also remove them from all subsequent checks 
|
+| {{{kbd(S)}}}                   | Sort reports by the column at point         
|
+
+** Context Dependent Documentation
+:PROPERTIES:
+:DESCRIPTION: Read documentation about current syntax.
+:ALT_TITLE: Documentation Access
+:END:
+#+cindex: documentation
+#+cindex: Info
+
+#+findex: org-info-find-node
+#+kindex: C-c C-x I
+{{{kbd(C-c C-x I)}}} in an Org file tries to open a suitable section
+of the Org manual depending on the syntax at point.  For example,
+using it on a headline displays "Document Structure" section.
+
+{{{kbd(q)}}} closes the Info window.
+
+** Escape Character
+:PROPERTIES:
+:DESCRIPTION: Prevent Org from interpreting your writing.
+:END:
+
+#+cindex: escape character
+#+cindex: zero width space
+You may sometimes want to write text that looks like Org syntax, but
+should really read as plain text.  Org may use a specific escape
+character in some situations, i.e., a backslash in macros (see [[*Macro
+Replacement]]) and links (see [[*Link Format]]), or a comma in source and
+example blocks (see [[*Literal Examples]]).  In the general case, however,
+we suggest to use the zero width space.  You can insert one with any
+of the following:
+
+: C-x 8 <RET> zero width space <RET>
+: C-x 8 <RET> 200B <RET>
+
+For example, in order to write =[[1,2]]= as-is in your document, you
+may write instead
+
+: [X[1,2]]
+
+where =X= denotes the zero width space character.
+
+** Code Evaluation and Security Issues
+:PROPERTIES:
+:DESCRIPTION: Org files evaluate in-line code.
+:ALT_TITLE: Code Evaluation Security
+:END:
+
+Unlike plain text, running code comes with risk.  Each source code
+block, in terms of risk, is equivalent to an executable file.  Org
+therefore puts a few confirmation prompts by default.  This is to
+alert the casual user from accidentally running untrusted code.
+
+For users who do not run code blocks or write code regularly, Org's
+default settings should suffice.  However, some users may want to
+tweak the prompts for fewer interruptions.  To weigh the risks of
+automatic execution of code blocks, here are some details about code
+evaluation.
+
+Org evaluates code in the following circumstances:
+
+- /Source code blocks/ ::
+
+  Org evaluates source code blocks in an Org file during export.  Org
+  also evaluates a source code block with the {{{kbd(C-c C-c)}}} key
+  chord.  Users exporting or running code blocks must load files only
+  from trusted sources.  Be wary of customizing variables that remove
+  or alter default security measures.
+
+  #+attr_texinfo: :options org-confirm-babel-evaluate
+  #+begin_defopt
+  When ~t~, Org prompts the user for confirmation before executing
+  each code block.  When ~nil~, Org executes code blocks without
+  prompting the user for confirmation.  When this option is set to
+  a custom function, Org invokes the function with these two
+  arguments: the source code language and the body of the code block.
+  The custom function must return either a ~t~ or ~nil~, which
+  determines if the user is prompted.  Each source code language can
+  be handled separately through this function argument.
+  #+end_defopt
+
+  For example, here is how to execute ditaa code blocks without
+  prompting:
+
+  #+begin_src emacs-lisp
+  (defun my-org-confirm-babel-evaluate (lang body)
+    (not (string= lang "ditaa")))  ;don't ask for ditaa
+  (setq org-confirm-babel-evaluate #'my-org-confirm-babel-evaluate)
+  #+end_src
+
+- /Following =shell= and =elisp= links/ ::
+
+  Org has two link types that can directly evaluate code (see
+  [[*External Links]]).  Because such code is not visible, these links
+  have a potential risk.  Org therefore prompts the user when it
+  encounters such links.  The customization variables are:
+
+  #+attr_texinfo: :options org-link-shell-confirm-function
+  #+begin_defopt
+  Function that prompts the user before executing a shell link.
+  #+end_defopt
+
+  #+attr_texinfo: :options org-link-elisp-confirm-function
+  #+begin_defopt
+  Function that prompts the user before executing an Emacs Lisp link.
+  #+end_defopt
+
+- /Formulas in tables/ ::
+
+  Formulas in tables (see [[*The Spreadsheet]]) are code that is evaluated
+  either by the Calc interpreter, or by the Emacs Lisp interpreter.
+
+** Interaction with Other Packages
+:PROPERTIES:
+:DESCRIPTION: With other Emacs packages.
+:ALT_TITLE: Interaction
+:END:
+#+cindex: packages, interaction with other
+
+Org's compatibility and the level of interaction with other Emacs
+packages are documented here.
+
+*** Packages that Org cooperates with
+:PROPERTIES:
+:DESCRIPTION: Packages Org cooperates with.
+:ALT_TITLE: Cooperation
+:END:
+
+- =calc.el= by Dave Gillespie ::
+  #+cindex: @file{calc.el}
+
+  Org uses the Calc package for implementing spreadsheet functionality
+  in its tables (see [[*The Spreadsheet]]).  Org also uses Calc for
+  embedded calculations.  See [[info:calc::Embedded Mode][GNU Emacs Calc 
Manual]].
+
+- =constants.el= by Carsten Dominik ::
+  #+cindex: @file{constants.el}
+  #+vindex: org-table-formula-constants
+
+  Org can use names for constants in formulas in tables.  Org can also
+  use calculation suffixes for units, such as =M= for =Mega=.  For
+  a standard collection of such constants, install the =constants=
+  package.  Install version 2.0 of this package, available at
+  [[http://www.astro.uva.nl/~dominik/Tools]].  Org checks if the function
+  ~constants-get~ has been autoloaded.  Installation instructions are
+  in the file =constants.el=.
+
+- =cdlatex.el= by Carsten Dominik ::
+  #+cindex: @file{cdlatex.el}
+
+  Org mode can make use of the CDLaTeX package to efficiently enter
+  LaTeX fragments into Org files.  See [[*Using CDLaTeX to enter math]].
+
+- =imenu.el= by Ake Stenhoff and Lars Lindberg ::
+  #+cindex: @file{imenu.el}
+
+  Imenu creates dynamic menus based on an index of items in a file.
+  Org mode supports Imenu menus.  Enable it with a mode hook as
+  follows:
+
+  #+begin_src emacs-lisp
+  (add-hook 'org-mode-hook
+            (lambda () (imenu-add-to-menubar "Imenu")))
+  #+end_src
+
+  #+vindex: org-imenu-depth
+  By default the index is two levels deep---you can modify the
+  depth using the option ~org-imenu-depth~.
+
+- =speedbar.el= by Eric\nbsp{}M.\nbsp{}Ludlam ::
+  #+cindex: @file{speedbar.el}
+
+  Speedbar package creates a special Emacs frame for displaying files
+  and index items in files.  Org mode supports Speedbar; users can
+  drill into Org files directly from the Speedbar.  The {{{kbd(<)}}}
+  in the Speedbar frame tweaks the agenda commands to that file or to
+  a subtree.
+
+- =table.el= by Takaaki Ota ::
+  #+cindex: table editor, @file{table.el}
+  #+cindex: @file{table.el}
+
+  Complex ASCII tables with automatic line wrapping, column- and
+  row-spanning, and alignment can be created using the Emacs table
+  package by Takaaki Ota.  Org mode recognizes such tables and exports
+  them properly.  {{{kbd(C-c ')}}} to edit these tables in a special
+  buffer, much like Org's code blocks.  Because of interference with
+  other Org mode functionality, Takaaki Ota tables cannot be edited
+  directly in the Org buffer.
+
+  - {{{kbd(C-c ')}}} (~org-edit-special~) ::
+
+    #+kindex: C-c '
+    #+findex: org-edit-special
+    Edit a =table.el= table.  Works when point is in a =table.el=
+    table.
+
+  - {{{kbd(C-c ~​)}}} (~org-table-create-with-table.el~) ::
+
+    #+kindex: C-c ~
+    #+findex: org-table-create-with-table.el
+    Insert a =table.el= table.  If there is already a table at point,
+    this command converts it between the =table.el= format and the Org
+    mode format.  See the documentation string of the command
+    ~org-convert-table~ for the restrictions under which this is
+    possible.
+
+*** Packages that conflict with Org mode
+:PROPERTIES:
+:DESCRIPTION: Packages that lead to conflicts.
+:ALT_TITLE: Conflicts
+:END:
+
+#+cindex: shift-selection
+#+vindex: org-support-shift-select
+In Emacs, shift-selection combines motions of point with shift key to
+enlarge regions.  Emacs sets this mode by default.  This conflicts
+with Org's use of {{{kbd(S-<cursor>)}}} commands to change timestamps,
+TODO keywords, priorities, and item bullet types, etc.  Since
+{{{kbd(S-<cursor>)}}} commands outside of specific contexts do not do
+anything, Org offers the variable ~org-support-shift-select~ for
+customization.  Org mode accommodates shift selection by (i) making it
+available outside of the special contexts where special commands
+apply, and (ii) extending an existing active region even if point
+moves across a special context.
+
+- =cua.el= by Kim\nbsp{}F.\nbsp{}Storm ::
+
+  #+cindex: @file{cua.el}
+  #+vindex: org-replace-disputed-keys
+  Org key bindings conflict with {{{kbd(S-<cursor>)}}} keys used by
+  CUA mode.  For Org to relinquish these bindings to CUA mode,
+  configure the variable ~org-replace-disputed-keys~.  When set, Org
+  moves the following key bindings in Org files, and in the agenda
+  buffer---but not during date selection.
+
+  #+attr_texinfo: :columns 0.4 0.4
+  | {{{kbd(S-UP)}}}      \rArr{}  {{{kbd(M-p)}}}   | {{{kbd(S-DOWN)}}}     
\rArr{}  {{{kbd(M-n)}}}   |
+  | {{{kbd(S-LEFT)}}}    \rArr{}  {{{kbd(M--)}}}   | {{{kbd(S-RIGHT)}}}    
\rArr{}  {{{kbd(M-+)}}}   |
+  | {{{kbd(C-S-LEFT)}}}  \rArr{}  {{{kbd(M-S--)}}} | {{{kbd(C-S-RIGHT)}}}  
\rArr{}  {{{kbd(M-S-+)}}} |
+
+  #+vindex: org-disputed-keys
+  Yes, these are unfortunately more difficult to remember.  If you
+  want to have other replacement keys, look at the variable
+  ~org-disputed-keys~.
+
+- =ecomplete.el= by Lars Magne Ingebrigtsen ::
+
+  #+cindex: @file{ecomplete.el}
+  Ecomplete provides "electric" address completion in address header
+  lines in message buffers.  Sadly Orgtbl mode cuts Ecomplete's power
+  supply: no completion happens when Orgtbl mode is enabled in message
+  buffers while entering text in address header lines.  If one wants
+  to use ecomplete one should /not/ follow the advice to automagically
+  turn on Orgtbl mode in message buffers (see [[*The Orgtbl Minor Mode]]),
+  but instead---after filling in the message headers---turn on Orgtbl
+  mode manually when needed in the messages body.
+
+- =filladapt.el= by Kyle Jones ::
+
+  #+cindex: @file{filladapt.el}
+  Org mode tries to do the right thing when filling paragraphs, list
+  items and other elements.  Many users reported problems using both
+  =filladapt.el= and Org mode, so a safe thing to do is to disable
+  filladapt like this:
+
+  #+begin_src emacs-lisp
+  (add-hook 'org-mode-hook 'turn-off-filladapt-mode)
+  #+end_src
+
+- =viper.el= by Michael Kifer ::
+  #+cindex: @file{viper.el}
+  #+kindex: C-c /
+
+  Viper uses {{{kbd(C-c /)}}} and therefore makes this key not access
+  the corresponding Org mode command ~org-sparse-tree~.  You need to
+  find another key for this command, or override the key in
+  ~viper-vi-global-user-map~ with
+
+  #+begin_src emacs-lisp
+  (define-key viper-vi-global-user-map "C-c /" 'org-sparse-tree)
+  #+end_src
+
+- =windmove.el= by Hovav Shacham ::
+  #+cindex: @file{windmove.el}
+
+  This package also uses the {{{kbd(S-<cursor>)}}} keys, so everything
+  written in the paragraph above about CUA mode also applies here.  If
+  you want to make the windmove function active in locations where Org
+  mode does not have special functionality on {{{kbd(S-<cursor>)}}},
+  add this to your configuration:
+
+  #+begin_src emacs-lisp
+  ;; Make windmove work in Org mode:
+  (add-hook 'org-shiftup-final-hook 'windmove-up)
+  (add-hook 'org-shiftleft-final-hook 'windmove-left)
+  (add-hook 'org-shiftdown-final-hook 'windmove-down)
+  (add-hook 'org-shiftright-final-hook 'windmove-right)
+  #+end_src
+
+- =yasnippet.el= ::
+
+  #+cindex: @file{yasnippet.el}
+  The way Org mode binds the {{{kbd(TAB)}}} key (binding to ~[tab]~
+  instead of ~"\t"~) overrules YASnippet's access to this key.  The
+  following code fixed this problem:
+
+  #+begin_src emacs-lisp
+  (add-hook 'org-mode-hook
+            (lambda ()
+              (setq-local yas/trigger-key [tab])
+              (define-key yas/keymap [tab] 'yas/next-field-or-maybe-expand)))
+  #+end_src
+
+  The latest version of YASnippet does not play well with Org mode.
+  If the above code does not fix the conflict, start by defining
+  the following function:
+
+  #+begin_src emacs-lisp
+  (defun yas/org-very-safe-expand ()
+    (let ((yas/fallback-behavior 'return-nil)) (yas/expand)))
+  #+end_src
+
+  Then, tell Org mode to use that function:
+
+  #+begin_src emacs-lisp
+  (add-hook 'org-mode-hook
+            (lambda ()
+              (make-variable-buffer-local 'yas/trigger-key)
+              (setq yas/trigger-key [tab])
+              (add-to-list 'org-tab-first-hook 'yas/org-very-safe-expand)
+              (define-key yas/keymap [tab] 'yas/next-field)))
+  #+end_src
+** Using Org on a TTY
+:PROPERTIES:
+:DESCRIPTION: Using Org on a tty.
+:ALT_TITLE: TTY Keys
+:END:
+#+cindex: tty key bindings
+
+Org provides alternative key bindings for TTY and modern mobile
+devices that cannot perform movement commands on point and key
+bindings with modifier keys.  Some of these workarounds may be more
+cumbersome than necessary.  Users should look into customizing these
+further based on their usage needs.  For example, the normal
+{{{kbd(S-<cursor>)}}} for editing timestamp might be better with
+{{{kbd(C-c .)}}} chord.
+
+#+attr_texinfo: :columns 0.2 0.28 0.15 0.21
+| Default              | Alternative 1            | Speed key    | Alternative 
2        |
+|----------------------+--------------------------+--------------+----------------------|
+| {{{kbd(S-TAB)}}}     | {{{kbd(C-u TAB)}}}       | {{{kbd(C)}}} |             
         |
+| {{{kbd(M-LEFT)}}}    | {{{kbd(C-c C-x l)}}}     | {{{kbd(l)}}} | {{{kbd(Esc 
LEFT)}}}  |
+| {{{kbd(M-S-LEFT)}}}  | {{{kbd(C-c C-x L)}}}     | {{{kbd(L)}}} |             
         |
+| {{{kbd(M-RIGHT)}}}   | {{{kbd(C-c C-x r)}}}     | {{{kbd(r)}}} | {{{kbd(Esc 
RIGHT)}}} |
+| {{{kbd(M-S-RIGHT)}}} | {{{kbd(C-c C-x R)}}}     | {{{kbd(R)}}} |             
         |
+| {{{kbd(M-UP)}}}      | {{{kbd(C-c C-x u)}}}     |              | {{{kbd(Esc 
UP)}}}    |
+| {{{kbd(M-S-UP)}}}    | {{{kbd(C-c C-x U)}}}     | {{{kbd(U)}}} |             
         |
+| {{{kbd(M-DOWN)}}}    | {{{kbd(C-c C-x d)}}}     |              | {{{kbd(Esc 
DOWN)}}}  |
+| {{{kbd(M-S-DOWN)}}}  | {{{kbd(C-c C-x D)}}}     | {{{kbd(D)}}} |             
         |
+| {{{kbd(S-RET)}}}     | {{{kbd(C-c C-x c)}}}     |              |             
         |
+| {{{kbd(M-RET)}}}     | {{{kbd(C-c C-x m)}}}     |              | {{{kbd(Esc 
RET)}}}   |
+| {{{kbd(M-S-RET)}}}   | {{{kbd(C-c C-x M)}}}     |              |             
         |
+| {{{kbd(S-LEFT)}}}    | {{{kbd(C-c LEFT)}}}      |              |             
         |
+| {{{kbd(S-RIGHT)}}}   | {{{kbd(C-c RIGHT)}}}     |              |             
         |
+| {{{kbd(S-UP)}}}      | {{{kbd(C-c UP)}}}        |              |             
         |
+| {{{kbd(S-DOWN)}}}    | {{{kbd(C-c DOWN)}}}      |              |             
         |
+| {{{kbd(C-S-LEFT)}}}  | {{{kbd(C-c C-x LEFT)}}}  |              |             
         |
+| {{{kbd(C-S-RIGHT)}}} | {{{kbd(C-c C-x RIGHT)}}} |              |             
         |
+
+** Protocols for External Access
+:PROPERTIES:
+:DESCRIPTION: External access to Emacs and Org.
+:ALT_TITLE: Protocols
+:END:
+#+cindex: protocols, for external access
+
+Org protocol is a tool to trigger custom actions in Emacs from
+external applications.  Any application that supports calling external
+programs with an URL as argument may be used with this functionality.
+For example, you can configure bookmarks in your web browser to send a
+link to the current page to Org and create a note from it using
+capture (see [[*Capture]]).  You can also create a bookmark that tells
+Emacs to open the local source file of a remote website you are
+browsing.
+
+#+cindex: Org protocol, set-up
+#+cindex: Installing Org protocol
+In order to use Org protocol from an application, you need to register
+=org-protocol://= as a valid scheme-handler.  External calls are
+passed to Emacs through the =emacsclient= command, so you also need to
+ensure an Emacs server is running.  More precisely, when the
+application calls
+
+: emacsclient org-protocol://PROTOCOL?key1=val1&key2=val2
+
+#+texinfo: @noindent
+Emacs calls the handler associated to {{{var(PROTOCOL)}}} with
+argument =(:key1 val1 :key2 val2)=.
+
+#+cindex: protocol, new protocol
+#+cindex: defining new protocols
+Org protocol comes with three predefined protocols, detailed in the
+following sections.  Configure ~org-protocol-protocol-alist~ to define
+your own.
+
+*** The ~store-link~ protocol
+:PROPERTIES:
+:DESCRIPTION: Store a link, push URL to kill-ring.
+:END:
+#+cindex: store-link protocol
+#+cindex: protocol, store-link
+
+Using the ~store-link~ handler, you can copy links, to that they can
+be inserted using {{{kbd(M-x org-insert-link)}}} or yanking.  More
+precisely, the command
+
+: emacsclient org-protocol://store-link?url=URL&title=TITLE
+
+#+texinfo: @noindent
+stores the following link:
+
+: [[URL][TITLE]]
+
+In addition, {{{var(URL)}}} is pushed on the kill-ring for yanking.
+You need to encode {{{var(URL)}}} and {{{var(TITLE)}}} if they contain
+slashes, and probably quote those for the shell.
+
+To use this feature from a browser, add a bookmark with an arbitrary
+name, e.g., =Org: store-link= and enter this as /Location/:
+
+#+begin_example
+javascript:location.href='org-protocol://store-link?url='+
+      encodeURIComponent(location.href);
+#+end_example
+
+*** The ~capture~ protocol
+:PROPERTIES:
+:DESCRIPTION: Fill a buffer with external information.
+:END:
+#+cindex: capture protocol
+#+cindex: protocol, capture
+
+Activating the "capture" handler pops up a =Capture= buffer in Emacs,
+using acapture template.
+
+: emacsclient org-protocol://capture?template=X?url=URL?title=TITLE?body=BODY
+
+To use this feature, add a bookmark with an arbitrary name, e.g.,
+=Org: capture=, and enter this as =Location=:
+
+#+begin_example
+javascript:location.href='org-protocol://capture?template=x'+
+      '&url='+encodeURIComponent(window.location.href)+
+      '&title='+encodeURIComponent(document.title)+
+      '&body='+encodeURIComponent(window.getSelection());
+#+end_example
+
+#+vindex: org-protocol-default-template-key
+The capture template to be used can be specified in the bookmark (like
+=X= above).  If unspecified, the template key is set in the variable
+~org-protocol-default-template-key~.  The following template
+placeholders are available:
+
+#+begin_example
+%:link          The URL
+%:description   The webpage title
+%:annotation    Equivalent to [[%:link][%:description]]
+%i              The selected text
+#+end_example
+
+*** The ~open-source~ protocol
+:PROPERTIES:
+:DESCRIPTION: Edit published contents.
+:END:
+#+cindex: open-source protocol
+#+cindex: protocol, open-source
+
+The ~open-source~ handler is designed to help with editing local
+sources when reading a document.  To that effect, you can use
+a bookmark with the following location:
+
+#+begin_example
+javascript:location.href='org-protocol://open-source?&url='+
+      encodeURIComponent(location.href)
+#+end_example
+
+#+vindex: org-protocol-project-alist
+The variable ~org-protocol-project-alist~ maps URLs to local file
+names, by stripping URL parameters from the end and replacing the
+~:base-url~ with ~:working-directory~ and ~:online-suffix~ with
+~:working-suffix~.  For example, assuming you own a local copy of
+=https://orgmode.org/worg/= contents at =/home/user/worg=, you can set
+~org-protocol-project-alist~ to the following
+
+#+begin_src emacs-lisp
+(setq org-protocol-project-alist
+      '(("Worg"
+         :base-url "https://orgmode.org/worg/";
+         :working-directory "/home/user/worg/"
+         :online-suffix ".html"
+         :working-suffix ".org")))
+#+end_src
+
+#+texinfo: @noindent
+If you are now browsing
+=https://orgmode.org/worg/org-contrib/org-protocol.html= and find
+a typo or have an idea about how to enhance the documentation, simply
+click the bookmark and start editing.
+
+#+cindex: rewritten URL in open-source protocol
+#+cindex: protocol, open-source rewritten URL
+However, such mapping may not always yield the desired results.
+Suppose you maintain an online store located at =http://example.com/=.
+The local sources reside in =/home/user/example/=.  It is common
+practice to serve all products in such a store through one file and
+rewrite URLs that do not match an existing file on the server.  That
+way, a request to =http://example.com/print/posters.html= might be
+rewritten on the server to something like
+=http://example.com/shop/products.php/posters.html.php=.  The
+~open-source~ handler probably cannot find a file named
+=/home/user/example/print/posters.html.php= and fails.
+
+Such an entry in ~org-protocol-project-alist~ may hold an additional
+property ~:rewrites~.  This property is a list of cons cells, each of
+which maps a regular expression to a path relative to the
+~:working-directory~.
+
+Now map the URL to the path =/home/user/example/products.php= by
+adding ~:rewrites~ rules like this:
+
+#+begin_src emacs-lisp
+(setq org-protocol-project-alist
+      '(("example.com"
+         :base-url "http://example.com/";
+         :working-directory "/home/user/example/"
+         :online-suffix ".php"
+         :working-suffix ".php"
+         :rewrites (("example.com/print/" . "products.php")
+                    ("example.com/$" . "index.php")))))
+#+end_src
+
+#+texinfo: @noindent
+Since =example.com/$= is used as a regular expression, it maps
+=http://example.com/=, =https://example.com=,
+=http://www.example.com/= and similar to
+=/home/user/example/index.php=.
+
+The ~:rewrites~ rules are searched as a last resort if and only if no
+existing file name is matched.
+
+#+cindex: protocol, open-source, set-up mapping
+#+cindex: mappings in open-source protocol
+#+findex: org-protocol-create
+#+findex: org-protocol-create-for-org
+Two functions can help you filling ~org-protocol-project-alist~ with
+valid contents: ~org-protocol-create~ and
+~org-protocol-create-for-org~.  The latter is of use if you're editing
+an Org file that is part of a publishing project.
+** Org Crypt
+:PROPERTIES:
+:DESCRIPTION: Encrypting Org files.
+:END:
+
+Org Crypt encrypts the text of an entry, but not the headline, or
+properties.  Behind the scene, it uses the Emacs EasyPG library to
+encrypt and decrypt files.
+
+#+vindex: org-crypt-tag-matcher
+Any text below a headline that has a =crypt= tag is automatically
+encrypted when the file is saved.  To use a different tag, customize
+the ~org-crypt-tag-matcher~ setting.
+
+Here is a suggestion for Org Crypt settings in Emacs init file:
+
+#+begin_src emacs-lisp
+(require 'org-crypt)
+(org-crypt-use-before-save-magic)
+(setq org-tags-exclude-from-inheritance '("crypt"))
+
+(setq org-crypt-key nil)
+;; GPG key to use for encryption
+;; Either the Key ID or set to nil to use symmetric encryption.
+
+(setq auto-save-default nil)
+;; Auto-saving does not cooperate with org-crypt.el: so you need to
+;; turn it off if you plan to use org-crypt.el quite often.  Otherwise,
+;; you'll get an (annoying) message each time you start Org.
+
+;; To turn it off only locally, you can insert this:
+;;
+;; # -*- buffer-auto-save-file-name: nil; -*-
+#+end_src
+
+It's possible to use different keys for different headings by
+specifying the respective key as property =CRYPTKEY=, e.g.:
+
+#+begin_example
+,* Totally secret :crypt:
+  :PROPERTIES:
+  :CRYPTKEY: 0x0123456789012345678901234567890123456789
+  :END:
+#+end_example
+
+Excluding the =crypt= tag from inheritance prevents already encrypted
+text from being encrypted again.
+
+** Org Mobile
+:PROPERTIES:
+:DESCRIPTION: Viewing and capture on a mobile device.
+:END:
+#+cindex: smartphone
+
+Org Mobile is a protocol for synchronizing Org files between Emacs and
+other applications, e.g., on mobile devices.  It enables offline-views
+and capture support for an Org mode system that is rooted on a "real"
+computer.  The external application can also record changes to
+existing entries.
+
+This appendix describes Org's support for agenda view formats
+compatible with Org Mobile.  It also describes synchronizing changes,
+such as to notes, between the mobile application and the computer.
+
+To change tags and TODO states in the mobile application, first
+customize the variables ~org-todo-keywords~, ~org-tag-alist~ and
+~org-tag-persistent-alist~.  These should cover all the important tags
+and TODO keywords, even if Org files use only some of them.  Though
+the mobile application is expected to support in-buffer settings, it
+is required to understand TODO states /sets/ (see [[*Setting up keywords
+for individual files]]) and /mutually exclusive/ tags (see [[*Setting
+Tags]]) only for those set in these variables.
+
+*** Setting up the staging area
+:PROPERTIES:
+:DESCRIPTION: For the mobile device.
+:END:
+
+#+vindex: org-mobile-directory
+The mobile application needs access to a file directory on
+a server[fn:151] to interact with Emacs.  Pass its location through
+the ~org-mobile-directory~ variable.  If you can mount that directory
+locally just set the variable to point to that directory:
+
+#+begin_src emacs-lisp
+(setq org-mobile-directory "~/orgmobile/")
+#+end_src
+
+Alternatively, by using TRAMP (see [[info:tramp][TRAMP User Manual]]),
+~org-mobile-directory~ may point to a remote directory accessible
+through, for example, SSH, SCP, or DAVS:
+
+#+begin_src emacs-lisp
+(setq org-mobile-directory "/davs:user@remote.host:/org/webdav/")
+#+end_src
+
+#+vindex: org-mobile-encryption
+With a public server, consider encrypting the files.  Org also
+requires OpenSSL installed on the local computer.  To turn on
+encryption, set the same password in the mobile application and in
+Emacs.  Set the password in the variable
+~org-mobile-use-encryption~[fn:152].  Note that even after the mobile
+application encrypts the file contents, the file name remains visible
+on the file systems of the local computer, the server, and the mobile
+device.
+
+*** Pushing to the mobile application
+:PROPERTIES:
+:DESCRIPTION: Uploading Org files and agendas.
+:END:
+
+#+findex: org-mobile-push
+#+vindex: org-mobile-files
+The command ~org-mobile-push~ copies files listed in
+~org-mobile-files~ into the staging area.  Files include agenda files
+(as listed in ~org-agenda-files~).  Customize ~org-mobile-files~ to
+add other files.  File names are staged with paths relative to
+~org-directory~, so all files should be inside this directory[fn:153].
+
+Push creates a special Org file =agendas.org= with custom agenda views
+defined by the user[fn:154].
+
+Finally, Org writes the file =index.org=, containing links to other
+files.  The mobile application reads this file first from the server
+to determine what other files to download for agendas.  For faster
+downloads, it is expected to only read files whose checksums[fn:155]
+have changed.
+
+*** Pulling from the mobile application
+:PROPERTIES:
+:DESCRIPTION: Integrating captured and flagged items.
+:END:
+
+#+findex: org-mobile-pull
+The command ~org-mobile-pull~ synchronizes changes with the server.
+More specifically, it first pulls the Org files for viewing.  It then
+appends captured entries and pointers to flagged or changed entries to
+the file =mobileorg.org= on the server.  Org ultimately integrates its
+data in an inbox file format, through the following steps:
+
+1.
+   #+vindex: org-mobile-inbox-for-pull
+   Org moves all entries found in =mobileorg.org=[fn:156] and appends
+   them to the file pointed to by the variable
+   ~org-mobile-inbox-for-pull~.  It should reside neither in the
+   staging area nor on the server.  Each captured entry and each
+   editing event is a top-level entry in the inbox file.
+
+2.
+   #+cindex: @samp{FLAGGED}, tag
+   After moving the entries, Org processes changes to the shared
+   files.  Some of them are applied directly and without user
+   interaction.  Examples include changes to tags, TODO state,
+   headline and body text.  Entries requiring further action are
+   tagged as =FLAGGED=.  Org marks entries with problems with an error
+   message in the inbox.  They have to be resolved manually.
+
+3. Org generates an agenda view for flagged entries for user
+   intervention to clean up.  For notes stored in flagged entries, Org
+   displays them in the echo area when point is on the corresponding
+   agenda item.
+
+   - {{{kbd(?)}}} ::
+
+     Pressing {{{kbd(?)}}} displays the entire flagged note in another
+     window.  Org also pushes it to the kill ring.  To store flagged
+     note as a normal note, use {{{kbd(? z C-y C-c C-c)}}}.  Pressing
+     {{{kbd(?)}}} twice does these things: first it removes the
+     =FLAGGED= tag; second, it removes the flagged note from the
+     property drawer; third, it signals that manual editing of the
+     flagged entry is now finished.
+
+#+kindex: ? @r{(Agenda dispatcher)}
+From the agenda dispatcher, {{{kbd(?)}}} returns to the view to finish
+processing flagged entries.  Note that these entries may not be the
+most recent since the mobile application searches files that were last
+pulled.  To get an updated agenda view with changes since the last
+pull, pull again.
+
+* Hacking
+:PROPERTIES:
+:DESCRIPTION: How to hack your way around.
+:APPENDIX: t
+:END:
+#+cindex: hacking
+
+This appendix describes some ways a user can extend the functionality
+of Org.
+
+** Hooks
+:PROPERTIES:
+:DESCRIPTION: How to reach into Org's internals.
+:END:
+#+cindex: hooks
+
+Org has a large number of hook variables for adding functionality.
+This appendix illustrates using a few.  A complete list of hooks with
+documentation is maintained by the Worg project at
+https://orgmode.org/worg/doc.html#hooks.
+
+** Add-on Packages
+:PROPERTIES:
+:DESCRIPTION: Available extensions.
+:END:
+#+cindex: add-on packages
+
+Various authors wrote a large number of add-on packages for Org.
+
+These packages are not part of Emacs, but they are distributed as
+contributed packages with the separate release available at
+https://orgmode.org.  See the =contrib/README= file in the source code
+directory for a list of contributed files.  Worg page with more
+information is at: https://orgmode.org/worg/org-contrib/.
+
+** Adding Hyperlink Types
+:PROPERTIES:
+:DESCRIPTION: New custom link types.
+:END:
+#+cindex: hyperlinks, adding new types
+
+Org has many built-in hyperlink types (see [[*Hyperlinks]]), and an
+interface for adding new link types.  The following example shows the
+process of adding Org links to Unix man pages, which look like this
+
+: [[man:printf][The printf manual]]
+
+#+texinfo: @noindent
+The following =ol-man.el= file implements it
+
+#+begin_src emacs-lisp
+;;; ol-man.el - Support for links to man pages in Org mode
+(require 'ol)
+
+(org-link-set-parameters "man"
+                         :follow #'org-man-open
+                         :export #'org-man-export
+                         :store #'org-man-store-link)
+
+(defcustom org-man-command 'man
+  "The Emacs command to be used to display a man page."
+  :group 'org-link
+  :type '(choice (const man) (const woman)))
+
+(defun org-man-open (path _)
+  "Visit the manpage on PATH.
+PATH should be a topic that can be thrown at the man command."
+  (funcall org-man-command path))
+
+(defun org-man-store-link ()
+  "Store a link to a man page."
+  (when (memq major-mode '(Man-mode woman-mode))
+    ;; This is a man page, we do make this link.
+    (let* ((page (org-man-get-page-name))
+           (link (concat "man:" page))
+           (description (format "Man page for %s" page)))
+      (org-link-store-props
+       :type "man"
+       :link link
+       :description description))))
+
+(defun org-man-get-page-name ()
+  "Extract the page name from the buffer name."
+  ;; This works for both `Man-mode' and `woman-mode'.
+  (if (string-match " \\(\\S-+\\)\\*" (buffer-name))
+      (match-string 1 (buffer-name))
+    (error "Cannot create link to this man page")))
+
+(defun org-man-export (link description format _)
+  "Export a man page link from Org files."
+  (let ((path (format "http://man.he.net/?topic=%s&section=all"; link))
+        (desc (or description link)))
+    (pcase format
+      (`html (format "<a target=\"_blank\" href=\"%s\">%s</a>" path desc))
+      (`latex (format "\\href{%s}{%s}" path desc))
+      (`texinfo (format "@uref{%s,%s}" path desc))
+      (`ascii (format "%s (%s)" desc path))
+      (t path))))
+
+(provide ol-man)
+;;; ol-man.el ends here
+#+end_src
+
+#+texinfo: @noindent
+To activate links to man pages in Org, enter this in the Emacs init
+file:
+
+#+begin_src emacs-lisp
+(require 'ol-man)
+#+end_src
+
+#+texinfo: @noindent
+A review of =ol-man.el=:
+
+1. First, =(require 'ol)= ensures that =ol.el= is loaded.
+
+2.
+
+   #+findex: org-link-set-parameters
+   #+vindex: org-link-parameters
+   Then ~org-link-set-parameters~ defines a new link type with =man=
+   prefix and associates functions for following, exporting and
+   storing such links.  See the variable ~org-link-parameters~ for
+   a complete list of possible associations.
+
+3. The rest of the file implements necessary variables and functions.
+
+   For example, ~org-man-store-link~ is responsible for storing a link
+   when ~org-store-link~ (see [[*Handling Links]]) is called from a buffer
+   displaying a man page.  It first checks if the major mode is
+   appropriate.  If check fails, the function returns ~nil~, which
+   means it isn't responsible for creating a link to the current
+   buffer.  Otherwise the function makes a link string by combining
+   the =man:= prefix with the man topic.  It also provides a default
+   description.  The function ~org-insert-link~ can insert it back
+   into an Org buffer later on.
+
+** Adding Export Back-ends
+:PROPERTIES:
+:DESCRIPTION: How to write new export back-ends.
+:END:
+#+cindex: Export, writing back-ends
+
+Org's export engine makes it easy for writing new back-ends.  The
+framework on which the engine was built makes it easy to derive new
+back-ends from existing ones.
+
+#+findex: org-export-define-backend
+#+findex: org-export-define-derived-backend
+The two main entry points to the export engine are:
+~org-export-define-backend~ and ~org-export-define-derived-backend~.
+To grok these functions, see =ox-latex.el= for an example of defining
+a new back-end from scratch, and =ox-beamer.el= for an example of
+deriving from an existing engine.
+
+For creating a new back-end from scratch, first set its name as
+a symbol in an alist consisting of elements and export functions.  To
+make the back-end visible to the export dispatcher, set ~:menu-entry~
+keyword.  For export options specific to this back-end, set the
+~:options-alist~.
+
+For creating a new back-end from an existing one, set
+~:translate-alist~ to an alist of export functions.  This alist
+replaces the parent back-end functions.
+
+For complete documentation, see 
[[https://orgmode.org/worg/dev/org-export-reference.html][the Org Export 
Reference on Worg]].
+
+** Tables in Arbitrary Syntax
+:PROPERTIES:
+:DESCRIPTION: Orgtbl for LaTeX and other programs.
+:END:
+#+cindex: tables, in other modes
+#+cindex: lists, in other modes
+#+cindex: Orgtbl mode
+
+Due to Org's success in handling tables with Orgtbl, a frequently
+requested feature is the use of Org's table functions in other modes,
+e.g., LaTeX.  This would be hard to do in a general way without
+complicated customization nightmares.  Moreover, that would take Org
+away from its simplicity roots that Orgtbl has proven.  There is,
+however, an alternate approach to accomplishing the same.
+
+This approach involves implementing a custom /translate/ function that
+operates on a native Org /source table/ to produce a table in another
+format.  This strategy would keep the excellently working Orgtbl
+simple and isolate complications, if any, confined to the translate
+function.  To add more alien table formats, we just add more translate
+functions.  Also the burden of developing custom translate functions
+for new table formats is in the hands of those who know those formats
+best.
+
+*** Radio tables
+:PROPERTIES:
+:DESCRIPTION: Sending and receiving radio tables.
+:END:
+#+cindex: radio tables
+
+Radio tables are target locations for translated tables that are not near
+their source.  Org finds the target location and inserts the translated
+table.
+
+The key to finding the target location is the magic words =BEGIN/END
+RECEIVE ORGTBL=.  They have to appear as comments in the current mode.
+If the mode is C, then:
+
+#+begin_example
+/* BEGIN RECEIVE ORGTBL table_name */
+/* END RECEIVE ORGTBL table_name */
+#+end_example
+
+At the location of source, Org needs a special line to direct Orgtbl
+to translate and to find the target for inserting the translated
+table.  For example:
+
+#+cindex: @samp{ORGTBL}, keyword
+: #+ORGTBL: SEND table_name translation_function arguments ...
+
+#+texinfo: @noindent
+=table_name= is the table's reference name, which is also used in the
+receiver lines, and the =translation_function= is the Lisp function
+that translates.  This line, in addition, may also contain alternating
+key and value arguments at the end.  The translation function gets
+these values as a property list.  A few standard parameters are
+already recognized and acted upon before the translation function is
+called:
+
+- =:skip N= ::
+
+  Skip the first N lines of the table.  Hlines do count; include them
+  if they are to be skipped.
+
+- =:skipcols (n1 n2 ...)= ::
+
+  List of columns to be skipped.  First Org automatically discards
+  columns with calculation marks and then sends the table to the
+  translator function, which then skips columns as specified in
+  =skipcols=.
+
+To keep the source table intact in the buffer without being disturbed
+when the source file is compiled or otherwise being worked on, use one
+of these strategies:
+
+- Place the table in a block comment.  For example, in C mode you
+  could wrap the table between =/*= and =*/= lines.
+
+- Put the table after an "end" statement.  For example ~\bye~ in TeX
+  and ~\end{document}~ in LaTeX.
+
+- Comment and un-comment each line of the table during edits.  The
+  {{{kbd(M-x orgtbl-toggle-comment)}}} command makes toggling easy.
+
+*** A LaTeX example of radio tables
+:PROPERTIES:
+:DESCRIPTION: Step by step, almost a tutorial.
+:ALT_TITLE: A LaTeX example
+:END:
+#+cindex: @LaTeX{}, and Orgtbl mode
+
+To wrap a source table in LaTeX, use the =comment= environment
+provided by =comment.sty=[fn:157].  To activate it, put
+~\usepackage{comment}~ in the document header.  Orgtbl mode inserts
+a radio table skeleton[fn:158] with the command {{{kbd(M-x
+orgtbl-insert-radio-table)}}}, which prompts for a table name.  For
+example, if =salesfigures= is the name, the template inserts:
+
+#+begin_example
+% BEGIN RECEIVE ORGTBL salesfigures
+% END RECEIVE ORGTBL salesfigures
+\begin{comment}
+,#+ORGTBL: SEND salesfigures orgtbl-to-latex
+| | |
+\end{comment}
+#+end_example
+
+#+vindex: LaTeX-verbatim-environments
+#+texinfo: @noindent
+The line =#+ORGTBL: SEND= tells Orgtbl mode to use the function
+~orgtbl-to-latex~ to convert the table to LaTeX format, then insert
+the table at the target (receive) location named =salesfigures=.  Now
+the table is ready for data entry.  It can even use spreadsheet
+features[fn:159]:
+
+#+begin_example
+% BEGIN RECEIVE ORGTBL salesfigures
+% END RECEIVE ORGTBL salesfigures
+\begin{comment}
+,#+ORGTBL: SEND salesfigures orgtbl-to-latex
+| Month | Days | Nr sold | per day |
+|-------+------+---------+---------|
+| Jan   |   23 |      55 |     2.4 |
+| Feb   |   21 |      16 |     0.8 |
+| March |   22 |     278 |    12.6 |
+,#+TBLFM: $4=$3/$2;%.1f
+% $ (optional extra dollar to keep Font Lock happy, see footnote)
+\end{comment}
+#+end_example
+
+After editing, {{{kbd(C-c C-c)}}} inserts the translated table at the
+target location, between the two marker lines.
+
+For hand-made custom tables, note that the translator needs to skip
+the first two lines of the source table.  Also the command has to
+/splice/ out the target table without the header and footer.
+
+#+begin_example
+\begin{tabular}{lrrr}
+Month & \multicolumn{1}{c}{Days} & Nr.\ sold & per day\\
+% BEGIN RECEIVE ORGTBL salesfigures
+% END RECEIVE ORGTBL salesfigures
+\end{tabular}
+%
+\begin{comment}
+,#+ORGTBL: SEND salesfigures orgtbl-to-latex :splice t :skip 2
+| Month | Days | Nr sold | per day |
+|-------+------+---------+---------|
+| Jan   |   23 |      55 |     2.4 |
+| Feb   |   21 |      16 |     0.8 |
+| March |   22 |     278 |    12.6 |
+,#+TBLFM: $4=$3/$2;%.1f
+\end{comment}
+#+end_example
+
+The LaTeX translator function ~orgtbl-to-latex~ is already part of
+Orgtbl mode and uses a =tabular= environment to typeset the table and
+marks horizontal lines with ~\hline~.  For additional parameters to
+control output, see [[*Translator functions]]:
+
+- =:splice BOOLEAN= ::
+
+  When {{{var(BOOLEAN}}} is non-~nil~, return only table body lines;
+  i.e., not wrapped in =tabular= environment.  Default is ~nil~.
+
+- =:fmt FMT= ::
+
+  Format string to warp each field.  It should contain =%s= for the
+  original field value.  For example, to wrap each field value in
+  dollar symbol, you could use =:fmt "$%s$"=.  Format can also wrap
+  a property list with column numbers and formats, for example =:fmt
+  (2 "$%s$" 4 "%s\\%%")=.  In place of a string, a function of one
+  argument can be used; the function must return a formatted string.
+
+- =:efmt EFMT= ::
+
+  Format numbers as exponentials.  The spec should have =%s= twice for
+  inserting mantissa and exponent, for example ="%s\\times10^{%s}"=.  This
+  may also be a property list with column numbers and formats, for
+  example =:efmt (2 "$%s\\times10^{%s}$" 4 "$%s\\cdot10^{%s}$")=.  After
+  {{{var(EFMT)}}} has been applied to a value, {{{var(FMT)}}}---see
+  above---is also applied.  Functions with two arguments can be
+  supplied instead of strings.  By default, no special formatting is
+  applied.
+
+*** Translator functions
+:PROPERTIES:
+:DESCRIPTION: Copy and modify.
+:END:
+#+cindex: HTML, and Orgtbl mode
+#+cindex: translator function
+
+#+findex: orgtbl-to-csv
+#+findex: orgtbl-to-tsv
+#+findex: orgtbl-to-latex
+#+findex: orgtbl-to-html
+#+findex: orgtbl-to-texinfo
+#+findex: orgtbl-to-unicode
+#+findex: orgtbl-to-orgtbl
+#+findex: orgtbl-to-generic
+Orgtbl mode has built-in translator functions: ~orgtbl-to-csv~
+(comma-separated values), ~orgtbl-to-tsv~ (TAB-separated values),
+~orgtbl-to-latex~, ~orgtbl-to-html~, ~orgtbl-to-texinfo~,
+~orgtbl-to-unicode~ and ~orgtbl-to-orgtbl~.  They use the generic
+translator, ~orgtbl-to-generic~, which delegates translations to
+various export back-ends.
+
+Properties passed to the function through the =ORGTBL SEND= line take
+precedence over properties defined inside the function.  For example,
+this overrides the default LaTeX line endings, ~\\~, with ~\\[2mm]~:
+
+: #+ORGTBL: SEND test orgtbl-to-latex :lend " \\\\[2mm]"
+
+For a new language translator, define a converter function.  It can be
+a generic function, such as shown in this example.  It marks
+a beginning and ending of a table with =!BTBL!= and =!ETBL!=;
+a beginning and ending of lines with =!BL!= and =!EL!=; and uses a TAB
+for a field separator:
+
+#+begin_src emacs-lisp
+(defun orgtbl-to-language (table params)
+  "Convert the orgtbl-mode TABLE to language."
+  (orgtbl-to-generic
+   table
+   (org-combine-plists
+    '(:tstart "!BTBL!" :tend "!ETBL!" :lstart "!BL!" :lend "!EL!" :sep "\t")
+    params)))
+#+end_src
+
+#+texinfo: @noindent
+The documentation for the ~orgtbl-to-generic~ function shows
+a complete list of parameters, each of which can be passed through to
+~orgtbl-to-latex~, ~orgtbl-to-texinfo~, and any other function using
+that generic function.
+
+For complicated translations the generic translator function could be
+replaced by a custom translator function.  Such a custom function must
+take two arguments and return a single string containing the formatted
+table.  The first argument is the table whose lines are a list of
+fields or the symbol ~hline~.  The second argument is the property
+list consisting of parameters specified in the =#+ORGTBL: SEND= line.
+Please share your translator functions by posting them to the Org
+users mailing list, at mailto:emacs-orgmode@gnu.org.
+
+** Dynamic Blocks
+:PROPERTIES:
+:DESCRIPTION: Automatically filled blocks.
+:END:
+#+cindex: dynamic blocks
+
+Org supports /dynamic blocks/ in Org documents.  They are inserted
+with begin and end markers like any other code block, but the contents
+are updated automatically by a user function.
+
+#+kindex: C-c C-x x
+#+findex: org-dynamic-block-insert-dblock
+You can insert a dynamic block with ~org-dynamic-block-insert-dblock~,
+which is bound to {{{kbd(C-c C-x x)}}} by default.  For example,
+{{{kbd(C-c C-x x c l o c k t a b l e RET)}}} inserts a table that
+updates the work time (see [[*Clocking Work Time]]).
+
+Dynamic blocks can have names and function parameters.  The syntax is
+similar to source code block specifications:
+
+#+begin_example
+,#+BEGIN: myblock :parameter1 value1 :parameter2 value2 ...
+  ...
+,#+END:
+#+end_example
+
+These commands update dynamic blocks:
+
+- {{{kbd(C-c C-x C-u)}}} (~org-dblock-update~) ::
+
+  #+kindex: C-c C-x C-u
+  #+findex: org-dblock-update
+  Update dynamic block at point.
+
+- {{{kbd(C-u C-c C-x C-u)}}} ::
+
+  #+kindex: C-u C-c C-x C-u
+  Update all dynamic blocks in the current file.
+
+Before updating a dynamic block, Org removes content between the
+=BEGIN= and =END= markers.  Org then reads the parameters on the
+=BEGIN= line for passing to the writer function as a plist.  The
+previous content of the dynamic block becomes erased from the buffer
+and appended to the plist under ~:content~.
+
+The syntax for naming a writer function with a dynamic block labeled
+=myblock= is: ~org-dblock-write:myblock~.
+
+The following is an example of a dynamic block and a block writer function
+that updates the time when the function was last run:
+
+#+begin_example
+,#+BEGIN: block-update-time :format "on %m/%d/%Y at %H:%M"
+  ...
+,#+END:
+#+end_example
+
+#+texinfo: @noindent
+The dynamic block's writer function:
+
+#+begin_src emacs-lisp
+(defun org-dblock-write:block-update-time (params)
+  (let ((fmt (or (plist-get params :format) "%d. %m. %Y")))
+    (insert "Last block update at: "
+            (format-time-string fmt))))
+#+end_src
+
+To keep dynamic blocks up-to-date in an Org file, use the function,
+~org-update-all-dblocks~ in hook, such as ~before-save-hook~.  The
+~org-update-all-dblocks~ function does not run if the file is not in
+Org mode.
+
+#+findex: org-narrow-to-block
+Dynamic blocks, like any other block, can be narrowed with
+~org-narrow-to-block~.
+
+** Special Agenda Views
+:PROPERTIES:
+:DESCRIPTION: Customized views.
+:END:
+#+cindex: agenda views, user-defined
+
+#+vindex: org-agenda-skip-function
+#+vindex: org-agenda-skip-function-global
+Org provides a special hook to further limit items in agenda views:
+~agenda~, ~agenda*~[fn:160], ~todo~, ~alltodo~, ~tags~, ~tags-todo~,
+~tags-tree~.  Specify a custom function that tests inclusion of every
+matched item in the view.  This function can also skip as much as is
+needed.
+
+For a global condition applicable to agenda views, use the
+~org-agenda-skip-function-global~ variable.  Org uses a global
+condition with ~org-agenda-skip-function~ for custom searching.
+
+This example defines a function for a custom view showing TODO items
+with =waiting= status.  Manually this is a multi-step search process,
+but with a custom view, this can be automated as follows:
+
+The custom function searches the subtree for the =waiting= tag and
+returns ~nil~ on match.  Otherwise it gives the location from where
+the search continues.
+
+#+begin_src emacs-lisp
+(defun my-skip-unless-waiting ()
+  "Skip trees that are not waiting"
+  (let ((subtree-end (save-excursion (org-end-of-subtree t))))
+    (if (re-search-forward ":waiting:" subtree-end t)
+        nil          ; tag found, do not skip
+      subtree-end))) ; tag not found, continue after end of subtree
+#+end_src
+
+To use this custom function in a custom agenda command:
+
+#+begin_src emacs-lisp
+(org-add-agenda-custom-command
+ '("b" todo "PROJECT"
+   ((org-agenda-skip-function 'my-skip-unless-waiting)
+    (org-agenda-overriding-header "Projects waiting for something: "))))
+#+end_src
+
+#+vindex: org-agenda-overriding-header
+Note that this also binds ~org-agenda-overriding-header~ to a more
+meaningful string suitable for the agenda view.
+
+#+vindex: org-odd-levels-only
+#+vindex: org-agenda-skip-function
+Search for entries with a limit set on levels for the custom search.
+This is a general approach to creating custom searches in Org.  To
+include all levels, use =LEVEL>0=[fn:161].  Then to selectively pick
+the matched entries, use ~org-agenda-skip-function~, which also
+accepts Lisp forms, such as ~org-agenda-skip-entry-if~ and
+~org-agenda-skip-subtree-if~.  For example:
+
+- =(org-agenda-skip-entry-if 'scheduled)= ::
+
+  Skip current entry if it has been scheduled.
+
+- =(org-agenda-skip-entry-if 'notscheduled)= ::
+
+  Skip current entry if it has not been scheduled.
+
+- =(org-agenda-skip-entry-if 'deadline)= ::
+
+  Skip current entry if it has a deadline.
+
+- =(org-agenda-skip-entry-if 'scheduled 'deadline)= ::
+
+  Skip current entry if it has a deadline, or if it is scheduled.
+
+- =(org-agenda-skip-entry-if 'todo '("TODO" "WAITING"))= ::
+
+  Skip current entry if the TODO keyword is TODO or WAITING.
+
+- =(org-agenda-skip-entry-if 'todo 'done)= ::
+
+  Skip current entry if the TODO keyword marks a DONE state.
+
+- =(org-agenda-skip-entry-if 'timestamp)= ::
+
+  Skip current entry if it has any timestamp, may also be deadline or
+  scheduled.
+
+- =(org-agenda-skip-entry-if 'regexp "regular expression")= ::
+
+  Skip current entry if the regular expression matches in the entry.
+
+- =(org-agenda-skip-entry-if 'notregexp "regular expression")= ::
+
+  Skip current entry unless the regular expression matches.
+
+- =(org-agenda-skip-subtree-if 'regexp "regular expression")= ::
+
+  Same as above, but check and skip the entire subtree.
+
+The following is an example of a search for =waiting= without the
+special function:
+
+#+begin_src emacs-lisp
+(org-add-agenda-custom-command
+ '("b" todo "PROJECT"
+   ((org-agenda-skip-function '(org-agenda-skip-subtree-if
+                                'regexp ":waiting:"))
+    (org-agenda-overriding-header "Projects waiting for something: "))))
+#+end_src
+
+** Speeding Up Your Agendas
+:PROPERTIES:
+:DESCRIPTION: Tips on how to speed up your agendas.
+:END:
+#+cindex: agenda views, optimization
+
+Some agenda commands slow down when the Org files grow in size or
+number.  Here are tips to speed up:
+
+- Reduce the number of Org agenda files to avoid slowdowns due to hard drive
+  accesses.
+
+- Reduce the number of DONE and archived headlines so agenda
+  operations that skip over these can finish faster.
+
+- Do not dim blocked tasks:
+  #+vindex: org-agenda-dim-blocked-tasks
+
+  #+begin_src emacs-lisp
+  (setq org-agenda-dim-blocked-tasks nil)
+  #+end_src
+
+- Stop preparing agenda buffers on startup:
+  #+vindex: org-startup-folded
+  #+vindex: org-agenda-inhibit-startup
+
+  #+begin_src emacs-lisp
+  (setq org-agenda-inhibit-startup t)
+  #+end_src
+
+- Disable tag inheritance for agendas:
+  #+vindex: org-agenda-show-inherited-tags
+  #+vindex: org-agenda-use-tag-inheritance
+
+  #+begin_src emacs-lisp
+  (setq org-agenda-use-tag-inheritance nil)
+  #+end_src
+
+These options can be applied to selected agenda views.  For more
+details about generation of agenda views, see the docstrings for the
+relevant variables, and this 
[[https://orgmode.org/worg/agenda-optimization.html][dedicated Worg page]] for 
agenda
+optimization.
+
+** Extracting Agenda Information
+:PROPERTIES:
+:DESCRIPTION: Post-processing agenda information.
+:END:
+#+cindex: agenda, pipe
+#+cindex: scripts, for agenda processing
+
+Org provides commands to access agendas through Emacs batch mode.
+Through this command-line interface, agendas are automated for further
+processing or printing.
+
+#+vindex: org-agenda-custom-commands
+#+findex: org-batch-agenda
+~org-batch-agenda~ creates an agenda view in ASCII and outputs to
+standard output.  This command takes one string parameter.  When
+string consists of a single character, Org uses it as a key to
+~org-agenda-custom-commands~.  These are the same ones available
+through the agenda dispatcher (see [[*The Agenda Dispatcher]]).
+
+This example command line directly prints the TODO list to the printer:
+
+: emacs -batch -l ~/.emacs -eval '(org-batch-agenda "t")' | lpr
+
+When the string parameter length is two or more characters, Org
+matches it with tags/TODO strings.  For example, this example command
+line prints items tagged with =shop=, but excludes items tagged with
+=NewYork=:
+
+#+begin_example
+emacs -batch -l ~/.emacs                                      \
+      -eval '(org-batch-agenda "+shop-NewYork")' | lpr
+#+end_example
+
+#+texinfo: @noindent
+An example showing on-the-fly parameter modifications:
+
+#+begin_example
+emacs -batch -l ~/.emacs                                      \
+   -eval '(org-batch-agenda "a"                               \
+           org-agenda-span (quote month)                      \
+           org-agenda-include-diary nil                       \
+           org-agenda-files (quote ("~/org/project.org")))'   \
+   | lpr
+#+end_example
+
+#+texinfo: @noindent
+which produces an agenda for the next 30 days from just the
+=~/org/projects.org= file.
+
+#+findex: org-batch-agenda-csv
+For structured processing of agenda output, use ~org-batch-agenda-csv~
+with the following fields:
+
+- category :: The category of the item
+- head :: The headline, without TODO keyword, TAGS and PRIORITY
+- type :: The type of the agenda entry, can be
+
+  | ~todo~              | selected in TODO match              |
+  | ~tagsmatch~         | selected in tags match              |
+  | ~diary~             | imported from diary                 |
+  | ~deadline~          | a deadline                          |
+  | ~scheduled~         | scheduled                           |
+  | ~timestamp~         | appointment, selected by timestamp  |
+  | ~closed~            | entry was closed on date            |
+  | ~upcoming-deadline~ | warning about nearing deadline      |
+  | ~past-scheduled~    | forwarded scheduled item            |
+  | ~block~             | entry has date block including date |
+
+- todo :: The TODO keyword, if any
+- tags :: All tags including inherited ones, separated by colons
+- date :: The relevant date, like =2007-2-14=
+- time :: The time, like =15:00-16:50=
+- extra :: String with extra planning info
+- priority-l :: The priority letter if any was given
+- priority-n :: The computed numerical priority
+
+If the selection of the agenda item was based on a timestamp,
+including those items with =DEADLINE= and =SCHEDULED= keywords, then
+Org includes date and time in the output.
+
+If the selection of the agenda item was based on a timestamp  (or
+deadline/scheduled), then Org includes date and time in the output.
+
+Here is an example of a post-processing script in Perl.  It takes the
+CSV output from Emacs and prints with a checkbox:
+
+#+begin_src perl
+#!/usr/bin/perl
+
+# define the Emacs command to run
+$cmd = "emacs -batch -l ~/.emacs -eval '(org-batch-agenda-csv \"t\")'";
+
+# run it and capture the output
+$agenda = qx{$cmd 2>/dev/null};
+
+# loop over all lines
+foreach $line (split(/\n/,$agenda)) {
+    # get the individual values
+    ($category,$head,$type,$todo,$tags,$date,$time,$extra,
+     $priority_l,$priority_n) = split(/,/,$line);
+    # process and print
+    print "[ ] $head\n";
+}
+#+end_src
+
+** Using the Property API
+:PROPERTIES:
+:DESCRIPTION: Writing programs that use entry properties.
+:END:
+#+cindex: API, for properties
+#+cindex: properties, API
+
+Here is a description of the functions that can be used to work with
+properties.
+
+#+attr_texinfo: :options org-entry-properties &optional pom which
+#+begin_defun
+Get all properties of the entry at point-or-marker {{{var(POM)}}}.
+This includes the TODO keyword, the tags, time strings for deadline,
+scheduled, and clocking, and any additional properties defined in the
+entry.  The return value is an alist.  Keys may occur multiple times
+if the property key was used several times.  {{{var(POM)}}} may also
+be ~nil~, in which case the current entry is used.  If
+{{{var(WHICH)}}} is ~nil~ or ~all~, get all properties.  If
+{{{var(WHICH)}}} is ~special~ or ~standard~, only get that subclass.
+#+end_defun
+
+#+vindex: org-use-property-inheritance
+#+findex: org-insert-property-drawer
+#+attr_texinfo: :options org-entry-get pom property &optional inherit
+#+begin_defun
+Get value of {{{var(PROPERTY)}}} for entry at point-or-marker
+{{{var(POM)}}}.  By default, this only looks at properties defined
+locally in the entry.  If {{{var(INHERIT)}}} is non-~nil~ and the
+entry does not have the property, then also check higher levels of the
+hierarchy.  If {{{var(INHERIT)}}} is the symbol ~selective~, use
+inheritance if and only if the setting of
+~org-use-property-inheritance~ selects {{{var(PROPERTY)}}} for
+inheritance.
+#+end_defun
+
+#+attr_texinfo: :options org-entry-delete pom property
+#+begin_defun
+Delete the property {{{var(PROPERTY)}}} from entry at point-or-marker
+{{{var(POM)}}}.
+#+end_defun
+
+#+attr_texinfo: :options org-entry-put pom property value
+#+begin_defun
+Set {{{var(PROPERTY)}}} to {{{var(VALUES)}}} for entry at
+point-or-marker POM.
+#+end_defun
+
+#+attr_texinfo: :options org-buffer-property-keys &optional include-specials
+#+begin_defun
+Get all property keys in the current buffer.
+#+end_defun
+
+#+attr_texinfo: :options org-insert-property-drawer
+#+begin_defun
+Insert a property drawer for the current entry.  Also
+#+end_defun
+
+#+attr_texinfo: :options org-entry-put-multivalued-property pom property &rest 
values
+#+begin_defun
+Set {{{var(PROPERTY)}}} at point-or-marker {{{var(POM)}}} to
+{{{var(VALUES)}}}.  {{{var(VALUES)}}} should be a list of strings.
+They are concatenated, with spaces as separators.
+#+end_defun
+
+#+attr_texinfo: :options org-entry-get-multivalued-property pom property
+#+begin_defun
+Treat the value of the property {{{var(PROPERTY)}}} as
+a whitespace-separated list of values and return the values as a list
+of strings.
+#+end_defun
+
+#+attr_texinfo: :options org-entry-add-to-multivalued-property pom property 
value
+#+begin_defun
+Treat the value of the property {{{var(PROPERTY)}}} as
+a whitespace-separated list of values and make sure that
+{{{var(VALUE)}}} is in this list.
+#+end_defun
+
+#+attr_texinfo: :options org-entry-remove-from-multivalued-property pom 
property value
+#+begin_defun
+Treat the value of the property {{{var(PROPERTY)}}} as
+a whitespace-separated list of values and make sure that
+{{{var(VALUE)}}} is /not/ in this list.
+#+end_defun
+
+#+attr_texinfo: :options org-entry-member-in-multivalued-property pom property 
value
+#+begin_defun
+Treat the value of the property {{{var(PROPERTY)}}} as
+a whitespace-separated list of values and check if {{{var(VALUE)}}} is
+in this list.
+#+end_defun
+
+#+attr_texinfo: :options org-property-allowed-value-functions
+#+begin_defopt
+Hook for functions supplying allowed values for a specific property.
+The functions must take a single argument, the name of the property,
+and return a flat list of allowed values.  If =:ETC= is one of the
+values, use the values as completion help, but allow also other values
+to be entered.  The functions must return ~nil~ if they are not
+responsible for this property.
+#+end_defopt
+
+** Using the Mapping API
+:PROPERTIES:
+:DESCRIPTION: Mapping over all or selected entries.
+:END:
+#+cindex: API, for mapping
+#+cindex: mapping entries, API
+
+Org has sophisticated mapping capabilities to find all entries
+satisfying certain criteria.  Internally, this functionality is used
+to produce agenda views, but there is also an API that can be used to
+execute arbitrary functions for each or selected entries.  The main
+entry point for this API is:
+
+#+attr_texinfo: :options org-map-entries func &optional match scope &rest skip
+#+begin_defun
+Call {{{var(FUNC)}}} at each headline selected by {{{var(MATCH)}}} in
+{{{var(SCOPE)}}}.
+
+{{{var(FUNC)}}} is a function or a Lisp form.  With point positioned
+at the beginning of the headline, call the function without arguments.
+Org returns an alist of return values of calls to the function.
+
+To avoid preserving point, Org wraps the call to {{{var(FUNC)}}} in
+~save-excursion~ form.  After evaluation, Org moves point to the end
+of the line that was just processed.  Search continues from that point
+forward.  This may not always work as expected under some conditions,
+such as if the current sub-tree was removed by a previous archiving
+operation.  In such rare circumstances, Org skips the next entry
+entirely when it should not.  To stop Org from such skips, make
+{{{var(FUNC)}}} set the variable ~org-map-continue-from~ to a specific
+buffer position.
+
+{{{var(MATCH)}}} is a tags/property/TODO match.  Org iterates only
+matched headlines.  Org iterates over all headlines when
+{{{var(MATCH)}}} is ~nil~ or ~t~.
+
+{{{var(SCOPE)}}} determines the scope of this command.  It can be any
+of:
+
+- ~nil~ ::
+
+  The current buffer, respecting the restriction, if any.
+
+- ~tree~ ::
+
+  The subtree started with the entry at point.
+
+- ~region~ ::
+
+  The entries within the active region, if any.
+
+- ~file~ ::
+
+  The current buffer, without restriction.
+
+- ~file-with-archives~ ::
+
+  The current buffer, and any archives associated with it.
+
+- ~agenda~ ::
+
+  All agenda files.
+
+- ~agenda-with-archives~ ::
+
+  All agenda files with any archive files associated with them.
+
+- list of filenames ::
+
+  If this is a list, all files in the list are scanned.
+
+#+texinfo: @noindent
+The remaining arguments are treated as settings for the scanner's
+skipping facilities.  Valid arguments are:
+
+- ~archive~ ::
+
+  Skip trees with the =ARCHIVE= tag.
+
+- ~comment~ ::
+
+  Skip trees with the COMMENT keyword.
+
+- function or Lisp form ::
+
+  #+vindex: org-agenda-skip-function
+  Used as value for ~org-agenda-skip-function~, so whenever the
+  function returns ~t~, {{{var(FUNC)}}} is called for that entry and
+  search continues from the point where the function leaves it.
+#+end_defun
+
+The mapping routine can call any arbitrary function, even functions
+that change meta data or query the property API (see [[*Using the
+Property API]]).  Here are some handy functions:
+
+#+attr_texinfo: :options org-todo &optional arg
+#+begin_defun
+Change the TODO state of the entry.  See the docstring of the
+functions for the many possible values for the argument
+{{{var(ARG)}}}.
+#+end_defun
+
+#+attr_texinfo: :options org-priority &optional action
+#+begin_defun
+Change the priority of the entry.  See the docstring of this function
+for the possible values for {{{var(ACTION)}}}.
+#+end_defun
+
+#+attr_texinfo: :options org-toggle-tag tag &optional onoff
+#+begin_defun
+Toggle the tag {{{var(TAG)}}} in the current entry.  Setting
+{{{var(ONOFF)}}} to either ~on~ or ~off~ does not toggle tag, but
+ensure that it is either on or off.
+#+end_defun
+
+#+attr_texinfo: :options org-promote
+#+begin_defun
+Promote the current entry.
+#+end_defun
+
+#+attr_texinfo: :options org-demote
+#+begin_defun
+Demote the current entry.
+#+end_defun
+
+This example turns all entries tagged with =TOMORROW= into TODO
+entries with keyword =UPCOMING=.  Org ignores entries in comment trees
+and archive trees.
+
+#+begin_src emacs-lisp
+(org-map-entries '(org-todo "UPCOMING")
+                 "+TOMORROW" 'file 'archive 'comment)
+#+end_src
+
+The following example counts the number of entries with TODO keyword
+=WAITING=, in all agenda files.
+
+#+begin_src emacs-lisp
+(length (org-map-entries t "/+WAITING" 'agenda))
+#+end_src
+
+* History and Acknowledgments
+:PROPERTIES:
+:DESCRIPTION: How Org came into being.
+:APPENDIX: t
+:END:
+
+** From Carsten
+:PROPERTIES:
+:UNNUMBERED: notoc
+:END:
+
+Org was born in 2003, out of frustration over the user interface of
+the Emacs Outline mode.  I was trying to organize my notes and
+projects, and using Emacs seemed to be the natural way to go.
+However, having to remember eleven different commands with two or
+three keys per command, only to hide and show parts of the outline
+tree, that seemed entirely unacceptable to me.  Also, when using
+outlines to take notes, I constantly wanted to restructure the tree,
+organizing it parallel to my thoughts and plans.  /Visibility cycling/
+and /structure editing/ were originally implemented in the package
+=outline-magic.el=, but quickly moved to the more general =org.el=.
+As this environment became comfortable for project planning, the next
+step was adding /TODO entries/, basic /timestamps/, and /table
+support/.  These areas highlighted the two main goals that Org still
+has today: to be a new, outline-based, plain text mode with innovative
+and intuitive editing features, and to incorporate project planning
+functionality directly into a notes file.
+
+Since the first release, literally thousands of emails to me or to the
+[[mailto:emacs-orgmode@gnu.org][mailing list]] have provided a constant stream 
of bug reports, feedback,
+new ideas, and sometimes patches and add-on code.  Many thanks to
+everyone who has helped to improve this package.  I am trying to keep
+here a list of the people who had significant influence in shaping one
+or more aspects of Org.  The list may not be complete, if I have
+forgotten someone, please accept my apologies and let me know.
+
+Before I get to this list, a few special mentions are in order:
+
+- Bastien Guerry ::
+
+  Bastien has written a large number of extensions to Org (most of
+  them integrated into the core by now), including the LaTeX exporter
+  and the plain list parser.  His support during the early days was
+  central to the success of this project.  Bastien also invented Worg,
+  helped establishing the Web presence of Org, and sponsored hosting
+  costs for the orgmode.org website.  Bastien stepped in as maintainer
+  of Org between 2011 and 2013, at a time when I desperately needed
+  a break.
+
+- Eric Schulte and Dan Davison ::
+
+  Eric and Dan are jointly responsible for the Org Babel system, which
+  turns Org into a multi-language environment for evaluating code and
+  doing literate programming and reproducible research.  This has
+  become one of Org's killer features that define what Org is today.
+
+- John Wiegley ::
+
+  John has contributed a number of great ideas and patches directly to
+  Org, including the attachment system (=org-attach.el=), integration
+  with Apple Mail (=org-mac-message.el=), hierarchical dependencies of
+  TODO items, habit tracking (=org-habits.el=), and encryption
+  (=org-crypt.el=).  Also, the capture system is really an extended
+  copy of his great =remember.el=.
+
+- Sebastian Rose ::
+
+  Without Sebastian, the HTML/XHTML publishing of Org would be the
+  pitiful work of an ignorant amateur.  Sebastian has pushed this part
+  of Org onto a much higher level.  He also wrote =org-info.js=,
+  a JavaScript program for displaying webpages derived from Org using
+  an Info-like or a folding interface with single-key navigation.
+
+See below for the full list of contributions!  Again, please let me
+know what I am missing here!
+
+** From Bastien
+:PROPERTIES:
+:UNNUMBERED: notoc
+:END:
+
+I (Bastien) have been maintaining Org between 2011 and 2013.  This
+appendix would not be complete without adding a few more
+acknowledgments and thanks.
+
+I am first grateful to Carsten for his trust while handing me over the
+maintainership of Org.  His unremitting support is what really helped
+me getting more confident over time, with both the community and the
+code.
+
+When I took over maintainership, I knew I would have to make Org more
+collaborative than ever, as I would have to rely on people that are
+more knowledgeable than I am on many parts of the code.  Here is
+a list of the persons I could rely on, they should really be
+considered co-maintainers, either of the code or the community:
+
+- Eric Schulte ::
+
+  Eric is maintaining the Babel parts of Org.  His reactivity here
+  kept me away from worrying about possible bugs here and let me focus
+  on other parts.
+
+- Nicolas Goaziou ::
+
+  Nicolas is maintaining the consistency of the deepest parts of Org.
+  His work on =org-element.el= and =ox.el= has been outstanding, and
+  it opened the doors for many new ideas and features.  He rewrote
+  many of the old exporters to use the new export engine, and helped
+  with documenting this major change.  More importantly (if that's
+  possible), he has been more than reliable during all the work done
+  for Org 8.0, and always very reactive on the mailing list.
+
+- Achim Gratz ::
+
+  Achim rewrote the building process of Org, turning some /ad hoc/
+  tools into a flexible and conceptually clean process.  He patiently
+  coped with the many hiccups that such a change can create for users.
+
+- Nick Dokos ::
+
+  The Org mode mailing list would not be such a nice place without
+  Nick, who patiently helped users so many times.  It is impossible to
+  overestimate such a great help, and the list would not be so active
+  without him.
+
+I received support from so many users that it is clearly impossible to
+be fair when shortlisting a few of them, but Org's history would not
+be complete if the ones above were not mentioned in this manual.
+
+** List of Contributions
+:PROPERTIES:
+:UNNUMBERED: notoc
+:END:
+
+- Russell Adams came up with the idea for drawers.
+
+- Thomas Baumann wrote =ol-bbdb.el= and =ol-mhe.el=.
+
+- Christophe Bataillon created the great unicorn logo that we use on
+  the Org mode website.
+
+- Alex Bochannek provided a patch for rounding timestamps.
+
+- Jan Böcker wrote =ol-docview.el=.
+
+- Brad Bozarth showed how to pull RSS feed data into Org files.
+
+- Tom Breton wrote =org-choose.el=.
+
+- Charles Cave's suggestion sparked the implementation of templates
+  for Remember, which are now templates for capture.
+
+- Pavel Chalmoviansky influenced the agenda treatment of items with
+  specified time.
+
+- Gregory Chernov patched support for Lisp forms into table
+  calculations and improved XEmacs compatibility, in particular by
+  porting =nouline.el= to XEmacs.
+
+- Sacha Chua suggested copying some linking code from Planner.
+
+- Baoqiu Cui contributed the DocBook exporter.
+
+- Eddward DeVilla proposed and tested checkbox statistics.  He also
+  came up with the idea of properties, and that there should be an API
+  for them.
+
+- Nick Dokos tracked down several nasty bugs.
+
+- Kees Dullemond used to edit projects lists directly in HTML and so
+  inspired some of the early development, including HTML export.  He
+  also asked for a way to narrow wide table columns.
+
+- Thomas\nbsp{}S.\nbsp{}Dye contributed documentation on Worg and helped
+  integrating the Org Babel documentation into the manual.
+
+- Christian Egli converted the documentation into Texinfo format,
+  inspired the agenda, patched CSS formatting into the HTML exporter,
+  and wrote =org-taskjuggler.el=.
+
+- David Emery provided a patch for custom CSS support in exported HTML
+  agendas.
+
+- Nic Ferrier contributed mailcap and XOXO support.
+
+- Miguel\nbsp{}A.\nbsp{}Figueroa-Villanueva implemented hierarchical 
checkboxes.
+
+- John Foerch figured out how to make incremental search show context
+  around a match in a hidden outline tree.
+
+- Raimar Finken wrote =org-git-line.el=.
+
+- Mikael Fornius works as a mailing list moderator.
+
+- Austin Frank works as a mailing list moderator.
+
+- Eric Fraga drove the development of Beamer export with ideas and
+  testing.
+
+- Barry Gidden did proofreading the manual in preparation for the book
+  publication through Network Theory Ltd.
+
+- Niels Giesen had the idea to automatically archive DONE trees.
+
+- Nicolas Goaziou rewrote much of the plain list code.
+
+- Kai Grossjohann pointed out key-binding conflicts with other
+  packages.
+
+- Brian Gough of Network Theory Ltd publishes the Org mode manual as
+  a book.
+
+- Bernt Hansen has driven much of the support for auto-repeating
+  tasks, task state change logging, and the clocktable.  His clear
+  explanations have been critical when we started to adopt the Git
+  version control system.
+
+- Manuel Hermenegildo has contributed various ideas, small fixes and
+  patches.
+
+- Phil Jackson wrote =ol-irc.el=.
+
+- Scott Jaderholm proposed footnotes, control over whitespace between
+  folded entries, and column view for properties.
+
+- Matt Jones wrote MobileOrg Android.
+
+- Tokuya Kameshima wrote =org-wl.el= and =org-mew.el=.
+
+- Shidai Liu ("Leo") asked for embedded LaTeX and tested it.  He also
+  provided frequent feedback and some patches.
+
+- Matt Lundin has proposed last-row references for table formulas and
+  named invisible anchors.  He has also worked a lot on the FAQ.
+
+- David Maus wrote =org-atom.el=, maintains the issues file for Org,
+  and is a prolific contributor on the mailing list with competent
+  replies, small fixes and patches.
+
+- Jason\nbsp{}F.\nbsp{}McBrayer suggested agenda export to CSV format.
+
+- Max Mikhanosha came up with the idea of refiling.
+
+- Dmitri Minaev sent a patch to set priority limits on a per-file
+  basis.
+
+- Stefan Monnier provided a patch to keep the Emacs Lisp compiler
+  happy.
+
+- Richard Moreland wrote MobileOrg for the iPhone.
+
+- Rick Moynihan proposed allowing multiple TODO sequences in a file
+  and being able to quickly restrict the agenda to a subtree.
+
+- Todd Neal provided patches for links to Info files and Elisp forms.
+
+- Greg Newman refreshed the unicorn logo into its current form.
+
+- Tim O'Callaghan suggested in-file links, search options for general
+  file links, and tags.
+
+- Osamu Okano wrote =orgcard2ref.pl=, a Perl program to create a text
+  version of the reference card.
+
+- Takeshi Okano translated the manual and David O'Toole's tutorial
+  into Japanese.
+
+- Oliver Oppitz suggested multi-state TODO items.
+
+- Scott Otterson sparked the introduction of descriptive text for
+  links, among other things.
+
+- Pete Phillips helped during the development of the TAGS feature,
+  and provided frequent feedback.
+
+- Martin Pohlack provided the code snippet to bundle character
+  insertion into bundles of 20 for undo.
+
+- T.\nbsp{}V.\nbsp{}Raman reported bugs and suggested improvements.
+
+- Matthias Rempe (Oelde) provided ideas, Windows support, and quality
+  control.
+
+- Paul Rivier provided the basic implementation of named footnotes.
+  He also acted as mailing list moderator for some time.
+
+- Kevin Rogers contributed code to access VM files on remote hosts.
+
+- Frank Ruell solved the mystery of the =keymapp nil= bug, a conflict
+  with =allout.el=.
+
+- Jason Riedy generalized the send-receive mechanism for Orgtbl
+  tables with extensive patches.
+
+- Philip Rooke created the Org reference card, provided lots of
+  feedback, developed and applied standards to the Org documentation.
+
+- Christian Schlauer proposed angular brackets around links, among
+  other things.
+
+- Paul Sexton wrote =org-ctags.el=.
+
+- Tom Shannon's =organizer-mode.el= inspired linking to VM/BBDB/Gnus.
+
+- Ilya Shlyakhter proposed the Archive Sibling, line numbering in
+  literal examples, and remote highlighting for referenced code lines.
+
+- Stathis Sideris wrote the =ditaa.jar= ASCII to PNG converter that is
+  now packaged into Org's =contrib/= directory.
+
+- Daniel Sinder came up with the idea of internal archiving by locking
+  subtrees.
+
+- Dale Smith proposed link abbreviations.
+
+- James TD Smith has contributed a large number of patches for
+  useful tweaks and features.
+
+- Adam Spiers asked for global linking commands, inspired the link
+  extension system, added support for Mairix, and proposed the mapping
+  API.
+
+- Ulf Stegemann created the table to translate special symbols to
+  HTML, LaTeX, UTF-8, Latin-1 and ASCII.
+
+- Andy Stewart contributed code to =ol-w3m.el=, to copy
+  HTML content with links transformation to Org syntax.
+
+- David O'Toole wrote =org-publish.el= and drafted the
+  manual chapter about publishing.
+
+- Jambunathan\nbsp{}K.\nbsp{}contributed the ODT exporter.
+
+- Sebastien Vauban reported many issues with LaTeX and Beamer export
+  and enabled source code highlighting in Gnus.
+
+- Stefan Vollmar organized a video-recorded talk at the
+  Max-Planck-Institute for Neurology.  He also inspired the creation
+  of a concept index for HTML export.
+
+- Jürgen Vollmer contributed code generating the table of contents in
+  HTML output.
+
+- Samuel Wales has provided important feedback and bug reports.
+
+- Chris Wallace provided a patch implementing the =QUOTE= block.
+
+- David Wainberg suggested archiving, and improvements to the
+  linking system.
+
+- Carsten Wimmer suggested some changes and helped fix a bug in
+  linking to Gnus.
+
+- Roland Winkler requested additional key bindings to make Org work on
+  a TTY.
+
+- Piotr Zielinski wrote =org-mouse.el=, proposed agenda
+  blocks and contributed various ideas and code snippets.
+
+- Marco Wahl wrote =ol-eww.el=.
+
+* GNU Free Documentation License
+:PROPERTIES:
+:APPENDIX: t
+:DESCRIPTION: The license for this documentation.
+:END:
+
+#+texinfo: @include doclicense.texi
+
+* Main Index
+:PROPERTIES:
+:INDEX:    cp
+:DESCRIPTION: An index of Org's concepts and features.
+:END:
+
+* Key Index
+:PROPERTIES:
+:DESCRIPTION: Key bindings and where they are described.
+:INDEX:    ky
+:END:
+
+* Command and Function Index
+:PROPERTIES:
+:DESCRIPTION: Command names and some internal functions.
+:INDEX:    fn
+:END:
+
+* Variable Index
+:PROPERTIES:
+:DESCRIPTION: Variables mentioned in the manual.
+:INDEX:    vr
+:END:
+
+This is not a complete index of variables and faces, only the ones
+that are mentioned in the manual.  For a more complete list, use
+{{{kbd(M-x org-customize)}}} and then click yourself through the tree.
+
+* Copying
+:PROPERTIES:
+:copying:  t
+:END:
+
+This manual is for Org version {{{version}}}.
+
+Copyright \copy 2004--2021 Free Software Foundation, Inc.
+
+#+begin_quote
+Permission is granted to copy, distribute and/or modify this document
+under the terms of the GNU Free Documentation License, Version 1.3 or
+any later version published by the Free Software Foundation; with no
+Invariant Sections, with the Front-Cover Texts being "A GNU Manual,"
+and with the Back-Cover Texts as in (a) below.  A copy of the license
+is included in the section entitled "GNU Free Documentation License."
+
+(a) The FSF's Back-Cover Text is: "You have the freedom to copy and
+modify this GNU manual."
+#+end_quote
+
+* Export Setup                                                          
:noexport:
+
+#+setupfile: org-setup.org
+
+#+export_file_name: org.texi
+
+#+texinfo_dir_category: Emacs editing modes
+#+texinfo_dir_title: Org Mode: (org)
+#+texinfo_dir_desc: Outline-based notes management and organizer
+
+* Footnotes
+
+[fn:1] If you do not use Font Lock globally turn it on in Org buffer
+with =(add-hook 'org-mode-hook 'turn-on-font-lock)=.
+
+[fn:2] Please consider subscribing to the mailing list in order to
+minimize the work the mailing list moderators have to do.
+
+[fn:3] See the variables ~org-special-ctrl-a/e~, ~org-special-ctrl-k~,
+and ~org-ctrl-k-protect-subtree~ to configure special behavior of
+{{{kbd(C-a)}}}, {{{kbd(C-e)}}}, and {{{kbd(C-k)}}} in headlines.  Note
+also that clocking only works with headings indented less than 30
+stars.
+
+[fn:4] See, however, the option ~org-cycle-emulate-tab~.
+
+[fn:5] The indirect buffer contains the entire buffer, but is narrowed
+to the current tree.  Editing the indirect buffer also changes the
+original buffer, but without affecting visibility in that buffer.  For
+more information about indirect buffers, see [[info:emacs#Indirect 
Buffers][GNU Emacs Manual]].
+
+[fn:6] When ~org-agenda-inhibit-startup~ is non-~nil~, Org does not
+honor the default visibility state when first opening a file for the
+agenda (see [[*Speeding Up Your Agendas]]).
+
+[fn:7] See also the variable ~org-show-context-detail~ to decide how
+much context is shown around each match.
+
+[fn:8] This depends on the option ~org-remove-highlights-with-change~.
+
+[fn:9] When using =*= as a bullet, lines must be indented so that they
+are not interpreted as headlines.  Also, when you are hiding leading
+stars to get a clean outline view, plain list items starting with
+a star may be hard to distinguish from true headlines.  In short: even
+though =*= is supported, it may be better to not use it for plain list
+items.
+
+[fn:10] You can filter out any of them by configuring
+~org-plain-list-ordered-item-terminator~.
+
+[fn:11] You can also get =a.=, =A.=, =a)= and =A)= by configuring
+~org-list-allow-alphabetical~.  To minimize confusion with normal
+text, those are limited to one character only.  Beyond that limit,
+bullets automatically become numbers.
+
+[fn:12] If there's a checkbox in the item, the cookie must be put
+/before/ the checkbox.  If you have activated alphabetical lists, you
+can also use counters like =[@b]=.
+
+[fn:13] If you do not want the item to be split, customize the
+variable ~org-M-RET-may-split-line~.
+
+[fn:14] If you want to cycle around items that way, you may customize
+~org-list-use-circular-motion~.
+
+[fn:15] See ~org-list-use-circular-motion~ for a cyclic behavior.
+
+[fn:16] Many desktops intercept {{{kbd(M-TAB)}}} to switch windows.
+Use {{{kbd(C-M-i)}}} or {{{kbd(ESC TAB)}}} instead.
+
+[fn:17] To insert a vertical bar into a table field, use =\vert= or,
+inside a word =abc\vert{}def=.
+
+[fn:18] Org understands references typed by the user as =B4=, but it
+does not use this syntax when offering a formula for editing.  You can
+customize this behavior using the variable
+~org-table-use-standard-references~.
+
+[fn:19] The computation time scales as O(N^2) because table
+{{{var(FOO)}}} is parsed for each field to be copied.
+
+[fn:20] The file =constants.el= can supply the values of constants in
+two different unit systems, =SI= and =cgs=.  Which one is used depends
+on the value of the variable ~constants-unit-system~.  You can use the
+=STARTUP= options =constSI= and =constcgs= to set this value for the
+current buffer.
+
+[fn:21] The printf reformatting is limited in precision because the
+value passed to it is converted into an "integer" or "double".  The
+"integer" is limited in size by truncating the signed value to 32
+bits.  The "double" is limited in precision to 64 bits overall which
+leaves approximately 16 significant decimal digits.
+
+[fn:22] Such names must start with an alphabetic character and use
+only alphanumeric/underscore characters.
+
+[fn:23] Plain URIs are recognized only for a well-defined set of
+schemes.  See [[*External Links]].  Unlike URI syntax, they cannot contain
+parenthesis or white spaces, either.  URIs within angle brackets have
+no such limitation.
+
+[fn:24] More accurately, the precise behavior depends on how point
+arrived there---see [[info:elisp#Invisible Text][Invisible Text]].
+
+[fn:25] To insert a link targeting a headline, in-buffer completion
+can be used.  Just type a star followed by a few optional letters into
+the buffer and press {{{kbd(M-TAB)}}}.  All headlines in the current
+buffer are offered as completions.
+
+[fn:26] When targeting a =NAME= keyword, the =CAPTION= keyword is
+mandatory in order to get proper numbering (see [[*Captions]]).
+
+[fn:27] The actual behavior of the search depends on the value of the
+variable ~org-link-search-must-match-exact-headline~.  If its value is
+~nil~, then a fuzzy text search is done.  If it is ~t~, then only the
+exact headline is matched, ignoring spaces and statistic cookies.  If
+the value is ~query-to-create~, then an exact headline is searched; if
+it is not found, then the user is queried to create it.
+
+[fn:28] If the headline contains a timestamp, it is removed from the
+link, which results in a wrong link---you should avoid putting
+a timestamp in the headline.
+
+[fn:29] The Org Id library must first be loaded, either through
+~org-customize~, by enabling ~id~ in ~org-modules~, or by adding
+=(require 'org-id)= in your Emacs init file.
+
+[fn:30] Note that you do not have to use this command to insert
+a link.  Links in Org are plain text, and you can type or paste them
+straight into the buffer.  By using this command, the links are
+automatically enclosed in double brackets, and you will be asked for
+the optional descriptive text.
+
+[fn:31] After insertion of a stored link, the link will be removed
+from the list of stored links.  To keep it in the list for later use,
+use a triple {{{kbd(C-u)}}} prefix argument to {{{kbd(C-c C-l)}}}, or
+configure the option ~org-link-keep-stored-after-insertion~.
+
+[fn:32] This works if a function has been defined in the ~:complete~
+property of a link in ~org-link-parameters~.
+
+[fn:33] See the variable ~org-link-use-indirect-buffer-for-internals~.
+
+[fn:34] For backward compatibility, line numbers can also follow a
+single colon.
+
+[fn:35] Of course, you can make a document that contains only long
+lists of TODO items, but this is not required.
+
+[fn:36] Changing the variable ~org-todo-keywords~ only becomes
+effective after restarting Org mode in a buffer.
+
+[fn:37] This is also true for the {{{kbd(t)}}} command in the agenda
+buffer.
+
+[fn:38] All characters are allowed except =@=, =^= and =!=, which have
+a special meaning here.
+
+[fn:39] Check also the variable ~org-fast-tag-selection-include-todo~,
+it allows you to change the TODO state through the tags interface (see
+[[*Setting Tags]]), in case you like to mingle the two concepts.  Note
+that this means you need to come up with unique keys across both sets
+of keywords.
+
+[fn:40] Org mode parses these lines only when Org mode is activated
+after visiting a file.  {{{kbd(C-c C-c)}}} with point in a line
+starting with =#+= is simply restarting Org mode for the current
+buffer.
+
+[fn:41] The corresponding in-buffer setting is: =#+STARTUP: logdone=.
+
+[fn:42] The corresponding in-buffer setting is: =#+STARTUP:
+lognotedone=.
+
+[fn:43] See the variable ~org-log-states-order-reversed~.
+
+[fn:44] Note that the =LOGBOOK= drawer is unfolded when pressing
+{{{kbd(SPC)}}} in the agenda to show an entry---use {{{kbd(C-u
+SPC)}}} to keep it folded here.
+
+[fn:45] It is possible that Org mode records two timestamps when you
+are using both ~org-log-done~ and state change logging.  However, it
+never prompts for two notes: if you have configured both, the state
+change recording note takes precedence and cancel the closing note.
+
+[fn:46] See also the option ~org-priority-start-cycle-with-default~.
+
+[fn:47] To keep subtasks out of the global TODO list, see the option
+~org-agenda-todo-list-sublevels~.
+
+[fn:48] With the exception of description lists.  But you can allow it
+by modifying ~org-list-automatic-rules~ accordingly.
+
+[fn:49] Set the variable ~org-hierarchical-checkbox-statistics~ if you
+want such cookies to count all checkboxes below the cookie, not just
+those belonging to direct children.
+
+[fn:50] {{{kbd(C-u C-c C-c)}}} on the /first/ item of a list with no
+checkbox adds checkboxes to the rest of the list.
+
+[fn:51] As with all these in-buffer settings, pressing {{{kbd(C-c
+C-c)}}} activates any changes in the line.
+
+[fn:52] This is only true if the search does not involve more complex
+tests including properties (see [[*Property Searches]]).
+
+[fn:53] To extend this default list to all tags used in all agenda
+files (see [[*Agenda Views]]), customize the variable
+~org-complete-tags-always-offer-all-agenda-tags~.
+
+[fn:54] Keys are automatically assigned to tags that have no
+configured keys.
+
+[fn:55] If more than one summary type applies to the same property,
+the parent values are computed according to the first of them.
+
+[fn:56] An age can be defined as a duration, using units defined in
+~org-duration-units~, e.g., =3d 1h=.  If any value in the column is as
+such, the summary is also expressed as a duration.
+
+[fn:57] Please note that the =COLUMNS= definition must be on a single
+line; it is wrapped here only because of formatting constraints.
+
+[fn:58] Contributed packages are not part of Emacs, but are
+distributed with the main distribution of Org---visit
+[[https://orgmode.org]].
+
+[fn:59] The Org date format is inspired by the standard ISO 8601
+date/time format.  To use an alternative format, see [[*Custom time
+format]].  The day name is optional when you type the date yourself.
+However, any date inserted or modified by Org adds that day name, for
+reading convenience.
+
+[fn:60] When working with the standard diary expression functions, you
+need to be very careful with the order of the arguments.  That order
+depends evilly on the variable ~calendar-date-style~.  For example, to
+specify a date December 12, 2005, the call might look like
+=(diary-date 12 1 2005)= or =(diary-date 1 12 2005)= or =(diary-date
+2005 12 1)=, depending on the settings.  This has been the source of
+much confusion.  Org mode users can resort to special versions of
+these functions like ~org-date~ or ~org-anniversary~.  These work just
+like the corresponding ~diary-~ functions, but with stable ISO order
+of arguments (year, month, day) wherever applicable, independent of
+the value of ~calendar-date-style~.
+
+[fn:61] See the variable ~org-read-date-prefer-future~.  You may set
+that variable to the symbol ~time~ to even make a time before now
+shift the date to tomorrow.
+
+[fn:62] If you do not need/want the calendar, configure the variable
+~org-popup-calendar-for-date-prompt~.
+
+[fn:63] You can also use the calendar command {{{kbd(.)}}} to jump to
+today's date, but if you are inserting an hour specification for your
+timestamp, {{{kbd(.)}}} will then insert a dot after the hour.  By contrast,
+{{{kbd(C-.)}}} will always jump to today's date.
+
+[fn:64] If you find this distracting, turn off the display with
+~org-read-date-display-live~.
+
+[fn:65] It will still be listed on that date after it has been marked
+as done.  If you do not like this, set the variable
+~org-agenda-skip-scheduled-if-done~.
+
+[fn:66] The =SCHEDULED= and =DEADLINE= dates are inserted on the line
+right below the headline.  Do not put any text between this line and
+the headline.
+
+[fn:67] Note the corresponding =STARTUP= options =logredeadline=,
+=lognoteredeadline=, and =nologredeadline=.
+
+[fn:68] Note the corresponding =STARTUP= options =logreschedule=,
+=lognotereschedule=, and =nologreschedule=.
+
+[fn:69] Org does not repeat inactive timestamps, however.  See
+[[*Timestamps]].
+
+[fn:70] In fact, the target state is taken from, in this sequence, the
+=REPEAT_TO_STATE= property, the variable ~org-todo-repeat-to-state~ if
+it is a string, the previous TODO state if ~org-todo-repeat-to-state~
+is ~t~, or the first state of the TODO state sequence.
+
+[fn:71] You can change this using the option ~org-log-repeat~, or the
+=STARTUP= options =logrepeat=, =lognoterepeat=, and =nologrepeat=.
+With =lognoterepeat=, you will also be prompted for a note.
+
+[fn:72] Clocking only works if all headings are indented with less
+than 30 stars.  This is a hard-coded limitation of ~lmax~ in
+~org-clock-sum~.
+
+[fn:73] To resume the clock under the assumption that you have worked
+on this task while outside Emacs, use =(setq org-clock-persist t)=.
+
+[fn:74] To add an effort estimate "on the fly", hook a function doing
+this to ~org-clock-in-prepare-hook~.
+
+[fn:75] The last reset of the task is recorded by the =LAST_REPEAT=
+property.
+
+[fn:76] See also the variable ~org-clock-mode-line-total~.
+
+[fn:77] The corresponding in-buffer setting is: =#+STARTUP:
+lognoteclock-out=.
+
+[fn:78] When using ~:step~, ~untilnow~ starts from the beginning of
+2003, not the beginning of time.
+
+[fn:79] Language terms can be set through the variable
+~org-clock-clocktable-language-setup~.
+
+[fn:80] Note that all parameters must be specified in a single
+line---the line is broken here only to fit it into the manual.
+
+[fn:81] On computers using macOS, idleness is based on actual user
+idleness, not just Emacs' idle time.  For X11, you can install
+a utility program =x11idle.c=, available in the =contrib/scripts/=
+directory of the Org Git distribution, or install the xprintidle
+package and set it to the variable ~org-clock-x11idle-program-name~ if
+you are running Debian, to get the same general treatment of idleness.
+On other systems, idle time refers to Emacs idle time only.
+
+[fn:82] Please note the pitfalls of summing hierarchical data in
+a flat list (see [[*Using Column View in the Agenda]]).
+
+[fn:83] Note the corresponding =STARTUP= options =logrefile=,
+=lognoterefile=, and =nologrefile=.
+
+[fn:84] Org used to offer four different targets for date/week tree
+capture.  Now, Org automatically translates these to use
+~file+olp+datetree~, applying the ~:time-prompt~ and ~:tree-type~
+properties.  Please rewrite your date/week-tree targets using
+~file+olp+datetree~ since the older targets are now deprecated.
+
+[fn:85] A date tree is an outline structure with years on the highest
+level, months or ISO weeks as sublevels and then dates on the lowest
+level.  Tags are allowed in the tree structure.
+
+[fn:86] When the file name is not absolute, Org assumes it is relative
+to ~org-directory~.
+
+[fn:87] If you need one of these sequences literally, escape the =%=
+with a backslash.
+
+[fn:88] If you define your own link types (see [[*Adding Hyperlink
+Types]]), any property you store with ~org-store-link-props~ can be
+accessed in capture templates in a similar way.
+
+[fn:89] This is always the other, not the user.  See the variable
+~org-link-from-user-regexp~.
+
+[fn:90] If you move entries or Org files from one directory to
+another, you may want to configure ~org-attach-id-dir~ to contain
+an absolute path.
+
+[fn:91] If the value of that variable is not a list, but a single file
+name, then the list of agenda files in maintained in that external
+file.
+
+[fn:92] When using the dispatcher, pressing {{{kbd(<)}}} before
+selecting a command actually limits the command to the current file,
+and ignores ~org-agenda-files~ until the next dispatcher command.
+
+[fn:93] For backward compatibility, you can also press {{{kbd(1)}}} to
+restrict to the current buffer.
+
+[fn:94] For backward compatibility, you can also press {{{kbd(0)}}} to
+restrict to the current region/subtree.
+
+[fn:95] For backward compatibility, the universal prefix argument
+{{{kbd(C-u)}}} causes all TODO entries to be listed before the agenda.
+This feature is deprecated, use the dedicated TODO list, or a block
+agenda instead (see [[*Block agenda]]).
+
+[fn:96] The variable ~org-anniversary~ used in the example is just
+like ~diary-anniversary~, but the argument order is always according
+to ISO and therefore independent of the value of
+~calendar-date-style~.
+
+[fn:97] You can, however, disable this by setting
+~org-agenda-search-headline-for-time~ variable to a ~nil~ value.
+
+[fn:98] Custom agenda commands can preset a filter by binding one of
+the variables ~org-agenda-tag-filter-preset~,
+~org-agenda-category-filter-preset~, ~org-agenda-effort-filter-preset~
+or ~org-agenda-regexp-filter-preset~ as an option.  This filter is
+then applied to the view and persists as a basic filter through
+refreshes and more secondary filtering.  The filter is a global
+property of the entire agenda view---in a block agenda, you should
+only set this in the global options section, not in the section of an
+individual block.
+
+[fn:99] Only tags filtering is respected here, effort filtering is
+ignored.
+
+[fn:100] You can also create persistent custom functions through
+~org-agenda-bulk-custom-functions~.
+
+[fn:101] This file is parsed for the agenda when
+~org-agenda-include-diary~ is set.
+
+[fn:102] You can provide a description for a prefix key by inserting
+a cons cell with the prefix and the description.
+
+[fn:103] /Planned/ means here that these entries have some planning
+information attached to them, like a time-stamp, a scheduled or
+a deadline string.  See ~org-agenda-entry-types~ on how to set what
+planning information is taken into account.
+
+[fn:104] For HTML you need to install Hrvoje Nikšić's =htmlize.el=
+as an Emacs package from MELPA or from 
[[https://github.com/hniksic/emacs-htmlize][Hrvoje Nikšić's repository]].
+
+[fn:105] To create PDF output, the Ghostscript ps2pdf utility must be
+installed on the system.  Selecting a PDF file also creates the
+postscript file.
+
+[fn:106] If you want to store standard views like the weekly agenda or
+the global TODO list as well, you need to define custom commands for
+them in order to be able to specify file names.
+
+[fn:107] Quoting depends on the system you use, please check the FAQ
+for examples.
+
+[fn:108] You can turn this on by default by setting the variable
+~org-pretty-entities~, or on a per-file base with the =STARTUP= option
+=entitiespretty=.
+
+[fn:109] This behavior can be disabled with =-= export setting (see
+[[*Export Settings]]).
+
+[fn:110] LaTeX is a macro system based on Donald\nbsp{}E.\nbsp{}Knuth's TeX
+system.  Many of the features described here as "LaTeX" are really
+from TeX, but for simplicity I am blurring this distinction.
+
+[fn:111] When MathJax is used, only the environments recognized by
+MathJax are processed.  When dvipng, dvisvgm, or ImageMagick suite is
+used to create images, any LaTeX environment is handled.
+
+[fn:112] These are respectively available at
+[[http://sourceforge.net/projects/dvipng/]], [[http://dvisvgm.bplaced.net/]]
+and from the ImageMagick suite.  Choose the converter by setting the
+variable ~org-preview-latex-default-process~ accordingly.
+
+[fn:113] Org mode has a method to test if point is inside such
+a fragment, see the documentation of the function
+~org-inside-LaTeX-fragment-p~.
+
+[fn:114] This works automatically for the HTML backend (it requires
+version 1.34 of the =htmlize.el= package, which you need to install).
+Fontified code chunks in LaTeX can be achieved using either the
+[[https://www.ctan.org/pkg/listings][listings]] package or the 
[[https://www.ctan.org/pkg/minted][minted]] package.  Refer to
+~org-export-latex-listings~ for details.
+
+[fn:115] Source code in code blocks may also be evaluated either
+interactively or on export.  See [[*Working with Source Code]] for more
+information on evaluating code blocks.
+
+[fn:116] Adding =-k= to =-n -r= /keeps/ the labels in the source code
+while using line numbers for the links, which might be useful to
+explain those in an Org mode example code.
+
+[fn:117] You may select a different mode with the variable
+~org-edit-fixed-width-region-mode~.
+
+[fn:118] What Emacs considers to be an image depends on
+~image-file-name-extensions~ and ~image-file-name-regexps~.
+
+[fn:119] The variable ~org-startup-with-inline-images~ can be set
+within a buffer with the =STARTUP= options =inlineimages= and
+=noinlineimages=.
+
+[fn:120] The corresponding in-buffer setting is: =#+STARTUP: fninline=
+or =#+STARTUP: nofninline=.
+
+[fn:121] The corresponding in-buffer options are =#+STARTUP: fnadjust=
+and =#+STARTUP: nofnadjust=.
+
+[fn:122] The variable ~org-export-date-timestamp-format~ defines how
+this timestamp are exported.
+
+[fn:123] DEFINITION NOT FOUND.
+
+[fn:124] At the moment, some export back-ends do not obey this
+specification.  For example, LaTeX export excludes every unnumbered
+headline from the table of contents.
+
+[fn:125] Note that ~org-link-search-must-match-exact-headline~ is
+locally bound to non-~nil~.  Therefore, ~org-link-search~ only matches
+headlines and named elements.
+
+[fn:126] Since commas separate the arguments, commas within arguments
+have to be escaped with the backslash character.  So only those
+backslash characters before a comma need escaping with another
+backslash character.
+
+[fn:127] For a less drastic behavior, consider using a select tag (see
+[[*Export Settings]]) instead.
+
+[fn:128] If =BEAMER_ENV= is set, Org export adds =B_environment= tag
+to make it visible.  The tag serves as a visual aid and has no
+semantic relevance.
+
+[fn:129] By default Org loads MathJax from [[https://cdnjs.com][cdnjs.com]] as 
recommended by
+[[http://www.mathjax.org][MathJax]].
+
+[fn:130] Please note that exported formulas are part of an HTML
+document, and that signs such as =<=, =>=, or =&= have special
+meanings.  See 
[[http://docs.mathjax.org/en/latest/tex.html#tex-and-latex-in-html-documents][MathJax
 TeX and LaTeX support]].
+
+[fn:131] See [[http://docs.mathjax.org/en/latest/tex.html#tex-extensions][TeX 
and LaTeX extensions]] in the [[http://docs.mathjax.org][MathJax manual]] to 
learn
+about extensions.
+
+[fn:132] If the classes on TODO keywords and tags lead to conflicts,
+use the variables ~org-html-todo-kwd-class-prefix~ and
+~org-html-tag-class-prefix~ to make them unique.
+
+[fn:133] This does not allow setting different bibliography compilers
+for different files.  However, "smart" LaTeX compilation systems, such
+as latexmk, can select the correct bibliography compiler.
+
+[fn:134] See 
[[http://docs.oasis-open.org/office/v1.2/OpenDocument-v1.2.html][Open Document 
Format for Office Applications
+(OpenDocument) Version 1.2]].
+
+[fn:135] See [[http://www.mathtoweb.com/cgi-bin/mathtoweb_home.pl][MathToWeb]].
+
+[fn:136] See [[http://dlmf.nist.gov/LaTeXML/]].
+
+[fn:137] 
[[http://docs.oasis-open.org/office/v1.2/OpenDocument-v1.2.html][OpenDocument-v1.2
 Specification]]
+
+[fn:138] See the =<table:table-template>= element of the
+OpenDocument-v1.2 specification.
+
+[fn:139] See the attributes =table:template-name=,
+=table:use-first-row-styles=, =table:use-last-row-styles=,
+=table:use-first-column-styles=, =table:use-last-column-styles=,
+=table:use-banding-rows-styles=, and =table:use-banding-column-styles=
+of the =<table:table>= element in the OpenDocument-v1.2 specification.
+
+[fn:140] If the publishing directory is the same as the source
+directory, =file.org= is exported as =file.org.org=, so you probably
+do not want to do this.
+
+[fn:141] The option ~org-babel-no-eval-on-ctrl-c-ctrl-c~ can be used
+to remove code evaluation from the {{{kbd(C-c C-c)}}} key binding.
+
+[fn:142] Actually, the constructs =call_<name>()= and =src_<lang>{}=
+are not evaluated when they appear in a keyword (see [[*Summary of
+In-Buffer Settings]]).
+
+[fn:143] C++ language is handled in =ob-C.el=.  Even though the
+identifier for such source blocks is =C++=, you activate it by loading
+the C language.
+
+[fn:144] D language is handled in =ob-C.el=.  Even though the
+identifier for such source blocks is =D=, you activate it by loading
+the C language.
+
+[fn:145] For noweb literate programming details, see
+http://www.cs.tufts.edu/~nr/noweb/.
+
+[fn:146] For more information, please refer to the commentary section
+in =org-tempo.el=.
+
+[fn:147] Org Indent mode also sets ~wrap-prefix~ correctly for
+indenting and wrapping long lines of headlines or text.  This minor
+mode also handles Visual Line mode and directly applied settings
+through ~word-wrap~.
+
+[fn:148] This works, but requires extra effort.  Org Indent mode is
+more convenient for most applications.
+
+[fn:149] ~org-adapt-indentation~ can also be set to ='headline-data=,
+in which case only data lines below the headline will be indented.
+
+[fn:150] Note that Org Indent mode also sets the ~wrap-prefix~
+property, such that Visual Line mode (or purely setting ~word-wrap~)
+wraps long lines, including headlines, correctly indented.
+
+[fn:151] For a server to host files, consider using a WebDAV server,
+such as [[https://nextcloud.com][Nextcloud]].  Additional help is at this 
[[https://orgmode.org/worg/org-faq.html#mobileorg_webdav][FAQ entry]].
+
+[fn:152] If Emacs is configured for safe storing of passwords, then
+configure the variable ~org-mobile-encryption-password~; please read
+the docstring of that variable.
+
+[fn:153] Symbolic links in ~org-directory~ need to have the same name
+as their targets.
+
+[fn:154] While creating the agendas, Org mode forces =ID= properties
+on all referenced entries, so that these entries can be uniquely
+identified if Org Mobile flags them for further action.  To avoid
+setting properties configure the variable
+~org-mobile-force-id-on-agenda-items~ to ~nil~.  Org mode then relies
+on outline paths, assuming they are unique.
+
+[fn:155] Checksums are stored automatically in the file
+=checksums.dat=.
+
+[fn:156] The file will be empty after this operation.
+
+[fn:157] https://www.ctan.org/pkg/comment
+
+[fn:158] By default this works only for LaTeX, HTML, and Texinfo.
+Configure the variable ~orgtbl-radio-table-templates~ to install
+templates for other modes.
+
+[fn:159] If the =TBLFM= keyword contains an odd number of dollar
+characters, this may cause problems with Font Lock in LaTeX mode.  As
+shown in the example you can fix this by adding an extra line inside
+the =comment= environment that is used to balance the dollar
+expressions.  If you are using AUCTeX with the font-latex library,
+a much better solution is to add the =comment= environment to the
+variable ~LaTeX-verbatim-environments~.
+
+[fn:160] The ~agenda*~ view is the same as ~agenda~ except that it
+only considers /appointments/, i.e., scheduled and deadline items that
+have a time specification =[h]h:mm= in their time-stamps.
+
+[fn:161] Note that, for ~org-odd-levels-only~, a level number
+corresponds to order in the hierarchy, not to the number of stars.
diff --git a/doc/misc/org.texi b/doc/misc/org.texi
deleted file mode 100644
index 8902d62..0000000
--- a/doc/misc/org.texi
+++ /dev/null
@@ -1,23148 +0,0 @@
-\input texinfo    @c -*- texinfo -*-
-@c %**start of header
-@setfilename org.info
-@settitle The Org Manual
-@documentencoding UTF-8
-@documentlanguage en
-@set txicodequoteundirected
-@set txicodequotebacktick
-@set MAINTAINERSITE @uref{https://orgmode.org,maintainers webpage}
-@set MAINTAINER Bastien Guerry
-@set MAINTAINEREMAIL @email{bzg@gnu.org}
-@set MAINTAINERCONTACT @uref{mailto:bzg@gnu.org,contact the maintainer}
-@c %**end of header
-
-@copying
-This manual is for Org version 9.4.
-
-Copyright @copyright{} 2004--2021 Free Software Foundation, Inc.
-
-@quotation
-Permission is granted to copy, distribute and/or modify this document
-under the terms of the GNU Free Documentation License, Version 1.3 or
-any later version published by the Free Software Foundation; with no
-Invariant Sections, with the Front-Cover Texts being ``A GNU Manual,''
-and with the Back-Cover Texts as in (a) below.  A copy of the license
-is included in the section entitled ``GNU Free Documentation License.''
-
-(a) The FSF's Back-Cover Text is: ``You have the freedom to copy and
-modify this GNU manual.''
-
-@end quotation
-@end copying
-
-@dircategory Emacs editing modes
-@direntry
-* Org Mode: (org).      Outline-based notes management and organizer.
-@end direntry
-
-@finalout
-@titlepage
-@title The Org Manual
-@subtitle Release 9.4
-@author The Org Mode Developers
-@page
-@vskip 0pt plus 1filll
-@insertcopying
-@end titlepage
-
-@contents
-
-@ifnottex
-@node Top
-@top The Org Manual
-
-@insertcopying
-@end ifnottex
-
-@menu
-* Introduction::                 Getting started.
-* Document Structure::           A tree works like your brain.
-* Tables::                       Pure magic for quick formatting.
-* Hyperlinks::                   Notes in context.
-* TODO Items::                   Every tree branch can be a TODO item.
-* Tags::                         Tagging headlines and matching sets of tags.
-* Properties and Columns::       Storing information about an entry.
-* Dates and Times::              Making items useful for planning.
-* Refiling and Archiving::       Moving and copying information with ease.
-* Capture and Attachments::      Dealing with external data.
-* Agenda Views::                 Collecting information into views.
-* Markup for Rich Contents::     Compose beautiful documents.
-* Exporting::                    Sharing and publishing notes.
-* Publishing::                   Create a web site of linked Org files.
-* Working with Source Code::     Export, evaluate, and tangle code blocks.
-* Miscellaneous::                All the rest which did not fit elsewhere.
-* Hacking::                      How to hack your way around.
-* History and Acknowledgments::  How Org came into being.
-* GNU Free Documentation License:: The license for this documentation.
-* Main Index::                   An index of Org's concepts and features.
-* Key Index::                    Key bindings and where they are described.
-* Command and Function Index::   Command names and some internal functions.
-* Variable Index::               Variables mentioned in the manual.
-
-@detailmenu
---- The Detailed Node Listing ---
-
-Introduction
-
-* Summary::                      Brief summary of what Org does.
-* Installation::                 Installing Org.
-* Activation::                   How to activate Org for certain buffers.
-* Feedback::                     Bug reports, ideas, patches, etc.
-* Conventions::                  Typesetting conventions used in this manual.
-
-Document Structure
-
-* Headlines::                    How to typeset Org tree headlines.
-* Visibility Cycling::           Show and hide, much simplified.
-* Motion::                       Jumping to other headlines.
-* Structure Editing::            Changing sequence and level of headlines.
-* Sparse Trees::                 Matches embedded in context.
-* Plain Lists::                  Additional structure within an entry.
-* Drawers::                      Tucking stuff away.
-* Blocks::                       Folding blocks.
-
-Visibility Cycling
-
-* Global and local cycling::     Cycling through various visibility states.
-* Initial visibility::           Setting the initial visibility state.
-* Catching invisible edits::     Preventing mistakes when editing invisible 
parts.
-
-Tables
-
-* Built-in Table Editor::        Simple tables.
-* Column Width and Alignment::   Overrule the automatic settings.
-* Column Groups::                Grouping to trigger vertical lines.
-* Orgtbl Mode::                  The table editor as minor mode.
-* The Spreadsheet::              The table editor has spreadsheet capabilities.
-* Org Plot::                     Plotting from Org tables.
-
-The Spreadsheet
-
-* References::                   How to refer to another field or range.
-* Formula syntax for Calc::      Using Calc to compute stuff.
-* Formula syntax for Lisp::      Writing formulas in Emacs Lisp.
-* Durations and time values::    How to compute durations and time values.
-* Field and range formulas::     Formula for specific (ranges of) fields.
-* Column formulas::              Formulas valid for an entire column.
-* Lookup functions::             Lookup functions for searching tables.
-* Editing and debugging formulas:: Fixing formulas.
-* Updating the table::           Recomputing all dependent fields.
-* Advanced features::            Field and column names, automatic 
recalculation...
-
-Hyperlinks
-
-* Link Format::                  How links in Org are formatted.
-* Internal Links::               Links to other places in the current file.
-* Radio Targets::                Make targets trigger links in plain text.
-* External Links::               URL-like links to the world.
-* Handling Links::               Creating, inserting and following.
-* Using Links Outside Org::      Linking from my C source code?
-* Link Abbreviations::           Shortcuts for writing complex links.
-* Search Options::               Linking to a specific location.
-* Custom Searches::              When the default search is not enough.
-
-TODO Items
-
-* TODO Basics::                  Marking and displaying TODO entries.
-* TODO Extensions::              Workflow and assignments.
-* Progress Logging::             Dates and notes for progress.
-* Priorities::                   Some things are more important than others.
-* Breaking Down Tasks::          Splitting a task into manageable pieces.
-* Checkboxes::                   Tick-off lists.
-
-TODO Extensions
-
-* Workflow states::              From TODO to DONE in steps.
-* TODO types::                   I do this, Fred does the rest.
-* Multiple sets in one file::    Mixing it all, still finding your way.
-* Fast access to TODO states::   Single letter selection of state.
-* Per-file keywords::            Different files, different requirements.
-* Faces for TODO keywords::      Highlighting states.
-* TODO dependencies::            When one task needs to wait for others.
-
-Progress Logging
-
-* Closing items::                When was this entry marked as done?
-* Tracking TODO state changes::  When did the status change?
-* Tracking your habits::         How consistent have you been?
-
-Tags
-
-* Tag Inheritance::              Tags use the tree structure of an outline.
-* Setting Tags::                 How to assign tags to a headline.
-* Tag Hierarchy::                Create a hierarchy of tags.
-* Tag Searches::                 Searching for combinations of tags.
-
-Properties and Columns
-
-* Property Syntax::              How properties are spelled out.
-* Special Properties::           Access to other Org mode features.
-* Property Searches::            Matching property values.
-* Property Inheritance::         Passing values down a tree.
-* Column View::                  Tabular viewing and editing.
-
-Column View
-
-* Defining columns::             The COLUMNS format property.
-* Using column view::            How to create and use column view.
-* Capturing column view::        A dynamic block for column view.
-
-Defining columns
-
-* Scope of column definitions::  Where defined, where valid?
-* Column attributes::            Appearance and content of a column.
-
-Dates and Times
-
-* Timestamps::                   Assigning a time to a tree entry.
-* Creating Timestamps::          Commands to insert timestamps.
-* Deadlines and Scheduling::     Planning your work.
-* Clocking Work Time::           Tracking how long you spend on a task.
-* Effort Estimates::             Planning work effort in advance.
-* Timers::                       Notes with a running timer.
-
-Creating Timestamps
-
-* The date/time prompt::         How Org mode helps you enter dates and times.
-* Custom time format::           Making dates look different.
-
-Deadlines and Scheduling
-
-* Inserting deadline/schedule::  Planning items.
-* Repeated tasks::               Items that show up again and again.
-
-Clocking Work Time
-
-* Clocking commands::            Starting and stopping a clock.
-* The clock table::              Detailed reports.
-* Resolving idle time::          Resolving time when you've been idle.
-
-Refiling and Archiving
-
-* Refile and Copy::              Moving/copying a tree from one place to 
another.
-* Archiving::                    What to do with finished products.
-
-Archiving
-
-* Moving subtrees::              Moving a tree to an archive file.
-* Internal archiving::           Switch off a tree but keep it in the file.
-
-Capture and Attachments
-
-* Capture::                      Capturing new stuff.
-* Attachments::                  Attach files to outlines.
-* RSS Feeds::                    Getting input from RSS feeds.
-
-Capture
-
-* Setting up capture::           Where notes will be stored.
-* Using capture::                Commands to invoke and terminate capture.
-* Capture templates::            Define the outline of different note types.
-
-Capture templates
-
-* Template elements::            What is needed for a complete template entry.
-* Template expansion::           Filling in information about time and context.
-* Templates in contexts::        Only show a template in a specific context.
-
-Attachments
-
-* Attachment defaults and dispatcher:: How to access attachment commands
-* Attachment options::           Configuring the attachment system
-* Attachment links::             Hyperlink access to attachments
-* Automatic version-control with Git:: Everything safely stored away
-* Attach from Dired::            Using dired to select an attachment
-
-Agenda Views
-
-* Agenda Files::                 Files being searched for agenda information.
-* Agenda Dispatcher::            Keyboard access to agenda views.
-* Built-in Agenda Views::        What is available out of the box?
-* Presentation and Sorting::     How agenda items are prepared for display.
-* Agenda Commands::              Remote editing of Org trees.
-* Custom Agenda Views::          Defining special searches and views.
-* Exporting Agenda Views::       Writing a view to a file.
-* Agenda Column View::           Using column view for collected entries.
-
-Built-in Agenda Views
-
-* Weekly/daily agenda::          The calendar page with current tasks.
-* Global TODO list::             All unfinished action items.
-* Matching tags and properties:: Structured information with fine-tuned search.
-* Search view::                  Find entries by searching for text.
-* Stuck projects::               Find projects you need to review.
-
-Presentation and Sorting
-
-* Categories::                   Not all tasks are equal.
-* Time-of-day specifications::   How the agenda knows the time.
-* Sorting of agenda items::      The order of things.
-* Filtering/limiting agenda items:: Dynamically narrow the agenda.
-
-Custom Agenda Views
-
-* Storing searches::             Type once, use often.
-* Block agenda::                 All the stuff you need in a single buffer.
-* Setting options::              Changing the rules.
-
-Markup for Rich Contents
-
-* Paragraphs::                   The basic unit of text.
-* Emphasis and Monospace::       Bold, italic, etc.
-* Subscripts and Superscripts::  Simple syntax for raising/lowering text.
-* Special Symbols::              Greek letters and other symbols.
-* Embedded @LaTeX{}::            LaTeX can be freely used inside Org documents.
-* Literal Examples::             Source code examples with special formatting.
-* Images::                       Display an image.
-* Captions::                     Describe tables, images...
-* Horizontal Rules::             Make a line.
-* Creating Footnotes::           Edit and read footnotes.
-
-Embedded @LaTeX{}
-
-* @LaTeX{} fragments::           Complex formulas made easy.
-* Previewing @LaTeX{} fragments:: What will this snippet look like?
-* CD@LaTeX{} mode::              Speed up entering of formulas.
-
-Exporting
-
-* The Export Dispatcher::        The main interface.
-* Export Settings::              Common export settings.
-* Table of Contents::            The if and where of the table of contents.
-* Include Files::                Include additional files into a document.
-* Macro Replacement::            Use macros to create templates.
-* Comment Lines::                What will not be exported.
-* ASCII/Latin-1/UTF-8 export::   Exporting to flat files with encoding.
-* Beamer Export::                Producing presentations and slides.
-* HTML Export::                  Exporting to HTML.
-* @LaTeX{} Export::              Exporting to @LaTeX{} and processing to PDF.
-* Markdown Export::              Exporting to Markdown.
-* OpenDocument Text Export::     Exporting to OpenDocument Text.
-* Org Export::                   Exporting to Org.
-* Texinfo Export::               Exporting to Texinfo.
-* iCalendar Export::             Exporting to iCalendar.
-* Other Built-in Back-ends::     Exporting to a man page.
-* Advanced Export Configuration:: Fine-tuning the export output.
-* Export in Foreign Buffers::    Author tables and lists in Org syntax.
-
-Beamer Export
-
-* Beamer export commands::       For creating Beamer documents.
-* Beamer specific export settings:: For customizing Beamer export.
-* Frames and Blocks in Beamer::  For composing Beamer slides.
-* Beamer specific syntax::       For using in Org documents.
-* Editing support::              Editing support.
-* A Beamer example::             A complete presentation.
-
-HTML Export
-
-* HTML export commands::         Invoking HTML export.
-* HTML specific export settings:: Settings for HTML export.
-* HTML doctypes::                Exporting various (X)HTML flavors.
-* HTML preamble and postamble::  Inserting preamble and postamble.
-* Quoting HTML tags::            Using direct HTML in Org files.
-* Headlines in HTML export::     Formatting headlines.
-* Links in HTML export::         Inserting and formatting links.
-* Tables in HTML export::        How to modify the formatting of tables.
-* Images in HTML export::        How to insert figures into HTML output.
-* Math formatting in HTML export:: Beautiful math also on the web.
-* Text areas in HTML export::    An alternate way to show an example.
-* CSS support::                  Changing the appearance of the output.
-* JavaScript support::           Info and folding in a web browser.
-
-@LaTeX{} Export
-
-* @LaTeX{}/PDF export commands:: For producing @LaTeX{} and PDF documents.
-* @LaTeX{} specific export settings:: Unique to this @LaTeX{} back-end.
-* @LaTeX{} header and sectioning:: Setting up the export file structure.
-* Quoting @LaTeX{} code::        Incorporating literal @LaTeX{} code.
-* Tables in @LaTeX{} export::    Options for exporting tables to @LaTeX{}.
-* Images in @LaTeX{} export::    How to insert figures into @LaTeX{} output.
-* Plain lists in @LaTeX{} export:: Attributes specific to lists.
-* Source blocks in @LaTeX{} export:: Attributes specific to source code blocks.
-* Example blocks in @LaTeX{} export:: Attributes specific to example blocks.
-* Special blocks in @LaTeX{} export:: Attributes specific to special blocks.
-* Horizontal rules in @LaTeX{} export:: Attributes specific to horizontal 
rules.
-
-OpenDocument Text Export
-
-* Pre-requisites for ODT export:: Required packages.
-* ODT export commands::          Invoking export.
-* ODT specific export settings:: Configuration options.
-* Extending ODT export::         Producing DOC, PDF files.
-* Applying custom styles::       Styling the output.
-* Links in ODT export::          Handling and formatting links.
-* Tables in ODT export::         Org tables conversions.
-* Images in ODT export::         Inserting images.
-* Math formatting in ODT export:: Formatting @LaTeX{} fragments.
-* Labels and captions in ODT export:: Rendering objects.
-* Literal examples in ODT export:: For source code and example blocks.
-* Advanced topics in ODT export:: For power users.
-
-Math formatting in ODT export
-
-* @LaTeX{} math snippets::       Embedding in @LaTeX{} format.
-* MathML and OpenDocument formula files:: Embedding in native format.
-
-Texinfo Export
-
-* Texinfo export commands::      Invoking commands.
-* Texinfo specific export settings:: Setting the environment.
-* Texinfo file header::          Generating the header.
-* Texinfo title and copyright page:: Creating preamble pages.
-* Info directory file::          Installing a manual in Info file hierarchy.
-* Headings and sectioning structure:: Building document structure.
-* Indices::                      Creating indices.
-* Quoting Texinfo code::         Incorporating literal Texinfo code.
-* Plain lists in Texinfo export:: List attributes.
-* Tables in Texinfo export::     Table attributes.
-* Images in Texinfo export::     Image attributes.
-* Quotations in Texinfo export:: Quote block attributes.
-* Special blocks in Texinfo export:: Special block attributes.
-* A Texinfo example::            Processing Org to Texinfo.
-
-Export in Foreign Buffers
-
-* Bare HTML::                    Exporting HTML without CSS, Javascript, etc.
-
-Publishing
-
-* Configuration::                Defining projects.
-* Uploading Files::              How to get files up on the server.
-* Sample Configuration::         Example projects.
-* Triggering Publication::       Publication commands.
-
-Configuration
-
-* Project alist::                The central configuration variable.
-* Sources and destinations::     From here to there.
-* Selecting files::              What files are part of the project?
-* Publishing action::            Setting the function doing the publishing.
-* Publishing options::           Tweaking HTML/@LaTeX{} export.
-* Publishing links::             Which links keep working after publishing?
-* Site map::                     Generating a list of all pages.
-* Generating an index::          An index that reaches across pages.
-
-Sample Configuration
-
-* Simple example::               One-component publishing.
-* Complex example::              A multi-component publishing example.
-
-Working with Source Code
-
-* Features Overview::            Enjoy the versatility of source blocks.
-* Structure of Code Blocks::     Code block syntax described.
-* Using Header Arguments::       Different ways to set header arguments.
-* Environment of a Code Block::  Arguments, sessions, working directory...
-* Evaluating Code Blocks::       Place results of evaluation in the Org buffer.
-* Results of Evaluation::        Choosing a results type, post-processing...
-* Exporting Code Blocks::        Export contents and/or results.
-* Extracting Source Code::       Create pure source code files.
-* Languages::                    List of supported code block languages.
-* Editing Source Code::          Language major-mode editing.
-* Noweb Reference Syntax::       Literate programming in Org mode.
-* Library of Babel::             Use and contribute to a library of useful 
code blocks.
-* Key bindings and Useful Functions:: Work quickly with code blocks.
-* Batch Execution::              Call functions from the command line.
-
-Miscellaneous
-
-* Completion::                   @kbd{M-@key{TAB}} guesses completions.
-* Structure Templates::          Quick insertion of structural elements.
-* Speed Keys::                   Electric commands at the beginning of a 
headline.
-* Clean View::                   Getting rid of leading stars in the outline.
-* Execute commands in the active region:: Execute commands on multiple items 
in Org or agenda view.
-* Dynamic Headline Numbering::   Display and update outline numbering.
-* The Very Busy @kbd{C-c C-c} Key:: When in doubt, press @kbd{C-c C-c}.
-* In-buffer Settings::           Overview of keywords.
-* Org Syntax::                   Formal description of Org's syntax.
-* Documentation Access::         Read documentation about current syntax.
-* Escape Character::             Prevent Org from interpreting your writing.
-* Code Evaluation Security::     Org files evaluate in-line code.
-* Interaction::                  With other Emacs packages.
-* TTY Keys::                     Using Org on a tty.
-* Protocols::                    External access to Emacs and Org.
-* Org Crypt::                    Encrypting Org files.
-* Org Mobile::                   Viewing and capture on a mobile device.
-
-Clean View
-
-* Org Indent Mode::
-* Hard indentation::
-
-Interaction
-
-* Cooperation::                  Packages Org cooperates with.
-* Conflicts::                    Packages that lead to conflicts.
-
-Protocols
-
-* The @code{store-link} protocol:: Store a link, push URL to kill-ring.
-* The @code{capture} protocol::  Fill a buffer with external information.
-* The @code{open-source} protocol:: Edit published contents.
-
-Org Mobile
-
-* Setting up the staging area::  For the mobile device.
-* Pushing to the mobile application:: Uploading Org files and agendas.
-* Pulling from the mobile application:: Integrating captured and flagged items.
-
-Hacking
-
-* Hooks: Hooks (2).              How to reach into Org's internals.
-* Add-on Packages::              Available extensions.
-* Adding Hyperlink Types::       New custom link types.
-* Adding Export Back-ends::      How to write new export back-ends.
-* Tables in Arbitrary Syntax::   Orgtbl for LaTeX and other programs.
-* Dynamic Blocks::               Automatically filled blocks.
-* Special Agenda Views::         Customized views.
-* Speeding Up Your Agendas::     Tips on how to speed up your agendas.
-* Extracting Agenda Information:: Post-processing agenda information.
-* Using the Property API::       Writing programs that use entry properties.
-* Using the Mapping API::        Mapping over all or selected entries.
-
-Tables in Arbitrary Syntax
-
-* Radio tables::                 Sending and receiving radio tables.
-* A @LaTeX{} example::           Step by step, almost a tutorial.
-* Translator functions::         Copy and modify.
-
-@end detailmenu
-@end menu
-
-@node Introduction
-@chapter Introduction
-
-@cindex introduction
-
-@menu
-* Summary::                      Brief summary of what Org does.
-* Installation::                 Installing Org.
-* Activation::                   How to activate Org for certain buffers.
-* Feedback::                     Bug reports, ideas, patches, etc.
-* Conventions::                  Typesetting conventions used in this manual.
-@end menu
-
-@node Summary
-@section Summary
-
-@cindex summary
-
-Org is a mode for keeping notes, maintaining TODO lists, and project
-planning with a fast and effective plain-text markup language.  It
-also is an authoring system with unique support for literate
-programming and reproducible research.
-
-Org is implemented on top of Outline mode, which makes it possible to
-keep the content of large files well structured.  Visibility cycling
-and structure editing help to work with the tree.  Tables are easily
-created with a built-in table editor.  Plain text URL-like links
-connect to websites, emails, Usenet messages, BBDB entries, and any
-files related to the projects.
-
-Org develops organizational tasks around notes files that contain
-lists or information about projects as plain text.  Project planning
-and task management make use of metadata which is part of an outline
-node.  Based on this data, specific entries can be extracted in
-queries and create dynamic @emph{agenda views} that also integrate the
-Emacs calendar and diary.  Org can be used to implement many different
-project planning schemes, such as David Allen's GTD system.
-
-Org files can serve as a single source authoring system with export to
-many different formats such as HTML, @LaTeX{}, Open Document, and
-Markdown.  New export backends can be derived from existing ones, or
-defined from scratch.
-
-Org files can include source code blocks, which makes Org uniquely
-suited for authoring technical documents with code examples.  Org
-source code blocks are fully functional; they can be evaluated in
-place and their results can be captured in the file.  This makes it
-possible to create a single file reproducible research compendium.
-
-Org keeps simple things simple.  When first fired up, it should feel
-like a straightforward, easy to use outliner.  Complexity is not
-imposed, but a large amount of functionality is available when needed.
-Org is a toolbox.  Many users actually run only a---very
-personal---fraction of Org's capabilities, and know that there is more
-whenever they need it.
-
-All of this is achieved with strictly plain text files, the most
-portable and future-proof file format.  Org runs in Emacs.  Emacs is
-one of the most widely ported programs, so that Org mode is available
-on every major platform.
-
-@cindex FAQ
-There is a website for Org which provides links to the newest version
-of Org, as well as additional information, frequently asked questions
-(FAQ), links to tutorials, etc.  This page is located at
-@uref{https://orgmode.org}.
-
-@cindex print edition
-An earlier version (7.3) of this manual is available as a 
@uref{http://www.network-theory.co.uk/org/manual/, paperback
-book from Network Theory Ltd.}.
-
-@node Installation
-@section Installation
-
-@cindex installation
-
-Org is included in all recent distributions of GNU Emacs, so you
-probably do not need to install it.  Most users will simply activate
-Org and begin exploring its many features.
-
-If, for one reason or another, you want to install Org on top of this
-pre-packaged version, there are three ways to do it:
-
-@itemize
-@item
-by using the Emacs package system;
-@item
-by downloading Org as an archive; or
-@item
-by using Org's git repository.
-@end itemize
-
-We @strong{strongly recommend} sticking to a single installation method.
-
-@anchor{Using Emacs packaging system}
-@subheading Using Emacs packaging system
-
-Recent Emacs distributions include a packaging system which lets you
-install Elisp libraries.  You can install Org from the ``package menu'',
-with @kbd{M-x list-packages}.  See @ref{Package Menu,Package Menu,,emacs,}.
-
-@quotation Important
-You need to do this in a session where no @samp{.org} file has been
-visited, i.e., where no Org built-in function have been loaded.
-Otherwise autoload Org functions will mess up the installation.
-
-@end quotation
-
-If you want to use Org's package repository, check out the 
@uref{https://orgmode.org/elpa.html, Org ELPA
-page}.
-
-@anchor{Downloading Org as an archive}
-@subheading Downloading Org as an archive
-
-You can download Org latest release from @uref{https://orgmode.org/, Org's 
website}.  In this case,
-make sure you set the load path correctly in your Emacs init file:
-
-@lisp
-(add-to-list 'load-path "~/path/to/orgdir/lisp")
-@end lisp
-
-The downloaded archive contains contributed libraries that are not
-included in Emacs.  If you want to use them, add the @samp{contrib/}
-directory to your load path:
-
-@lisp
-(add-to-list 'load-path "~/path/to/orgdir/contrib/lisp" t)
-@end lisp
-
-Optionally, you can compile the files and/or install them in your
-system.  Run @samp{make help} to list compilation and installation options.
-
-@anchor{Using Org's git repository}
-@subheading Using Org's git repository
-
-You can clone Org's repository and install Org like this:
-
-@example
-$ cd ~/src/
-$ git clone https://code.orgmode.org/bzg/org-mode.git
-$ cd org-mode/
-$ make autoloads
-@end example
-
-Note that in this case, @samp{make autoloads} is mandatory: it defines
-Org's version in @samp{org-version.el} and Org's autoloads in
-@samp{org-loaddefs.el}.
-
-Remember to add the correct load path as described in the method
-above.
-
-You can also compile with @samp{make}, generate the documentation with
-@samp{make doc}, create a local configuration with @samp{make config} and
-install Org with @samp{make install}.  Please run @samp{make help} to get the
-list of compilation/installation options.
-
-For more detailed explanations on Org's build system, please check the
-Org Build System page on 
@uref{https://orgmode.org/worg/dev/org-build-system.html, Worg}.
-
-@node Activation
-@section Activation
-
-@cindex activation
-@cindex autoload
-@cindex ELPA
-@cindex global key bindings
-@cindex key bindings, global
-
-Org mode buffers need Font Lock to be turned on: this is the default
-in Emacs@footnote{If you do not use Font Lock globally turn it on in Org buffer
-with @samp{(add-hook 'org-mode-hook 'turn-on-font-lock)}.}.
-
-There are compatibility issues between Org mode and some other Elisp
-packages (see @ref{Conflicts}).  Please take the
-time to check the list.
-
-@findex org-agenda
-@findex org-capture
-@findex org-store-link
-For a better experience, the three Org commands @code{org-store-link},
-@code{org-capture} and @code{org-agenda} ought to be accessible anywhere in
-Emacs, not just in Org buffers.  To that effect, you need to bind them
-to globally available keys, like the ones reserved for users (see
-@ref{Key Binding Conventions,,,elisp,}).  Here are suggested bindings,
-please modify the keys to your own liking.
-
-@lisp
-(global-set-key (kbd "C-c l") 'org-store-link)
-(global-set-key (kbd "C-c a") 'org-agenda)
-(global-set-key (kbd "C-c c") 'org-capture)
-@end lisp
-
-@cindex Org mode, turning on
-Files with the @samp{.org} extension use Org mode by default.  To turn on
-Org mode in a file that does not have the extension @samp{.org}, make the
-first line of a file look like this:
-
-@example
-MY PROJECTS    -*- mode: org; -*-
-@end example
-
-
-@vindex org-insert-mode-line-in-empty-file
-@noindent
-which selects Org mode for this buffer no matter what the file's name
-is.  See also the variable @code{org-insert-mode-line-in-empty-file}.
-
-Many commands in Org work on the region if the region is @emph{active}.  To
-make use of this, you need to have Transient Mark mode turned on,
-which is the default.  If you do not like it, you can create an active
-region by using the mouse to select a region, or pressing
-@kbd{C-@key{SPC}} twice before moving point.
-
-@node Feedback
-@section Feedback
-
-@cindex feedback
-@cindex bug reports
-@cindex reporting a bug
-@cindex maintainer
-@cindex author
-
-If you find problems with Org, or if you have questions, remarks, or
-ideas about it, please send an email to the Org mailing list
-@email{emacs-orgmode@@gnu.org}.  You can subscribe to the list 
@uref{https://lists.gnu.org/mailman/listinfo/emacs-orgmode, from this
-web page}.  If you are not a member of the mailing list, your mail will
-be passed to the list after a moderator has approved it@footnote{Please 
consider subscribing to the mailing list in order to
-minimize the work the mailing list moderators have to do.}.  We ask
-you to read and respect the 
@uref{https://www.gnu.org/philosophy/kind-communication.html, GNU Kind 
Communications Guidelines} when
-sending messages on this mailing list.
-
-@findex org-version
-@findex org-submit-bug-report
-For bug reports, please first try to reproduce the bug with the latest
-version of Org available---if you are running an outdated version, it
-is quite possible that the bug has been fixed already.  If the bug
-persists, prepare a report and provide as much information as
-possible, including the version information of Emacs (@kbd{M-x emacs-version}) 
and Org (@kbd{M-x org-version}), as well as
-the Org related setup in the Emacs init file.  The easiest way to do
-this is to use the command
-
-@example
-M-x org-submit-bug-report <RET>
-@end example
-
-
-@noindent
-which puts all this information into an Emacs mail buffer so that you
-only need to add your description.  If you are not sending the Email
-from within Emacs, please copy and paste the content into your Email
-program.
-
-Sometimes you might face a problem due to an error in your Emacs or
-Org mode setup.  Before reporting a bug, it is very helpful to start
-Emacs with minimal customizations and reproduce the problem.  Doing so
-often helps you determine if the problem is with your customization or
-with Org mode itself.  You can start a typical minimal session with
-a command like the example below.
-
-@example
-$ emacs -Q -l /path/to/minimal-org.el
-@end example
-
-
-However if you are using Org mode as distributed with Emacs, a minimal
-setup is not necessary.  In that case it is sufficient to start Emacs
-as @samp{emacs -Q}.  The @samp{minimal-org.el} setup file can have contents as
-shown below.
-
-@lisp
-;;; Minimal setup to load latest `org-mode'.
-
-;; Activate debugging.
-(setq debug-on-error t
-      debug-on-signal nil
-      debug-on-quit nil)
-
-;; Add latest Org mode to load path.
-(add-to-list 'load-path (expand-file-name "/path/to/org-mode/lisp"))
-(add-to-list 'load-path (expand-file-name "/path/to/org-mode/contrib/lisp" t))
-@end lisp
-
-If an error occurs, a ``backtrace'' can be very useful---see below on
-how to create one.  Often a small example file helps, along with clear
-information about:
-
-@enumerate
-@item
-What exactly did you do?
-@item
-What did you expect to happen?
-@item
-What happened instead?
-@end enumerate
-
-Thank you for helping to improve this program.
-
-@anchor{How to create a useful backtrace}
-@subheading How to create a useful backtrace
-
-@cindex backtrace of an error
-If working with Org produces an error with a message you do not
-understand, you may have hit a bug.  The best way to report this is by
-providing, in addition to what was mentioned above, a backtrace.  This
-is information from the built-in debugger about where and how the
-error occurred.  Here is how to produce a useful backtrace:
-
-@enumerate
-@item
-Reload uncompiled versions of all Org mode Lisp files.  The
-backtrace contains much more information if it is produced with
-uncompiled code.  To do this, use
-
-@example
-C-u M-x org-reload <RET>
-@end example
-
-
-@noindent
-or, from the menu: Org @arrow{} Refresh/Reload @arrow{} Reload Org uncompiled.
-
-@item
-Then, activate the debugger:
-
-@example
-M-x toggle-debug-on-error <RET>
-@end example
-
-
-@noindent
-or, from the menu: Options @arrow{} Enter Debugger on Error.
-
-@item
-Do whatever you have to do to hit the error.  Do not forget to
-document the steps you take.
-
-@item
-When you hit the error, a @samp{*Backtrace*} buffer appears on the
-screen.  Save this buffer to a file---for example using @kbd{C-x C-w}---and 
attach it to your bug report.
-@end enumerate
-
-@node Conventions
-@section Typesetting Conventions Used in this Manual
-
-
-
-@anchor{TODO keywords tags properties etc}
-@subheading TODO keywords, tags, properties, etc.
-
-Org uses various syntactical elements: TODO keywords, tags, property
-names, keywords, blocks, etc.  In this manual we use the following
-conventions:
-
-@table @asis
-@item @samp{TODO}
-@itemx @samp{WAITING}
-TODO keywords are written with all capitals, even if they are
-user-defined.
-
-@item @samp{boss}
-@itemx @samp{ARCHIVE}
-Tags are case-sensitive.  User-defined tags are written in
-lowercase; built-in tags with special meaning are written as they
-should appear in the document, usually with all capitals.
-
-@item @samp{Release}
-@itemx @samp{PRIORITY}
-User-defined properties are capitalized; built-in properties with
-special meaning are written with all capitals.
-
-@item @samp{TITLE}
-@itemx @samp{BEGIN} @dots{} @samp{END}
-Keywords and blocks are written in uppercase to enhance their
-readability, but you can use lowercase in your Org files.
-@end table
-
-@anchor{Key bindings and commands}
-@subheading Key bindings and commands
-
-The manual lists both the keys and the corresponding commands for
-accessing a functionality.  Org mode often uses the same key for
-different functions, depending on context.  The command that is bound
-to such keys has a generic name, like @code{org-metaright}.  In the manual
-we will, wherever possible, give the function that is internally
-called by the generic command.  For example, in the chapter on
-document structure, @kbd{M-@key{RIGHT}} will be listed to call
-@code{org-do-demote}, while in the chapter on tables, it will be listed to
-call @code{org-table-move-column-right}.
-
-@node Document Structure
-@chapter Document Structure
-
-@cindex document structure
-@cindex structure of document
-Org is an outliner.  Outlines allow a document to be organized in
-a hierarchical structure, which, least for me, is the best
-representation of notes and thoughts.  An overview of this structure
-is achieved by folding, i.e., hiding large parts of the document to
-show only the general document structure and the parts currently being
-worked on.  Org greatly simplifies the use of outlines by compressing
-the entire show and hide functionalities into a single command,
-@code{org-cycle}, which is bound to the @kbd{@key{TAB}} key.
-
-@menu
-* Headlines::                    How to typeset Org tree headlines.
-* Visibility Cycling::           Show and hide, much simplified.
-* Motion::                       Jumping to other headlines.
-* Structure Editing::            Changing sequence and level of headlines.
-* Sparse Trees::                 Matches embedded in context.
-* Plain Lists::                  Additional structure within an entry.
-* Drawers::                      Tucking stuff away.
-* Blocks::                       Folding blocks.
-@end menu
-
-@node Headlines
-@section Headlines
-
-@cindex headlines
-@cindex outline tree
-@vindex org-special-ctrl-a/e
-@vindex org-special-ctrl-k
-@vindex org-ctrl-k-protect-subtree
-
-Headlines define the structure of an outline tree.  Org headlines
-start on the left margin@footnote{See the variables 
@code{org-special-ctrl-a/e}, @code{org-special-ctrl-k},
-and @code{org-ctrl-k-protect-subtree} to configure special behavior of
-@kbd{C-a}, @kbd{C-e}, and @kbd{C-k} in headlines.  Note
-also that clocking only works with headings indented less than 30
-stars.} with one or more stars followed by
-a space.  For example:
-
-@example
-* Top level headline
-** Second level
-*** Third level
-    some text
-*** Third level
-    more text
-* Another top level headline
-@end example
-
-@vindex org-footnote-section
-The name defined in @code{org-footnote-section} is reserved.  Do not use it
-as a title for your own headings.
-
-Some people find the many stars too noisy and would prefer an outline
-that has whitespace followed by a single star as headline starters.
-This can be achieved using a Org Indent minor mode.  See @ref{Clean View} for 
more information.
-
-Headlines are not numbered.  However, you may want to dynamically
-number some, or all, of them.  See @ref{Dynamic Headline Numbering}.
-
-@vindex org-cycle-separator-lines
-An empty line after the end of a subtree is considered part of it and
-is hidden when the subtree is folded.  However, if you leave at least
-two empty lines, one empty line remains visible after folding the
-subtree, in order to structure the collapsed view.  See the variable
-@code{org-cycle-separator-lines} to modify this behavior.
-
-@node Visibility Cycling
-@section Visibility Cycling
-
-@cindex cycling, visibility
-@cindex visibility cycling
-@cindex trees, visibility
-@cindex show hidden text
-@cindex hide text
-
-@menu
-* Global and local cycling::     Cycling through various visibility states.
-* Initial visibility::           Setting the initial visibility state.
-* Catching invisible edits::     Preventing mistakes when editing invisible 
parts.
-@end menu
-
-@node Global and local cycling
-@subsection Global and local cycling
-
-@cindex subtree visibility states
-@cindex subtree cycling
-@cindex folded, subtree visibility state
-@cindex children, subtree visibility state
-@cindex subtree, subtree visibility state
-
-Outlines make it possible to hide parts of the text in the buffer.
-Org uses just two commands, bound to @kbd{@key{TAB}} and
-@kbd{S-@key{TAB}} to change the visibility in the buffer.
-
-@table @asis
-@item @kbd{@key{TAB}} (@code{org-cycle})
-@kindex TAB
-@findex org-cycle
-@emph{Subtree cycling}: Rotate current subtree among the states
-
-@example
-,-> FOLDED -> CHILDREN -> SUBTREE --.
-'-----------------------------------'
-@end example
-
-@vindex org-cycle-emulate-tab
-Point must be on a headline for this to work@footnote{See, however, the option 
@code{org-cycle-emulate-tab}.}.
-
-@item @kbd{S-@key{TAB}} (@code{org-global-cycle})
-@itemx @kbd{C-u @key{TAB}}
-@cindex global visibility states
-@cindex global cycling
-@cindex overview, global visibility state
-@cindex contents, global visibility state
-@cindex show all, global visibility state
-@kindex C-u TAB
-@kindex S-TAB
-@findex org-global-cycle
-@emph{Global cycling}: Rotate the entire buffer among the states
-
-@example
-,-> OVERVIEW -> CONTENTS -> SHOW ALL --.
-'--------------------------------------'
-@end example
-
-When @kbd{S-@key{TAB}} is called with a numeric prefix argument
-@var{N}, view contents only up to headlines of level
-@var{N}.
-
-Note that inside tables (see @ref{Tables}), @kbd{S-@key{TAB}} jumps to the
-previous field instead.
-
-@vindex org-cycle-global-at-bob
-You can run global cycling using @kbd{@key{TAB}} only if point is at
-the very beginning of the buffer, but not on a headline, and
-@code{org-cycle-global-at-bob} is set to a non-@code{nil} value.
-
-@item @kbd{C-u C-u @key{TAB}} (@code{org-set-startup-visibility})
-@cindex startup visibility
-@kindex C-u C-u TAB
-@findex org-set-startup-visibility
-Switch back to the startup visibility of the buffer (see @ref{Initial 
visibility}).
-
-@item @kbd{C-u C-u C-u @key{TAB}} (@code{outline-show-all})
-@cindex show all, command
-@kindex C-u C-u C-u TAB
-@findex outline-show-all
-Show all, including drawers.
-
-@item @kbd{C-c C-r} (@code{org-reveal})
-@cindex revealing context
-@kindex C-c C-r
-@findex org-reveal
-Reveal context around point, showing the current entry, the
-following heading and the hierarchy above.  It is useful for working
-near a location that has been exposed by a sparse tree command (see
-@ref{Sparse Trees}) or an agenda command (see @ref{Agenda Commands}).  With a 
prefix argument, show, on each level, all sibling
-headings.  With a double prefix argument, also show the entire
-subtree of the parent.
-
-@item @kbd{C-c C-k} (@code{outline-show-branches})
-@cindex show branches, command
-@kindex C-c C-k
-@findex outline-show-branches
-Expose all the headings of the subtree, but not their bodies.
-
-@item @kbd{C-c @key{TAB}} (@code{outline-show-children})
-@cindex show children, command
-@kindex C-c TAB
-@findex outline-show-children
-Expose all direct children of the subtree.  With a numeric prefix
-argument @var{N}, expose all children down to level
-@var{N}.
-
-@item @kbd{C-c C-x b} (@code{org-tree-to-indirect-buffer})
-@kindex C-c C-x b
-@findex org-tree-to-indirect-buffer
-Show the current subtree in an indirect buffer@footnote{The indirect buffer 
contains the entire buffer, but is narrowed
-to the current tree.  Editing the indirect buffer also changes the
-original buffer, but without affecting visibility in that buffer.  For
-more information about indirect buffers, see @ref{Indirect Buffers,GNU Emacs 
Manual,,emacs,}.}.  With
-a numeric prefix argument @var{N}, go up to level @var{N}
-and then take that tree.  If @var{N} is negative then go up
-that many levels.  With a @kbd{C-u} prefix, do not remove the
-previously used indirect buffer.
-
-@item @kbd{C-c C-x v} (@code{org-copy-visible})
-@kindex C-c C-x v
-@findex org-copy-visible
-Copy the @emph{visible} text in the region into the kill ring.
-@end table
-
-@node Initial visibility
-@subsection Initial visibility
-
-@vindex org-startup-folded
-When Emacs first visits an Org file, the global state is set to
-@code{showeverything}, i.e., all file content is visible@footnote{When 
@code{org-agenda-inhibit-startup} is non-@code{nil}, Org does not
-honor the default visibility state when first opening a file for the
-agenda (see @ref{Speeding Up Your Agendas}).}.  This can
-be configured through the variable @code{org-startup-folded}, or on
-a per-file basis by adding one of the following lines anywhere in the
-buffer:
-
-@cindex @samp{STARTUP}, keyword
-@example
-#+STARTUP: overview
-#+STARTUP: content
-#+STARTUP: showall
-#+STARTUP: showeverything
-@end example
-
-@cindex @samp{VISIBILITY}, property
-Furthermore, any entries with a @samp{VISIBILITY} property (see 
@ref{Properties and Columns}) get their visibility adapted accordingly.  
Allowed values
-for this property are @samp{folded}, @samp{children}, @samp{content}, and 
@samp{all}.
-
-@table @asis
-@item @kbd{C-u C-u @key{TAB}} (@code{org-set-startup-visibility})
-@kindex C-u C-u TAB
-@findex org-set-startup-visibility
-Switch back to the startup visibility of the buffer, i.e., whatever
-is requested by startup options and @samp{VISIBILITY} properties in
-individual entries.
-@end table
-
-@node Catching invisible edits
-@subsection Catching invisible edits
-
-@cindex edits, catching invisible
-
-@vindex org-catch-invisible-edits
-Sometimes you may inadvertently edit an invisible part of the buffer
-and be confused on what has been edited and how to undo the mistake.
-Setting @code{org-catch-invisible-edits} to non-@code{nil} helps preventing
-this.  See the docstring of this option on how Org should catch
-invisible edits and process them.
-
-@node Motion
-@section Motion
-
-@cindex motion, between headlines
-@cindex jumping, to headlines
-@cindex headline navigation
-
-The following commands jump to other headlines in the buffer.
-
-@table @asis
-@item @kbd{C-c C-n} (@code{org-next-visible-heading})
-@kindex C-c C-n
-@findex org-next-visible-heading
-Next heading.
-
-@item @kbd{C-c C-p} (@code{org-previous-visible-heading})
-@kindex C-c C-p
-@findex org-previous-visible-heading
-Previous heading.
-
-@item @kbd{C-c C-f} (@code{org-forward-heading-same-level})
-@kindex C-c C-f
-@findex org-forward-heading-same-level
-Next heading same level.
-
-@item @kbd{C-c C-b} (@code{org-backward-heading-same-level})
-@kindex C-c C-b
-@findex org-backward-heading-same-level
-Previous heading same level.
-
-@item @kbd{C-c C-u} (@code{outline-up-heading})
-@kindex C-c C-u
-@findex outline-up-heading
-Backward to higher level heading.
-
-@item @kbd{C-c C-j} (@code{org-goto})
-@kindex C-c C-j
-@findex org-goto
-@vindex org-goto-auto-isearch
-Jump to a different place without changing the current outline
-visibility.  Shows the document structure in a temporary buffer,
-where you can use the following keys to find your destination:
-
-@multitable @columnfractions 0.3 0.7
-@item @kbd{@key{TAB}}
-@tab Cycle visibility.
-@item @kbd{@key{DOWN}} / @kbd{@key{UP}}
-@tab Next/previous visible headline.
-@item @kbd{@key{RET}}
-@tab Select this location.
-@item @kbd{/}
-@tab Do a Sparse-tree search
-@end multitable
-
-@noindent
-The following keys work if you turn off @code{org-goto-auto-isearch}
-
-@multitable @columnfractions 0.3 0.7
-@item @kbd{n} / @kbd{p}
-@tab Next/previous visible headline.
-@item @kbd{f} / @kbd{b}
-@tab Next/previous headline same level.
-@item @kbd{u}
-@tab One level up.
-@item @kbd{0} @dots{} @kbd{9}
-@tab Digit argument.
-@item @kbd{q}
-@tab Quit.
-@end multitable
-
-@vindex org-goto-interface
-@noindent
-See also the variable @code{org-goto-interface}.
-@end table
-
-@node Structure Editing
-@section Structure Editing
-
-@cindex structure editing
-@cindex headline, promotion and demotion
-@cindex promotion, of subtrees
-@cindex demotion, of subtrees
-@cindex subtree, cut and paste
-@cindex pasting, of subtrees
-@cindex cutting, of subtrees
-@cindex copying, of subtrees
-@cindex sorting, of subtrees
-@cindex subtrees, cut and paste
-
-@table @asis
-@item @kbd{M-@key{RET}} (@code{org-meta-return})
-@kindex M-RET
-@findex org-meta-return
-@vindex org-M-RET-may-split-line
-Insert a new heading, item or row.
-
-If the command is used at the @emph{beginning} of a line, and if there is
-a heading or a plain list item (see @ref{Plain Lists}) at point, the new
-heading/item is created @emph{before} the current line.  When used at the
-beginning of a regular line of text, turn that line into a heading.
-
-When this command is used in the middle of a line, the line is split
-and the rest of the line becomes the new item or headline.  If you
-do not want the line to be split, customize
-@code{org-M-RET-may-split-line}.
-
-Calling the command with a @kbd{C-u} prefix unconditionally
-inserts a new heading at the end of the current subtree, thus
-preserving its contents.  With a double @kbd{C-u C-u} prefix,
-the new heading is created at the end of the parent subtree instead.
-
-@item @kbd{C-@key{RET}} (@code{org-insert-heading-respect-content})
-@kindex C-RET
-@findex org-insert-heading-respect-content
-Insert a new heading at the end of the current subtree.
-
-@item @kbd{M-S-@key{RET}} (@code{org-insert-todo-heading})
-@kindex M-S-RET
-@findex org-insert-todo-heading
-@vindex org-treat-insert-todo-heading-as-state-change
-Insert new TODO entry with same level as current heading.  See also
-the variable @code{org-treat-insert-todo-heading-as-state-change}.
-
-@item @kbd{C-S-@key{RET}} (@code{org-insert-todo-heading-respect-content})
-@kindex C-S-RET
-@findex org-insert-todo-heading-respect-content
-Insert new TODO entry with same level as current heading.  Like
-@kbd{C-@key{RET}}, the new headline is inserted after the current
-subtree.
-
-@item @kbd{@key{TAB}} (@code{org-cycle})
-@kindex TAB
-@findex org-cycle
-In a new entry with no text yet, the first @kbd{@key{TAB}} demotes
-the entry to become a child of the previous one.  The next
-@kbd{@key{TAB}} makes it a parent, and so on, all the way to top
-level.  Yet another @kbd{@key{TAB}}, and you are back to the initial
-level.
-
-@item @kbd{M-@key{LEFT}} (@code{org-do-promote})
-@itemx @kbd{M-@key{RIGHT}} (@code{org-do-demote})
-@kindex M-LEFT
-@findex org-do-promote
-@kindex M-RIGHT
-@findex org-do-demote
-Promote or demote current heading by one level.
-
-@cindex region, active
-@cindex active region
-@cindex transient mark mode
-When there is an active region---i.e., when Transient Mark mode is
-active---promotion and demotion work on all headlines in the region.
-To select a region of headlines, it is best to place both point and
-mark at the beginning of a line, mark at the beginning of the first
-headline, and point at the line just after the last headline to
-change.
-
-@item @kbd{M-S-@key{LEFT}} (@code{org-promote-subtree})
-@kindex M-S-LEFT
-@findex org-promote-subtree
-Promote the current subtree by one level.
-
-@item @kbd{M-S-@key{RIGHT}} (@code{org-demote-subtree})
-@kindex M-S-RIGHT
-@findex org-demote-subtree
-Demote the current subtree by one level.
-
-@item @kbd{M-@key{UP}} (@code{org-move-subtree-up})
-@kindex M-UP
-@findex org-move-subtree-up
-Move subtree up, i.e., swap with previous subtree of same level.
-
-@item @kbd{M-@key{DOWN}} (@code{org-move-subtree-down})
-@kindex M-DOWN
-@findex org-move-subtree-down
-Move subtree down, i.e., swap with next subtree of same level.
-
-@item @kbd{C-c @@} (@code{org-mark-subtree})
-@kindex C-c @@
-@findex org-mark-subtree
-Mark the subtree at point.  Hitting repeatedly marks subsequent
-subtrees of the same level as the marked subtree.
-
-@item @kbd{C-c C-x C-w} (@code{org-cut-subtree})
-@kindex C-c C-x C-w
-@findex org-cut-subtree
-Kill subtree, i.e., remove it from buffer but save in kill ring.
-With a numeric prefix argument N, kill N sequential subtrees.
-
-@item @kbd{C-c C-x M-w} (@code{org-copy-subtree})
-@kindex C-c C-x M-w
-@findex org-copy-subtree
-Copy subtree to kill ring.  With a numeric prefix argument N, copy
-the N sequential subtrees.
-
-@item @kbd{C-c C-x C-y} (@code{org-paste-subtree})
-@kindex C-c C-x C-y
-@findex org-paste-subtree
-Yank subtree from kill ring.  This does modify the level of the
-subtree to make sure the tree fits in nicely at the yank position.
-The yank level can also be specified with a numeric prefix argument,
-or by yanking after a headline marker like @samp{****}.
-
-@item @kbd{C-y} (@code{org-yank})
-@kindex C-y
-@findex org-yank
-@vindex org-yank-adjusted-subtrees
-@vindex org-yank-folded-subtrees
-Depending on the variables @code{org-yank-adjusted-subtrees} and
-@code{org-yank-folded-subtrees}, Org's internal @code{yank} command pastes
-subtrees folded and in a clever way, using the same command as
-@kbd{C-c C-x C-y}.  With the default settings, no level
-adjustment takes place, but the yanked tree is folded unless doing
-so would swallow text previously visible.  Any prefix argument to
-this command forces a normal @code{yank} to be executed, with the prefix
-passed along.  A good way to force a normal yank is @kbd{C-u C-y}.  If you use 
@code{yank-pop} after a yank, it yanks previous kill
-items plainly, without adjustment and folding.
-
-@item @kbd{C-c C-x c} (@code{org-clone-subtree-with-time-shift})
-@kindex C-c C-x c
-@findex org-clone-subtree-with-time-shift
-Clone a subtree by making a number of sibling copies of it.  You are
-prompted for the number of copies to make, and you can also specify
-if any timestamps in the entry should be shifted.  This can be
-useful, for example, to create a number of tasks related to a series
-of lectures to prepare.  For more details, see the docstring of the
-command @code{org-clone-subtree-with-time-shift}.
-
-@item @kbd{C-c C-w} (@code{org-refile})
-@kindex C-c C-w
-@findex org-refile
-Refile entry or region to a different location.  See @ref{Refile and Copy}.
-
-@item @kbd{C-c ^} (@code{org-sort})
-@kindex C-c ^
-@findex org-sort
-Sort same-level entries.  When there is an active region, all
-entries in the region are sorted.  Otherwise the children of the
-current headline are sorted.  The command prompts for the sorting
-method, which can be alphabetically, numerically, by time---first
-timestamp with active preferred, creation time, scheduled time,
-deadline time---by priority, by TODO keyword---in the sequence the
-keywords have been defined in the setup---or by the value of
-a property.  Reverse sorting is possible as well.  You can also
-supply your own function to extract the sorting key.  With
-a @kbd{C-u} prefix, sorting is case-sensitive.
-
-@item @kbd{C-x n s} (@code{org-narrow-to-subtree})
-@kindex C-x n s
-@findex org-narrow-to-subtree
-Narrow buffer to current subtree.
-
-@item @kbd{C-x n b} (@code{org-narrow-to-block})
-@kindex C-x n b
-@findex org-narrow-to-block
-Narrow buffer to current block.
-
-@item @kbd{C-x n w} (@code{widen})
-@kindex C-x n w
-@findex widen
-Widen buffer to remove narrowing.
-
-@item @kbd{C-c *} (@code{org-toggle-heading})
-@kindex C-c *
-@findex org-toggle-heading
-Turn a normal line or plain list item into a headline---so that it
-becomes a subheading at its location.  Also turn a headline into
-a normal line by removing the stars.  If there is an active region,
-turn all lines in the region into headlines.  If the first line in
-the region was an item, turn only the item lines into headlines.
-Finally, if the first line is a headline, remove the stars from all
-headlines in the region.
-@end table
-
-Note that when point is inside a table (see @ref{Tables}), the Meta-Cursor
-keys have different functionality.
-
-@node Sparse Trees
-@section Sparse Trees
-
-@cindex sparse trees
-@cindex trees, sparse
-@cindex folding, sparse trees
-@cindex occur, command
-
-@vindex org-show-context-detail
-An important feature of Org mode is the ability to construct @emph{sparse
-trees} for selected information in an outline tree, so that the entire
-document is folded as much as possible, but the selected information
-is made visible along with the headline structure above it@footnote{See also 
the variable @code{org-show-context-detail} to decide how
-much context is shown around each match.}.
-Just try it out and you will see immediately how it works.
-
-Org mode contains several commands creating such trees, all these
-commands can be accessed through a dispatcher:
-
-@table @asis
-@item @kbd{C-c /} (@code{org-sparse-tree})
-@kindex C-c /
-@findex org-sparse-tree
-This prompts for an extra key to select a sparse-tree creating
-command.
-
-@item @kbd{C-c / r} or @kbd{C-c / /} (@code{org-occur})
-@kindex C-c / r
-@kindex C-c / /
-@findex org-occur
-@vindex org-remove-highlights-with-change
-Prompts for a regexp and shows a sparse tree with all matches.  If
-the match is in a headline, the headline is made visible.  If the
-match is in the body of an entry, headline and body are made
-visible.  In order to provide minimal context, also the full
-hierarchy of headlines above the match is shown, as well as the
-headline following the match.  Each match is also highlighted; the
-highlights disappear when the buffer is changed by an editing
-command, or by pressing @kbd{C-c C-c}@footnote{This depends on the option 
@code{org-remove-highlights-with-change}.}.  When called with
-a @kbd{C-u} prefix argument, previous highlights are kept, so
-several calls to this command can be stacked.
-
-@item @kbd{M-g n} or @kbd{M-g M-n} (@code{next-error})
-@kindex M-g n
-@kindex M-g M-n
-@findex next-error
-Jump to the next sparse tree match in this buffer.
-
-@item @kbd{M-g p} or @kbd{M-g M-p} (@code{previous-error})
-@kindex M-g p
-@kindex M-g M-p
-@findex previous-error
-Jump to the previous sparse tree match in this buffer.
-@end table
-
-@vindex org-agenda-custom-commands
-For frequently used sparse trees of specific search strings, you can
-use the variable @code{org-agenda-custom-commands} to define fast keyboard
-access to specific sparse trees.  These commands will then be
-accessible through the agenda dispatcher (see @ref{Agenda Dispatcher}).
-For example:
-
-@lisp
-(setq org-agenda-custom-commands
-      '(("f" occur-tree "FIXME")))
-@end lisp
-
-@noindent
-defines the key @kbd{f} as a shortcut for creating a sparse tree
-matching the string @samp{FIXME}.
-
-The other sparse tree commands select headings based on TODO keywords,
-tags, or properties and are discussed later in this manual.
-
-@kindex C-c C-e C-v
-@cindex printing sparse trees
-@cindex visible text, printing
-To print a sparse tree, you can use the Emacs command
-@code{ps-print-buffer-with-faces} which does not print invisible parts of
-the document.  Or you can use the command @kbd{C-c C-e C-v} to
-export only the visible part of the document and print the resulting
-file.
-
-@node Plain Lists
-@section Plain Lists
-
-@cindex plain lists
-@cindex lists, plain
-@cindex lists, ordered
-@cindex ordered lists
-
-Within an entry of the outline tree, hand-formatted lists can provide
-additional structure.  They also provide a way to create lists of
-checkboxes (see @ref{Checkboxes}).  Org supports editing such lists, and
-every exporter (see @ref{Exporting}) can parse and format them.
-
-Org knows ordered lists, unordered lists, and description lists.
-
-@itemize
-@item
-@emph{Unordered} list items start with @samp{-}, @samp{+}, or 
@samp{*}@footnote{When using @samp{*} as a bullet, lines must be indented so 
that they
-are not interpreted as headlines.  Also, when you are hiding leading
-stars to get a clean outline view, plain list items starting with
-a star may be hard to distinguish from true headlines.  In short: even
-though @samp{*} is supported, it may be better to not use it for plain list
-items.} as bullets.
-
-@item
-@vindex org-plain-list-ordered-item-terminator
-@vindex org-alphabetical-lists
-@emph{Ordered} list items start with a numeral followed by either
-a period or a right parenthesis@footnote{You can filter out any of them by 
configuring
-@code{org-plain-list-ordered-item-terminator}.}, such as @samp{1.} or 
@samp{1)}@footnote{You can also get @samp{a.}, @samp{A.}, @samp{a)} and 
@samp{A)} by configuring
-@code{org-list-allow-alphabetical}.  To minimize confusion with normal
-text, those are limited to one character only.  Beyond that limit,
-bullets automatically become numbers.}
-If you want a list to start with a different value---e.g.,
-20---start the text of the item with @samp{[@@20]}@footnote{If there's a 
checkbox in the item, the cookie must be put
-@emph{before} the checkbox.  If you have activated alphabetical lists, you
-can also use counters like @samp{[@@b]}.}.  Those
-constructs can be used in any item of the list in order to enforce
-a particular numbering.
-
-@item
-@emph{Description} list items are unordered list items, and contain the
-separator @samp{::} to distinguish the description @emph{term} from the
-description.
-@end itemize
-
-Items belonging to the same list must have the same indentation on the
-first line.  In particular, if an ordered list reaches number @samp{10.},
-then the 2-digit numbers must be written left-aligned with the other
-numbers in the list.  An item ends before the next line that is less
-or equally indented than its bullet/number.
-
-A list ends whenever every item has ended, which means before any line
-less or equally indented than items at top level.  It also ends before
-two blank lines.  In that case, all items are closed.  Here is an
-example:
-
-@example
-* Lord of the Rings
-My favorite scenes are (in this order)
-1. The attack of the Rohirrim
-2. Eowyn's fight with the witch king
-   + this was already my favorite scene in the book
-   + I really like Miranda Otto.
-3. Peter Jackson being shot by Legolas
-   - on DVD only
-   He makes a really funny face when it happens.
-But in the end, no individual scenes matter but the film as a whole.
-Important actors in this film are:
-- Elijah Wood :: He plays Frodo
-- Sean Astin :: He plays Sam, Frodo's friend.  I still remember him
-     very well from his role as Mikey Walsh in /The Goonies/.
-@end example
-
-Org supports these lists by tuning filling and wrapping commands to
-deal with them correctly, and by exporting them properly (see
-@ref{Exporting}).  Since indentation is what governs the structure of these
-lists, many structural constructs like @samp{#+BEGIN_} blocks can be
-indented to signal that they belong to a particular item.
-
-@vindex org-list-demote-modify-bullet
-@vindex org-list-indent-offset
-If you find that using a different bullet for a sub-list---than that
-used for the current list-level---improves readability, customize the
-variable @code{org-list-demote-modify-bullet}.  To get a greater difference
-of indentation between items and theirs sub-items, customize
-@code{org-list-indent-offset}.
-
-@vindex org-list-automatic-rules
-The following commands act on items when point is in the first line of
-an item---the line with the bullet or number.  Some of them imply the
-application of automatic rules to keep list structure intact.  If some
-of these actions get in your way, configure @code{org-list-automatic-rules}
-to disable them individually.
-
-@table @asis
-@item @kbd{@key{TAB}} (@code{org-cycle})
-@cindex cycling, in plain lists
-@kindex TAB
-@findex org-cycle
-@vindex org-cycle-include-plain-lists
-Items can be folded just like headline levels.  Normally this works
-only if point is on a plain list item.  For more details, see the
-variable @code{org-cycle-include-plain-lists}.  If this variable is set
-to @code{integrate}, plain list items are treated like low-level
-headlines.  The level of an item is then given by the indentation of
-the bullet/number.  Items are always subordinate to real headlines,
-however; the hierarchies remain completely separated.  In a new item
-with no text yet, the first @kbd{@key{TAB}} demotes the item to
-become a child of the previous one.  Subsequent @kbd{@key{TAB}}s move
-the item to meaningful levels in the list and eventually get it back
-to its initial position.
-
-@item @kbd{M-@key{RET}} (@code{org-insert-heading})
-@kindex M-RET
-@findex org-insert-heading
-@vindex org-M-RET-may-split-line
-Insert new item at current level.  With a prefix argument, force
-a new heading (see @ref{Structure Editing}).  If this command is used in
-the middle of an item, that item is @emph{split} in two, and the second
-part becomes the new item@footnote{If you do not want the item to be split, 
customize the
-variable @code{org-M-RET-may-split-line}.}.  If this command is executed
-@emph{before item's body}, the new item is created @emph{before} the current
-one.
-
-@item @kbd{M-S-@key{RET}}
-@kindex M-S-RET
-Insert a new item with a checkbox (see @ref{Checkboxes}).
-
-@item @kbd{S-@key{UP}}
-@itemx @kbd{S-@key{DOWN}}
-@kindex S-UP
-@kindex S-DOWN
-@cindex shift-selection-mode
-@vindex org-support-shift-select
-@vindex org-list-use-circular-motion
-Jump to the previous/next item in the current list, but only if
-@code{org-support-shift-select} is off@footnote{If you want to cycle around 
items that way, you may customize
-@code{org-list-use-circular-motion}.}.  If not, you can still use
-paragraph jumping commands like @kbd{C-@key{UP}} and
-@kbd{C-@key{DOWN}} to quite similar effect.
-
-@item @kbd{M-@key{UP}}
-@itemx @kbd{M-@key{DOWN}}
-@kindex M-UP
-@kindex M-DOWN
-Move the item including subitems up/down@footnote{See 
@code{org-list-use-circular-motion} for a cyclic behavior.}, i.e., swap with
-previous/next item of same indentation.  If the list is ordered,
-renumbering is automatic.
-
-@item @kbd{M-@key{LEFT}}
-@itemx @kbd{M-@key{RIGHT}}
-@kindex M-LEFT
-@kindex M-RIGHT
-Decrease/increase the indentation of an item, leaving children
-alone.
-
-@item @kbd{M-S-@key{LEFT}}
-@itemx @kbd{M-S-@key{RIGHT}}
-@kindex M-S-LEFT
-@kindex M-S-RIGHT
-Decrease/increase the indentation of the item, including subitems.
-Initially, the item tree is selected based on current indentation.
-When these commands are executed several times in direct succession,
-the initially selected region is used, even if the new indentation
-would imply a different hierarchy.  To use the new hierarchy, break
-the command chain by moving point.
-
-As a special case, using this command on the very first item of
-a list moves the whole list.  This behavior can be disabled by
-configuring @code{org-list-automatic-rules}.  The global indentation of
-a list has no influence on the text @emph{after} the list.
-
-@item @kbd{C-c C-c}
-@kindex C-c C-c
-If there is a checkbox (see @ref{Checkboxes}) in the item line, toggle
-the state of the checkbox.  In any case, verify bullets and
-indentation consistency in the whole list.
-
-@item @kbd{C-c -}
-@kindex C-c -
-@vindex org-plain-list-ordered-item-terminator
-Cycle the entire list level through the different itemize/enumerate
-bullets (@samp{-}, @samp{+}, @samp{*}, @samp{1.}, @samp{1)}) or a subset of 
them, depending
-on @code{org-plain-list-ordered-item-terminator}, the type of list, and
-its indentation.  With a numeric prefix argument N, select the Nth
-bullet from this list.  If there is an active region when calling
-this, all lines are converted to list items.  With a prefix
-argument, the selected text is changed into a single item.  If the
-first line already was a list item, any item marker is removed from
-the list.  Finally, even without an active region, a normal line is
-converted into a list item.
-
-@item @kbd{C-c *}
-@kindex C-c *
-Turn a plain list item into a headline---so that it becomes
-a subheading at its location.  See @ref{Structure Editing}, for
-a detailed explanation.
-
-@item @kbd{C-c C-*}
-@kindex C-c C-*
-Turn the whole plain list into a subtree of the current heading.
-Checkboxes (see @ref{Checkboxes}) become @samp{TODO}, respectively @samp{DONE},
-keywords when unchecked, respectively checked.
-
-@item @kbd{S-@key{LEFT}}
-@itemx @kbd{S-@key{RIGHT}}
-@vindex org-support-shift-select
-@kindex S-LEFT
-@kindex S-RIGHT
-This command also cycles bullet styles when point is in on the
-bullet or anywhere in an item line, details depending on
-@code{org-support-shift-select}.
-
-@item @kbd{C-c ^}
-@kindex C-c ^
-@cindex sorting, of plain list
-Sort the plain list.  Prompt for the sorting method: numerically,
-alphabetically, by time, or by custom function.
-@end table
-
-@node Drawers
-@section Drawers
-
-@cindex drawers
-@cindex visibility cycling, drawers
-
-Sometimes you want to keep information associated with an entry, but
-you normally do not want to see it.  For this, Org mode has @emph{drawers}.
-They can contain anything but a headline and another drawer.  Drawers
-look like this:
-
-@example
-** This is a headline
-Still outside the drawer
-:DRAWERNAME:
-This is inside the drawer.
-:END:
-After the drawer.
-@end example
-
-@kindex C-c C-x d
-@findex org-insert-drawer
-You can interactively insert a drawer at point by calling
-@code{org-insert-drawer}, which is bound to @kbd{C-c C-x d}.  With an
-active region, this command puts the region inside the drawer.  With
-a prefix argument, this command calls @code{org-insert-property-drawer},
-which creates a @samp{PROPERTIES} drawer right below the current headline.
-Org mode uses this special drawer for storing properties (see
-@ref{Properties and Columns}).  You cannot use it for anything else.
-
-Completion over drawer keywords is also possible using
-@kbd{M-@key{TAB}}@footnote{Many desktops intercept @kbd{M-@key{TAB}} to switch 
windows.
-Use @kbd{C-M-i} or @kbd{@key{ESC} @key{TAB}} instead.}.
-
-Visibility cycling (see @ref{Visibility Cycling}) on the headline hides and
-shows the entry, but keep the drawer collapsed to a single line.  In
-order to look inside the drawer, you need to move point to the drawer
-line and press @kbd{@key{TAB}} there.
-
-You can also arrange for state change notes (see @ref{Tracking TODO state 
changes}) and clock times (see @ref{Clocking Work Time}) to be stored in
-a @samp{LOGBOOK} drawer.  If you want to store a quick note there, in
-a similar way to state changes, use
-
-@table @asis
-@item @kbd{C-c C-z}
-@kindex C-c C-z
-Add a time-stamped note to the @samp{LOGBOOK} drawer.
-@end table
-
-@node Blocks
-@section Blocks
-
-@vindex org-hide-block-startup
-@cindex blocks, folding
-
-Org mode uses @samp{#+BEGIN} @dots{} @samp{#+END} blocks for various purposes 
from
-including source code examples (see @ref{Literal Examples}) to capturing
-time logging information (see @ref{Clocking Work Time}).  These blocks can
-be folded and unfolded by pressing @kbd{@key{TAB}} in the @samp{#+BEGIN}
-line.  You can also get all blocks folded at startup by configuring
-the variable @code{org-hide-block-startup} or on a per-file basis by using
-
-@cindex STARTUP, keyword
-@example
-#+STARTUP: hideblocks
-#+STARTUP: nohideblocks
-@end example
-
-@node Tables
-@chapter Tables
-
-@cindex tables
-@cindex editing tables
-
-Org comes with a fast and intuitive table editor.  Spreadsheet-like
-calculations are supported using the Emacs Calc package (see @ref{Top,GNU Emacs
-Calculator Manual,,calc,}).
-
-@menu
-* Built-in Table Editor::        Simple tables.
-* Column Width and Alignment::   Overrule the automatic settings.
-* Column Groups::                Grouping to trigger vertical lines.
-* Orgtbl Mode::                  The table editor as minor mode.
-* The Spreadsheet::              The table editor has spreadsheet capabilities.
-* Org Plot::                     Plotting from Org tables.
-@end menu
-
-@node Built-in Table Editor
-@section Built-in Table Editor
-
-@cindex table editor, built-in
-
-@cindex header lines, in tables
-@cindex horizontal rule, in tables
-@cindex row separator, in tables
-@cindex table syntax
-Org makes it easy to format tables in plain ASCII@.  Any line with @samp{|}
-as the first non-whitespace character is considered part of a table.
-@samp{|} is also the column separator@footnote{To insert a vertical bar into a 
table field, use @samp{\vert} or,
-inside a word @samp{abc\vert@{@}def}.}.  Moreover, a line starting
-with @samp{|-} is a horizontal rule.  It separates rows explicitly.  Rows
-before the first horizontal rule are header lines.  A table might look
-like this:
-
-@example
-| Name  | Phone | Age |
-|-------+-------+-----|
-| Peter |  1234 |  17 |
-| Anna  |  4321 |  25 |
-@end example
-
-A table is re-aligned automatically each time you press
-@kbd{@key{TAB}}, @kbd{@key{RET}} or @kbd{C-c C-c} inside the table.
-@kbd{@key{TAB}} also moves to the next field---@kbd{@key{RET}} to the
-next row---and creates new table rows at the end of the table or
-before horizontal lines.  The indentation of the table is set by the
-first line.  Horizontal rules are automatically expanded on every
-re-align to span the whole table width.  So, to create the above
-table, you would only type
-
-@example
-|Name|Phone|Age|
-|-
-@end example
-
-@noindent
-and then press @kbd{@key{TAB}} to align the table and start filling in
-fields.  Even faster would be to type @samp{|Name|Phone|Age} followed by
-@kbd{C-c @key{RET}}.
-
-When typing text into a field, Org treats @kbd{DEL},
-@kbd{Backspace}, and all character keys in a special way, so that
-inserting and deleting avoids shifting other fields.  Also, when
-typing @emph{immediately} after point was moved into a new field with
-@kbd{@key{TAB}}, @kbd{S-@key{TAB}} or @kbd{@key{RET}}, the field is
-automatically made blank.  If this behavior is too unpredictable for
-you, configure the option @code{org-table-auto-blank-field}.
-
-@anchor{Creation and conversion}
-@subheading Creation and conversion
-
-@table @asis
-@item @kbd{C-c |} (@code{org-table-create-or-convert-from-region})
-@kindex C-c |
-@findex org-table-create-or-convert-from-region
-Convert the active region to table.  If every line contains at least
-one @kbd{@key{TAB}} character, the function assumes that the material
-is tab separated.  If every line contains a comma, comma-separated
-values (CSV) are assumed.  If not, lines are split at whitespace
-into fields.  You can use a prefix argument to force a specific
-separator: @kbd{C-u} forces CSV, @kbd{C-u C-u} forces
-@kbd{@key{TAB}}, @kbd{C-u C-u C-u} prompts for a regular
-expression to match the separator, and a numeric argument
-N indicates that at least N consecutive spaces, or alternatively
-a @kbd{@key{TAB}} will be the separator.
-
-If there is no active region, this command creates an empty Org
-table.  But it is easier just to start typing, like @kbd{| N a m e | P h o n e 
| A g e @key{RET} | - @key{TAB}}.
-@end table
-
-@anchor{Re-aligning and field motion}
-@subheading Re-aligning and field motion
-
-@table @asis
-@item @kbd{C-c C-c} (@code{org-table-align})
-@kindex C-c C-c
-@findex org-table-align
-Re-align the table without moving point.
-
-@item @kbd{@key{TAB}} (@code{org-table-next-field})
-@kindex TAB
-@findex org-table-next-field
-Re-align the table, move to the next field.  Creates a new row if
-necessary.
-
-@item @kbd{C-c @key{SPC}} (@code{org-table-blank-field})
-@kindex C-c SPC
-@findex org-table-blank-field
-Blank the field at point.
-
-@item @kbd{S-@key{TAB}} (@code{org-table-previous-field})
-@kindex S-TAB
-@findex org-table-previous-field
-Re-align, move to previous field.
-
-@item @kbd{@key{RET}} (@code{org-table-next-row})
-@kindex RET
-@findex org-table-next-row
-Re-align the table and move down to next row.  Creates a new row if
-necessary.  At the beginning or end of a line, @kbd{@key{RET}} still
-inserts a new line, so it can be used to split a table.
-
-@item @kbd{M-a} (@code{org-table-beginning-of-field})
-@kindex M-a
-@findex org-table-beginning-of-field
-Move to beginning of the current table field, or on to the previous
-field.
-
-@item @kbd{M-e} (@code{org-table-end-of-field})
-@kindex M-e
-@findex org-table-end-of-field
-Move to end of the current table field, or on to the next field.
-@end table
-
-@anchor{Column and row editing}
-@subheading Column and row editing
-
-@table @asis
-@item @kbd{M-@key{LEFT}} (@code{org-table-move-column-left})
-@kindex M-LEFT
-@findex org-table-move-column-left
-Move the current column left.
-
-@item @kbd{M-@key{RIGHT}} (@code{org-table-move-column-right})
-@kindex M-RIGHT
-@findex org-table-move-column-right
-Move the current column right.
-
-@item @kbd{M-S-@key{LEFT}} (@code{org-table-delete-column})
-@kindex M-S-LEFT
-@findex org-table-delete-column
-Kill the current column.
-
-@item @kbd{M-S-@key{RIGHT}} (@code{org-table-insert-column})
-@kindex M-S-RIGHT
-@findex org-table-insert-column
-Insert a new column at point position.  Move the recent column and
-all cells to the right of this column to the right.
-
-@item @kbd{M-@key{UP}} (@code{org-table-move-row-up})
-@kindex M-UP
-@findex org-table-move-row-up
-Move the current row up.
-
-@item @kbd{M-@key{DOWN}} (@code{org-table-move-row-down})
-@kindex M-DOWN
-@findex org-table-move-row-down
-Move the current row down.
-
-@item @kbd{M-S-@key{UP}} (@code{org-table-kill-row})
-@kindex M-S-UP
-@findex org-table-kill-row
-Kill the current row or horizontal line.
-
-@item @kbd{S-@key{UP}} (@code{org-table-move-cell-up})
-@kindex S-UP
-@findex org-table-move-cell-up
-Move cell up by swapping with adjacent cell.
-
-@item @kbd{S-@key{DOWN}} (@code{org-table-move-cell-down})
-@kindex S-DOWN
-@findex org-table-move-cell-down
-Move cell down by swapping with adjacent cell.
-
-@item @kbd{S-@key{LEFT}} (@code{org-table-move-cell-left})
-@kindex S-LEFT
-@findex org-table-move-cell-left
-Move cell left by swapping with adjacent cell.
-
-@item @kbd{S-@key{RIGHT}} (@code{org-table-move-cell-right})
-@kindex S-RIGHT
-@findex org-table-move-cell-right
-Move cell right by swapping with adjacent cell.
-
-@item @kbd{M-S-@key{DOWN}} (@code{org-table-insert-row})
-@kindex M-S-DOWN
-@findex org-table-insert-row
-Insert a new row above the current row.  With a prefix argument, the
-line is created below the current one.
-
-@item @kbd{C-c -} (@code{org-table-insert-hline})
-@kindex C-c -
-@findex org-table-insert-hline
-Insert a horizontal line below current row.  With a prefix argument,
-the line is created above the current line.
-
-@item @kbd{C-c @key{RET}} (@code{org-table-hline-and-move})
-@kindex C-c RET
-@findex org-table-hline-and-move
-Insert a horizontal line below current row, and move point into the
-row below that line.
-
-@item @kbd{C-c ^} (@code{org-table-sort-lines})
-@kindex C-c ^
-@findex org-table-sort-lines
-Sort the table lines in the region.  The position of point indicates
-the column to be used for sorting, and the range of lines is the
-range between the nearest horizontal separator lines, or the entire
-table.  If point is before the first column, you are prompted for
-the sorting column.  If there is an active region, the mark
-specifies the first line and the sorting column, while point should
-be in the last line to be included into the sorting.  The command
-prompts for the sorting type, alphabetically, numerically, or by
-time.  You can sort in normal or reverse order.  You can also supply
-your own key extraction and comparison functions.  When called with
-a prefix argument, alphabetic sorting is case-sensitive.
-@end table
-
-@anchor{Regions}
-@subheading Regions
-
-@table @asis
-@item @kbd{C-c C-x M-w} (@code{org-table-copy-region})
-@kindex C-c C-x M-w
-@findex org-table-copy-region
-Copy a rectangular region from a table to a special clipboard.
-Point and mark determine edge fields of the rectangle.  If there is
-no active region, copy just the current field.  The process ignores
-horizontal separator lines.
-
-@item @kbd{C-c C-x C-w} (@code{org-table-cut-region})
-@kindex C-c C-x C-w
-@findex org-table-cut-region
-Copy a rectangular region from a table to a special clipboard, and
-blank all fields in the rectangle.  So this is the ``cut'' operation.
-
-@item @kbd{C-c C-x C-y} (@code{org-table-paste-rectangle})
-@kindex C-c C-x C-y
-@findex org-table-paste-rectangle
-Paste a rectangular region into a table.  The upper left corner ends
-up in the current field.  All involved fields are overwritten.  If
-the rectangle does not fit into the present table, the table is
-enlarged as needed.  The process ignores horizontal separator lines.
-
-@item @kbd{M-@key{RET}} (@code{org-table-wrap-region})
-@kindex M-RET
-@findex org-table-wrap-region
-Split the current field at point position and move the rest to the
-line below.  If there is an active region, and both point and mark
-are in the same column, the text in the column is wrapped to minimum
-width for the given number of lines.  A numeric prefix argument may
-be used to change the number of desired lines.  If there is no
-region, but you specify a prefix argument, the current field is made
-blank, and the content is appended to the field above.
-@end table
-
-@anchor{Calculations}
-@subheading Calculations
-
-@cindex formula, in tables
-@cindex calculations, in tables
-
-@table @asis
-@item @kbd{C-c +} (@code{org-table-sum})
-@kindex C-c +
-@findex org-table-sum
-Sum the numbers in the current column, or in the rectangle defined
-by the active region.  The result is shown in the echo area and can
-be inserted with @kbd{C-y}.
-
-@item @kbd{S-@key{RET}} (@code{org-table-copy-down})
-@kindex S-RET
-@findex org-table-copy-down
-@vindex org-table-copy-increment
-When current field is empty, copy from first non-empty field above.
-When not empty, copy current field down to next row and move point
-along with it.
-
-Depending on the variable @code{org-table-copy-increment}, integer and
-time stamp field values, and fields prefixed or suffixed with
-a whole number, can be incremented during copy.  Also, a @code{0} prefix
-argument temporarily disables the increment.
-
-This key is also used by shift-selection and related modes (see
-@ref{Conflicts}).
-@end table
-
-@anchor{Miscellaneous (1)}
-@subheading Miscellaneous
-
-@table @asis
-@item @kbd{C-c `} (@code{org-table-edit-field})
-@kindex C-c `
-@findex org-table-edit-field
-Edit the current field in a separate window.  This is useful for
-fields that are not fully visible (see @ref{Column Width and Alignment}).
-When called with a @kbd{C-u} prefix, just make the full field
-visible, so that it can be edited in place.  When called with two
-@kbd{C-u} prefixes, make the editor window follow point through
-the table and always show the current field.  The follow mode exits
-automatically when point leaves the table, or when you repeat this
-command with @kbd{C-u C-u C-c `}.
-
-@item @kbd{M-x org-table-import}
-@findex org-table-import
-Import a file as a table.  The table should be TAB or whitespace
-separated.  Use, for example, to import a spreadsheet table or data
-from a database, because these programs generally can write
-TAB-separated text files.  This command works by inserting the file
-into the buffer and then converting the region to a table.  Any
-prefix argument is passed on to the converter, which uses it to
-determine the separator.
-
-@item @kbd{C-c |} (@code{org-table-create-or-convert-from-region})
-@kindex C-c |
-@findex org-table-create-or-convert-from-region
-Tables can also be imported by pasting tabular text into the Org
-buffer, selecting the pasted text with @kbd{C-x C-x} and then
-using the @kbd{C-c |} command (see @ref{Creation and conversion}).
-
-@item @kbd{M-x org-table-export}
-@findex org-table-export
-@vindex org-table-export-default-format
-Export the table, by default as a TAB-separated file.  Use for data
-exchange with, for example, spreadsheet or database programs.  The
-format used to export the file can be configured in the variable
-@code{org-table-export-default-format}.  You may also use properties
-@samp{TABLE_EXPORT_FILE} and @samp{TABLE_EXPORT_FORMAT} to specify the file
-name and the format for table export in a subtree.  Org supports
-quite general formats for exported tables.  The exporter format is
-the same as the format used by Orgtbl radio tables, see @ref{Translator 
functions}, for a detailed description.
-
-@item @kbd{M-x org-table-header-line-mode}
-@findex org-table-header-line-mode
-@vindex org-table-header-line-p
-Turn on the display of the first data row of the table at point in
-the window header line when this first row is not visible anymore in
-the buffer.  You can activate this minor mode by default by setting
-the option @code{org-table-header-line-p} to @code{t}.
-
-@item @kbd{M-x org-table-transpose-table-at-point}
-@findex org-table-transpose-table-at-point
-Transpose the table at point and eliminate hlines.
-@end table
-
-@node Column Width and Alignment
-@section Column Width and Alignment
-
-@cindex narrow columns in tables
-@cindex alignment in tables
-
-The width of columns is automatically determined by the table editor.
-The alignment of a column is determined automatically from the
-fraction of number-like versus non-number fields in the column.
-
-@vindex org-table-automatic-realign
-Editing a field may modify alignment of the table.  Moving
-a contiguous row or column---i.e., using @kbd{@key{TAB}} or
-@kbd{@key{RET}}---automatically re-aligns it.  If you want to disable
-this behavior, set @code{org-table-automatic-realign} to @code{nil}.  In any
-case, you can always align manually a table:
-
-@table @asis
-@item @kbd{C-c C-c} (@code{org-table-align})
-@kindex C-c C-c
-@findex org-table-align
-Align the current table.
-@end table
-
-@vindex org-startup-align-all-tables
-Setting the option @code{org-startup-align-all-tables} re-aligns all tables
-in a file upon visiting it.  You can also set this option on
-a per-file basis with:
-
-@example
-#+STARTUP: align
-#+STARTUP: noalign
-@end example
-
-Sometimes a single field or a few fields need to carry more text,
-leading to inconveniently wide columns.  Maybe you want to hide away
-several columns or display them with a fixed width, regardless of
-content, as shown in the following example.
-
-@example
-|---+---------------------+--------|           |---+-------…+…|
-|   | <6>                 |        |           |   | <6>   …|…|
-| 1 | one                 | some   |   ----\   | 1 | one   …|…|
-| 2 | two                 | boring |   ----/   | 2 | two   …|…|
-| 3 | This is a long text | column |           | 3 | This i…|…|
-|---+---------------------+--------|           |---+-------…+…|
-@end example
-
-To set the width of a column, one field anywhere in the column may
-contain just the string @samp{<N>} where @var{N} specifies the width
-as a number of characters.  You control displayed width of columns
-with the following tools:
-
-@table @asis
-@item @kbd{C-c @key{TAB}} (@code{org-table-toggle-column-width})
-@kindex C-c TAB
-@findex org-table-toggle-column-width
-Shrink or expand current column.
-
-If a width cookie specifies a width W for the column, shrinking it
-displays the first W visible characters only.  Otherwise, the column
-is shrunk to a single character.
-
-When called before the first column or after the last one, ask for
-a list of column ranges to operate on.
-
-@item @kbd{C-u C-c @key{TAB}} (@code{org-table-shrink})
-@kindex C-u C-c TAB
-@findex org-table-shrink
-Shrink all columns with a column width.  Expand the others.
-
-@item @kbd{C-u C-u C-c @key{TAB}} (@code{org-table-expand})
-@kindex C-u C-u C-c TAB
-@findex org-table-expand
-Expand all columns.
-@end table
-
-To see the full text of a shrunk field, hold the mouse over it:
-a tool-tip window then shows the full contents of the field.
-Alternatively, @kbd{C-h .} (@code{display-local-help}) reveals them,
-too.  For convenience, any change near the shrunk part of a column
-expands it.
-
-@vindex org-startup-shrink-all-tables
-Setting the option @code{org-startup-shrink-all-tables} shrinks all columns
-containing a width cookie in a file the moment it is visited.  You can
-also set this option on a per-file basis with:
-
-@example
-#+STARTUP: shrink
-@end example
-
-
-If you would like to overrule the automatic alignment of number-rich
-columns to the right and of string-rich columns to the left, you can
-use @samp{<r>}, @samp{<c>} or @samp{<l>} in a similar fashion.  You may also 
combine
-alignment and field width like this: @samp{<r10>}.
-
-Lines which only contain these formatting cookies are removed
-automatically upon exporting the document.
-
-@node Column Groups
-@section Column Groups
-
-@cindex grouping columns in tables
-
-When Org exports tables, it does so by default without vertical lines
-because that is visually more satisfying in general.  Occasionally
-however, vertical lines can be useful to structure a table into groups
-of columns, much like horizontal lines can do for groups of rows.  In
-order to specify column groups, you can use a special row where the
-first field contains only @samp{/}.  The further fields can either contain
-@samp{<} to indicate that this column should start a group, @samp{>} to 
indicate
-the end of a column, or @samp{<>} (no space between @samp{<} and @samp{>}) to 
make
-a column a group of its own.  Upon export, boundaries between column
-groups are marked with vertical lines.  Here is an example:
-
-@example
-| N | N^2 | N^3 | N^4 | sqrt(n) | sqrt[4](N) |
-|---+-----+-----+-----+---------+------------|
-| / |  <  |     |  >  |       < |          > |
-| 1 |  1  |  1  |  1  |       1 |          1 |
-| 2 |  4  |  8  | 16  |  1.4142 |     1.1892 |
-| 3 |  9  | 27  | 81  |  1.7321 |     1.3161 |
-|---+-----+-----+-----+---------+------------|
-#+TBLFM: $2=$1^2::$3=$1^3::$4=$1^4::$5=sqrt($1)::$6=sqrt(sqrt(($1)))
-@end example
-
-It is also sufficient to just insert the column group starters after
-every vertical line you would like to have:
-
-@example
-| N | N^2 | N^3 | N^4 | sqrt(n) | sqrt[4](N) |
-|---+-----+-----+-----+---------+------------|
-| / | <   |     |     | <       |            |
-@end example
-
-@node Orgtbl Mode
-@section The Orgtbl Minor Mode
-
-@cindex Orgtbl mode
-@cindex minor mode for tables
-
-@findex orgtbl-mode
-If you like the intuitive way the Org table editor works, you might
-also want to use it in other modes like Text mode or Mail mode.  The
-minor mode Orgtbl mode makes this possible.  You can always toggle the
-mode with @kbd{M-x orgtbl-mode}.  To turn it on by default, for
-example in Message mode, use
-
-@lisp
-(add-hook 'message-mode-hook 'turn-on-orgtbl)
-@end lisp
-
-Furthermore, with some special setup, it is possible to maintain
-tables in arbitrary syntax with Orgtbl mode.  For example, it is
-possible to construct @LaTeX{} tables with the underlying ease and power
-of Orgtbl mode, including spreadsheet capabilities.  For details, see
-@ref{Tables in Arbitrary Syntax}.
-
-@node The Spreadsheet
-@section The Spreadsheet
-
-@cindex calculations, in tables
-@cindex spreadsheet capabilities
-@cindex Calc package
-
-The table editor makes use of the Emacs Calc package to implement
-spreadsheet-like capabilities.  It can also evaluate Emacs Lisp forms
-to derive fields from other fields.  While fully featured, Org's
-implementation is not identical to other spreadsheets.  For example,
-Org knows the concept of a @emph{column formula} that will be applied to
-all non-header fields in a column without having to copy the formula
-to each relevant field.  There is also a formula debugger, and a
-formula editor with features for highlighting fields in the table
-corresponding to the references at point in the formula, moving these
-references by arrow keys.
-
-@menu
-* References::                   How to refer to another field or range.
-* Formula syntax for Calc::      Using Calc to compute stuff.
-* Formula syntax for Lisp::      Writing formulas in Emacs Lisp.
-* Durations and time values::    How to compute durations and time values.
-* Field and range formulas::     Formula for specific (ranges of) fields.
-* Column formulas::              Formulas valid for an entire column.
-* Lookup functions::             Lookup functions for searching tables.
-* Editing and debugging formulas:: Fixing formulas.
-* Updating the table::           Recomputing all dependent fields.
-* Advanced features::            Field and column names, automatic 
recalculation...
-@end menu
-
-@node References
-@subsection References
-
-@cindex references
-
-To compute fields in the table from other fields, formulas must
-reference other fields or ranges.  In Org, fields can be referenced by
-name, by absolute coordinates, and by relative coordinates.  To find
-out what the coordinates of a field are, press @kbd{C-c ?} in
-that field, or press @kbd{C-c @}} to toggle the display of a grid.
-
-@anchor{Field references}
-@subsubheading Field references
-
-@cindex field references
-@cindex references, to fields
-Formulas can reference the value of another field in two ways.  Like
-in any other spreadsheet, you may reference fields with
-a letter/number combination like @samp{B3}, meaning the second field in the
-third row.  However, Org prefers to use another, more general
-representation that looks like this:@footnote{Org understands references typed 
by the user as @samp{B4}, but it
-does not use this syntax when offering a formula for editing.  You can
-customize this behavior using the variable
-@code{org-table-use-standard-references}.}
-
-@example
-@@ROW$COLUMN
-@end example
-
-
-Column specifications can be absolute like @samp{$1}, @samp{$2}, @dots{}, 
@samp{$N}, or
-relative to the current column, i.e., the column of the field which is
-being computed, like @samp{$+1} or @samp{$-2}.  @samp{$<} and @samp{$>} are 
immutable
-references to the first and last column, respectively, and you can use
-@samp{$>>>} to indicate the third column from the right.
-
-The row specification only counts data lines and ignores horizontal
-separator lines, or ``hlines''.  Like with columns, you can use absolute
-row numbers @samp{@@1}, @samp{@@2}, @dots{}, @samp{@@N}, and row numbers 
relative to the
-current row like @samp{@@+3} or @samp{@@-1}.  @samp{@@<} and @samp{@@>} are 
immutable
-references the first and last row in the table, respectively.  You may
-also specify the row relative to one of the hlines: @samp{@@I} refers to the
-first hline, @samp{@@II} to the second, etc.  @samp{@@-I} refers to the first 
such
-line above the current line, @samp{@@+I} to the first such line below the
-current line.  You can also write @samp{@@III+2} which is the second data
-line after the third hline in the table.
-
-@samp{@@0} and @samp{$0} refer to the current row and column, respectively, 
i.e.,
-to the row/column for the field being computed.  Also, if you omit
-either the column or the row part of the reference, the current
-row/column is implied.
-
-Org's references with @emph{unsigned} numbers are fixed references in the
-sense that if you use the same reference in the formula for two
-different fields, the same field is referenced each time.  Org's
-references with @emph{signed} numbers are floating references because the
-same reference operator can reference different fields depending on
-the field being calculated by the formula.
-
-Here are a few examples:
-
-@multitable @columnfractions 0.2 0.8
-@item @samp{@@2$3}
-@tab 2nd row, 3rd column (same as @samp{C2})
-@item @samp{$5}
-@tab column 5 in the current row (same as @samp{E&})
-@item @samp{@@2}
-@tab current column, row 2
-@item @samp{@@-1$-3}
-@tab field one row up, three columns to the left
-@item @samp{@@-I$2}
-@tab field just under hline above current row, column 2
-@item @samp{@@>$5}
-@tab field in the last row, in column 5
-@end multitable
-
-@anchor{Range references}
-@subsubheading Range references
-
-@cindex range references
-@cindex references, to ranges
-You may reference a rectangular range of fields by specifying two
-field references connected by two dots @samp{..}.  The ends are included in
-the range.  If both fields are in the current row, you may simply use
-@samp{$2..$7}, but if at least one field is in a different row, you need to
-use the general @samp{@@ROW$COLUMN} format at least for the first field,
-i.e., the reference must start with @samp{@@} in order to be interpreted
-correctly.  Examples:
-
-@multitable @columnfractions 0.2 0.8
-@item @samp{$1..$3}
-@tab first three fields in the current row
-@item @samp{$P..$Q}
-@tab range, using column names (see @ref{Advanced features})
-@item @samp{$<<<..$>>}
-@tab start in third column, continue to the last but one
-@item @samp{@@2$1..@@4$3}
-@tab nine fields between these two fields (same as @samp{A2..C4})
-@item @samp{@@-1$-2..@@-1}
-@tab 3 fields in the row above, starting from 2 columns on the left
-@item @samp{@@I..II}
-@tab between first and second hline, short for @samp{@@I..@@II}
-@end multitable
-
-@noindent
-Range references return a vector of values that can be fed into Calc
-vector functions.  Empty fields in ranges are normally suppressed, so
-that the vector contains only the non-empty fields.  For other options
-with the mode switches @samp{E}, @samp{N} and examples, see @ref{Formula 
syntax for Calc}.
-
-@anchor{Field coordinates in formulas}
-@subsubheading Field coordinates in formulas
-
-@cindex field coordinates
-@cindex coordinates, of field
-@cindex row, of field coordinates
-@cindex column, of field coordinates
-@vindex org-table-current-column
-@vindex org-table-current-dline
-One of the very first actions during evaluation of Calc formulas and
-Lisp formulas is to substitute @samp{@@#} and @samp{$#} in the formula with the
-row or column number of the field where the current result will go to.
-The traditional Lisp formula equivalents are @code{org-table-current-dline}
-and @code{org-table-current-column}.  Examples:
-
-@table @asis
-@item @samp{if(@@# % 2, $#, string(""))}
-Insert column number on odd rows, set field to empty on even rows.
-
-@item @samp{$2 = '(identity remote(FOO, @@@@#$1))}
-Copy text or values of each row of column 1 of the table named
-@var{FOO} into column 2 of the current table.
-
-@item @samp{@@3 = 2 * remote(FOO, @@1$$#)}
-Insert the doubled value of each column of row 1 of the table
-named @var{FOO} into row 3 of the current table.
-@end table
-
-@noindent
-For the second and third examples, table @var{FOO} must have at
-least as many rows or columns as the current table.  Note that this is
-inefficient@footnote{The computation time scales as O(N^2) because table
-@var{FOO} is parsed for each field to be copied.} for large number of rows.
-
-@anchor{Named references}
-@subsubheading Named references
-
-@cindex named references
-@cindex references, named
-@cindex name, of column or field
-@cindex constants, in calculations
-@cindex @samp{CONSTANTS}, keyword
-@vindex org-table-formula-constants
-
-@samp{$name} is interpreted as the name of a column, parameter or constant.
-Constants are defined globally through the variable
-@code{org-table-formula-constants}, and locally---for the file---through
-a line like this example:
-
-@example
-#+CONSTANTS: c=299792458. pi=3.14 eps=2.4e-6
-@end example
-
-
-@vindex constants-unit-system
-@pindex constants.el
-Also, properties (see @ref{Properties and Columns}) can be used as
-constants in table formulas: for a property @samp{Xyz} use the name
-@samp{$PROP_Xyz}, and the property will be searched in the current outline
-entry and in the hierarchy above it.  If you have the @samp{constants.el}
-package, it will also be used to resolve constants, including natural
-constants like @samp{$h} for Planck's constant, and units like @samp{$km} for
-kilometers@footnote{The file @samp{constants.el} can supply the values of 
constants in
-two different unit systems, @samp{SI} and @samp{cgs}.  Which one is used 
depends
-on the value of the variable @code{constants-unit-system}.  You can use the
-@samp{STARTUP} options @samp{constSI} and @samp{constcgs} to set this value 
for the
-current buffer.}.  Column names and parameters can be specified in
-special table lines.  These are described below, see @ref{Advanced features}.  
All names must start with a letter, and further consist
-of letters and numbers.
-
-@anchor{Remote references}
-@subsubheading Remote references
-
-@cindex remote references
-@cindex references, remote
-@cindex references, to a different table
-@cindex name, of column or field
-@cindex @samp{NAME}, keyword
-You may also reference constants, fields and ranges from a different
-table, either in the current file or even in a different file.  The
-syntax is
-
-@example
-remote(NAME,REF)
-@end example
-
-
-@noindent
-where @var{NAME} can be the name of a table in the current file
-as set by a @samp{#+NAME:} line before the table.  It can also be the ID of
-an entry, even in a different file, and the reference then refers to
-the first table in that entry.  @var{REF} is an absolute field or
-range reference as described above for example @samp{@@3$3} or 
@samp{$somename},
-valid in the referenced table.
-
-@cindex table indirection
-When @var{NAME} has the format @samp{@@ROW$COLUMN}, it is substituted
-with the name or ID found in this field of the current table.  For
-example @samp{remote($1, @@@@>$2)} @result{} @samp{remote(year_2013, 
@@@@>$1)}.  The format
-@samp{B3} is not supported because it can not be distinguished from a plain
-table name or ID@.
-
-@node Formula syntax for Calc
-@subsection Formula syntax for Calc
-
-@cindex formula syntax, Calc
-@cindex syntax, of formulas
-
-A formula can be any algebraic expression understood by the Emacs Calc
-package.  Note that Calc has the non-standard convention that @samp{/} has
-lower precedence than @samp{*}, so that @samp{a/b*c} is interpreted as
-@samp{(a/(b*c))}.  Before evaluation by @code{calc-eval} (see @ref{Calling 
Calc from Your Programs,Calling Calc from
-Your Lisp Programs,,calc,}), variable substitution takes place according to
-the rules described above.
-
-@cindex vectors, in table calculations
-The range vectors can be directly fed into the Calc vector functions
-like @code{vmean} and @code{vsum}.
-
-@cindex format specifier, in spreadsheet
-@cindex mode, for Calc
-@vindex org-calc-default-modes
-A formula can contain an optional mode string after a semicolon.  This
-string consists of flags to influence Calc and other modes during
-execution.  By default, Org uses the standard Calc modes (precision
-12, angular units degrees, fraction and symbolic modes off).  The
-display format, however, has been changed to @samp{(float 8)} to keep
-tables compact.  The default settings can be configured using the
-variable @code{org-calc-default-modes}.
-
-@table @asis
-@item @samp{p20}
-Set the internal Calc calculation precision to 20 digits.
-
-@item @samp{n3}, @samp{s3}, @samp{e2}, @samp{f4}
-Normal, scientific, engineering or fixed format of the result of
-Calc passed back to Org.  Calc formatting is unlimited in precision
-as long as the Calc calculation precision is greater.
-
-@item @samp{D}, @samp{R}
-Degree and radian angle modes of Calc.
-
-@item @samp{F}, @samp{S}
-Fraction and symbolic modes of Calc.
-
-@item @samp{T}, @samp{t}, @samp{U}
-Duration computations in Calc or Lisp, @ref{Durations and time values}.
-
-@item @samp{E}
-If and how to consider empty fields.  Without @samp{E} empty fields in
-range references are suppressed so that the Calc vector or Lisp list
-contains only the non-empty fields.  With @samp{E} the empty fields are
-kept.  For empty fields in ranges or empty field references the
-value @samp{nan} (not a number) is used in Calc formulas and the empty
-string is used for Lisp formulas.  Add @samp{N} to use 0 instead for both
-formula types.  For the value of a field the mode @samp{N} has higher
-precedence than @samp{E}.
-
-@item @samp{N}
-Interpret all fields as numbers, use 0 for non-numbers.  See the
-next section to see how this is essential for computations with Lisp
-formulas.  In Calc formulas it is used only occasionally because
-there number strings are already interpreted as numbers without @samp{N}.
-
-@item @samp{L}
-Literal, for Lisp formulas only.  See the next section.
-@end table
-
-Unless you use large integer numbers or high-precision calculation and
-display for floating point numbers you may alternatively provide
-a @code{printf} format specifier to reformat the Calc result after it has
-been passed back to Org instead of letting Calc already do the
-formatting@footnote{The printf reformatting is limited in precision because the
-value passed to it is converted into an ``integer'' or ``double''.  The
-``integer'' is limited in size by truncating the signed value to 32
-bits.  The ``double'' is limited in precision to 64 bits overall which
-leaves approximately 16 significant decimal digits.}.  A few examples:
-
-@multitable {aaaaaaaaaaaaaaaaaa} 
{aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa}
-@item @samp{$1+$2}
-@tab Sum of first and second field
-@item @samp{$1+$2;%.2f}
-@tab Same, format result to two decimals
-@item @samp{exp($2)+exp($1)}
-@tab Math functions can be used
-@item @samp{$0;%.1f}
-@tab Reformat current cell to 1 decimal
-@item @samp{($3-32)*5/9}
-@tab Degrees F @arrow{} C conversion
-@item @samp{$c/$1/$cm}
-@tab Hz @arrow{} cm conversion, using @samp{constants.el}
-@item @samp{tan($1);Dp3s1}
-@tab Compute in degrees, precision 3, display SCI 1
-@item @samp{sin($1);Dp3%.1e}
-@tab Same, but use @code{printf} specifier for display
-@item @samp{vmean($2..$7)}
-@tab Compute column range mean, using vector function
-@item @samp{vmean($2..$7);EN}
-@tab Same, but treat empty fields as 0
-@item @samp{taylor($3,x=7,2)}
-@tab Taylor series of $3, at x=7, second degree
-@end multitable
-
-Calc also contains a complete set of logical operations (see @ref{Logical 
Operations,Logical
-Operations,,calc,}).  For example
-
-@table @asis
-@item @samp{if($1 < 20, teen, string(""))}
-@samp{"teen"} if age @samp{$1} is less than 20, else the Org table result
-field is set to empty with the empty string.
-
-@item @samp{if("$1" =​= "nan" || "$2" =​= "nan", string(""), $1 + $2); E f-1}
-Sum of the first two columns.  When at least one of the input fields
-is empty the Org table result field is set to empty.  @samp{E} is
-required to not convert empty fields to 0.  @samp{f-1} is an optional
-Calc format string similar to @samp{%.1f} but leaves empty results empty.
-
-@item @samp{if(typeof(vmean($1..$7)) =​= 12, string(""), vmean($1..$7); E}
-Mean value of a range unless there is any empty field.  Every field
-in the range that is empty is replaced by @samp{nan} which lets @samp{vmean}
-result in @samp{nan}.  Then @samp{typeof =} 12= detects the @samp{nan} from 
@code{vmean}
-and the Org table result field is set to empty.  Use this when the
-sample set is expected to never have missing values.
-
-@item @samp{if("$1..$7" =​= "[]", string(""), vmean($1..$7))}
-Mean value of a range with empty fields skipped.  Every field in the
-range that is empty is skipped.  When all fields in the range are
-empty the mean value is not defined and the Org table result field
-is set to empty.  Use this when the sample set can have a variable
-size.
-
-@item @samp{vmean($1..$7); EN}
-To complete the example before: Mean value of a range with empty
-fields counting as samples with value 0.  Use this only when
-incomplete sample sets should be padded with 0 to the full size.
-@end table
-
-You can add your own Calc functions defined in Emacs Lisp with
-@code{defmath} and use them in formula syntax for Calc.
-
-@node Formula syntax for Lisp
-@subsection Emacs Lisp forms as formulas
-
-@cindex Lisp forms, as table formulas
-
-It is also possible to write a formula in Emacs Lisp.  This can be
-useful for string manipulation and control structures, if Calc's
-functionality is not enough.
-
-If a formula starts with a single-quote followed by an opening
-parenthesis, then it is evaluated as a Lisp form.  The evaluation
-should return either a string or a number.  Just as with Calc
-formulas, you can specify modes and a @code{printf} format after
-a semicolon.
-
-With Emacs Lisp forms, you need to be conscious about the way field
-references are interpolated into the form.  By default, a reference is
-interpolated as a Lisp string (in double-quotes) containing the field.
-If you provide the @samp{N} mode switch, all referenced elements are
-numbers---non-number fields will be zero---and interpolated as Lisp
-numbers, without quotes.  If you provide the @samp{L} flag, all fields are
-interpolated literally, without quotes.  For example, if you want a
-reference to be interpreted as a string by the Lisp form, enclose the
-reference operator itself in double-quotes, like @samp{"$3"}.  Ranges are
-inserted as space-separated fields, so you can embed them in list or
-vector syntax.
-
-Here are a few examples---note how the @samp{N} mode is used when we do
-computations in Lisp:
-
-@table @asis
-@item @samp{'(concat (substring $1 1 2) (substring $1 0 1) (substring $1 2))}
-Swap the first two characters of the content of column 1.
-
-@item @samp{'(+ $1 $2);N}
-Add columns 1 and 2, equivalent to Calc's @samp{$1+$2}.
-
-@item @samp{'(apply '+ '($1..$4));N}
-Compute the sum of columns 1 to 4, like Calc's @samp{vsum($1..$4)}.
-@end table
-
-@node Durations and time values
-@subsection Durations and time values
-
-@cindex duration, computing
-@cindex time, computing
-@vindex org-table-duration-custom-format
-
-If you want to compute time values use the @samp{T}, @samp{t}, or @samp{U} 
flag,
-either in Calc formulas or Elisp formulas:
-
-@example
-|  Task 1 |   Task 2 |    Total |
-|---------+----------+----------|
-|    2:12 |     1:47 | 03:59:00 |
-|    2:12 |     1:47 |    03:59 |
-| 3:02:20 | -2:07:00 |     0.92 |
-#+TBLFM: @@2$3=$1+$2;T::@@3$3=$1+$2;U::@@4$3=$1+$2;t
-@end example
-
-Input duration values must be of the form @samp{HH:MM[:SS]}, where seconds
-are optional.  With the @samp{T} flag, computed durations are displayed as
-@samp{HH:MM:SS} (see the first formula above).  With the @samp{U} flag, seconds
-are omitted so that the result is only @samp{HH:MM} (see second formula
-above).  Zero-padding of the hours field depends upon the value of the
-variable @code{org-table-duration-hour-zero-padding}.
-
-With the @samp{t} flag, computed durations are displayed according to the
-value of the option @code{org-table-duration-custom-format}, which defaults
-to @code{hours} and displays the result as a fraction of hours (see the
-third formula in the example above).
-
-Negative duration values can be manipulated as well, and integers are
-considered as seconds in addition and subtraction.
-
-@node Field and range formulas
-@subsection Field and range formulas
-
-@cindex field formula
-@cindex range formula
-@cindex formula, for individual table field
-@cindex formula, for range of fields
-
-To assign a formula to a particular field, type it directly into the
-field, preceded by @samp{:=}, for example @samp{vsum(@@II..III)}.  When you 
press
-@kbd{@key{TAB}} or @kbd{@key{RET}} or @kbd{C-c C-c} with point
-still in the field, the formula is stored as the formula for this
-field, evaluated, and the current field is replaced with the result.
-
-@cindex @samp{TBLFM}, keyword
-Formulas are stored in a special @samp{TBLFM} keyword located directly
-below the table.  If you type the equation in the fourth field of the
-third data line in the table, the formula looks like @samp{@@3$4=$1+$2}.
-When inserting/deleting/swapping column and rows with the appropriate
-commands, @emph{absolute references} (but not relative ones) in stored
-formulas are modified in order to still reference the same field.  To
-avoid this from happening, in particular in range references, anchor
-ranges at the table borders (using @samp{@@<}, @samp{@@>}, @samp{$<}, 
@samp{$>}), or at
-hlines using the @samp{@@I} notation.  Automatic adaptation of field
-references does not happen if you edit the table structure with normal
-editing commands---you must fix the formulas yourself.
-
-Instead of typing an equation into the field, you may also use the
-following command
-
-@table @asis
-@item @kbd{C-u C-c =} (@code{org-table-eval-formula})
-@kindex C-u C-c =
-@findex org-table-eval-formula
-Install a new formula for the current field.  The command prompts
-for a formula with default taken from the @samp{TBLFM} keyword,
-applies it to the current field, and stores it.
-@end table
-
-The left-hand side of a formula can also be a special expression in
-order to assign the formula to a number of different fields.  There is
-no keyboard shortcut to enter such range formulas.  To add them, use
-the formula editor (see @ref{Editing and debugging formulas}) or edit
-the @samp{TBLFM} keyword directly.
-
-@table @asis
-@item @samp{$2=}
-Column formula, valid for the entire column.  This is so common that
-Org treats these formulas in a special way, see @ref{Column formulas}.
-
-@item @samp{@@3=}
-Row formula, applies to all fields in the specified row.  @samp{@@>=}
-means the last row.
-
-@item @samp{@@1$2..@@4$3=}
-Range formula, applies to all fields in the given rectangular range.
-This can also be used to assign a formula to some but not all fields
-in a row.
-
-@item @samp{$NAME=}
-Named field, see @ref{Advanced features}.
-@end table
-
-@node Column formulas
-@subsection Column formulas
-
-@cindex column formula
-@cindex formula, for table column
-
-When you assign a formula to a simple column reference like @samp{$3=}, the
-same formula is used in all fields of that column, with the following
-very convenient exceptions: (i) If the table contains horizontal
-separator hlines with rows above and below, everything before the
-first such hline is considered part of the table @emph{header} and is not
-modified by column formulas.  Therefore a header is mandatory when you
-use column formulas and want to add hlines to group rows, like for
-example to separate a total row at the bottom from the summand rows
-above.  (ii) Fields that already get a value from a field/range
-formula are left alone by column formulas.  These conditions make
-column formulas very easy to use.
-
-To assign a formula to a column, type it directly into any field in
-the column, preceded by an equal sign, like @samp{=$1+$2}.  When you press
-@kbd{@key{TAB}} or @kbd{@key{RET}} or @kbd{C-c C-c} with point
-still in the field, the formula is stored as the formula for the
-current column, evaluated and the current field replaced with the
-result.  If the field contains only @samp{=}, the previously stored formula
-for this column is used.  For each column, Org only remembers the most
-recently used formula.  In the @samp{TBLFM} keyword, column formulas look
-like @samp{$4=$1+$2}.  The left-hand side of a column formula can not be
-the name of column, it must be the numeric column reference or @samp{$>}.
-
-Instead of typing an equation into the field, you may also use the
-following command:
-
-@table @asis
-@item @kbd{C-c =} (@code{org-table-eval-formula})
-@kindex C-c =
-@findex org-table-eval-formula
-Install a new formula for the current column and replace current
-field with the result of the formula.  The command prompts for
-a formula, with default taken from the @samp{TBLFM} keyword, applies it
-to the current field and stores it.  With a numeric prefix argument,
-e.g., @kbd{C-5 C-c =}, the command applies it to that many
-consecutive fields in the current column.
-@end table
-
-@node Lookup functions
-@subsection Lookup functions
-
-@cindex lookup functions in tables
-@cindex table lookup functions
-
-Org has three predefined Emacs Lisp functions for lookups in tables.
-
-@table @asis
-@item @samp{(org-lookup-first VAL S-LIST R-LIST &optional PREDICATE)}
-@findex org-lookup-first
-Searches for the first element @var{S} in list
-@var{S-LIST} for which
-@lisp
-(PREDICATE VAL S)
-@end lisp
-is non-@code{nil}; returns the value from the corresponding position in
-list @var{R-LIST}.  The default @var{PREDICATE} is
-@code{equal}.  Note that the parameters @var{VAL} and @var{S}
-are passed to @var{PREDICATE} in the same order as the
-corresponding parameters are in the call to @code{org-lookup-first},
-where @var{VAL} precedes @var{S-LIST}.  If
-@var{R-LIST} is @code{nil}, the matching element @var{S} of
-@var{S-LIST} is returned.
-
-@item @samp{(org-lookup-last VAL S-LIST R-LIST &optional PREDICATE)}
-@findex org-lookup-last
-Similar to @code{org-lookup-first} above, but searches for the @emph{last}
-element for which @var{PREDICATE} is non-@code{nil}.
-
-@item @samp{(org-lookup-all VAL S-LIST R-LIST &optional PREDICATE)}
-@findex org-lookup-all
-Similar to @code{org-lookup-first}, but searches for @emph{all} elements for
-which @var{PREDICATE} is non-@code{nil}, and returns @emph{all}
-corresponding values.  This function can not be used by itself in
-a formula, because it returns a list of values.  However, powerful
-lookups can be built when this function is combined with other Emacs
-Lisp functions.
-@end table
-
-If the ranges used in these functions contain empty fields, the @samp{E}
-mode for the formula should usually be specified: otherwise empty
-fields are not included in @var{S-LIST} and/or @var{R-LIST}
-which can, for example, result in an incorrect mapping from an element
-of @var{S-LIST} to the corresponding element of
-@var{R-LIST}.
-
-These three functions can be used to implement associative arrays,
-count matching cells, rank results, group data, etc.  For practical
-examples see @uref{https://orgmode.org/worg/org-tutorials/org-lookups.html, 
this tutorial on Worg}.
-
-@node Editing and debugging formulas
-@subsection Editing and debugging formulas
-
-@cindex formula editing
-@cindex editing, of table formulas
-
-@vindex org-table-use-standard-references
-You can edit individual formulas in the minibuffer or directly in the
-field.  Org can also prepare a special buffer with all active formulas
-of a table.  When offering a formula for editing, Org converts
-references to the standard format (like @samp{B3} or @samp{D&}) if possible.  
If
-you prefer to only work with the internal format (like @samp{@@3$2} or
-@samp{$4}), configure the variable @code{org-table-use-standard-references}.
-
-@table @asis
-@item @kbd{C-c =} or @kbd{C-u C-c =} (@code{org-table-eval-formula})
-@kindex C-c =
-@kindex C-u C-c =
-@findex org-table-eval-formula
-Edit the formula associated with the current column/field in the
-minibuffer.  See @ref{Column formulas}, and @ref{Field and range formulas}.
-
-@item @kbd{C-u C-u C-c =} (@code{org-table-eval-formula})
-@kindex C-u C-u C-c =
-@findex org-table-eval-formula
-Re-insert the active formula (either a field formula, or a column
-formula) into the current field, so that you can edit it directly in
-the field.  The advantage over editing in the minibuffer is that you
-can use the command @kbd{C-c ?}.
-
-@item @kbd{C-c ?} (@code{org-table-field-info})
-@kindex C-c ?
-@findex org-table-field-info
-While editing a formula in a table field, highlight the field(s)
-referenced by the reference at point position in the formula.
-
-@item @kbd{C-c @}} (@code{org-table-toggle-coordinate-overlays})
-@kindex C-c @}
-@findex org-table-toggle-coordinate-overlays
-Toggle the display of row and column numbers for a table, using
-overlays.  These are updated each time the table is aligned; you can
-force it with @kbd{C-c C-c}.
-
-@item @kbd{C-c @{} (@code{org-table-toggle-formula-debugger})
-@kindex C-c @{
-@findex org-table-toggle-formula-debugger
-Toggle the formula debugger on and off.  See below.
-
-@item @kbd{C-c '} (@code{org-table-edit-formulas})
-@kindex C-c '
-@findex org-table-edit-formulas
-Edit all formulas for the current table in a special buffer, where
-the formulas are displayed one per line.  If the current field has
-an active formula, point in the formula editor marks it.  While
-inside the special buffer, Org automatically highlights any field or
-range reference at point position.  You may edit, remove and add
-formulas, and use the following commands:
-
-@table @asis
-@item @kbd{C-c C-c} or @kbd{C-x C-s} (@code{org-table-fedit-finish})
-@kindex C-x C-s
-@kindex C-c C-c
-@findex org-table-fedit-finish
-Exit the formula editor and store the modified formulas.  With
-@kbd{C-u} prefix, also apply the new formulas to the
-entire table.
-
-@item @kbd{C-c C-q} (@code{org-table-fedit-abort})
-@kindex C-c C-q
-@findex org-table-fedit-abort
-Exit the formula editor without installing changes.
-
-@item @kbd{C-c C-r} (@code{org-table-fedit-toggle-ref-type})
-@kindex C-c C-r
-@findex org-table-fedit-toggle-ref-type
-Toggle all references in the formula editor between standard (like
-@samp{B3}) and internal (like @samp{@@3$2}).
-
-@item @kbd{@key{TAB}} (@code{org-table-fedit-lisp-indent})
-@kindex TAB
-@findex org-table-fedit-lisp-indent
-Pretty-print or indent Lisp formula at point.  When in a line
-containing a Lisp formula, format the formula according to Emacs
-Lisp rules.  Another @kbd{@key{TAB}} collapses the formula back
-again.  In the open formula, @kbd{@key{TAB}} re-indents just like
-in Emacs Lisp mode.
-
-@item @kbd{M-@key{TAB}} (@code{lisp-complete-symbol})
-@kindex M-TAB
-@findex lisp-complete-symbol
-Complete Lisp symbols, just like in Emacs Lisp mode.
-
-@item @kbd{S-@key{UP}}, @kbd{S-@key{DOWN}}, @kbd{S-@key{LEFT}}, 
@kbd{S-@key{RIGHT}}
-@kindex S-UP
-@kindex S-DOWN
-@kindex S-LEFT
-@kindex S-RIGHT
-@findex org-table-fedit-ref-up
-@findex org-table-fedit-ref-down
-@findex org-table-fedit-ref-left
-@findex org-table-fedit-ref-right
-Shift the reference at point.  For example, if the reference is
-@samp{B3} and you press @kbd{S-@key{RIGHT}}, it becomes @samp{C3}.  This also
-works for relative references and for hline references.
-
-@item @kbd{M-S-@key{UP}} (@code{org-table-fedit-line-up})
-@kindex M-S-UP
-@findex org-table-fedit-line-up
-Move the test line for column formulas up in the Org buffer.
-
-@item @kbd{M-S-@key{DOWN}} (@code{org-table-fedit-line-down})
-@kindex M-S-DOWN
-@findex org-table-fedit-line-down
-Move the test line for column formulas down in the Org buffer.
-
-@item @kbd{M-@key{UP}} (@code{org-table-fedit-scroll-up})
-@kindex M-UP
-@findex org-table-fedit-scroll-up
-Scroll up the window displaying the table.
-
-@item @kbd{M-@key{DOWN}} (@code{org-table-fedit-scroll-down})
-@kindex M-DOWN
-@findex org-table-fedit-scroll-down
-Scroll down the window displaying the table.
-
-@item @kbd{C-c @}}
-@kindex C-c @}
-@findex org-table-toggle-coordinate-overlays
-Turn the coordinate grid in the table on and off.
-@end table
-@end table
-
-Making a table field blank does not remove the formula associated with
-the field, because that is stored in a different line---the @samp{TBLFM}
-keyword line.  During the next recalculation, the field will be filled
-again.  To remove a formula from a field, you have to give an empty
-reply when prompted for the formula, or to edit the @samp{TBLFM} keyword.
-
-@kindex C-c C-c
-You may edit the @samp{TBLFM} keyword directly and re-apply the changed
-equations with @kbd{C-c C-c} in that line or with the normal
-recalculation commands in the table.
-
-@anchor{Using multiple @samp{TBLFM} lines}
-@subsubheading Using multiple @samp{TBLFM} lines
-
-@cindex multiple formula lines
-@cindex @samp{TBLFM} keywords, multiple
-@cindex @samp{TBLFM}, switching
-
-@kindex C-c C-c
-You may apply the formula temporarily.  This is useful when you want
-to switch the formula applied to the table.  Place multiple @samp{TBLFM}
-keywords right after the table, and then press @kbd{C-c C-c} on
-the formula to apply.  Here is an example:
-
-@example
-| x | y |
-|---+---|
-| 1 |   |
-| 2 |   |
-#+TBLFM: $2=$1*1
-#+TBLFM: $2=$1*2
-@end example
-
-@noindent
-Pressing @kbd{C-c C-c} in the line of @samp{#+TBLFM: $2=$1*2} yields:
-
-@example
-| x | y |
-|---+---|
-| 1 | 2 |
-| 2 | 4 |
-#+TBLFM: $2=$1*1
-#+TBLFM: $2=$1*2
-@end example
-
-@noindent
-If you recalculate this table, with @kbd{C-u C-c *}, for example,
-you get the following result from applying only the first @samp{TBLFM}
-keyword.
-
-@example
-| x | y |
-|---+---|
-| 1 | 1 |
-| 2 | 2 |
-#+TBLFM: $2=$1*1
-#+TBLFM: $2=$1*2
-@end example
-
-@anchor{Debugging formulas}
-@subsubheading Debugging formulas
-
-@cindex formula debugging
-@cindex debugging, of table formulas
-
-When the evaluation of a formula leads to an error, the field content
-becomes the string @samp{#ERROR}.  If you would like to see what is going
-on during variable substitution and calculation in order to find
-a bug, turn on formula debugging in the Tbl menu and repeat the
-calculation, for example by pressing @kbd{C-u C-u C-c = @key{RET}} in
-a field.  Detailed information are displayed.
-
-@node Updating the table
-@subsection Updating the table
-
-@cindex recomputing table fields
-@cindex updating, table
-
-Recalculation of a table is normally not automatic, but needs to be
-triggered by a command.  To make recalculation at least
-semi-automatic, see @ref{Advanced features}.
-
-In order to recalculate a line of a table or the entire table, use the
-following commands:
-
-@table @asis
-@item @kbd{C-c *} (@code{org-table-recalculate})
-@kindex C-c *
-@findex org-table-recalculate
-Recalculate the current row by first applying the stored column
-formulas from left to right, and all field/range formulas in the
-current row.
-
-@item @kbd{C-u C-c *} or @kbd{C-u C-c C-c}
-@kindex C-u C-c *
-@kindex C-u C-c C-c
-Recompute the entire table, line by line.  Any lines before the
-first hline are left alone, assuming that these are part of the
-table header.
-
-@item @kbd{C-u C-u C-c *} or @kbd{C-u C-u C-c C-c} (@code{org-table-iterate})
-@kindex C-u C-u C-c *
-@kindex C-u C-u C-c C-c
-@findex org-table-iterate
-Iterate the table by recomputing it until no further changes occur.
-This may be necessary if some computed fields use the value of other
-fields that are computed @emph{later} in the calculation sequence.
-
-@item @kbd{M-x org-table-recalculate-buffer-tables}
-@findex org-table-recalculate-buffer-tables
-Recompute all tables in the current buffer.
-
-@item @kbd{M-x org-table-iterate-buffer-tables}
-@findex org-table-iterate-buffer-tables
-Iterate all tables in the current buffer, in order to converge
-table-to-table dependencies.
-@end table
-
-@node Advanced features
-@subsection Advanced features
-
-If you want the recalculation of fields to happen automatically, or if
-you want to be able to assign @emph{names}@footnote{Such names must start with 
an alphabetic character and use
-only alphanumeric/underscore characters.} to fields and columns,
-you need to reserve the first column of the table for special marking
-characters.
-
-@table @asis
-@item @kbd{C-#} (@code{org-table-rotate-recalc-marks})
-@kindex C-#
-@findex org-table-rotate-recalc-marks
-Rotate the calculation mark in first column through the states @samp{#},
-@samp{*}, @samp{!}, @samp{$}.  When there is an active region, change all 
marks in
-the region.
-@end table
-
-Here is an example of a table that collects exam results of students
-and makes use of these features:
-
-@example
-|---+---------+--------+--------+--------+-------+------|
-|   | Student | Prob 1 | Prob 2 | Prob 3 | Total | Note |
-|---+---------+--------+--------+--------+-------+------|
-| ! |         |     P1 |     P2 |     P3 |   Tot |      |
-| # | Maximum |     10 |     15 |     25 |    50 | 10.0 |
-| ^ |         |     m1 |     m2 |     m3 |    mt |      |
-|---+---------+--------+--------+--------+-------+------|
-| # | Peter   |     10 |      8 |     23 |    41 |  8.2 |
-| # | Sam     |      2 |      4 |      3 |     9 |  1.8 |
-|---+---------+--------+--------+--------+-------+------|
-|   | Average |        |        |        |  25.0 |      |
-| ^ |         |        |        |        |    at |      |
-| $ | max=50  |        |        |        |       |      |
-|---+---------+--------+--------+--------+-------+------|
-#+TBLFM: $6=vsum($P1..$P3)::$7=10*$Tot/$max;%.1f::$at=vmean(@@-II..@@-I);%.1f
-@end example
-
-@quotation Important
-Please note that for these special tables, recalculating the table
-with @kbd{C-u C-c *} only affects rows that are marked @samp{#} or
-@samp{*}, and fields that have a formula assigned to the field itself.  The
-column formulas are not applied in rows with empty first field.
-
-@end quotation
-
-@cindex marking characters, tables
-The marking characters have the following meaning:
-
-@table @asis
-@item @samp{!}
-The fields in this line define names for the columns, so that you
-may refer to a column as @samp{$Tot} instead of @samp{$6}.
-
-@item @samp{^}
-This row defines names for the fields @emph{above} the row.  With such
-a definition, any formula in the table may use @samp{$m1} to refer to the
-value @samp{10}.  Also, if you assign a formula to a names field, it is
-stored as @samp{$name = ...}.
-
-@item @samp{_}
-Similar to @samp{^}, but defines names for the fields in the row @emph{below}.
-
-@item @samp{$}
-Fields in this row can define @emph{parameters} for formulas.  For
-example, if a field in a @samp{$} row contains @samp{max=50}, then formulas in
-this table can refer to the value 50 using @samp{$max}.  Parameters work
-exactly like constants, only that they can be defined on a per-table
-basis.
-
-@item @samp{#}
-Fields in this row are automatically recalculated when pressing
-@kbd{@key{TAB}} or @kbd{@key{RET}} or @kbd{S-@key{TAB}} in this row.
-Also, this row is selected for a global recalculation with
-@kbd{C-u C-c *}.  Unmarked lines are left alone by this
-command.
-
-@item @samp{*}
-Selects this line for global recalculation with @kbd{C-u C-c *}, but not for 
automatic recalculation.  Use this when automatic
-recalculation slows down editing too much.
-
-@item @samp{/}
-Do not export this line.  Useful for lines that contain the
-narrowing @samp{<N>} markers or column group markers.
-@end table
-
-Finally, just to whet your appetite for what can be done with the
-fantastic Calc package, here is a table that computes the Taylor
-series of degree n at location x for a couple of functions.
-
-@example
-|---+-------------+---+-----+--------------------------------------|
-|   | Func        | n | x   | Result                               |
-|---+-------------+---+-----+--------------------------------------|
-| # | exp(x)      | 1 | x   | 1 + x                                |
-| # | exp(x)      | 2 | x   | 1 + x + x^2 / 2                      |
-| # | exp(x)      | 3 | x   | 1 + x + x^2 / 2 + x^3 / 6            |
-| # | x^2+sqrt(x) | 2 | x=0 | x*(0.5 / 0) + x^2 (2 - 0.25 / 0) / 2 |
-| # | x^2+sqrt(x) | 2 | x=1 | 2 + 2.5 x - 2.5 + 0.875 (x - 1)^2    |
-| * | tan(x)      | 3 | x   | 0.0175 x + 1.77e-6 x^3               |
-|---+-------------+---+-----+--------------------------------------|
-#+TBLFM: $5=taylor($2,$4,$3);n3
-@end example
-
-@node Org Plot
-@section Org Plot
-
-@cindex graph, in tables
-@cindex plot tables using Gnuplot
-
-Org Plot can produce graphs of information stored in Org tables,
-either graphically or in ASCII art.
-
-@anchor{Graphical plots using Gnuplot}
-@subheading Graphical plots using Gnuplot
-
-@cindex @samp{PLOT}, keyword
-Org Plot can produce 2D and 3D graphs of information stored in Org
-tables using @uref{http://www.gnuplot.info/, Gnuplot} and 
@uref{http://cars9.uchicago.edu/~ravel/software/gnuplot-mode.html, Gnuplot 
mode}.  To see this in action, ensure
-that you have both Gnuplot and Gnuplot mode installed on your system,
-then call @kbd{C-c " g} or @kbd{M-x org-plot/gnuplot} on the
-following table.
-
-@example
-#+PLOT: title:"Citas" ind:1 deps:(3) type:2d with:histograms set:"yrange [0:]"
-| Sede      | Max cites | H-index |
-|-----------+-----------+---------|
-| Chile     |    257.72 |   21.39 |
-| Leeds     |    165.77 |   19.68 |
-| Sao Paolo |     71.00 |   11.50 |
-| Stockholm |    134.19 |   14.33 |
-| Morelia   |    257.56 |   17.67 |
-@end example
-
-Notice that Org Plot is smart enough to apply the table's headers as
-labels.  Further control over the labels, type, content, and
-appearance of plots can be exercised through the @samp{PLOT} keyword
-preceding a table.  See below for a complete list of Org Plot options.
-For more information and examples see the 
@uref{https://orgmode.org/worg/org-tutorials/org-plot.html, Org Plot tutorial}.
-
-@anchor{Plot options}
-@subsubheading Plot options
-
-@table @asis
-@item @samp{set}
-Specify any Gnuplot option to be set when graphing.
-
-@item @samp{title}
-Specify the title of the plot.
-
-@item @samp{ind}
-Specify which column of the table to use as the @samp{x} axis.
-
-@item @samp{deps}
-Specify the columns to graph as a Lisp style list, surrounded by
-parentheses and separated by spaces for example @samp{dep:(3 4)} to graph
-the third and fourth columns.  Defaults to graphing all other
-columns aside from the @samp{ind} column.
-
-@item @samp{type}
-Specify whether the plot is @samp{2d}, @samp{3d}, or @samp{grid}.
-
-@item @samp{with}
-Specify a @samp{with} option to be inserted for every column being
-plotted, e.g., @samp{lines}, @samp{points}, @samp{boxes}, @samp{impulses}.  
Defaults to
-@samp{lines}.
-
-@item @samp{file}
-If you want to plot to a file, specify
-@samp{"path/to/desired/output-file"}.
-
-@item @samp{labels}
-List of labels to be used for the @samp{deps}.  Defaults to the column
-headers if they exist.
-
-@item @samp{line}
-Specify an entire line to be inserted in the Gnuplot script.
-
-@item @samp{map}
-When plotting @samp{3d} or @samp{grid} types, set this to @samp{t} to graph a 
flat
-mapping rather than a @samp{3d} slope.
-
-@item @samp{timefmt}
-Specify format of Org mode timestamps as they will be parsed by
-Gnuplot.  Defaults to @samp{%Y-%m-%d-%H:%M:%S}.
-
-@item @samp{script}
-If you want total control, you can specify a script file---place the
-file name between double-quotes---which will be used to plot.
-Before plotting, every instance of @samp{$datafile} in the specified
-script will be replaced with the path to the generated data file.
-Note: even if you set this option, you may still want to specify the
-plot type, as that can impact the content of the data file.
-@end table
-
-@anchor{ASCII bar plots}
-@subheading ASCII bar plots
-
-While point is on a column, typing @kbd{C-c `` a} or @kbd{M-x 
orgtbl-ascii-plot} create a new column containing an ASCII-art bars
-plot.  The plot is implemented through a regular column formula.  When
-the source column changes, the bar plot may be updated by refreshing
-the table, for example typing @kbd{C-u C-c *}.
-
-@example
-| Sede          | Max cites |              |
-|---------------+-----------+--------------|
-| Chile         |    257.72 | WWWWWWWWWWWW |
-| Leeds         |    165.77 | WWWWWWWh     |
-| Sao Paolo     |     71.00 | WWW;         |
-| Stockholm     |    134.19 | WWWWWW:      |
-| Morelia       |    257.56 | WWWWWWWWWWWH |
-| Rochefourchat |      0.00 |              |
-#+TBLFM: $3='(orgtbl-ascii-draw $2 0.0 257.72 12)
-@end example
-
-The formula is an Elisp call.
-
-@defun orgtbl-ascii-draw value min max &optional width
-Draw an ASCII bar in a table.
-
-@var{VALUE} is the value to plot.
-
-@var{MIN} is the value displayed as an empty bar.  @var{MAX}
-is the value filling all the @var{WIDTH}.  Sources values outside
-this range are displayed as @samp{too small} or @samp{too large}.
-
-@var{WIDTH} is the number of characters of the bar plot.  It
-defaults to @samp{12}.
-@end defun
-
-@node Hyperlinks
-@chapter Hyperlinks
-
-@cindex hyperlinks
-
-Like HTML, Org provides support for links inside a file, external
-links to other files, Usenet articles, emails, and much more.
-
-@menu
-* Link Format::                  How links in Org are formatted.
-* Internal Links::               Links to other places in the current file.
-* Radio Targets::                Make targets trigger links in plain text.
-* External Links::               URL-like links to the world.
-* Handling Links::               Creating, inserting and following.
-* Using Links Outside Org::      Linking from my C source code?
-* Link Abbreviations::           Shortcuts for writing complex links.
-* Search Options::               Linking to a specific location.
-* Custom Searches::              When the default search is not enough.
-@end menu
-
-@node Link Format
-@section Link Format
-
-@cindex link format
-@cindex format, of links
-
-@cindex angle bracket links
-@cindex plain links
-Org recognizes plain URIs, possibly wrapped within angle
-brackets@footnote{Plain URIs are recognized only for a well-defined set of
-schemes.  See @ref{External Links}.  Unlike URI syntax, they cannot contain
-parenthesis or white spaces, either.  URIs within angle brackets have
-no such limitation.}, and activate them as clickable links.
-
-@cindex bracket links
-The general link format, however, looks like this:
-
-@example
-[[LINK][DESCRIPTION]]
-@end example
-
-
-@noindent
-or alternatively
-
-@example
-[[LINK]]
-@end example
-
-
-@cindex escape syntax, for links
-@cindex backslashes, in links
-Some @samp{\}, @samp{[} and @samp{]} characters in the @var{LINK} part need to
-be ``escaped'', i.e., preceded by another @samp{\} character.  More
-specifically, the following characters, and only them, must be
-escaped:
-
-@enumerate
-@item
-all @samp{[} and @samp{]} characters,
-@item
-every @samp{\} character preceding either @samp{]} or @samp{[},
-@item
-every @samp{\} character at the end of the link.
-@end enumerate
-
-@findex org-link-escape
-Functions inserting links (see @ref{Handling Links}) properly escape
-ambiguous characters.  You only need to bother about the rules above
-when inserting directly, or yanking, a URI within square brackets.
-When in doubt, you may use the function @code{org-link-escape}, which turns
-a link string into its escaped form.
-
-Once a link in the buffer is complete, with all brackets present, Org
-changes the display so that @samp{DESCRIPTION} is displayed instead of
-@samp{[[LINK][DESCRIPTION]]} and @samp{LINK} is displayed instead of 
@samp{[[LINK]]}.
-Links are highlighted in the @code{org-link} face, which, by default, is an
-underlined face.
-
-You can directly edit the visible part of a link.  This can be either
-the @var{LINK} part, if there is no description, or the
-@var{DESCRIPTION} part otherwise.  To also edit the invisible
-@var{LINK} part, use @kbd{C-c C-l} with point on the link
-(see @ref{Handling Links}).
-
-If you place point at the beginning or just behind the end of the
-displayed text and press @kbd{@key{BS}}, you remove
-the---invisible---bracket at that location@footnote{More accurately, the 
precise behavior depends on how point
-arrived there---see @ref{Invisible Text,Invisible Text,,elisp,}.}.  This makes 
the link
-incomplete and the internals are again displayed as plain text.
-Inserting the missing bracket hides the link internals again.  To show
-the internal structure of all links, use the menu: Org @arrow{} Hyperlinks 
@arrow{}
-Literal links.
-
-@node Internal Links
-@section Internal Links
-
-@cindex internal links
-@cindex links, internal
-
-A link that does not look like a URL---i.e., does not start with
-a known scheme or a file name---refers to the current document.  You
-can follow it with @kbd{C-c C-o} when point is on the link, or
-with a mouse click (see @ref{Handling Links}).
-
-@cindex @samp{CUSTOM_ID}, property
-Org provides several refinements to internal navigation within
-a document.  Most notably, a construct like @samp{[[#my-custom-id]]}
-specifically targets the entry with the @samp{CUSTOM_ID} property set to
-@samp{my-custom-id}.  Also, an internal link looking like @samp{[[*Some
-section]]} points to a headline with the name @samp{Some section}@footnote{To 
insert a link targeting a headline, in-buffer completion
-can be used.  Just type a star followed by a few optional letters into
-the buffer and press @kbd{M-@key{TAB}}.  All headlines in the current
-buffer are offered as completions.}.
-
-@cindex targets, for links
-When the link does not belong to any of the cases above, Org looks for
-a @emph{dedicated target}: the same string in double angular brackets, like
-@samp{<<My Target>>}.
-
-@cindex @samp{NAME}, keyword
-If no dedicated target exists, the link tries to match the exact name
-of an element within the buffer.  Naming is done, unsurprisingly, with
-the @samp{NAME} keyword, which has to be put in the line before the element
-it refers to, as in the following example
-
-@example
-#+NAME: My Target
-| a  | table      |
-|----+------------|
-| of | four cells |
-@end example
-
-@vindex org-link-search-must-match-exact-headline
-Ultimately, if none of the above succeeds, Org searches for a headline
-that is exactly the link text but may also include a TODO keyword and
-tags, or initiates a plain text search, according to the value of
-@code{org-link-search-must-match-exact-headline}.
-
-Note that you must make sure custom IDs, dedicated targets, and names
-are unique throughout the document.  Org provides a linter to assist
-you in the process, if needed.  See @ref{Org Syntax}.
-
-During export, internal links are used to mark objects and assign them
-a number.  Marked objects are then referenced by links pointing to
-them.  In particular, links without a description appear as the number
-assigned to the marked object@footnote{When targeting a @samp{NAME} keyword, 
the @samp{CAPTION} keyword is
-mandatory in order to get proper numbering (see @ref{Captions}).}.  In the 
following excerpt from
-an Org buffer
-
-@example
-1. one item
-2. <<target>>another item
-Here we refer to item [[target]].
-@end example
-
-@noindent
-The last sentence will appear as @samp{Here we refer to item 2} when
-exported.
-
-In non-Org files, the search looks for the words in the link text.  In
-the above example the search would be for @samp{target}.
-
-Following a link pushes a mark onto Org's own mark ring.  You can
-return to the previous position with @kbd{C-c &}.  Using this
-command several times in direct succession goes back to positions
-recorded earlier.
-
-@node Radio Targets
-@section Radio Targets
-
-@cindex radio targets
-@cindex targets, radio
-@cindex links, radio targets
-
-Org can automatically turn any occurrences of certain target names in
-normal text into a link.  So without explicitly creating a link, the
-text connects to the target radioing its position.  Radio targets are
-enclosed by triple angular brackets.  For example, a target @samp{<<<My
-Target>>>} causes each occurrence of @samp{my target} in normal text to
-become activated as a link.  The Org file is scanned automatically for
-radio targets only when the file is first loaded into Emacs.  To
-update the target list during editing, press @kbd{C-c C-c} with
-point on or at a target.
-
-@node External Links
-@section External Links
-
-@cindex links, external
-@cindex external links
-@cindex attachment links
-@cindex BBDB links
-@cindex Elisp links
-@cindex file links
-@cindex Gnus links
-@cindex Help links
-@cindex IRC links
-@cindex Info links
-@cindex MH-E links
-@cindex Rmail links
-@cindex shell links
-@cindex URL links
-@cindex Usenet links
-
-Org supports links to files, websites, Usenet and email messages, BBDB
-database entries and links to both IRC conversations and their logs.
-External links are URL-like locators.  They start with a short
-identifying string followed by a colon.  There can be no space after
-the colon.
-
-Here is the full set of built-in link types:
-
-@table @asis
-@item @samp{file}
-File links.  File name may be remote, absolute, or relative.
-
-Additionally, you can specify a line number, or a text search.
-In Org files, you may link to a headline name, a custom ID, or a
-code reference instead.
-
-As a special case, ``file'' prefix may be omitted if the file name
-is complete, e.g., it starts with @samp{./}, or @samp{/}.
-
-@item @samp{attachment}
-Same as file links but for files and folders attached to the current
-node (see @ref{Attachments}).  Attachment links are intended to behave
-exactly as file links but for files relative to the attachment
-directory.
-
-@item @samp{bbdb}
-Link to a BBDB record, with possible regexp completion.
-
-@item @samp{docview}
-Link to a document opened with DocView mode.  You may specify a page
-number.
-
-@item @samp{doi}
-Link to an electronic resource, through its handle.
-
-@item @samp{elisp}
-Execute an Elisp command upon activation.
-
-@item @samp{gnus}, @samp{rmail}, @samp{mhe}
-Link to messages or folders from a given Emacs' MUA@.
-
-@item @samp{help}
-Display documentation of a symbol in @samp{*Help*} buffer.
-
-@item @samp{http}, @samp{https}
-Web links.
-
-@item @samp{id}
-Link to a specific headline by its ID property, in an Org file.
-
-@item @samp{info}
-Link to an Info manual, or to a specific node.
-
-@item @samp{irc}
-Link to an IRC channel.
-
-@item @samp{mailto}
-Link to message composition.
-
-@item @samp{news}
-Usenet links.
-
-@item @samp{shell}
-Execute a shell command upon activation.
-@end table
-
-The following table illustrates the link types above, along with their
-options:
-
-@multitable {aaaaaaaaaa} 
{aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa}
-@headitem Link Type
-@tab Example
-@item http
-@tab @samp{http://staff.science.uva.nl/c.dominik/}
-@item https
-@tab @samp{https://orgmode.org/}
-@item doi
-@tab @samp{doi:10.1000/182}
-@item file
-@tab @samp{file:/home/dominik/images/jupiter.jpg}
-@item
-@tab @samp{/home/dominik/images/jupiter.jpg} (same as above)
-@item
-@tab @samp{file:papers/last.pdf}
-@item
-@tab @samp{./papers/last.pdf} (same as above)
-@item
-@tab @samp{file:/ssh:me@@some.where:papers/last.pdf} (remote)
-@item
-@tab @samp{/ssh:me@@some.where:papers/last.pdf} (same as above)
-@item
-@tab @samp{file:sometextfile::NNN} (jump to line number)
-@item
-@tab @samp{file:projects.org}
-@item
-@tab @samp{file:projects.org::some words} (text search)@footnote{The actual 
behavior of the search depends on the value of the
-variable @code{org-link-search-must-match-exact-headline}.  If its value is
-@code{nil}, then a fuzzy text search is done.  If it is @code{t}, then only the
-exact headline is matched, ignoring spaces and statistic cookies.  If
-the value is @code{query-to-create}, then an exact headline is searched; if
-it is not found, then the user is queried to create it.}
-@item
-@tab @samp{file:projects.org::*task title} (headline search)
-@item
-@tab @samp{file:projects.org::#custom-id} (headline search)
-@item attachment
-@tab @samp{attachment:projects.org}
-@item
-@tab @samp{attachment:projects.org::some words} (text search)
-@item docview
-@tab @samp{docview:papers/last.pdf::NNN}
-@item id
-@tab @samp{id:B7423F4D-2E8A-471B-8810-C40F074717E9}
-@item news
-@tab @samp{news:comp.emacs}
-@item mailto
-@tab @samp{mailto:adent@@galaxy.net}
-@item mhe
-@tab @samp{mhe:folder} (folder link)
-@item
-@tab @samp{mhe:folder#id} (message link)
-@item rmail
-@tab @samp{rmail:folder} (folder link)
-@item
-@tab @samp{rmail:folder#id} (message link)
-@item gnus
-@tab @samp{gnus:group} (group link)
-@item
-@tab @samp{gnus:group#id} (article link)
-@item bbdb
-@tab @samp{bbdb:R.*Stallman} (record with regexp)
-@item irc
-@tab @samp{irc:/irc.com/#emacs/bob}
-@item help
-@tab @samp{help:org-store-link}
-@item info
-@tab @samp{info:org#External links}
-@item shell
-@tab @samp{shell:ls *.org}
-@item elisp
-@tab @samp{elisp:(find-file "Elisp.org")} (Elisp form to evaluate)
-@item
-@tab @samp{elisp:org-agenda} (interactive Elisp command)
-@end multitable
-
-@cindex VM links
-@cindex Wanderlust links
-On top of these built-in link types, additional ones are available
-through the @samp{contrib/} directory (see @ref{Installation}).  For example,
-these links to VM or Wanderlust messages are available when you load
-the corresponding libraries from the @samp{contrib/} directory:
-
-@multitable {aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa} {aaaaaaaaaaaaaaaaaaaaaaa}
-@item @samp{vm:folder}
-@tab VM folder link
-@item @samp{vm:folder#id}
-@tab VM message link
-@item @samp{vm://myself@@some.where.org/folder#id}
-@tab VM on remote machine
-@item @samp{vm-imap:account:folder}
-@tab VM IMAP folder link
-@item @samp{vm-imap:account:folder#id}
-@tab VM IMAP message link
-@item @samp{wl:folder}
-@tab Wanderlust folder link
-@item @samp{wl:folder#id}
-@tab Wanderlust message link
-@end multitable
-
-For information on customizing Org to add new link types, see @ref{Adding 
Hyperlink Types}.
-
-A link should be enclosed in double brackets and may contain
-descriptive text to be displayed instead of the URL (see @ref{Link Format}), 
for example:
-
-@example
-[[https://www.gnu.org/software/emacs/][GNU Emacs]]
-@end example
-
-
-If the description is a file name or URL that points to an image, HTML
-export (see @ref{HTML Export}) inlines the image as a clickable button.  If
-there is no description at all and the link points to an image, that
-image is inlined into the exported HTML file.
-
-@cindex square brackets, around links
-@cindex angular brackets, around links
-@cindex plain text external links
-Org also recognizes external links amid normal text and activates them
-as links.  If spaces must be part of the link (for example in
-@samp{bbdb:R.*Stallman}), or if you need to remove ambiguities about the
-end of the link, enclose the link in square or angular brackets.
-
-@node Handling Links
-@section Handling Links
-
-@cindex links, handling
-
-Org provides methods to create a link in the correct syntax, to insert
-it into an Org file, and to follow the link.
-
-@findex org-store-link
-@cindex storing links
-The main function is @code{org-store-link}, called with @kbd{M-x 
org-store-link}.  Because of its importance, we suggest to bind it
-to a widely available key (see @ref{Activation}).  It stores a link to the
-current location.  The link is stored for later insertion into an Org
-buffer---see below.  The kind of link that is created depends on the
-current buffer:
-
-@table @asis
-@item @emph{Org mode buffers}
-For Org files, if there is a @samp{<<target>>} at point, the link points
-to the target.  Otherwise it points to the current headline, which
-is also the description@footnote{If the headline contains a timestamp, it is 
removed from the
-link, which results in a wrong link---you should avoid putting
-a timestamp in the headline.}.
-
-@vindex org-id-link-to-org-use-id
-@cindex @samp{CUSTOM_ID}, property
-@cindex @samp{ID}, property
-If the headline has a @samp{CUSTOM_ID} property, store a link to this
-custom ID@.  In addition or alternatively, depending on the value of
-@code{org-id-link-to-org-use-id}, create and/or use a globally unique
-@samp{ID} property for the link@footnote{The Org Id library must first be 
loaded, either through
-@code{org-customize}, by enabling @code{id} in @code{org-modules}, or by adding
-@samp{(require 'org-id)} in your Emacs init file.}.  So using this command in 
Org
-buffers potentially creates two links: a human-readable link from
-the custom ID, and one that is globally unique and works even if the
-entry is moved from file to file.  Later, when inserting the link,
-you need to decide which one to use.
-
-@item @emph{Email/News clients: VM, Rmail, Wanderlust, MH-E, Gnus}
-@vindex org-link-email-description-format
-Pretty much all Emacs mail clients are supported.  The link points
-to the current article, or, in some Gnus buffers, to the group.  The
-description is constructed according to the variable
-@code{org-link-email-description-format}.  By default, it refers to the
-addressee and the subject.
-
-@item @emph{Web browsers: W3, W3M and EWW}
-Here the link is the current URL, with the page title as the
-description.
-
-@item @emph{Contacts: BBDB}
-Links created in a BBDB buffer point to the current entry.
-
-@item @emph{Chat: IRC}
-@vindex org-irc-links-to-logs
-For IRC links, if the variable @code{org-irc-link-to-logs} is non-@code{nil},
-create a @samp{file} style link to the relevant point in the logs for the
-current conversation.  Otherwise store an @samp{irc} style link to the
-user/channel/server under the point.
-
-@item @emph{Other files}
-For any other file, the link points to the file, with a search
-string (see @ref{Search Options}) pointing to the contents
-of the current line.  If there is an active region, the selected
-words form the basis of the search string.  You can write custom Lisp
-functions to select the search string and perform the search for
-particular file types (see @ref{Custom Searches}).
-
-You can also define dedicated links to other files.  See @ref{Adding Hyperlink 
Types}.
-
-@item @emph{Agenda view}
-When point is in an agenda view, the created link points to the
-entry referenced by the current line.
-@end table
-
-From an Org buffer, the following commands create, navigate or, more
-generally, act on links.
-
-@table @asis
-@item @kbd{C-c C-l} (@code{org-insert-link})
-@kindex C-c C-l
-@findex org-insert-link
-@cindex link completion
-@cindex completion, of links
-@cindex inserting links
-@vindex org-link-keep-stored-after-insertion
-Insert a link@footnote{Note that you do not have to use this command to insert
-a link.  Links in Org are plain text, and you can type or paste them
-straight into the buffer.  By using this command, the links are
-automatically enclosed in double brackets, and you will be asked for
-the optional descriptive text.}.  This prompts for a link to be inserted into
-the buffer.  You can just type a link, using text for an internal
-link, or one of the link type prefixes mentioned in the examples
-above.  The link is inserted into the buffer, along with
-a descriptive text@footnote{After insertion of a stored link, the link will be 
removed
-from the list of stored links.  To keep it in the list for later use,
-use a triple @kbd{C-u} prefix argument to @kbd{C-c C-l}, or
-configure the option @code{org-link-keep-stored-after-insertion}.}.  If some 
text was selected at this time,
-it becomes the default description.
-
-@table @asis
-@item @emph{Inserting stored links}
-All links stored during the current session are part of the
-history for this prompt, so you can access them with @kbd{@key{UP}}
-and @kbd{@key{DOWN}} (or @kbd{M-p}, @kbd{M-n}).
-
-@item @emph{Completion support}
-Completion with @kbd{@key{TAB}} helps you to insert valid link
-prefixes like @samp{http} or @samp{ftp}, including the prefixes defined
-through link abbreviations (see @ref{Link Abbreviations}).  If you
-press @kbd{@key{RET}} after inserting only the prefix, Org offers
-specific completion support for some link types@footnote{This works if a 
function has been defined in the @code{:complete}
-property of a link in @code{org-link-parameters}.}.  For
-example, if you type @kbd{f i l e @key{RET}}---alternative access:
-@kbd{C-u C-c C-l}, see below---Org offers file name
-completion, and after @kbd{b b d b @key{RET}} you can complete
-contact names.
-@end table
-
-@item @kbd{C-u C-c C-l}
-@cindex file name completion
-@cindex completion, of file names
-@kindex C-u C-c C-l
-When @kbd{C-c C-l} is called with a @kbd{C-u} prefix
-argument, insert a link to a file.  You may use file name completion
-to select the name of the file.  The path to the file is inserted
-relative to the directory of the current Org file, if the linked
-file is in the current directory or in a sub-directory of it, or if
-the path is written relative to the current directory using @samp{../}.
-Otherwise an absolute path is used, if possible with @samp{~/} for your
-home directory.  You can force an absolute path with two
-@kbd{C-u} prefixes.
-
-@item @kbd{C-c C-l} (with point on existing link)
-@cindex following links
-When point is on an existing link, @kbd{C-c C-l} allows you to
-edit the link and description parts of the link.
-
-@item @kbd{C-c C-o} (@code{org-open-at-point})
-@kindex C-c C-o
-@findex org-open-at-point
-@vindex org-file-apps
-Open link at point.  This launches a web browser for URL (using
-@code{browse-url-at-point}), run VM/MH-E/Wanderlust/Rmail/Gnus/BBDB for
-the corresponding links, and execute the command in a shell link.
-When point is on an internal link, this command runs the
-corresponding search.  When point is on the tags part of a headline,
-it creates the corresponding tags view (see @ref{Matching tags and 
properties}).  If point is on a timestamp, it compiles the agenda for
-that date.  Furthermore, it visits text and remote files in @samp{file}
-links with Emacs and select a suitable application for local
-non-text files.  Classification of files is based on file extension
-only.  See option @code{org-file-apps}.  If you want to override the
-default application and visit the file with Emacs, use
-a @kbd{C-u} prefix.  If you want to avoid opening in Emacs, use
-a @kbd{C-u C-u} prefix.
-
-@vindex org-link-frame-setup
-If point is on a headline, but not on a link, offer all links in the
-headline and entry text.  If you want to setup the frame
-configuration for following links, customize @code{org-link-frame-setup}.
-
-@item @kbd{@key{RET}}
-@vindex org-return-follows-link
-@kindex RET
-When @code{org-return-follows-link} is set, @kbd{@key{RET}} also follows
-the link at point.
-
-@item @kbd{mouse-2} or @kbd{mouse-1}
-@kindex mouse-2
-@kindex mouse-1
-On links, @kbd{mouse-1} and @kbd{mouse-2} opens the link
-just as @kbd{C-c C-o} does.
-
-@item @kbd{mouse-3}
-@vindex org-link-use-indirect-buffer-for-internals
-@kindex mouse-3
-Like @kbd{mouse-2}, but force file links to be opened with
-Emacs, and internal links to be displayed in another window@footnote{See the 
variable @code{org-link-use-indirect-buffer-for-internals}.}.
-
-@item @kbd{C-c %} (@code{org-mark-ring-push})
-@kindex C-c %
-@findex org-mark-ring-push
-@cindex mark ring
-Push the current position onto the Org mark ring, to be able to
-return easily.  Commands following an internal link do this
-automatically.
-
-@item @kbd{C-c &} (@code{org-mark-ring-goto})
-@kindex C-c &
-@findex org-mark-ring-goto
-@cindex links, returning to
-Jump back to a recorded position.  A position is recorded by the
-commands following internal links, and by @kbd{C-c %}.  Using
-this command several times in direct succession moves through a ring
-of previously recorded positions.
-
-@item @kbd{C-c C-x C-n} (@code{org-next-link})
-@itemx @kbd{C-c C-x C-p} (@code{org-previous-link})
-@kindex C-c C-x C-p
-@findex org-previous-link
-@kindex C-c C-x C-n
-@findex org-next-link
-@cindex links, finding next/previous
-Move forward/backward to the next link in the buffer.  At the limit
-of the buffer, the search fails once, and then wraps around.  The
-key bindings for this are really too long; you might want to bind
-this also to @kbd{M-n} and @kbd{M-p}.
-
-@lisp
-(with-eval-after-load 'org
-  (define-key org-mode-map (kbd "M-n") 'org-next-link)
-  (define-key org-mode-map (kbd "M-p") 'org-previous-link))
-@end lisp
-@end table
-
-@node Using Links Outside Org
-@section Using Links Outside Org
-
-@findex org-insert-link-global
-@findex org-open-at-point-global
-You can insert and follow links that have Org syntax not only in Org,
-but in any Emacs buffer.  For this, Org provides two functions:
-@code{org-insert-link-global} and @code{org-open-at-point-global}.
-
-You might want to bind them to globally available keys.  See
-@ref{Activation} for some advice.
-
-@node Link Abbreviations
-@section Link Abbreviations
-
-@cindex link abbreviations
-@cindex abbreviation, links
-
-Long URL can be cumbersome to type, and often many similar links are
-needed in a document.  For this you can use link abbreviations.  An
-abbreviated link looks like this
-
-@example
-[[linkword:tag][description]]
-@end example
-
-
-@noindent
-@vindex org-link-abbrev-alist
-where the tag is optional.  The @emph{linkword} must be a word, starting
-with a letter, followed by letters, numbers, @samp{-}, and @samp{_}.
-Abbreviations are resolved according to the information in the
-variable @code{org-link-abbrev-alist} that relates the linkwords to
-replacement text.  Here is an example:
-
-@lisp
-(setq org-link-abbrev-alist
-      '(("bugzilla"        . "http://10.1.2.9/bugzilla/show_bug.cgi?id=";)
-        ("Nu Html Checker" . "https://validator.w3.org/nu/?doc=%h";)
-        ("duckduckgo"      . "https://duckduckgo.com/?q=%s";)
-        ("omap"            . 
"http://nominatim.openstreetmap.org/search?q=%s&polygon=1";)
-        ("ads"             . 
"https://ui.adsabs.harvard.edu/search/q=%20author%3A\"%s\"";)))
-@end lisp
-
-If the replacement text contains the string @samp{%s}, it is replaced with
-the tag.  Using @samp{%h} instead of @samp{%s} percent-encodes the tag (see the
-example above, where we need to encode the URL parameter).  Using
-@samp{%(my-function)} passes the tag to a custom Lisp function, and replace
-it by the resulting string.
-
-If the replacement text do not contain any specifier, it is simply
-appended to the string in order to create the link.
-
-Instead of a string, you may also specify a Lisp function to create
-the link.  Such a function will be called with the tag as the only
-argument.
-
-With the above setting, you could link to a specific bug with
-@samp{[[bugzilla:129]]}, search the web for @samp{OrgMode} with 
@samp{[[duckduckgo:OrgMode]]},
-show the map location of the Free Software Foundation @samp{[[gmap:51
-Franklin Street, Boston]]} or of Carsten office @samp{[[omap:Science Park 904,
-Amsterdam, The Netherlands]]} and find out what the Org author is doing
-besides Emacs hacking with @samp{[[ads:Dominik,C]]}.
-
-If you need special abbreviations just for a single Org buffer, you
-can define them in the file with
-
-@cindex @samp{LINK}, keyword
-@example
-#+LINK: bugzilla   http://10.1.2.9/bugzilla/show_bug.cgi?id=
-#+LINK: duckduckgo https://duckduckgo.com/?q=%s
-@end example
-
-In-buffer completion (see @ref{Completion}) can be used after @samp{[} to
-complete link abbreviations.  You may also define a Lisp function that
-implements special (e.g., completion) support for inserting such a
-link with @kbd{C-c C-l}.  Such a function should not accept any
-arguments, and should return the full link with a prefix.  You can set
-the link completion function like this:
-
-@lisp
-(org-link-set-parameter "type" :complete #'some-completion-function)
-@end lisp
-
-@node Search Options
-@section Search Options in File Links
-
-@cindex search option in file links
-@cindex file links, searching
-@cindex attachment links, searching
-
-File links can contain additional information to make Emacs jump to a
-particular location in the file when following a link.  This can be a
-line number or a search option after a double colon@footnote{For backward 
compatibility, line numbers can also follow a
-single colon.}.  For
-example, when the command @code{org-store-link} creates a link (see
-@ref{Handling Links}) to a file, it encodes the words in the current line
-as a search string that can be used to find this line back later when
-following the link with @kbd{C-c C-o}.
-
-Note that all search options apply for Attachment links in the same
-way that they apply for File links.
-
-Here is the syntax of the different ways to attach a search to a file
-link, together with explanations for each:
-
-@example
-[[file:~/code/main.c::255]]
-[[file:~/xx.org::My Target]]
-[[file:~/xx.org::*My Target]]
-[[file:~/xx.org::#my-custom-id]]
-[[file:~/xx.org::/regexp/]]
-[[attachment:main.c::255]]
-@end example
-
-@table @asis
-@item @samp{255}
-Jump to line 255.
-
-@item @samp{My Target}
-Search for a link target @samp{<<My Target>>}, or do a text search for
-@samp{my target}, similar to the search in internal links, see @ref{Internal 
Links}.  In HTML export (see @ref{HTML Export}), such a file link becomes
-a HTML reference to the corresponding named anchor in the linked
-file.
-
-@item @samp{*My Target}
-In an Org file, restrict search to headlines.
-
-@item @samp{#my-custom-id}
-Link to a heading with a @samp{CUSTOM_ID} property
-
-@item @samp{/REGEXP/}
-Do a regular expression search for @var{REGEXP}.  This uses the
-Emacs command @code{occur} to list all matches in a separate window.  If
-the target file is in Org mode, @code{org-occur} is used to create
-a sparse tree with the matches.
-@end table
-
-As a degenerate case, a file link with an empty file name can be used
-to search the current file.  For example, @samp{[[file:::find me]]} does
-a search for @samp{find me} in the current file, just as @samp{[[find me]]}
-would.
-
-@node Custom Searches
-@section Custom Searches
-
-@cindex custom search strings
-@cindex search strings, custom
-
-The default mechanism for creating search strings and for doing the
-actual search related to a file link may not work correctly in all
-cases.  For example, Bib@TeX{} database files have many entries like
-@code{year="1993"} which would not result in good search strings, because
-the only unique identification for a Bib@TeX{} entry is the citation key.
-
-@vindex org-create-file-search-functions
-@vindex org-execute-file-search-functions
-If you come across such a problem, you can write custom functions to
-set the right search string for a particular file type, and to do the
-search for the string in the file.  Using @code{add-hook}, these functions
-need to be added to the hook variables
-@code{org-create-file-search-functions} and
-@code{org-execute-file-search-functions}.  See the docstring for these
-variables for more information.  Org actually uses this mechanism for
-Bib@TeX{} database files, and you can use the corresponding code as an
-implementation example.  See the file @samp{ol-bibtex.el}.
-
-@node TODO Items
-@chapter TODO Items
-
-@cindex TODO items
-
-Org mode does not maintain TODO lists as separate documents@footnote{Of 
course, you can make a document that contains only long
-lists of TODO items, but this is not required.}.
-Instead, TODO items are an integral part of the notes file, because
-TODO items usually come up while taking notes!  With Org mode, simply
-mark any entry in a tree as being a TODO item.  In this way,
-information is not duplicated, and the entire context from which the
-TODO item emerged is always present.
-
-Of course, this technique for managing TODO items scatters them
-throughout your notes file.  Org mode compensates for this by
-providing methods to give you an overview of all the things that you
-have to do.
-
-@menu
-* TODO Basics::                  Marking and displaying TODO entries.
-* TODO Extensions::              Workflow and assignments.
-* Progress Logging::             Dates and notes for progress.
-* Priorities::                   Some things are more important than others.
-* Breaking Down Tasks::          Splitting a task into manageable pieces.
-* Checkboxes::                   Tick-off lists.
-@end menu
-
-@node TODO Basics
-@section Basic TODO Functionality
-
-Any headline becomes a TODO item when it starts with the word @samp{TODO},
-for example:
-
-@example
-*** TODO Write letter to Sam Fortune
-@end example
-
-
-The most important commands to work with TODO entries are:
-
-@table @asis
-@item @kbd{C-c C-t} (@code{org-todo})
-@kindex C-c C-t
-@cindex cycling, of TODO states
-Rotate the TODO state of the current item among
-
-@example
-,-> (unmarked) -> TODO -> DONE --.
-'--------------------------------'
-@end example
-
-If TODO keywords have fast access keys (see @ref{Fast access to TODO states}), 
prompt for a TODO keyword through the fast selection
-interface; this is the default behavior when
-@code{org-use-fast-todo-selection} is non-@code{nil}.
-
-The same state changing can also be done ``remotely'' from the agenda
-buffer with the @kbd{t} command key (see @ref{Agenda Commands}).
-
-@item @kbd{S-@key{RIGHT}} @kbd{S-@key{LEFT}}
-@kindex S-RIGHT
-@kindex S-LEFT
-@vindex org-treat-S-cursor-todo-selection-as-state-change
-Select the following/preceding TODO state, similar to cycling.
-Useful mostly if more than two TODO states are possible (see
-@ref{TODO Extensions}).  See also @ref{Conflicts}, for a discussion of the 
interaction with
-shift-selection.  See also the variable
-@code{org-treat-S-cursor-todo-selection-as-state-change}.
-
-@item @kbd{C-c / t} (@code{org-show-todo-tree})
-@kindex C-c / t
-@cindex sparse tree, for TODO
-@vindex org-todo-keywords
-@findex org-show-todo-tree
-View TODO items in a @emph{sparse tree} (see @ref{Sparse Trees}).  Folds the
-entire buffer, but shows all TODO items---with not-DONE state---and
-the headings hierarchy above them.  With a prefix argument, or by
-using @kbd{C-c / T}, search for a specific TODO@.  You are
-prompted for the keyword, and you can also give a list of keywords
-like @samp{KWD1|KWD2|...} to list entries that match any one of these
-keywords.  With a numeric prefix argument N, show the tree for the
-Nth keyword in the variable @code{org-todo-keywords}.  With two prefix
-arguments, find all TODO states, both un-done and done.
-
-@item @kbd{M-x org-agenda t} (@code{org-todo-list})
-@kindex t @r{(Agenda dispatcher)}
-Show the global TODO list.  Collects the TODO items (with not-DONE
-states) from all agenda files (see @ref{Agenda Views}) into a single
-buffer.  The new buffer is in Org Agenda mode, which provides
-commands to examine and manipulate the TODO entries from the new
-buffer (see @ref{Agenda Commands}).  See @ref{Global TODO list}, for more 
information.
-
-@item @kbd{S-M-@key{RET}} (@code{org-insert-todo-heading})
-@kindex S-M-RET
-@findex org-insert-todo-heading
-Insert a new TODO entry below the current one.
-@end table
-
-@vindex org-todo-state-tags-triggers
-Changing a TODO state can also trigger tag changes.  See the docstring
-of the option @code{org-todo-state-tags-triggers} for details.
-
-@node TODO Extensions
-@section Extended Use of TODO Keywords
-
-@cindex extended TODO keywords
-
-@vindex org-todo-keywords
-By default, marked TODO entries have one of only two states: TODO and
-DONE@.  Org mode allows you to classify TODO items in more complex ways
-with @emph{TODO keywords} (stored in @code{org-todo-keywords}).  With special
-setup, the TODO keyword system can work differently in different
-files.
-
-Note that @emph{tags} are another way to classify headlines in general and
-TODO items in particular (see @ref{Tags}).
-
-@menu
-* Workflow states::              From TODO to DONE in steps.
-* TODO types::                   I do this, Fred does the rest.
-* Multiple sets in one file::    Mixing it all, still finding your way.
-* Fast access to TODO states::   Single letter selection of state.
-* Per-file keywords::            Different files, different requirements.
-* Faces for TODO keywords::      Highlighting states.
-* TODO dependencies::            When one task needs to wait for others.
-@end menu
-
-@node Workflow states
-@subsection TODO keywords as workflow states
-
-@cindex TODO workflow
-@cindex workflow states as TODO keywords
-
-You can use TODO keywords to indicate different, possibly @emph{sequential}
-states in the process of working on an item, for example@footnote{Changing the 
variable @code{org-todo-keywords} only becomes
-effective after restarting Org mode in a buffer.}:
-
-@lisp
-(setq org-todo-keywords
-      '((sequence "TODO" "FEEDBACK" "VERIFY" "|" "DONE" "DELEGATED")))
-@end lisp
-
-The vertical bar separates the TODO keywords (states that @emph{need
-action}) from the DONE states (which need @emph{no further action}).  If
-you do not provide the separator bar, the last state is used as the
-DONE state.
-
-@cindex completion, of TODO keywords
-With this setup, the command @kbd{C-c C-t} cycles an entry from
-@samp{TODO} to @samp{FEEDBACK}, then to @samp{VERIFY}, and finally to 
@samp{DONE} and
-@samp{DELEGATED}.  You may also use a numeric prefix argument to quickly
-select a specific state.  For example @kbd{C-3 C-c C-t} changes
-the state immediately to @samp{VERIFY}.  Or you can use @kbd{S-@key{RIGHT}}
-and @kbd{S-@key{LEFT}} to go forward and backward through the states.
-If you define many keywords, you can use in-buffer completion (see
-@ref{Completion}) or a special one-key selection scheme (see @ref{Fast access 
to TODO states}) to insert these words into the buffer.
-Changing a TODO state can be logged with a timestamp, see @ref{Tracking TODO 
state changes}, for more information.
-
-@node TODO types
-@subsection TODO keywords as types
-
-@cindex TODO types
-@cindex names as TODO keywords
-@cindex types as TODO keywords
-
-The second possibility is to use TODO keywords to indicate different
-@emph{types} of action items.  For example, you might want to indicate that
-items are for ``work'' or ``home''.  Or, when you work with several people
-on a single project, you might want to assign action items directly to
-persons, by using their names as TODO keywords.  This type of
-functionality is actually much better served by using tags (see
-@ref{Tags}), so the TODO implementation is kept just for backward
-compatibility.
-
-Using TODO types, it would be set up like this:
-
-@lisp
-(setq org-todo-keywords '((type "Fred" "Sara" "Lucy" "|" "DONE")))
-@end lisp
-
-In this case, different keywords do not indicate states, but
-rather different types.  So the normal work flow would be to assign
-a task to a person, and later to mark it DONE@.  Org mode supports this
-style by adapting the workings of the command @kbd{C-c C-t}@footnote{This is 
also true for the @kbd{t} command in the agenda
-buffer.}.  When used several times in succession, it still
-cycles through all names, in order to first select the right type for
-a task.  But when you return to the item after some time and execute
-@kbd{C-c C-t} again, it will switch from any name directly to
-@samp{DONE}.  Use prefix arguments or completion to quickly select
-a specific name.  You can also review the items of a specific TODO
-type in a sparse tree by using a numeric prefix to @kbd{C-c / t}.
-For example, to see all things Lucy has to do, you would use
-@kbd{C-3 C-c / t}.  To collect Lucy's items from all agenda files
-into a single buffer, you would use the numeric prefix argument as
-well when creating the global TODO list: @kbd{C-3 M-x org-agenda t}.
-
-@node Multiple sets in one file
-@subsection Multiple keyword sets in one file
-
-@cindex TODO keyword sets
-
-Sometimes you may want to use different sets of TODO keywords in
-parallel.  For example, you may want to have the basic TODO/DONE, but
-also a workflow for bug fixing, and a separate state indicating that
-an item has been canceled---so it is not DONE, but also does not
-require action.  Your setup would then look like this:
-
-@lisp
-(setq org-todo-keywords
-      '((sequence "TODO" "|" "DONE")
-        (sequence "REPORT" "BUG" "KNOWNCAUSE" "|" "FIXED")
-        (sequence "|" "CANCELED")))
-@end lisp
-
-The keywords should all be different, this helps Org mode keep track
-of which subsequence should be used for a given entry.  In this setup,
-@kbd{C-c C-t} only operates within a sub-sequence, so it switches
-from @samp{DONE} to (nothing) to @samp{TODO}, and from @samp{FIXED} to 
(nothing) to
-@samp{REPORT}.  Therefore you need a mechanism to initially select the
-correct sequence.  In addition to typing a keyword or using completion
-(see @ref{Completion}), you may also apply the following commands:
-
-@table @asis
-@item @kbd{C-u C-u C-c C-t}
-@itemx @kbd{C-S-@key{RIGHT}}
-@itemx @kbd{C-S-@key{LEFT}}
-@kindex C-S-RIGHT
-@kindex C-S-LEFT
-@kindex C-u C-u C-c C-t
-These keys jump from one TODO sub-sequence to the next.  In the
-above example, @kbd{C-u C-u C-c C-t} or @kbd{C-S-@key{RIGHT}}
-would jump from @samp{TODO} or @samp{DONE} to @samp{REPORT}, and any of the 
words
-in the second row to @samp{CANCELED}.  Note that the @kbd{C-S-} key
-binding conflict with shift-selection (see @ref{Conflicts}).
-
-@item @kbd{S-@key{RIGHT}}
-@itemx @kbd{S-@key{LEFT}}
-@kindex S-RIGHT
-@kindex S-LEFT
-@kbd{S-@key{LEFT}} and @kbd{S-@key{RIGHT}} walk through @emph{all} keywords
-from all sub-sequences, so for example @kbd{S-@key{RIGHT}} would
-switch from @samp{DONE} to @samp{REPORT} in the example above.  For
-a discussion of the interaction with shift-selection, see @ref{Conflicts}.
-@end table
-
-@node Fast access to TODO states
-@subsection Fast access to TODO states
-
-If you would like to quickly change an entry to an arbitrary TODO
-state instead of cycling through the states, you can set up keys for
-single-letter access to the states.  This is done by adding the
-selection character after each keyword, in parentheses@footnote{All characters 
are allowed except @samp{@@}, @samp{^} and @samp{!}, which have
-a special meaning here.}.  For
-example:
-
-@lisp
-(setq org-todo-keywords
-      '((sequence "TODO(t)" "|" "DONE(d)")
-        (sequence "REPORT(r)" "BUG(b)" "KNOWNCAUSE(k)" "|" "FIXED(f)")
-        (sequence "|" "CANCELED(c)")))
-@end lisp
-
-@vindex org-fast-tag-selection-include-todo
-If you then press @kbd{C-c C-t} followed by the selection key,
-the entry is switched to this state.  @kbd{@key{SPC}} can be used to
-remove any TODO keyword from an entry@footnote{Check also the variable 
@code{org-fast-tag-selection-include-todo},
-it allows you to change the TODO state through the tags interface (see
-@ref{Setting Tags}), in case you like to mingle the two concepts.  Note
-that this means you need to come up with unique keys across both sets
-of keywords.}.
-
-@node Per-file keywords
-@subsection Setting up keywords for individual files
-
-@cindex keyword options
-@cindex per-file keywords
-@cindex @samp{TODO}, keyword
-@cindex @samp{TYP_TODO}, keyword
-@cindex @samp{SEQ_TODO}, keyword
-
-It can be very useful to use different aspects of the TODO mechanism
-in different files.  For file-local settings, you need to add special
-lines to the file which set the keywords and interpretation for that
-file only.  For example, to set one of the two examples discussed
-above, you need one of the following lines, starting in column zero
-anywhere in the file:
-
-@example
-#+TODO: TODO FEEDBACK VERIFY | DONE CANCELED
-@end example
-
-
-You may also write @samp{#+SEQ_TODO} to be explicit about the
-interpretation, but it means the same as @samp{#+TODO}, or
-
-@example
-#+TYP_TODO: Fred Sara Lucy Mike | DONE
-@end example
-
-
-A setup for using several sets in parallel would be:
-
-@example
-#+TODO: TODO | DONE
-#+TODO: REPORT BUG KNOWNCAUSE | FIXED
-#+TODO: | CANCELED
-@end example
-
-@cindex completion, of option keywords
-@kindex M-TAB
-To make sure you are using the correct keyword, type @samp{#+} into the
-buffer and then use @kbd{M-@key{TAB}} to complete it (see @ref{Completion}).
-
-@cindex DONE, final TODO keyword
-Remember that the keywords after the vertical bar---or the last
-keyword if no bar is there---must always mean that the item is DONE,
-although you may use a different word.  After changing one of these
-lines, use @kbd{C-c C-c} with point still in the line to make the
-changes known to Org mode@footnote{Org mode parses these lines only when Org 
mode is activated
-after visiting a file.  @kbd{C-c C-c} with point in a line
-starting with @samp{#+} is simply restarting Org mode for the current
-buffer.}.
-
-@node Faces for TODO keywords
-@subsection Faces for TODO keywords
-
-@cindex faces, for TODO keywords
-
-@vindex org-todo, face
-@vindex org-done, face
-@vindex org-todo-keyword-faces
-Org mode highlights TODO keywords with special faces: @code{org-todo} for
-keywords indicating that an item still has to be acted upon, and
-@code{org-done} for keywords indicating that an item is finished.  If you
-are using more than two different states, you might want to use
-special faces for some of them.  This can be done using the variable
-@code{org-todo-keyword-faces}.  For example:
-
-@lisp
-(setq org-todo-keyword-faces
-      '(("TODO" . org-warning) ("STARTED" . "yellow")
-        ("CANCELED" . (:foreground "blue" :weight bold))))
-@end lisp
-
-@vindex org-faces-easy-properties
-While using a list with face properties as shown for @samp{CANCELED}
-@emph{should} work, this does not always seem to be the case.  If
-necessary, define a special face and use that.  A string is
-interpreted as a color.  The variable @code{org-faces-easy-properties}
-determines if that color is interpreted as a foreground or
-a background color.
-
-@node TODO dependencies
-@subsection TODO dependencies
-
-@cindex TODO dependencies
-@cindex dependencies, of TODO states
-
-@vindex org-enforce-todo-dependencies
-@cindex @samp{ORDERED}, property
-The structure of Org files---hierarchy and lists---makes it easy to
-define TODO dependencies.  Usually, a parent TODO task should not be
-marked as done until all TODO subtasks, or children tasks, are marked
-as done.  Sometimes there is a logical sequence to (sub)tasks, so that
-one subtask cannot be acted upon before all siblings above it have
-been marked as done.  If you customize the variable
-@code{org-enforce-todo-dependencies}, Org blocks entries from changing
-state to DONE while they have TODO children that are not DONE@.
-Furthermore, if an entry has a property @samp{ORDERED}, each of its TODO
-children is blocked until all earlier siblings are marked as done.
-Here is an example:
-
-@example
-* TODO Blocked until (two) is done
-** DONE one
-** TODO two
-
-* Parent
-:PROPERTIES:
-:ORDERED:  t
-:END:
-** TODO a
-** TODO b, needs to wait for (a)
-** TODO c, needs to wait for (a) and (b)
-@end example
-
-@cindex TODO dependencies, @samp{NOBLOCKING}
-@cindex @samp{NOBLOCKING}, property
-You can ensure an entry is never blocked by using the @samp{NOBLOCKING}
-property (see @ref{Properties and Columns}):
-
-@example
-* This entry is never blocked
-:PROPERTIES:
-:NOBLOCKING: t
-:END:
-@end example
-
-@table @asis
-@item @kbd{C-c C-x o} (@code{org-toggle-ordered-property})
-@kindex C-c C-x o
-@findex org-toggle-ordered-property
-@vindex org-track-ordered-property-with-tag
-Toggle the @samp{ORDERED} property of the current entry.  A property is
-used for this behavior because this should be local to the current
-entry, not inherited from entries above like a tag (see @ref{Tags}).
-However, if you would like to @emph{track} the value of this property
-with a tag for better visibility, customize the variable
-@code{org-track-ordered-property-with-tag}.
-
-@item @kbd{C-u C-u C-u C-c C-t}
-@kindex C-u C-u C-u C-u C-c C-t
-Change TODO state, regardless of any state blocking.
-@end table
-
-@vindex org-agenda-dim-blocked-tasks
-If you set the variable @code{org-agenda-dim-blocked-tasks}, TODO entries
-that cannot be marked as done because of unmarked children are shown
-in a dimmed font or even made invisible in agenda views (see @ref{Agenda 
Views}).
-
-@cindex checkboxes and TODO dependencies
-@vindex org-enforce-todo-dependencies
-You can also block changes of TODO states by using checkboxes (see
-@ref{Checkboxes}).  If you set the variable
-@code{org-enforce-todo-checkbox-dependencies}, an entry that has unchecked
-checkboxes is blocked from switching to DONE@.
-
-If you need more complex dependency structures, for example
-dependencies between entries in different trees or files, check out
-the contributed module @samp{org-depend.el}.
-
-@node Progress Logging
-@section Progress Logging
-
-@cindex progress logging
-@cindex logging, of progress
-
-To record a timestamp and a note when changing a TODO state, call the
-command @code{org-todo} with a prefix argument.
-
-@table @asis
-@item @kbd{C-u C-c C-t} (@code{org-todo})
-@kindex C-u C-c C-t
-Prompt for a note and record a the time of the TODO state change.
-The note is inserted as a list item below the headline, but can also
-be placed into a drawer, see @ref{Tracking TODO state changes}.
-@end table
-
-If you want to be more systematic, Org mode can automatically record a
-timestamp and optionally a note when you mark a TODO item as DONE, or
-even each time you change the state of a TODO item.  This system is
-highly configurable, settings can be on a per-keyword basis and can be
-localized to a file or even a subtree.  For information on how to
-clock working time for a task, see @ref{Clocking Work Time}.
-
-@menu
-* Closing items::                When was this entry marked as done?
-* Tracking TODO state changes::  When did the status change?
-* Tracking your habits::         How consistent have you been?
-@end menu
-
-@node Closing items
-@subsection Closing items
-
-The most basic automatic logging is to keep track of @emph{when} a certain
-TODO item was marked as done.  This can be achieved with@footnote{The 
corresponding in-buffer setting is: @samp{#+STARTUP: logdone}.}
-
-@lisp
-(setq org-log-done 'time)
-@end lisp
-
-@vindex org-closed-keep-when-no-todo
-@noindent
-Then each time you turn an entry from a TODO (not-done) state into any
-of the DONE states, a line @samp{CLOSED: [timestamp]} is inserted just
-after the headline.  If you turn the entry back into a TODO item
-through further state cycling, that line is removed again.  If you
-turn the entry back to a non-TODO state (by pressing @kbd{C-c C-t @key{SPC}} 
for example), that line is also removed, unless you set
-@code{org-closed-keep-when-no-todo} to non-@code{nil}.  If you want to record
-a note along with the timestamp, use@footnote{The corresponding in-buffer 
setting is: @samp{#+STARTUP:
-lognotedone}.}
-
-@lisp
-(setq org-log-done 'note)
-@end lisp
-
-@noindent
-You are then prompted for a note, and that note is stored below the
-entry with a @samp{Closing Note} heading.
-
-@node Tracking TODO state changes
-@subsection Tracking TODO state changes
-
-@cindex drawer, for state change recording
-
-@vindex org-log-states-order-reversed
-@vindex org-log-into-drawer
-@cindex @samp{LOG_INTO_DRAWER}, property
-You might want to automatically keep track of when a state change
-occurred and maybe take a note about this change.  You can either
-record just a timestamp, or a time-stamped note.  These records are
-inserted after the headline as an itemized list, newest first@footnote{See the 
variable @code{org-log-states-order-reversed}.}.
-When taking a lot of notes, you might want to get the notes out of the
-way into a drawer (see @ref{Drawers}).  Customize the variable
-@code{org-log-into-drawer} to get this behavior---the recommended drawer
-for this is called @samp{LOGBOOK}@footnote{Note that the @samp{LOGBOOK} drawer 
is unfolded when pressing
-@kbd{@key{SPC}} in the agenda to show an entry---use @kbd{C-u @key{SPC}} to 
keep it folded here.}.  You can also overrule the
-setting of this variable for a subtree by setting a @samp{LOG_INTO_DRAWER}
-property.
-
-Since it is normally too much to record a note for every state, Org
-mode expects configuration on a per-keyword basis for this.  This is
-achieved by adding special markers @samp{!} (for a timestamp) or @samp{@@} (for
-a note with timestamp) in parentheses after each keyword.  For
-example, with the setting
-
-@lisp
-(setq org-todo-keywords
-      '((sequence "TODO(t)" "WAIT(w@@/!)" "|" "DONE(d!)" "CANCELED(c@@)")))
-@end lisp
-
-@noindent
-To record a timestamp without a note for TODO keywords configured with
-@samp{@@}, just type @kbd{C-c C-c} to enter a blank note when prompted.
-
-@vindex org-log-done
-You not only define global TODO keywords and fast access keys, but
-also request that a time is recorded when the entry is set to @samp{DONE},
-and that a note is recorded when switching to @samp{WAIT} or
-@samp{CANCELED}@footnote{It is possible that Org mode records two timestamps 
when you
-are using both @code{org-log-done} and state change logging.  However, it
-never prompts for two notes: if you have configured both, the state
-change recording note takes precedence and cancel the closing note.}.  The 
setting for @samp{WAIT} is even more special: the
-@samp{!} after the slash means that in addition to the note taken when
-entering the state, a timestamp should be recorded when @emph{leaving} the
-@samp{WAIT} state, if and only if the @emph{target} state does not configure
-logging for entering it.  So it has no effect when switching from
-@samp{WAIT} to @samp{DONE}, because @samp{DONE} is configured to record a 
timestamp
-only.  But when switching from @samp{WAIT} back to @samp{TODO}, the @samp{/!} 
in the
-@samp{WAIT} setting now triggers a timestamp even though @samp{TODO} has no
-logging configured.
-
-You can use the exact same syntax for setting logging preferences local
-to a buffer:
-
-@example
-#+TODO: TODO(t) WAIT(w@@/!) | DONE(d!) CANCELED(c@@)
-@end example
-
-
-@cindex @samp{LOGGING}, property
-In order to define logging settings that are local to a subtree or
-a single item, define a @samp{LOGGING} property in this entry.  Any
-non-empty @samp{LOGGING} property resets all logging settings to @code{nil}.
-You may then turn on logging for this specific tree using @samp{STARTUP}
-keywords like @samp{lognotedone} or @samp{logrepeat}, as well as adding state
-specific settings like @samp{TODO(!)}.  For example:
-
-@example
-* TODO Log each state with only a time
-  :PROPERTIES:
-  :LOGGING: TODO(!) WAIT(!) DONE(!) CANCELED(!)
-  :END:
-* TODO Only log when switching to WAIT, and when repeating
-  :PROPERTIES:
-  :LOGGING: WAIT(@@) logrepeat
-  :END:
-* TODO No logging at all
-  :PROPERTIES:
-  :LOGGING: nil
-  :END:
-@end example
-
-@node Tracking your habits
-@subsection Tracking your habits
-
-@cindex habits
-@cindex @samp{STYLE}, property
-
-Org has the ability to track the consistency of a special category of
-TODO, called ``habits.''  To use habits, you have to enable the @code{habits}
-module by customizing the variable @code{org-modules}.
-
-A habit has the following properties:
-
-@enumerate
-@item
-The habit is a TODO item, with a TODO keyword representing an open
-state.
-
-@item
-The property @samp{STYLE} is set to the value @samp{habit} (see 
@ref{Properties and Columns}).
-
-@item
-The TODO has a scheduled date, usually with a @samp{.+} style repeat
-interval.  A @samp{++} style may be appropriate for habits with time
-constraints, e.g., must be done on weekends, or a @samp{+} style for an
-unusual habit that can have a backlog, e.g., weekly reports.
-
-@item
-The TODO may also have minimum and maximum ranges specified by
-using the syntax @samp{.+2d/3d}, which says that you want to do the task
-at least every three days, but at most every two days.
-
-@item
-State logging for the DONE state is enabled (see @ref{Tracking TODO state 
changes}), in order for historical data to be represented in
-the consistency graph.  If it is not enabled it is not an error,
-but the consistency graphs are largely meaningless.
-@end enumerate
-
-To give you an idea of what the above rules look like in action, here's an
-actual habit with some history:
-
-@example
-** TODO Shave
-   SCHEDULED: <2009-10-17 Sat .+2d/4d>
-   :PROPERTIES:
-   :STYLE:    habit
-   :LAST_REPEAT: [2009-10-19 Mon 00:36]
-   :END:
-   - State "DONE"       from "TODO"       [2009-10-15 Thu]
-   - State "DONE"       from "TODO"       [2009-10-12 Mon]
-   - State "DONE"       from "TODO"       [2009-10-10 Sat]
-   - State "DONE"       from "TODO"       [2009-10-04 Sun]
-   - State "DONE"       from "TODO"       [2009-10-02 Fri]
-   - State "DONE"       from "TODO"       [2009-09-29 Tue]
-   - State "DONE"       from "TODO"       [2009-09-25 Fri]
-   - State "DONE"       from "TODO"       [2009-09-19 Sat]
-   - State "DONE"       from "TODO"       [2009-09-16 Wed]
-   - State "DONE"       from "TODO"       [2009-09-12 Sat]
-@end example
-
-What this habit says is: I want to shave at most every 2 days---given
-by the @samp{SCHEDULED} date and repeat interval---and at least every
-4 days.  If today is the 15th, then the habit first appears in the
-agenda (see @ref{Agenda Views}) on Oct 17, after the minimum of 2 days has
-elapsed, and will appear overdue on Oct 19, after four days have
-elapsed.
-
-What's really useful about habits is that they are displayed along
-with a consistency graph, to show how consistent you've been at
-getting that task done in the past.  This graph shows every day that
-the task was done over the past three weeks, with colors for each day.
-The colors used are:
-
-@table @asis
-@item Blue
-If the task was not to be done yet on that day.
-@item Green
-If the task could have been done on that day.
-@item Yellow
-If the task was going to be overdue the next day.
-@item Red
-If the task was overdue on that day.
-@end table
-
-In addition to coloring each day, the day is also marked with an
-asterisk if the task was actually done that day, and an exclamation
-mark to show where the current day falls in the graph.
-
-There are several configuration variables that can be used to change
-the way habits are displayed in the agenda.
-
-@table @asis
-@item @code{org-habit-graph-column}
-@vindex org-habit-graph-column
-The buffer column at which the consistency graph should be drawn.
-This overwrites any text in that column, so it is a good idea to
-keep your habits' titles brief and to the point.
-
-@item @code{org-habit-preceding-days}
-@vindex org-habit-preceding-days
-The amount of history, in days before today, to appear in
-consistency graphs.
-
-@item @code{org-habit-following-days}
-@vindex org-habit-following-days
-The number of days after today that appear in consistency graphs.
-
-@item @code{org-habit-show-habits-only-for-today}
-@vindex org-habit-show-habits-only-for-today
-If non-@code{nil}, only show habits in today's agenda view.  The default
-value is @code{t}.  Pressing @kbd{C-u K} in the agenda toggles this
-variable.
-@end table
-
-Lastly, pressing @kbd{K} in the agenda buffer causes habits to
-temporarily be disabled and do not appear at all.  Press @kbd{K}
-again to bring them back.  They are also subject to tag filtering, if
-you have habits which should only be done in certain contexts, for
-example.
-
-@node Priorities
-@section Priorities
-
-@cindex priorities
-@cindex priority cookie
-
-If you use Org mode extensively, you may end up with enough TODO items
-that it starts to make sense to prioritize them.  Prioritizing can be
-done by placing a @emph{priority cookie} into the headline of a TODO item
-right after the TODO keyword, like this:
-
-@example
-*** TODO [#A] Write letter to Sam Fortune
-@end example
-
-
-@vindex org-priority-faces
-By default, Org mode supports three priorities: @samp{A}, @samp{B}, and 
@samp{C}.
-@samp{A} is the highest priority.  An entry without a cookie is treated as
-equivalent if it had priority @samp{B}.  Priorities make a difference only
-for sorting in the agenda (see @ref{Weekly/daily agenda}).  Outside the
-agenda, they have no inherent meaning to Org mode.  The cookies are
-displayed with the face defined by the variable @code{org-priority-faces},
-which can be customized.
-
-You can also use numeric values for priorities, such as
-
-@example
-*** TODO [#1] Write letter to Sam Fortune
-@end example
-
-
-When using numeric priorities, you need to set @code{org-priority-highest},
-@code{org-priority-lowest} and @code{org-priority-default} to integers, which
-must all be strictly inferior to 65.
-
-Priorities can be attached to any outline node; they do not need to be
-TODO items.
-
-@table @asis
-@item @kbd{C-c ,} (@code{org-priority})
-@kindex C-c ,
-@findex org-priority
-Set the priority of the current headline.  The command prompts for
-a priority character @samp{A}, @samp{B} or @samp{C}.  When you press 
@kbd{@key{SPC}}
-instead, the priority cookie, if one is set, is removed from the
-headline.  The priorities can also be changed ``remotely'' from the
-agenda buffer with the @kbd{,} command (see @ref{Agenda Commands}).
-
-@item @kbd{S-@key{UP}} (@code{org-priority-up})
-@itemx @kbd{S-@key{DOWN}} (@code{org-priority-down})
-@kindex S-UP
-@kindex S-DOWN
-@findex org-priority-up
-@findex org-priority-down
-@vindex org-priority-start-cycle-with-default
-Increase/decrease the priority of the current headline@footnote{See also the 
option @code{org-priority-start-cycle-with-default}.}.  Note
-that these keys are also used to modify timestamps (see @ref{Creating 
Timestamps}).  See also @ref{Conflicts}, for
-a discussion of the interaction with shift-selection.
-@end table
-
-@vindex org-priority-highest
-@vindex org-priority-lowest
-@vindex org-priority-default
-You can change the range of allowed priorities by setting the
-variables @code{org-priority-highest}, @code{org-priority-lowest}, and
-@code{org-priority-default}.  For an individual buffer, you may set these
-values (highest, lowest, default) like this (please make sure that the
-highest priority is earlier in the alphabet than the lowest priority):
-
-@cindex @samp{PRIORITIES}, keyword
-@example
-#+PRIORITIES: A C B
-@end example
-
-
-Or, using numeric values:
-
-@example
-#+PRIORITIES: 1 10 5
-@end example
-
-@node Breaking Down Tasks
-@section Breaking Down Tasks into Subtasks
-
-@cindex tasks, breaking down
-@cindex statistics, for TODO items
-
-@vindex org-agenda-todo-list-sublevels
-It is often advisable to break down large tasks into smaller,
-manageable subtasks.  You can do this by creating an outline tree
-below a TODO item, with detailed subtasks on the tree@footnote{To keep 
subtasks out of the global TODO list, see the option
-@code{org-agenda-todo-list-sublevels}.}.  To keep
-an overview of the fraction of subtasks that have already been marked
-as done, insert either @samp{[/]} or @samp{[%]} anywhere in the headline.  
These
-cookies are updated each time the TODO status of a child changes, or
-when pressing @kbd{C-c C-c} on the cookie.  For example:
-
-@example
-* Organize Party [33%]
-** TODO Call people [1/2]
-*** TODO Peter
-*** DONE Sarah
-** TODO Buy food
-** DONE Talk to neighbor
-@end example
-
-@cindex @samp{COOKIE_DATA}, property
-If a heading has both checkboxes and TODO children below it, the
-meaning of the statistics cookie become ambiguous.  Set the property
-@samp{COOKIE_DATA} to either @samp{checkbox} or @samp{todo} to resolve this 
issue.
-
-@vindex org-hierarchical-todo-statistics
-If you would like to have the statistics cookie count any TODO entries
-in the subtree (not just direct children), configure the variable
-@code{org-hierarchical-todo-statistics}.  To do this for a single subtree,
-include the word @samp{recursive} into the value of the @samp{COOKIE_DATA}
-property.
-
-@example
-* Parent capturing statistics [2/20]
-  :PROPERTIES:
-  :COOKIE_DATA: todo recursive
-  :END:
-@end example
-
-If you would like a TODO entry to automatically change to DONE when
-all children are done, you can use the following setup:
-
-@lisp
-(defun org-summary-todo (n-done n-not-done)
-  "Switch entry to DONE when all subentries are done, to TODO otherwise."
-  (let (org-log-done org-log-states)   ; turn off logging
-    (org-todo (if (= n-not-done 0) "DONE" "TODO"))))
-
-(add-hook 'org-after-todo-statistics-hook 'org-summary-todo)
-@end lisp
-
-Another possibility is the use of checkboxes to identify (a hierarchy
-of) a large number of subtasks (see @ref{Checkboxes}).
-
-@node Checkboxes
-@section Checkboxes
-
-@cindex checkboxes
-
-@vindex org-list-automatic-rules
-Every item in a plain list@footnote{With the exception of description lists.  
But you can allow it
-by modifying @code{org-list-automatic-rules} accordingly.} (see @ref{Plain 
Lists}) can be made into
-a checkbox by starting it with the string @samp{[ ]}.  This feature is
-similar to TODO items (see @ref{TODO Items}), but is more lightweight.
-Checkboxes are not included into the global TODO list, so they are
-often great to split a task into a number of simple steps.  Or you can
-use them in a shopping list.
-
-Here is an example of a checkbox list.
-
-@example
-* TODO Organize party [2/4]
-  - [-] call people [1/3]
-    - [ ] Peter
-    - [X] Sarah
-    - [ ] Sam
-  - [X] order food
-  - [ ] think about what music to play
-  - [X] talk to the neighbors
-@end example
-
-Checkboxes work hierarchically, so if a checkbox item has children
-that are checkboxes, toggling one of the children checkboxes makes the
-parent checkbox reflect if none, some, or all of the children are
-checked.
-
-@cindex statistics, for checkboxes
-@cindex checkbox statistics
-@cindex @samp{COOKIE_DATA}, property
-@vindex org-hierarchical-checkbox-statistics
-The @samp{[2/4]} and @samp{[1/3]} in the first and second line are cookies
-indicating how many checkboxes present in this entry have been checked
-off, and the total number of checkboxes present.  This can give you an
-idea on how many checkboxes remain, even without opening a folded
-entry.  The cookies can be placed into a headline or into (the first
-line of) a plain list item.  Each cookie covers checkboxes of direct
-children structurally below the headline/item on which the cookie
-appears@footnote{Set the variable @code{org-hierarchical-checkbox-statistics} 
if you
-want such cookies to count all checkboxes below the cookie, not just
-those belonging to direct children.}.  You have to insert the cookie yourself 
by typing
-either @samp{[/]} or @samp{[%]}.  With @samp{[/]} you get an @samp{n out of m} 
result, as
-in the examples above.  With @samp{[%]} you get information about the
-percentage of checkboxes checked (in the above example, this would be
-@samp{[50%]} and @samp{[33%]}, respectively).  In a headline, a cookie can 
count
-either checkboxes below the heading or TODO states of children, and it
-displays whatever was changed last.  Set the property @samp{COOKIE_DATA} to
-either @samp{checkbox} or @samp{todo} to resolve this issue.
-
-@cindex blocking, of checkboxes
-@cindex checkbox blocking
-@cindex @samp{ORDERED}, property
-If the current outline node has an @samp{ORDERED} property, checkboxes must
-be checked off in sequence, and an error is thrown if you try to check
-off a box while there are unchecked boxes above it.
-
-The following commands work with checkboxes:
-
-@table @asis
-@item @kbd{C-c C-c} (@code{org-toggle-checkbox})
-@kindex C-c C-c
-@findex org-toggle-checkbox
-Toggle checkbox status or---with prefix argument---checkbox presence
-at point.  With a single prefix argument, add an empty checkbox or
-remove the current one@footnote{@kbd{C-u C-c C-c} on the @emph{first} item of 
a list with no
-checkbox adds checkboxes to the rest of the list.}.  With a double prefix 
argument, set
-it to @samp{[-]}, which is considered to be an intermediate state.
-
-@item @kbd{C-c C-x C-b} (@code{org-toggle-checkbox})
-@kindex C-c C-x C-b
-Toggle checkbox status or---with prefix argument---checkbox presence
-at point.  With double prefix argument, set it to @samp{[-]}, which is
-considered to be an intermediate state.
-
-@itemize
-@item
-If there is an active region, toggle the first checkbox in the
-region and set all remaining boxes to the same status as the
-first.  With a prefix argument, add or remove the checkbox for all
-items in the region.
-
-@item
-If point is in a headline, toggle checkboxes in the region between
-this headline and the next---so @emph{not} the entire subtree.
-
-@item
-If there is no active region, just toggle the checkbox at point.
-@end itemize
-
-@item @kbd{C-c C-x C-r} (@code{org-toggle-radio-button})
-@kindex C-c C-x C-r
-@findex org-toggle-radio-button
-@cindex radio button, checkbox as
-Toggle checkbox status by using the checkbox of the item at point as
-a radio button: when the checkbox is turned on, all other checkboxes
-on the same level will be turned off.  With a universal prefix
-argument, toggle the presence of the checkbox.  With a double prefix
-argument, set it to @samp{[-]}.
-
-@findex org-list-checkbox-radio-mode
-@kbd{C-c C-c} can be told to consider checkboxes as radio buttons by
-setting @samp{#+ATTR_ORG: :radio t} right before the list or by calling
-@kbd{M-x org-list-checkbox-radio-mode} to activate this minor mode.
-
-@item @kbd{M-S-@key{RET}} (@code{org-insert-todo-heading})
-@kindex M-S-RET
-@findex org-insert-todo-heading
-Insert a new item with a checkbox.  This works only if point is
-already in a plain list item (see @ref{Plain Lists}).
-
-@item @kbd{C-c C-x o} (@code{org-toggle-ordered-property})
-@kindex C-c C-x o
-@findex org-toggle-ordered-property
-@vindex org-track-ordered-property-with-tag
-Toggle the @samp{ORDERED} property of the entry, to toggle if checkboxes
-must be checked off in sequence.  A property is used for this
-behavior because this should be local to the current entry, not
-inherited like a tag.  However, if you would like to @emph{track} the
-value of this property with a tag for better visibility, customize
-@code{org-track-ordered-property-with-tag}.
-
-@item @kbd{C-c #} (@code{org-update-statistics-cookies})
-@kindex C-c #
-@findex org-update-statistics-cookies
-Update the statistics cookie in the current outline entry.  When
-called with a @kbd{C-u} prefix, update the entire file.
-Checkbox statistic cookies are updated automatically if you toggle
-checkboxes with @kbd{C-c C-c} and make new ones with
-@kbd{M-S-@key{RET}}.  TODO statistics cookies update when changing
-TODO states.  If you delete boxes/entries or add/change them by
-hand, use this command to get things back into sync.
-@end table
-
-@node Tags
-@chapter Tags
-
-@cindex tags
-@cindex headline tagging
-@cindex matching, tags
-@cindex sparse tree, tag based
-
-An excellent way to implement labels and contexts for
-cross-correlating information is to assign @emph{tags} to headlines.  Org
-mode has extensive support for tags.
-
-@vindex org-tag-faces
-Every headline can contain a list of tags; they occur at the end of
-the headline.  Tags are normal words containing letters, numbers, @samp{_},
-and @samp{@@}.  Tags must be preceded and followed by a single colon, e.g.,
-@samp{:work:}.  Several tags can be specified, as in @samp{:work:urgent:}.  
Tags
-by default are in bold face with the same color as the headline.  You
-may specify special faces for specific tags using the variable
-@code{org-tag-faces}, in much the same way as you can for TODO keywords
-(see @ref{Faces for TODO keywords}).
-
-@menu
-* Tag Inheritance::              Tags use the tree structure of an outline.
-* Setting Tags::                 How to assign tags to a headline.
-* Tag Hierarchy::                Create a hierarchy of tags.
-* Tag Searches::                 Searching for combinations of tags.
-@end menu
-
-@node Tag Inheritance
-@section Tag Inheritance
-
-@cindex tag inheritance
-@cindex inheritance, of tags
-@cindex sublevels, inclusion into tags match
-
-@emph{Tags} make use of the hierarchical structure of outline trees.  If
-a heading has a certain tag, all subheadings inherit the tag as well.
-For example, in the list
-
-@example
-* Meeting with the French group      :work:
-** Summary by Frank                  :boss:notes:
-*** TODO Prepare slides for him      :action:
-@end example
-
-@noindent
-the final heading has the tags @samp{work}, @samp{boss}, @samp{notes}, and 
@samp{action}
-even though the final heading is not explicitly marked with those
-tags.  You can also set tags that all entries in a file should inherit
-just as if these tags were defined in a hypothetical level zero that
-surrounds the entire file.  Use a line like this@footnote{As with all these 
in-buffer settings, pressing @kbd{C-c C-c} activates any changes in the line.}
-
-@cindex @samp{FILETAGS}, keyword
-@example
-#+FILETAGS: :Peter:Boss:Secret:
-@end example
-
-
-@vindex org-use-tag-inheritance
-@vindex org-tags-exclude-from-inheritance
-To limit tag inheritance to specific tags, or to turn it off entirely,
-use the variables @code{org-use-tag-inheritance} and
-@code{org-tags-exclude-from-inheritance}.
-
-@vindex org-tags-match-list-sublevels
-When a headline matches during a tags search while tag inheritance is
-turned on, all the sublevels in the same tree---for a simple match
-form---match as well@footnote{This is only true if the search does not involve 
more complex
-tests including properties (see @ref{Property Searches}).}.  The list of 
matches may then become
-very long.  If you only want to see the first tags match in a subtree,
-configure the variable @code{org-tags-match-list-sublevels} (not
-recommended).
-
-@vindex org-agenda-use-tag-inheritance
-Tag inheritance is relevant when the agenda search tries to match
-a tag, either in the @code{tags} or @code{tags-todo} agenda types.  In other
-agenda types, @code{org-use-tag-inheritance} has no effect.  Still, you may
-want to have your tags correctly set in the agenda, so that tag
-filtering works fine, with inherited tags.  Set
-@code{org-agenda-use-tag-inheritance} to control this: the default value
-includes all agenda types, but setting this to @code{nil} can really speed
-up agenda generation.
-
-@node Setting Tags
-@section Setting Tags
-
-@cindex setting tags
-@cindex tags, setting
-
-@kindex M-TAB
-Tags can simply be typed into the buffer at the end of a headline.
-After a colon, @kbd{M-@key{TAB}} offers completion on tags.  There is
-also a special command for inserting tags:
-
-@table @asis
-@item @kbd{C-c C-q} (@code{org-set-tags-command})
-@kindex C-c C-q
-@findex org-set-tags-command
-@cindex completion, of tags
-@vindex org-tags-column
-Enter new tags for the current headline.  Org mode either offers
-completion or a special single-key interface for setting tags, see
-below.  After pressing @kbd{@key{RET}}, the tags are inserted and
-aligned to @code{org-tags-column}.  When called with a @kbd{C-u}
-prefix, all tags in the current buffer are aligned to that column,
-just to make things look nice.  Tags are automatically realigned
-after promotion, demotion, and TODO state changes (see @ref{TODO Basics}).
-
-@item @kbd{C-c C-c} (@code{org-set-tags-command})
-@kindex C-c C-c
-When point is in a headline, this does the same as @kbd{C-c C-q}.
-@end table
-
-@vindex org-complete-tags-always-offer-all-agenda-tags
-@vindex org-tag-alist
-@cindex @samp{TAGS}, keyword
-Org supports tag insertion based on a @emph{list of tags}.  By default this
-list is constructed dynamically, containing all tags currently used in
-the buffer@footnote{To extend this default list to all tags used in all agenda
-files (see @ref{Agenda Views}), customize the variable
-@code{org-complete-tags-always-offer-all-agenda-tags}.}.  You may also 
globally specify a hard list of tags
-with the variable @code{org-tag-alist}.  Finally you can set the default
-tags for a given file using the @samp{TAGS} keyword, like
-
-@example
-#+TAGS: @@work @@home @@tennisclub
-#+TAGS: laptop car pc sailboat
-@end example
-
-If you have globally defined your preferred set of tags using the
-variable @code{org-tag-alist}, but would like to use a dynamic tag list in
-a specific file, add an empty @samp{TAGS} keyword to that file:
-
-@example
-#+TAGS:
-@end example
-
-
-@vindex org-tag-persistent-alist
-If you have a preferred set of tags that you would like to use in
-every file, in addition to those defined on a per-file basis by @samp{TAGS}
-keyword, then you may specify a list of tags with the variable
-@code{org-tag-persistent-alist}.  You may turn this off on a per-file basis
-by adding a @samp{STARTUP} keyword to that file:
-
-@example
-#+STARTUP: noptag
-@end example
-
-
-By default Org mode uses the standard minibuffer completion facilities
-for entering tags.  However, it also implements another, quicker, tag
-selection method called @emph{fast tag selection}.  This allows you to
-select and deselect tags with just a single key press.  For this to
-work well you should assign unique letters to most of your commonly
-used tags.  You can do this globally by configuring the variable
-@code{org-tag-alist} in your Emacs init file.  For example, you may find
-the need to tag many items in different files with @samp{@@home}.  In this
-case you can set something like:
-
-@lisp
-(setq org-tag-alist '(("@@work" . ?w) ("@@home" . ?h) ("laptop" . ?l)))
-@end lisp
-
-If the tag is only relevant to the file you are working on, then you
-can instead set the @samp{TAGS} keyword as:
-
-@example
-#+TAGS: @@work(w)  @@home(h)  @@tennisclub(t)  laptop(l)  pc(p)
-@end example
-
-
-The tags interface shows the available tags in a splash window.  If
-you want to start a new line after a specific tag, insert @samp{\n} into
-the tag list
-
-@example
-#+TAGS: @@work(w) @@home(h) @@tennisclub(t) \n laptop(l) pc(p)
-@end example
-
-
-@noindent
-or write them in two lines:
-
-@example
-#+TAGS: @@work(w)  @@home(h)  @@tennisclub(t)
-#+TAGS: laptop(l)  pc(p)
-@end example
-
-You can also group together tags that are mutually exclusive by using
-braces, as in:
-
-@example
-#+TAGS: @{ @@work(w)  @@home(h)  @@tennisclub(t) @}  laptop(l)  pc(p)
-@end example
-
-
-@noindent
-you indicate that at most one of @samp{@@work}, @samp{@@home}, and 
@samp{@@tennisclub}
-should be selected.  Multiple such groups are allowed.
-
-Do not forget to press @kbd{C-c C-c} with point in one of these
-lines to activate any changes.
-
-To set these mutually exclusive groups in the variable
-@code{org-tags-alist}, you must use the dummy tags @code{:startgroup} and
-@code{:endgroup} instead of the braces.  Similarly, you can use @code{:newline}
-to indicate a line break.  The previous example would be set globally
-by the following configuration:
-
-@lisp
-(setq org-tag-alist '((:startgroup . nil)
-                      ("@@work" . ?w) ("@@home" . ?h)
-                      ("@@tennisclub" . ?t)
-                      (:endgroup . nil)
-                      ("laptop" . ?l) ("pc" . ?p)))
-@end lisp
-
-If at least one tag has a selection key then pressing @kbd{C-c C-c} 
automatically presents you with a special interface, listing
-inherited tags, the tags of the current headline, and a list of all
-valid tags with corresponding keys@footnote{Keys are automatically assigned to 
tags that have no
-configured keys.}.
-
-Pressing keys assigned to tags adds or removes them from the list of
-tags in the current line.  Selecting a tag in a group of mutually
-exclusive tags turns off any other tag from that group.
-
-In this interface, you can also use the following special keys:
-
-@table @asis
-@item @kbd{@key{TAB}}
-@kindex TAB
-Enter a tag in the minibuffer, even if the tag is not in the
-predefined list.  You can complete on all tags present in the
-buffer.  You can also add several tags: just separate them with
-a comma.
-
-@item @kbd{@key{SPC}}
-@kindex SPC
-Clear all tags for this line.
-
-@item @kbd{@key{RET}}
-@kindex RET
-Accept the modified set.
-
-@item @kbd{C-g}
-@kindex C-g
-Abort without installing changes.
-
-@item @kbd{q}
-@kindex q
-If @kbd{q} is not assigned to a tag, it aborts like
-@kbd{C-g}.
-
-@item @kbd{!}
-@kindex !
-Turn off groups of mutually exclusive tags.  Use this to (as an
-exception) assign several tags from such a group.
-
-@item @kbd{C-c}
-@kindex C-c C-c
-Toggle auto-exit after the next change (see below).  If you are
-using expert mode, the first @kbd{C-c} displays the selection
-window.
-@end table
-
-This method lets you assign tags to a headline with very few keys.
-With the above setup, you could clear the current tags and set
-@samp{@@home}, @samp{laptop} and @samp{pc} tags with just the following keys:
-@kbd{C-c C-c @key{SPC} h l p @key{RET}}.  Switching from @samp{@@home} to 
@samp{@@work}
-would be done with @kbd{C-c C-c w @key{RET}} or alternatively with
-@kbd{C-c C-c C-c w}.  Adding the non-predefined tag @samp{sarah} could
-be done with @kbd{C-c C-c @key{TAB} s a r a h @key{RET}}.
-
-@vindex org-fast-tag-selection-single-key
-If you find that most of the time you need only a single key press to
-modify your list of tags, set the variable
-@code{org-fast-tag-selection-single-key}.  Then you no longer have to press
-@kbd{@key{RET}} to exit fast tag selection---it exits after the first
-change.  If you then occasionally need more keys, press @kbd{C-c}
-to turn off auto-exit for the current tag selection process (in
-effect: start selection with @kbd{C-c C-c C-c} instead of
-@kbd{C-c C-c}).  If you set the variable to the value @code{expert},
-the special window is not even shown for single-key tag selection, it
-comes up only when you press an extra @kbd{C-c}.
-
-@node Tag Hierarchy
-@section Tag Hierarchy
-
-@cindex group tags
-@cindex tags, groups
-@cindex tags hierarchy
-
-Tags can be defined in hierarchies.  A tag can be defined as a @emph{group
-tag} for a set of other tags.  The group tag can be seen as the
-``broader term'' for its set of tags.  Defining multiple group tags and
-nesting them creates a tag hierarchy.
-
-One use-case is to create a taxonomy of terms (tags) that can be used
-to classify nodes in a document or set of documents.
-
-When you search for a group tag, it return matches for all members in
-the group and its subgroups.  In an agenda view, filtering by a group
-tag displays or hide headlines tagged with at least one of the members
-of the group or any of its subgroups.  This makes tag searches and
-filters even more flexible.
-
-You can set group tags by using brackets and inserting a colon between
-the group tag and its related tags---beware that all whitespaces are
-mandatory so that Org can parse this line correctly:
-
-@example
-#+TAGS: [ GTD : Control Persp ]
-@end example
-
-
-In this example, @samp{GTD} is the group tag and it is related to two other
-tags: @samp{Control}, @samp{Persp}.  Defining @samp{Control} and @samp{Persp} 
as group
-tags creates a hierarchy of tags:
-
-@example
-#+TAGS: [ Control : Context Task ]
-#+TAGS: [ Persp : Vision Goal AOF Project ]
-@end example
-
-That can conceptually be seen as a hierarchy of tags:
-
-@itemize
-@item
-@samp{GTD}
-@itemize
-@item
-@samp{Persp}
-@itemize
-@item
-@samp{Vision}
-@item
-@samp{Goal}
-@item
-@samp{AOF}
-@item
-@samp{Project}
-@end itemize
-@item
-@samp{Control}
-@itemize
-@item
-@samp{Context}
-@item
-@samp{Task}
-@end itemize
-@end itemize
-@end itemize
-
-You can use the @code{:startgrouptag}, @code{:grouptags} and 
@code{:endgrouptag}
-keyword directly when setting @code{org-tag-alist} directly:
-
-@lisp
-(setq org-tag-alist '((:startgrouptag)
-                      ("GTD")
-                      (:grouptags)
-                      ("Control")
-                      ("Persp")
-                      (:endgrouptag)
-                      (:startgrouptag)
-                      ("Control")
-                      (:grouptags)
-                      ("Context")
-                      ("Task")
-                      (:endgrouptag)))
-@end lisp
-
-The tags in a group can be mutually exclusive if using the same group
-syntax as is used for grouping mutually exclusive tags together; using
-curly brackets.
-
-@example
-#+TAGS: @{ Context : @@Home @@Work @@Call @}
-@end example
-
-
-When setting @code{org-tag-alist} you can use @code{:startgroup} and 
@code{:endgroup}
-instead of @code{:startgrouptag} and @code{:endgrouptag} to make the tags
-mutually exclusive.
-
-Furthermore, the members of a group tag can also be regular
-expressions, creating the possibility of a more dynamic and rule-based
-tag structure.  The regular expressions in the group must be specified
-within curly brackets.  Here is an expanded example:
-
-@example
-#+TAGS: [ Vision : @{V@@.+@} ]
-#+TAGS: [ Goal : @{G@@.+@} ]
-#+TAGS: [ AOF : @{AOF@@.+@} ]
-#+TAGS: [ Project : @{P@@.+@} ]
-@end example
-
-Searching for the tag @samp{Project} now lists all tags also including
-regular expression matches for @samp{P@@.+}, and similarly for tag searches
-on @samp{Vision}, @samp{Goal} and @samp{AOF}.  For example, this would work 
well for
-a project tagged with a common project-identifier, e.g.,
-@samp{P@@2014_OrgTags}.
-
-@kindex C-c C-x q
-@findex org-toggle-tags-groups
-@vindex org-group-tags
-If you want to ignore group tags temporarily, toggle group tags
-support with @code{org-toggle-tags-groups}, bound to @kbd{C-c C-x q}.
-If you want to disable tag groups completely, set @code{org-group-tags} to
-@code{nil}.
-
-@node Tag Searches
-@section Tag Searches
-
-@cindex tag searches
-@cindex searching for tags
-
-Once a system of tags has been set up, it can be used to collect
-related information into special lists.
-
-@table @asis
-@item @kbd{C-c / m} or @kbd{C-c \} (@code{org-match-sparse-tree})
-@kindex C-c / m
-@kindex C-c \
-@findex org-match-sparse-tree
-Create a sparse tree with all headlines matching a tags search.
-With a @kbd{C-u} prefix argument, ignore headlines that are not
-a TODO line.
-
-@item @kbd{M-x org-agenda m} (@code{org-tags-view})
-@kindex m @r{(Agenda dispatcher)}
-@findex org-tags-view
-Create a global list of tag matches from all agenda files.  See
-@ref{Matching tags and properties}.
-
-@item @kbd{M-x org-agenda M} (@code{org-tags-view})
-@kindex M @r{(Agenda dispatcher)}
-@vindex org-tags-match-list-sublevels
-Create a global list of tag matches from all agenda files, but check
-only TODO items and force checking subitems (see the option
-@code{org-tags-match-list-sublevels}).
-@end table
-
-These commands all prompt for a match string which allows basic
-Boolean logic like @samp{+boss+urgent-project1}, to find entries with tags
-@samp{boss} and @samp{urgent}, but not @samp{project1}, or @samp{Kathy|Sally} 
to find
-entries which are tagged, like @samp{Kathy} or @samp{Sally}.  The full syntax 
of
-the search string is rich and allows also matching against TODO
-keywords, entry levels and properties.  For a complete description
-with many examples, see @ref{Matching tags and properties}.
-
-@node Properties and Columns
-@chapter Properties and Columns
-
-@cindex properties
-
-A property is a key-value pair associated with an entry.  Properties
-can be set so they are associated with a single entry, with every
-entry in a tree, or with the whole buffer.
-
-There are two main applications for properties in Org mode.  First,
-properties are like tags, but with a value.  Imagine maintaining
-a file where you document bugs and plan releases for a piece of
-software.  Instead of using tags like @samp{release_1}, @samp{release_2}, you
-can use a property, say @samp{Release}, that in different subtrees has
-different values, such as @samp{1.0} or @samp{2.0}.  Second, you can use
-properties to implement (very basic) database capabilities in an Org
-buffer.  Imagine keeping track of your music CDs, where properties
-could be things such as the album, artist, date of release, number of
-tracks, and so on.
-
-Properties can be conveniently edited and viewed in column view (see
-@ref{Column View}).
-
-@menu
-* Property Syntax::              How properties are spelled out.
-* Special Properties::           Access to other Org mode features.
-* Property Searches::            Matching property values.
-* Property Inheritance::         Passing values down a tree.
-* Column View::                  Tabular viewing and editing.
-@end menu
-
-@node Property Syntax
-@section Property Syntax
-
-@cindex property syntax
-@cindex drawer, for properties
-
-Properties are key--value pairs.  When they are associated with
-a single entry or with a tree they need to be inserted into a special
-drawer (see @ref{Drawers}) with the name @samp{PROPERTIES}, which has to be
-located right below a headline, and its planning line (see @ref{Deadlines and 
Scheduling}) when applicable.  Each property is specified on
-a single line, with the key---surrounded by colons---first, and the
-value after it.  Keys are case-insensitive.  Here is an example:
-
-@example
-* CD collection
-** Classic
-*** Goldberg Variations
-    :PROPERTIES:
-    :Title:     Goldberg Variations
-    :Composer:  J.S. Bach
-    :Artist:    Glenn Gould
-    :Publisher: Deutsche Grammophon
-    :NDisks:    1
-    :END:
-@end example
-
-Depending on the value of @code{org-use-property-inheritance}, a property
-set this way is associated either with a single entry, or with the
-sub-tree defined by the entry, see @ref{Property Inheritance}.
-
-You may define the allowed values for a particular property @samp{Xyz} by
-setting a property @samp{Xyz_ALL}.  This special property is @emph{inherited},
-so if you set it in a level 1 entry, it applies to the entire tree.
-When allowed values are defined, setting the corresponding property
-becomes easier and is less prone to typing errors.  For the example
-with the CD collection, we can pre-define publishers and the number of
-disks in a box like this:
-
-@example
-* CD collection
-  :PROPERTIES:
-  :NDisks_ALL:  1 2 3 4
-  :Publisher_ALL: "Deutsche Grammophon" Philips EMI
-  :END:
-@end example
-
-Properties can be inserted on buffer level.  That means they apply
-before the first headline and can be inherited by all entries in a
-file.  Property blocks defined before first headline needs to be
-located at the top of the buffer, allowing only comments above.
-
-Properties can also be defined using lines like:
-
-@cindex @samp{_ALL} suffix, in properties
-@cindex @samp{PROPERTY}, keyword
-@example
-#+PROPERTY: NDisks_ALL 1 2 3 4
-@end example
-
-
-@cindex @samp{+} suffix, in properties
-If you want to add to the value of an existing property, append a @samp{+}
-to the property name.  The following results in the property @samp{var}
-having the value @samp{foo=1 bar=2}.
-
-@example
-#+PROPERTY: var  foo=1
-#+PROPERTY: var+ bar=2
-@end example
-
-It is also possible to add to the values of inherited properties.  The
-following results in the @samp{Genres} property having the value @samp{Classic
-Baroque} under the @samp{Goldberg Variations} subtree.
-
-@example
-* CD collection
-** Classic
-    :PROPERTIES:
-    :Genres: Classic
-    :END:
-*** Goldberg Variations
-    :PROPERTIES:
-    :Title:     Goldberg Variations
-    :Composer:  J.S. Bach
-    :Artist:    Glenn Gould
-    :Publisher: Deutsche Grammophon
-    :NDisks:    1
-    :Genres+:   Baroque
-    :END:
-@end example
-
-Note that a property can only have one entry per drawer.
-
-@vindex org-global-properties
-Property values set with the global variable @code{org-global-properties}
-can be inherited by all entries in all Org files.
-
-The following commands help to work with properties:
-
-@table @asis
-@item @kbd{M-@key{TAB}} (@code{pcomplete})
-@kindex M-TAB
-@findex pcomplete
-After an initial colon in a line, complete property keys.  All keys
-used in the current file are offered as possible completions.
-
-@item @kbd{C-c C-x p} (@code{org-set-property})
-@kindex C-c C-x p
-@findex org-set-property
-Set a property.  This prompts for a property name and a value.  If
-necessary, the property drawer is created as well.
-
-@item @kbd{C-u M-x org-insert-drawer}
-@findex org-insert-drawer
-Insert a property drawer into the current entry.  The drawer is
-inserted early in the entry, but after the lines with planning
-information like deadlines.  If before first headline the drawer is
-inserted at the top of the drawer after any potential comments.
-
-@item @kbd{C-c C-c} (@code{org-property-action})
-@kindex C-c C-c
-@findex org-property-action
-With point in a property drawer, this executes property commands.
-
-@item @kbd{C-c C-c s} (@code{org-set-property})
-@kindex C-c C-c s
-@findex org-set-property
-Set a property in the current entry.  Both the property and the
-value can be inserted using completion.
-
-@item @kbd{S-@key{RIGHT}} (@code{org-property-next-allowed-values})
-@itemx @kbd{S-@key{LEFT}} (@code{org-property-previous-allowed-value})
-@kindex S-RIGHT
-@kindex S-LEFT
-Switch property at point to the next/previous allowed value.
-
-@item @kbd{C-c C-c d} (@code{org-delete-property})
-@kindex C-c C-c d
-@findex org-delete-property
-Remove a property from the current entry.
-
-@item @kbd{C-c C-c D} (@code{org-delete-property-globally})
-@kindex C-c C-c D
-@findex org-delete-property-globally
-Globally remove a property, from all entries in the current file.
-
-@item @kbd{C-c C-c c} (@code{org-compute-property-at-point})
-@kindex C-c C-c c
-@findex org-compute-property-at-point
-Compute the property at point, using the operator and scope from the
-nearest column format definition.
-@end table
-
-@node Special Properties
-@section Special Properties
-
-@cindex properties, special
-
-Special properties provide an alternative access method to Org mode
-features, like the TODO state or the priority of an entry, discussed
-in the previous chapters.  This interface exists so that you can
-include these states in a column view (see @ref{Column View}), or to use
-them in queries.  The following property names are special and should
-not be used as keys in the properties drawer:
-
-@cindex @samp{ALLTAGS}, special property
-@cindex @samp{BLOCKED}, special property
-@cindex @samp{CLOCKSUM}, special property
-@cindex @samp{CLOCKSUM_T}, special property
-@cindex @samp{CLOSED}, special property
-@cindex @samp{DEADLINE}, special property
-@cindex @samp{FILE}, special property
-@cindex @samp{ITEM}, special property
-@cindex @samp{PRIORITY}, special property
-@cindex @samp{SCHEDULED}, special property
-@cindex @samp{TAGS}, special property
-@cindex @samp{TIMESTAMP}, special property
-@cindex @samp{TIMESTAMP_IA}, special property
-@cindex @samp{TODO}, special property
-@multitable {aaaaaaaaaaaaaa} 
{aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa}
-@item @samp{ALLTAGS}
-@tab All tags, including inherited ones.
-@item @samp{BLOCKED}
-@tab @code{t} if task is currently blocked by children or siblings.
-@item @samp{CATEGORY}
-@tab The category of an entry.
-@item @samp{CLOCKSUM}
-@tab The sum of CLOCK intervals in the subtree.  @code{org-clock-sum}
-@item
-@tab must be run first to compute the values in the current buffer.
-@item @samp{CLOCKSUM_T}
-@tab The sum of CLOCK intervals in the subtree for today.
-@item
-@tab @code{org-clock-sum-today} must be run first to compute the
-@item
-@tab values in the current buffer.
-@item @samp{CLOSED}
-@tab When was this entry closed?
-@item @samp{DEADLINE}
-@tab The deadline timestamp.
-@item @samp{FILE}
-@tab The filename the entry is located in.
-@item @samp{ITEM}
-@tab The headline of the entry.
-@item @samp{PRIORITY}
-@tab The priority of the entry, a string with a single letter.
-@item @samp{SCHEDULED}
-@tab The scheduling timestamp.
-@item @samp{TAGS}
-@tab The tags defined directly in the headline.
-@item @samp{TIMESTAMP}
-@tab The first keyword-less timestamp in the entry.
-@item @samp{TIMESTAMP_IA}
-@tab The first inactive timestamp in the entry.
-@item @samp{TODO}
-@tab The TODO keyword of the entry.
-@end multitable
-
-@node Property Searches
-@section Property Searches
-
-@cindex properties, searching
-@cindex searching, of properties
-
-To create sparse trees and special lists with selection based on
-properties, the same commands are used as for tag searches (see @ref{Tag 
Searches}).
-
-@table @asis
-@item @kbd{C-c / m} or @kbd{C-c \} (@code{org-match-sparse-tree})
-@kindex C-c / m
-@kindex C-c \
-@findex org-match-sparse-tree
-Create a sparse tree with all matching entries.  With
-a @kbd{C-u} prefix argument, ignore headlines that are not
-a TODO line.
-
-@item @kbd{M-x org-agenda m} (@code{org-tags-view})
-@kindex m @r{(Agenda dispatcher)}
-@findex org-tags-view
-Create a global list of tag/property matches from all agenda files.
-
-@item @kbd{M-x org-agenda M} (@code{org-tags-view})
-@kindex M @r{(Agenda dispatcher)}
-@vindex org-tags-match-list-sublevels
-Create a global list of tag matches from all agenda files, but check
-only TODO items and force checking of subitems (see the option
-@code{org-tags-match-list-sublevels}).
-@end table
-
-The syntax for the search string is described in @ref{Matching tags and 
properties}.
-
-There is also a special command for creating sparse trees based on a
-single property:
-
-@table @asis
-@item @kbd{C-c / p}
-@kindex C-c / p
-Create a sparse tree based on the value of a property.  This first
-prompts for the name of a property, and then for a value.  A sparse
-tree is created with all entries that define this property with the
-given value.  If you enclose the value in curly braces, it is
-interpreted as a regular expression and matched against the property
-values.
-@end table
-
-@node Property Inheritance
-@section Property Inheritance
-
-@cindex properties, inheritance
-@cindex inheritance, of properties
-
-@vindex org-use-property-inheritance
-The outline structure of Org documents lends itself to an inheritance
-model of properties: if the parent in a tree has a certain property,
-the children can inherit this property.  Org mode does not turn this
-on by default, because it can slow down property searches
-significantly and is often not needed.  However, if you find
-inheritance useful, you can turn it on by setting the variable
-@code{org-use-property-inheritance}.  It may be set to @code{t} to make all
-properties inherited from the parent, to a list of properties that
-should be inherited, or to a regular expression that matches inherited
-properties.  If a property has the value @code{nil}, this is interpreted as
-an explicit un-define of the property, so that inheritance search
-stops at this value and returns @code{nil}.
-
-Org mode has a few properties for which inheritance is hard-coded, at
-least for the special applications for which they are used:
-
-@table @asis
-@item @code{COLUMNS}
-@cindex @samp{COLUMNS}, property
-The @samp{COLUMNS} property defines the format of column view (see
-@ref{Column View}).  It is inherited in the sense that the level where
-a @samp{COLUMNS} property is defined is used as the starting point for
-a column view table, independently of the location in the subtree
-from where columns view is turned on.
-
-@item @code{CATEGORY}
-@cindex @samp{CATEGORY}, property
-For agenda view, a category set through a @samp{CATEGORY} property
-applies to the entire subtree.
-
-@item @code{ARCHIVE}
-@cindex @samp{ARCHIVE}, property
-For archiving, the @samp{ARCHIVE} property may define the archive
-location for the entire subtree (see @ref{Moving subtrees}).
-
-@item @code{LOGGING}
-@cindex @samp{LOGGING}, property
-The @samp{LOGGING} property may define logging settings for an entry or
-a subtree (see @ref{Tracking TODO state changes}).
-@end table
-
-@node Column View
-@section Column View
-
-A great way to view and edit properties in an outline tree is @emph{column
-view}.  In column view, each outline node is turned into a table row.
-Columns in this table provide access to properties of the entries.
-Org mode implements columns by overlaying a tabular structure over the
-headline of each item.  While the headlines have been turned into
-a table row, you can still change the visibility of the outline tree.
-For example, you get a compact table by switching to ``contents''
-view---@kbd{S-@key{TAB}} @kbd{S-@key{TAB}}, or simply @kbd{c}
-while column view is active---but you can still open, read, and edit
-the entry below each headline.  Or, you can switch to column view
-after executing a sparse tree command and in this way get a table only
-for the selected items.  Column view also works in agenda buffers (see
-@ref{Agenda Views}) where queries have collected selected items, possibly
-from a number of files.
-
-@menu
-* Defining columns::             The COLUMNS format property.
-* Using column view::            How to create and use column view.
-* Capturing column view::        A dynamic block for column view.
-@end menu
-
-@node Defining columns
-@subsection Defining columns
-
-@cindex column view, for properties
-@cindex properties, column view
-
-Setting up a column view first requires defining the columns.  This is
-done by defining a column format line.
-
-@menu
-* Scope of column definitions::  Where defined, where valid?
-* Column attributes::            Appearance and content of a column.
-@end menu
-
-@node Scope of column definitions
-@subsubsection Scope of column definitions
-
-To specify a format that only applies to a specific tree, add
-a @samp{COLUMNS} property to the top node of that tree, for example:
-
-@example
-** Top node for columns view
-   :PROPERTIES:
-   :COLUMNS: %25ITEM %TAGS %PRIORITY %TODO
-   :END:
-@end example
-
-A @samp{COLUMNS} property within a property drawer before first headline
-will apply to the entire file.  As an addition to property drawers,
-keywords can also be defined for an entire file using a line like:
-
-@cindex @samp{COLUMNS}, keyword
-@example
-#+COLUMNS: %25ITEM %TAGS %PRIORITY %TODO
-@end example
-
-
-If a @samp{COLUMNS} property is present in an entry, it defines columns for
-the entry itself, and for the entire subtree below it.  Since the
-column definition is part of the hierarchical structure of the
-document, you can define columns on level 1 that are general enough
-for all sublevels, and more specific columns further down, when you
-edit a deeper part of the tree.
-
-@node Column attributes
-@subsubsection Column attributes
-
-A column definition sets the attributes of a column.  The general
-definition looks like this:
-
-@example
-%[WIDTH]PROPERTY[(TITLE)][@{SUMMARY-TYPE@}]
-@end example
-
-
-@noindent
-Except for the percent sign and the property name, all items are
-optional.  The individual parts have the following meaning:
-
-@table @asis
-@item @var{WIDTH}
-An integer specifying the width of the column in characters.  If
-omitted, the width is determined automatically.
-
-@item @var{PROPERTY}
-The property that should be edited in this column.  Special
-properties representing meta data are allowed here as well (see
-@ref{Special Properties}).
-
-@item @var{TITLE}
-The header text for the column.  If omitted, the property name is
-used.
-
-@item @var{SUMMARY-TYPE}
-The summary type.  If specified, the column values for parent nodes
-are computed from the children@footnote{If more than one summary type applies 
to the same property,
-the parent values are computed according to the first of them.}.
-
-Supported summary types are:
-
-@multitable {aaaaaaaa} {aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa}
-@item @samp{+}
-@tab Sum numbers in this column.
-@item @samp{+;%.1f}
-@tab Like @samp{+}, but format result with @samp{%.1f}.
-@item @samp{$}
-@tab Currency, short for @samp{+;%.2f}.
-@item @samp{min}
-@tab Smallest number in column.
-@item @samp{max}
-@tab Largest number.
-@item @samp{mean}
-@tab Arithmetic mean of numbers.
-@item @samp{X}
-@tab Checkbox status, @samp{[X]} if all children are @samp{[X]}.
-@item @samp{X/}
-@tab Checkbox status, @samp{[n/m]}.
-@item @samp{X%}
-@tab Checkbox status, @samp{[n%]}.
-@item @samp{:}
-@tab Sum times, HH:MM, plain numbers are minutes.
-@item @samp{:min}
-@tab Smallest time value in column.
-@item @samp{:max}
-@tab Largest time value.
-@item @samp{:mean}
-@tab Arithmetic mean of time values.
-@item @samp{@@min}
-@tab Minimum age@footnote{An age can be defined as a duration, using units 
defined in
-@code{org-duration-units}, e.g., @samp{3d 1h}.  If any value in the column is 
as
-such, the summary is also expressed as a duration.} (in 
days/hours/mins/seconds).
-@item @samp{@@max}
-@tab Maximum age (in days/hours/mins/seconds).
-@item @samp{@@mean}
-@tab Arithmetic mean of ages (in days/hours/mins/seconds).
-@item @samp{est+}
-@tab Add low-high estimates.
-@end multitable
-
-@vindex org-columns-summary-types
-You can also define custom summary types by setting
-@code{org-columns-summary-types}.
-@end table
-
-The @samp{est+} summary type requires further explanation.  It is used for
-combining estimates, expressed as low-high ranges.  For example,
-instead of estimating a particular task will take 5 days, you might
-estimate it as 5--6 days if you're fairly confident you know how much
-work is required, or 1--10 days if you do not really know what needs
-to be done.  Both ranges average at 5.5 days, but the first represents
-a more predictable delivery.
-
-When combining a set of such estimates, simply adding the lows and
-highs produces an unrealistically wide result.  Instead, @samp{est+} adds
-the statistical mean and variance of the subtasks, generating a final
-estimate from the sum.  For example, suppose you had ten tasks, each
-of which was estimated at 0.5 to 2 days of work.  Straight addition
-produces an estimate of 5 to 20 days, representing what to expect if
-everything goes either extremely well or extremely poorly.  In
-contrast, @samp{est+} estimates the full job more realistically, at 10--15
-days.
-
-Here is an example for a complete columns definition, along with
-allowed values@footnote{Please note that the @samp{COLUMNS} definition must be 
on a single
-line; it is wrapped here only because of formatting constraints.}.
-
-@example
-:COLUMNS:  %25ITEM %9Approved(Approved?)@{X@} %Owner %11Status \
-                   %10Time_Estimate@{:@} %CLOCKSUM %CLOCKSUM_T
-:Owner_ALL:    Tammy Mark Karl Lisa Don
-:Status_ALL:   "In progress" "Not started yet" "Finished" ""
-:Approved_ALL: "[ ]" "[X]"
-@end example
-
-@noindent
-The first column, @samp{%25ITEM}, means the first 25 characters of the item
-itself, i.e., of the headline.  You probably always should start the
-column definition with the @samp{ITEM} specifier.  The other specifiers
-create columns @samp{Owner} with a list of names as allowed values, for
-@samp{Status} with four different possible values, and for a checkbox field
-@samp{Approved}.  When no width is given after the @samp{%} character, the
-column is exactly as wide as it needs to be in order to fully display
-all values.  The @samp{Approved} column does have a modified title
-(@samp{Approved?}, with a question mark).  Summaries are created for the
-@samp{Time_Estimate} column by adding time duration expressions like HH:MM,
-and for the @samp{Approved} column, by providing an @samp{[X]} status if all
-children have been checked.  The @samp{CLOCKSUM} and @samp{CLOCKSUM_T} columns
-are special, they lists the sums of CLOCK intervals in the subtree,
-either for all clocks or just for today.
-
-@node Using column view
-@subsection Using column view
-
-
-
-@anchor{Turning column view on or off}
-@subsubheading Turning column view on or off
-
-@table @asis
-@item @kbd{C-c C-x C-c} (@code{org-columns})
-@kindex C-c C-x C-c
-@vindex org-columns
-@vindex org-columns-default-format
-Turn on column view.  If point is before the first headline in the
-file, column view is turned on for the entire file, using the
-@samp{#+COLUMNS} definition.  If point is somewhere inside the outline,
-this command searches the hierarchy, up from point, for a @samp{COLUMNS}
-property that defines a format.  When one is found, the column view
-table is established for the tree starting at the entry that
-contains the @samp{COLUMNS} property.  If no such property is found, the
-format is taken from the @samp{#+COLUMNS} line or from the variable
-@code{org-columns-default-format}, and column view is established for the
-current entry and its subtree.
-
-@item @kbd{r} or @kbd{g} on a columns view line (@code{org-columns-redo})
-@kindex r
-@kindex g
-@findex org-columns-redo
-Recreate the column view, to include recent changes made in the
-buffer.
-
-@item @kbd{C-c C-c} or @kbd{q} on a columns view line (@code{org-columns-quit})
-@kindex q
-@kindex C-c C-c
-@findex org-columns-quit
-Exit column view.
-@end table
-
-@anchor{Editing values}
-@subsubheading Editing values
-
-@table @asis
-@item @kbd{@key{LEFT}}, @kbd{@key{RIGHT}}, @kbd{@key{UP}}, @kbd{@key{DOWN}}
-Move through the column view from field to field.
-
-@item @kbd{1..9,0}
-@kindex 1..9,0
-Directly select the Nth allowed value, @kbd{0} selects the
-10th value.
-
-@item @kbd{n} or @kbd{S-@key{RIGHT}} (@code{org-columns-next-allowed-value})
-@itemx @kbd{p} or @kbd{S-@key{LEFT}} 
(@code{org-columns-previous-allowed-value})
-@kindex n
-@kindex S-RIGHT
-@kindex p
-@kindex S-LEFT
-@findex org-columns-next-allowed-value
-@findex org-columns-previous-allowed-value
-Switch to the next/previous allowed value of the field.  For this,
-you have to have specified allowed values for a property.
-
-@item @kbd{e} (@code{org-columns-edit-value})
-@kindex e
-@findex org-columns-edit-value
-Edit the property at point.  For the special properties, this
-invokes the same interface that you normally use to change that
-property.  For example, the tag completion or fast selection
-interface pops up when editing a @samp{TAGS} property.
-
-@item @kbd{C-c C-c} (@code{org-columns-toggle-or-columns-quit})
-@kindex C-c C-c
-@findex org-columns-toggle-or-columns-quit
-When there is a checkbox at point, toggle it.  Else exit column
-view.
-
-@item @kbd{v} (@code{org-columns-show-value})
-@kindex v
-@findex org-columns-show-value
-View the full value of this property.  This is useful if the width
-of the column is smaller than that of the value.
-
-@item @kbd{a} (@code{org-columns-edit-allowed})
-@kindex a
-@findex org-columns-edit-allowed
-Edit the list of allowed values for this property.  If the list is
-found in the hierarchy, the modified values is stored there.  If no
-list is found, the new value is stored in the first entry that is
-part of the current column view.
-@end table
-
-@anchor{Modifying column view on-the-fly}
-@subsubheading Modifying column view on-the-fly
-
-@table @asis
-@item @kbd{<} (@code{org-columns-narrow})
-@itemx @kbd{>} (@code{org-columns-widen})
-@kindex <
-@kindex >
-@findex org-columns-narrow
-@findex org-columns-widen
-Make the column narrower/wider by one character.
-
-@item @kbd{S-M-@key{RIGHT}} (@code{org-columns-new})
-@kindex S-M-RIGHT
-@findex org-columns-new
-Insert a new column, to the left of the current column.
-
-@item @kbd{S-M-@key{LEFT}} (@code{org-columns-delete})
-@kindex S-M-LEFT
-@findex org-columns-delete
-Delete the current column.
-@end table
-
-@node Capturing column view
-@subsection Capturing column view
-
-Since column view is just an overlay over a buffer, it cannot be
-exported or printed directly.  If you want to capture a column view,
-use a @samp{columnview} dynamic block (see @ref{Dynamic Blocks}).  The frame of
-this block looks like this:
-
-@cindex @samp{BEGIN columnview}
-@example
-* The column view
-#+BEGIN: columnview :hlines 1 :id "label"
-
-#+END:
-@end example
-
-This dynamic block has the following parameters:
-
-@table @asis
-@item @samp{:id}
-This is the most important parameter.  Column view is a feature that
-is often localized to a certain (sub)tree, and the capture block
-might be at a different location in the file.  To identify the tree
-whose view to capture, you can use four values:
-
-@table @asis
-@item @samp{local}
-Use the tree in which the capture block is located.
-
-@item @samp{global}
-Make a global view, including all headings in the file.
-
-@item @samp{file:FILENAME}
-Run column view at the top of the @var{FILENAME} file.
-
-@item @samp{LABEL}
-@cindex @samp{ID}, property
-Call column view in the tree that has an @samp{ID} property with the
-value @var{LABEL}.  You can use @kbd{M-x org-id-copy} to
-create a globally unique ID for the current entry and copy it to
-the kill-ring.
-@end table
-
-@item @samp{:match}
-When set to a string, use this as a tags/property match filter to
-select only a subset of the headlines in the scope set by the @code{:id}
-parameter.
-@end table
-
-
-@table @asis
-@item @samp{:hlines}
-When @code{t}, insert an hline after every line.  When a number N, insert
-an hline before each headline with level @code{<= N}.
-
-@item @samp{:vlines}
-When non-@code{nil}, force column groups to get vertical lines.
-
-@item @samp{:maxlevel}
-When set to a number, do not capture entries below this level.
-
-@item @samp{:skip-empty-rows}
-When non-@code{nil}, skip rows where the only non-empty specifier of
-the column view is @samp{ITEM}.
-
-@item @samp{:exclude-tags}
-List of tags to exclude from column view table: entries with these
-tags will be excluded from the column view.
-
-@item @samp{:indent}
-When non-@code{nil}, indent each @samp{ITEM} field according to its level.
-
-@item @samp{:format}
-Specify a column attribute (see @ref{Column attributes}) for the dynamic
-block.
-@end table
-
-The following commands insert or update the dynamic block:
-
-@table @asis
-@item @code{org-columns-insert-dblock}
-@kindex C-c C-x x
-@findex org-columns-insert-dblock
-Insert a dynamic block capturing a column view.  Prompt for the
-scope or ID of the view.
-
-This command can be invoked by calling
-@code{org-dynamic-block-insert-dblock} (@kbd{C-c C-x x}) and
-selecting ``columnview'' (see @ref{Dynamic Blocks}).
-
-@item @kbd{C-c C-c} @kbd{C-c C-x C-u} (@code{org-dblock-update})
-@kindex C-c C-c
-@kindex C-c C-x C-u
-@findex org-dblock-update
-Update dynamic block at point.  point needs to be in the @samp{#+BEGIN}
-line of the dynamic block.
-
-@item @kbd{C-u C-c C-x C-u} (@code{org-update-all-dblocks})
-@kindex C-u C-c C-x C-u
-Update all dynamic blocks (see @ref{Dynamic Blocks}).  This is useful if
-you have several clock table blocks, column-capturing blocks or
-other dynamic blocks in a buffer.
-@end table
-
-You can add formulas to the column view table and you may add plotting
-instructions in front of the table---these survive an update of the
-block.  If there is a @samp{TBLFM} keyword after the table, the table is
-recalculated automatically after an update.
-
-An alternative way to capture and process property values into a table
-is provided by Eric Schulte's @samp{org-collector.el}, which is
-a contributed package@footnote{Contributed packages are not part of Emacs, but 
are
-distributed with the main distribution of Org---visit
-@uref{https://orgmode.org}.}.  It provides a general API to collect
-properties from entries in a certain scope, and arbitrary Lisp
-expressions to process these values before inserting them into a table
-or a dynamic block.
-
-@node Dates and Times
-@chapter Dates and Times
-
-@cindex dates
-@cindex times
-@cindex timestamp
-@cindex date stamp
-
-To assist project planning, TODO items can be labeled with a date
-and/or a time.  The specially formatted string carrying the date and
-time information is called a @emph{timestamp} in Org mode.  This may be
-a little confusing because timestamp is often used as indicating when
-something was created or last changed.  However, in Org mode this term
-is used in a much wider sense.
-
-@menu
-* Timestamps::                   Assigning a time to a tree entry.
-* Creating Timestamps::          Commands to insert timestamps.
-* Deadlines and Scheduling::     Planning your work.
-* Clocking Work Time::           Tracking how long you spend on a task.
-* Effort Estimates::             Planning work effort in advance.
-* Timers::                       Notes with a running timer.
-@end menu
-
-@node Timestamps
-@section Timestamps
-
-@cindex timestamps
-@cindex ranges, time
-@cindex date stamps
-@cindex deadlines
-@cindex scheduling
-
-A timestamp is a specification of a date (possibly with a time or
-a range of times) in a special format, either @samp{<2003-09-16 Tue>} or
-@samp{<2003-09-16 Tue 09:39>} or @samp{<2003-09-16 Tue 
12:00-12:30>}@footnote{The Org date format is inspired by the standard ISO 8601
-date/time format.  To use an alternative format, see @ref{Custom time format}. 
 The day name is optional when you type the date yourself.
-However, any date inserted or modified by Org adds that day name, for
-reading convenience.}.
-A timestamp can appear anywhere in the headline or body of an Org tree
-entry.  Its presence causes entries to be shown on specific dates in
-the agenda (see @ref{Weekly/daily agenda}).  We distinguish:
-
-@table @asis
-@item Plain timestamp; Event; Appointment
-@cindex timestamp
-@cindex appointment
-A simple timestamp just assigns a date/time to an item.  This is
-just like writing down an appointment or event in a paper agenda.
-In the agenda display, the headline of an entry associated with
-a plain timestamp is shown exactly on that date.
-
-@example
-* Meet Peter at the movies
-  <2006-11-01 Wed 19:15>
-* Discussion on climate change
-  <2006-11-02 Thu 20:00-22:00>
-@end example
-
-@item Timestamp with repeater interval
-@cindex timestamp, with repeater interval
-A timestamp may contain a @emph{repeater interval}, indicating that it
-applies not only on the given date, but again and again after
-a certain interval of N days (d), weeks (w), months (m), or years
-(y).  The following shows up in the agenda every Wednesday:
-
-@example
-* Pick up Sam at school
-  <2007-05-16 Wed 12:30 +1w>
-@end example
-
-@item Diary-style expression entries
-@cindex diary style timestamps
-@cindex sexp timestamps
-For more complex date specifications, Org mode supports using the
-special expression diary entries implemented in the Emacs Calendar
-package@footnote{When working with the standard diary expression functions, you
-need to be very careful with the order of the arguments.  That order
-depends evilly on the variable @code{calendar-date-style}.  For example, to
-specify a date December 12, 2005, the call might look like
-@samp{(diary-date 12 1 2005)} or @samp{(diary-date 1 12 2005)} or 
@samp{(diary-date
-2005 12 1)}, depending on the settings.  This has been the source of
-much confusion.  Org mode users can resort to special versions of
-these functions like @code{org-date} or @code{org-anniversary}.  These work 
just
-like the corresponding @code{diary-} functions, but with stable ISO order
-of arguments (year, month, day) wherever applicable, independent of
-the value of @code{calendar-date-style}.}.  For example, with optional time:
-
-@example
-* 22:00-23:00 The nerd meeting on every 2nd Thursday of the month
-  <%%(diary-float t 4 2)>
-@end example
-
-@item Time/Date range
-@cindex timerange
-@cindex date range
-Two timestamps connected by @samp{--} denote a range.  The headline is
-shown on the first and last day of the range, and on any dates that
-are displayed and fall in the range.  Here is an example:
-
-@example
-** Meeting in Amsterdam
-   <2004-08-23 Mon>--<2004-08-26 Thu>
-@end example
-
-@item Inactive timestamp
-@cindex timestamp, inactive
-@cindex inactive timestamp
-Just like a plain timestamp, but with square brackets instead of
-angular ones.  These timestamps are inactive in the sense that they
-do @emph{not} trigger an entry to show up in the agenda.
-
-@example
-* Gillian comes late for the fifth time
-  [2006-11-01 Wed]
-@end example
-@end table
-
-@node Creating Timestamps
-@section Creating Timestamps
-
-For Org mode to recognize timestamps, they need to be in the specific
-format.  All commands listed below produce timestamps in the correct
-format.
-
-@table @asis
-@item @kbd{C-c .} (@code{org-time-stamp})
-@kindex C-c .
-@findex org-time-stamp
-Prompt for a date and insert a corresponding timestamp.  When point
-is at an existing timestamp in the buffer, the command is used to
-modify this timestamp instead of inserting a new one.  When this
-command is used twice in succession, a time range is inserted.
-
-@kindex C-u C-c .
-@vindex org-time-stamp-rounding-minutes
-When called with a prefix argument, use the alternative format which
-contains date and time.  The default time can be rounded to
-multiples of 5 minutes.  See the option
-@code{org-time-stamp-rounding-minutes}.
-
-@kindex C-u C-u C-c .
-With two prefix arguments, insert an active timestamp with the
-current time without prompting.
-
-@item @kbd{C-c !} (@code{org-time-stamp-inactive})
-@kindex C-c !
-@kindex C-u C-c !
-@kindex C-u C-u C-c !
-@findex org-time-stamp-inactive
-Like @kbd{C-c .}, but insert an inactive timestamp that does
-not cause an agenda entry.
-
-@item @kbd{C-c C-c}
-@kindex C-c C-c
-Normalize timestamp, insert or fix day name if missing or wrong.
-
-@item @kbd{C-c <} (@code{org-date-from-calendar})
-@kindex C-c <
-@findex org-date-from-calendar
-Insert a timestamp corresponding to point date in the calendar.
-
-@item @kbd{C-c >} (@code{org-goto-calendar})
-@kindex C-c >
-@findex org-goto-calendar
-Access the Emacs calendar for the current date.  If there is
-a timestamp in the current line, go to the corresponding date
-instead.
-
-@item @kbd{C-c C-o} (@code{org-open-at-point})
-@kindex C-c C-o
-@findex org-open-at-point
-Access the agenda for the date given by the timestamp or -range at
-point (see @ref{Weekly/daily agenda}).
-
-@item @kbd{S-@key{LEFT}} (@code{org-timestamp-down-day})
-@itemx @kbd{S-@key{RIGHT}} (@code{org-timestamp-up-day})
-@kindex S-LEFT
-@kindex S-RIGHT
-@findex org-timestamp-down-day
-@findex org-timestamp-up-day
-Change date at point by one day.  These key bindings conflict with
-shift-selection and related modes (see @ref{Conflicts}).
-
-@item @kbd{S-@key{UP}} (@code{org-timestamp-up})
-@itemx @kbd{S-@key{DOWN}} (@code{org-timestamp-down})
-@kindex S-UP
-@kindex S-DOWN
-On the beginning or enclosing bracket of a timestamp, change its
-type.  Within a timestamp, change the item under point.  Point can
-be on a year, month, day, hour or minute.  When the timestamp
-contains a time range like @samp{15:30-16:30}, modifying the first time
-also shifts the second, shifting the time block with constant
-length.  To change the length, modify the second time.  Note that if
-point is in a headline and not at a timestamp, these same keys
-modify the priority of an item (see @ref{Priorities}).  The key bindings
-also conflict with shift-selection and related modes (see @ref{Conflicts}).
-
-@item @kbd{C-c C-y} (@code{org-evaluate-time-range})
-@kindex C-c C-y
-@findex org-evaluate-time-range
-@cindex evaluate time range
-Evaluate a time range by computing the difference between start and
-end.  With a prefix argument, insert result after the time range (in
-a table: into the following column).
-@end table
-
-@menu
-* The date/time prompt::         How Org mode helps you enter dates and times.
-* Custom time format::           Making dates look different.
-@end menu
-
-@node The date/time prompt
-@subsection The date/time prompt
-
-@cindex date, reading in minibuffer
-@cindex time, reading in minibuffer
-
-@vindex org-read-date-prefer-future
-When Org mode prompts for a date/time, the default is shown in default
-date/time format, and the prompt therefore seems to ask for a specific
-format.  But it in fact accepts date/time information in a variety of
-formats.  Generally, the information should start at the beginning of
-the string.  Org mode finds whatever information is in there and
-derives anything you have not specified from the @emph{default date and
-time}.  The default is usually the current date and time, but when
-modifying an existing timestamp, or when entering the second stamp of
-a range, it is taken from the stamp in the buffer.  When filling in
-information, Org mode assumes that most of the time you want to enter
-a date in the future: if you omit the month/year and the given
-day/month is @emph{before} today, it assumes that you mean a future
-date@footnote{See the variable @code{org-read-date-prefer-future}.  You may set
-that variable to the symbol @code{time} to even make a time before now
-shift the date to tomorrow.}.  If the date has been automatically shifted into 
the
-future, the time prompt shows this with @samp{(=>F)}.
-
-For example, let's assume that today is @strong{June 13, 2006}.  Here is how
-various inputs are interpreted, the items filled in by Org mode are in
-@strong{bold}.
-
-@multitable {aaaaaaaaaaaaaa} {aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa}
-@item @samp{3-2-5}
-@tab @result{} 2003-02-05
-@item @samp{2/5/3}
-@tab @result{} 2003-02-05
-@item @samp{14}
-@tab @result{} @strong{2006}-@strong{06}-14
-@item @samp{12}
-@tab @result{} @strong{2006}-@strong{07}-12
-@item @samp{2/5}
-@tab @result{} @strong{2007}-02-05
-@item @samp{Fri}
-@tab @result{} nearest Friday (default date or later)
-@item @samp{sep 15}
-@tab @result{} @strong{2006}-09-15
-@item @samp{feb 15}
-@tab @result{} @strong{2007}-02-15
-@item @samp{sep 12 9}
-@tab @result{} 2009-09-12
-@item @samp{12:45}
-@tab @result{} @strong{2006}-@strong{06}-@strong{13} 12:45
-@item @samp{22 sept 0:34}
-@tab @result{} @strong{2006}-09-22 0:34
-@item @samp{w4}
-@tab @result{} ISO week for of the current year @strong{2006}
-@item @samp{2012 w4 fri}
-@tab @result{} Friday of ISO week 4 in 2012
-@item @samp{2012-w04-5}
-@tab @result{} Same as above
-@end multitable
-
-Furthermore you can specify a relative date by giving, as the @emph{first}
-thing in the input: a plus/minus sign, a number and a letter---@samp{d},
-@samp{w}, @samp{m} or @samp{y}---to indicate change in days, weeks, months, or
-years.  With a single plus or minus, the date is always relative to
-today.  With a double plus or minus, it is relative to the default
-date.  If instead of a single letter, you use the abbreviation of day
-name, the date is the Nth such day, e.g.:
-
-@multitable {aaaaaaa} {aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa}
-@item @samp{+0}
-@tab @result{} today
-@item @samp{.}
-@tab @result{} today
-@item @samp{+4d}
-@tab @result{} four days from today
-@item @samp{+4}
-@tab @result{} same as +4d
-@item @samp{+2w}
-@tab @result{} two weeks from today
-@item @samp{++5}
-@tab @result{} five days from default date
-@item @samp{+2tue}
-@tab @result{} second Tuesday from now
-@end multitable
-
-@vindex parse-time-months
-@vindex parse-time-weekdays
-The function understands English month and weekday abbreviations.  If
-you want to use un-abbreviated names and/or other languages, configure
-the variables @code{parse-time-months} and @code{parse-time-weekdays}.
-
-@vindex org-read-date-force-compatible-dates
-Not all dates can be represented in a given Emacs implementation.  By
-default Org mode forces dates into the compatibility range 1970--2037
-which works on all Emacs implementations.  If you want to use dates
-outside of this range, read the docstring of the variable
-@code{org-read-date-force-compatible-dates}.
-
-You can specify a time range by giving start and end times or by
-giving a start time and a duration (in HH:MM format).  Use one or two
-dash(es) as the separator in the former case and use @samp{+} as the
-separator in the latter case, e.g.:
-
-@multitable {aaaaaaaaaaaaaa} {aaaaaaaaaaaaaaaaaaaaa}
-@item @samp{11am-1:15pm}
-@tab @result{} 11:00-13:15
-@item @samp{11am--1:15pm}
-@tab @result{} same as above
-@item @samp{11am+2:15}
-@tab @result{} same as above
-@end multitable
-
-@cindex calendar, for selecting date
-@vindex org-popup-calendar-for-date-prompt
-Parallel to the minibuffer prompt, a calendar is popped up@footnote{If you do 
not need/want the calendar, configure the variable
-@code{org-popup-calendar-for-date-prompt}.}.
-When you exit the date prompt, either by clicking on a date in the
-calendar, or by pressing @kbd{@key{RET}}, the date selected in the
-calendar is combined with the information entered at the prompt.  You
-can control the calendar fully from the minibuffer:
-
-@kindex <
-@kindex >
-@kindex M-v
-@kindex C-v
-@kindex mouse-1
-@kindex S-RIGHT
-@kindex S-LEFT
-@kindex S-DOWN
-@kindex S-UP
-@kindex M-S-RIGHT
-@kindex M-S-LEFT
-@kindex RET
-@kindex .
-@kindex C-.
-@multitable @columnfractions 0.25 0.55
-@item @kbd{@key{RET}}
-@tab Choose date at point in calendar.
-@item @kbd{mouse-1}
-@tab Select date by clicking on it.
-@item @kbd{S-@key{RIGHT}}
-@tab One day forward.
-@item @kbd{S-@key{LEFT}}
-@tab One day backward.
-@item @kbd{S-@key{DOWN}}
-@tab One week forward.
-@item @kbd{S-@key{UP}}
-@tab One week backward.
-@item @kbd{M-S-@key{RIGHT}}
-@tab One month forward.
-@item @kbd{M-S-@key{LEFT}}
-@tab One month backward.
-@item @kbd{>}
-@tab Scroll calendar forward by one month.
-@item @kbd{<}
-@tab Scroll calendar backward by one month.
-@item @kbd{M-v}
-@tab Scroll calendar forward by 3 months.
-@item @kbd{C-v}
-@tab Scroll calendar backward by 3 months.
-@item @kbd{C-.}
-@tab Select today's date@footnote{You can also use the calendar command 
@kbd{.} to jump to
-today's date, but if you are inserting an hour specification for your
-timestamp, @kbd{.} will then insert a dot after the hour.  By contrast,
-@kbd{C-.} will always jump to today's date.}
-@end multitable
-
-@vindex org-read-date-display-live
-The actions of the date/time prompt may seem complex, but I assure you
-they will grow on you, and you will start getting annoyed by pretty
-much any other way of entering a date/time out there.  To help you
-understand what is going on, the current interpretation of your input
-is displayed live in the minibuffer@footnote{If you find this distracting, 
turn off the display with
-@code{org-read-date-display-live}.}.
-
-@node Custom time format
-@subsection Custom time format
-
-@cindex custom date/time format
-@cindex time format, custom
-@cindex date format, custom
-
-@vindex org-display-custom-times
-@vindex org-time-stamp-custom-formats
-Org mode uses the standard ISO notation for dates and times as it is
-defined in ISO 8601.  If you cannot get used to this and require
-another representation of date and time to keep you happy, you can get
-it by customizing the variables @code{org-display-custom-times} and
-@code{org-time-stamp-custom-formats}.
-
-@table @asis
-@item @kbd{C-c C-x C-t} (@code{org-toggle-time-stamp-overlays})
-@kindex C-c C-x C-t
-@findex org-toggle-time-stamp-overlays
-Toggle the display of custom formats for dates and times.
-@end table
-
-Org mode needs the default format for scanning, so the custom
-date/time format does not @emph{replace} the default format.  Instead, it
-is put @emph{over} the default format using text properties.  This has the
-following consequences:
-
-@itemize
-@item
-You cannot place point onto a timestamp anymore, only before or
-after.
-
-@item
-The @kbd{S-@key{UP}} and @kbd{S-@key{DOWN}} keys can no longer be used
-to adjust each component of a timestamp.  If point is at the
-beginning of the stamp, @kbd{S-@key{UP}} and @kbd{S-@key{DOWN}} change
-the stamp by one day, just like @kbd{S-@key{LEFT}}
-@kbd{S-@key{RIGHT}}.  At the end of the stamp, change the time by one
-minute.
-
-@item
-If the timestamp contains a range of clock times or a repeater,
-these are not overlaid, but remain in the buffer as they were.
-
-@item
-When you delete a timestamp character-by-character, it only
-disappears from the buffer after @emph{all} (invisible) characters
-belonging to the ISO timestamp have been removed.
-
-@item
-If the custom timestamp format is longer than the default and you
-are using dates in tables, table alignment will be messed up.  If
-the custom format is shorter, things do work as expected.
-@end itemize
-
-@node Deadlines and Scheduling
-@section Deadlines and Scheduling
-
-A timestamp may be preceded by special keywords to facilitate
-planning.  Both the timestamp and the keyword have to be positioned
-immediately after the task they refer to.
-
-@table @asis
-@item @samp{DEADLINE}
-@cindex @samp{DEADLINE} marker
-Meaning: the task---most likely a TODO item, though not
-necessarily---is supposed to be finished on that date.
-
-@vindex org-deadline-warning-days
-On the deadline date, the task is listed in the agenda.  In
-addition, the agenda for @emph{today} carries a warning about the
-approaching or missed deadline, starting @code{org-deadline-warning-days}
-before the due date, and continuing until the entry is marked as
-done.  An example:
-
-@example
-*** TODO write article about the Earth for the Guide
-    DEADLINE: <2004-02-29 Sun>
-    The editor in charge is [[bbdb:Ford Prefect]]
-@end example
-
-@vindex org-agenda-skip-deadline-prewarning-if-scheduled
-You can specify a different lead time for warnings for a specific
-deadlines using the following syntax.  Here is an example with
-a warning period of 5 days @samp{DEADLINE: <2004-02-29 Sun -5d>}.  This
-warning is deactivated if the task gets scheduled and you set
-@code{org-agenda-skip-deadline-prewarning-if-scheduled} to @code{t}.
-
-@item @samp{SCHEDULED}
-@cindex @samp{SCHEDULED} marker
-Meaning: you are planning to start working on that task on the given
-date.
-
-@vindex org-agenda-skip-scheduled-if-done
-The headline is listed under the given date@footnote{It will still be listed 
on that date after it has been marked
-as done.  If you do not like this, set the variable
-@code{org-agenda-skip-scheduled-if-done}.}.  In addition,
-a reminder that the scheduled date has passed is present in the
-compilation for @emph{today}, until the entry is marked as done, i.e.,
-the task is automatically forwarded until completed.
-
-@example
-*** TODO Call Trillian for a date on New Years Eve.
-    SCHEDULED: <2004-12-25 Sat>
-@end example
-
-@vindex org-scheduled-delay-days
-@vindex org-agenda-skip-scheduled-delay-if-deadline
-If you want to @emph{delay} the display of this task in the agenda, use
-@samp{SCHEDULED: <2004-12-25 Sat -2d>}: the task is still scheduled on
-the 25th but will appear two days later.  In case the task contains
-a repeater, the delay is considered to affect all occurrences; if
-you want the delay to only affect the first scheduled occurrence of
-the task, use @samp{--2d} instead.  See @code{org-scheduled-delay-days} and
-@code{org-agenda-skip-scheduled-delay-if-deadline} for details on how to
-control this globally or per agenda.
-
-@quotation Important
-Scheduling an item in Org mode should @emph{not} be understood in the
-same way that we understand @emph{scheduling a meeting}.  Setting a date
-for a meeting is just a simple appointment, you should mark this
-entry with a simple plain timestamp, to get this item shown on the
-date where it applies.  This is a frequent misunderstanding by Org
-users.  In Org mode, @emph{scheduling} means setting a date when you want
-to start working on an action item.
-
-@end quotation
-@end table
-
-You may use timestamps with repeaters in scheduling and deadline
-entries.  Org mode issues early and late warnings based on the
-assumption that the timestamp represents the @emph{nearest instance} of the
-repeater.  However, the use of diary expression entries like
-
-@example
-<%%(diary-float t 42)>
-@end example
-
-
-@noindent
-in scheduling and deadline timestamps is limited.  Org mode does not
-know enough about the internals of each function to issue early and
-late warnings.  However, it shows the item on each day where the
-expression entry matches.
-
-@menu
-* Inserting deadline/schedule::  Planning items.
-* Repeated tasks::               Items that show up again and again.
-@end menu
-
-@node Inserting deadline/schedule
-@subsection Inserting deadlines or schedules
-
-The following commands allow you to quickly insert a deadline or to
-schedule an item:@footnote{The @samp{SCHEDULED} and @samp{DEADLINE} dates are 
inserted on the line
-right below the headline.  Do not put any text between this line and
-the headline.}
-
-@table @asis
-@item @kbd{C-c C-d} (@code{org-deadline})
-@kindex C-c C-d
-@findex org-deadline
-@vindex org-log-redeadline
-Insert @samp{DEADLINE} keyword along with a stamp.  The insertion happens
-in the line directly following the headline.  Remove any @samp{CLOSED}
-timestamp .  When called with a prefix argument, also remove any
-existing deadline from the entry.  Depending on the variable
-@code{org-log-redeadline}, take a note when changing an existing
-deadline@footnote{Note the corresponding @samp{STARTUP} options 
@samp{logredeadline},
-@samp{lognoteredeadline}, and @samp{nologredeadline}.}.
-
-@item @kbd{C-c C-s} (@code{org-schedule})
-@kindex C-c C-s
-@findex org-schedule
-@vindex org-log-reschedule
-Insert @samp{SCHEDULED} keyword along with a stamp.  The insertion
-happens in the line directly following the headline.  Remove any
-@samp{CLOSED} timestamp.  When called with a prefix argument, also remove
-the scheduling date from the entry.  Depending on the variable
-@code{org-log-reschedule}, take a note when changing an existing
-scheduling time@footnote{Note the corresponding @samp{STARTUP} options 
@samp{logreschedule},
-@samp{lognotereschedule}, and @samp{nologreschedule}.}.
-
-@item @kbd{C-c / d} (@code{org-check-deadlines})
-@kindex C-c / d
-@findex org-check-deadlines
-@cindex sparse tree, for deadlines
-@vindex org-deadline-warning-days
-Create a sparse tree with all deadlines that are either past-due, or
-which will become due within @code{org-deadline-warning-days}.  With
-@kbd{C-u} prefix, show all deadlines in the file.  With
-a numeric prefix, check that many days.  For example, @kbd{C-1 C-c / d} shows 
all deadlines due tomorrow.
-
-@item @kbd{C-c / b} (@code{org-check-before-date})
-@kindex C-c / b
-@findex org-check-before-date
-Sparse tree for deadlines and scheduled items before a given date.
-
-@item @kbd{C-c / a} (@code{org-check-after-date})
-@kindex C-c / a
-@findex org-check-after-date
-Sparse tree for deadlines and scheduled items after a given date.
-@end table
-
-Note that @code{org-schedule} and @code{org-deadline} supports setting the date
-by indicating a relative time e.g., @samp{+1d} sets the date to the next
-day after today, and @samp{--1w} sets the date to the previous week before
-any current timestamp.
-
-@node Repeated tasks
-@subsection Repeated tasks
-
-@cindex tasks, repeated
-@cindex repeated tasks
-
-Some tasks need to be repeated again and again.  Org mode helps to
-organize such tasks using a so-called repeater in a @samp{DEADLINE},
-@samp{SCHEDULED}, or plain timestamps@footnote{Org does not repeat inactive 
timestamps, however.  See
-@ref{Timestamps}.}.  In the following example:
-
-@example
-** TODO Pay the rent
-   DEADLINE: <2005-10-01 Sat +1m>
-@end example
-
-@noindent
-the @samp{+1m} is a repeater; the intended interpretation is that the task
-has a deadline on @samp{<2005-10-01>} and repeats itself every (one) month
-starting from that time.  You can use yearly, monthly, weekly, daily
-and hourly repeat cookies by using the @samp{y}, @samp{m}, @samp{w}, @samp{d} 
and @samp{h}
-letters.  If you need both a repeater and a special warning period in
-a deadline entry, the repeater should come first and the warning
-period last
-
-@example
-DEADLINE: <2005-10-01 Sat +1m -3d>
-@end example
-
-
-@vindex org-todo-repeat-to-state
-Deadlines and scheduled items produce entries in the agenda when they
-are over-due, so it is important to be able to mark such an entry as
-done once you have done so.  When you mark a @samp{DEADLINE} or
-a @samp{SCHEDULED} with the TODO keyword @samp{DONE}, it no longer produces
-entries in the agenda.  The problem with this is, however, is that
-then also the @emph{next} instance of the repeated entry will not be
-active.  Org mode deals with this in the following way: when you try
-to mark such an entry as done, using @kbd{C-c C-t}, it shifts the
-base date of the repeating timestamp by the repeater interval, and
-immediately sets the entry state back to TODO@footnote{In fact, the target 
state is taken from, in this sequence, the
-@samp{REPEAT_TO_STATE} property, the variable @code{org-todo-repeat-to-state} 
if
-it is a string, the previous TODO state if @code{org-todo-repeat-to-state}
-is @code{t}, or the first state of the TODO state sequence.}.  In the example
-above, setting the state to @samp{DONE} would actually switch the date like
-this:
-
-@example
-** TODO Pay the rent
-   DEADLINE: <2005-11-01 Tue +1m>
-@end example
-
-To mark a task with a repeater as DONE, use @kbd{C-- 1 C-c C-t},
-i.e., @code{org-todo} with a numeric prefix argument of @samp{-1}.
-
-@vindex org-log-repeat
-A timestamp@footnote{You can change this using the option 
@code{org-log-repeat}, or the
-@samp{STARTUP} options @samp{logrepeat}, @samp{lognoterepeat}, and 
@samp{nologrepeat}.
-With @samp{lognoterepeat}, you will also be prompted for a note.} is added 
under the deadline, to keep a record that
-you actually acted on the previous instance of this deadline.
-
-As a consequence of shifting the base date, this entry is no longer
-visible in the agenda when checking past dates, but all future
-instances will be visible.
-
-With the @samp{+1m} cookie, the date shift is always exactly one month.  So
-if you have not paid the rent for three months, marking this entry
-DONE still keeps it as an overdue deadline.  Depending on the task,
-this may not be the best way to handle it.  For example, if you forgot
-to call your father for 3 weeks, it does not make sense to call him
-3 times in a single day to make up for it.  Finally, there are tasks,
-like changing batteries, which should always repeat a certain time
-@emph{after} the last time you did it.  For these tasks, Org mode has
-special repeaters @samp{++} and @samp{.+}.  For example:
-
-@example
-** TODO Call Father
-   DEADLINE: <2008-02-10 Sun ++1w>
-   Marking this DONE shifts the date by at least one week, but also
-   by as many weeks as it takes to get this date into the future.
-   However, it stays on a Sunday, even if you called and marked it
-   done on Saturday.
-
-** TODO Empty kitchen trash
-   DEADLINE: <2008-02-08 Fri 20:00 ++1d>
-   Marking this DONE shifts the date by at least one day, and also
-   by as many days as it takes to get the timestamp into the future.
-   Since there is a time in the timestamp, the next deadline in the
-   future will be on today's date if you complete the task before
-   20:00.
-
-** TODO Check the batteries in the smoke detectors
-   DEADLINE: <2005-11-01 Tue .+1m>
-   Marking this DONE shifts the date to one month after today.
-
-** TODO Wash my hands
-   DEADLINE: <2019-04-05 08:00 Sun .+1h>
-   Marking this DONE shifts the date to exactly one hour from now.
-@end example
-
-@vindex org-agenda-skip-scheduled-if-deadline-is-shown
-You may have both scheduling and deadline information for a specific
-task.  If the repeater is set for the scheduling information only, you
-probably want the repeater to be ignored after the deadline.  If so,
-set the variable @code{org-agenda-skip-scheduled-if-deadline-is-shown} to
-@code{repeated-after-deadline}.  However, any scheduling information
-without a repeater is no longer relevant once the task is done, and
-thus, removed upon repeating the task.  If you want both scheduling
-and deadline information to repeat after the same interval, set the
-same repeater for both timestamps.
-
-An alternative to using a repeater is to create a number of copies of
-a task subtree, with dates shifted in each copy.  The command
-@kbd{C-c C-x c} was created for this purpose; it is described in
-@ref{Structure Editing}.
-
-@node Clocking Work Time
-@section Clocking Work Time
-
-@cindex clocking time
-@cindex time clocking
-
-Org mode allows you to clock the time you spend on specific tasks in
-a project.  When you start working on an item, you can start the
-clock.  When you stop working on that task, or when you mark the task
-done, the clock is stopped and the corresponding time interval is
-recorded.  It also computes the total time spent on each
-subtree@footnote{Clocking only works if all headings are indented with less
-than 30 stars.  This is a hard-coded limitation of @code{lmax} in
-@code{org-clock-sum}.} of a project.  And it remembers a history or tasks
-recently clocked, so that you can jump quickly between a number of
-tasks absorbing your time.
-
-To save the clock history across Emacs sessions, use:
-
-@lisp
-(setq org-clock-persist 'history)
-(org-clock-persistence-insinuate)
-@end lisp
-
-@vindex org-clock-persist
-When you clock into a new task after resuming Emacs, the incomplete
-clock@footnote{To resume the clock under the assumption that you have worked
-on this task while outside Emacs, use @samp{(setq org-clock-persist t)}.} is 
retrieved (see @ref{Resolving idle time (1)}) and you are
-prompted about what to do with it.
-
-@menu
-* Clocking commands::            Starting and stopping a clock.
-* The clock table::              Detailed reports.
-* Resolving idle time::          Resolving time when you've been idle.
-@end menu
-
-@node Clocking commands
-@subsection Clocking commands
-
-@table @asis
-@item @kbd{C-c C-x C-i} (@code{org-clock-in})
-@kindex C-c C-x C-i
-@findex org-clock-in
-@vindex org-clock-into-drawer
-@vindex org-clock-continuously
-@cindex @samp{LOG_INTO_DRAWER}, property
-Start the clock on the current item (clock-in).  This inserts the
-@samp{CLOCK} keyword together with a timestamp.  If this is not the first
-clocking of this item, the multiple @samp{CLOCK} lines are wrapped into
-a @samp{LOGBOOK} drawer (see also the variable @code{org-clock-into-drawer}).
-You can also overrule the setting of this variable for a subtree by
-setting a @samp{CLOCK_INTO_DRAWER} or @samp{LOG_INTO_DRAWER} property.  When
-called with a @kbd{C-u} prefix argument, select the task from
-a list of recently clocked tasks.  With two @kbd{C-u C-u}
-prefixes, clock into the task at point and mark it as the default
-task; the default task is always be available with letter
-@kbd{d} when selecting a clocking task.  With three @kbd{C-u C-u C-u} 
prefixes, force continuous clocking by starting the
-clock when the last clock stopped.
-
-@cindex @samp{CLOCK_MODELINE_TOTAL}, property
-@cindex @samp{LAST_REPEAT}, property
-@vindex org-clock-mode-line-total
-@vindex org-clock-in-prepare-hook
-While the clock is running, Org shows the current clocking time in
-the mode line, along with the title of the task.  The clock time
-shown is all time ever clocked for this task and its children.  If
-the task has an effort estimate (see @ref{Effort Estimates}), the mode
-line displays the current clocking time against it@footnote{To add an effort 
estimate ``on the fly'', hook a function doing
-this to @code{org-clock-in-prepare-hook}.}.  If the
-task is a repeating one (see @ref{Repeated tasks}), show only the time
-since the last reset of the task@footnote{The last reset of the task is 
recorded by the @samp{LAST_REPEAT}
-property.}.  You can exercise more
-control over show time with the @samp{CLOCK_MODELINE_TOTAL} property.  It
-may have the values @samp{current} to show only the current clocking
-instance, @samp{today} to show all time clocked on this tasks today---see
-also the variable @code{org-extend-today-until}, @code{all} to include all
-time, or @code{auto} which is the default@footnote{See also the variable 
@code{org-clock-mode-line-total}.}.  Clicking with
-@kbd{mouse-1} onto the mode line entry pops up a menu with
-clocking options.
-
-@item @kbd{C-c C-x C-o} (@code{org-clock-out})
-@kindex C-c C-x C-o
-@findex org-clock-out
-@vindex org-log-note-clock-out
-Stop the clock (clock-out).  This inserts another timestamp at the
-same location where the clock was last started.  It also directly
-computes the resulting time in inserts it after the time range as
-@samp{=>HH:MM}.  See the variable @code{org-log-note-clock-out} for the
-possibility to record an additional note together with the clock-out
-timestamp@footnote{The corresponding in-buffer setting is: @samp{#+STARTUP:
-lognoteclock-out}.}.
-
-@item @kbd{C-c C-x C-x} (@code{org-clock-in-last})
-@kindex C-c C-x C-x
-@findex org-clock-in-last
-@vindex org-clock-continuously
-Re-clock the last clocked task.  With one @kbd{C-u} prefix
-argument, select the task from the clock history.  With two
-@kbd{C-u} prefixes, force continuous clocking by starting the
-clock when the last clock stopped.
-
-@item @kbd{C-c C-x C-e} (@code{org-clock-modify-effort-estimate})
-@kindex C-c C-x C-e
-@findex org-clock-modify-effort-estimate
-Update the effort estimate for the current clock task.
-
-@item @kbd{C-c C-c} or @kbd{C-c C-y} (@code{org-evaluate-time-range})
-@kindex C-c C-c
-@kindex C-c C-y
-@findex org-evaluate-time-range
-Recompute the time interval after changing one of the timestamps.
-This is only necessary if you edit the timestamps directly.  If you
-change them with @kbd{S-<cursor>} keys, the update is
-automatic.
-
-@item @kbd{C-S-@key{UP}} (@code{org-clock-timestamps-up})
-@itemx @kbd{C-S-@key{DOWN}} (@code{org-clock-timestamps-down})
-@kindex C-S-UP
-@findex org-clock-timestamps-up
-@kindex C-S-DOWN
-@findex org-clock-timestamps-down
-On CLOCK log lines, increase/decrease both timestamps so that the
-clock duration keeps the same value.
-
-@item @kbd{S-M-@key{UP}} (@code{org-timestamp-up})
-@itemx @kbd{S-M-@key{DOWN}} (@code{org-timestamp-down})
-@kindex S-M-UP
-@findex org-clock-timestamp-up
-@kindex S-M-DOWN
-@findex org-clock-timestamp-down
-On @samp{CLOCK} log lines, increase/decrease the timestamp at point and
-the one of the previous, or the next, clock timestamp by the same
-duration.  For example, if you hit @kbd{S-M-@key{UP}} to increase
-a clocked-out timestamp by five minutes, then the clocked-in
-timestamp of the next clock is increased by five minutes.
-
-@item @kbd{C-c C-t} (@code{org-todo})
-@kindex C-c C-t
-@findex org-todo
-Changing the TODO state of an item to DONE automatically stops the
-clock if it is running in this same item.
-
-@item @kbd{C-c C-x C-q} (@code{org-clock-cancel})
-@kindex C-c C-x C-q
-@findex org-clock-cancel
-Cancel the current clock.  This is useful if a clock was started by
-mistake, or if you ended up working on something else.
-
-@item @kbd{C-c C-x C-j} (@code{org-clock-goto})
-@kindex C-c C-x C-j
-@findex or-clock-goto
-Jump to the headline of the currently clocked in task.  With
-a @kbd{C-u} prefix argument, select the target task from a list
-of recently clocked tasks.
-
-@item @kbd{C-c C-x C-d} (@code{org-clock-display})
-@kindex C-c C-x C-d
-@findex org-clock-display
-@vindex org-remove-highlights-with-change
-Display time summaries for each subtree in the current buffer.  This
-puts overlays at the end of each headline, showing the total time
-recorded under that heading, including the time of any subheadings.
-You can use visibility cycling to study the tree, but the overlays
-disappear when you change the buffer (see variable
-@code{org-remove-highlights-with-change}) or press @kbd{C-c C-c}.
-@end table
-
-The @kbd{l} key may be used in the agenda (see @ref{Weekly/daily agenda}) to 
show which tasks have been worked on or closed during
-a day.
-
-@strong{Important:} note that both @code{org-clock-out} and 
@code{org-clock-in-last}
-can have a global keybinding and do not modify the window disposition.
-
-@node The clock table
-@subsection The clock table
-
-@cindex clocktable, dynamic block
-@cindex report, of clocked time
-
-Org mode can produce quite complex reports based on the time clocking
-information.  Such a report is called a @emph{clock table}, because it is
-formatted as one or several Org tables.
-
-@table @asis
-@item @code{org-clock-report}
-@kindex C-c C-x x
-@findex org-clock-report
-Insert or update a clock table.  When called with a prefix argument,
-jump to the first clock table in the current document and update it.
-The clock table includes archived trees.
-
-This command can be invoked by calling
-@code{org-dynamic-block-insert-dblock} (@kbd{C-c C-x x}) and
-selecting ``clocktable'' (see @ref{Dynamic Blocks}).
-
-@item @kbd{C-c C-c} or @kbd{C-c C-x C-u} (@code{org-dblock-update})
-@kindex C-c C-c
-@kindex C-c C-x C-u
-@findex org-dblock-update
-Update dynamic block at point.  Point needs to be in the @samp{BEGIN}
-line of the dynamic block.
-
-@item @kbd{C-u C-c C-x C-u}
-@kindex C-u C-c C-x C-u
-Update all dynamic blocks (see @ref{Dynamic Blocks}).  This is useful if
-you have several clock table blocks in a buffer.
-
-@item @kbd{S-@key{LEFT}}
-@itemx @kbd{S-@key{RIGHT}} (@code{org-clocktable-try-shift})
-@kindex S-LEFT
-@kindex S-RIGHT
-@findex org-clocktable-try-shift
-Shift the current @samp{:block} interval and update the table.  Point
-needs to be in the @samp{#+BEGIN: clocktable} line for this command.  If
-@samp{:block} is @samp{today}, it is shifted to @samp{today-1}, etc.
-@end table
-
-Here is an example of the frame for a clock table as it is inserted
-into the buffer by @code{org-clock-report}:
-
-@cindex @samp{BEGIN clocktable}
-@example
-#+BEGIN: clocktable :maxlevel 2 :emphasize nil :scope file
-#+END: clocktable
-@end example
-
-@vindex org-clocktable-defaults
-The @samp{#+BEGIN} line contains options to define the scope, structure,
-and formatting of the report.  Defaults for all these options can be
-configured in the variable @code{org-clocktable-defaults}.
-
-First there are options that determine which clock entries are to
-be selected:
-
-@table @asis
-@item @samp{:maxlevel}
-Maximum level depth to which times are listed in the table.  Clocks
-at deeper levels are summed into the upper level.
-
-@item @samp{:scope}
-The scope to consider.  This can be any of the following:
-
-@multitable {aaaaaaaaaaaaaaaaaaaaaa} 
{aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa}
-@item @samp{nil}
-@tab the current buffer or narrowed region
-@item @samp{file}
-@tab the full current buffer
-@item @samp{subtree}
-@tab the subtree where the clocktable is located
-@item @samp{treeN}
-@tab the surrounding level N tree, for example @samp{tree3}
-@item @samp{tree}
-@tab the surrounding level 1 tree
-@item @samp{agenda}
-@tab all agenda files
-@item @samp{("file" ...)}
-@tab scan these files
-@item @samp{FUNCTION}
-@tab scan files returned by calling @var{FUNCTION} with no argument
-@item @samp{file-with-archives}
-@tab current file and its archives
-@item @samp{agenda-with-archives}
-@tab all agenda files, including archives
-@end multitable
-
-@item @samp{:block}
-The time block to consider.  This block is specified either
-absolutely, or relative to the current time and may be any of these
-formats:
-
-@multitable {aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa} {aaaaaaaaaaaaaaaaaaaaa}
-@item @samp{2007-12-31}
-@tab New year eve 2007
-@item @samp{2007-12}
-@tab December 2007
-@item @samp{2007-W50}
-@tab ISO-week 50 in 2007
-@item @samp{2007-Q2}
-@tab 2nd quarter in 2007
-@item @samp{2007}
-@tab the year 2007
-@item @samp{today}, @samp{yesterday}, @samp{today-N}
-@tab a relative day
-@item @samp{thisweek}, @samp{lastweek}, @samp{thisweek-N}
-@tab a relative week
-@item @samp{thismonth}, @samp{lastmonth}, @samp{thismonth-N}
-@tab a relative month
-@item @samp{thisyear}, @samp{lastyear}, @samp{thisyear-N}
-@tab a relative year
-@item @samp{untilnow}@footnote{When using @code{:step}, @code{untilnow} starts 
from the beginning of
-2003, not the beginning of time.}
-@tab all clocked time ever
-@end multitable
-
-@vindex org-clock-display-default-range
-When this option is not set, Org falls back to the value in
-@code{org-clock-display-default-range}, which defaults to the current
-year.
-
-Use @kbd{S-@key{LEFT}} or @kbd{S-@key{RIGHT}} to shift the time
-interval.
-
-@item @samp{:tstart}
-A time string specifying when to start considering times.  Relative
-times like @samp{"<-2w>"} can also be used.  See @ref{Matching tags and 
properties} for relative time syntax.
-
-@item @samp{:tend}
-A time string specifying when to stop considering times.  Relative
-times like @samp{"<now>"} can also be used.  See @ref{Matching tags and 
properties} for relative time syntax.
-
-@item @samp{:wstart}
-The starting day of the week.  The default is 1 for Monday.
-
-@item @samp{:mstart}
-The starting day of the month.  The default is 1 for the first.
-
-@item @samp{:step}
-Set to @samp{day}, @samp{week}, @samp{semimonth}, @samp{month}, or @samp{year} 
to split the
-table into chunks.  To use this, either @samp{:block}, or @samp{:tstart} and
-@samp{:tend} are required.
-
-@item @samp{:stepskip0}
-When non-@code{nil}, do not show steps that have zero time.
-
-@item @samp{:fileskip0}
-When non-@code{nil}, do not show table sections from files which did not
-contribute.
-
-@item @samp{:match}
-A tags match to select entries that should contribute.  See
-@ref{Matching tags and properties} for the match syntax.
-@end table
-
-@findex org-clocktable-write-default
-Then there are options that determine the formatting of the table.
-There options are interpreted by the function
-@code{org-clocktable-write-default}, but you can specify your own function
-using the @samp{:formatter} parameter.
-
-@table @asis
-@item @samp{:emphasize}
-When non-@code{nil}, emphasize level one and level two items.
-
-@item @samp{:lang}
-Language@footnote{Language terms can be set through the variable
-@code{org-clock-clocktable-language-setup}.} to use for descriptive cells like 
``Task''.
-
-@item @samp{:link}
-Link the item headlines in the table to their origins.
-
-@item @samp{:narrow}
-An integer to limit the width of the headline column in the Org
-table.  If you write it like @samp{50!}, then the headline is also
-shortened in export.
-
-@item @samp{:indent}
-Indent each headline field according to its level.
-
-@item @samp{:hidefiles}
-Hide the file column when multiple files are used to produce the
-table.
-
-@item @samp{:tcolumns}
-Number of columns to be used for times.  If this is smaller than
-@samp{:maxlevel}, lower levels are lumped into one column.
-
-@item @samp{:level}
-Should a level number column be included?
-
-@item @samp{:sort}
-A cons cell containing the column to sort and a sorting type.  E.g.,
-@samp{:sort (1 . ?a)} sorts the first column alphabetically.
-
-@item @samp{:compact}
-Abbreviation for @samp{:level nil :indent t :narrow 40! :tcolumns 1}.
-All are overwritten except if there is an explicit @samp{:narrow}.
-
-@item @samp{:timestamp}
-A timestamp for the entry, when available.  Look for @samp{SCHEDULED},
-@samp{DEADLINE}, @samp{TIMESTAMP} and @samp{TIMESTAMP_IA} special properties 
(see
-@ref{Special Properties}), in this order.
-
-@item @samp{:tags}
-When this flag is non-@code{nil}, show the headline's tags.
-
-@item @samp{:properties}
-List of properties shown in the table.  Each property gets its own
-column.
-
-@item @samp{:inherit-props}
-When this flag is non-@code{nil}, the values for @samp{:properties} are
-inherited.
-
-@item @samp{:formula}
-Content of a @samp{TBLFM} keyword to be added and evaluated.  As
-a special case, @samp{:formula %} adds a column with % time.  If you do
-not specify a formula here, any existing formula below the clock
-table survives updates and is evaluated.
-
-@item @samp{:formatter}
-A function to format clock data and insert it into the buffer.
-@end table
-
-To get a clock summary of the current level 1 tree, for the current
-day, you could write:
-
-@example
-#+BEGIN: clocktable :maxlevel 2 :block today :scope tree1 :link t
-#+END: clocktable
-@end example
-
-@noindent
-To use a specific time range you could write@footnote{Note that all parameters 
must be specified in a single
-line---the line is broken here only to fit it into the manual.}
-
-@example
-#+BEGIN: clocktable :tstart "<2006-08-10 Thu 10:00>"
-                    :tend "<2006-08-10 Thu 12:00>"
-#+END: clocktable
-@end example
-
-@noindent
-A range starting a week ago and ending right now could be written as
-
-@example
-#+BEGIN: clocktable :tstart "<-1w>" :tend "<now>"
-#+END: clocktable
-@end example
-
-@noindent
-A summary of the current subtree with % times would be
-
-@example
-#+BEGIN: clocktable :scope subtree :link t :formula %
-#+END: clocktable
-@end example
-
-@noindent
-A horizontally compact representation of everything clocked during
-last week would be
-
-@example
-#+BEGIN: clocktable :scope agenda :block lastweek :compact t
-#+END: clocktable
-@end example
-
-@node Resolving idle time
-@subsection Resolving idle time and continuous clocking
-
-
-
-@anchor{Resolving idle time (1)}
-@subsubheading Resolving idle time
-
-@cindex resolve idle time
-@cindex idle, resolve, dangling
-
-If you clock in on a work item, and then walk away from your
-computer---perhaps to take a phone call---you often need to
-``resolve'' the time you were away by either subtracting it from the
-current clock, or applying it to another one.
-
-@vindex org-clock-idle-time
-@vindex org-clock-x11idle-program-name
-By customizing the variable @code{org-clock-idle-time} to some integer,
-such as 10 or 15, Emacs can alert you when you get back to your
-computer after being idle for that many minutes@footnote{On computers using 
macOS, idleness is based on actual user
-idleness, not just Emacs' idle time.  For X11, you can install
-a utility program @samp{x11idle.c}, available in the @samp{contrib/scripts/}
-directory of the Org Git distribution, or install the xprintidle
-package and set it to the variable @code{org-clock-x11idle-program-name} if
-you are running Debian, to get the same general treatment of idleness.
-On other systems, idle time refers to Emacs idle time only.}, and ask what
-you want to do with the idle time.  There will be a question waiting
-for you when you get back, indicating how much idle time has passed
-constantly updated with the current amount, as well as a set of
-choices to correct the discrepancy:
-
-@table @asis
-@item @kbd{k}
-@kindex k
-To keep some or all of the minutes and stay clocked in, press
-@kbd{k}.  Org asks how many of the minutes to keep.  Press
-@kbd{@key{RET}} to keep them all, effectively changing nothing, or
-enter a number to keep that many minutes.
-
-@item @kbd{K}
-@kindex K
-If you use the shift key and press @kbd{K}, it keeps however
-many minutes you request and then immediately clock out of that
-task.  If you keep all of the minutes, this is the same as just
-clocking out of the current task.
-
-@item @kbd{s}
-@kindex s
-To keep none of the minutes, use @kbd{s} to subtract all the
-away time from the clock, and then check back in from the moment you
-returned.
-
-@item @kbd{S}
-@kindex S
-To keep none of the minutes and just clock out at the start of the
-away time, use the shift key and press @kbd{S}.  Remember that
-using shift always leave you clocked out, no matter which option you
-choose.
-
-@item @kbd{C}
-@kindex C
-To cancel the clock altogether, use @kbd{C}.  Note that if
-instead of canceling you subtract the away time, and the resulting
-clock amount is less than a minute, the clock is still canceled
-rather than cluttering up the log with an empty entry.
-@end table
-
-What if you subtracted those away minutes from the current clock, and
-now want to apply them to a new clock?  Simply clock in to any task
-immediately after the subtraction.  Org will notice that you have
-subtracted time ``on the books'', so to speak, and will ask if you want
-to apply those minutes to the next task you clock in on.
-
-There is one other instance when this clock resolution magic occurs.
-Say you were clocked in and hacking away, and suddenly your cat chased
-a mouse who scared a hamster that crashed into your UPS's power
-button!  You suddenly lose all your buffers, but thanks to auto-save
-you still have your recent Org mode changes, including your last clock
-in.
-
-If you restart Emacs and clock into any task, Org will notice that you
-have a dangling clock which was never clocked out from your last
-session.  Using that clock's starting time as the beginning of the
-unaccounted-for period, Org will ask how you want to resolve that
-time.  The logic and behavior is identical to dealing with away time
-due to idleness; it is just happening due to a recovery event rather
-than a set amount of idle time.
-
-You can also check all the files visited by your Org agenda for
-dangling clocks at any time using @kbd{M-x org-resolve-clocks @key{RET}} (or 
@kbd{C-c C-x C-z}).
-
-@anchor{Continuous clocking}
-@subsubheading Continuous clocking
-
-@cindex continuous clocking
-
-@vindex org-clock-continuously
-You may want to start clocking from the time when you clocked out the
-previous task.  To enable this systematically, set
-@code{org-clock-continuously} to non-@code{nil}.  Each time you clock in, Org
-retrieves the clock-out time of the last clocked entry for this
-session, and start the new clock from there.
-
-If you only want this from time to time, use three universal prefix
-arguments with @code{org-clock-in} and two @kbd{C-u C-u} with
-@code{org-clock-in-last}.
-
-@anchor{Clocking out automatically after some idle time}
-@subsubheading Clocking out automatically after some idle time
-
-@cindex auto clocking out after idle time
-
-@vindex org-clock-auto-clockout-timer
-When you often forget to clock out before being idle and you don't
-want to manually set the clocking time to take into account, you can
-set @code{org-clock-auto-clockout-timer} to a number of seconds and add
-@samp{(org-clock-auto-clockout-insinuate)} to your @samp{.emacs} file.
-
-When the clock is running and Emacs is idle for more than this number
-of seconds, the clock will be clocked out automatically.
-
-Use @samp{M-x org-clock-toggle-auto-clockout RET} to temporarily turn this
-on or off.
-
-@node Effort Estimates
-@section Effort Estimates
-
-@cindex effort estimates
-@cindex @samp{EFFORT}, property
-@vindex org-effort-property
-
-If you want to plan your work in a very detailed way, or if you need
-to produce offers with quotations of the estimated work effort, you
-may want to assign effort estimates to entries.  If you are also
-clocking your work, you may later want to compare the planned effort
-with the actual working time, a great way to improve planning
-estimates.
-
-Effort estimates are stored in a special property @samp{EFFORT}.  Multiple
-formats are supported, such as @samp{3:12}, @samp{1:23:45}, or 
@samp{1d3h5min}; see
-the file @samp{org-duration.el} for more detailed information about the
-format.
-
-You can set the effort for an entry with the following commands:
-
-@table @asis
-@item @kbd{C-c C-x e}  (@code{org-set-effort})
-@kindex C-c C-x e
-@findex org-set-effort
-Set the effort estimate for the current entry.  With a prefix
-argument, set it to the next allowed value---see below.  This
-command is also accessible from the agenda with the @kbd{e}
-key.
-
-@item @kbd{C-c C-x C-e} (@code{org-clock-modify-effort-estimate})
-@kindex C-c C-x C-e
-@findex org-clock-modify-effort-estimate
-Modify the effort estimate of the item currently being clocked.
-@end table
-
-Clearly the best way to work with effort estimates is through column
-view (see @ref{Column View}).  You should start by setting up discrete
-values for effort estimates, and a @samp{COLUMNS} format that displays
-these values together with clock sums---if you want to clock your
-time.  For a specific buffer you can use:
-
-@example
-#+PROPERTY: Effort_ALL 0 0:10 0:30 1:00 2:00 3:00 4:00 5:00 6:00 7:00
-#+COLUMNS: %40ITEM(Task) %17Effort(Estimated Effort)@{:@} %CLOCKSUM
-@end example
-
-@noindent
-@vindex org-global-properties
-@vindex org-columns-default-format
-or, even better, you can set up these values globally by customizing
-the variables @code{org-global-properties} and
-@code{org-columns-default-format}.  In particular if you want to use this
-setup also in the agenda, a global setup may be advised.
-
-The way to assign estimates to individual items is then to switch to
-column mode, and to use @kbd{S-@key{RIGHT}} and @kbd{S-@key{LEFT}} to
-change the value.  The values you enter are immediately summed up in
-the hierarchy.  In the column next to it, any clocked time is
-displayed.
-
-@vindex org-agenda-columns-add-appointments-to-effort-sum
-If you switch to column view in the daily/weekly agenda, the effort
-column summarizes the estimated work effort for each day@footnote{Please note 
the pitfalls of summing hierarchical data in
-a flat list (see @ref{Agenda Column View}).}, and
-you can use this to find space in your schedule.  To get an overview
-of the entire part of the day that is committed, you can set the
-option @code{org-agenda-columns-add-appointments-to-effort-sum}.  The
-appointments on a day that take place over a specified time interval
-are then also added to the load estimate of the day.
-
-Effort estimates can be used in secondary agenda filtering that is
-triggered with the @kbd{/} key in the agenda (see @ref{Agenda Commands}).  If 
you have these estimates defined consistently,
-two or three key presses narrow down the list to stuff that fits into
-an available time slot.
-
-@node Timers
-@section Taking Notes with a Relative Timer
-
-@cindex relative timer
-@cindex countdown timer
-
-Org provides two types of timers.  There is a relative timer that
-counts up, which can be useful when taking notes during, for example,
-a meeting or a video viewing.  There is also a countdown timer.
-
-The relative and countdown are started with separate commands.
-
-@table @asis
-@item @kbd{C-c C-x 0} (@code{org-timer-start})
-@kindex C-c C-x 0
-@findex org-timer-start
-Start or reset the relative timer.  By default, the timer is set
-to 0.  When called with a @kbd{C-u} prefix, prompt the user for
-a starting offset.  If there is a timer string at point, this is
-taken as the default, providing a convenient way to restart taking
-notes after a break in the process.  When called with a double
-prefix argument @kbd{C-u C-u}, change all timer strings in the
-active region by a certain amount.  This can be used to fix timer
-strings if the timer was not started at exactly the right moment.
-
-@item @kbd{C-c C-x ;} (@code{org-timer-set-timer})
-@kindex C-c C-x ;
-@findex org-timer-set-timer
-@vindex org-timer-default-timer
-Start a countdown timer.  The user is prompted for a duration.
-@code{org-timer-default-timer} sets the default countdown value.  Giving
-a numeric prefix argument overrides this default value.  This
-command is available as @kbd{;} in agenda buffers.
-@end table
-
-Once started, relative and countdown timers are controlled with the
-same commands.
-
-@table @asis
-@item @kbd{C-c C-x .} (@code{org-timer})
-@kindex C-c C-x .
-@findex org-timer
-Insert a relative time into the buffer.  The first time you use
-this, the timer starts.  Using a prefix argument restarts it.
-
-@item @kbd{C-c C-x -} (@code{org-timer-item})
-@kindex C-c C-x -
-@findex org-timer-item
-Insert a description list item with the current relative time.  With
-a prefix argument, first reset the timer to 0.
-
-@item @kbd{M-@key{RET}} (@code{org-insert-heading})
-@kindex M-RET
-@findex org-insert-heading
-Once the timer list is started, you can also use @kbd{M-@key{RET}} to
-insert new timer items.
-
-@item @kbd{C-c C-x ,} (@code{org-timer-pause-or-continue})
-@kindex C-c C-x ,
-@findex org-timer-pause-or-continue
-Pause the timer, or continue it if it is already paused.
-
-@item @kbd{C-c C-x _} (@code{org-timer-stop})
-@kindex C-c C-x _
-@findex org-timer-stop
-Stop the timer.  After this, you can only start a new timer, not
-continue the old one.  This command also removes the timer from the
-mode line.
-@end table
-
-@node Refiling and Archiving
-@chapter Refiling and Archiving
-
-@cindex refiling notes
-@cindex copying notes
-@cindex archiving
-
-Once information is in the system, it may need to be moved around.
-Org provides Refile, Copy and Archive commands for this.  Refile and
-Copy helps with moving and copying outlines.  Archiving helps to keep
-the system compact and fast.
-
-@menu
-* Refile and Copy::              Moving/copying a tree from one place to 
another.
-* Archiving::                    What to do with finished products.
-@end menu
-
-@node Refile and Copy
-@section Refile and Copy
-
-@cindex refiling notes
-@cindex copying notes
-
-When reviewing the captured data, you may want to refile or to copy
-some of the entries into a different list, for example into a project.
-Cutting, finding the right location, and then pasting the note is
-cumbersome.  To simplify this process, you can use the following
-special command:
-
-@table @asis
-@item @kbd{C-c C-w} (@code{org-refile})
-@kindex C-c C-w
-@findex org-refile
-@vindex org-reverse-note-order
-@vindex org-refile-targets
-@vindex org-refile-use-outline-path
-@vindex org-outline-path-complete-in-steps
-@vindex org-refile-allow-creating-parent-nodes
-@vindex org-log-refile
-Refile the entry or region at point.  This command offers possible
-locations for refiling the entry and lets you select one with
-completion.  The item (or all items in the region) is filed below
-the target heading as a subitem.  Depending on
-@code{org-reverse-note-order}, it is either the first or last subitem.
-
-By default, all level 1 headlines in the current buffer are
-considered to be targets, but you can have more complex definitions
-across a number of files.  See the variable @code{org-refile-targets} for
-details.  If you would like to select a location via
-a file-path-like completion along the outline path, see the
-variables @code{org-refile-use-outline-path} and
-@code{org-outline-path-complete-in-steps}.  If you would like to be able
-to create new nodes as new parents for refiling on the fly, check
-the variable @code{org-refile-allow-creating-parent-nodes}.  When the
-variable @code{org-log-refile}@footnote{Note the corresponding @samp{STARTUP} 
options @samp{logrefile},
-@samp{lognoterefile}, and @samp{nologrefile}.} is set, a timestamp or a note is
-recorded whenever an entry is refiled.
-
-@item @kbd{C-u C-c C-w}
-@kindex C-u C-c C-w
-Use the refile interface to jump to a heading.
-
-@item @kbd{C-u C-u C-c C-w} (@code{org-refile-goto-last-stored})
-@kindex C-u C-u C-c C-w
-@findex org-refile-goto-last-stored
-Jump to the location where @code{org-refile} last moved a tree to.
-
-@item @kbd{C-2 C-c C-w}
-@kindex C-2 C-c C-w
-Refile as the child of the item currently being clocked.
-
-@item @kbd{C-3 C-c C-w}
-@kindex C-3 C-c C-w
-@vindex org-refile-keep
-Refile and keep the entry in place.  Also see @code{org-refile-keep} to
-make this the default behavior, and beware that this may result in
-duplicated @samp{ID} properties.
-
-@item @kbd{C-0 C-c C-w} or @kbd{C-u C-u C-u C-c C-w} 
(@code{org-refile-cache-clear})
-@kindex C-u C-u C-u C-c C-w
-@kindex C-0 C-c C-w
-@findex org-refile-cache-clear
-@vindex org-refile-use-cache
-Clear the target cache.  Caching of refile targets can be turned on
-by setting @code{org-refile-use-cache}.  To make the command see new
-possible targets, you have to clear the cache with this command.
-
-@item @kbd{C-c M-w} (@code{org-refile-copy})
-@kindex C-c M-w
-@findex org-refile-copy
-Copying works like refiling, except that the original note is not
-deleted.
-@end table
-
-@node Archiving
-@section Archiving
-
-@cindex archiving
-
-When a project represented by a (sub)tree is finished, you may want to
-move the tree out of the way and to stop it from contributing to the
-agenda.  Archiving is important to keep your working files compact and
-global searches like the construction of agenda views fast.
-
-@table @asis
-@item @kbd{C-c C-x C-a} (@code{org-archive-subtree-default})
-@kindex C-c C-x C-a
-@findex org-archive-subtree-default
-@vindex org-archive-default-command
-Archive the current entry using the command specified in the
-variable @code{org-archive-default-command}.
-@end table
-
-@menu
-* Moving subtrees::              Moving a tree to an archive file.
-* Internal archiving::           Switch off a tree but keep it in the file.
-@end menu
-
-@node Moving subtrees
-@subsection Moving a tree to an archive file
-
-@cindex external archiving
-
-The most common archiving action is to move a project tree to another
-file, the archive file.
-
-@table @asis
-@item @kbd{C-c C-x C-s} or short @kbd{C-c $} (@code{org-archive-subtree})
-@kindex C-c C-x C-s
-@kindex C-c $
-@findex org-archive-subtree
-@vindex org-archive-location
-Archive the subtree starting at point position to the location given
-by @code{org-archive-location}.
-
-@item @kbd{C-u C-c C-x C-s}
-@kindex C-u C-c C-x C-s
-Check if any direct children of the current headline could be moved
-to the archive.  To do this, check each subtree for open TODO
-entries.  If none is found, the command offers to move it to the
-archive location.  If point is @emph{not} on a headline when this command
-is invoked, check level 1 trees.
-
-@item @kbd{C-u C-u C-c C-x C-s}
-@kindex C-u C-u C-c C-x C-s
-As above, but check subtree for timestamps instead of TODO entries.
-The command offers to archive the subtree if it @emph{does} contain
-a timestamp, and that timestamp is in the past.
-@end table
-
-@cindex archive locations
-The default archive location is a file in the same directory as the
-current file, with the name derived by appending @samp{_archive} to the
-current file name.  You can also choose what heading to file archived
-items under, with the possibility to add them to a datetree in a file.
-For information and examples on how to specify the file and the
-heading, see the documentation string of the variable
-@code{org-archive-location}.
-
-There is also an in-buffer option for setting this variable, for
-example:
-
-@cindex @samp{ARCHIVE}, keyword
-@example
-#+ARCHIVE: %s_done::
-@end example
-
-
-@cindex ARCHIVE, property
-If you would like to have a special archive location for a single
-entry or a (sub)tree, give the entry an @samp{ARCHIVE} property with the
-location as the value (see @ref{Properties and Columns}).
-
-@vindex org-archive-save-context-info
-When a subtree is moved, it receives a number of special properties
-that record context information like the file from where the entry
-came, its outline path the archiving time etc.  Configure the variable
-@code{org-archive-save-context-info} to adjust the amount of information
-added.
-
-@vindex org-archive-subtree-save-file-p
-When @code{org-archive-subtree-save-file-p} is non-@code{nil}, save the target
-archive buffer.
-
-@node Internal archiving
-@subsection Internal archiving
-
-@cindex @samp{ARCHIVE}, tag
-If you want to just switch off---for agenda views---certain subtrees
-without moving them to a different file, you can use the @samp{ARCHIVE}
-tag.
-
-A headline that is marked with the @samp{ARCHIVE} tag (see @ref{Tags}) stays at
-its location in the outline tree, but behaves in the following way:
-
-@itemize
-@item
-@vindex org-cycle-open-archived-trees
-It does not open when you attempt to do so with a visibility cycling
-command (see @ref{Visibility Cycling}).  You can force cycling archived
-subtrees with @kbd{C-@key{TAB}}, or by setting the option
-@code{org-cycle-open-archived-trees}.  Also normal outline commands, like
-@code{outline-show-all}, open archived subtrees.
-
-@item
-@vindex org-sparse-tree-open-archived-trees
-During sparse tree construction (see @ref{Sparse Trees}), matches in
-archived subtrees are not exposed, unless you configure the option
-@code{org-sparse-tree-open-archived-trees}.
-
-@item
-@vindex org-agenda-skip-archived-trees
-During agenda view construction (see @ref{Agenda Views}), the content of
-archived trees is ignored unless you configure the option
-@code{org-agenda-skip-archived-trees}, in which case these trees are
-always included.  In the agenda you can press @kbd{v a} to get
-archives temporarily included.
-
-@item
-@vindex org-export-with-archived-trees
-Archived trees are not exported (see @ref{Exporting}), only the headline
-is.  Configure the details using the variable
-@code{org-export-with-archived-trees}.
-
-@item
-@vindex org-columns-skip-archived-trees
-Archived trees are excluded from column view unless the variable
-@code{org-columns-skip-archived-trees} is configured to @code{nil}.
-@end itemize
-
-The following commands help manage the @samp{ARCHIVE} tag:
-
-@table @asis
-@item @kbd{C-c C-x a} (@code{org-toggle-archive-tag})
-@kindex C-c C-x a
-@findex org-toggle-archive-tag
-Toggle the archive tag for the current headline.  When the tag is
-set, the headline changes to a shadowed face, and the subtree below
-it is hidden.
-
-@item @kbd{C-u C-c C-x a}
-@kindex C-u C-c C-x a
-Check if any direct children of the current headline should be
-archived.  To do this, check each subtree for open TODO entries.  If
-none is found, the command offers to set the @samp{ARCHIVE} tag for the
-child.  If point is @emph{not} on a headline when this command is
-invoked, check the level 1 trees.
-
-@item @kbd{C-c C-@key{TAB}} (@code{org-force-cycle-archived})
-@kindex C-TAB
-Cycle a tree even if it is tagged with @samp{ARCHIVE}.
-
-@item @kbd{C-c C-x A} (@code{org-archive-to-archive-sibling})
-@kindex C-c C-x A
-@findex org-archive-to-archive-sibling
-Move the current entry to the @emph{Archive Sibling}.  This is a sibling
-of the entry with the heading @samp{Archive} and the archive tag.  The
-entry becomes a child of that sibling and in this way retains a lot
-of its original context, including inherited tags and approximate
-position in the outline.
-@end table
-
-@node Capture and Attachments
-@chapter Capture and Attachments
-
-@cindex capture
-@cindex attachments
-@cindex RSS feeds
-@cindex Atom feeds
-@cindex protocols, for external access
-
-An important part of any organization system is the ability to quickly
-capture new ideas and tasks, and to associate reference material with
-them.  Org does this using a process called @emph{capture}.  It also can
-store files related to a task (@emph{attachments}) in a special directory.
-Finally, it can parse RSS feeds for information.  To learn how to let
-external programs (for example a web browser) trigger Org to capture
-material, see @ref{Protocols}.
-
-@menu
-* Capture::                      Capturing new stuff.
-* Attachments::                  Attach files to outlines.
-* RSS Feeds::                    Getting input from RSS feeds.
-@end menu
-
-@node Capture
-@section Capture
-
-@cindex capture
-
-Capture lets you quickly store notes with little interruption of your
-work flow.  Org's method for capturing new items is heavily inspired
-by John Wiegley's excellent Remember package.
-
-@menu
-* Setting up capture::           Where notes will be stored.
-* Using capture::                Commands to invoke and terminate capture.
-* Capture templates::            Define the outline of different note types.
-@end menu
-
-@node Setting up capture
-@subsection Setting up capture
-
-The following customization sets a default target file for notes.
-
-@vindex org-default-notes-file
-@lisp
-(setq org-default-notes-file (concat org-directory "/notes.org"))
-@end lisp
-
-You may also define a global key for capturing new material (see
-@ref{Activation}).
-
-@node Using capture
-@subsection Using capture
-
-@table @asis
-@item @kbd{M-x org-capture} (@code{org-capture})
-@findex org-capture
-@cindex date tree
-Display the capture templates menu.  If you have templates defined
-(see @ref{Capture templates}), it offers these templates for selection or
-use a new Org outline node as the default template.  It inserts the
-template into the target file and switch to an indirect buffer
-narrowed to this new node.  You may then insert the information you
-want.
-
-@item @kbd{C-c C-c} (@code{org-capture-finalize})
-@kindex C-c C-c @r{(Capture buffer)}
-@findex org-capture-finalize
-Once you have finished entering information into the capture buffer,
-@kbd{C-c C-c} returns you to the window configuration before
-the capture process, so that you can resume your work without
-further distraction.  When called with a prefix argument, finalize
-and then jump to the captured item.
-
-@item @kbd{C-c C-w} (@code{org-capture-refile})
-@kindex C-c C-w @r{(Capture buffer)}
-@findex org-capture-refile
-Finalize the capture process by refiling the note to a different
-place (see @ref{Refile and Copy}).  Please realize that this is a normal
-refiling command that will be executed---so point position at the
-moment you run this command is important.  If you have inserted
-a tree with a parent and children, first move point back to the
-parent.  Any prefix argument given to this command is passed on to
-the @code{org-refile} command.
-
-@item @kbd{C-c C-k} (@code{org-capture-kill})
-@kindex C-c C-k @r{(Capture buffer)}
-@findex org-capture-kill
-Abort the capture process and return to the previous state.
-@end table
-
-@kindex k c @r{(Agenda)}
-You can also call @code{org-capture} in a special way from the agenda,
-using the @kbd{k c} key combination.  With this access, any
-timestamps inserted by the selected capture template defaults to the
-date at point in the agenda, rather than to the current date.
-
-To find the locations of the last stored capture, use @code{org-capture}
-with prefix commands:
-
-@table @asis
-@item @kbd{C-u M-x org-capture}
-Visit the target location of a capture template.  You get to select
-the template in the usual way.
-
-@item @kbd{C-u C-u M-x org-capture}
-Visit the last stored capture item in its buffer.
-@end table
-
-@vindex org-capture-bookmark
-@vindex org-capture-last-stored
-You can also jump to the bookmark @code{org-capture-last-stored}, which is
-automatically created unless you set @code{org-capture-bookmark} to @code{nil}.
-
-To insert the capture at point in an Org buffer, call @code{org-capture}
-with a @kbd{C-0} prefix argument.
-
-@node Capture templates
-@subsection Capture templates
-
-@cindex templates, for Capture
-
-You can use templates for different types of capture items, and for
-different target locations.  The easiest way to create such templates
-is through the customize interface.
-
-@table @asis
-@item @kbd{C}
-@kindex C @r{(Capture menu}
-@vindex org-capture-templates
-Customize the variable @code{org-capture-templates}.
-@end table
-
-Before we give the formal description of template definitions, let's
-look at an example.  Say you would like to use one template to create
-general TODO entries, and you want to put these entries under the
-heading @samp{Tasks} in your file @samp{~/org/gtd.org}.  Also, a date tree in
-the file @samp{journal.org} should capture journal entries.  A possible
-configuration would look like:
-
-@lisp
-(setq org-capture-templates
-      '(("t" "Todo" entry (file+headline "~/org/gtd.org" "Tasks")
-         "* TODO %?\n  %i\n  %a")
-        ("j" "Journal" entry (file+datetree "~/org/journal.org")
-         "* %?\nEntered on %U\n  %i\n  %a")))
-@end lisp
-
-If you then press @kbd{t} from the capture menu, Org will prepare
-the template for you like this:
-
-@example
-* TODO
-  [[file:LINK TO WHERE YOU INITIATED CAPTURE]]
-@end example
-
-@noindent
-During expansion of the template, @samp{%a} has been replaced by a link to
-the location from where you called the capture command.  This can be
-extremely useful for deriving tasks from emails, for example.  You
-fill in the task definition, press @kbd{C-c C-c} and Org returns
-you to the same place where you started the capture process.
-
-To define special keys to capture to a particular template without
-going through the interactive template selection, you can create your
-key binding like this:
-
-@lisp
-(define-key global-map (kbd "C-c x")
-  (lambda () (interactive) (org-capture nil "x")))
-@end lisp
-
-@menu
-* Template elements::            What is needed for a complete template entry.
-* Template expansion::           Filling in information about time and context.
-* Templates in contexts::        Only show a template in a specific context.
-@end menu
-
-@node Template elements
-@subsubsection Template elements
-
-Now lets look at the elements of a template definition.  Each entry in
-@code{org-capture-templates} is a list with the following items:
-
-@table @asis
-@item keys
-The keys that selects the template, as a string, characters only,
-for example @samp{"a"}, for a template to be selected with a single key,
-or @samp{"bt"} for selection with two keys.  When using several keys,
-keys using the same prefix key must be sequential in the list and
-preceded by a 2-element entry explaining the prefix key, for
-example:
-
-@lisp
-("b" "Templates for marking stuff to buy")
-@end lisp
-
-If you do not define a template for the @kbd{C} key, this key
-opens the Customize buffer for this complex variable.
-
-@item description
-A short string describing the template, shown during selection.
-
-@item type
-The type of entry, a symbol.  Valid values are:
-
-@table @asis
-@item @code{entry}
-An Org mode node, with a headline.  Will be filed as the child of
-the target entry or as a top-level entry.  The target file should
-be an Org file.
-
-@item @code{item}
-A plain list item, placed in the first plain list at the target
-location.  Again the target file should be an Org file.
-
-@item @code{checkitem}
-A checkbox item.  This only differs from the plain list item by
-the default template.
-
-@item @code{table-line}
-A new line in the first table at the target location.  Where
-exactly the line will be inserted depends on the properties
-@code{:prepend} and @code{:table-line-pos} (see below).
-
-@item @code{plain}
-Text to be inserted as it is.
-@end table
-
-@item target
-@vindex org-default-notes-file
-@vindex org-directory
-Specification of where the captured item should be placed.  In Org
-files, targets usually define a node.  Entries will become children
-of this node.  Other types will be added to the table or list in the
-body of this node.  Most target specifications contain a file name.
-If that file name is the empty string, it defaults to
-@code{org-default-notes-file}.  A file can also be given as a variable or
-as a function called with no argument.  When an absolute path is not
-specified for a target, it is taken as relative to @code{org-directory}.
-
-Valid values are:
-
-@table @asis
-@item @samp{(file "path/to/file")}
-Text will be placed at the beginning or end of that file.
-
-@item @samp{(id "id of existing org entry")}
-Filing as child of this entry, or in the body of the entry.
-
-@item @samp{(file+headline "filename" "node headline")}
-Fast configuration if the target heading is unique in the file.
-
-@item @samp{(file+olp "filename" "Level 1 heading" "Level 2" ...)}
-For non-unique headings, the full path is safer.
-
-@item @samp{(file+regexp "filename" "regexp to find location")}
-Use a regular expression to position point.
-
-@item @samp{(file+olp+datetree "filename" [ "Level 1 heading" ...])}
-This target@footnote{Org used to offer four different targets for date/week 
tree
-capture.  Now, Org automatically translates these to use
-@code{file+olp+datetree}, applying the @code{:time-prompt} and 
@code{:tree-type}
-properties.  Please rewrite your date/week-tree targets using
-@code{file+olp+datetree} since the older targets are now deprecated.} creates 
a heading in a date tree@footnote{A date tree is an outline structure with 
years on the highest
-level, months or ISO weeks as sublevels and then dates on the lowest
-level.  Tags are allowed in the tree structure.} for
-today's date.  If the optional outline path is given, the tree
-will be built under the node it is pointing to, instead of at top
-level.  Check out the @code{:time-prompt} and @code{:tree-type} properties
-below for additional options.
-
-@item @samp{(file+function "filename" function-finding-location)}
-A function to find the right location in the file.
-
-@item @samp{(clock)}
-File to the entry that is currently being clocked.
-
-@item @samp{(function function-finding-location)}
-Most general way: write your own function which both visits the
-file and moves point to the right location.
-@end table
-
-@item template
-The template for creating the capture item.  If you leave this
-empty, an appropriate default template will be used.  Otherwise this
-is a string with escape codes, which will be replaced depending on
-time and context of the capture call.  You may also get this
-template string from a file@footnote{When the file name is not absolute, Org 
assumes it is relative
-to @code{org-directory}.}, or dynamically, from a function
-using either syntax:
-
-@example
-(file "/path/to/template-file")
-(function FUNCTION-RETURNING-THE-TEMPLATE)
-@end example
-
-@item properties
-The rest of the entry is a property list of additional options.
-Recognized properties are:
-
-@table @asis
-@item @code{:prepend}
-Normally new captured information will be appended at the target
-location (last child, last table line, last list item, @dots{}).
-Setting this property changes that.
-
-@item @code{:immediate-finish}
-When set, do not offer to edit the information, just file it away
-immediately.  This makes sense if the template only needs
-information that can be added automatically.
-
-@item @code{:jump-to-captured}
-When set, jump to the captured entry when finished.
-
-@item @code{:empty-lines}
-Set this to the number of lines to insert before and after the new
-item.  Default 0, and the only other common value is 1.
-
-@item @code{:empty-lines-after}
-Set this to the number of lines that should be inserted after the
-new item.  Overrides @code{:empty-lines} for the number of lines
-inserted after.
-
-@item @code{:empty-lines-before}
-Set this to the number of lines that should be inserted before the
-new item.  Overrides @code{:empty-lines} for the number lines inserted
-before.
-
-@item @code{:clock-in}
-Start the clock in this item.
-
-@item @code{:clock-keep}
-Keep the clock running when filing the captured entry.
-
-@item @code{:clock-resume}
-If starting the capture interrupted a clock, restart that clock
-when finished with the capture.  Note that @code{:clock-keep} has
-precedence over @code{:clock-resume}.  When setting both to non-@code{nil},
-the current clock will run and the previous one will not be
-resumed.
-
-@item @code{:time-prompt}
-Prompt for a date/time to be used for date/week trees and when
-filling the template.  Without this property, capture uses the
-current date and time.  Even if this property has not been set,
-you can force the same behavior by calling @code{org-capture} with
-a @kbd{C-1} prefix argument.
-
-@item @code{:tree-type}
-Use @code{week} to make a week tree instead of the month-day tree,
-i.e., place the headings for each day under a heading with the
-current ISO week.  Use @code{month} to group entries by month
-only.  Default is to group entries by day.
-
-@item @code{:unnarrowed}
-Do not narrow the target buffer, simply show the full buffer.
-Default is to narrow it so that you only see the new material.
-
-@item @code{:table-line-pos}
-Specification of the location in the table where the new line
-should be inserted.  It should be a string like @samp{II-3} meaning
-that the new line should become the third line before the second
-horizontal separator line.
-
-@item @code{:kill-buffer}
-If the target file was not yet visited when capture was invoked,
-kill the buffer again after capture is completed.
-
-@item @code{:no-save}
-Do not save the target file after finishing the capture.
-@end table
-@end table
-
-@node Template expansion
-@subsubsection Template expansion
-
-In the template itself, special ``%-escapes''@footnote{If you need one of 
these sequences literally, escape the @samp{%}
-with a backslash.} allow dynamic
-insertion of content.  The templates are expanded in the order given
-here:
-
-@table @asis
-@item @samp{%[FILE]}
-Insert the contents of the file given by @var{FILE}.
-
-@item @samp{%(EXP)}
-Evaluate Elisp expression @var{EXP} and replace it with the
-result.  The @var{EXP} form must return a string.  Only
-placeholders pre-existing within the template, or introduced with
-@samp{%[file]}, are expanded this way.  Since this happens after
-expanding non-interactive ``%-escapes'', those can be used to fill the
-expression.
-
-@item @samp{%<FORMAT>}
-The result of format-time-string on the @var{FORMAT}
-specification.
-
-@item @samp{%t}
-Timestamp, date only.
-
-@item @samp{%T}
-Timestamp, with date and time.
-
-@item @samp{%u}, @samp{%U}
-Like @samp{%t}, @samp{%T} above, but inactive timestamps.
-
-@item @samp{%i}
-Initial content, the region when capture is called while the region
-is active.  If there is text before @samp{%i} on the same line, such as
-indentation, and @samp{%i} is not inside a @samp{%(exp)} form, that prefix is
-added before every line in the inserted text.
-
-@item @samp{%a}
-Annotation, normally the link created with @code{org-store-link}.
-
-@item @samp{%A}
-Like @samp{%a}, but prompt for the description part.
-
-@item @samp{%l}
-Like @samp{%a}, but only insert the literal link.
-
-@item @samp{%c}
-Current kill ring head.
-
-@item @samp{%x}
-Content of the X clipboard.
-
-@item @samp{%k}
-Title of the currently clocked task.
-
-@item @samp{%K}
-Link to the currently clocked task.
-
-@item @samp{%n}
-User name (taken from @code{user-full-name}).
-
-@item @samp{%f}
-File visited by current buffer when org-capture was called.
-
-@item @samp{%F}
-Full path of the file or directory visited by current buffer.
-
-@item @samp{%:keyword}
-Specific information for certain link types, see below.
-
-@item @samp{%^g}
-Prompt for tags, with completion on tags in target file.
-
-@item @samp{%^G}
-Prompt for tags, with completion all tags in all agenda files.
-
-@item @samp{%^t}
-Like @samp{%t}, but prompt for date.  Similarly @samp{%^T}, @samp{%^u}, 
@samp{%^U}.  You
-may define a prompt like @samp{%^@{Birthday@}t}.
-
-@item @samp{%^C}
-Interactive selection of which kill or clip to use.
-
-@item @samp{%^L}
-Like @samp{%^C}, but insert as link.
-
-@item @samp{%^@{PROP@}p}
-Prompt the user for a value for property @var{PROP}.
-
-@item @samp{%^@{PROMPT@}}
-Prompt the user for a string and replace this sequence with it.  You
-may specify a default value and a completion table with
-@samp{%^@{prompt|default|completion2|completion3...@}}.  The arrow keys
-access a prompt-specific history.
-
-@item @samp{%\N}
-Insert the text entered at the @var{N}th @samp{%^@{PROMPT@}}, where
-@var{N} is a number, starting from 1.
-
-@item @samp{%?}
-After completing the template, position point here.
-@end table
-
-@vindex org-store-link-props
-For specific link types, the following keywords are defined@footnote{If you 
define your own link types (see @ref{Adding Hyperlink Types}), any property you 
store with @code{org-store-link-props} can be
-accessed in capture templates in a similar way.}:
-
-@vindex org-link-from-user-regexp
-@multitable {aaaaaaaaaaaa} 
{aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa}
-@headitem Link type
-@tab Available keywords
-@item bbdb
-@tab @samp{%:name}, @samp{%:company}
-@item irc
-@tab @samp{%:server}, @samp{%:port}, @samp{%:nick}
-@item mh, rmail
-@tab @samp{%:type}, @samp{%:subject}, @samp{%:message-id}
-@item
-@tab @samp{%:from}, @samp{%:fromname}, @samp{%:fromaddress}
-@item
-@tab @samp{%:to}, @samp{%:toname}, @samp{%:toaddress}
-@item
-@tab @samp{%:date} (message date header field)
-@item
-@tab @samp{%:date-timestamp} (date as active timestamp)
-@item
-@tab @samp{%:date-timestamp-inactive} (date as inactive timestamp)
-@item
-@tab @samp{%:fromto} (either ``to NAME'' or ``from NAME'')@footnote{This is 
always the other, not the user.  See the variable
-@code{org-link-from-user-regexp}.}
-@item gnus
-@tab @samp{%:group}, for messages also all email fields
-@item w3, w3m
-@tab @samp{%:url}
-@item info
-@tab @samp{%:file}, @samp{%:node}
-@item calendar
-@tab @samp{%:date}
-@item org-protocol
-@tab @samp{%:link}, @samp{%:description}, @samp{%:annotation}
-@end multitable
-
-@node Templates in contexts
-@subsubsection Templates in contexts
-
-@vindex org-capture-templates-contexts
-To control whether a capture template should be accessible from
-a specific context, you can customize
-@code{org-capture-templates-contexts}.  Let's say, for example, that you
-have a capture template ``p'' for storing Gnus emails containing
-patches.  Then you would configure this option like this:
-
-@lisp
-(setq org-capture-templates-contexts
-      '(("p" (in-mode . "message-mode"))))
-@end lisp
-
-You can also tell that the command key @kbd{p} should refer to
-another template.  In that case, add this command key like this:
-
-@lisp
-(setq org-capture-templates-contexts
-      '(("p" "q" (in-mode . "message-mode"))))
-@end lisp
-
-See the docstring of the variable for more information.
-
-@node Attachments
-@section Attachments
-
-@cindex attachments
-
-It is often useful to associate reference material with an outline
-node.  Small chunks of plain text can simply be stored in the subtree
-of a project.  Hyperlinks (see @ref{Hyperlinks}) can establish associations
-with files that live elsewhere on a local, or even remote, computer,
-like emails or source code files belonging to a project.
-
-Another method is @emph{attachments}, which are files located in a
-directory belonging to an outline node.  Org uses directories either
-named by a unique ID of each entry, or by a @samp{DIR} property.
-
-@menu
-* Attachment defaults and dispatcher:: How to access attachment commands
-* Attachment options::           Configuring the attachment system
-* Attachment links::             Hyperlink access to attachments
-* Automatic version-control with Git:: Everything safely stored away
-* Attach from Dired::            Using dired to select an attachment
-@end menu
-
-@node Attachment defaults and dispatcher
-@subsection Attachment defaults and dispatcher
-
-By default, Org attach uses ID properties when adding attachments to
-outline nodes.  This makes working with attachments fully automated.
-There is no decision needed for folder-name or location.  ID-based
-directories are by default located in the @samp{data/} directory, which
-lives in the same directory where your Org file lives@footnote{If you move 
entries or Org files from one directory to
-another, you may want to configure @code{org-attach-id-dir} to contain
-an absolute path.}.
-
-When attachments are made using @code{org-attach} a default tag @samp{ATTACH} 
is
-added to the node that gets the attachments.
-
-For more control over the setup, see @ref{Attachment options}.
-
-The following commands deal with attachments:
-
-@table @asis
-@item @kbd{C-c C-a} (@code{org-attach})
-@kindex C-c C-a
-@findex org-attach
-The dispatcher for commands related to the attachment system.  After
-these keys, a list of commands is displayed and you must press an
-additional key to select a command:
-
-@table @asis
-@item @kbd{a} (@code{org-attach-attach})
-@kindex C-c C-a a
-@findex org-attach-attach
-@vindex org-attach-method
-Select a file and move it into the task's attachment directory.
-The file is copied, moved, or linked, depending on
-@code{org-attach-method}.  Note that hard links are not supported on
-all systems.
-
-@item @kbd{c}/@kbd{m}/@kbd{l}
-@kindex C-c C-a c
-@kindex C-c C-a m
-@kindex C-c C-a l
-Attach a file using the copy/move/link method.  Note that hard
-links are not supported on all systems.
-
-@item @kbd{b} (@code{org-attach-buffer})
-@kindex C-c C-a b
-@findex org-attach-buffer
-Select a buffer and save it as a file in the task's attachment
-directory.
-
-@item @kbd{n} (@code{org-attach-new})
-@kindex C-c C-a n
-@findex org-attach-new
-Create a new attachment as an Emacs buffer.
-
-@item @kbd{z} (@code{org-attach-sync})
-@kindex C-c C-a z
-@findex org-attach-sync
-Synchronize the current task with its attachment directory, in
-case you added attachments yourself.
-
-@item @kbd{o} (@code{org-attach-open})
-@kindex C-c C-a o
-@findex org-attach-open
-@vindex org-file-apps
-Open current task's attachment.  If there is more than one, prompt
-for a file name first.  Opening follows the rules set by
-@code{org-file-apps}.  For more details, see the information on
-following hyperlinks (see @ref{Handling Links}).
-
-@item @kbd{O} (@code{org-attach-open-in-emacs})
-@kindex C-c C-a O
-@findex org-attach-open-in-emacs
-Also open the attachment, but force opening the file in Emacs.
-
-@item @kbd{f} (@code{org-attach-reveal})
-@kindex C-c C-a f
-@findex org-attach-reveal
-Open the current task's attachment directory.
-
-@item @kbd{F} (@code{org-attach-reveal-in-emacs})
-@kindex C-c C-a F
-@findex org-attach-reveal-in-emacs
-Also open the directory, but force using Dired in Emacs.
-
-@item @kbd{d} (@code{org-attach-delete-one})
-@kindex C-c C-a d
-Select and delete a single attachment.
-
-@item @kbd{D} (@code{org-attach-delete-all})
-@kindex C-c C-a D
-Delete all of a task's attachments.  A safer way is to open the
-directory in Dired and delete from there.
-
-@item @kbd{s} (@code{org-attach-set-directory})
-@kindex C-c C-a s
-@cindex @samp{DIR}, property
-Set a specific directory as the entry's attachment directory.
-This works by putting the directory path into the @samp{DIR}
-property.
-
-@item @kbd{S} (@code{org-attach-unset-directory})
-@kindex C-c C-a S
-@cindex @samp{DIR}, property
-Remove the attachment directory.  This command removes the @samp{DIR}
-property and asks the user to either move content inside that
-folder, if an @samp{ID} property is set, delete the content, or to
-leave the attachment directory as is but no longer attached to the
-outline node.
-@end table
-@end table
-
-@node Attachment options
-@subsection Attachment options
-
-There are a couple of options for attachments that are worth
-mentioning.
-
-@table @asis
-@item @code{org-attach-id-dir}
-@vindex org-attach-id-dir
-The directory where attachments are stored when @samp{ID} is used as
-method.
-
-@item @code{org-attach-dir-relative}
-@vindex org-attach-dir-relative
-When setting the @samp{DIR} property on a node using @kbd{C-c C-a s}
-(@code{org-attach-set-directory}), absolute links are entered by default.
-This option changes that to relative links.
-
-@item @code{org-attach-use-inheritance}
-@vindex org-attach-use-inheritance
-By default folders attached to an outline node are inherited from
-parents according to @code{org-use-property-inheritance}.  If one instead
-want to set inheritance specifically for Org attach that can be done
-using @code{org-attach-use-inheritance}.  Inheriting documents through
-the node hierarchy makes a lot of sense in most cases.  Especially
-when using attachment links (see @ref{Attachment links}).  The following
-example shows one use case for attachment inheritance:
-
-@example
-* Chapter A ...
-  :PROPERTIES:
-  :DIR: Chapter A/
-  :END:
-** Introduction
-Some text
-
-#+NAME: Image 1
-[[attachment:image 1.jpg]]
-@end example
-
-Without inheritance one would not be able to resolve the link to
-@samp{image 1.jpg}, since the link is inside a sub-heading to @samp{Chapter
-  A}.
-
-Inheritance works the same way for both @samp{ID} and @samp{DIR} property.  If
-both properties are defined on the same headline then @samp{DIR} takes
-precedence.  This is also true if inheritance is enabled.  If @samp{DIR}
-is inherited from a parent node in the outline, that property still
-takes precedence over an @samp{ID} property defined on the node itself.
-
-@item @code{org-attach-method}
-@vindex org-attach-method
-When attaching files using the dispatcher @kbd{C-c C-a} it
-defaults to copying files.  The behavior can be changed by
-customizing @code{org-attach-method}.  Options are Copy, Move/Rename,
-Hard link or Symbolic link.
-
-@item @code{org-attach-preferred-new-method}
-@vindex org-attach-preferred-new-method
-This customization lets you choose the default way to attach to
-nodes without existing @samp{ID} and @samp{DIR} property.  It defaults to 
@code{id}
-but can also be set to @code{dir}, @code{ask} or @code{nil}.
-
-@item @code{org-attach-archive-delete}
-@vindex org-attach-archive-delete
-Configure this to determine if attachments should be deleted or not
-when a subtree that has attachments is archived.
-
-@item @code{org-attach-auto-tag}
-@vindex org-attach-auto-tag
-When attaching files to a heading it will be assigned a tag
-according to what is set here.
-
-@item @code{org-attach-id-to-path-function-list}
-@vindex org-attach-id-to-path-function-list
-When @samp{ID} is used for attachments, the ID is parsed into a part of a
-directory-path.  See @code{org-attach-id-uuid-folder-format} for the
-default function.  Define a new one and add it as first element in
-@code{org-attach-id-to-path-function-list} if you want the folder
-structure in any other way.  All functions in this list will be
-tried when resolving existing ID's into paths, to maintain backward
-compatibility with existing folders in your system.
-
-@item @code{org-attach-store-link-p}
-@vindex org-attach-store-link-p
-Stores a link to the file that is being attached.  The link is
-stored in @code{org-stored-links} for later insertion with @kbd{C-c C-l} (see 
@ref{Handling Links}).  Depending on what option is set in
-@code{org-attach-store-link-p}, the link is stored to either the original
-location as a file link, the attachment location as an attachment
-link or to the attachment location as a file link.
-
-@item @code{org-attach-commands}
-@vindex org-attach-commands
-List of all commands used in the attach dispatcher.
-
-@item @code{org-attach-expert}
-@vindex org-attach-expert
-Do not show the splash buffer with the attach dispatcher when
-@code{org-attach-expert} is set to non-@code{nil}.
-@end table
-
-See customization group @samp{Org Attach} if you want to change the
-default settings.
-
-@node Attachment links
-@subsection Attachment links
-
-Attached files and folders can be referenced using attachment links.
-This makes it easy to refer to the material added to an outline node.
-Especially if it was attached using the unique ID of the entry!
-
-@example
-* TODO Some task
-  :PROPERTIES:
-  :ID:       95d50008-c12e-479f-a4f2-cc0238205319
-  :END:
-See attached document for more information: [[attachment:info.org]]
-@end example
-
-See @ref{External Links} for more information about these links.
-
-@node Automatic version-control with Git
-@subsection Automatic version-control with Git
-
-If the directory attached to an outline node is a Git repository, Org
-can be configured to automatically commit changes to that repository
-when it sees them.
-
-To make Org mode take care of versioning of attachments for you, add
-the following to your Emacs config:
-
-@lisp
-(require 'org-attach-git)
-@end lisp
-
-@node Attach from Dired
-@subsection Attach from Dired
-
-@cindex attach from Dired
-@findex org-attach-dired-to-subtree
-
-It is possible to attach files to a subtree from a Dired buffer.  To
-use this feature, have one window in Dired mode containing the file(s)
-to be attached and another window with point in the subtree that shall
-get the attachments.  In the Dired window, with point on a file,
-@kbd{M-x org-attach-dired-to-subtree} attaches the file to the
-subtree using the attachment method set by variable
-@code{org-attach-method}.  When files are marked in the Dired window then
-all marked files get attached.
-
-Add the following lines to the Emacs init file to have @kbd{C-c C-x a} attach 
files in Dired buffers.
-
-@lisp
-(add-hook 'dired-mode-hook
-          (lambda ()
-            (define-key dired-mode-map
-              (kbd "C-c C-x a")
-              #'org-attach-dired-to-subtree)))
-@end lisp
-
-The following code shows how to bind the previous command with
-a specific attachment method.
-
-@lisp
-(add-hook 'dired-mode-hook
-          (lambda ()
-            (define-key dired-mode-map (kbd "C-c C-x c")
-              (lambda ()
-                (interactive)
-                (let ((org-attach-method 'cp))
-                  (call-interactively #'org-attach-dired-to-subtree))))))
-@end lisp
-
-@node RSS Feeds
-@section RSS Feeds
-
-@cindex RSS feeds
-@cindex Atom feeds
-
-Org can add and change entries based on information found in RSS feeds
-and Atom feeds.  You could use this to make a task out of each new
-podcast in a podcast feed.  Or you could use a phone-based
-note-creating service on the web to import tasks into Org.  To access
-feeds, configure the variable @code{org-feed-alist}.  The docstring of this
-variable has detailed information.  With the following
-
-@lisp
-(setq org-feed-alist
-      '(("Slashdot"
-         "http://rss.slashdot.org/Slashdot/slashdot";
-         "~/txt/org/feeds.org" "Slashdot Entries")))
-@end lisp
-
-@noindent
-new items from the feed provided by @samp{rss.slashdot.org} result in new
-entries in the file @samp{~/org/feeds.org} under the heading @samp{Slashdot
-Entries}, whenever the following command is used:
-
-@table @asis
-@item @kbd{C-c C-x g} (@code{org-feed-update-all})
-@kindex C-c C-x g
-Collect items from the feeds configured in @code{org-feed-alist} and act
-upon them.
-
-@item @kbd{C-c C-x G} (@code{org-feed-goto-inbox})
-@kindex C-c C-x G
-Prompt for a feed name and go to the inbox configured for this feed.
-@end table
-
-Under the same headline, Org creates a drawer @samp{FEEDSTATUS} in which it
-stores information about the status of items in the feed, to avoid
-adding the same item several times.
-
-For more information, including how to read atom feeds, see
-@samp{org-feed.el} and the docstring of @code{org-feed-alist}.
-
-@node Agenda Views
-@chapter Agenda Views
-
-@cindex agenda views
-
-Due to the way Org works, TODO items, time-stamped items, and tagged
-headlines can be scattered throughout a file or even a number of
-files.  To get an overview of open action items, or of events that are
-important for a particular date, this information must be collected,
-sorted and displayed in an organized way.
-
-Org can select items based on various criteria and display them in
-a separate buffer.  Six different view types are provided:
-
-@itemize
-@item
-an @emph{agenda} that is like a calendar and shows information for
-specific dates,
-
-@item
-a @emph{TODO list} that covers all unfinished action items,
-
-@item
-a @emph{match view}, showings headlines based on the tags, properties,
-and TODO state associated with them,
-
-@item
-a @emph{text search view} that shows all entries from multiple files that
-contain specified keywords,
-
-@item
-a @emph{stuck projects view} showing projects that currently do not move
-along, and
-
-@item
-@emph{custom views} that are special searches and combinations of
-different views.
-@end itemize
-
-The extracted information is displayed in a special @emph{agenda buffer}.
-This buffer is read-only, but provides commands to visit the
-corresponding locations in the original Org files, and even to edit
-these files remotely.
-
-@vindex org-agenda-skip-comment-trees
-@vindex org-agenda-skip-archived-trees
-@cindex commented entries, in agenda views
-@cindex archived entries, in agenda views
-By default, the report ignores commented (see @ref{Comment Lines}) and
-archived (see @ref{Internal archiving}) entries.  You can override this by
-setting @code{org-agenda-skip-comment-trees} and
-@code{org-agenda-skip-archived-trees} to @code{nil}.
-
-@vindex org-agenda-window-setup
-@vindex org-agenda-restore-windows-after-quit
-Two variables control how the agenda buffer is displayed and whether
-the window configuration is restored when the agenda exits:
-@code{org-agenda-window-setup} and 
@code{org-agenda-restore-windows-after-quit}.
-
-@menu
-* Agenda Files::                 Files being searched for agenda information.
-* Agenda Dispatcher::            Keyboard access to agenda views.
-* Built-in Agenda Views::        What is available out of the box?
-* Presentation and Sorting::     How agenda items are prepared for display.
-* Agenda Commands::              Remote editing of Org trees.
-* Custom Agenda Views::          Defining special searches and views.
-* Exporting Agenda Views::       Writing a view to a file.
-* Agenda Column View::           Using column view for collected entries.
-@end menu
-
-@node Agenda Files
-@section Agenda Files
-
-@cindex agenda files
-@cindex files for agenda
-
-@vindex org-agenda-files
-The information to be shown is normally collected from all @emph{agenda
-files}, the files listed in the variable @code{org-agenda-files}@footnote{If 
the value of that variable is not a list, but a single file
-name, then the list of agenda files in maintained in that external
-file.}.
-If a directory is part of this list, all files with the extension
-@samp{.org} in this directory are part of the list.
-
-Thus, even if you only work with a single Org file, that file should
-be put into the list@footnote{When using the dispatcher, pressing @kbd{<} 
before
-selecting a command actually limits the command to the current file,
-and ignores @code{org-agenda-files} until the next dispatcher command.}.  You 
can customize @code{org-agenda-files},
-but the easiest way to maintain it is through the following commands
-
-@table @asis
-@item @kbd{C-c [} (@code{org-agenda-file-to-front})
-@kindex C-c [
-@findex org-agenda-file-to-front
-@cindex files, adding to agenda list
-Add current file to the list of agenda files.  The file is added to
-the front of the list.  If it was already in the list, it is moved
-to the front.  With a prefix argument, file is added/moved to the
-end.
-
-@item @kbd{C-c ]} (@code{org-remove-file})
-@kindex C-c ]
-@findex org-remove-file
-Remove current file from the list of agenda files.
-
-@item @kbd{C-'}
-@itemx @kbd{C-,} (@code{org-cycle-agenda-files})
-@kindex C-'
-@kindex C-,
-@findex org-cycle-agenda-files
-@cindex cycling, of agenda files
-Cycle through agenda file list, visiting one file after the other.
-
-@item @kbd{M-x org-switchb}
-@findex org-switchb
-Command to use an Iswitchb-like interface to switch to and between
-Org buffers.
-@end table
-
-@noindent
-The Org menu contains the current list of files and can be used to
-visit any of them.
-
-If you would like to focus the agenda temporarily on a file not in
-this list, or on just one file in the list, or even on only a subtree
-in a file, then this can be done in different ways.  For a single
-agenda command, you may press @kbd{<} once or several times in
-the dispatcher (see @ref{Agenda Dispatcher}).  To restrict the agenda
-scope for an extended period, use the following commands:
-
-@table @asis
-@item @kbd{C-c C-x <} (@code{org-agenda-set-restriction-lock})
-@kindex C-c C-x <
-@findex org-agenda-set-restriction-lock
-Restrict the agenda to the current subtree.  If there already is
-a restriction at point, remove it.  When called with a universal
-prefix argument or with point before the first headline in a file,
-set the agenda scope to the entire file.  This restriction remains
-in effect until removed with @kbd{C-c C-x >}, or by typing
-either @kbd{<} or @kbd{>} in the agenda dispatcher.  If
-there is a window displaying an agenda view, the new restriction
-takes effect immediately.
-
-@item @kbd{C-c C-x >} (@code{org-agenda-remove-restriction-lock})
-@kindex C-c C-x >
-@findex org-agenda-remove-restriction-lock
-Remove the restriction created by @kbd{C-c C-x <}.
-@end table
-
-When working with Speedbar, you can use the following commands in the
-Speedbar frame:
-
-@table @asis
-@item @kbd{<} (@code{org-speedbar-set-agenda-restriction})
-@findex org-speedbar-set-agenda-restriction
-Restrict the agenda to the item---either an Org file or a subtree in
-such a file---at point in the Speedbar frame.  If agenda is already
-restricted there, remove the restriction.  If there is a window
-displaying an agenda view, the new restriction takes effect
-immediately.
-
-@item @kbd{>} (@code{org-agenda-remove-restriction-lock})
-@findex org-agenda-remove-restriction-lock
-Remove the restriction.
-@end table
-
-@node Agenda Dispatcher
-@section The Agenda Dispatcher
-
-@cindex agenda dispatcher
-@cindex dispatching agenda commands
-
-The views are created through a dispatcher, accessible with @kbd{M-x 
org-agenda}, or, better, bound to a global key (see @ref{Activation}).
-It displays a menu from which an additional letter is required to
-execute a command.  The dispatcher offers the following default
-commands:
-
-@table @asis
-@item @kbd{a}
-Create the calendar-like agenda (see @ref{Weekly/daily agenda}).
-
-@item @kbd{t}
-@itemx @kbd{T}
-Create a list of all TODO items (see @ref{Global TODO list}).
-
-@item @kbd{m}
-@itemx @kbd{M}
-Create a list of headlines matching a given expression (see
-@ref{Matching tags and properties}).
-
-@item @kbd{s}
-@kindex s @r{(Agenda dispatcher)}
-Create a list of entries selected by a boolean expression of
-keywords and/or regular expressions that must or must not occur in
-the entry.
-
-@item @kbd{/}
-@kindex / @r{(Agenda dispatcher)}
-@vindex org-agenda-text-search-extra-files
-Search for a regular expression in all agenda files and additionally
-in the files listed in @code{org-agenda-text-search-extra-files}.  This
-uses the Emacs command @code{multi-occur}.  A prefix argument can be used
-to specify the number of context lines for each match, default is
-@enumerate
-@item
-@end enumerate
-
-@item @kbd{#}
-Create a list of stuck projects (see @ref{Stuck projects}).
-
-@item @kbd{!}
-Configure the list of stuck projects (see @ref{Stuck projects}).
-
-@item @kbd{<}
-@kindex < @r{(Agenda dispatcher)}
-Restrict an agenda command to the current buffer@footnote{For backward 
compatibility, you can also press @kbd{1} to
-restrict to the current buffer.}.  If
-narrowing is in effect restrict to the narrowed part of the buffer.
-After pressing @kbd{<}, you still need to press the character
-selecting the command.
-
-@item @kbd{< <}
-@kindex < < @r{(Agenda dispatcher)}
-If there is an active region, restrict the following agenda command
-to the region.  Otherwise, restrict it to the current
-subtree@footnote{For backward compatibility, you can also press @kbd{0} to
-restrict to the current region/subtree.}.  After pressing @kbd{< <}, you still 
need to
-press the character selecting the command.
-
-@item @kbd{*}
-@kindex * @r{(Agenda dispatcher)}
-@vindex org-agenda-sticky
-@findex org-toggle-sticky-agenda
-Toggle sticky agenda views.  By default, Org maintains only a single
-agenda buffer and rebuilds it each time you change the view, to make
-sure everything is always up to date.  If you switch between views
-often and the build time bothers you, you can turn on sticky agenda
-buffers (make this the default by customizing the variable
-@code{org-agenda-sticky}).  With sticky agendas, the dispatcher only
-switches to the selected view, you need to update it by hand with
-@kbd{r} or @kbd{g}.  You can toggle sticky agenda view any
-time with @code{org-toggle-sticky-agenda}.
-@end table
-
-You can also define custom commands that are accessible through the
-dispatcher, just like the default commands.  This includes the
-possibility to create extended agenda buffers that contain several
-blocks together, for example the weekly agenda, the global TODO list
-and a number of special tags matches.  See @ref{Custom Agenda Views}.
-
-@node Built-in Agenda Views
-@section The Built-in Agenda Views
-
-In this section we describe the built-in views.
-
-@menu
-* Weekly/daily agenda::          The calendar page with current tasks.
-* Global TODO list::             All unfinished action items.
-* Matching tags and properties:: Structured information with fine-tuned search.
-* Search view::                  Find entries by searching for text.
-* Stuck projects::               Find projects you need to review.
-@end menu
-
-@node Weekly/daily agenda
-@subsection Weekly/daily agenda
-
-@cindex agenda
-@cindex weekly agenda
-@cindex daily agenda
-
-The purpose of the weekly/daily @emph{agenda} is to act like a page of
-a paper agenda, showing all the tasks for the current week or day.
-
-@table @asis
-@item @kbd{M-x org-agenda a} (@code{org-agenda-list})
-@kindex a @r{(Agenda dispatcher)}
-@findex org-agenda-list
-@cindex org-agenda, command
-Compile an agenda for the current week from a list of Org files.
-The agenda shows the entries for each day.  With a numeric prefix
-argument@footnote{For backward compatibility, the universal prefix argument
-@kbd{C-u} causes all TODO entries to be listed before the agenda.
-This feature is deprecated, use the dedicated TODO list, or a block
-agenda instead (see @ref{Block agenda}).}---like @kbd{C-u 2 1 M-x org-agenda 
a}---you may
-set the number of days to be displayed.
-@end table
-
-@vindex org-agenda-span
-@vindex org-agenda-start-day
-@vindex org-agenda-start-on-weekday
-The default number of days displayed in the agenda is set by the
-variable @code{org-agenda-span}.  This variable can be set to any number of
-days you want to see by default in the agenda, or to a span name, such
-a @code{day}, @code{week}, @code{month} or @code{year}.  For weekly agendas, 
the default
-is to start on the previous Monday (see
-@code{org-agenda-start-on-weekday}).  You can also set the start date using
-a date shift: @samp{(setq org-agenda-start-day "+10d")} starts the agenda
-ten days from today in the future.
-
-Remote editing from the agenda buffer means, for example, that you can
-change the dates of deadlines and appointments from the agenda buffer.
-The commands available in the Agenda buffer are listed in @ref{Agenda 
Commands}.
-
-@anchor{Calendar/Diary integration}
-@subsubheading Calendar/Diary integration
-
-@cindex calendar integration
-@cindex diary integration
-
-Emacs contains the calendar and diary by Edward@tie{}M@.@tie{}Reingold.  The
-calendar displays a three-month calendar with holidays from different
-countries and cultures.  The diary allows you to keep track of
-anniversaries, lunar phases, sunrise/set, recurrent appointments
-(weekly, monthly) and more.  In this way, it is quite complementary to
-Org.  It can be very useful to combine output from Org with the diary.
-
-In order to include entries from the Emacs diary into Org mode's
-agenda, you only need to customize the variable
-
-@lisp
-(setq org-agenda-include-diary t)
-@end lisp
-
-@noindent
-After that, everything happens automatically.  All diary entries
-including holidays, anniversaries, etc., are included in the agenda
-buffer created by Org mode.  @kbd{@key{SPC}}, @kbd{@key{TAB}}, and
-@kbd{@key{RET}} can be used from the agenda buffer to jump to the diary
-file in order to edit existing diary entries.  The @kbd{i}
-command to insert new entries for the current date works in the agenda
-buffer, as well as the commands @kbd{S}, @kbd{M}, and
-@kbd{C} to display Sunrise/Sunset times, show lunar phases and to
-convert to other calendars, respectively.  @kbd{c} can be used to
-switch back and forth between calendar and agenda.
-
-If you are using the diary only for expression entries and holidays,
-it is faster to not use the above setting, but instead to copy or even
-move the entries into an Org file.  Org mode evaluates diary-style
-expression entries, and does it faster because there is no overhead
-for first creating the diary display.  Note that the expression
-entries must start at the left margin, no whitespace is allowed before
-them, as seen in the following segment of an Org file:@footnote{The variable 
@code{org-anniversary} used in the example is just
-like @code{diary-anniversary}, but the argument order is always according
-to ISO and therefore independent of the value of
-@code{calendar-date-style}.}
-
-@example
-* Holidays
-  :PROPERTIES:
-  :CATEGORY: Holiday
-  :END:
-%%(org-calendar-holiday)   ; special function for holiday names
-
-* Birthdays
-  :PROPERTIES:
-  :CATEGORY: Ann
-  :END:
-%%(org-anniversary 1956  5 14) Arthur Dent is %d years old
-%%(org-anniversary 1869 10  2) Mahatma Gandhi would be %d years old
-@end example
-
-@anchor{Anniversaries from BBDB}
-@subsubheading Anniversaries from BBDB
-
-@cindex BBDB, anniversaries
-@cindex anniversaries, from BBDB
-
-@findex org-bbdb-anniversaries
-If you are using the Insidious Big Brother Database to store your
-contacts, you very likely prefer to store anniversaries in BBDB rather
-than in a separate Org or diary file.  Org supports this and can show
-BBDB anniversaries as part of the agenda.  All you need to do is to
-add the following to one of your agenda files:
-
-@example
-* Anniversaries
-  :PROPERTIES:
-  :CATEGORY: Anniv
-  :END:
-%%(org-bbdb-anniversaries)
-@end example
-
-You can then go ahead and define anniversaries for a BBDB record.
-Basically, you need a field named @samp{anniversary} for the BBDB record
-which contains the date in the format @samp{YYYY-MM-DD} or @samp{MM-DD},
-followed by a space and the class of the anniversary (@samp{birthday},
-@samp{wedding}, or a format string).  If you omit the class, it defaults to
-@samp{birthday}.  Here are a few examples, the header for the file
-@samp{ol-bbdb.el} contains more detailed information.
-
-@example
-1973-06-22
-06-22
-1955-08-02 wedding
-2008-04-14 %s released version 6.01 of Org mode, %d years ago
-@end example
-
-After a change to BBDB, or for the first agenda display during an
-Emacs session, the agenda display suffers a short delay as Org updates
-its hash with anniversaries.  However, from then on things will be
-very fast, much faster in fact than a long list of
-@samp{%%(diary-anniversary)} entries in an Org or Diary file.
-
-@findex org-bbdb-anniversaries-future
-If you would like to see upcoming anniversaries with a bit of
-forewarning, you can use the following instead:
-
-@example
-* Anniversaries
-  :PROPERTIES:
-  :CATEGORY: Anniv
-  :END:
-%%(org-bbdb-anniversaries-future 3)
-@end example
-
-That will give you three days' warning: on the anniversary date itself
-and the two days prior.  The argument is optional: if omitted, it
-defaults to 7.
-
-@anchor{Appointment reminders}
-@subsubheading Appointment reminders
-
-@cindex @file{appt.el}
-@cindex appointment reminders
-@cindex appointment
-@cindex reminders
-
-@cindex APPT_WARNTIME, keyword
-Org can interact with Emacs appointments notification facility.  To
-add the appointments of your agenda files, use the command
-@code{org-agenda-to-appt}.  This command lets you filter through the list
-of your appointments and add only those belonging to a specific
-category or matching a regular expression.  It also reads
-a @samp{APPT_WARNTIME} property which overrides the value of
-@code{appt-message-warning-time} for this appointment.  See the docstring
-for details.
-
-@node Global TODO list
-@subsection The global TODO list
-
-@cindex global TODO list
-@cindex TODO list, global
-
-The global TODO list contains all unfinished TODO items formatted and
-collected into a single place.
-
-@table @asis
-@item @kbd{M-x org-agenda t} (@code{org-todo-list})
-@kindex t @r{(Agenda dispatcher)}
-@findex org-todo-list
-Show the global TODO list.  This collects the TODO items from all
-agenda files (see @ref{Agenda Views}) into a single buffer.  By default,
-this lists items with a state the is not a DONE state.  The buffer
-is in Agenda mode, so there are commands to examine and manipulate
-the TODO entries directly from that buffer (see @ref{Agenda Commands}).
-
-@item @kbd{M-x org-agenda T} (@code{org-todo-list})
-@kindex T @r{(Agenda dispatcher)}
-@findex org-todo-list
-@cindex TODO keyword matching
-@vindex org-todo-keywords
-Like the above, but allows selection of a specific TODO keyword.
-You can also do this by specifying a prefix argument to
-@kbd{t}.  You are prompted for a keyword, and you may also
-specify several keywords by separating them with @samp{|} as the boolean
-OR operator.  With a numeric prefix, the Nth keyword in
-@code{org-todo-keywords} is selected.
-
-@kindex r
-The @kbd{r} key in the agenda buffer regenerates it, and you
-can give a prefix argument to this command to change the selected
-TODO keyword, for example @kbd{3 r}.  If you often need
-a search for a specific keyword, define a custom command for it (see
-@ref{Agenda Dispatcher}).
-
-Matching specific TODO keywords can also be done as part of a tags
-search (see @ref{Tag Searches}).
-@end table
-
-Remote editing of TODO items means that you can change the state of
-a TODO entry with a single key press.  The commands available in the
-TODO list are described in @ref{Agenda Commands}.
-
-@cindex sublevels, inclusion into TODO list
-Normally the global TODO list simply shows all headlines with TODO
-keywords.  This list can become very long.  There are two ways to keep
-it more compact:
-
-@itemize
-@item
-@vindex org-agenda-todo-ignore-scheduled
-@vindex org-agenda-todo-ignore-deadlines
-@vindex org-agenda-todo-ignore-timestamp
-@vindex org-agenda-todo-ignore-with-date
-Some people view a TODO item that has been @emph{scheduled} for execution
-or have a @emph{deadline} (see @ref{Timestamps}) as no longer @emph{open}.
-Configure the variables @code{org-agenda-todo-ignore-scheduled} to
-exclude some or all scheduled items from the global TODO list,
-@code{org-agenda-todo-ignore-deadlines} to exclude some or all items with
-a deadline set, @code{org-agenda-todo-ignore-timestamp} to exclude some
-or all items with an active timestamp other than a DEADLINE or
-a SCHEDULED timestamp and/or @code{org-agenda-todo-ignore-with-date} to
-exclude items with at least one active timestamp.
-
-@item
-@vindex org-agenda-todo-list-sublevels
-TODO items may have sublevels to break up the task into subtasks.
-In such cases it may be enough to list only the highest level TODO
-headline and omit the sublevels from the global list.  Configure the
-variable @code{org-agenda-todo-list-sublevels} to get this behavior.
-@end itemize
-
-@node Matching tags and properties
-@subsection Matching tags and properties
-
-@cindex matching, of tags
-@cindex matching, of properties
-@cindex tags view
-@cindex match view
-
-If headlines in the agenda files are marked with @emph{tags} (see @ref{Tags}),
-or have properties (see @ref{Properties and Columns}), you can select
-headlines based on this metadata and collect them into an agenda
-buffer.  The match syntax described here also applies when creating
-sparse trees with @kbd{C-c / m}.
-
-@table @asis
-@item @kbd{M-x org-agenda m} (@code{org-tags-view})
-@kindex m @r{(Agenda dispatcher)}
-@findex org-tags-view
-Produce a list of all headlines that match a given set of tags.  The
-command prompts for a selection criterion, which is a boolean logic
-expression with tags, like @samp{+work+urgent-withboss} or @samp{work|home}
-(see @ref{Tags}).  If you often need a specific search, define a custom
-command for it (see @ref{Agenda Dispatcher}).
-
-@item @kbd{M-x org-agenda M} (@code{org-tags-view})
-@kindex M @r{(Agenda dispatcher)}
-@findex org-tags-view
-@vindex org-tags-match-list-sublevels
-@vindex org-agenda-tags-todo-honor-ignore-options
-Like @kbd{m}, but only select headlines that are also TODO
-items and force checking subitems (see the variable
-@code{org-tags-match-list-sublevels}).  To exclude scheduled/deadline
-items, see the variable @code{org-agenda-tags-todo-honor-ignore-options}.
-Matching specific TODO keywords together with a tags match is also
-possible, see @ref{Tag Searches}.
-@end table
-
-The commands available in the tags list are described in @ref{Agenda Commands}.
-
-@cindex boolean logic, for agenda searches
-A search string can use Boolean operators @samp{&} for AND and @samp{|} for 
OR@.
-@samp{&} binds more strongly than @samp{|}.  Parentheses are currently not
-implemented.  Each element in the search is either a tag, a regular
-expression matching tags, or an expression like @samp{PROPERTY OPERATOR
-VALUE} with a comparison operator, accessing a property value.  Each
-element may be preceded by @samp{-} to select against it, and @samp{+} is
-syntactic sugar for positive selection.  The AND operator @samp{&} is
-optional when @samp{+} or @samp{-} is present.  Here are some examples, using
-only tags.
-
-@table @asis
-@item @samp{+work-boss}
-Select headlines tagged @samp{work}, but discard those also tagged
-@samp{boss}.
-
-@item @samp{work|laptop}
-Selects lines tagged @samp{work} or @samp{laptop}.
-
-@item @samp{work|laptop+night}
-Like before, but require the @samp{laptop} lines to be tagged also
-@samp{night}.
-@end table
-
-@cindex regular expressions, with tags search
-Instead of a tag, you may also specify a regular expression enclosed
-in curly braces.  For example, @samp{work+@{^boss.*@}} matches headlines that
-contain the tag @samp{:work:} and any tag @emph{starting} with @samp{boss}.
-
-@cindex group tags, as regular expressions
-Group tags (see @ref{Tag Hierarchy}) are expanded as regular expressions.
-E.g., if @samp{work} is a group tag for the group @samp{:work:lab:conf:}, then
-searching for @samp{work} also searches for @samp{@{\(?:work\|lab\|conf\)@}} 
and
-searching for @samp{-work} searches for all headlines but those with one of
-the tags in the group (i.e., @samp{-@{\(?:work\|lab\|conf\)@}}).
-
-@cindex TODO keyword matching, with tags search
-@cindex level, for tags/property match
-@cindex category, for tags/property match
-@vindex org-odd-levels-only
-You may also test for properties (see @ref{Properties and Columns}) at the
-same time as matching tags.  The properties may be real properties, or
-special properties that represent other metadata (see @ref{Special 
Properties}).  For example, the property @samp{TODO} represents the TODO
-keyword of the entry.  Or, the property @samp{LEVEL} represents the level
-of an entry.  So searching @samp{+LEVEL=3+boss-TODO​="DONE"} lists all level
-three headlines that have the tag @samp{boss} and are @emph{not} marked with 
the
-TODO keyword @samp{DONE}.  In buffers with @code{org-odd-levels-only} set,
-@samp{LEVEL} does not count the number of stars, but @samp{LEVEL=2} corresponds
-to 3 stars etc.
-
-Here are more examples:
-
-@table @asis
-@item @samp{work+TODO​="WAITING"}
-Select @samp{work}-tagged TODO lines with the specific TODO keyword
-@samp{WAITING}.
-
-@item @samp{work+TODO​="WAITING"|home+TODO​="WAITING"}
-Waiting tasks both at work and at home.
-@end table
-
-When matching properties, a number of different operators can be used
-to test the value of a property.  Here is a complex example:
-
-@example
-+work-boss+PRIORITY="A"+Coffee="unlimited"+Effort<2
-         +With=@{Sarah|Denny@}+SCHEDULED>="<2008-10-11>"
-@end example
-
-@noindent
-The type of comparison depends on how the comparison value is written:
-
-@itemize
-@item
-If the comparison value is a plain number, a numerical comparison is
-done, and the allowed operators are @samp{<}, @samp{=}, @samp{>}, @samp{<=}, 
@samp{>=}, and
-@samp{<>}.
-
-@item
-If the comparison value is enclosed in double-quotes, a string
-comparison is done, and the same operators are allowed.
-
-@item
-If the comparison value is enclosed in double-quotes @emph{and} angular
-brackets (like @samp{DEADLINE<​="<2008-12-24 18:30>"}), both values are
-assumed to be date/time specifications in the standard Org way, and
-the comparison is done accordingly.  Valid values also include
-@samp{"<now>"} for now (including time), @samp{"<today>"}, and 
@samp{"<tomorrow>"}
-for these days at 0:00 hours, i.e., without a time specification.
-You can also use strings like @samp{"<+5d>"} or @samp{"<-2m>"} with units 
@samp{d},
-@samp{w}, @samp{m}, and @samp{y} for day, week, month, and year, respectively.
-
-@item
-If the comparison value is enclosed in curly braces, a regexp match
-is performed, with @samp{=} meaning that the regexp matches the property
-value, and @samp{<>} meaning that it does not match.
-@end itemize
-
-So the search string in the example finds entries tagged @samp{work} but
-not @samp{boss}, which also have a priority value @samp{A}, a @samp{Coffee} 
property
-with the value @samp{unlimited}, an @samp{EFFORT} property that is numerically
-smaller than 2, a @samp{With} property that is matched by the regular
-expression @samp{Sarah|Denny}, and that are scheduled on or after October
-11, 2008.
-
-You can configure Org mode to use property inheritance during
-a search, but beware that this can slow down searches considerably.
-See @ref{Property Inheritance}, for details.
-
-For backward compatibility, and also for typing speed, there is also
-a different way to test TODO states in a search.  For this, terminate
-the tags/property part of the search string (which may include several
-terms connected with @samp{|}) with a @samp{/} and then specify a Boolean
-expression just for TODO keywords.  The syntax is then similar to that
-for tags, but should be applied with care: for example, a positive
-selection on several TODO keywords cannot meaningfully be combined
-with boolean AND@.  However, @emph{negative selection} combined with AND can
-be meaningful.  To make sure that only lines are checked that actually
-have any TODO keyword (resulting in a speed-up), use @kbd{M-x org-agenda M}, 
or equivalently start the TODO part after the slash
-with @samp{!}.  Using @kbd{M-x org-agenda M} or @samp{/!} does not match
-TODO keywords in a DONE state.  Examples:
-
-@table @asis
-@item @samp{work/WAITING}
-Same as @samp{work+TODO​="WAITING"}.
-
-@item @samp{work/!-WAITING-NEXT}
-Select @samp{work}-tagged TODO lines that are neither @samp{WAITING} nor
-@samp{NEXT}.
-
-@item @samp{work/!+WAITING|+NEXT}
-Select @samp{work}-tagged TODO lines that are either @samp{WAITING} or 
@samp{NEXT}.
-@end table
-
-@node Search view
-@subsection Search view
-
-@cindex search view
-@cindex text search
-@cindex searching, for text
-
-This agenda view is a general text search facility for Org mode
-entries.  It is particularly useful to find notes.
-
-@table @asis
-@item @kbd{M-x org-agenda s} (@code{org-search-view})
-@kindex s @r{(Agenda dispatcher)}
-@findex org-search-view
-This is a special search that lets you select entries by matching
-a substring or specific words using a boolean logic.
-@end table
-
-For example, the search string @samp{computer equipment} matches entries
-that contain @samp{computer equipment} as a substring, even if the two
-words are separated by more space or a line break.
-
-Search view can also search for specific keywords in the entry, using
-Boolean logic.  The search string @samp{+computer
-+wifi -ethernet -@{8\.11[bg]@}} matches note entries that contain the
-keywords @samp{computer} and @samp{wifi}, but not the keyword @samp{ethernet}, 
and
-which are also not matched by the regular expression @samp{8\.11[bg]},
-meaning to exclude both @samp{8.11b} and @samp{8.11g}.  The first @samp{+} is
-necessary to turn on boolean search, other @samp{+} characters are
-optional.  For more details, see the docstring of the command
-@code{org-search-view}.
-
-You can incrementally and conveniently adjust a boolean search from
-the agenda search view with the following keys
-
-@multitable @columnfractions 0.1 0.6
-@item @kbd{[}
-@tab Add a positive search word
-@item @kbd{]}
-@tab Add a negative search word
-@item @kbd{@{}
-@tab Add a positive regular expression
-@item @kbd{@}}
-@tab Add a negative regular expression
-@end multitable
-
-@vindex org-agenda-text-search-extra-files
-Note that in addition to the agenda files, this command also searches
-the files listed in @code{org-agenda-text-search-extra-files}.
-
-@node Stuck projects
-@subsection Stuck projects
-
-@pindex GTD, Getting Things Done
-
-If you are following a system like David Allen's GTD to organize your
-work, one of the ``duties'' you have is a regular review to make sure
-that all projects move along.  A @emph{stuck} project is a project that has
-no defined next actions, so it never shows up in the TODO lists Org
-mode produces.  During the review, you need to identify such projects
-and define next actions for them.
-
-@table @asis
-@item @kbd{M-x org-agenda #} (@code{org-agenda-list-stuck-projects})
-@kindex # @r{(Agenda dispatcher)}
-@findex org-agenda-list-stuck-projects
-List projects that are stuck.
-
-@item @kbd{M-x org-agenda !}
-@kindex ! @r{(Agenda dispatcher)}
-@vindex org-stuck-projects
-Customize the variable @code{org-stuck-projects} to define what a stuck
-project is and how to find it.
-@end table
-
-You almost certainly need to configure this view before it works for
-you.  The built-in default assumes that all your projects are level-2
-headlines, and that a project is not stuck if it has at least one
-entry marked with a TODO keyword @samp{TODO} or @samp{NEXT} or 
@samp{NEXTACTION}.
-
-Let's assume that you, in your own way of using Org mode, identify
-projects with a tag @samp{:PROJECT:}, and that you use a TODO keyword
-@samp{MAYBE} to indicate a project that should not be considered yet.
-Let's further assume that the TODO keyword @samp{DONE} marks finished
-projects, and that @samp{NEXT} and @samp{TODO} indicate next actions.  The tag
-@samp{:@@shop:} indicates shopping and is a next action even without the
-NEXT tag.  Finally, if the project contains the special word @samp{IGNORE}
-anywhere, it should not be listed either.  In this case you would
-start by identifying eligible projects with a tags/TODO match (see
-@ref{Tag Searches}) @samp{+PROJECT/-MAYBE-DONE}, and then check for 
@samp{TODO},
-@samp{NEXT}, @samp{@@shop}, and @samp{IGNORE} in the subtree to identify 
projects that
-are not stuck.  The correct customization for this is:
-
-@lisp
-(setq org-stuck-projects
-      '("+PROJECT/-MAYBE-DONE" ("NEXT" "TODO") ("@@shop")
-        "\\<IGNORE\\>"))
-@end lisp
-
-Note that if a project is identified as non-stuck, the subtree of this
-entry is searched for stuck projects.
-
-@node Presentation and Sorting
-@section Presentation and Sorting
-
-@cindex presentation, of agenda items
-
-@vindex org-agenda-prefix-format
-@vindex org-agenda-tags-column
-Before displaying items in an agenda view, Org mode visually prepares
-the items and sorts them.  Each item occupies a single line.  The line
-starts with a @emph{prefix} that contains the @emph{category} (see 
@ref{Categories})
-of the item and other important information.  You can customize in
-which column tags are displayed through @code{org-agenda-tags-column}.  You
-can also customize the prefix using the option
-@code{org-agenda-prefix-format}.  This prefix is followed by a cleaned-up
-version of the outline headline associated with the item.
-
-@menu
-* Categories::                   Not all tasks are equal.
-* Time-of-day specifications::   How the agenda knows the time.
-* Sorting of agenda items::      The order of things.
-* Filtering/limiting agenda items:: Dynamically narrow the agenda.
-@end menu
-
-@node Categories
-@subsection Categories
-
-@cindex category
-@cindex @samp{CATEGORY}, keyword
-
-The category is a broad label assigned to each agenda item.  By
-default, the category is simply derived from the file name, but you
-can also specify it with a special line in the buffer, like
-this:
-
-@example
-#+CATEGORY: Thesis
-@end example
-
-
-@cindex @samp{CATEGORY}, property
-If you would like to have a special category for a single entry or
-a (sub)tree, give the entry a @samp{CATEGORY} property with the special
-category you want to apply as the value.
-
-@vindex org-agenda-category-icon-alist
-The display in the agenda buffer looks best if the category is not
-longer than 10 characters.  You can set up icons for category by
-customizing the @code{org-agenda-category-icon-alist} variable.
-
-@node Time-of-day specifications
-@subsection Time-of-day specifications
-
-@cindex time-of-day specification
-
-Org mode checks each agenda item for a time-of-day specification.  The
-time can be part of the timestamp that triggered inclusion into the
-agenda, for example
-
-@example
-<2005-05-10 Tue 19:00>
-@end example
-
-
-@noindent
-Time ranges can be specified with two timestamps:
-
-@example
-<2005-05-10 Tue 20:30>--<2005-05-10 Tue 22:15>
-@end example
-
-
-@vindex org-agenda-search-headline-for-time
-In the headline of the entry itself, a time(range)---like @samp{12:45} or
-a @samp{8:30-1pm}---may also appear as plain text@footnote{You can, however, 
disable this by setting
-@code{org-agenda-search-headline-for-time} variable to a @code{nil} value.}.
-
-If the agenda integrates the Emacs diary (see @ref{Weekly/daily agenda}),
-time specifications in diary entries are recognized as well.
-
-For agenda display, Org mode extracts the time and displays it in
-a standard 24 hour format as part of the prefix.  The example times in
-the previous paragraphs would end up in the agenda like this:
-
-@example
- 8:30-13:00 Arthur Dent lies in front of the bulldozer
-12:45...... Ford Prefect arrives and takes Arthur to the pub
-19:00...... The Vogon reads his poem
-20:30-22:15 Marvin escorts the Hitchhikers to the bridge
-@end example
-
-@cindex time grid
-If the agenda is in single-day mode, or for the display of today, the
-timed entries are embedded in a time grid, like
-
-@example
- 8:00...... ------------------
- 8:30-13:00 Arthur Dent lies in front of the bulldozer
-10:00...... ------------------
-12:00...... ------------------
-12:45...... Ford Prefect arrives and takes Arthur to the pub
-14:00...... ------------------
-16:00...... ------------------
-18:00...... ------------------
-19:00...... The Vogon reads his poem
-20:00...... ------------------
-20:30-22:15 Marvin escorts the Hitchhikers to the bridge
-@end example
-
-@vindex org-agenda-use-time-grid
-@vindex org-agenda-time-grid
-The time grid can be turned on and off with the variable
-@code{org-agenda-use-time-grid}, and can be configured with
-@code{org-agenda-time-grid}.
-
-@node Sorting of agenda items
-@subsection Sorting of agenda items
-
-@cindex sorting, of agenda items
-@cindex priorities, of agenda items
-
-Before being inserted into a view, the items are sorted.  How this is
-done depends on the type of view.
-
-@itemize
-@item
-@vindex org-agenda-files
-For the daily/weekly agenda, the items for each day are sorted.  The
-default order is to first collect all items containing an explicit
-time-of-day specification.  These entries are shown at the beginning
-of the list, as a @emph{schedule} for the day.  After that, items remain
-grouped in categories, in the sequence given by @code{org-agenda-files}.
-Within each category, items are sorted by priority (see
-@ref{Priorities}), which is composed of the base priority (2000 for
-priority @samp{A}, 1000 for @samp{B}, and 0 for @samp{C}), plus additional
-increments for overdue scheduled or deadline items.
-
-@item
-For the TODO list, items remain in the order of categories, but
-within each category, sorting takes place according to priority (see
-@ref{Priorities}).  The priority used for sorting derives from the
-priority cookie, with additions depending on how close an item is to
-its due or scheduled date.
-
-@item
-For tags matches, items are not sorted at all, but just appear in
-the sequence in which they are found in the agenda files.
-@end itemize
-
-@vindex org-agenda-sorting-strategy
-Sorting can be customized using the variable
-@code{org-agenda-sorting-strategy}, and may also include criteria based on
-the estimated effort of an entry (see @ref{Effort Estimates}).
-
-@node Filtering/limiting agenda items
-@subsection Filtering/limiting agenda items
-
-@vindex org-agenda-category-filter-preset
-@vindex org-agenda-tag-filter-preset
-@vindex org-agenda-effort-filter-preset
-@vindex org-agenda-regexp-filter-preset
-Agenda built-in or custom commands are statically defined.  Agenda
-filters and limits allow to flexibly narrow down the list of agenda
-entries.
-
-@emph{Filters} only change the visibility of items, are very fast and are
-mostly used interactively@footnote{Custom agenda commands can preset a filter 
by binding one of
-the variables @code{org-agenda-tag-filter-preset},
-@code{org-agenda-category-filter-preset}, 
@code{org-agenda-effort-filter-preset}
-or @code{org-agenda-regexp-filter-preset} as an option.  This filter is
-then applied to the view and persists as a basic filter through
-refreshes and more secondary filtering.  The filter is a global
-property of the entire agenda view---in a block agenda, you should
-only set this in the global options section, not in the section of an
-individual block.}.  You can switch quickly between
-different filters without having to recreate the agenda.  @emph{Limits} on
-the other hand take effect before the agenda buffer is populated, so
-they are mostly useful when defined as local variables within custom
-agenda commands.
-
-@anchor{Filtering in the agenda}
-@subsubheading Filtering in the agenda
-
-@cindex agenda filtering
-@cindex filtering entries, in agenda
-@cindex tag filtering, in agenda
-@cindex category filtering, in agenda
-@cindex top headline filtering, in agenda
-@cindex effort filtering, in agenda
-@cindex query editing, in agenda
-
-The general filtering command is @code{org-agenda-filter}, bound to
-@kbd{/}.  Before we introduce it, we describe commands for
-individual filter types.  All filtering commands handle prefix
-arguments in the same way:  A single @kbd{C-u} prefix negates the
-filter, so it removes lines selected by the filter.  A double prefix
-adds the new filter condition to the one(s) already in place, so
-filter elements are accumulated.
-
-@table @asis
-@item @kbd{\} (@code{org-agenda-filter-by-tag})
-@findex org-agenda-filter-by-tag
-Filter the agenda view with respect to a tag.  You are prompted for
-a tag selection letter; @kbd{@key{SPC}} means any tag at all.
-Pressing @kbd{@key{TAB}} at that prompt offers completion to select a
-tag, including any tags that do not have a selection character.  The
-command then hides all entries that do not contain or inherit this
-tag.  Pressing @kbd{+} or @kbd{-} at the prompt switches
-between filtering for and against the next tag.  To clear the
-filter, press @kbd{\} twice (once to call the command again,
-and once at the prompt).
-
-@item @kbd{<} (@code{org-agenda-filter-by-category})
-@findex org-agenda-filter-by-category
-Filter by category of the line at point, and show only entries with
-this category.  When called with a prefix argument, hide all entries
-with the category at point.  To clear the filter, call this command
-again by pressing @kbd{<}.
-
-@item @kbd{=} (@code{org-agenda-filter-by-regexp})
-@findex org-agenda-filter-by-regexp
-Filter the agenda view by a regular expression: only show agenda
-entries matching the regular expression the user entered.  To clear
-the filter, call the command again by pressing @kbd{=}.
-
-@item @kbd{_} (@code{org-agenda-filter-by-effort})
-@findex org-agenda-filter-by-effort
-Filter the agenda view with respect to effort estimates, so select
-tasks that take the right amount of time.  You first need to set up
-a list of efforts globally, for example
-
-@lisp
-(setq org-global-properties
-      '(("Effort_ALL". "0 0:10 0:30 1:00 2:00 3:00 4:00")))
-@end lisp
-
-@vindex org-sort-agenda-noeffort-is-high
-You can then filter for an effort by first typing an operator, one
-of @kbd{<}, @kbd{>} and @kbd{=}, and then the
-one-digit index of an effort estimate in your array of allowed
-values, where @kbd{0} means the 10th value.  The filter then
-restricts to entries with effort smaller-or-equal, equal, or
-larger-or-equal than the selected value.  For application of the
-operator, entries without a defined effort are treated according to
-the value of @code{org-sort-agenda-noeffort-is-high}.  To clear the
-filter, press @kbd{_} twice (once to call the command again,
-and once at the first prompt).
-
-@item @kbd{^} (@code{org-agenda-filter-by-top-headline})
-@findex org-agenda-filter-by-top-headline
-Filter the current agenda view and only display items that fall
-under the same top-level headline as the current entry.  To clear
-the filter, call this command again by pressing @kbd{^}.
-
-@item @kbd{/} (@code{org-agenda-filter})
-@findex org-agenda-filter
-This is the unified interface to four of the five filter methods
-described above.  At the prompt, specify different filter elements
-in a single string, with full completion support.  For example,
-
-@example
-+work-John+<0:10-/plot/
-@end example
-
-
-selects entries with category @samp{work} and effort estimates below 10
-minutes, and deselects entries with tag @samp{John} or matching the
-regexp @samp{plot}.  You can leave @samp{+} out if that does not lead to
-ambiguities.  The sequence of elements is arbitrary.  The filter
-syntax assumes that there is no overlap between categories and tags.
-Otherwise, tags take priority.  If you reply to the prompt with the
-empty string, all filtering is removed.  If a filter is specified,
-it replaces all current filters.  But if you call the command with
-a double prefix argument, or if you add an additional @samp{+} (e.g.,
-@samp{++work}) to the front of the string, the new filter elements are
-added to the active ones.  A single prefix argument applies the
-entire filter in a negative sense.
-
-@item @kbd{|} (@code{org-agenda-filter-remove-all})
-Remove all filters in the current agenda view.
-@end table
-
-@anchor{Computed tag filtering}
-@subsubheading Computed tag filtering
-
-@vindex org-agenda-auto-exclude-function
-If the variable @code{org-agenda-auto-exclude-function} is set to
-a user-defined function, that function can select tags that should be
-used as a tag filter when requested.  The function will be called with
-lower-case versions of all tags represented in the current view.  The
-function should return @samp{"-tag"} if the filter should remove
-entries with that tag, @samp{"+tag"} if only entries with this tag should
-be kept, or @samp{nil} if that tag is irrelevant.  For example, let's say
-you use a @samp{Net} tag to identify tasks which need network access, an
-@samp{Errand} tag for errands in town, and a @samp{Call} tag for making phone
-calls.  You could auto-exclude these tags based on the availability of
-the Internet, and outside of business hours, with something like this:
-
-@lisp
-(defun my-auto-exclude-fn (tag)
-  (when (cond ((string= tag "net")
-               (/= 0 (call-process "/sbin/ping" nil nil nil
-                                   "-c1" "-q" "-t1" "mail.gnu.org")))
-              ((member tag '("errand" "call"))
-               (let ((hr (nth 2 (decode-time))))
-                 (or (< hr 8) (> hr 21)))))
-    (concat "-" tag)))
-
-(setq org-agenda-auto-exclude-function #'my-auto-exclude-fn)
-@end lisp
-
-You can apply this self-adapting filter by using a triple prefix
-argument to @code{org-agenda-filter}, i.e.@tie{}press @kbd{C-u C-u C-u /},
-or by pressing @kbd{@key{RET}} in @code{org-agenda-filter-by-tag}.
-
-@anchor{Setting limits for the agenda}
-@subsubheading Setting limits for the agenda
-
-@cindex limits, in agenda
-
-Here is a list of options that you can set, either globally, or
-locally in your custom agenda views (see @ref{Custom Agenda Views}).
-
-@table @asis
-@item @code{org-agenda-max-entries}
-@vindex org-agenda-max-entries
-Limit the number of entries.
-
-@item @code{org-agenda-max-effort}
-@vindex org-agenda-max-effort
-Limit the duration of accumulated efforts (as minutes).
-
-@item @code{org-agenda-max-todos}
-@vindex org-agenda-max-todos
-Limit the number of entries with TODO keywords.
-
-@item @code{org-agenda-max-tags}
-@vindex org-agenda-max-tags
-Limit the number of tagged entries.
-@end table
-
-When set to a positive integer, each option excludes entries from
-other categories: for example, @samp{(setq org-agenda-max-effort 100)}
-limits the agenda to 100 minutes of effort and exclude any entry that
-has no effort property.  If you want to include entries with no effort
-property, use a negative value for @code{org-agenda-max-effort}.  One
-useful setup is to use @code{org-agenda-max-entries} locally in a custom
-command.  For example, this custom command displays the next five
-entries with a @samp{NEXT} TODO keyword.
-
-@lisp
-(setq org-agenda-custom-commands
-      '(("n" todo "NEXT"
-         ((org-agenda-max-entries 5)))))
-@end lisp
-
-Once you mark one of these five entry as DONE, rebuilding the agenda
-will again the next five entries again, including the first entry that
-was excluded so far.
-
-You can also dynamically set temporary limits, which are lost when
-rebuilding the agenda:
-
-@table @asis
-@item @kbd{~} (@code{org-agenda-limit-interactively})
-@findex org-agenda-limit-interactively
-This prompts for the type of limit to apply and its value.
-@end table
-
-@node Agenda Commands
-@section Commands in the Agenda Buffer
-
-@cindex commands, in agenda buffer
-
-Entries in the agenda buffer are linked back to the Org file or diary
-file where they originate.  You are not allowed to edit the agenda
-buffer itself, but commands are provided to show and jump to the
-original entry location, and to edit the Org files ``remotely'' from the
-agenda buffer.  In this way, all information is stored only once,
-removing the risk that your agenda and note files may diverge.
-
-Some commands can be executed with mouse clicks on agenda lines.  For
-the other commands, point needs to be in the desired line.
-
-@anchor{Motion (1)}
-@subheading Motion
-
-@cindex motion commands in agenda
-
-@table @asis
-@item @kbd{n} (@code{org-agenda-next-line})
-@kindex n
-@findex org-agenda-next-line
-Next line (same as @kbd{@key{DOWN}} and @kbd{C-n}).
-
-@item @kbd{p} (@code{org-agenda-previous-line})
-@kindex p
-@findex org-agenda-previous-line
-Previous line (same as @kbd{@key{UP}} and @kbd{C-p}).
-@end table
-
-@anchor{View/Go to Org file}
-@subheading View/Go to Org file
-
-@cindex view file commands in agenda
-
-@table @asis
-@item @kbd{@key{SPC}} or @kbd{mouse-3} (@code{org-agenda-show-and-scroll-up})
-@kindex SPC
-@kindex mouse-3
-@findex org-agenda-show-and-scroll-up
-Display the original location of the item in another window.
-With a prefix argument, make sure that drawers stay folded.
-
-@item @kbd{L} (@code{org-agenda-recenter})
-@findex org-agenda-recenter
-Display original location and recenter that window.
-
-@item @kbd{@key{TAB}} or @kbd{mouse-2} (@code{org-agenda-goto})
-@kindex TAB
-@kindex mouse-2
-@findex org-agenda-goto
-Go to the original location of the item in another window.
-
-@item @kbd{@key{RET}} (@code{org-agenda-switch-to})
-@kindex RET
-@findex org-agenda-switch-to
-Go to the original location of the item and delete other windows.
-
-@item @kbd{F} (@code{org-agenda-follow-mode})
-@kindex F
-@findex org-agenda-follow-mode
-@vindex org-agenda-start-with-follow-mode
-Toggle Follow mode.  In Follow mode, as you move point through the
-agenda buffer, the other window always shows the corresponding
-location in the Org file.  The initial setting for this mode in new
-agenda buffers can be set with the variable
-@code{org-agenda-start-with-follow-mode}.
-
-@item @kbd{C-c C-x b} (@code{org-agenda-tree-to-indirect-buffer})
-@kindex C-c C-x b
-@findex org-agenda-tree-to-indirect-buffer
-Display the entire subtree of the current item in an indirect
-buffer.  With a numeric prefix argument N, go up to level N and then
-take that tree.  If N is negative, go up that many levels.  With
-a @kbd{C-u} prefix, do not remove the previously used indirect
-buffer.
-
-@item @kbd{C-c C-o} (@code{org-agenda-open-link})
-@kindex C-c C-o
-@findex org-agenda-open-link
-Follow a link in the entry.  This offers a selection of any links in
-the text belonging to the referenced Org node.  If there is only one
-link, follow it without a selection prompt.
-@end table
-
-@anchor{Change display}
-@subheading Change display
-
-@cindex change agenda display
-@cindex display changing, in agenda
-
-@table @asis
-@item @kbd{A}
-@kindex A
-Interactively select another agenda view and append it to the
-current view.
-
-@item @kbd{o}
-@kindex o
-Delete other windows.
-
-@item @kbd{v d} or short @kbd{d} (@code{org-agenda-day-view})
-@kindex v d
-@kindex d
-@findex org-agenda-day-view
-Switch to day view.  When switching to day view, this setting
-becomes the default for subsequent agenda refreshes.  A numeric
-prefix argument may be used to jump directly to a specific day of
-the year.  For example, @kbd{32 d} jumps to February 1st.  When
-setting day view, a year may be encoded in the prefix argument as
-well.  For example, @kbd{200712 d} jumps to January 12, 2007.
-If such a year specification has only one or two digits, it is
-expanded into one of the 30 next years or the last 69 years.
-
-@item @kbd{v w} or short @kbd{w} (@code{org-agenda-week-view})
-@kindex v w
-@kindex w
-@findex org-agenda-week-view
-Switch to week view.  When switching week view, this setting becomes
-the default for subsequent agenda refreshes.  A numeric prefix
-argument may be used to jump directly to a specific day of the ISO
-week.  For example @kbd{9 w} to ISO week number 9.  When
-setting week view, a year may be encoded in the prefix argument as
-well.  For example, @kbd{200712 w} jumps to week 12 in 2007.
-If such a year specification has only one or two digits, it is
-expanded into one of the 30 next years or the last 69 years.
-
-@item @kbd{v m} (@code{org-agenda-month-view})
-@kindex v m
-@findex org-agenda-month-view
-Switch to month view.  Because month views are slow to create, they
-do not become the default for subsequent agenda refreshes.
-A numeric prefix argument may be used to jump directly to a specific
-day of the month.  When setting month view, a year may be encoded in
-the prefix argument as well.  For example, @kbd{200712 m} jumps
-to December, 2007.  If such a year specification has only one or two
-digits, it is expanded into one of the 30 next years or the last 69
-years.
-
-@item @kbd{v y} (@code{org-agenda-year-view})
-@kindex v y
-@findex org-agenda-year-view
-Switch to year view.  Because year views are slow to create, they do
-not become the default for subsequent agenda refreshes.  A numeric
-prefix argument may be used to jump directly to a specific day of
-the year.
-
-@item @kbd{v @key{SPC}} (@code{org-agenda-reset-view})
-@kindex v SPC
-@findex org-agenda-reset-view
-@vindex org-agenda-span
-Reset the current view to @code{org-agenda-span}.
-
-@item @kbd{f} (@code{org-agenda-later})
-@kindex f
-@findex org-agenda-later
-Go forward in time to display the span following the current one.
-For example, if the display covers a week, switch to the following
-week.  With a prefix argument, repeat that many times.
-
-@item @kbd{b} (@code{org-agenda-earlier})
-@kindex b
-@findex org-agenda-earlier
-Go backward in time to display earlier dates.
-
-@item @kbd{.} (@code{org-agenda-goto-today})
-@kindex .
-@findex org-agenda-goto-today
-Go to today.
-
-@item @kbd{j} (@code{org-agenda-goto-date})
-@kindex j
-@findex org-agenda-goto-date
-Prompt for a date and go there.
-
-@item @kbd{J} (@code{org-agenda-clock-goto})
-@kindex J
-@findex org-agenda-clock-goto
-Go to the currently clocked-in task @emph{in the agenda buffer}.
-
-@item @kbd{D} (@code{org-agenda-toggle-diary})
-@kindex D
-@findex org-agenda-toggle-diary
-Toggle the inclusion of diary entries.  See @ref{Weekly/daily agenda}.
-
-@item @kbd{v l} or @kbd{v L} or short @kbd{l} (@code{org-agenda-log-mode})
-@kindex v l
-@kindex l
-@kindex v L
-@findex org-agenda-log-mode
-@vindex org-log-done
-@vindex org-agenda-log-mode-items
-Toggle Logbook mode.  In Logbook mode, entries that were marked as
-done while logging was on (see the variable @code{org-log-done}) are
-shown in the agenda, as are entries that have been clocked on that
-day.  You can configure the entry types that should be included in
-log mode using the variable @code{org-agenda-log-mode-items}.  When
-called with a @kbd{C-u} prefix argument, show all possible
-logbook entries, including state changes.  When called with two
-prefix arguments @kbd{C-u C-u}, show only logging information,
-nothing else.  @kbd{v L} is equivalent to @kbd{C-u v l}.
-
-@item @kbd{v [} or short @kbd{[} (@code{org-agenda-manipulate-query-add})
-@kindex v [
-@kindex [
-@findex org-agenda-manipulate-query-add
-Include inactive timestamps into the current view.  Only for
-weekly/daily agenda.
-
-@item @kbd{v a} (@code{org-agenda-archives-mode})
-@kindex v a
-@findex org-agenda-archives-mode
-Toggle Archives mode.  In Archives mode, trees that are archived
-(see @ref{Internal archiving}) are also scanned when producing the
-agenda.  To exit archives mode, press @kbd{v a} again.
-
-@item @kbd{v A}
-@kindex v A
-Toggle Archives mode.  Include all archive files as well.
-
-@item @kbd{v R} or short @kbd{R} (@code{org-agenda-clockreport-mode})
-@kindex v R
-@kindex R
-@findex org-agenda-clockreport-mode
-@vindex org-agenda-start-with-clockreport-mode
-@vindex org-clock-report-include-clocking-task
-Toggle Clockreport mode.  In Clockreport mode, the daily/weekly
-agenda always shows a table with the clocked times for the time span
-and file scope covered by the current agenda view.  The initial
-setting for this mode in new agenda buffers can be set with the
-variable @code{org-agenda-start-with-clockreport-mode}.  By using
-a prefix argument when toggling this mode (i.e., @kbd{C-u R}),
-the clock table does not show contributions from entries that are
-hidden by agenda filtering@footnote{Only tags filtering is respected here, 
effort filtering is
-ignored.}.  See also the variable
-@code{org-clock-report-include-clocking-task}.
-
-@item @kbd{v c}
-@kindex v c
-@vindex org-agenda-clock-consistency-checks
-Show overlapping clock entries, clocking gaps, and other clocking
-problems in the current agenda range.  You can then visit clocking
-lines and fix them manually.  See the variable
-@code{org-agenda-clock-consistency-checks} for information on how to
-customize the definition of what constituted a clocking problem.  To
-return to normal agenda display, press @kbd{l} to exit Logbook
-mode.
-
-@item @kbd{v E} or short @kbd{E} (@code{org-agenda-entry-text-mode})
-@kindex v E
-@kindex E
-@findex org-agenda-entry-text-mode
-@vindex org-agenda-start-with-entry-text-mode
-@vindex org-agenda-entry-text-maxlines
-Toggle entry text mode.  In entry text mode, a number of lines from
-the Org outline node referenced by an agenda line are displayed
-below the line.  The maximum number of lines is given by the
-variable @code{org-agenda-entry-text-maxlines}.  Calling this command
-with a numeric prefix argument temporarily modifies that number to
-the prefix value.
-
-@item @kbd{G} (@code{org-agenda-toggle-time-grid})
-@kindex G
-@vindex org-agenda-use-time-grid
-@vindex org-agenda-time-grid
-Toggle the time grid on and off.  See also the variables
-@code{org-agenda-use-time-grid} and @code{org-agenda-time-grid}.
-
-@item @kbd{r} (@code{org-agenda-redo})
-@itemx @kbd{g}
-@kindex r
-@kindex g
-@findex org-agenda-redo
-Recreate the agenda buffer, for example to reflect the changes after
-modification of the timestamps of items with @kbd{S-@key{LEFT}} and
-@kbd{S-@key{RIGHT}}.  When the buffer is the global TODO list,
-a prefix argument is interpreted to create a selective list for
-a specific TODO keyword.
-
-@item @kbd{C-x C-s} or short @kbd{s} (@code{org-save-all-org-buffers})
-@kindex C-x C-s
-@findex org-save-all-org-buffers
-@kindex s
-Save all Org buffers in the current Emacs session, and also the
-locations of IDs.
-
-@item @kbd{C-c C-x C-c} (@code{org-agenda-columns})
-@kindex C-c C-x C-c
-@findex org-agenda-columns
-@vindex org-columns-default-format
-Invoke column view (see @ref{Column View}) in the agenda buffer.  The
-column view format is taken from the entry at point, or, if there is
-no entry at point, from the first entry in the agenda view.  So
-whatever the format for that entry would be in the original buffer
-(taken from a property, from a @samp{COLUMNS} keyword, or from the
-default variable @code{org-columns-default-format}) is used in the
-agenda.
-
-@item @kbd{C-c C-x >} (@code{org-agenda-remove-restriction-lock})
-@kindex C-c C-x >
-@findex org-agenda-remove-restriction-lock
-Remove the restriction lock on the agenda, if it is currently
-restricted to a file or subtree (see @ref{Agenda Files}).
-
-@item @kbd{M-@key{UP}} (@code{org-agenda-drag-line-backward})
-@kindex M-UP
-@findex org-agenda-drag-line-backward
-Drag the line at point backward one line.  With a numeric prefix
-argument, drag backward by that many lines.
-
-Moving agenda lines does not persist after an agenda refresh and
-does not modify the contributing Org files.
-
-@item @kbd{M-@key{DOWN}} (@code{org-agenda-drag-line-forward})
-@kindex M-DOWN
-@findex org-agenda-drag-line-forward
-Drag the line at point forward one line.  With a numeric prefix
-argument, drag forward by that many lines.
-@end table
-
-@anchor{Remote editing}
-@subheading Remote editing
-
-@cindex remote editing, from agenda
-
-@table @asis
-@item @kbd{0--9}
-Digit argument.
-
-@item @kbd{C-_} (@code{org-agenda-undo})
-@kindex C-_
-@findex org-agenda-undo
-@cindex undoing remote-editing events
-@cindex remote editing, undo
-Undo a change due to a remote editing command.  The change is undone
-both in the agenda buffer and in the remote buffer.
-
-@item @kbd{t} (@code{org-agenda-todo})
-@kindex t
-@findex org-agenda-todo
-Change the TODO state of the item, both in the agenda and in the
-original Org file.  A prefix arg is passed through to the @code{org-todo}
-command, so for example a @kbd{C-u} prefix are will trigger
-taking a note to document the state change.
-
-@item @kbd{C-S-@key{RIGHT}} (@code{org-agenda-todo-nextset})
-@kindex C-S-RIGHT
-@findex org-agenda-todo-nextset
-Switch to the next set of TODO keywords.
-
-@item @kbd{C-S-@key{LEFT}}, @code{org-agenda-todo-previousset}
-@kindex C-S-LEFT
-Switch to the previous set of TODO keywords.
-
-@item @kbd{C-k} (@code{org-agenda-kill})
-@kindex C-k
-@findex org-agenda-kill
-@vindex org-agenda-confirm-kill
-Delete the current agenda item along with the entire subtree
-belonging to it in the original Org file.  If the text to be deleted
-remotely is longer than one line, the kill needs to be confirmed by
-the user.  See variable @code{org-agenda-confirm-kill}.
-
-@item @kbd{C-c C-w} (@code{org-agenda-refile})
-@kindex C-c C-w
-@findex org-agenda-refile
-Refile the entry at point.
-
-@item @kbd{C-c C-x C-a} or short @kbd{a} 
(@code{org-agenda-archive-default-with-confirmation})
-@kindex C-c C-x C-a
-@kindex a
-@findex org-agenda-archive-default-with-confirmation
-@vindex org-archive-default-command
-Archive the subtree corresponding to the entry at point using the
-default archiving command set in @code{org-archive-default-command}.
-When using the @kbd{a} key, confirmation is required.
-
-@item @kbd{C-c C-x a} (@code{org-agenda-toggle-archive-tag})
-@kindex C-c C-x a
-@findex org-agenda-toggle-archive-tag
-Toggle the archive tag (see @ref{Internal archiving}) for the current
-headline.
-
-@item @kbd{C-c C-x A} (@code{org-agenda-archive-to-archive-sibling})
-@kindex C-c C-x A
-@findex org-agenda-archive-to-archive-sibling
-Move the subtree corresponding to the current entry to its @emph{archive
-sibling}.
-
-@item @kbd{C-c C-x C-s} or short @kbd{$} (@code{org-agenda-archive})
-@kindex C-c C-x C-s
-@kindex $
-@findex org-agenda-archive
-Archive the subtree corresponding to the current headline.  This
-means the entry is moved to the configured archive location, most
-likely a different file.
-
-@item @kbd{T} (@code{org-agenda-show-tags})
-@kindex T
-@findex org-agenda-show-tags
-@vindex org-agenda-show-inherited-tags
-Show all tags associated with the current item.  This is useful if
-you have turned off @code{org-agenda-show-inherited-tags}, but still want
-to see all tags of a headline occasionally.
-
-@item @kbd{:} (@code{org-agenda-set-tags})
-@kindex :
-@findex org-agenda-set-tags
-Set tags for the current headline.  If there is an active region in
-the agenda, change a tag for all headings in the region.
-
-@item @kbd{,} (@code{org-agenda-priority})
-@kindex ,
-@findex org-agenda-priority
-Set the priority for the current item.  Org mode prompts for the
-priority character.  If you reply with @kbd{@key{SPC}}, the priority
-cookie is removed from the entry.
-
-@item @kbd{+} or @kbd{S-@key{UP}} (@code{org-agenda-priority-up})
-@kindex +
-@kindex S-UP
-@findex org-agenda-priority-up
-Increase the priority of the current item.  The priority is changed
-in the original buffer, but the agenda is not resorted.  Use the
-@kbd{r} key for this.
-
-@item @kbd{-} or @kbd{S-@key{DOWN}} (@code{org-agenda-priority-down})
-@kindex -
-@kindex S-DOWN
-@findex org-agenda-priority-down
-Decrease the priority of the current item.
-
-@item @kbd{C-c C-x e} or short @kbd{e} (@code{org-agenda-set-effort})
-@kindex e
-@kindex C-c C-x e
-@findex org-agenda-set-effort
-Set the effort property for the current item.
-
-@item @kbd{C-c C-z} or short @kbd{z} (@code{org-agenda-add-note})
-@kindex z
-@kindex C-c C-z
-@findex org-agenda-add-note
-@vindex org-log-into-drawer
-Add a note to the entry.  This note is recorded, and then filed to
-the same location where state change notes are put.  Depending on
-@code{org-log-into-drawer}, this may be inside a drawer.
-
-@item @kbd{C-c C-a} (@code{org-attach})
-@kindex C-c C-a
-@findex org-attach
-Dispatcher for all command related to attachments.
-
-@item @kbd{C-c C-s} (@code{org-agenda-schedule})
-@kindex C-c C-s
-@findex org-agenda-schedule
-Schedule this item.  With a prefix argument, remove the
-scheduling timestamp
-
-@item @kbd{C-c C-d} (@code{org-agenda-deadline})
-@kindex C-c C-d
-@findex org-agenda-deadline
-Set a deadline for this item.  With a prefix argument, remove the
-deadline.
-
-@item @kbd{S-@key{RIGHT}} (@code{org-agenda-do-date-later})
-@kindex S-RIGHT
-@findex org-agenda-do-date-later
-Change the timestamp associated with the current line by one day
-into the future.  If the date is in the past, the first call to this
-command moves it to today.  With a numeric prefix argument, change
-it by that many days.  For example, @kbd{3 6 5 S-@key{RIGHT}} changes
-it by a year.  With a @kbd{C-u} prefix, change the time by one
-hour.  If you immediately repeat the command, it will continue to
-change hours even without the prefix argument.  With a double
-@kbd{C-u C-u} prefix, do the same for changing minutes.  The
-stamp is changed in the original Org file, but the change is not
-directly reflected in the agenda buffer.  Use @kbd{r} or
-@kbd{g} to update the buffer.
-
-@item @kbd{S-@key{LEFT}} (@code{org-agenda-do-date-earlier})
-@kindex S-LEFT
-@findex org-agenda-do-date-earlier
-Change the timestamp associated with the current line by one day
-into the past.
-
-@item @kbd{>} (@code{org-agenda-date-prompt})
-@kindex >
-@findex org-agenda-date-prompt
-Change the timestamp associated with the current line.  The key
-@kbd{>} has been chosen, because it is the same as
-@kbd{S-.}  on my keyboard.
-
-@item @kbd{I} (@code{org-agenda-clock-in})
-@kindex I
-@findex org-agenda-clock-in
-Start the clock on the current item.  If a clock is running already,
-it is stopped first.
-
-@item @kbd{O} (@code{org-agenda-clock-out})
-@kindex O
-@findex org-agenda-clock-out
-Stop the previously started clock.
-
-@item @kbd{X} (@code{org-agenda-clock-cancel})
-@kindex X
-@findex org-agenda-clock-cancel
-Cancel the currently running clock.
-
-@item @kbd{J} (@code{org-agenda-clock-goto})
-@kindex J
-@findex org-agenda-clock-goto
-Jump to the running clock in another window.
-
-@item @kbd{k} (@code{org-agenda-capture})
-@kindex k
-@findex org-agenda-capture
-@cindex capturing, from agenda
-@vindex org-capture-use-agenda-date
-Like @code{org-capture}, but use the date at point as the default date
-for the capture template.  See @code{org-capture-use-agenda-date} to make
-this the default behavior of @code{org-capture}.
-@end table
-
-@anchor{Bulk remote editing selected entries}
-@subheading Bulk remote editing selected entries
-
-@cindex remote editing, bulk, from agenda
-@vindex org-agenda-bulk-custom-functions
-
-@table @asis
-@item @kbd{m} (@code{org-agenda-bulk-mark})
-@kindex m
-@findex org-agenda-bulk-mark
-
-Mark the entry at point for bulk action.  If there is an active
-region in the agenda, mark the entries in the region.  With numeric
-prefix argument, mark that many successive entries.
-
-@item @kbd{*} (@code{org-agenda-bulk-mark-all})
-@kindex *
-@findex org-agenda-bulk-mark-all
-
-Mark all visible agenda entries for bulk action.
-
-@item @kbd{u} (@code{org-agenda-bulk-unmark})
-@kindex u
-@findex org-agenda-bulk-unmark
-
-Unmark entry for bulk action.
-
-@item @kbd{U} (@code{org-agenda-bulk-remove-all-marks})
-@kindex U
-@findex org-agenda-bulk-remove-all-marks
-
-Unmark all marked entries for bulk action.
-
-@item @kbd{M-m} (@code{org-agenda-bulk-toggle})
-@kindex M-m
-@findex org-agenda-bulk-toggle
-
-Toggle mark of the entry at point for bulk action.
-
-@item @kbd{M-*} (@code{org-agenda-bulk-toggle-all})
-@kindex M-*
-@findex org-agenda-bulk-toggle-all
-
-Toggle mark of every entry for bulk action.
-
-@item @kbd{%} (@code{org-agenda-bulk-mark-regexp})
-@kindex %
-@findex org-agenda-bulk-mark-regexp
-
-Mark entries matching a regular expression for bulk action.
-
-@item @kbd{B} (@code{org-agenda-bulk-action})
-@kindex B
-@findex org-agenda-bulk-action
-@vindex org-agenda-bulk-persistent-marks
-
-Bulk action: act on all marked entries in the agenda.  This prompts
-for another key to select the action to be applied.  The prefix
-argument to @kbd{B} is passed through to the @kbd{s} and
-@kbd{d} commands, to bulk-remove these special timestamps.  By
-default, marks are removed after the bulk.  If you want them to
-persist, set @code{org-agenda-bulk-persistent-marks} to @code{t} or hit
-@kbd{p} at the prompt.
-
-@table @asis
-@item @kbd{p}
-Toggle persistent marks.
-
-@item @kbd{$}
-Archive all selected entries.
-
-@item @kbd{A}
-Archive entries by moving them to their respective archive
-siblings.
-
-@item @kbd{t}
-Change TODO state.  This prompts for a single TODO keyword and
-changes the state of all selected entries, bypassing blocking and
-suppressing logging notes---but not timestamps.
-
-@item @kbd{+}
-Add a tag to all selected entries.
-
-@item @kbd{-}
-Remove a tag from all selected entries.
-
-@item @kbd{s}
-Schedule all items to a new date.  To shift existing schedule
-dates by a fixed number of days, use something starting with
-double plus at the prompt, for example @samp{++8d} or @samp{++2w}.
-
-@item @kbd{d}
-Set deadline to a specific date.
-
-@item @kbd{r}
-Prompt for a single refile target and move all entries.  The
-entries are no longer in the agenda; refresh (@kbd{g}) to
-bring them back.
-
-@item @kbd{S}
-Reschedule randomly into the coming N days.  N is prompted for.
-With a prefix argument (@kbd{C-u B S}), scatter only across
-weekdays.
-
-@item @kbd{f}
-@vindex org-agenda-bulk-custom-functions
-Apply a function@footnote{You can also create persistent custom functions 
through
-@code{org-agenda-bulk-custom-functions}.} to marked entries.  For example, the
-function below sets the @samp{CATEGORY} property of the entries to
-@samp{web}.
-
-@lisp
-(defun set-category ()
-  (interactive "P")
-  (let ((marker (or (org-get-at-bol 'org-hd-marker)
-                    (org-agenda-error))))
-    (org-with-point-at marker
-      (org-back-to-heading t)
-      (org-set-property "CATEGORY" "web"))))
-@end lisp
-@end table
-@end table
-
-@anchor{Calendar commands}
-@subheading Calendar commands
-
-@cindex calendar commands, from agenda
-
-@table @asis
-@item @kbd{c} (@code{org-agenda-goto-calendar})
-@kindex c
-@findex org-agenda-goto-calendar
-Open the Emacs calendar and go to the date at point in the agenda.
-
-@item @kbd{c} (@code{org-calendar-goto-agenda})
-@kindex c
-@findex org-calendar-goto-agenda
-When in the calendar, compute and show the Org agenda for the date
-at point.
-
-@item @kbd{i} (@code{org-agenda-diary-entry})
-@kindex i
-@findex org-agenda-diary-entry
-
-@cindex diary entries, creating from agenda
-Insert a new entry into the diary, using the date at point and (for
-block entries) the date at the mark.  This adds to the Emacs diary
-file@footnote{This file is parsed for the agenda when
-@code{org-agenda-include-diary} is set.}, in a way similar to the @kbd{i} 
command in the
-calendar.  The diary file pops up in another window, where you can
-add the entry.
-
-@vindex org-agenda-diary-file
-If you configure @code{org-agenda-diary-file} to point to an Org file,
-Org creates entries in that file instead.  Most entries are stored
-in a date-based outline tree that will later make it easy to archive
-appointments from previous months/years.  The tree is built under an
-entry with a @samp{DATE_TREE} property, or else with years as top-level
-entries.  Emacs prompts you for the entry text---if you specify it,
-the entry is created in @code{org-agenda-diary-file} without further
-interaction.  If you directly press @kbd{@key{RET}} at the prompt
-without typing text, the target file is shown in another window for
-you to finish the entry there.  See also the @kbd{k r} command.
-
-@item @kbd{M} (@code{org-agenda-phases-of-moon})
-@kindex M
-@findex org-agenda-phases-of-moon
-Show the phases of the moon for the three months around current
-date.
-
-@item @kbd{S} (@code{org-agenda-sunrise-sunset})
-@kindex S
-@findex org-agenda-sunrise-sunset
-Show sunrise and sunset times.  The geographical location must be
-set with calendar variables, see the documentation for the Emacs
-calendar.
-
-@item @kbd{C} (@code{org-agenda-convert-date})
-@kindex C
-@findex org-agenda-convert-date
-Convert the date at point into many other cultural and historic
-calendars.
-
-@item @kbd{H} (@code{org-agenda-holidays})
-@kindex H
-@findex org-agenda-holidays
-Show holidays for three months around point date.
-@end table
-
-@anchor{Quit and exit}
-@subheading Quit and exit
-
-@table @asis
-@item @kbd{q} (@code{org-agenda-quit})
-@kindex q
-@findex org-agenda-quit
-
-Quit agenda, remove the agenda buffer.
-
-@item @kbd{x} (@code{org-agenda-exit})
-@kindex x
-@findex org-agenda-exit
-
-@cindex agenda files, removing buffers
-Exit agenda, remove the agenda buffer and all buffers loaded by
-Emacs for the compilation of the agenda.  Buffers created by the
-user to visit Org files are not removed.
-@end table
-
-@node Custom Agenda Views
-@section Custom Agenda Views
-
-@cindex custom agenda views
-@cindex agenda views, custom
-
-Custom agenda commands serve two purposes: to store and quickly access
-frequently used TODO and tags searches, and to create special
-composite agenda buffers.  Custom agenda commands are accessible
-through the dispatcher (see @ref{Agenda Dispatcher}), just like the
-default commands.
-
-@menu
-* Storing searches::             Type once, use often.
-* Block agenda::                 All the stuff you need in a single buffer.
-* Setting options::              Changing the rules.
-@end menu
-
-@node Storing searches
-@subsection Storing searches
-
-The first application of custom searches is the definition of keyboard
-shortcuts for frequently used searches, either creating an agenda
-buffer, or a sparse tree (the latter covering of course only the
-current buffer).
-
-@kindex C @r{(Agenda dispatcher)}
-@vindex org-agenda-custom-commands
-@cindex agenda views, main example
-@cindex agenda, as an agenda views
-@cindex agenda*, as an agenda views
-@cindex tags, as an agenda view
-@cindex todo, as an agenda view
-@cindex tags-todo
-@cindex todo-tree
-@cindex occur-tree
-@cindex tags-tree
-Custom commands are configured in the variable
-@code{org-agenda-custom-commands}.  You can customize this variable, for
-example by pressing @kbd{C} from the agenda dispatcher (see @ref{Agenda 
Dispatcher}).  You can also directly set it with Emacs Lisp in
-the Emacs init file.  The following example contains all valid agenda
-views:
-
-@lisp
-(setq org-agenda-custom-commands
-      '(("x" agenda)
-        ("y" agenda*)
-        ("w" todo "WAITING")
-        ("W" todo-tree "WAITING")
-        ("u" tags "+boss-urgent")
-        ("v" tags-todo "+boss-urgent")
-        ("U" tags-tree "+boss-urgent")
-        ("f" occur-tree "\\<FIXME\\>")
-        ("h" . "HOME+Name tags searches") ;description for "h" prefix
-        ("hl" tags "+home+Lisa")
-        ("hp" tags "+home+Peter")
-        ("hk" tags "+home+Kim")))
-@end lisp
-
-The initial string in each entry defines the keys you have to press
-after the dispatcher command in order to access the command.  Usually
-this is just a single character, but if you have many similar
-commands, you can also define two-letter combinations where the first
-character is the same in several combinations and serves as a prefix
-key@footnote{You can provide a description for a prefix key by inserting
-a cons cell with the prefix and the description.}.  The second parameter is 
the search type, followed by the
-string or regular expression to be used for the matching.  The example
-above will therefore define:
-
-@table @asis
-@item @kbd{x}
-as a global search for agenda entries planned@footnote{@emph{Planned} means 
here that these entries have some planning
-information attached to them, like a time-stamp, a scheduled or
-a deadline string.  See @code{org-agenda-entry-types} on how to set what
-planning information is taken into account.} this week/day.
-
-@item @kbd{y}
-as the same search, but only for entries with an hour specification
-like @samp{[h]h:mm}---think of them as appointments.
-
-@item @kbd{w}
-as a global search for TODO entries with @samp{WAITING} as the TODO
-keyword.
-
-@item @kbd{W}
-as the same search, but only in the current buffer and displaying
-the results as a sparse tree.
-
-@item @kbd{u}
-as a global tags search for headlines tagged @samp{boss} but not
-@samp{urgent}.
-
-@item @kbd{v}
-The same search, but limiting it to headlines that are also TODO
-items.
-
-@item @kbd{U}
-as the same search, but only in the current buffer and displaying
-the result as a sparse tree.
-
-@item @kbd{f}
-to create a sparse tree (again, current buffer only) with all
-entries containing the word @samp{FIXME}.
-
-@item @kbd{h}
-as a prefix command for a @samp{HOME} tags search where you have to press
-an additional key (@kbd{l}, @kbd{p} or @kbd{k}) to
-select a name (Lisa, Peter, or Kim) as additional tag to match.
-@end table
-
-Note that @code{*-tree} agenda views need to be called from an Org buffer
-as they operate on the current buffer only.
-
-@node Block agenda
-@subsection Block agenda
-
-@cindex block agenda
-@cindex agenda, with block views
-
-Another possibility is the construction of agenda views that comprise
-the results of @emph{several} commands, each of which creates a block in
-the agenda buffer.  The available commands include @code{agenda} for the
-daily or weekly agenda (as created with @kbd{a}) , @code{alltodo} for
-the global TODO list (as constructed with @kbd{t}), @code{stuck} for
-the list of stuck projects (as obtained with @kbd{#}) and the
-matching commands discussed above: @code{todo}, @code{tags}, and 
@code{tags-todo}.
-
-Here are two examples:
-
-@lisp
-(setq org-agenda-custom-commands
-      '(("h" "Agenda and Home-related tasks"
-         ((agenda "")
-          (tags-todo "home")
-          (tags "garden")))
-        ("o" "Agenda and Office-related tasks"
-         ((agenda "")
-          (tags-todo "work")
-          (tags "office")))))
-@end lisp
-
-@noindent
-This defines @kbd{h} to create a multi-block view for stuff you
-need to attend to at home.  The resulting agenda buffer contains your
-agenda for the current week, all TODO items that carry the tag @samp{home},
-and also all lines tagged with @samp{garden}.  Finally the command
-@kbd{o} provides a similar view for office tasks.
-
-@node Setting options
-@subsection Setting options for custom commands
-
-@cindex options, for custom agenda views
-
-@vindex org-agenda-custom-commands
-Org mode contains a number of variables regulating agenda construction
-and display.  The global variables define the behavior for all agenda
-commands, including the custom commands.  However, if you want to
-change some settings just for a single custom view, you can do so.
-Setting options requires inserting a list of variable names and values
-at the right spot in @code{org-agenda-custom-commands}.  For example:
-
-@lisp
-(setq org-agenda-custom-commands
-      '(("w" todo "WAITING"
-         ((org-agenda-sorting-strategy '(priority-down))
-          (org-agenda-prefix-format "  Mixed: ")))
-        ("U" tags-tree "+boss-urgent"
-         ((org-show-context-detail 'minimal)))
-        ("N" search ""
-         ((org-agenda-files '("~org/notes.org"))
-          (org-agenda-text-search-extra-files nil)))))
-@end lisp
-
-@noindent
-Now the @kbd{w} command sorts the collected entries only by
-priority, and the prefix format is modified to just say @samp{Mixed:}
-instead of giving the category of the entry.  The sparse tags tree of
-@kbd{U} now turns out ultra-compact, because neither the headline
-hierarchy above the match, nor the headline following the match are
-shown.  The command @kbd{N} does a text search limited to only
-a single file.
-
-For command sets creating a block agenda, @code{org-agenda-custom-commands}
-has two separate spots for setting options.  You can add options that
-should be valid for just a single command in the set, and options that
-should be valid for all commands in the set.  The former are just
-added to the command entry; the latter must come after the list of
-command entries.  Going back to the block agenda example (see @ref{Block 
agenda}), let's change the sorting strategy for the @kbd{h}
-commands to @code{priority-down}, but let's sort the results for @samp{garden}
-tags query in the opposite order, @code{priority-up}.  This would look like
-this:
-
-@lisp
-(setq org-agenda-custom-commands
-      '(("h" "Agenda and Home-related tasks"
-         ((agenda)
-          (tags-todo "home")
-          (tags "garden"
-                ((org-agenda-sorting-strategy '(priority-up)))))
-         ((org-agenda-sorting-strategy '(priority-down))))
-        ("o" "Agenda and Office-related tasks"
-         ((agenda)
-          (tags-todo "work")
-          (tags "office")))))
-@end lisp
-
-As you see, the values and parentheses setting is a little complex.
-When in doubt, use the customize interface to set this variable---it
-fully supports its structure.  Just one caveat: when setting options
-in this interface, the @emph{values} are just Lisp expressions.  So if the
-value is a string, you need to add the double-quotes around the value
-yourself.
-
-@vindex org-agenda-custom-commands-contexts
-To control whether an agenda command should be accessible from
-a specific context, you can customize
-@code{org-agenda-custom-commands-contexts}.  Let's say for example that you
-have an agenda command @kbd{o} displaying a view that you only
-need when reading emails.  Then you would configure this option like
-this:
-
-@lisp
-(setq org-agenda-custom-commands-contexts
-      '(("o" (in-mode . "message-mode"))))
-@end lisp
-
-You can also tell that the command key @kbd{o} should refer to
-another command key @kbd{r}.  In that case, add this command key
-like this:
-
-@lisp
-(setq org-agenda-custom-commands-contexts
-      '(("o" "r" (in-mode . "message-mode"))))
-@end lisp
-
-See the docstring of the variable for more information.
-
-@node Exporting Agenda Views
-@section Exporting Agenda Views
-
-@cindex agenda views, exporting
-
-If you are away from your computer, it can be very useful to have
-a printed version of some agenda views to carry around.  Org mode can
-export custom agenda views as plain text, HTML@footnote{For HTML you need to 
install Hrvoje Nikšić's @samp{htmlize.el}
-as an Emacs package from MELPA or from 
@uref{https://github.com/hniksic/emacs-htmlize, Hrvoje Nikšić's repository}.}, 
Postscript,
-PDF@footnote{To create PDF output, the Ghostscript ps2pdf utility must be
-installed on the system.  Selecting a PDF file also creates the
-postscript file.}, and iCalendar files.  If you want to do this only
-occasionally, use the following command:
-
-@table @asis
-@item @kbd{C-x C-w} (@code{org-agenda-write})
-@kindex C-x C-w
-@findex org-agenda-write
-@cindex exporting agenda views
-@cindex agenda views, exporting
-
-@vindex org-agenda-exporter-settings
-Write the agenda view to a file.
-@end table
-
-If you need to export certain agenda views frequently, you can
-associate any custom agenda command with a list of output file
-names@footnote{If you want to store standard views like the weekly agenda or
-the global TODO list as well, you need to define custom commands for
-them in order to be able to specify file names.}.  Here is an example that 
first defines custom commands
-for the agenda and the global TODO list, together with a number of
-files to which to export them.  Then we define two block agenda
-commands and specify file names for them as well.  File names can be
-relative to the current working directory, or absolute.
-
-@lisp
-(setq org-agenda-custom-commands
-      '(("X" agenda "" nil ("agenda.html" "agenda.ps"))
-        ("Y" alltodo "" nil ("todo.html" "todo.txt" "todo.ps"))
-        ("h" "Agenda and Home-related tasks"
-         ((agenda "")
-          (tags-todo "home")
-          (tags "garden"))
-         nil
-         ("~/views/home.html"))
-        ("o" "Agenda and Office-related tasks"
-         ((agenda)
-          (tags-todo "work")
-          (tags "office"))
-         nil
-         ("~/views/office.ps" "~/calendars/office.ics"))))
-@end lisp
-
-The extension of the file name determines the type of export.  If it
-is @samp{.html}, Org mode uses the htmlize package to convert the buffer to
-HTML and save it to this file name.  If the extension is @samp{.ps},
-@code{ps-print-buffer-with-faces} is used to produce Postscript output.  If
-the extension is @samp{.ics}, iCalendar export is run export over all files
-that were used to construct the agenda, and limit the export to
-entries listed in the agenda.  Any other extension produces a plain
-ASCII file.
-
-The export files are @emph{not} created when you use one of those
-commands interactively because this might use too much overhead.
-Instead, there is a special command to produce @emph{all} specified
-files in one step:
-
-@table @asis
-@item @kbd{e} (@code{org-store-agenda-views})
-@kindex e @r{(Agenda dispatcher)}
-@findex org-store-agenda-views
-Export all agenda views that have export file names associated with
-them.
-@end table
-
-You can use the options section of the custom agenda commands to also
-set options for the export commands.  For example:
-
-@lisp
-(setq org-agenda-custom-commands
-      '(("X" agenda ""
-         ((ps-number-of-columns 2)
-          (ps-landscape-mode t)
-          (org-agenda-prefix-format " [ ] ")
-          (org-agenda-with-colors nil)
-          (org-agenda-remove-tags t))
-         ("theagenda.ps"))))
-@end lisp
-
-@noindent
-@vindex org-agenda-exporter-settings
-This command sets two options for the Postscript exporter, to make it
-print in two columns in landscape format---the resulting page can be
-cut in two and then used in a paper agenda.  The remaining settings
-modify the agenda prefix to omit category and scheduling information,
-and instead include a checkbox to check off items.  We also remove the
-tags to make the lines compact, and we do not want to use colors for
-the black-and-white printer.  Settings specified in
-@code{org-agenda-exporter-settings} also apply, e.g.,
-
-@lisp
-(setq org-agenda-exporter-settings
-      '((ps-number-of-columns 2)
-        (ps-landscape-mode t)
-        (org-agenda-add-entry-text-maxlines 5)
-        (htmlize-output-type 'css)))
-@end lisp
-
-@noindent
-but the settings in @code{org-agenda-custom-commands} take precedence.
-
-From the command line you may also use:
-
-@example
-emacs -eval (org-batch-store-agenda-views) -kill
-@end example
-
-@noindent
-or, if you need to modify some parameters@footnote{Quoting depends on the 
system you use, please check the FAQ
-for examples.}
-
-@example
-emacs -eval '(org-batch-store-agenda-views                      \
-              org-agenda-span (quote month)                     \
-              org-agenda-start-day "2007-11-01"                 \
-              org-agenda-include-diary nil                      \
-              org-agenda-files (quote ("~/org/project.org")))'  \
-      -kill
-@end example
-
-@noindent
-which creates the agenda views restricted to the file
-@samp{~/org/project.org}, without diary entries and with a 30-day extent.
-
-You can also extract agenda information in a way that allows further
-processing by other programs.  See @ref{Extracting Agenda Information}, for
-more information.
-
-@node Agenda Column View
-@section Using Column View in the Agenda
-
-@cindex column view, in agenda
-@cindex agenda, column view
-
-Column view (see @ref{Column View}) is normally used to view and edit
-properties embedded in the hierarchical structure of an Org file.  It
-can be quite useful to use column view also from the agenda, where
-entries are collected by certain criteria.
-
-@table @asis
-@item @kbd{C-c C-x C-c} (@code{org-agenda-columns})
-@kindex C-c C-x C-c
-@findex org-agenda-columns
-
-Turn on column view in the agenda.
-@end table
-
-To understand how to use this properly, it is important to realize
-that the entries in the agenda are no longer in their proper outline
-environment.  This causes the following issues:
-
-@enumerate
-@item
-@vindex org-columns-default-format-for-agenda
-@vindex org-columns-default-format
-Org needs to make a decision which columns format to use.  Since
-the entries in the agenda are collected from different files, and
-different files may have different columns formats, this is a
-non-trivial problem.  Org first checks if
-@code{org-overriding-columns-format} is currently set, and if so, takes
-the format from there.  You should set this variable only in the
-@emph{local settings section} of a custom agenda command (see @ref{Custom 
Agenda Views}) to make it valid for that specific agenda view.  If
-no such binding exists, it checks, in sequence,
-@code{org-columns-default-format-for-agenda}, the format associated with
-the first item in the agenda (through a property or a @samp{#+COLUMNS}
-setting in that buffer) and finally @code{org-columns-default-format}.
-
-@item
-@cindex @samp{CLOCKSUM}, special property
-If any of the columns has a summary type defined (see @ref{Column 
attributes}), turning on column view in the agenda visits all
-relevant agenda files and make sure that the computations of this
-property are up to date.  This is also true for the special
-@samp{CLOCKSUM} property.  Org then sums the values displayed in the
-agenda.  In the daily/weekly agenda, the sums cover a single day;
-in all other views they cover the entire block.
-
-It is important to realize that the agenda may show the same entry
-@emph{twice}---for example as scheduled and as a deadline---and it may
-show two entries from the same hierarchy (for example a @emph{parent}
-and its @emph{child}).  In these cases, the summation in the agenda
-leads to incorrect results because some values count double.
-
-@item
-When the column view in the agenda shows the @samp{CLOCKSUM} property,
-that is always the entire clocked time for this item.  So even in
-the daily/weekly agenda, the clocksum listed in column view may
-originate from times outside the current view.  This has the
-advantage that you can compare these values with a column listing
-the planned total effort for a task---one of the major
-applications for column view in the agenda.  If you want
-information about clocked time in the displayed period use clock
-table mode (press @kbd{R} in the agenda).
-
-@item
-@cindex @samp{CLOCKSUM_T}, special property
-When the column view in the agenda shows the @samp{CLOCKSUM_T} property,
-that is always today's clocked time for this item.  So even in the
-weekly agenda, the clocksum listed in column view only originates
-from today.  This lets you compare the time you spent on a task for
-today, with the time already spent---via @samp{CLOCKSUM}---and with
-the planned total effort for it.
-@end enumerate
-
-@node Markup for Rich Contents
-@chapter Markup for Rich Contents
-
-Org is primarily about organizing and searching through your
-plain-text notes.  However, it also provides a lightweight yet robust
-markup language for rich text formatting and more.  For instance, you
-may want to center or emphasize text.  Or you may need to insert
-a formula or image in your writing.  Org offers syntax for all of this
-and more.  Used in conjunction with the export framework (see
-@ref{Exporting}), you can author beautiful documents in Org---like the fine
-manual you are currently reading.
-
-@menu
-* Paragraphs::                   The basic unit of text.
-* Emphasis and Monospace::       Bold, italic, etc.
-* Subscripts and Superscripts::  Simple syntax for raising/lowering text.
-* Special Symbols::              Greek letters and other symbols.
-* Embedded @LaTeX{}::            LaTeX can be freely used inside Org documents.
-* Literal Examples::             Source code examples with special formatting.
-* Images::                       Display an image.
-* Captions::                     Describe tables, images...
-* Horizontal Rules::             Make a line.
-* Creating Footnotes::           Edit and read footnotes.
-@end menu
-
-@node Paragraphs
-@section Paragraphs
-
-@cindex paragraphs, markup rules
-Paragraphs are separated by at least one empty line.  If you need to
-enforce a line break within a paragraph, use @samp{\\} at the end of
-a line.
-
-@cindex line breaks, markup rules
-To preserve the line breaks, indentation and blank lines in a region,
-but otherwise use normal formatting, you can use this construct, which
-can also be used to format poetry.
-
-@cindex @samp{BEGIN_VERSE}
-@cindex verse blocks
-@example
-#+BEGIN_VERSE
- Great clouds overhead
- Tiny black birds rise and fall
- Snow covers Emacs
-
-    ---AlexSchroeder
-#+END_VERSE
-@end example
-
-When quoting a passage from another document, it is customary to
-format this as a paragraph that is indented on both the left and the
-right margin.  You can include quotations in Org documents like this:
-
-@cindex @samp{BEGIN_QUOTE}
-@cindex quote blocks
-@example
-#+BEGIN_QUOTE
-Everything should be made as simple as possible,
-but not any simpler ---Albert Einstein
-#+END_QUOTE
-@end example
-
-If you would like to center some text, do it like this:
-
-@cindex @samp{BEGIN_CENTER}
-@cindex center blocks
-@example
-#+BEGIN_CENTER
-Everything should be made as simple as possible, \\
-but not any simpler
-#+END_CENTER
-@end example
-
-@node Emphasis and Monospace
-@section Emphasis and Monospace
-
-@cindex underlined text, markup rules
-@cindex bold text, markup rules
-@cindex italic text, markup rules
-@cindex verbatim text, markup rules
-@cindex code text, markup rules
-@cindex strike-through text, markup rules
-
-You can make words @samp{*bold*}, @samp{/italic/}, @samp{_underlined_}, 
@samp{=verbatim=}
-and @samp{~code~}, and, if you must, @samp{+strike-through+}.  Text in the code
-and verbatim string is not processed for Org specific syntax; it is
-exported verbatim.
-
-@vindex org-fontify-emphasized-text
-To turn off fontification for marked up text, you can set
-@code{org-fontify-emphasized-text} to @code{nil}.  To narrow down the list of
-available markup syntax, you can customize @code{org-emphasis-alist}.
-
-@node Subscripts and Superscripts
-@section Subscripts and Superscripts
-
-@cindex subscript
-@cindex superscript
-
-@samp{^} and @samp{_} are used to indicate super- and subscripts.  To increase
-the readability of ASCII text, it is not necessary, but OK, to
-surround multi-character sub- and superscripts with curly braces.  For
-example
-
-@example
-The radius of the sun is R_sun = 6.96 x 10^8 m.  On the other hand,
-the radius of Alpha Centauri is R_@{Alpha Centauri@} = 1.28 x R_@{sun@}.
-@end example
-
-@vindex org-use-sub-superscripts
-If you write a text where the underscore is often used in a different
-context, Org's convention to always interpret these as subscripts can
-get in your way.  Configure the variable @code{org-use-sub-superscripts} to
-change this convention.  For example, when setting this variable to
-@code{@{@}}, @samp{a_b} is not interpreted as a subscript, but @samp{a_@{b@}} 
is.
-
-You can set @code{org-use-sub-superscripts} in a file using the export
-option @samp{^:} (see @ref{Export Settings}).  For example, @samp{#+OPTIONS: 
^:@{@}}
-sets @code{org-use-sub-superscripts} to @code{@{@}} and limits super- and
-subscripts to the curly bracket notation.
-
-You can also toggle the visual display of super- and subscripts:
-
-@table @asis
-@item @kbd{C-c C-x \} (@code{org-toggle-pretty-entities})
-@kindex C-c C-x \
-@findex org-toggle-pretty-entities
-This command formats sub- and superscripts in a WYSIWYM way.
-@end table
-
-@vindex org-pretty-entities
-@vindex org-pretty-entities-include-sub-superscripts
-Set both @code{org-pretty-entities} and
-@code{org-pretty-entities-include-sub-superscripts} to @code{t} to start with
-super- and subscripts @emph{visually} interpreted as specified by the
-option @code{org-use-sub-superscripts}.
-
-@node Special Symbols
-@section Special Symbols
-
-@cindex math symbols
-@cindex special symbols
-@cindex entities
-
-You can use @LaTeX{}-like syntax to insert special symbols---named
-entities---like @samp{\alpha} to indicate the Greek letter, or @samp{\to} to 
indicate
-an arrow.  Completion for these symbols is available, just type @samp{\}
-and maybe a few letters, and press @kbd{M-@key{TAB}} to see possible
-completions.  If you need such a symbol inside a word, terminate it
-with a pair of curly brackets.  For example
-
-@example
-Pro tip: Given a circle \Gamma of diameter d, the length of its
-circumference is \pi@{@}d.
-@end example
-
-@findex org-entities-help
-@vindex org-entities-user
-A large number of entities is provided, with names taken from both
-HTML and @LaTeX{}; you can comfortably browse the complete list from
-a dedicated buffer using the command @code{org-entities-help}.  It is also
-possible to provide your own special symbols in the variable
-@code{org-entities-user}.
-
-During export, these symbols are transformed into the native format of
-the exporter back-end.  Strings like @samp{\alpha} are exported as 
@samp{&alpha;} in
-the HTML output, and as @samp{\(\alpha\)} in the @LaTeX{} output.  Similarly, 
@samp{\nbsp}
-becomes @samp{&nbsp;} in HTML and @samp{~} in @LaTeX{}.
-
-@cindex special symbols, in-buffer display
-If you would like to see entities displayed as UTF-8 characters, use
-the following command@footnote{You can turn this on by default by setting the 
variable
-@code{org-pretty-entities}, or on a per-file base with the @samp{STARTUP} 
option
-@samp{entitiespretty}.}:
-
-@table @asis
-@item @kbd{C-c C-x \} (@code{org-toggle-pretty-entities})
-@kindex C-c C-x \
-@findex org-toggle-pretty-entities
-
-Toggle display of entities as UTF-8 characters.  This does not
-change the buffer content which remains plain ASCII, but it overlays
-the UTF-8 character for display purposes only.
-@end table
-
-@cindex shy hyphen, special symbol
-@cindex dash, special symbol
-@cindex ellipsis, special symbol
-In addition to regular entities defined above, Org exports in
-a special way@footnote{This behavior can be disabled with @samp{-} export 
setting (see
-@ref{Export Settings}).} the following commonly used character
-combinations: @samp{\-} is treated as a shy hyphen, @samp{--} and @samp{---} 
are
-converted into dashes, and @samp{...} becomes a compact set of dots.
-
-@node Embedded @LaTeX{}
-@section Embedded @LaTeX{}
-
-@cindex @TeX{} interpretation
-@cindex @LaTeX{} interpretation
-
-Plain ASCII is normally sufficient for almost all note taking.
-Exceptions include scientific notes, which often require mathematical
-symbols and the occasional formula.  @LaTeX{}@footnote{@LaTeX{} is a macro 
system based on Donald@tie{}E@.@tie{}Knuth's @TeX{}
-system.  Many of the features described here as ``@LaTeX{}'' are really
-from @TeX{}, but for simplicity I am blurring this distinction.} is widely 
used to
-typeset scientific documents.  Org mode supports embedding @LaTeX{} code
-into its files, because many academics are used to writing and reading
-@LaTeX{} source code, and because it can be readily processed to produce
-pretty output for a number of export back-ends.
-
-@menu
-* @LaTeX{} fragments::           Complex formulas made easy.
-* Previewing @LaTeX{} fragments:: What will this snippet look like?
-* CD@LaTeX{} mode::              Speed up entering of formulas.
-@end menu
-
-@node @LaTeX{} fragments
-@subsection @LaTeX{} fragments
-
-@cindex @LaTeX{} fragments
-
-@vindex org-format-latex-header
-Org mode can contain @LaTeX{} math fragments, and it supports ways to
-process these for several export back-ends.  When exporting to @LaTeX{},
-the code is left as it is.  When exporting to HTML, Org can use either
-@uref{http://www.mathjax.org, MathJax} (see @ref{Math formatting in HTML 
export}) or transcode the math
-into images (see @ref{Previewing @LaTeX{} fragments}).
-
-@LaTeX{} fragments do not need any special marking at all.  The following
-snippets are identified as @LaTeX{} source code:
-
-@itemize
-@item
-Environments of any kind@footnote{When MathJax is used, only the environments 
recognized by
-MathJax are processed.  When dvipng, dvisvgm, or ImageMagick suite is
-used to create images, any @LaTeX{} environment is handled.}.  The only 
requirement is that the
-@samp{\begin} statement appears on a new line, preceded by only
-whitespace.
-
-@item
-Text within the usual @LaTeX{} math delimiters.  To avoid conflicts
-with currency specifications, single @samp{$} characters are only
-recognized as math delimiters if the enclosed text contains at most
-two line breaks, is directly attached to the @samp{$} characters with no
-whitespace in between, and if the closing @samp{$} is followed by
-whitespace, punctuation or a dash.  For the other delimiters, there
-is no such restriction, so when in doubt, use @samp{\(...\)} as inline
-math delimiters.
-@end itemize
-
-@noindent
-For example:
-
-@example
-\begin@{equation@}                        % arbitrary environments,
-x=\sqrt@{b@}                              % even tables, figures
-\end@{equation@}                          % etc
-
-If $a^2=b$ and \( b=2 \), then the solution must be
-either $$ a=+\sqrt@{2@} $$ or \[ a=-\sqrt@{2@} \].
-@end example
-
-@vindex org-export-with-latex
-@LaTeX{} processing can be configured with the variable
-@code{org-export-with-latex}.  The default setting is @code{t} which means
-MathJax for HTML, and no processing for ASCII and @LaTeX{} back-ends.
-You can also set this variable on a per-file basis using one of these
-lines:
-
-@multitable {aaaaaaaaaaaaaaaaaaaaaaaaa} 
{aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa}
-@item @samp{#+OPTIONS: tex:t}
-@tab Do the right thing automatically (MathJax)
-@item @samp{#+OPTIONS: tex:nil}
-@tab Do not process @LaTeX{} fragments at all
-@item @samp{#+OPTIONS: tex:verbatim}
-@tab Verbatim export, for jsMath or so
-@end multitable
-
-@node Previewing @LaTeX{} fragments
-@subsection Previewing @LaTeX{} fragments
-
-@cindex @LaTeX{} fragments, preview
-
-@vindex org-preview-latex-default-process
-If you have a working @LaTeX{} installation and @samp{dvipng}, @samp{dvisvgm} 
or
-@samp{convert} installed@footnote{These are respectively available at
-@uref{http://sourceforge.net/projects/dvipng/}, 
@uref{http://dvisvgm.bplaced.net/}
-and from the ImageMagick suite.  Choose the converter by setting the
-variable @code{org-preview-latex-default-process} accordingly.}, @LaTeX{} 
fragments can be processed to
-produce images of the typeset expressions to be used for inclusion
-while exporting to HTML (see @ref{@LaTeX{} fragments}), or for inline
-previewing within Org mode.
-
-@vindex org-format-latex-options
-@vindex org-format-latex-header
-You can customize the variables @code{org-format-latex-options} and
-@code{org-format-latex-header} to influence some aspects of the preview.
-In particular, the @code{:scale} (and for HTML export, @code{:html-scale})
-property of the former can be used to adjust the size of the preview
-images.
-
-@table @asis
-@item @kbd{C-c C-x C-l} (@code{org-latex-preview})
-@kindex C-c C-x C-l
-@findex org-latex-preview
-
-Produce a preview image of the @LaTeX{} fragment at point and overlay
-it over the source code.  If there is no fragment at point, process
-all fragments in the current entry---between two headlines.
-
-When called with a single prefix argument, clear all images in the
-current entry.  Two prefix arguments produce a preview image for all
-fragments in the buffer, while three of them clear all the images in
-that buffer.
-@end table
-
-@vindex org-startup-with-latex-preview
-You can turn on the previewing of all @LaTeX{} fragments in a file with
-
-@example
-#+STARTUP: latexpreview
-@end example
-
-
-To disable it, simply use
-
-@example
-#+STARTUP: nolatexpreview
-@end example
-
-@node CD@LaTeX{} mode
-@subsection Using CD@LaTeX{} to enter math
-
-@cindex CD@LaTeX{}
-
-CD@LaTeX{} mode is a minor mode that is normally used in combination with
-a major @LaTeX{} mode like AUC@TeX{} in order to speed-up insertion of
-environments and math templates.  Inside Org mode, you can make use of
-some of the features of CD@LaTeX{} mode.  You need to install
-@samp{cdlatex.el} and @samp{texmathp.el} (the latter comes also with AUC@TeX{})
-using @uref{https://melpa.org/, MELPA} with the 
@uref{https://www.gnu.org/software/emacs/manual/html_node/emacs/Package-Installation.html,
 Emacs packaging system} or alternatively from
-@uref{https://staff.fnwi.uva.nl/c.dominik/Tools/cdlatex/}.  Do not use
-CD@LaTeX{} mode itself under Org mode, but use the special version Org
-CD@LaTeX{} minor mode that comes as part of Org.  Turn it on for the
-current buffer with @kbd{M-x org-cdlatex-mode}, or for all Org
-files with
-
-@lisp
-(add-hook 'org-mode-hook 'turn-on-org-cdlatex)
-@end lisp
-
-When this mode is enabled, the following features are present (for
-more details see the documentation of CD@LaTeX{} mode):
-
-@table @asis
-@item @kbd{C-c @{}
-@kindex C-c @{
-
-Insert an environment template.
-
-@item @kbd{@key{TAB}}
-@kindex TAB
-
-The @kbd{@key{TAB}} key expands the template if point is inside
-a @LaTeX{} fragment@footnote{Org mode has a method to test if point is inside 
such
-a fragment, see the documentation of the function
-@code{org-inside-LaTeX-fragment-p}.}.  For example, @kbd{@key{TAB}} expands 
@samp{fr}
-to @samp{\frac@{@}@{@}} and position point correctly inside the first brace.
-Another @kbd{@key{TAB}} gets you into the second brace.
-
-Even outside fragments, @kbd{@key{TAB}} expands environment
-abbreviations at the beginning of a line.  For example, if you write
-@samp{equ} at the beginning of a line and press @kbd{@key{TAB}}, this
-abbreviation is expanded to an @samp{equation} environment.  To get
-a list of all abbreviations, type @kbd{M-x cdlatex-command-help}.
-
-@item @kbd{^}
-@itemx @kbd{_}
-@kindex _
-@kindex ^
-@vindex cdlatex-simplify-sub-super-scripts
-
-Pressing @kbd{_} and @kbd{^} inside a @LaTeX{} fragment
-inserts these characters together with a pair of braces.  If you use
-@kbd{@key{TAB}} to move out of the braces, and if the braces surround
-only a single character or macro, they are removed again (depending
-on the variable @code{cdlatex-simplify-sub-super-scripts}).
-
-@item @kbd{`}
-@kindex `
-
-Pressing the backquote followed by a character inserts math macros,
-also outside @LaTeX{} fragments.  If you wait more than 1.5 seconds
-after the backquote, a help window pops up.
-
-@item @kbd{'}
-@kindex '
-
-Pressing the single-quote followed by another character modifies the
-symbol before point with an accent or a font.  If you wait more than
-1.5 seconds after the single-quote, a help window pops up.
-Character modification works only inside @LaTeX{} fragments; outside
-the quote is normal.
-@end table
-
-@node Literal Examples
-@section Literal Examples
-
-@cindex literal examples, markup rules
-@cindex code line references, markup rules
-
-You can include literal examples that should not be subjected to
-markup.  Such examples are typeset in monospace, so this is well
-suited for source code and similar examples.
-
-@cindex @samp{BEGIN_EXAMPLE}
-@cindex example block
-@example
-#+BEGIN_EXAMPLE
-  Some example from a text file.
-#+END_EXAMPLE
-@end example
-
-@cindex comma escape, in literal examples
-There is one limitation, however.  You must insert a comma right
-before lines starting with either @samp{*}, @samp{,*}, @samp{#+} or 
@samp{,#+}, as those
-may be interpreted as outlines nodes or some other special syntax.
-Org transparently strips these additional commas whenever it accesses
-the contents of the block.
-
-@example
-#+BEGIN_EXAMPLE
-,* I am no real headline
-#+END_EXAMPLE
-@end example
-
-For simplicity when using small examples, you can also start the
-example lines with a colon followed by a space.  There may also be
-additional whitespace before the colon:
-
-@example
-Here is an example
-   : Some example from a text file.
-@end example
-
-@cindex formatting source code, markup rules
-@vindex org-latex-listings
-If the example is source code from a programming language, or any
-other text that can be marked up by Font Lock in Emacs, you can ask
-for the example to look like the fontified Emacs buffer@footnote{This works 
automatically for the HTML backend (it requires
-version 1.34 of the @samp{htmlize.el} package, which you need to install).
-Fontified code chunks in @LaTeX{} can be achieved using either the
-@uref{https://www.ctan.org/pkg/listings, listings} package or the 
@uref{https://www.ctan.org/pkg/minted, minted} package.  Refer to
-@code{org-export-latex-listings} for details.}.  This
-is done with the code block, where you also need to specify the name
-of the major mode that should be used to fontify the example@footnote{Source 
code in code blocks may also be evaluated either
-interactively or on export.  See @ref{Working with Source Code} for more
-information on evaluating code blocks.},
-see @ref{Structure Templates} for shortcuts to easily insert code blocks.
-
-@cindex @samp{BEGIN_SRC}
-@cindex source block
-@example
-#+BEGIN_SRC emacs-lisp
-  (defun org-xor (a b)
-    "Exclusive or."
-    (if a (not b) b))
- #+END_SRC
-@end example
-
-Both in @samp{example} and in @samp{src} snippets, you can add a @samp{-n} 
switch to
-the end of the @samp{#+BEGIN} line, to get the lines of the example
-numbered.  The @samp{-n} takes an optional numeric argument specifying the
-starting line number of the block.  If you use a @samp{+n} switch, the
-numbering from the previous numbered snippet is continued in the
-current one.  The @samp{+n} switch can also take a numeric argument.  This
-adds the value of the argument to the last line of the previous block
-to determine the starting line number.
-
-@example
-#+BEGIN_SRC emacs-lisp -n 20
-  ;; This exports with line number 20.
-  (message "This is line 21")
-#+END_SRC
-
-#+BEGIN_SRC emacs-lisp +n 10
-  ;; This is listed as line 31.
-  (message "This is line 32")
-#+END_SRC
-@end example
-
-In literal examples, Org interprets strings like @samp{(ref:name)} as
-labels, and use them as targets for special hyperlinks like
-@samp{[[(name)]]}---i.e., the reference name enclosed in single parenthesis.
-In HTML, hovering the mouse over such a link remote-highlights the
-corresponding code line, which is kind of cool.
-
-You can also add a @samp{-r} switch which @emph{removes} the labels from the
-source code@footnote{Adding @samp{-k} to @samp{-n -r} @emph{keeps} the labels 
in the source code
-while using line numbers for the links, which might be useful to
-explain those in an Org mode example code.}.  With the @samp{-n} switch, links 
to these references
-are labeled by the line numbers from the code listing.  Otherwise
-links use the labels with no parentheses.  Here is an example:
-
-@example
-#+BEGIN_SRC emacs-lisp -n -r
-  (save-excursion                 (ref:sc)
-     (goto-char (point-min))      (ref:jump)
-#+END_SRC
-In line [[(sc)]] we remember the current position. [[(jump)][Line (jump)]]
-jumps to point-min.
-@end example
-
-@cindex indentation, in source blocks
-Source code and examples may be @emph{indented} in order to align nicely
-with the surrounding text, and in particular with plain list structure
-(see @ref{Plain Lists}).  By default, Org only retains the relative
-indentation between lines, e.g., when exporting the contents of the
-block.  However, you can use the @samp{-i} switch to also preserve the
-global indentation, if it does matter.  See @ref{Editing Source Code}.
-
-@vindex org-coderef-label-format
-If the syntax for the label format conflicts with the language syntax,
-use a @samp{-l} switch to change the format, for example
-
-@example
-#+BEGIN_SRC pascal -n -r -l "((%s))"
-@end example
-
-
-@noindent
-See also the variable @code{org-coderef-label-format}.
-
-HTML export also allows examples to be published as text areas (see
-@ref{Text areas in HTML export}).
-
-Because the @samp{#+BEGIN} @dots{} @samp{#+END} patterns need to be added so 
often,
-a shortcut is provided (see @ref{Structure Templates}).
-
-@table @asis
-@item @kbd{C-c '} (@code{org-edit-special})
-@kindex C-c '
-@findex org-edit-special
-Edit the source code example at point in its native mode.  This
-works by switching to a temporary buffer with the source code.  You
-need to exit by pressing @kbd{C-c '} again.  The edited version
-then replaces the old version in the Org buffer.  Fixed-width
-regions---where each line starts with a colon followed by
-a space---are edited using Artist mode@footnote{You may select a different 
mode with the variable
-@code{org-edit-fixed-width-region-mode}.} to allow creating
-ASCII drawings easily.  Using this command in an empty line creates
-a new fixed-width region.
-@end table
-
-@cindex storing link, in a source code buffer
-Calling @code{org-store-link} (see @ref{Handling Links}) while editing a source
-code example in a temporary buffer created with @kbd{C-c '}
-prompts for a label.  Make sure that it is unique in the current
-buffer, and insert it with the proper formatting like @samp{(ref:label)} at
-the end of the current line.  Then the label is stored as a link
-@samp{(label)}, for retrieval with @kbd{C-c C-l}.
-
-@node Images
-@section Images
-
-@cindex inlining images
-@cindex images, markup rules
-An image is a link to an image file@footnote{What Emacs considers to be an 
image depends on
-@code{image-file-name-extensions} and @code{image-file-name-regexps}.} that 
does not have
-a description part, for example
-
-@example
-./img/cat.jpg
-@end example
-
-
-If you wish to define a caption for the image (see @ref{Captions}) and
-maybe a label for internal cross references (see @ref{Internal Links}),
-make sure that the link is on a line by itself and precede it with
-@samp{CAPTION} and @samp{NAME} keywords as follows:
-
-@example
-#+CAPTION: This is the caption for the next figure link (or table)
-#+NAME:   fig:SED-HR4049
-[[./img/a.jpg]]
-@end example
-
-Such images can be displayed within the buffer with the following
-command:
-
-@table @asis
-@item @kbd{C-c C-x C-v} (@code{org-toggle-inline-images})
-@kindex C-c C-x C-v
-@findex org-toggle-inline-images
-@vindex org-startup-with-inline-images
-Toggle the inline display of linked images.  When called with
-a prefix argument, also display images that do have a link
-description.  You can ask for inline images to be displayed at
-startup by configuring the variable
-@code{org-startup-with-inline-images}@footnote{The variable 
@code{org-startup-with-inline-images} can be set
-within a buffer with the @samp{STARTUP} options @samp{inlineimages} and
-@samp{noinlineimages}.}.
-@end table
-
-@node Captions
-@section Captions
-
-@cindex captions, markup rules
-@cindex @samp{CAPTION}, keyword
-
-You can assign a caption to a specific part of a document by inserting
-a @samp{CAPTION} keyword immediately before it:
-
-@example
-#+CAPTION: This is the caption for the next table (or link)
-| ... | ... |
-|-----+-----|
-@end example
-
-Optionally, the caption can take the form:
-
-@example
-#+CAPTION[Short caption]: Longer caption.
-@end example
-
-
-Even though images and tables are prominent examples of captioned
-structures, the same caption mechanism can apply to many
-others---e.g., @LaTeX{} equations, source code blocks.  Depending on the
-export back-end, those may or may not be handled.
-
-@node Horizontal Rules
-@section Horizontal Rules
-
-@cindex horizontal rules, markup rules
-A line consisting of only dashes, and at least 5 of them, is exported
-as a horizontal line.
-
-@node Creating Footnotes
-@section Creating Footnotes
-
-@cindex footnotes
-
-A footnote is started by a footnote marker in square brackets in
-column 0, no indentation allowed.  It ends at the next footnote
-definition, headline, or after two consecutive empty lines.  The
-footnote reference is simply the marker in square brackets, inside
-text.  Markers always start with @samp{fn:}.  For example:
-
-@example
-The Org homepage[fn:1] now looks a lot better than it used to.
-...
-[fn:1] The link is: https://orgmode.org
-@end example
-
-Org mode extends the number-based syntax to @emph{named} footnotes and
-optional inline definition.  Here are the valid references:
-
-@table @asis
-@item @samp{[fn:NAME]}
-A named footnote reference, where @var{NAME} is a unique
-label word, or, for simplicity of automatic creation, a number.
-
-@item @samp{[fn:: This is the inline definition of this footnote]}
-An anonymous footnote where the definition is given directly at the
-reference point.
-
-@item @samp{[fn:NAME: a definition]}
-An inline definition of a footnote, which also specifies a name for
-the note.  Since Org allows multiple references to the same note,
-you can then use @samp{[fn:NAME]} to create additional references.
-@end table
-
-@vindex org-footnote-auto-label
-Footnote labels can be created automatically, or you can create names
-yourself.  This is handled by the variable @code{org-footnote-auto-label}
-and its corresponding @samp{STARTUP} keywords.  See the docstring of that
-variable for details.
-
-The following command handles footnotes:
-
-@table @asis
-@item @kbd{C-c C-x f}
-The footnote action command.
-
-@kindex C-c C-x f
-When point is on a footnote reference, jump to the definition.  When
-it is at a definition, jump to the---first---reference.
-
-@vindex org-footnote-define-inline
-@vindex org-footnote-section
-Otherwise, create a new footnote.  Depending on the variable
-@code{org-footnote-define-inline}@footnote{The corresponding in-buffer setting 
is: @samp{#+STARTUP: fninline}
-or @samp{#+STARTUP: nofninline}.}, the definition is placed right
-into the text as part of the reference, or separately into the
-location determined by the variable @code{org-footnote-section}.
-
-When this command is called with a prefix argument, a menu of
-additional options is offered:
-
-@multitable @columnfractions 0.1 0.9
-@item @kbd{s}
-@tab Sort the footnote definitions by reference sequence.
-@item @kbd{r}
-@tab Renumber the simple @samp{fn:N} footnotes.
-@item @kbd{S}
-@tab Short for first @kbd{r}, then @kbd{s} action.
-@item @kbd{n}
-@tab Rename all footnotes into a @samp{fn:1} @dots{} @samp{fn:n} sequence.
-@item @kbd{d}
-@tab Delete the footnote at point, including definition and references.
-@end multitable
-
-@vindex org-footnote-auto-adjust
-Depending on the variable @code{org-footnote-auto-adjust}@footnote{The 
corresponding in-buffer options are @samp{#+STARTUP: fnadjust}
-and @samp{#+STARTUP: nofnadjust}.},
-renumbering and sorting footnotes can be automatic after each
-insertion or deletion.
-
-@item @kbd{C-c C-c}
-@kindex C-c C-c
-If point is on a footnote reference, jump to the definition.  If it
-is at the definition, jump back to the reference.  When called at
-a footnote location with a prefix argument, offer the same menu as
-@kbd{C-c C-x f}.
-
-@item @kbd{C-c C-o} or @kbd{mouse-1/2}
-@kindex C-c C-o
-@kindex mouse-1
-@kindex mouse-2
-Footnote labels are also links to the corresponding definition or
-reference, and you can use the usual commands to follow these links.
-@end table
-
-@node Exporting
-@chapter Exporting
-
-@cindex exporting
-
-At some point you might want to print your notes, publish them on the
-web, or share them with people not using Org.  Org can convert and
-export documents to a variety of other formats while retaining as much
-structure (see @ref{Document Structure}) and markup (see @ref{Markup for Rich 
Contents}) as possible.
-
-@cindex export back-end
-The libraries responsible for translating Org files to other formats
-are called @emph{back-ends}.  Org ships with support for the following
-back-ends:
-
-@itemize
-@item
-@emph{ascii} (ASCII format)
-@item
-@emph{beamer} (@LaTeX{} Beamer format)
-@item
-@emph{html} (HTML format)
-@item
-@emph{icalendar} (iCalendar format)
-@item
-@emph{latex} (@LaTeX{} format)
-@item
-@emph{md} (Markdown format)
-@item
-@emph{odt} (OpenDocument Text format)
-@item
-@emph{org} (Org format)
-@item
-@emph{texinfo} (Texinfo format)
-@item
-@emph{man} (Man page format)
-@end itemize
-
-Users can install libraries for additional formats from the Emacs
-packaging system.  For easy discovery, these packages have a common
-naming scheme: @code{ox-NAME}, where @var{NAME} is a format.  For
-example, @code{ox-koma-letter} for @emph{koma-letter} back-end.  More libraries
-can be found in the @samp{contrib/} directory (see @ref{Installation}).
-
-@vindex org-export-backends
-Org only loads back-ends for the following formats by default: ASCII,
-HTML, iCalendar, @LaTeX{}, and ODT@.  Additional back-ends can be loaded
-in either of two ways: by configuring the @code{org-export-backends}
-variable, or by requiring libraries in the Emacs init file.  For
-example, to load the Markdown back-end, add this to your Emacs config:
-
-@lisp
-(require 'ox-md)
-@end lisp
-
-@menu
-* The Export Dispatcher::        The main interface.
-* Export Settings::              Common export settings.
-* Table of Contents::            The if and where of the table of contents.
-* Include Files::                Include additional files into a document.
-* Macro Replacement::            Use macros to create templates.
-* Comment Lines::                What will not be exported.
-* ASCII/Latin-1/UTF-8 export::   Exporting to flat files with encoding.
-* Beamer Export::                Producing presentations and slides.
-* HTML Export::                  Exporting to HTML.
-* @LaTeX{} Export::              Exporting to @LaTeX{} and processing to PDF.
-* Markdown Export::              Exporting to Markdown.
-* OpenDocument Text Export::     Exporting to OpenDocument Text.
-* Org Export::                   Exporting to Org.
-* Texinfo Export::               Exporting to Texinfo.
-* iCalendar Export::             Exporting to iCalendar.
-* Other Built-in Back-ends::     Exporting to a man page.
-* Advanced Export Configuration:: Fine-tuning the export output.
-* Export in Foreign Buffers::    Author tables and lists in Org syntax.
-@end menu
-
-@node The Export Dispatcher
-@section The Export Dispatcher
-
-@cindex dispatcher, for export commands
-@cindex export, dispatcher
-
-The export dispatcher is the main interface for Org's exports.
-A hierarchical menu presents the currently configured export formats.
-Options are shown as easy toggle switches on the same screen.
-
-@vindex org-export-dispatch-use-expert-ui
-Org also has a minimal prompt interface for the export dispatcher.
-When the variable @code{org-export-dispatch-use-expert-ui} is set to
-a non-@code{nil} value, Org prompts in the minibuffer.  To switch back to
-the hierarchical menu, press @kbd{?}.
-
-@table @asis
-@item @kbd{C-c C-e} (@code{org-export})
-@kindex C-c C-e
-@findex org-export
-
-Invokes the export dispatcher interface.  The options show default
-settings.  The @kbd{C-u} prefix argument preserves options from
-the previous export, including any sub-tree selections.
-@end table
-
-Org exports the entire buffer by default.  If the Org buffer has an
-active region, then Org exports just that region.
-
-Within the dispatcher interface, the following key combinations can
-further alter what is exported, and how.
-
-@table @asis
-@item @kbd{C-a}
-@kindex C-c C-e C-a
-
-Toggle asynchronous export.  Asynchronous export uses an external
-Emacs process with a specially configured initialization file to
-complete the exporting process in the background, without tying-up
-Emacs.  This is particularly useful when exporting long documents.
-
-Output from an asynchronous export is saved on the @emph{export stack}.
-To view this stack, call the export dispatcher with a double
-@kbd{C-u} prefix argument.  If already in the export dispatcher
-menu, @kbd{&} displays the stack.
-
-@vindex org-export-in-background
-You can make asynchronous export the default by setting
-@code{org-export-in-background}.
-
-@vindex org-export-async-init-file
-You can set the initialization file used by the background process
-by setting @code{org-export-async-init-file}.
-
-@item @kbd{C-b}
-@kindex C-c C-e C-b
-
-Toggle body-only export.  Useful for excluding headers and footers
-in the export.  Affects only those back-end formats that have
-sections like @samp{<head>...</head>} in HTML@.
-
-@item @kbd{C-s}
-@kindex C-c C-e C-s
-
-Toggle sub-tree export.  When turned on, Org exports only the
-sub-tree starting from point position at the time the export
-dispatcher was invoked.  Org uses the top heading of this sub-tree
-as the document's title.  If point is not on a heading, Org uses the
-nearest enclosing header.  If point is in the document preamble, Org
-signals an error and aborts export.
-
-@vindex org-export-initial-scope
-To make sub-tree export the default, customize the variable
-@code{org-export-initial-scope}.
-
-@item @kbd{C-v}
-@kindex C-c C-e C-v
-
-Toggle visible-only export.  This is useful for exporting only
-certain parts of an Org document by adjusting the visibility of
-particular headings.
-@end table
-
-@node Export Settings
-@section Export Settings
-
-@cindex options, for export
-@cindex Export, settings
-
-@cindex @samp{OPTIONS}, keyword
-Export options can be set: globally with variables; for an individual
-file by making variables buffer-local with in-buffer settings (see
-@ref{In-buffer Settings}); by setting individual keywords or
-specifying them in compact form with the @samp{OPTIONS} keyword; or for
-a tree by setting properties (see @ref{Properties and Columns}).  Options
-set at a specific level override options set at a more general level.
-
-@cindex @samp{SETUPFILE}, keyword
-In-buffer settings may appear anywhere in the file, either directly or
-indirectly through a file included using @samp{#+SETUPFILE: filename or
-URL} syntax.  Option keyword sets tailored to a particular back-end
-can be inserted from the export dispatcher (see @ref{The Export Dispatcher}) 
using the @samp{Insert template} command by pressing
-@kbd{#}.  To insert keywords individually, a good way to make
-sure the keyword is correct is to type @samp{#+} and then to use
-@kbd{M-@key{TAB}}@footnote{Many desktops intercept @kbd{M-@key{TAB}} to switch 
windows.
-Use @kbd{C-M-i} or @kbd{@key{ESC} @key{TAB}} instead.} for completion.
-
-The export keywords available for every back-end, and their equivalent
-global variables, include:
-
-@table @asis
-@item @samp{AUTHOR}
-@cindex @samp{AUTHOR}, keyword
-@vindex user-full-name
-The document author (@code{user-full-name}).
-
-@item @samp{CREATOR}
-@cindex @samp{CREATOR}, keyword
-@vindex org-expot-creator-string
-Entity responsible for output generation
-(@code{org-export-creator-string}).
-
-@item @samp{DATE}
-@cindex @samp{DATE}, keyword
-@vindex org-export-date-timestamp-format
-A date or a time-stamp@footnote{The variable 
@code{org-export-date-timestamp-format} defines how
-this timestamp are exported.}.
-
-@item @samp{EMAIL}
-@cindex @samp{EMAIL}, keyword
-@vindex user-mail-address
-The email address (@code{user-mail-address}).
-
-@item @samp{LANGUAGE}
-@cindex @samp{LANGUAGE}, keyword
-@vindex org-export-default-language
-Language to use for translating certain strings
-(@code{org-export-default-language}).  With @samp{#+LANGUAGE: fr}, for
-example, Org translates @samp{Table of contents} to the French @samp{Table des
-  matières}@footnote{DEFINITION NOT FOUND@.}.
-
-@item @samp{SELECT_TAGS}
-@cindex @samp{SELECT_TAGS}, keyword
-@vindex org-export-select-tags
-The default value is @samp{("export")}.  When a tree is tagged with
-@samp{export} (@code{org-export-select-tags}), Org selects that tree and its
-sub-trees for export.  Org excludes trees with @samp{noexport} tags, see
-below.  When selectively exporting files with @samp{export} tags set, Org
-does not export any text that appears before the first headline.
-
-@item @samp{EXCLUDE_TAGS}
-@cindex @samp{EXCLUDE_TAGS}, keyword
-@vindex org-export-exclude-tags
-The default value is @samp{("noexport")}.  When a tree is tagged with
-@samp{noexport} (@code{org-export-exclude-tags}), Org excludes that tree and
-its sub-trees from export.  Entries tagged with @samp{noexport} are
-unconditionally excluded from the export, even if they have an
-@samp{export} tag.  Even if a sub-tree is not exported, Org executes any
-code blocks contained there.
-
-@item @samp{TITLE}
-@cindex @samp{TITLE}, keyword
-@cindex document title
-Org displays this title.  For long titles, use multiple @samp{#+TITLE}
-lines.
-
-@item @samp{EXPORT_FILE_NAME}
-@cindex @samp{EXPORT_FILE_NAME}, keyword
-The name of the output file to be generated.  Otherwise, Org
-generates the file name based on the buffer name and the extension
-based on the back-end format.
-@end table
-
-The @samp{OPTIONS} keyword is a compact form.  To configure multiple
-options, use several @samp{OPTIONS} lines.  @samp{OPTIONS} recognizes the
-following arguments.
-
-@table @asis
-@item @code{'}
-@vindex org-export-with-smart-quotes
-Toggle smart quotes (@code{org-export-with-smart-quotes}).  Depending on
-the language used, when activated, Org treats pairs of double quotes
-as primary quotes, pairs of single quotes as secondary quotes, and
-single quote marks as apostrophes.
-
-@item @code{*}
-@vindex org-export-with-emphasize
-Toggle emphasized text (@code{org-export-with-emphasize}).
-
-@item @code{-}
-@vindex org-export-with-special-strings
-Toggle conversion of special strings
-(@code{org-export-with-special-strings}).
-
-@item @code{:}
-@vindex org-export-with-fixed-width
-Toggle fixed-width sections (@code{org-export-with-fixed-width}).
-
-@item @code{<}
-@vindex org-export-with-timestamps
-Toggle inclusion of time/date active/inactive stamps
-(@code{org-export-with-timestamps}).
-
-@item @code{\n}
-@vindex org-export-preserve-breaks
-Toggles whether to preserve line breaks
-(@code{org-export-preserve-breaks}).
-
-@item @code{^}
-@vindex org-export-with-sub-superscripts
-Toggle @TeX{}-like syntax for sub- and superscripts.  If you write
-@samp{^:@{@}}, @samp{a_@{b@}} is interpreted, but the simple @samp{a_b} is 
left as it
-is (@code{org-export-with-sub-superscripts}).
-
-@item @code{arch}
-@vindex org-export-with-archived-trees
-Configure how archived trees are exported.  When set to @code{headline},
-the export process skips the contents and processes only the
-headlines (@code{org-export-with-archived-trees}).
-
-@item @code{author}
-@vindex org-export-with-author
-Toggle inclusion of author name into exported file
-(@code{org-export-with-author}).
-
-@item @code{broken-links}
-@vindex org-export-with-broken-links
-Toggles if Org should continue exporting upon finding a broken
-internal link.  When set to @code{mark}, Org clearly marks the problem
-link in the output (@code{org-export-with-broken-links}).
-
-@item @code{c}
-@vindex org-export-with-clocks
-Toggle inclusion of @samp{CLOCK} keywords (@code{org-export-with-clocks}).
-
-@item @code{creator}
-@vindex org-export-with-creator
-Toggle inclusion of creator information in the exported file
-(@code{org-export-with-creator}).
-
-@item @code{d}
-@vindex org-export-with-drawers
-Toggles inclusion of drawers, or list of drawers to include, or list
-of drawers to exclude (@code{org-export-with-drawers}).
-
-@item @code{date}
-@vindex org-export-with-date
-Toggle inclusion of a date into exported file
-(@code{org-export-with-date}).
-
-@item @code{e}
-@vindex org-export-with-entities
-Toggle inclusion of entities (@code{org-export-with-entities}).
-
-@item @code{email}
-@vindex org-export-with-email
-Toggle inclusion of the author's e-mail into exported file
-(@code{org-export-with-email}).
-
-@item @code{f}
-@vindex org-export-with-footnotes
-Toggle the inclusion of footnotes (@code{org-export-with-footnotes}).
-
-@item @code{H}
-@vindex org-export-headline-levels
-Set the number of headline levels for export
-(@code{org-export-headline-levels}).  Below that level, headlines are
-treated differently.  In most back-ends, they become list items.
-
-@item @code{inline}
-@vindex org-export-with-inlinetasks
-Toggle inclusion of inlinetasks (@code{org-export-with-inlinetasks}).
-
-@item @code{num}
-@vindex org-export-with-section-numbers
-@cindex @samp{UNNUMBERED}, property
-Toggle section-numbers (@code{org-export-with-section-numbers}).  When
-set to number N, Org numbers only those headlines at level N or
-above.  Set @samp{UNNUMBERED} property to non-@code{nil} to disable numbering
-of heading and subheadings entirely.  Moreover, when the value is
-@samp{notoc} the headline, and all its children, do not appear in the
-table of contents either (see @ref{Table of Contents}).
-
-@item @code{p}
-@vindex org-export-with-planning
-Toggle export of planning information (@code{org-export-with-planning}).
-``Planning information'' comes from lines located right after the
-headline and contain any combination of these cookies: @samp{SCHEDULED},
-@samp{DEADLINE}, or @samp{CLOSED}.
-
-@item @code{pri}
-@vindex org-export-with-priority
-Toggle inclusion of priority cookies
-(@code{org-export-with-priority}).
-
-@item @code{prop}
-@vindex org-export-with-properties
-Toggle inclusion of property drawers, or list the properties to
-include (@code{org-export-with-properties}).
-
-@item @code{stat}
-@vindex org-export-with-statistics-cookies
-Toggle inclusion of statistics cookies
-(@code{org-export-with-statistics-cookies}).
-
-@item @code{tags}
-@vindex org-export-with-tags
-Toggle inclusion of tags, may also be @code{not-in-toc}
-(@code{org-export-with-tags}).
-
-@item @code{tasks}
-@vindex org-export-with-tasks
-Toggle inclusion of tasks (TODO items); or @code{nil} to remove all
-tasks; or @code{todo} to remove done tasks; or list the keywords to keep
-(@code{org-export-with-tasks}).
-
-@item @code{tex}
-@vindex org-export-with-latex
-@code{nil} does not export; @code{t} exports; @code{verbatim} keeps everything 
in
-verbatim (@code{org-export-with-latex}).
-
-@item @code{timestamp}
-@vindex org-export-time-stamp-file
-Toggle inclusion of the creation time in the exported file
-(@code{org-export-time-stamp-file}).
-
-@item @code{title}
-@vindex org-export-with-title
-Toggle inclusion of title (@code{org-export-with-title}).
-
-@item @code{toc}
-@vindex org-export-with-toc
-Toggle inclusion of the table of contents, or set the level limit
-(@code{org-export-with-toc}).
-
-@item @code{todo}
-@vindex org-export-with-todo-keywords
-Toggle inclusion of TODO keywords into exported text
-(@code{org-export-with-todo-keywords}).
-
-@item @code{|}
-@vindex org-export-with-tables
-Toggle inclusion of tables (@code{org-export-with-tables}).
-@end table
-
-When exporting sub-trees, special node properties can override the
-above keywords.  These properties have an @samp{EXPORT_} prefix.  For
-example, @samp{DATE} becomes, @samp{EXPORT_DATE} when used for a specific
-sub-tree.  Except for @samp{SETUPFILE}, all other keywords listed above
-have an @samp{EXPORT_} equivalent.
-
-@cindex @samp{BIND}, keyword
-@vindex org-export-allow-bind-keywords
-If @code{org-export-allow-bind-keywords} is non-@code{nil}, Emacs variables can
-become buffer-local during export by using the @samp{BIND} keyword.  Its
-syntax is @samp{#+BIND: variable value}.  This is particularly useful for
-in-buffer settings that cannot be changed using keywords.
-
-@node Table of Contents
-@section Table of Contents
-
-@cindex table of contents
-@cindex list of tables
-@cindex list of listings
-
-@cindex @samp{toc}, in @samp{OPTIONS} keyword
-@vindex org-export-with-toc
-The table of contents includes all headlines in the document.  Its
-depth is therefore the same as the headline levels in the file.  If
-you need to use a different depth, or turn it off entirely, set the
-@code{org-export-with-toc} variable accordingly.  You can achieve the same
-on a per file basis, using the following @samp{toc} item in @samp{OPTIONS}
-keyword:
-
-@example
-#+OPTIONS: toc:2          (only include two levels in TOC)
-#+OPTIONS: toc:nil        (no default TOC at all)
-@end example
-
-@cindex excluding entries from table of contents
-@cindex table of contents, exclude entries
-Org includes both numbered and unnumbered headlines in the table of
-contents@footnote{At the moment, some export back-ends do not obey this
-specification.  For example, @LaTeX{} export excludes every unnumbered
-headline from the table of contents.}.  If you need to exclude an unnumbered 
headline,
-along with all its children, set the @samp{UNNUMBERED} property to @samp{notoc}
-value.
-
-@example
-* Subtree not numbered, not in table of contents either
-  :PROPERTIES:
-  :UNNUMBERED: notoc
-  :END:
-@end example
-
-@cindex @samp{TOC}, keyword
-Org normally inserts the table of contents directly before the first
-headline of the file.  To move the table of contents to a different
-location, first turn off the default with @code{org-export-with-toc}
-variable or with @samp{#+OPTIONS: toc:nil}.  Then insert @samp{#+TOC: headlines
-N} at the desired location(s).
-
-@example
-#+OPTIONS: toc:nil
-...
-#+TOC: headlines 2
-@end example
-
-To adjust the table of contents depth for a specific section of the
-Org document, append an additional @samp{local} parameter.  This parameter
-becomes a relative depth for the current level.  The following example
-inserts a local table of contents, with direct children only.
-
-@example
-* Section
-#+TOC: headlines 1 local
-@end example
-
-Note that for this feature to work properly in @LaTeX{} export, the Org
-file requires the inclusion of the titletoc package.  Because of
-compatibility issues, titletoc has to be loaded @emph{before} hyperref.
-Customize the @code{org-latex-default-packages-alist} variable.
-
-The following example inserts a table of contents that links to the
-children of the specified target.
-
-@example
-* Target
-  :PROPERTIES:
-  :CUSTOM_ID: TargetSection
-  :END:
-** Heading A
-** Heading B
-* Another section
-#+TOC: headlines 1 :target #TargetSection
-@end example
-
-The @samp{:target} attribute is supported in HTML, Markdown, ODT, and ASCII 
export.
-
-Use the @samp{TOC} keyword to generate list of tables---respectively, all
-listings---with captions.
-
-@example
-#+TOC: listings
-#+TOC: tables
-@end example
-
-@cindex @samp{ALT_TITLE}, property
-Normally Org uses the headline for its entry in the table of contents.
-But with @samp{ALT_TITLE} property, a different entry can be specified for
-the table of contents.
-
-@node Include Files
-@section Include Files
-
-@cindex include files, during export
-@cindex export, include files
-@cindex @samp{INCLUDE}, keyword
-
-During export, you can include the content of another file.  For
-example, to include your @samp{.emacs} file, you could use:
-
-@example
-#+INCLUDE: "~/.emacs" src emacs-lisp
-@end example
-
-
-@noindent
-The first parameter is the file name to include.  The optional second
-parameter specifies the block type: @samp{example}, @samp{export} or 
@samp{src}.  The
-optional third parameter specifies the source code language to use for
-formatting the contents.  This is relevant to both @samp{export} and @samp{src}
-block types.
-
-If an included file is specified as having a markup language, Org
-neither checks for valid syntax nor changes the contents in any way.
-For example and source blocks, Org code-escapes the contents before
-inclusion.
-
-@cindex @samp{minlevel}, include
-If an included file is not specified as having any markup language,
-Org assumes it be in Org format and proceeds as usual with a few
-exceptions.  Org makes the footnote labels (see @ref{Creating Footnotes})
-in the included file local to that file.  The contents of the included
-file belong to the same structure---headline, item---containing the
-@samp{INCLUDE} keyword.  In particular, headlines within the file become
-children of the current section.  That behavior can be changed by
-providing an additional keyword parameter, @samp{:minlevel}.  It shifts the
-headlines in the included file to become the lowest level.  For
-example, this syntax makes the included file a sibling of the current
-top-level headline:
-
-@example
-#+INCLUDE: "~/my-book/chapter2.org" :minlevel 1
-@end example
-
-
-@cindex @samp{lines}, include
-Inclusion of only portions of files are specified using ranges
-parameter with @samp{:lines} keyword.  The line at the upper end of the
-range will not be included.  The start and/or the end of the range may
-be omitted to use the obvious defaults.
-
-@multitable {aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa} 
{aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa}
-@item @samp{#+INCLUDE: "~/.emacs" :lines "5-10"}
-@tab Include lines 5 to 10, 10 excluded
-@item @samp{#+INCLUDE: "~/.emacs" :lines "-10"}
-@tab Include lines 1 to 10, 10 excluded
-@item @samp{#+INCLUDE: "~/.emacs" :lines "10-"}
-@tab Include lines from 10 to EOF
-@end multitable
-
-Inclusions may specify a file-link to extract an object matched by
-@code{org-link-search}@footnote{Note that 
@code{org-link-search-must-match-exact-headline} is
-locally bound to non-@code{nil}.  Therefore, @code{org-link-search} only 
matches
-headlines and named elements.} (see @ref{Search Options}).  The
-ranges for @samp{:lines} keyword are relative to the requested element.
-Therefore,
-
-@example
-#+INCLUDE: "./paper.org::*conclusion" :lines 1-20
-@end example
-
-
-@noindent
-includes the first 20 lines of the headline named @samp{conclusion}.
-
-@cindex @samp{only-contents}, include
-To extract only the contents of the matched object, set
-@samp{:only-contents} property to non-@code{nil}.  This omits any planning 
lines
-or property drawers.  For example, to include the body of the heading
-with the custom ID @samp{theory}, you can use
-
-@example
-#+INCLUDE: "./paper.org::#theory" :only-contents t
-@end example
-
-
-The following command allows navigating to the included document:
-
-@table @asis
-@item @kbd{C-c '} (@code{org-edit~special})
-@kindex C-c '
-@findex org-edit-special
-
-Visit the included file at point.
-@end table
-
-@node Macro Replacement
-@section Macro Replacement
-
-@cindex macro replacement, during export
-@cindex @samp{MACRO}, keyword
-
-@vindex org-export-global-macros
-Macros replace text snippets during export.  Macros are defined
-globally in @code{org-export-global-macros}, or document-wise with the
-following syntax:
-
-@example
-#+MACRO: name   replacement text; $1, $2 are arguments
-@end example
-
-
-@noindent
-which can be referenced using @samp{@{@{@{name(arg1, 
arg2)@}@}@}}@footnote{Since commas separate the arguments, commas within 
arguments
-have to be escaped with the backslash character.  So only those
-backslash characters before a comma need escaping with another
-backslash character.}.  For
-example
-
-@example
-#+MACRO: poem Rose is $1, violet's $2. Life's ordered: Org assists you.
-@{@{@{poem(red,blue)@}@}@}
-@end example
-
-@noindent
-becomes
-
-@example
-Rose is red, violet's blue. Life's ordered: Org assists you.
-@end example
-
-
-As a special case, Org parses any replacement text starting with
-@samp{(eval} as an Emacs Lisp expression and evaluates it accordingly.
-Within such templates, arguments become strings.  Thus, the following
-macro
-
-@example
-#+MACRO: gnustamp (eval (concat "GNU/" (capitalize $1)))
-@end example
-
-
-@noindent
-turns @samp{@{@{@{gnustamp(linux)@}@}@}} into @samp{GNU/Linux} during export.
-
-Org recognizes macro references in following Org markup areas:
-paragraphs, headlines, verse blocks, tables cells and lists.  Org also
-recognizes macro references in keywords, such as @samp{CAPTION}, @samp{TITLE},
-@samp{AUTHOR}, @samp{DATE}, and for some back-end specific export options.
-
-Org comes with following pre-defined macros:
-
-@table @asis
-@item @samp{@{@{@{keyword(NAME)@}@}@}}
-@itemx @samp{@{@{@{title@}@}@}}
-@itemx @samp{@{@{@{author@}@}@}}
-@itemx @samp{@{@{@{email@}@}@}}
-@cindex @samp{keyword}, macro
-@cindex @samp{title}, macro
-@cindex @samp{author}, macro
-@cindex @samp{email}, macro
-The @samp{keyword} macro collects all values from @var{NAME}
-keywords throughout the buffer, separated with white space.
-@samp{title}, @samp{author} and @samp{email} macros are shortcuts for,
-respectively, @samp{@{@{@{keyword(TITLE)@}@}@}}, 
@samp{@{@{@{keyword(AUTHOR)@}@}@}} and
-@samp{@{@{@{keyword(EMAIL)@}@}@}}.
-
-@item @samp{@{@{@{date@}@}@}}
-@itemx @samp{@{@{@{date(FORMAT)@}@}@}}
-@cindex @samp{date}, macro
-This macro refers to the @samp{DATE} keyword.  @var{FORMAT} is an
-optional argument to the @samp{date} macro that is used only if @samp{DATE} is
-a single timestamp.  @var{FORMAT} should be a format string
-understood by @code{format-time-string}.
-
-@item @samp{@{@{@{time(FORMAT)@}@}@}}
-@itemx @samp{@{@{@{modification-time(FORMAT, VC)@}@}@}}
-@cindex @samp{time}, macro
-@cindex @samp{modification-time}, macro
-These macros refer to the document's date and time of export and
-date and time of modification.  @var{FORMAT} is a string
-understood by @code{format-time-string}.  If the second argument to the
-@code{modification-time} macro is non-@code{nil}, Org uses @samp{vc.el} to 
retrieve
-the document's modification time from the version control system.
-Otherwise Org reads the file attributes.
-
-@item @samp{@{@{@{input-file@}@}@}}
-@cindex @samp{input-file}, macro
-This macro refers to the filename of the exported file.
-
-@item @samp{@{@{@{property(PROPERTY-NAME)@}@}@}}
-@itemx @samp{@{@{@{property(PROPERTY-NAME, SEARCH OPTION)@}@}@}}
-@cindex @samp{property}, macro
-This macro returns the value of property @var{PROPERTY-NAME} in
-the current entry.  If @var{SEARCH-OPTION} (see @ref{Search Options}) refers 
to a remote entry, use it instead.
-
-@item @samp{@{@{@{n@}@}@}}
-@itemx @samp{@{@{@{n(NAME)@}@}@}}
-@itemx @samp{@{@{@{n(NAME, ACTION)@}@}@}}
-@cindex @samp{n}, macro
-@cindex counter, macro
-This macro implements custom counters by returning the number of
-times the macro has been expanded so far while exporting the buffer.
-You can create more than one counter using different @var{NAME}
-values.  If @var{ACTION} is @samp{-}, previous value of the counter
-is held, i.e., the specified counter is not incremented.  If the
-value is a number, the specified counter is set to that value.  If
-it is any other non-empty string, the specified counter is reset
-to 1.  You may leave @var{NAME} empty to reset the default
-counter.
-@end table
-
-@cindex @samp{results}, macro
-Moreover, inline source blocks (see @ref{Structure of Code Blocks}) use the
-special @samp{results} macro to mark their output.  As such, you are
-advised against re-defining it, unless you know what you are doing.
-
-@vindex org-hide-macro-markers
-The surrounding brackets can be made invisible by setting
-@code{org-hide-macro-markers} to a non-@code{nil} value.
-
-Org expands macros at the very beginning of the export process.
-
-@node Comment Lines
-@section Comment Lines
-
-@cindex exporting, not
-
-@cindex comment lines
-Lines starting with zero or more whitespace characters followed by one
-@samp{#} and a whitespace are treated as comments and, as such, are not
-exported.
-
-@cindex @samp{BEGIN_COMMENT}
-@cindex comment block
-Likewise, regions surrounded by @samp{#+BEGIN_COMMENT} @dots{} 
@samp{#+END_COMMENT}
-are not exported.
-
-@cindex comment trees
-Finally, a @samp{COMMENT} keyword at the beginning of an entry, but after
-any other keyword or priority cookie, comments out the entire subtree.
-In this case, the subtree is not exported and no code block within it
-is executed either@footnote{For a less drastic behavior, consider using a 
select tag (see
-@ref{Export Settings}) instead.}.  The command below helps changing the
-comment status of a headline.
-
-@table @asis
-@item @kbd{C-c ;} (@code{org-toggle-comment})
-@kindex C-c ;
-@findex org-toggle-comment
-
-Toggle the @samp{COMMENT} keyword at the beginning of an entry.
-@end table
-
-@node ASCII/Latin-1/UTF-8 export
-@section ASCII/Latin-1/UTF-8 export
-
-@cindex ASCII export
-@cindex Latin-1 export
-@cindex UTF-8 export
-
-ASCII export produces an output file containing only plain ASCII
-characters.  This is the simplest and most direct text output.  It
-does not contain any Org markup.  Latin-1 and UTF-8 export use
-additional characters and symbols available in these encoding
-standards.  All three of these export formats offer the most basic of
-text output for maximum portability.
-
-@vindex org-ascii-text-width
-On export, Org fills and justifies text according to the text width
-set in @code{org-ascii-text-width}.
-
-@vindex org-ascii-links-to-notes
-Org exports links using a footnote-like style where the descriptive
-part is in the text and the link is in a note before the next heading.
-See the variable @code{org-ascii-links-to-notes} for details.
-
-@anchor{ASCII export commands}
-@subheading ASCII export commands
-
-@table @asis
-@item @kbd{C-c C-e t a} (@code{org-ascii-export-to-ascii})
-@itemx @kbd{C-c C-e t l}
-@itemx @kbd{C-c C-e t u}
-@kindex C-c C-e t a
-@kindex C-c C-e t l
-@kindex C-c C-e t u
-@findex org-ascii-export-to-ascii
-
-Export as an ASCII file with a @samp{.txt} extension.  For @samp{myfile.org},
-Org exports to @samp{myfile.txt}, overwriting without warning.  For
-@samp{myfile.txt}, Org exports to @samp{myfile.txt.txt} in order to prevent
-data loss.
-
-@item @kbd{C-c C-e t A} (@code{org-ascii-export-to-ascii})
-@itemx @kbd{C-c C-e t L}
-@itemx @kbd{C-c C-e t U}
-@kindex C-c C-e t A
-@kindex C-c C-e t L
-@kindex C-c C-e t U
-@findex org-ascii-export-as-ascii
-
-Export to a temporary buffer.  Does not create a file.
-@end table
-
-@anchor{ASCII specific export settings}
-@subheading ASCII specific export settings
-
-The ASCII export back-end has one extra keyword for customizing ASCII
-output.  Setting this keyword works similar to the general options
-(see @ref{Export Settings}).
-
-@table @asis
-@item @samp{SUBTITLE}
-@cindex @samp{SUBTITLE}, keyword
-The document subtitle.  For long subtitles, use multiple
-@samp{#+SUBTITLE} lines in the Org file.  Org prints them on one
-continuous line, wrapping into multiple lines if necessary.
-@end table
-
-@anchor{Header and sectioning structure}
-@subheading Header and sectioning structure
-
-Org converts the first three outline levels into headlines for ASCII
-export.  The remaining levels are turned into lists.  To change this
-cut-off point where levels become lists, see @ref{Export Settings}.
-
-@anchor{Quoting ASCII text}
-@subheading Quoting ASCII text
-
-To insert text within the Org file by the ASCII back-end, use one the
-following constructs, inline, keyword, or export block:
-
-@cindex @samp{ASCII}, keyword
-@cindex @samp{BEGIN_EXPORT ascii}
-@example
-Inline text @@@@ascii:and additional text@@@@ within a paragraph.
-
-#+ASCII: Some text
-
-#+BEGIN_EXPORT ascii
-Org exports text in this block only when using ASCII back-end.
-#+END_EXPORT
-@end example
-
-@anchor{ASCII specific attributes}
-@subheading ASCII specific attributes
-
-@cindex @samp{ATTR_ASCII}, keyword
-@cindex horizontal rules, in ASCII export
-
-ASCII back-end recognizes only one attribute, @samp{:width}, which
-specifies the width of a horizontal rule in number of characters.  The
-keyword and syntax for specifying widths is:
-
-@example
-#+ATTR_ASCII: :width 10
------
-@end example
-
-@anchor{ASCII special blocks}
-@subheading ASCII special blocks
-
-@cindex special blocks, in ASCII export
-@cindex @samp{BEGIN_JUSTIFYLEFT}
-@cindex @samp{BEGIN_JUSTIFYRIGHT}
-
-Besides @samp{#+BEGIN_CENTER} blocks (see @ref{Paragraphs}), ASCII back-end has
-these two left and right justification blocks:
-
-@example
-#+BEGIN_JUSTIFYLEFT
-It's just a jump to the left...
-#+END_JUSTIFYLEFT
-
-#+BEGIN_JUSTIFYRIGHT
-...and then a step to the right.
-#+END_JUSTIFYRIGHT
-@end example
-
-@node Beamer Export
-@section Beamer Export
-
-@cindex Beamer export
-
-Org uses Beamer export to convert an Org file tree structure into
-high-quality interactive slides for presentations.  Beamer is a @LaTeX{}
-document class for creating presentations in PDF, HTML, and other
-popular display formats.
-
-@menu
-* Beamer export commands::       For creating Beamer documents.
-* Beamer specific export settings:: For customizing Beamer export.
-* Frames and Blocks in Beamer::  For composing Beamer slides.
-* Beamer specific syntax::       For using in Org documents.
-* Editing support::              Editing support.
-* A Beamer example::             A complete presentation.
-@end menu
-
-@node Beamer export commands
-@subsection Beamer export commands
-
-@table @asis
-@item @kbd{C-c C-e l b} (@code{org-beamer-export-to-latex})
-@kindex C-c C-e l b
-@findex org-beamer-export-to-latex
-
-Export as @LaTeX{} file with a @samp{.tex} extension.  For @samp{myfile.org}, 
Org
-exports to @samp{myfile.tex}, overwriting without warning.
-
-@item @kbd{C-c C-e l B} (@code{org-beamer-export-as-latex})
-@kindex C-c C-e l B
-@findex org-beamer-export-as-latex
-
-Export to a temporary buffer.  Does not create a file.
-
-@item @kbd{C-c C-e l P} (@code{org-beamer-export-to-pdf})
-@kindex C-c C-e l P
-@findex org-beamer-export-to-pdf
-
-Export as @LaTeX{} file and then convert it to PDF format.
-
-@item @kbd{C-c C-e l O}
-@kindex C-c C-e l O
-
-Export as @LaTeX{} file, convert it to PDF format, and then open the
-PDF file.
-@end table
-
-@node Beamer specific export settings
-@subsection Beamer specific export settings
-
-Beamer export back-end has several additional keywords for customizing
-Beamer output.  These keywords work similar to the general options
-settings (see @ref{Export Settings}).
-
-@table @asis
-@item @samp{BEAMER_THEME}
-@cindex @samp{BEAMER_THEME}, keyword
-@vindex org-beamer-theme
-The Beamer layout theme (@code{org-beamer-theme}).  Use square brackets
-for options.  For example:
-
-@example
-#+BEAMER_THEME: Rochester [height=20pt]
-@end example
-
-@item @samp{BEAMER_FONT_THEME}
-@cindex @samp{BEAMER_FONT_THEME}, keyword
-The Beamer font theme.
-
-@item @samp{BEAMER_INNER_THEME}
-@cindex @samp{BEAMER_INNER_THEME}, keyword
-The Beamer inner theme.
-
-@item @samp{BEAMER_OUTER_THEME}
-@cindex @samp{BEAMER_OUTER_THEME}, keyword
-The Beamer outer theme.
-
-@item @samp{BEAMER_HEADER}
-@cindex @samp{BEAMER_HEADER}, keyword
-Arbitrary lines inserted in the preamble, just before the @samp{hyperref}
-settings.
-
-@item @samp{DESCRIPTION}
-@cindex @samp{DESCRIPTION}, keyword
-The document description.  For long descriptions, use multiple
-@samp{DESCRIPTION} keywords.  By default, @samp{hyperref} inserts
-@samp{DESCRIPTION} as metadata.  Use @code{org-latex-hyperref-template} to
-configure document metadata.  Use @code{org-latex-title-command} to
-configure typesetting of description as part of front matter.
-
-@item @samp{KEYWORDS}
-@cindex @samp{KEYWORDS}, keyword
-The keywords for defining the contents of the document.  Use
-multiple @samp{KEYWORDS} lines if necessary.  By default, @samp{hyperref}
-inserts @samp{KEYWORDS} as metadata.  Use @code{org-latex-hyperref-template}
-to configure document metadata.  Use @code{org-latex-title-command} to
-configure typesetting of keywords as part of front matter.
-
-@item @samp{SUBTITLE}
-@cindex @samp{SUBTITLE}, keyword
-Document's subtitle.  For typesetting, use
-@code{org-beamer-subtitle-format} string.  Use
-@code{org-latex-hyperref-template} to configure document metadata.  Use
-@code{org-latex-title-command} to configure typesetting of subtitle as
-part of front matter.
-@end table
-
-@node Frames and Blocks in Beamer
-@subsection Frames and Blocks in Beamer
-
-Org transforms heading levels into Beamer's sectioning elements,
-frames and blocks.  Any Org tree with a not-too-deep-level nesting
-should in principle be exportable as a Beamer presentation.
-
-@itemize
-@item
-@vindex org-beamer-frame-level
-Org headlines become Beamer frames when the heading level in Org is
-equal to @code{org-beamer-frame-level} or @samp{H} value in a @samp{OPTIONS} 
line
-(see @ref{Export Settings}).
-
-@cindex @samp{BEAMER_ENV}, property
-Org overrides headlines to frames conversion for the current tree of
-an Org file if it encounters the @samp{BEAMER_ENV} property set to
-@samp{frame} or @samp{fullframe}.  Org ignores whatever
-@code{org-beamer-frame-level} happens to be for that headline level in
-the Org tree.  In Beamer terminology, a full frame is a frame
-without its title.
-
-@item
-Org exports a Beamer frame's objects as block environments.  Org can
-enforce wrapping in special block types when @samp{BEAMER_ENV} property
-is set@footnote{If @samp{BEAMER_ENV} is set, Org export adds 
@samp{B_environment} tag
-to make it visible.  The tag serves as a visual aid and has no
-semantic relevance.}.  For valid values see
-@code{org-beamer-environments-default}.  To add more values, see
-@code{org-beamer-environments-extra}.
-@vindex org-beamer-environments-default
-@vindex org-beamer-environments-extra
-
-@item
-@cindex @samp{BEAMER_REF}, property
-If @samp{BEAMER_ENV} is set to @samp{appendix}, Org exports the entry as an
-appendix.  When set to @samp{note}, Org exports the entry as a note
-within the frame or between frames, depending on the entry's heading
-level.  When set to @samp{noteNH}, Org exports the entry as a note
-without its title.  When set to @samp{againframe}, Org exports the entry
-with @samp{\againframe} command, which makes setting the @samp{BEAMER_REF}
-property mandatory because @samp{\againframe} needs frame to resume.
-
-When @samp{ignoreheading} is set, Org export ignores the entry's headline
-but not its content.  This is useful for inserting content between
-frames.  It is also useful for properly closing a @samp{column}
-environment.  @@end itemize
-
-@cindex @samp{BEAMER_ACT}, property
-@cindex @samp{BEAMER_OPT}, property
-When @samp{BEAMER_ACT} is set for a headline, Org export translates that
-headline as an overlay or action specification.  When enclosed in
-square brackets, Org export makes the overlay specification
-a default.  Use @samp{BEAMER_OPT} to set any options applicable to the
-current Beamer frame or block.  The Beamer export back-end wraps
-with appropriate angular or square brackets.  It also adds the
-@samp{fragile} option for any code that may require a verbatim block.
-
-@cindex @samp{BEAMER_COL}, property
-To create a column on the Beamer slide, use the @samp{BEAMER_COL}
-property for its headline in the Org file.  Set the value of
-@samp{BEAMER_COL} to a decimal number representing the fraction of the
-total text width.  Beamer export uses this value to set the column's
-width and fills the column with the contents of the Org entry.  If
-the Org entry has no specific environment defined, Beamer export
-ignores the heading.  If the Org entry has a defined environment,
-Beamer export uses the heading as title.  Behind the scenes, Beamer
-export automatically handles @LaTeX{} column separations for contiguous
-headlines.  To manually adjust them for any unique configurations
-needs, use the @samp{BEAMER_ENV} property.
-@end itemize
-
-@node Beamer specific syntax
-@subsection Beamer specific syntax
-
-Since Org's Beamer export back-end is an extension of the @LaTeX{}
-back-end, it recognizes other @LaTeX{} specific syntax---for example,
-@samp{#+LATEX:} or @samp{#+ATTR_LATEX:}.  See @ref{@LaTeX{} Export}, for 
details.
-
-Beamer export wraps the table of contents generated with @samp{toc:t}
-@samp{OPTION} keyword in a @samp{frame} environment.  Beamer export does not
-wrap the table of contents generated with @samp{TOC} keyword (see @ref{Table 
of Contents}).  Use square brackets for specifying options.
-
-@example
-#+TOC: headlines [currentsection]
-@end example
-
-
-Insert Beamer-specific code using the following constructs:
-
-@cindex @samp{BEAMER}, keyword
-@cindex @samp{BEGIN_EXPORT beamer}
-@example
-#+BEAMER: \pause
-
-#+BEGIN_EXPORT beamer
-  Only Beamer export back-end exports this.
-#+END_BEAMER
-
-Text @@@@beamer:some code@@@@ within a paragraph.
-@end example
-
-Inline constructs, such as the last one above, are useful for adding
-overlay specifications to objects with @code{bold}, @code{item}, @code{link},
-@code{radio-target} and @code{target} types.  Enclose the value in angular
-brackets and place the specification at the beginning of the object as
-shown in this example:
-
-@example
-A *@@@@beamer:<2->@@@@useful* feature
-@end example
-
-
-@cindex @samp{ATTR_BEAMER}, keyword
-Beamer export recognizes the @samp{ATTR_BEAMER} keyword with the following
-attributes from Beamer configurations: @samp{:environment} for changing
-local Beamer environment, @samp{:overlay} for specifying Beamer overlays in
-angular or square brackets, and @samp{:options} for inserting optional
-arguments.
-
-@example
-#+ATTR_BEAMER: :environment nonindentlist
-- item 1, not indented
-- item 2, not indented
-- item 3, not indented
-@end example
-
-@example
-#+ATTR_BEAMER: :overlay <+->
-- item 1
-- item 2
-@end example
-
-@example
-#+ATTR_BEAMER: :options [Lagrange]
-Let $G$ be a finite group, and let $H$ be
-a subgroup of $G$.  Then the order of $H$ divides the order of $G$.
-@end example
-
-@node Editing support
-@subsection Editing support
-
-Org Beamer mode is a special minor mode for faster editing of Beamer
-documents.
-
-@example
-#+STARTUP: beamer
-@end example
-
-
-@table @asis
-@item @kbd{C-c C-b} (@code{org-beamer-select-environment})
-@kindex C-c C-b
-@findex org-beamer-select-environment
-
-Org Beamer mode provides this key for quicker selections in Beamer
-normal environments, and for selecting the @samp{BEAMER_COL} property.
-@end table
-
-@node A Beamer example
-@subsection A Beamer example
-
-Here is an example of an Org document ready for Beamer export.
-
-@example
-#+TITLE: Example Presentation
-#+AUTHOR: Carsten Dominik
-#+OPTIONS: H:2 toc:t num:t
-#+LATEX_CLASS: beamer
-#+LATEX_CLASS_OPTIONS: [presentation]
-#+BEAMER_THEME: Madrid
-#+COLUMNS: %45ITEM %10BEAMER_ENV(Env) %10BEAMER_ACT(Act) %4BEAMER_COL(Col)
-
-* This is the first structural section
-
-** Frame 1
-*** Thanks to Eric Fraga                                           :B_block:
-    :PROPERTIES:
-    :BEAMER_COL: 0.48
-    :BEAMER_ENV: block
-    :END:
-    for the first viable Beamer setup in Org
-*** Thanks to everyone else                                        :B_block:
-    :PROPERTIES:
-    :BEAMER_COL: 0.48
-    :BEAMER_ACT: <2->
-    :BEAMER_ENV: block
-    :END:
-    for contributing to the discussion
-**** This will be formatted as a beamer note                       :B_note:
-     :PROPERTIES:
-     :BEAMER_env: note
-     :END:
-** Frame 2 (where we will not use columns)
-*** Request
-    Please test this stuff!
-@end example
-
-@node HTML Export
-@section HTML Export
-
-@cindex HTML export
-
-Org mode contains an HTML exporter with extensive HTML formatting
-compatible with XHTML 1.0 strict standard.
-
-@menu
-* HTML export commands::         Invoking HTML export.
-* HTML specific export settings:: Settings for HTML export.
-* HTML doctypes::                Exporting various (X)HTML flavors.
-* HTML preamble and postamble::  Inserting preamble and postamble.
-* Quoting HTML tags::            Using direct HTML in Org files.
-* Headlines in HTML export::     Formatting headlines.
-* Links in HTML export::         Inserting and formatting links.
-* Tables in HTML export::        How to modify the formatting of tables.
-* Images in HTML export::        How to insert figures into HTML output.
-* Math formatting in HTML export:: Beautiful math also on the web.
-* Text areas in HTML export::    An alternate way to show an example.
-* CSS support::                  Changing the appearance of the output.
-* JavaScript support::           Info and folding in a web browser.
-@end menu
-
-@node HTML export commands
-@subsection HTML export commands
-
-@table @asis
-@item @kbd{C-c C-e h h} (@code{org-html-export-to-html})
-@kindex C-c C-e h h
-@kindex C-c C-e h o
-@findex org-html-export-to-html
-
-Export as HTML file with a @samp{.html} extension.  For @samp{myfile.org}, Org
-exports to @samp{myfile.html}, overwriting without warning.  @{@{@{kbd@{C-c
-C-e h o)@}@}@} exports to HTML and opens it in a web browser.
-
-@item @kbd{C-c C-e h H} (@code{org-html-export-as-html})
-@kindex C-c C-e h H
-@findex org-html-export-as-html
-
-Exports to a temporary buffer.  Does not create a file.
-@end table
-
-@node HTML specific export settings
-@subsection HTML specific export settings
-
-HTML export has a number of keywords, similar to the general options
-settings described in @ref{Export Settings}.
-
-@table @asis
-@item @samp{DESCRIPTION}
-@cindex @samp{DESCRIPTION}, keyword
-This is the document's description, which the HTML exporter inserts
-it as a HTML meta tag in the HTML file.  For long descriptions, use
-multiple @samp{DESCRIPTION} lines.  The exporter takes care of wrapping
-the lines properly.
-
-@item @samp{HTML_DOCTYPE}
-@cindex @samp{HTML_DOCTYPE}, keyword
-@vindex org-html-doctype
-Specify the document type, for example: HTML5 (@code{org-html-doctype}).
-
-@item @samp{HTML_CONTAINER}
-@cindex @samp{HTML_CONTAINER}, keyword
-@vindex org-html-container-element
-Specify the HTML container, such as @samp{div}, for wrapping sections and
-elements (@code{org-html-container-element}).
-
-@item @samp{HTML_LINK_HOME}
-@cindex @samp{HTML_LINK_HOME}, keyword
-@vindex org-html-link-home
-The URL for home link (@code{org-html-link-home}).
-
-@item @samp{HTML_LINK_UP}
-@cindex @samp{HTML_LINK_UP}, keyword
-@vindex org-html-link-up
-The URL for the up link of exported HTML pages (@code{org-html-link-up}).
-
-@item @samp{HTML_MATHJAX}
-@cindex @samp{HTML_MATHJAX}, keyword
-@vindex org-html-mathjax-options
-Options for MathJax (@code{org-html-mathjax-options}).  MathJax is used
-to typeset @LaTeX{} math in HTML documents.  See @ref{Math formatting in HTML 
export}, for an example.
-
-@item @samp{HTML_HEAD}
-@cindex @samp{HTML_HEAD}, keyword
-@vindex org-html-head
-Arbitrary lines for appending to the HTML document's head
-(@code{org-html-head}).
-
-@item @samp{HTML_HEAD_EXTRA}
-@cindex @samp{HTML_HEAD_EXTRA}, keyword
-@vindex org-html-head-extra
-More arbitrary lines for appending to the HTML document's head
-(@code{org-html-head-extra}).
-
-@item @samp{KEYWORDS}
-@cindex @samp{KEYWORDS}, keyword
-Keywords to describe the document's content.  HTML exporter inserts
-these keywords as HTML meta tags.  For long keywords, use multiple
-@samp{KEYWORDS} lines.
-
-@item @samp{LATEX_HEADER}
-@cindex @samp{LATEX_HEADER}, keyword
-Arbitrary lines for appending to the preamble; HTML exporter appends
-when transcoding @LaTeX{} fragments to images (see @ref{Math formatting in 
HTML export}).
-
-@item @samp{SUBTITLE}
-@cindex @samp{SUBTITLE}, keyword
-The document's subtitle.  HTML exporter formats subtitle if document
-type is @samp{HTML5} and the CSS has a @samp{subtitle} class.
-@end table
-
-Some of these keywords are explained in more detail in the following
-sections of the manual.
-
-@node HTML doctypes
-@subsection HTML doctypes
-
-Org can export to various (X)HTML flavors.
-
-@vindex org-html-doctype
-@vindex org-html-doctype-alist
-Set the @code{org-html-doctype} variable for different (X)HTML variants.
-Depending on the variant, the HTML exporter adjusts the syntax of HTML
-conversion accordingly.  Org includes the following ready-made
-variants:
-
-@itemize
-@item
-@code{"html4-strict"}
-@item
-@code{"html4-transitional"}
-@item
-@code{"html4-frameset"}
-@item
-@code{"xhtml-strict"}
-@item
-@code{"xhtml-transitional"}
-@item
-@code{"xhtml-frameset"}
-@item
-@code{"xhtml-11"}
-@item
-@code{"html5"}
-@item
-@code{"xhtml5"}
-@end itemize
-
-@noindent
-See the variable @code{org-html-doctype-alist} for details.  The default is
-@code{"xhtml-strict"}.
-
-@vindex org-html-html5-fancy
-@cindex @samp{HTML5}, export new elements
-Org's HTML exporter does not by default enable new block elements
-introduced with the HTML5 standard.  To enable them, set
-@code{org-html-html5-fancy} to non-@code{nil}.  Or use an @samp{OPTIONS} line 
in the
-file to set @samp{html5-fancy}.
-
-HTML5 documents can now have arbitrary @samp{#+BEGIN} @dots{} @samp{#+END} 
blocks.
-For example:
-
-@example
-#+BEGIN_aside
-  Lorem ipsum
-#+END_aside
-@end example
-
-@noindent
-exports to:
-
-@example
-<aside>
-  <p>Lorem ipsum</p>
-</aside>
-@end example
-
-@noindent
-while this:
-
-@example
-#+ATTR_HTML: :controls controls :width 350
-#+BEGIN_video
-#+HTML: <source src="movie.mp4" type="video/mp4">
-#+HTML: <source src="movie.ogg" type="video/ogg">
-Your browser does not support the video tag.
-#+END_video
-@end example
-
-@noindent
-exports to:
-
-@example
-<video controls="controls" width="350">
-  <source src="movie.mp4" type="video/mp4">
-    <source src="movie.ogg" type="video/ogg">
-      <p>Your browser does not support the video tag.</p>
-</video>
-@end example
-
-@vindex org-html-html5-elements
-When special blocks do not have a corresponding HTML5 element, the
-HTML exporter reverts to standard translation (see
-@code{org-html-html5-elements}).  For example, @samp{#+BEGIN_lederhosen} 
exports
-to @code{<div class="lederhosen">}.
-
-Special blocks cannot have headlines.  For the HTML exporter to wrap
-the headline and its contents in @code{<section>} or @code{<article>} tags, set
-the @samp{HTML_CONTAINER} property for the headline.
-
-@node HTML preamble and postamble
-@subsection HTML preamble and postamble
-
-@vindex org-html-preamble
-@vindex org-html-postamble
-@vindex org-html-preamble-format
-@vindex org-html-postamble-format
-@vindex org-html-validation-link
-@vindex org-export-creator-string
-@vindex org-export-time-stamp-file
-
-The HTML exporter has delineations for preamble and postamble.  The
-default value for @code{org-html-preamble} is @code{t}, which makes the HTML
-exporter insert the preamble.  See the variable
-@code{org-html-preamble-format} for the format string.
-
-Set @code{org-html-preamble} to a string to override the default format
-string.  If the string is a function, the HTML exporter expects the
-function to return a string upon execution.  The HTML exporter inserts
-this string in the preamble.  The HTML exporter does not insert
-a preamble if @code{org-html-preamble} is set @code{nil}.
-
-The default value for @code{org-html-postamble} is @code{auto}, which makes the
-HTML exporter build a postamble from looking up author's name, email
-address, creator's name, and date.  Set @code{org-html-postamble} to @code{t} 
to
-insert the postamble in the format specified in the
-@code{org-html-postamble-format} variable.  The HTML exporter does not
-insert a postamble if @code{org-html-postamble} is set to @code{nil}.
-
-@node Quoting HTML tags
-@subsection Quoting HTML tags
-
-The HTML export back-end transforms @samp{<} and @samp{>} to @samp{&lt;} and 
@samp{&gt;}.
-To include raw HTML code in the Org file so the HTML export back-end
-can insert that HTML code in the output, use this inline syntax:
-@samp{@@@@html:...@@@@}.  For example:
-
-@example
-@@@@html:<b>@@@@bold text@@@@html:</b>@@@@
-@end example
-
-
-@cindex @samp{HTML}, keyword
-@cindex @samp{BEGIN_EXPORT html}
-For larger raw HTML code blocks, use these HTML export code blocks:
-
-@example
-#+HTML: Literal HTML code for export
-
-#+BEGIN_EXPORT html
-  All lines between these markers are exported literally
-#+END_EXPORT
-@end example
-
-@node Headlines in HTML export
-@subsection Headlines in HTML export
-
-@cindex headlines, in HTML export
-
-Headlines are exported to @samp{<h1>}, @samp{<h2>}, etc.  Each headline gets 
the
-@samp{id} attribute from @samp{CUSTOM_ID} property, or a unique generated 
value,
-see @ref{Internal Links}.
-
-@vindex org-html-self-link-headlines
-When @code{org-html-self-link-headlines} is set to a non-@code{nil} value, the
-text of the headlines is also wrapped in @samp{<a>} tags.  These tags have
-a @samp{href} attribute making the headlines link to themselves.
-
-@node Links in HTML export
-@subsection Links in HTML export
-
-@cindex links, in HTML export
-@cindex internal links, in HTML export
-@cindex external links, in HTML export
-
-The HTML export back-end transforms Org's internal links (see
-@ref{Internal Links}) to equivalent HTML links in the output.  The back-end
-similarly handles Org's automatic links created by radio targets (see
-@ref{Radio Targets}) similarly.  For Org links to external files, the
-back-end transforms the links to @emph{relative} paths.
-
-@vindex org-html-link-org-files-as-html
-For Org links to other @samp{.org} files, the back-end automatically
-changes the file extension to @samp{.html} and makes file paths relative.
-If the @samp{.org} files have an equivalent @samp{.html} version at the same
-location, then the converted links should work without any further
-manual intervention.  However, to disable this automatic path
-translation, set @code{org-html-link-org-files-as-html} to @code{nil}.  When
-disabled, the HTML export back-end substitutes the ID-based links in
-the HTML output.  For more about linking files when publishing to
-a directory, see @ref{Publishing links}.
-
-Org files can also have special directives to the HTML export
-back-end.  For example, by using @samp{#+ATTR_HTML} lines to specify new
-format attributes to @code{<a>} or @code{<img>} tags.  This example shows
-changing the link's title and style:
-
-@cindex @samp{ATTR_HTML}, keyword
-@example
-#+ATTR_HTML: :title The Org mode homepage :style color:red;
-[[https://orgmode.org]]
-@end example
-
-@node Tables in HTML export
-@subsection Tables in HTML export
-
-@cindex tables, in HTML
-@vindex org-export-html-table-tag
-
-The HTML export back-end uses @code{org-html-table-default-attributes} when
-exporting Org tables to HTML@.  By default, the exporter does not draw
-frames and cell borders.  To change for this for a table, use the
-following lines before the table in the Org file:
-
-@cindex @samp{CAPTION}, keyword
-@cindex @samp{ATTR_HTML}, keyword
-@example
-#+CAPTION: This is a table with lines around and between cells
-#+ATTR_HTML: :border 2 :rules all :frame border
-@end example
-
-The HTML export back-end preserves column groupings in Org tables (see
-@ref{Column Groups}) when exporting to HTML@.
-
-Additional options for customizing tables for HTML export.
-
-@table @asis
-@item @code{org-html-table-align-individual-fields}
-@vindex org-html-table-align-individual-fields
-Non-@code{nil} attaches style attributes for alignment to each table
-field.
-
-@item @code{org-html-table-caption-above}
-@vindex org-html-table-caption-above
-Non-@code{nil} places caption string at the beginning of the table.
-
-@item @code{org-html-table-data-tags}
-@vindex org-html-table-data-tags
-Opening and ending tags for table data fields.
-
-@item @code{org-html-table-default-attributes}
-@vindex org-html-table-default-attributes
-Default attributes and values for table tags.
-
-@item @code{org-html-table-header-tags}
-@vindex org-html-table-header-tags
-Opening and ending tags for table's header fields.
-
-@item @code{org-html-table-row-tags}
-@vindex org-html-table-row-tags
-Opening and ending tags for table rows.
-
-@item @code{org-html-table-use-header-tags-for-first-column}
-@vindex org-html-table-use-header-tags-for-first-column
-Non-@code{nil} formats column one in tables with header tags.
-@end table
-
-@node Images in HTML export
-@subsection Images in HTML export
-
-@cindex images, inline in HTML
-@cindex inlining images in HTML
-
-The HTML export back-end has features to convert Org image links to
-HTML inline images and HTML clickable image links.
-
-@vindex org-html-inline-images
-When the link in the Org file has no description, the HTML export
-back-end by default in-lines that image.  For example:
-@samp{[[file:myimg.jpg]]} is in-lined, while @samp{[[file:myimg.jpg][the 
image]]} links to the text,
-@samp{the image}.  For more details, see the variable
-@code{org-html-inline-images}.
-
-On the other hand, if the description part of the Org link is itself
-another link, such as @samp{file:} or @samp{http:} URL pointing to an image, 
the
-HTML export back-end in-lines this image and links to the main image.
-This Org syntax enables the back-end to link low-resolution thumbnail
-to the high-resolution version of the image, as shown in this example:
-
-@example
-[[file:highres.jpg][file:thumb.jpg]]
-@end example
-
-
-To change attributes of in-lined images, use @samp{#+ATTR_HTML} lines in
-the Org file.  This example shows realignment to right, and adds @code{alt}
-and @code{title} attributes in support of text viewers and modern web
-accessibility standards.
-
-@cindex @samp{CAPTION}, keyword
-@cindex @samp{ATTR_HTML}, keyword
-@example
-#+CAPTION: A black cat stalking a spider
-#+ATTR_HTML: :alt cat/spider image :title Action! :align right
-[[./img/a.jpg]]
-@end example
-
-The HTML export back-end copies the @samp{http} links from the Org file
-as-is.
-
-@node Math formatting in HTML export
-@subsection Math formatting in HTML export
-
-@cindex MathJax
-@cindex dvipng
-@cindex dvisvgm
-@cindex ImageMagick
-
-@vindex org-html-mathjax-options~
-@LaTeX{} math snippets (see @ref{@LaTeX{} fragments}) can be displayed in two
-different ways on HTML pages.  The default is to use the 
@uref{http://www.mathjax.org, MathJax},
-which should work out of the box with Org@footnote{By default Org loads 
MathJax from @uref{https://cdnjs.com, cdnjs.com} as recommended by
-@uref{http://www.mathjax.org, MathJax}.}@footnote{Please note that exported 
formulas are part of an HTML
-document, and that signs such as @samp{<}, @samp{>}, or @samp{&} have special
-meanings.  See 
@uref{http://docs.mathjax.org/en/latest/tex.html#tex-and-latex-in-html-documents,
 MathJax @TeX{} and @LaTeX{} support}.}.  Some MathJax
-display options can be configured via @code{org-html-mathjax-options}, or
-in the buffer.  For example, with the following settings,
-
-@example
-#+HTML_MATHJAX: align: left indent: 5em tagside: left font: Neo-Euler
-#+HTML_MATHJAX: cancel.js noErrors.js
-@end example
-
-@noindent
-equation labels are displayed on the left margin and equations are
-five em from the left margin.  In addition, it loads the two MathJax
-extensions @samp{cancel.js} and @samp{noErrors.js}@footnote{See 
@uref{http://docs.mathjax.org/en/latest/tex.html#tex-extensions, @TeX{} and 
@LaTeX{} extensions} in the @uref{http://docs.mathjax.org, MathJax manual} to 
learn
-about extensions.}.
-
-@vindex org-html-mathjax-template
-See the docstring of @code{org-html-mathjax-options} for all supported
-variables.  The MathJax template can be configure via
-@code{org-html-mathjax-template}.
-
-If you prefer, you can also request that @LaTeX{} fragments are processed
-into small images that will be inserted into the browser page.  Before
-the availability of MathJax, this was the default method for Org
-files.  This method requires that the dvipng program, dvisvgm or
-ImageMagick suite is available on your system.  You can still get this
-processing with
-
-@example
-#+OPTIONS: tex:dvipng
-@end example
-
-
-@example
-#+OPTIONS: tex:dvisvgm
-@end example
-
-
-@noindent
-or
-
-@example
-#+OPTIONS: tex:imagemagick
-@end example
-
-@node Text areas in HTML export
-@subsection Text areas in HTML export
-
-@cindex text areas, in HTML
-Before Org mode's Babel, one popular approach to publishing code in
-HTML was by using @samp{:textarea}.  The advantage of this approach was
-that copying and pasting was built into browsers with simple
-JavaScript commands.  Even editing before pasting was made simple.
-
-The HTML export back-end can create such text areas.  It requires an
-@samp{#+ATTR_HTML} line as shown in the example below with the @samp{:textarea}
-option.  This must be followed by either an example or a source code
-block.  Other Org block types do not honor the @samp{:textarea} option.
-
-By default, the HTML export back-end creates a text area 80 characters
-wide and height just enough to fit the content.  Override these
-defaults with @samp{:width} and @samp{:height} options on the 
@samp{#+ATTR_HTML}
-line.
-
-@example
-#+ATTR_HTML: :textarea t :width 40
-#+BEGIN_EXAMPLE
-  (defun org-xor (a b)
-     "Exclusive or."
-     (if a (not b) b))
-#+END_EXAMPLE
-@end example
-
-@node CSS support
-@subsection CSS support
-
-@cindex CSS, for HTML export
-@cindex HTML export, CSS
-
-@vindex org-export-html-todo-kwd-class-prefix
-@vindex org-export-html-tag-class-prefix
-You can modify the CSS style definitions for the exported file.  The
-HTML exporter assigns the following special CSS classes@footnote{If the 
classes on TODO keywords and tags lead to conflicts,
-use the variables @code{org-html-todo-kwd-class-prefix} and
-@code{org-html-tag-class-prefix} to make them unique.} to
-appropriate parts of the document---your style specifications may
-change these, in addition to any of the standard classes like for
-headlines, tables, etc.
-
-@multitable {aaaaaaaaaaaaaaaaaaaa} 
{aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa}
-@item @code{p.author}
-@tab author information, including email
-@item @code{p.date}
-@tab publishing date
-@item @code{p.creator}
-@tab creator info, about org mode version
-@item @code{.title}
-@tab document title
-@item @code{.subtitle}
-@tab document subtitle
-@item @code{.todo}
-@tab TODO keywords, all not-done states
-@item @code{.done}
-@tab the DONE keywords, all states that count as done
-@item @code{.WAITING}
-@tab each TODO keyword also uses a class named after itself
-@item @code{.timestamp}
-@tab timestamp
-@item @code{.timestamp-kwd}
-@tab keyword associated with a timestamp, like @samp{SCHEDULED}
-@item @code{.timestamp-wrapper}
-@tab span around keyword plus timestamp
-@item @code{.tag}
-@tab tag in a headline
-@item @code{._HOME}
-@tab each tag uses itself as a class, ``@@'' replaced by ``_''
-@item @code{.target}
-@tab target for links
-@item @code{.linenr}
-@tab the line number in a code example
-@item @code{.code-highlighted}
-@tab for highlighting referenced code lines
-@item @code{div.outline-N}
-@tab div for outline level N (headline plus text)
-@item @code{div.outline-text-N}
-@tab extra div for text at outline level N
-@item @code{.section-number-N}
-@tab section number in headlines, different for each level
-@item @code{.figure-number}
-@tab label like ``Figure 1:''
-@item @code{.table-number}
-@tab label like ``Table 1:''
-@item @code{.listing-number}
-@tab label like ``Listing 1:''
-@item @code{div.figure}
-@tab how to format an in-lined image
-@item @code{pre.src}
-@tab formatted source code
-@item @code{pre.example}
-@tab normal example
-@item @code{p.verse}
-@tab verse paragraph
-@item @code{div.footnotes}
-@tab footnote section headline
-@item @code{p.footnote}
-@tab footnote definition paragraph, containing a footnote
-@item @code{.footref}
-@tab a footnote reference number (always a <sup>)
-@item @code{.footnum}
-@tab footnote number in footnote definition (always <sup>)
-@item @code{.org-svg}
-@tab default class for a linked @samp{.svg} image
-@end multitable
-
-@vindex org-html-style-default
-@vindex org-html-head
-@vindex org-html-head-extra
-@cindex @samp{HTML_INCLUDE_STYLE}, keyword
-The HTML export back-end includes a compact default style in each
-exported HTML file.  To override the default style with another style,
-use these keywords in the Org file.  They will replace the global
-defaults the HTML exporter uses.
-
-@cindex @samp{HTML_HEAD}, keyword
-@cindex @samp{HTML_HEAD_EXTRA}, keyword
-@example
-#+HTML_HEAD: <link rel="stylesheet" type="text/css" href="style1.css" />
-#+HTML_HEAD_EXTRA: <link rel="alternate stylesheet" type="text/css" 
href="style2.css" />
-@end example
-
-@vindex org-html-head-include-default-style
-To just turn off the default style, customize
-@code{org-html-head-include-default-style} variable, or use this option
-line in the Org file.
-
-@cindex @samp{html-style}, @samp{OPTIONS} item
-@example
-#+OPTIONS: html-style:nil
-@end example
-
-
-For longer style definitions, either use several @samp{HTML_HEAD} and
-@samp{HTML_HEAD_EXTRA} keywords, or use @code{<style> ... </style>} blocks
-around them.  Both of these approaches can avoid referring to an
-external file.
-
-@cindex @samp{HTML_CONTAINER_CLASS}, property
-@cindex @samp{HTML_HEADLINE_CLASS}, property
-In order to add styles to a sub-tree, use the @samp{HTML_CONTAINER_CLASS}
-property to assign a class to the tree.  In order to specify CSS
-styles for a particular headline, you can use the ID specified in
-a @samp{CUSTOM_ID} property.  You can also assign a specific class to
-a headline with the @samp{HTML_HEADLINE_CLASS} property.
-
-Never change the @code{org-html-style-default} constant.  Instead use other
-simpler ways of customizing as described above.
-
-@node JavaScript support
-@subsection JavaScript supported display of web pages
-
-Sebastian Rose has written a JavaScript program especially designed to
-allow two different ways of viewing HTML files created with Org.  One
-is an @emph{Info}-like mode where each section is displayed separately and
-navigation can be done with the @kbd{n} and @kbd{p} keys, and some other
-keys as well, press @kbd{?} for an overview of the available keys.  The
-second one has a @emph{folding} view, much like Org provides inside Emacs.
-The script is available at @uref{https://orgmode.org/org-info.js} and the
-documentation at @uref{https://orgmode.org/worg/code/org-info-js/}.  The
-script is hosted on @uref{https://orgmode.org}, but for reliability, prefer
-installing it on your own web server.
-
-To use this program, just add this line to the Org file:
-
-@cindex @samp{INFOJS_OPT}, keyword
-@example
-#+INFOJS_OPT: view:info toc:nil
-@end example
-
-
-@noindent
-The HTML header now has the code needed to automatically invoke the
-script.  For setting options, use the syntax from the above line for
-options described below:
-
-@table @asis
-@item @samp{path:}
-The path to the script.  The default is to grab the script from
-@uref{https://orgmode.org/org-info.js}, but you might want to have a local
-copy and use a path like @samp{../scripts/org-info.js}.
-
-@item @samp{view:}
-Initial view when the website is first shown.  Possible values are:
-
-@multitable {aaaaaaaaaa} 
{aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa}
-@item @samp{info}
-@tab Info-like interface with one section per page
-@item @samp{overview}
-@tab Folding interface, initially showing only top-level
-@item @samp{content}
-@tab Folding interface, starting with all headlines visible
-@item @samp{showall}
-@tab Folding interface, all headlines and text visible
-@end multitable
-
-@item @samp{sdepth:}
-Maximum headline level still considered as an independent section
-for info and folding modes.  The default is taken from
-@code{org-export-headline-levels}, i.e., the @samp{H} switch in 
@samp{OPTIONS}.  If
-this is smaller than in @code{org-export-headline-levels}, each
-info/folding section can still contain child headlines.
-
-@item @samp{toc:}
-Should the table of contents @emph{initially} be visible?  Even when
-@samp{nil}, you can always get to the ``toc'' with @kbd{i}.
-
-@item @samp{tdepth:}
-The depth of the table of contents.  The defaults are taken from the
-variables @code{org-export-headline-levels} and @code{org-export-with-toc}.
-
-@item @samp{ftoc:}
-Does the CSS of the page specify a fixed position for the ``toc''?  If
-yes, the toc is displayed as a section.
-
-@item @samp{ltoc:}
-Should there be short contents (children) in each section?  Make
-this @samp{above} if the section should be above initial text.
-
-@item @samp{mouse:}
-Headings are highlighted when the mouse is over them.  Should be
-@samp{underline} (default) or a background color like @samp{#cccccc}.
-
-@item @samp{buttons:}
-Should view-toggle buttons be everywhere?  When @samp{nil} (the default),
-only one such button is present.
-@end table
-
-@vindex org-infojs-options
-@vindex org-export-html-use-infojs
-You can choose default values for these options by customizing the
-variable @code{org-infojs-options}.  If you always want to apply the script
-to your pages, configure the variable @code{org-export-html-use-infojs}.
-
-@node @LaTeX{} Export
-@section @LaTeX{} Export
-
-@cindex @LaTeX{} export
-@cindex PDF export
-
-The @LaTeX{} export back-end can handle complex documents, incorporate
-standard or custom @LaTeX{} document classes, generate documents using
-alternate @LaTeX{} engines, and produce fully linked PDF files with
-indexes, bibliographies, and tables of contents, destined for
-interactive online viewing or high-quality print publication.
-
-While the details are covered in-depth in this section, here are some
-quick references to variables for the impatient: for engines, see
-@code{org-latex-compiler}; for build sequences, see
-@code{org-latex-pdf-process}; for packages, see
-@code{org-latex-default-packages-alist} and @code{org-latex-packages-alist}.
-
-An important note about the @LaTeX{} export back-end: it is sensitive to
-blank lines in the Org document.  That's because @LaTeX{} itself depends
-on blank lines to tell apart syntactical elements, such as paragraphs.
-
-@menu
-* @LaTeX{}/PDF export commands:: For producing @LaTeX{} and PDF documents.
-* @LaTeX{} specific export settings:: Unique to this @LaTeX{} back-end.
-* @LaTeX{} header and sectioning:: Setting up the export file structure.
-* Quoting @LaTeX{} code::        Incorporating literal @LaTeX{} code.
-* Tables in @LaTeX{} export::    Options for exporting tables to @LaTeX{}.
-* Images in @LaTeX{} export::    How to insert figures into @LaTeX{} output.
-* Plain lists in @LaTeX{} export:: Attributes specific to lists.
-* Source blocks in @LaTeX{} export:: Attributes specific to source code blocks.
-* Example blocks in @LaTeX{} export:: Attributes specific to example blocks.
-* Special blocks in @LaTeX{} export:: Attributes specific to special blocks.
-* Horizontal rules in @LaTeX{} export:: Attributes specific to horizontal 
rules.
-@end menu
-
-@node @LaTeX{}/PDF export commands
-@subsection @LaTeX{}/PDF export commands
-
-@table @asis
-@item @kbd{C-c C-e l l} (@code{org-latex-export-to-latex})
-@kindex C-c C-e l l
-@findex org-latex-export-to-latex~
-Export to a @LaTeX{} file with a @samp{.tex} extension.  For @samp{myfile.org},
-Org exports to @samp{myfile.tex}, overwriting without warning.
-
-@item @kbd{C-c C-e l L} (@code{org-latex-export-as-latex})
-@kindex C-c C-e l L
-@findex org-latex-export-as-latex
-Export to a temporary buffer.  Do not create a file.
-
-@item @kbd{C-c C-e l p} (@code{org-latex-export-to-pdf})
-@kindex C-c C-e l p
-@findex org-latex-export-to-pdf
-Export as @LaTeX{} file and convert it to PDF file.
-
-@item @kbd{C-c C-e l o}
-@kindex C-c C-e l o
-Export as @LaTeX{} file and convert it to PDF, then open the PDF using
-the default viewer.
-
-@item @kbd{M-x org-export-region-as-latex}
-Convert the region to @LaTeX{} under the assumption that it was in Org
-mode syntax before.  This is a global command that can be invoked in
-any buffer.
-@end table
-
-@vindex org-latex-compiler
-@vindex org-latex-bibtex-compiler
-@vindex org-latex-default-packages-alist
-@cindex pdflatex
-@cindex xelatex
-@cindex lualatex
-@cindex @samp{LATEX_COMPILER}, keyword
-The @LaTeX{} export back-end can use any of these @LaTeX{} engines:
-@samp{pdflatex}, @samp{xelatex}, and @samp{lualatex}.  These engines compile 
@LaTeX{}
-files with different compilers, packages, and output options.  The
-@LaTeX{} export back-end finds the compiler version to use from
-@code{org-latex-compiler} variable or the @samp{#+LATEX_COMPILER} keyword in 
the
-Org file.  See the docstring for the
-@code{org-latex-default-packages-alist} for loading packages with certain
-compilers.  Also see @code{org-latex-bibtex-compiler} to set the
-bibliography compiler@footnote{This does not allow setting different 
bibliography compilers
-for different files.  However, ``smart'' @LaTeX{} compilation systems, such
-as latexmk, can select the correct bibliography compiler.}.
-
-@node @LaTeX{} specific export settings
-@subsection @LaTeX{} specific export settings
-
-The @LaTeX{} export back-end has several additional keywords for
-customizing @LaTeX{} output.  Setting these keywords works similar to the
-general options (see @ref{Export Settings}).
-
-@table @asis
-@item @samp{DESCRIPTION}
-@cindex @samp{DESCRIPTION}, keyword
-@vindex org-latex-hyperref-template
-@vindex org-latex-title-command
-The document's description.  The description along with author name,
-keywords, and related file metadata are inserted in the output file
-by the hyperref package.  See @code{org-latex-hyperref-template} for
-customizing metadata items.  See @code{org-latex-title-command} for
-typesetting description into the document's front matter.  Use
-multiple @samp{DESCRIPTION} keywords for long descriptions.
-
-@item @samp{LANGUAGE}
-@cindex @samp{LANGUAGE}, keyword
-@vindex org-latex-packages-alist
-In order to be effective, the @samp{babel} or @samp{polyglossia}
-packages---according to the @LaTeX{} compiler used---must be loaded
-with the appropriate language as argument.  This can be accomplished
-by modifying the @code{org-latex-packages-alist} variable, e.g., with the
-following snippet:
-
-@lisp
-(add-to-list 'org-latex-packages-alist
-             '("AUTO" "babel" t ("pdflatex")))
-(add-to-list 'org-latex-packages-alist
-             '("AUTO" "polyglossia" t ("xelatex" "lualatex")))
-@end lisp
-
-@item @samp{LATEX_CLASS}
-@cindex @samp{LATEX_CLASS}, keyword
-@vindex org-latex-default-class
-@vindex org-latex-classes
-This is @LaTeX{} document class, such as @emph{article}, @emph{report}, 
@emph{book},
-and so on, which contain predefined preamble and headline level
-mapping that the @LaTeX{} export back-end needs.  The back-end reads
-the default class name from the @code{org-latex-default-class} variable.
-Org has @emph{article} as the default class.  A valid default class must
-be an element of @code{org-latex-classes}.
-
-@item @samp{LATEX_CLASS_OPTIONS}
-@cindex @samp{LATEX_CLASS_OPTIONS}, keyword
-Options the @LaTeX{} export back-end uses when calling the @LaTeX{}
-document class.
-
-@item @samp{LATEX_COMPILER}
-@cindex @samp{LATEX_COMPILER}, keyword
-@vindex org-latex-compiler
-The compiler, such as @samp{pdflatex}, @samp{xelatex}, @samp{lualatex}, for
-producing the PDF@.  See @code{org-latex-compiler}.
-
-@item @samp{LATEX_HEADER}
-@itemx @samp{LATEX_HEADER_EXTRA}
-@cindex @samp{LATEX_HEADER}, keyword
-@cindex @samp{LATEX_HEADER_EXTRA}, keyword
-@vindex org-latex-classes
-Arbitrary lines to add to the document's preamble, before the
-hyperref settings.  See @code{org-latex-classes} for adjusting the
-structure and order of the @LaTeX{} headers.
-
-@item @samp{KEYWORDS}
-@cindex @samp{KEYWORDS}, keyword
-@vindex org-latex-hyperref-template
-@vindex org-latex-title-command
-The keywords for the document.  The description along with author
-name, keywords, and related file metadata are inserted in the output
-file by the hyperref package.  See @code{org-latex-hyperref-template} for
-customizing metadata items.  See @code{org-latex-title-command} for
-typesetting description into the document's front matter.  Use
-multiple @samp{KEYWORDS} lines if necessary.
-
-@item @samp{SUBTITLE}
-@cindex @samp{SUBTITLE}, keyword
-@vindex org-latex-subtitle-separate
-@vindex org-latex-subtitle-format
-The document's subtitle.  It is typeset as per
-@code{org-latex-subtitle-format}.  If @code{org-latex-subtitle-separate} is
-non-@code{nil}, it is typed outside of the @code{\title} macro.  See
-@code{org-latex-hyperref-template} for customizing metadata items.  See
-@code{org-latex-title-command} for typesetting description into the
-document's front matter.
-@end table
-
-The following sections have further details.
-
-@node @LaTeX{} header and sectioning
-@subsection @LaTeX{} header and sectioning structure
-
-@cindex @LaTeX{} class
-@cindex @LaTeX{} sectioning structure
-@cindex @LaTeX{} header
-@cindex header, for @LaTeX{} files
-@cindex sectioning structure, for @LaTeX{} export
-
-The @LaTeX{} export back-end converts the first three of Org's outline
-levels into @LaTeX{} headlines.  The remaining Org levels are exported as
-lists.  To change this globally for the cut-off point between levels
-and lists, (see @ref{Export Settings}).
-
-By default, the @LaTeX{} export back-end uses the @emph{article} class.
-
-@vindex org-latex-default-class
-@vindex org-latex-classes
-@vindex org-latex-default-packages-alist
-@vindex org-latex-packages-alist
-To change the default class globally, edit @code{org-latex-default-class}.
-To change the default class locally in an Org file, add option lines
-@samp{#+LATEX_CLASS: myclass}.  To change the default class for just a part
-of the Org file, set a sub-tree property, @samp{EXPORT_LATEX_CLASS}.  The
-class name entered here must be valid member of @code{org-latex-classes}.
-This variable defines a header template for each class into which the
-exporter splices the values of @code{org-latex-default-packages-alist} and
-@code{org-latex-packages-alist}.  Use the same three variables to define
-custom sectioning or custom classes.
-
-@cindex @samp{LATEX_CLASS}, keyword
-@cindex @samp{LATEX_CLASS_OPTIONS}, keyword
-@cindex @samp{EXPORT_LATEX_CLASS}, property
-@cindex @samp{EXPORT_LATEX_CLASS_OPTIONS}, property
-The @LaTeX{} export back-end sends the @samp{LATEX_CLASS_OPTIONS} keyword and
-@samp{EXPORT_LATEX_CLASS_OPTIONS} property as options to the @LaTeX{}
-@code{\documentclass} macro.  The options and the syntax for specifying
-them, including enclosing them in square brackets, follow @LaTeX{}
-conventions.
-
-@example
-#+LATEX_CLASS_OPTIONS: [a4paper,11pt,twoside,twocolumn]
-@end example
-
-
-@cindex @samp{LATEX_HEADER}, keyword
-@cindex @samp{LATEX_HEADER_EXTRA}, keyword
-The @LaTeX{} export back-end appends values from @samp{LATEX_HEADER} and
-@samp{LATEX_HEADER_EXTRA} keywords to the @LaTeX{} header.  The docstring for
-@code{org-latex-classes} explains in more detail.  Also note that @LaTeX{}
-export back-end does not append @samp{LATEX_HEADER_EXTRA} to the header
-when previewing @LaTeX{} snippets (see @ref{Previewing @LaTeX{} fragments}).
-
-A sample Org file with the above headers:
-
-@example
-#+LATEX_CLASS: article
-#+LATEX_CLASS_OPTIONS: [a4paper]
-#+LATEX_HEADER: \usepackage@{xyz@}
-
-* Headline 1
-  some text
-* Headline 2
-  some more text
-@end example
-
-@node Quoting @LaTeX{} code
-@subsection Quoting @LaTeX{} code
-
-The @LaTeX{} export back-end can insert any arbitrary @LaTeX{} code, see
-@ref{Embedded @LaTeX{}}.  There are three ways to embed such code in the Org
-file and they all use different quoting syntax.
-
-@cindex inline, in @LaTeX{} export
-Inserting in-line quoted with @@ symbols:
-
-@example
-Code embedded in-line @@@@latex:any arbitrary LaTeX code@@@@ in a paragraph.
-@end example
-
-
-@cindex @samp{LATEX}, keyword
-Inserting as one or more keyword lines in the Org file:
-
-@example
-#+LATEX: any arbitrary LaTeX code
-@end example
-
-
-@cindex @samp{BEGIN_EXPORT latex}
-Inserting as an export block in the Org file, where the back-end
-exports any code between begin and end markers:
-
-@example
-#+BEGIN_EXPORT latex
-  any arbitrary LaTeX code
-#+END_EXPORT
-@end example
-
-@node Tables in @LaTeX{} export
-@subsection Tables in @LaTeX{} export
-
-@cindex tables, in @LaTeX{} export
-
-The @LaTeX{} export back-end can pass several @LaTeX{} attributes for table
-contents and layout.  Besides specifying a label (see @ref{Internal Links})
-and a caption (see @ref{Captions}), the other valid @LaTeX{} attributes
-include:
-
-@table @asis
-@item @samp{:mode}
-@vindex org-latex-default-table-mode
-The @LaTeX{} export back-end wraps the table differently depending on
-the mode for accurate rendering of math symbols.  Mode is either
-@samp{table}, @samp{math}, @samp{inline-math} or @samp{verbatim}.
-
-For @samp{math} or @samp{inline-math} mode, @LaTeX{} export back-end wraps the
-table in a math environment, but every cell in it is exported as-is.
-The @LaTeX{} export back-end determines the default mode from
-@code{org-latex-default-table-mode}.  The @LaTeX{} export back-end merges
-contiguous tables in the same mode into a single environment.
-
-@item @samp{:environment}
-@vindex org-latex-default-table-environment
-Set the default @LaTeX{} table environment for the @LaTeX{} export
-back-end to use when exporting Org tables.  Common @LaTeX{} table
-environments are provided by these packages: tabularx, longtable,
-array, tabu, and bmatrix.  For packages, such as tabularx and tabu,
-or any newer replacements, include them in the
-@code{org-latex-packages-alist} variable so the @LaTeX{} export back-end can
-insert the appropriate load package headers in the converted @LaTeX{}
-file.  Look in the docstring for the @code{org-latex-packages-alist}
-variable for configuring these packages for @LaTeX{} snippet previews,
-if any.
-
-@item @samp{:caption}
-Use @samp{CAPTION} keyword to set a simple caption for a table (see
-@ref{Captions}).  For custom captions, use @samp{:caption} attribute, which
-accepts raw @LaTeX{} code.  @samp{:caption} value overrides @samp{CAPTION} 
value.
-
-@item @samp{:float}
-@itemx @samp{:placement}
-The table environments by default are not floats in @LaTeX{}.  To make
-them floating objects use @samp{:float} with one of the following
-options: @samp{sideways}, @samp{multicolumn}, @samp{t}, and @samp{nil}.
-
-@LaTeX{} floats can also have additional layout @samp{:placement}
-attributes.  These are the usual @samp{[h t b p ! H]} permissions
-specified in square brackets.  Note that for @samp{:float sideways}
-tables, the @LaTeX{} export back-end ignores @samp{:placement} attributes.
-
-@item @samp{:align}
-@itemx @samp{:font}
-@itemx @samp{:width}
-The @LaTeX{} export back-end uses these attributes for regular tables
-to set their alignments, fonts, and widths.
-
-@item @samp{:spread}
-When @samp{:spread} is non-@code{nil}, the @LaTeX{} export back-end spreads or
-shrinks the table by the @samp{:width} for tabu and longtabu
-environments.  @samp{:spread} has no effect if @samp{:width} is not set.
-
-@item @samp{:booktabs}
-@itemx @samp{:center}
-@itemx @samp{:rmlines}
-@vindex org-latex-tables-booktabs
-@vindex org-latex-tables-centered
-All three commands are toggles.  @samp{:booktabs} brings in modern
-typesetting enhancements to regular tables.  The booktabs package
-has to be loaded through @code{org-latex-packages-alist}.  @samp{:center} is
-for centering the table.  @samp{:rmlines} removes all but the very first
-horizontal line made of ASCII characters from ``table.el'' tables
-only.
-
-@item @samp{:math-prefix}
-@itemx @samp{:math-suffix}
-@itemx @samp{:math-arguments}
-The @LaTeX{} export back-end inserts @samp{:math-prefix} string value in
-a math environment before the table.  The @LaTeX{} export back-end
-inserts @samp{:math-suffix} string value in a math environment after the
-table.  The @LaTeX{} export back-end inserts @samp{:math-arguments} string
-value between the macro name and the table's contents.
-@samp{:math-arguments} comes in use for matrix macros that require more
-than one argument, such as @samp{qbordermatrix}.
-@end table
-
-@LaTeX{} table attributes help formatting tables for a wide range of
-situations, such as matrix product or spanning multiple pages:
-
-@example
-#+ATTR_LATEX: :environment longtable :align l|lp@{3cm@}r|l
-| ... | ... |
-| ... | ... |
-
-#+ATTR_LATEX: :mode math :environment bmatrix :math-suffix \times
-| a | b |
-| c | d |
-#+ATTR_LATEX: :mode math :environment bmatrix
-| 1 | 2 |
-| 3 | 4 |
-@end example
-
-Set the caption with the @LaTeX{} command
-@samp{\bicaption@{HeadingA@}@{HeadingB@}}:
-
-@example
-#+ATTR_LATEX: :caption \bicaption@{HeadingA@}@{HeadingB@}
-| ... | ... |
-| ... | ... |
-@end example
-
-@node Images in @LaTeX{} export
-@subsection Images in @LaTeX{} export
-
-@cindex images, inline in LaTeX
-@cindex inlining images in LaTeX
-@cindex @samp{ATTR_LATEX}, keyword
-
-The @LaTeX{} export back-end processes image links in Org files that do
-not have descriptions, such as these links @samp{[[file:img.jpg]]} or
-@samp{[[./img.jpg]]}, as direct image insertions in the final PDF output.  In
-the PDF, they are no longer links but actual images embedded on the
-page.  The @LaTeX{} export back-end uses @samp{\includegraphics} macro to
-insert the image.  But for TikZ (@uref{http://sourceforge.net/projects/pgf/})
-images, the back-end uses an @code{\input} macro wrapped within
-a @code{tikzpicture} environment.
-
-For specifying image @samp{:width}, @samp{:height}, @samp{:scale} and other 
@samp{:options},
-use this syntax:
-
-@example
-#+ATTR_LATEX: :width 5cm :options angle=90
-[[./img/sed-hr4049.pdf]]
-@end example
-
-A @samp{:scale} attribute overrides both @samp{:width} and @samp{:height} 
attributes.
-
-For custom commands for captions, use the @samp{:caption} attribute.  It
-overrides the default @samp{#+CAPTION} value:
-
-@example
-#+ATTR_LATEX: :caption \bicaption@{HeadingA@}@{HeadingB@}
-[[./img/sed-hr4049.pdf]]
-@end example
-
-When captions follow the method as described in @ref{Captions}, the @LaTeX{}
-export back-end wraps the picture in a floating @samp{figure} environment.
-To float an image without specifying a caption, set the @samp{:float}
-attribute to one of the following:
-
-@table @asis
-@item @samp{t}
-For a standard @samp{figure} environment; used by default whenever an
-image has a caption.
-
-@item @samp{multicolumn}
-To span the image across multiple columns of a page; the back-end
-wraps the image in a @samp{figure*} environment.
-
-@item @samp{wrap}
-For text to flow around the image on the right; the figure occupies
-the left half of the page.
-
-@item @samp{sideways}
-For a new page with the image sideways, rotated ninety degrees, in
-a @samp{sidewaysfigure} environment; overrides @samp{:placement} setting.
-
-@item @samp{nil}
-To avoid a @samp{:float} even if using a caption.
-@end table
-
-Use the @samp{placement} attribute to modify a floating environment's
-placement.
-
-@example
-#+ATTR_LATEX: :float wrap :width 0.38\textwidth :placement 
@{r@}@{0.4\textwidth@}
-[[./img/hst.png]]
-@end example
-
-@vindex org-latex-images-centered
-@cindex center image in LaTeX export
-@cindex image, centering in LaTeX export
-The @LaTeX{} export back-end centers all images by default.  Setting
-@samp{:center} to @samp{nil} disables centering.  To disable centering 
globally,
-set @code{org-latex-images-centered} to @samp{t}.
-
-Set the @samp{:comment-include} attribute to non-@code{nil} value for the 
@LaTeX{}
-export back-end to comment out the @samp{\includegraphics} macro.
-
-@node Plain lists in @LaTeX{} export
-@subsection Plain lists in @LaTeX{} export
-
-@cindex plain lists, in @LaTeX{} export
-@cindex @samp{ATTR_LATEX}, keyword
-The @LaTeX{} export back-end accepts the @samp{environment} and @samp{options}
-attributes for plain lists.  Both attributes work together for
-customizing lists, as shown in the examples:
-
-@example
-#+LATEX_HEADER: \usepackage[inline]@{enumitem@}
-Some ways to say "Hello":
-#+ATTR_LATEX: :environment itemize*
-#+ATTR_LATEX: :options [label=@{@}, itemjoin=@{,@}, itemjoin*=@{, and@}]
-- Hola
-- Bonjour
-- Guten Tag.
-@end example
-
-Since @LaTeX{} supports only four levels of nesting for lists, use an
-external package, such as @samp{enumitem} in @LaTeX{}, for levels deeper than
-four:
-
-@example
-#+LATEX_HEADER: \usepackage@{enumitem@}
-#+LATEX_HEADER: \renewlist@{itemize@}@{itemize@}@{9@}
-#+LATEX_HEADER: \setlist[itemize]@{label=$\circ$@}
-- One
-  - Two
-    - Three
-      - Four
-        - Five
-@end example
-
-@node Source blocks in @LaTeX{} export
-@subsection Source blocks in @LaTeX{} export
-
-@cindex source blocks, in @LaTeX{} export
-@cindex @samp{ATTR_LATEX}, keyword
-
-The @LaTeX{} export back-end can make source code blocks into floating
-objects through the attributes @samp{:float} and @samp{:options}.  For 
@samp{:float}:
-
-@table @asis
-@item @samp{t}
-Makes a source block float; by default floats any source block with
-a caption.
-
-@item @samp{multicolumn}
-Spans the source block across multiple columns of a page.
-
-@item @samp{nil}
-Avoids a @samp{:float} even if using a caption; useful for source code
-blocks that may not fit on a page.
-@end table
-
-@example
-#+ATTR_LATEX: :float nil
-#+BEGIN_SRC emacs-lisp
-  Lisp code that may not fit in a single page.
-#+END_SRC
-@end example
-
-@vindex org-latex-listings-options
-@vindex org-latex-minted-options
-The @LaTeX{} export back-end passes string values in @samp{:options} to 
@LaTeX{}
-packages for customization of that specific source block.  In the
-example below, the @samp{:options} are set for Minted.  Minted is a source
-code highlighting @LaTeX{} package with many configurable options.
-
-@example
-#+ATTR_LATEX: :options commentstyle=\bfseries
-#+BEGIN_SRC emacs-lisp
-  (defun Fib (n)
-    (if (< n 2) n (+ (Fib (- n 1)) (Fib (- n 2)))))
-#+END_SRC
-@end example
-
-To apply similar configuration options for all source blocks in
-a file, use the @code{org-latex-listings-options} and
-@code{org-latex-minted-options} variables.
-
-@node Example blocks in @LaTeX{} export
-@subsection Example blocks in @LaTeX{} export
-
-@cindex example blocks, in @LaTeX{} export
-@cindex verbatim blocks, in @LaTeX{} export
-@cindex @samp{ATTR_LATEX}, keyword
-
-The @LaTeX{} export back-end wraps the contents of example blocks in
-a @samp{verbatim} environment.  To change this behavior to use another
-environment globally, specify an appropriate export filter (see
-@ref{Advanced Export Configuration}).  To change this behavior to use
-another environment for each block, use the @samp{:environment} parameter
-to specify a custom environment.
-
-@example
-#+ATTR_LATEX: :environment myverbatim
-#+BEGIN_EXAMPLE
-  This sentence is false.
-#+END_EXAMPLE
-@end example
-
-@node Special blocks in @LaTeX{} export
-@subsection Special blocks in @LaTeX{} export
-
-@cindex special blocks, in @LaTeX{} export
-@cindex abstract, in @LaTeX{} export
-@cindex proof, in @LaTeX{} export
-@cindex @samp{ATTR_LATEX}, keyword
-
-For other special blocks in the Org file, the @LaTeX{} export back-end
-makes a special environment of the same name.  The back-end also takes
-@samp{:options}, if any, and appends as-is to that environment's opening
-string.  For example:
-
-@example
-#+BEGIN_abstract
-  We demonstrate how to solve the Syracuse problem.
-#+END_abstract
-
-#+ATTR_LATEX: :options [Proof of important theorem]
-#+BEGIN_proof
-  ...
-  Therefore, any even number greater than 2 is the sum of two primes.
-#+END_proof
-@end example
-
-@noindent
-exports to
-
-@example
-\begin@{abstract@}
-  We demonstrate how to solve the Syracuse problem.
-\end@{abstract@}
-
-\begin@{proof@}[Proof of important theorem]
-  ...
-  Therefore, any even number greater than 2 is the sum of two primes.
-\end@{proof@}
-@end example
-
-If you need to insert a specific caption command, use @samp{:caption}
-attribute.  It overrides standard @samp{CAPTION} value, if any.  For
-example:
-
-@example
-#+ATTR_LATEX: :caption \MyCaption@{HeadingA@}
-#+BEGIN_proof
-  ...
-#+END_proof
-@end example
-
-@node Horizontal rules in @LaTeX{} export
-@subsection Horizontal rules in @LaTeX{} export
-
-@cindex horizontal rules, in @LaTeX{} export
-@cindex @samp{ATTR_LATEX}, keyword
-
-The @LaTeX{} export back-end converts horizontal rules by the specified
-@samp{:width} and @samp{:thickness} attributes.  For example:
-
-@example
-#+ATTR_LATEX: :width .6\textwidth :thickness 0.8pt
------
-@end example
-
-@node Markdown Export
-@section Markdown Export
-
-@cindex Markdown export
-
-The Markdown export back-end, ``md'', converts an Org file to Markdown
-format, as defined at @uref{http://daringfireball.net/projects/markdown/}.
-
-Since it is built on top of the HTML back-end (see @ref{HTML Export}), it
-converts every Org construct not defined in Markdown syntax, such as
-tables, to HTML@.
-
-@anchor{Markdown export commands}
-@subheading Markdown export commands
-
-@table @asis
-@item @kbd{C-c C-e m m} (@code{org-md-export-to-markdown})
-@kindex C-c C-c m m
-@findex org-md-export-to-markdown
-Export to a text file with Markdown syntax.  For @samp{myfile.org}, Org
-exports to @samp{myfile.md}, overwritten without warning.
-
-@item @kbd{C-c C-e m M} (@code{org-md-export-as-markdown})
-@kindex C-c C-c m M
-@findex org-md-export-as-markdown
-Export to a temporary buffer.  Does not create a file.
-
-@item @kbd{C-c C-e m o}
-@kindex C-c C-e m o
-Export as a text file with Markdown syntax, then open it.
-@end table
-
-@anchor{Header and sectioning structure (1)}
-@subheading Header and sectioning structure
-
-@vindex org-md-headline-style
-Based on @code{org-md-headline-style}, Markdown export can generate
-headlines of both @emph{atx} and @emph{setext} types.  @emph{atx} limits 
headline
-levels to two whereas @emph{setext} limits headline levels to six.  Beyond
-these limits, the export back-end converts headlines to lists.  To set
-a limit to a level before the absolute limit (see @ref{Export Settings}).
-
-@node OpenDocument Text Export
-@section OpenDocument Text Export
-
-@cindex ODT
-@cindex OpenDocument
-@cindex export, OpenDocument
-@cindex LibreOffice
-
-The ODT export back-end handles creating of OpenDocument Text (ODT)
-format.  Documents created by this exporter use the
-@cite{OpenDocument-v1.2 specification}@footnote{See 
@uref{http://docs.oasis-open.org/office/v1.2/OpenDocument-v1.2.html, Open 
Document Format for Office Applications
-(OpenDocument) Version 1.2}.} and are compatible
-with LibreOffice 3.4.
-
-@menu
-* Pre-requisites for ODT export:: Required packages.
-* ODT export commands::          Invoking export.
-* ODT specific export settings:: Configuration options.
-* Extending ODT export::         Producing DOC, PDF files.
-* Applying custom styles::       Styling the output.
-* Links in ODT export::          Handling and formatting links.
-* Tables in ODT export::         Org tables conversions.
-* Images in ODT export::         Inserting images.
-* Math formatting in ODT export:: Formatting @LaTeX{} fragments.
-* Labels and captions in ODT export:: Rendering objects.
-* Literal examples in ODT export:: For source code and example blocks.
-* Advanced topics in ODT export:: For power users.
-@end menu
-
-@node Pre-requisites for ODT export
-@subsection Pre-requisites for ODT export
-
-@cindex zip
-
-The ODT export back-end relies on the zip program to create the final
-compressed ODT output.  Check if @samp{zip} is locally available and
-executable.  Without it, export cannot finish.
-
-@node ODT export commands
-@subsection ODT export commands
-
-@table @asis
-@item @kbd{C-c C-e o o} (@code{org-export-to-odt})
-@kindex C-c C-e o o
-@findex org-export-to-odt
-Export as OpenDocument Text file.
-
-@cindex @samp{EXPORT_FILE_NAME}, property
-@vindex org-odt-preferred-output-format
-
-If @code{org-odt-preferred-output-format} is specified, the ODT export
-back-end automatically converts the exported file to that format.
-
-For @samp{myfile.org}, Org exports to @samp{myfile.odt}, overwriting without
-warning.  The ODT export back-end exports a region only if a region
-was active.
-
-If the selected region is a single tree, the ODT export back-end
-makes the tree head the document title.  Incidentally, @kbd{C-c @@} selects 
the current sub-tree.  If the tree head entry has, or
-inherits, an @samp{EXPORT_FILE_NAME} property, the ODT export back-end
-uses that for file name.
-
-@item @kbd{C-c C-e o O}
-@kindex C-c C-e o O
-Export as an OpenDocument Text file and open the resulting file.
-
-@vindex org-export-odt-preferred-output-format
-If @code{org-export-odt-preferred-output-format} is specified, open the
-converted file instead.  See @ref{Automatically exporting to other formats}.
-@end table
-
-@node ODT specific export settings
-@subsection ODT specific export settings
-
-The ODT export back-end has several additional keywords for
-customizing ODT output.  Setting these keywords works similar to the
-general options (see @ref{Export Settings}).
-
-@table @asis
-@item @samp{DESCRIPTION}
-@cindex @samp{DESCRIPTION}, keyword
-This is the document's description, which the ODT export back-end
-inserts as document metadata.  For long descriptions, use multiple
-lines, prefixed with @samp{DESCRIPTION}.
-
-@item @samp{KEYWORDS}
-@cindex @samp{KEYWORDS}, keyword
-The keywords for the document.  The ODT export back-end inserts the
-description along with author name, keywords, and related file
-metadata as metadata in the output file.  Use multiple @samp{KEYWORDS} if
-necessary.
-
-@item @samp{ODT_STYLES_FILE}
-@cindex @samp{ODT_STYLES_FILE}, keyword
-@vindex org-odt-styles-file
-The ODT export back-end uses the @code{org-odt-styles-file} by default.
-See @ref{Applying custom styles} for details.
-
-@item @samp{SUBTITLE}
-@cindex @samp{SUBTITLE}, keyword
-The document subtitle.
-@end table
-
-@node Extending ODT export
-@subsection Extending ODT export
-
-The ODT export back-end can produce documents in other formats besides
-ODT using a specialized ODT converter process.  Its common interface
-works with popular converters to produce formats such as @samp{doc}, or
-convert a document from one format, say @samp{csv}, to another format, say
-@samp{xls}.
-
-@cindex @file{unoconv}
-@vindex org-odt-convert-process
-Customize @code{org-odt-convert-process} variable to point to @samp{unoconv},
-which is the ODT's preferred converter.  Working installations of
-LibreOffice would already have @samp{unoconv} installed.  Alternatively,
-other converters may be substituted here.  See @ref{Configuring a document 
converter}.
-
-@anchor{Automatically exporting to other formats}
-@subsubheading Automatically exporting to other formats
-
-@vindex org-odt-preferred-output-format
-If ODT format is just an intermediate step to get to other formats,
-such as @samp{doc}, @samp{docx}, @samp{rtf}, or @samp{pdf}, etc., then extend 
the ODT
-export back-end to directly produce that format.  Specify the final
-format in the @code{org-odt-preferred-output-format} variable.  This is one
-way to extend (see @ref{ODT export commands}).
-
-@anchor{Converting between document formats}
-@subsubheading Converting between document formats
-
-The Org export back-end is made to be inter-operable with a wide range
-of text document format converters.  Newer generation converters, such
-as LibreOffice and Pandoc, can handle hundreds of formats at once.
-Org provides a consistent interaction with whatever converter is
-installed.  Here are some generic commands:
-
-@table @asis
-@item @kbd{M-x org-odt-convert}
-@findex org-odt-convert
-Convert an existing document from one format to another.  With
-a prefix argument, opens the newly produced file.
-@end table
-
-@node Applying custom styles
-@subsection Applying custom styles
-
-@cindex styles, custom
-@cindex template, custom
-
-The ODT export back-end comes with many OpenDocument styles (see
-@ref{Working with OpenDocument style files}).  To expand or further
-customize these built-in style sheets, either edit the style sheets
-directly or generate them using an application such as LibreOffice.
-The example here shows creating a style using LibreOffice.
-
-@anchor{Applying custom styles the easy way}
-@subsubheading Applying custom styles: the easy way
-
-@enumerate
-@item
-Create a sample @samp{example.org} file with settings as shown below,
-and export it to ODT format.
-
-@example
-#+OPTIONS: H:10 num:t
-@end example
-
-@item
-Open the above @samp{example.odt} using LibreOffice.  Use the @emph{Stylist}
-to locate the target styles, which typically have the ``Org'' prefix.
-Open one, modify, and save as either OpenDocument Text (ODT) or
-OpenDocument Template (OTT) file.
-
-@item
-@vindex org-odt-styles-file
-Customize the variable @code{org-odt-styles-file} and point it to the
-newly created file.  For additional configuration options, see
-@ref{x-overriding-factory-styles, , Overriding factory styles}.
-
-@cindex @samp{ODT_STYLES_FILE}, keyword
-To apply an ODT style to a particular file, use the
-@samp{ODT_STYLES_FILE} keyword as shown in the example below:
-
-@example
-#+ODT_STYLES_FILE: "/path/to/example.ott"
-@end example
-
-
-@noindent
-or
-
-@example
-#+ODT_STYLES_FILE: ("/path/to/file.ott" ("styles.xml" "image/hdr.png"))
-@end example
-@end enumerate
-
-@anchor{Using third-party styles and templates}
-@subsubheading Using third-party styles and templates
-
-The ODT export back-end relies on many templates and style names.
-Using third-party styles and templates can lead to mismatches.
-Templates derived from built in ODT templates and styles seem to have
-fewer problems.
-
-@node Links in ODT export
-@subsection Links in ODT export
-
-@cindex links, in ODT export
-
-ODT exporter creates native cross-references for internal links.  It
-creates Internet-style links for all other links.
-
-A link with no description and pointing to a regular, un-itemized,
-outline heading is replaced with a cross-reference and section number
-of the heading.
-
-A @samp{\ref@{label@}}-style reference to an image, table etc., is replaced
-with a cross-reference and sequence number of the labeled entity.  See
-@ref{Labels and captions in ODT export}.
-
-@node Tables in ODT export
-@subsection Tables in ODT export
-
-@cindex tables, in ODT export
-
-The ODT export back-end handles native Org mode tables (see @ref{Tables})
-and simple @samp{table.el} tables.  Complex @samp{table.el} tables having 
column
-or row spans are not supported.  Such tables are stripped from the
-exported document.
-
-By default, the ODT export back-end exports a table with top and
-bottom frames and with ruled lines separating row and column groups
-(see @ref{Column Groups}).  All tables are typeset to occupy the same
-width.  The ODT export back-end honors any table alignments and
-relative widths for columns (see @ref{Column Width and Alignment}).
-
-Note that the ODT export back-end interprets column widths as weighted
-ratios, the default weight being 1.
-
-@cindex @samp{ATTR_ODT}, keyword
-Specifying @samp{:rel-width} property on an @samp{ATTR_ODT} line controls the
-width of the table.  For example:
-
-@example
-#+ATTR_ODT: :rel-width 50
-| Area/Month    |   Jan |   Feb |   Mar |   Sum |
-|---------------+-------+-------+-------+-------|
-| /             |     < |       |       |     < |
-| <l13>         |  <r5> |  <r5> |  <r5> |  <r6> |
-| North America |     1 |    21 |   926 |   948 |
-| Middle East   |     6 |    75 |   844 |   925 |
-| Asia Pacific  |     9 |    27 |   790 |   826 |
-|---------------+-------+-------+-------+-------|
-| Sum           |    16 |   123 |  2560 |  2699 |
-@end example
-
-On export, the above table takes 50% of text width area.  The exporter
-sizes the columns in the ratio: 13:5:5:5:6.  The first column is
-left-aligned and rest of the columns, right-aligned.  Vertical rules
-separate the header and the last column.  Horizontal rules separate
-the header and the last row.
-
-For even more customization, create custom table styles and associate
-them with a table using the @samp{ATTR_ODT} keyword.  See @ref{Customizing 
tables in ODT export}.
-
-@node Images in ODT export
-@subsection Images in ODT export
-
-@cindex images, embedding in ODT
-@cindex embedding images in ODT
-
-@anchor{Embedding images}
-@subsubheading Embedding images
-
-The ODT export back-end processes image links in Org files that do not
-have descriptions, such as these links @samp{[[file:img.jpg]]} or 
@samp{[[./img.jpg]]},
-as direct image insertions in the final output.  Either of these
-examples works:
-
-@example
-[[file:img.png]]
-@end example
-
-
-@example
-[[./img.png]]
-@end example
-
-@anchor{Embedding clickable images}
-@subsubheading Embedding clickable images
-
-For clickable images, provide a link whose description is another link
-to an image file.  For example, to embed an image
-@samp{org-mode-unicorn.png} which when clicked jumps to 
@uref{https://orgmode.org}
-website, do the following
-
-@example
-[[https://orgmode.org][./org-mode-unicorn.png]]
-@end example
-
-@anchor{Sizing and scaling of embedded images}
-@subsubheading Sizing and scaling of embedded images
-
-@cindex @samp{ATTR_ODT}, keyword
-
-Control the size and scale of the embedded images with the @samp{ATTR_ODT}
-attribute.
-
-@cindex identify, ImageMagick
-@vindex org-odt-pixels-per-inch
-The ODT export back-end starts with establishing the size of the image
-in the final document.  The dimensions of this size are measured in
-centimeters.  The back-end then queries the image file for its
-dimensions measured in pixels.  For this measurement, the back-end
-relies on ImageMagick's identify program or Emacs @code{create-image} and
-@code{image-size} API@.  ImageMagick is the preferred choice for large file
-sizes or frequent batch operations.  The back-end then converts the
-pixel dimensions using @code{org-odt-pixels-per-inch} into the familiar 72
-dpi or 96 dpi.  The default value for this is in
-@code{display-pixels-per-inch}, which can be tweaked for better results
-based on the capabilities of the output device.  Here are some common
-image scaling operations:
-
-@table @asis
-@item Explicitly size the image
-To embed @samp{img.png} as a 10 cm x 10 cm image, do the following:
-
-@example
-#+ATTR_ODT: :width 10 :height 10
-[[./img.png]]
-@end example
-
-@item Scale the image
-To embed @samp{img.png} at half its size, do the following:
-
-@example
-#+ATTR_ODT: :scale 0.5
-[[./img.png]]
-@end example
-
-@item Scale the image to a specific width
-To embed @samp{img.png} with a width of 10 cm while retaining the
-original height:width ratio, do the following:
-
-@example
-#+ATTR_ODT: :width 10
-[[./img.png]]
-@end example
-
-@item Scale the image to a specific height
-To embed @samp{img.png} with a height of 10 cm while retaining the
-original height:width ratio, do the following:
-
-@example
-#+ATTR_ODT: :height 10
-[[./img.png]]
-@end example
-@end table
-
-@anchor{Anchoring of images}
-@subsubheading Anchoring of images
-
-@cindex @samp{ATTR_ODT}, keyword
-The ODT export back-end can anchor images to @samp{as-char}, @samp{paragraph},
-or @samp{page}.  Set the preferred anchor using the @samp{:anchor} property of
-the @samp{ATTR_ODT} line.
-
-To create an image that is anchored to a page:
-
-@example
-#+ATTR_ODT: :anchor page
-[[./img.png]]
-@end example
-
-@node Math formatting in ODT export
-@subsection Math formatting in ODT export
-
-The ODT exporter has special support for handling math.
-
-@menu
-* @LaTeX{} math snippets::       Embedding in @LaTeX{} format.
-* MathML and OpenDocument formula files:: Embedding in native format.
-@end menu
-
-@node @LaTeX{} math snippets
-@subsubsection @LaTeX{} math snippets
-
-@LaTeX{} math snippets (see @ref{@LaTeX{} fragments}) can be embedded in the 
ODT
-document in one of the following ways:
-
-@table @asis
-@item MathML
-@cindex MathML
-Add this line to the Org file.  This option is activated on
-a per-file basis.
-
-@example
-#+OPTIONS: tex:t
-@end example
-
-
-With this option, @LaTeX{} fragments are first converted into MathML
-fragments using an external @LaTeX{}-to-MathML converter program.  The
-resulting MathML fragments are then embedded as an OpenDocument
-Formula in the exported document.
-
-@vindex org-latex-to-mathml-convert-command
-@vindex org-latex-to-mathml-jar-file
-You can specify the @LaTeX{}-to-MathML converter by customizing the
-variables @code{org-latex-to-mathml-convert-command} and
-@code{org-latex-to-mathml-jar-file}.
-
-If you prefer to use MathToWeb@footnote{See 
@uref{http://www.mathtoweb.com/cgi-bin/mathtoweb_home.pl, MathToWeb}.} as your 
converter, you can
-configure the above variables as shown below.
-
-@lisp
-(setq org-latex-to-mathml-convert-command
-      "java -jar %j -unicode -force -df %o %I"
-      org-latex-to-mathml-jar-file
-      "/path/to/mathtoweb.jar")
-@end lisp
-
-@noindent
-or, to use @LaTeX{}​ML@footnote{See @uref{http://dlmf.nist.gov/LaTeXML/}.} 
instead,
-
-@lisp
-(setq org-latex-to-mathml-convert-command
-      "latexmlmath \"%i\" --presentationmathml=%o")
-@end lisp
-
-To quickly verify the reliability of the @LaTeX{}-to-MathML
-converter, use the following commands:
-
-@table @asis
-@item @kbd{M-x org-export-as-odf}
-Convert a @LaTeX{} math snippet to an OpenDocument formula (@samp{.odf})
-file.
-
-@item @kbd{M-x org-export-as-odf-and-open}
-Convert a @LaTeX{} math snippet to an OpenDocument formula (@samp{.odf})
-file and open the formula file with the system-registered
-application.
-@end table
-
-@item PNG images
-@cindex dvipng
-@cindex dvisvgm
-@cindex ImageMagick
-Add this line to the Org file.  This option is activated on
-a per-file basis.
-
-@example
-#+OPTIONS: tex:dvipng
-@end example
-
-
-@example
-#+OPTIONS: tex:dvisvgm
-@end example
-
-
-@noindent
-or
-
-@example
-#+OPTIONS: tex:imagemagick
-@end example
-
-
-Under this option, @LaTeX{} fragments are processed into PNG or SVG
-images and the resulting images are embedded in the exported
-document.  This method requires dvipng program, dvisvgm or
-ImageMagick programs.
-@end table
-
-@node MathML and OpenDocument formula files
-@subsubsection MathML and OpenDocument formula files
-
-When embedding @LaTeX{} math snippets in ODT documents is not reliable,
-there is one more option to try.  Embed an equation by linking to its
-MathML (@samp{.mml}) source or its OpenDocument formula (@samp{.odf}) file as
-shown below:
-
-@example
-[[./equation.mml]]
-@end example
-
-
-@noindent
-or
-
-@example
-[[./equation.odf]]
-@end example
-
-@node Labels and captions in ODT export
-@subsection Labels and captions in ODT export
-
-ODT format handles labeling and captioning of objects based on their
-types.  Inline images, tables, @LaTeX{} fragments, and Math formulas are
-numbered and captioned separately.  Each object also gets a unique
-sequence number based on its order of first appearance in the Org
-file.  Each category has its own sequence.  A caption is just a label
-applied to these objects.
-
-@example
-#+CAPTION: Bell curve
-#+NAME:   fig:SED-HR4049
-[[./img/a.png]]
-@end example
-
-When rendered, it may show as follows in the exported document:
-
-@example
-Figure 2: Bell curve
-@end example
-
-
-@vindex org-odt-category-map-alist
-To modify the category component of the caption, customize the option
-@code{org-odt-category-map-alist}.  For example, to tag embedded images
-with the string ``Illustration'' instead of the default string ``Figure'',
-use the following setting:
-
-@lisp
-(setq org-odt-category-map-alist
-      '(("__Figure__" "Illustration" "value" "Figure" 
org-odt--enumerable-image-p)))
-@end lisp
-
-With the above modification, the previous example changes to:
-
-@example
-Illustration 2: Bell curve
-@end example
-
-@node Literal examples in ODT export
-@subsection Literal examples in ODT export
-
-The ODT export back-end supports literal examples (see @ref{Literal Examples}) 
with full fontification.  Internally, the ODT export
-back-end relies on @samp{htmlfontify.el} to generate the style definitions
-needed for fancy listings.  The auto-generated styles get @samp{OrgSrc}
-prefix and inherit colors from the faces used by Emacs Font Lock
-library for that source language.
-
-@vindex org-odt-fontify-srcblocks
-For custom fontification styles, customize the
-@code{org-odt-create-custom-styles-for-srcblocks} option.
-
-@vindex org-odt-create-custom-styles-for-srcblocks
-To turn off fontification of literal examples, customize the
-@code{org-odt-fontify-srcblocks} option.
-
-@node Advanced topics in ODT export
-@subsection Advanced topics in ODT export
-
-The ODT export back-end has extensive features useful for power users
-and frequent uses of ODT formats.
-
-@anchor{Configuring a document converter}
-@subsubheading Configuring a document converter
-
-@cindex convert
-@cindex doc, docx, rtf
-@cindex converter
-
-The ODT export back-end works with popular converters with little or
-no extra configuration.  See @ref{Extending ODT export}.  The following is
-for unsupported converters or tweaking existing defaults.
-
-@table @asis
-@item Register the converter
-@vindex org-export-odt-convert-processes
-Add the name of the converter to the @code{org-odt-convert-processes}
-variable.  Note that it also requires how the converter is invoked
-on the command line.  See the variable's docstring for details.
-
-@item Configure its capabilities
-@vindex org-export-odt-convert-capabilities
-Specify which formats the converter can handle by customizing the
-variable @code{org-odt-convert-capabilities}.  Use the entry for the
-default values in this variable for configuring the new converter.
-Also see its docstring for details.
-
-@item Choose the converter
-@vindex org-export-odt-convert-process
-Select the newly added converter as the preferred one by customizing
-the option @code{org-odt-convert-process}.
-@end table
-
-@anchor{Working with OpenDocument style files}
-@subsubheading Working with OpenDocument style files
-
-@cindex styles, custom
-@cindex template, custom
-
-This section explores the internals of the ODT exporter; the means by which
-it produces styled documents; the use of automatic and custom OpenDocument
-styles.
-
-The ODT exporter relies on two files for generating its output.  These
-files are bundled with the distribution under the directory pointed to
-by the variable @code{org-odt-styles-dir}.  The two files are:
-
-@table @asis
-@item @samp{OrgOdtStyles.xml} @anchor{x-orgodtstyles-xml}
-This file contributes to the @samp{styles.xml} file of the final ODT
-document.  This file gets modified for the following purposes:
-
-@enumerate
-@item
-To control outline numbering based on user settings;
-
-@item
-To add styles generated by @samp{htmlfontify.el} for fontification of
-code blocks.
-@end enumerate
-
-@item @samp{OrgOdtContentTemplate.xml} @anchor{x-orgodtcontenttemplate-xml}
-This file contributes to the @samp{content.xml} file of the final ODT
-document.  The contents of the Org outline are inserted between the
-@samp{<office:text>} @dots{} @samp{</office:text>} elements of this file.
-
-Apart from serving as a template file for the final @samp{content.xml},
-the file serves the following purposes:
-
-@enumerate
-@item
-It contains automatic styles for formatting of tables which are
-referenced by the exporter;
-
-@item
-It contains @samp{<text:sequence-decl>} @dots{} @samp{</text:sequence-decl>}
-elements that control numbering of tables, images, equations, and
-similar entities.
-@end enumerate
-@end table
-
-@anchor{x-overriding-factory-styles} The following two variables control
-the location from where the ODT exporter picks up the custom styles
-and content template files.  Customize these variables to override the
-factory styles used by the exporter.
-
-@table @asis
-@item @code{org-odt-styles-file}
-The ODT export back-end uses the file pointed to by this variable,
-such as @samp{styles.xml}, for the final output.  It can take one of the
-following values:
-
-@table @asis
-@item @samp{FILE.xml}
-Use this file instead of the default @samp{styles.xml}
-
-@item @samp{FILE.odt} or @samp{FILE.ott}
-Use the @samp{styles.xml} contained in the specified OpenDocument
-Text or Template file
-
-@item @samp{FILE.odt} or @samp{FILE.ott} and a subset of included files
-Use the @samp{styles.xml} contained in the specified OpenDocument Text
-or Template file.  Additionally extract the specified member files
-and embed those within the final ODT document.
-
-Use this option if the @samp{styles.xml} file references additional
-files like header and footer images.
-
-@item @code{nil}
-Use the default @samp{styles.xml}.
-@end table
-
-@item @code{org-odt-content-template-file}
-Use this variable to specify the blank @samp{content.xml} used in the
-final output.
-@end table
-
-@anchor{Creating one-off styles}
-@subsubheading Creating one-off styles
-
-The ODT export back-end can read embedded raw OpenDocument XML from
-the Org file.  Such direct formatting is useful for one-off instances.
-
-@table @asis
-@item Embedding ODT tags as part of regular text
-Enclose OpenDocument syntax in @samp{@@@@odt:...@@@@} for inline markup.  For
-example, to highlight a region of text do the following:
-
-@example
-@@@@odt:<text:span text:style-name="Highlight">This is highlighted
-text</text:span>@@@@.  But this is regular text.
-@end example
-
-@strong{Hint:} To see the above example in action, edit the @samp{styles.xml}
-(see @ref{x-orgodtstyles-xml, , Factory styles}) and add a custom 
@emph{Highlight} style as shown
-below:
-
-@example
-<style:style style:name="Highlight" style:family="text">
-  <style:text-properties fo:background-color="#ff0000"/>
-</style:style>
-@end example
-
-@item Embedding a one-line OpenDocument XML
-@cindex @samp{ODT}, keyword
-The ODT export back-end can read one-liner options with @samp{#+ODT:} in
-the Org file.  For example, to force a page break:
-
-@example
-#+ODT: <text:p text:style-name="PageBreak"/>
-@end example
-
-@strong{Hint:} To see the above example in action, edit your
-@samp{styles.xml} (see @ref{x-orgodtstyles-xml, , Factory styles}) and add a 
custom @samp{PageBreak}
-style as shown below.
-
-@example
-<style:style style:name="PageBreak" style:family="paragraph"
-             style:parent-style-name="Text_20_body">
-  <style:paragraph-properties fo:break-before="page"/>
-</style:style>
-@end example
-
-@item Embedding a block of OpenDocument XML
-The ODT export back-end can also read ODT export blocks for
-OpenDocument XML@.  Such blocks use the @samp{#+BEGIN_EXPORT odt}
-@dots{} @samp{#+END_EXPORT} constructs.
-
-For example, to create a one-off paragraph that uses bold text, do
-the following:
-
-@example
-#+BEGIN_EXPORT odt
-  <text:p text:style-name="Text_20_body_20_bold">
-  This paragraph is specially formatted and uses bold text.
-  </text:p>
-#+END_EXPORT
-@end example
-@end table
-
-@anchor{Customizing tables in ODT export}
-@subsubheading Customizing tables in ODT export
-
-@cindex tables, in ODT export
-@cindex @samp{ATTR_ODT}, keyword
-
-Override the default table format by specifying a custom table style
-with the @samp{#+ATTR_ODT} line.  For a discussion on default formatting of
-tables, see @ref{Tables in ODT export}.
-
-This feature closely mimics the way table templates are defined in the
-OpenDocument-v1.2 
specification@footnote{@uref{http://docs.oasis-open.org/office/v1.2/OpenDocument-v1.2.html,
 OpenDocument-v1.2 Specification}}.
-
-@vindex org-odt-table-styles
-For quick preview of this feature, install the settings below and export the
-table that follows:
-
-@lisp
-(setq org-export-odt-table-styles
-      (append org-export-odt-table-styles
-              '(("TableWithHeaderRowAndColumn" "Custom"
-                 ((use-first-row-styles . t)
-                  (use-first-column-styles . t)))
-                ("TableWithFirstRowandLastRow" "Custom"
-                 ((use-first-row-styles . t)
-                  (use-last-row-styles . t))))))
-@end lisp
-
-@example
-#+ATTR_ODT: :style TableWithHeaderRowAndColumn
-| Name  | Phone | Age |
-| Peter |  1234 |  17 |
-| Anna  |  4321 |  25 |
-@end example
-
-The example above used @samp{Custom} template and installed two table
-styles @samp{TableWithHeaderRowAndColumn} and
-@samp{TableWithFirstRowandLastRow}.  @strong{Important:} The OpenDocument 
styles
-needed for producing the above template were pre-defined.  They are
-available in the section marked @samp{Custom Table Template} in
-@samp{OrgOdtContentTemplate.xml} (see @ref{x-orgodtcontenttemplate-xml, , 
Factory styles}).  For adding new
-templates, define new styles there.
-
-To use this feature proceed as follows:
-
-@enumerate
-@item
-Create a table template@footnote{See the @samp{<table:table-template>} element 
of the
-OpenDocument-v1.2 specification.}.
-
-A table template is set of @samp{table-cell} and @samp{paragraph} styles for
-each of the following table cell categories:
-
-@itemize
-@item
-Body
-@item
-First column
-@item
-Last column
-@item
-First row
-@item
-Last row
-@item
-Even row
-@item
-Odd row
-@item
-Even column
-@item
-Odd Column
-@end itemize
-
-The names for the above styles must be chosen based on the name of
-the table template using a well-defined convention.
-
-The naming convention is better illustrated with an example.  For
-a table template with the name @samp{Custom}, the needed style names are
-listed in the following table.
-
-@multitable {aaaaaaaaaaaa} {aaaaaaaaaaaaaaaaaaaaaaaaaaaa} 
{aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa}
-@headitem Cell type
-@tab Cell style
-@tab Paragraph style
-@item Body
-@tab @samp{CustomTableCell}
-@tab @samp{CustomTableParagraph}
-@item First column
-@tab @samp{CustomFirstColumnTableCell}
-@tab @samp{CustomFirstColumnTableParagraph}
-@item Last column
-@tab @samp{CustomLastColumnTableCell}
-@tab @samp{CustomLastColumnTableParagraph}
-@item First row
-@tab @samp{CustomFirstRowTableCell}
-@tab @samp{CustomFirstRowTableParagraph}
-@item Last row
-@tab @samp{CustomLastRowTableCell}
-@tab @samp{CustomLastRowTableParagraph}
-@item Even row
-@tab @samp{CustomEvenRowTableCell}
-@tab @samp{CustomEvenRowTableParagraph}
-@item Odd row
-@tab @samp{CustomOddRowTableCell}
-@tab @samp{CustomOddRowTableParagraph}
-@item Even column
-@tab @samp{CustomEvenColumnTableCell}
-@tab @samp{CustomEvenColumnTableParagraph}
-@item Odd column
-@tab @samp{CustomOddColumnTableCell}
-@tab @samp{CustomOddColumnTableParagraph}
-@end multitable
-
-To create a table template with the name @samp{Custom}, define the above
-styles in the @samp{<office:automatic-styles>} @dots{}
-@samp{</office:automatic-styles>} element of the content template file
-(see @ref{x-orgodtcontenttemplate-xml, , Factory styles}).
-
-@item
-Define a table style@footnote{See the attributes @samp{table:template-name},
-@samp{table:use-first-row-styles}, @samp{table:use-last-row-styles},
-@samp{table:use-first-column-styles}, @samp{table:use-last-column-styles},
-@samp{table:use-banding-rows-styles}, and 
@samp{table:use-banding-column-styles}
-of the @samp{<table:table>} element in the OpenDocument-v1.2 specification.}.
-
-@vindex org-odt-table-styles
-To define a table style, create an entry for the style in the
-variable @code{org-odt-table-styles} and specify the following:
-
-@itemize
-@item
-the name of the table template created in step (1),
-@item
-the set of cell styles in that template that are to be activated.
-@end itemize
-
-For example, the entry below defines two different table styles
-@samp{TableWithHeaderRowAndColumn} and @samp{TableWithFirstRowandLastRow}
-based on the same template @samp{Custom}.  The styles achieve their
-intended effect by selectively activating the individual cell
-styles in that template.
-
-@lisp
-(setq org-export-odt-table-styles
-      (append org-export-odt-table-styles
-              '(("TableWithHeaderRowAndColumn" "Custom"
-                 ((use-first-row-styles . t)
-                  (use-first-column-styles . t)))
-                ("TableWithFirstRowandLastRow" "Custom"
-                 ((use-first-row-styles . t)
-                  (use-last-row-styles . t))))))
-@end lisp
-
-@item
-Associate a table with the table style.
-
-To do this, specify the table style created in step (2) as part of
-the @samp{ATTR_ODT} line as shown below.
-
-@example
-#+ATTR_ODT: :style TableWithHeaderRowAndColumn
-| Name  | Phone | Age |
-| Peter |  1234 |  17 |
-| Anna  |  4321 |  25 |
-@end example
-@end enumerate
-
-@anchor{Validating OpenDocument XML}
-@subsubheading Validating OpenDocument XML
-
-Sometimes ODT format files may not open due to @samp{.odt} file corruption.
-To verify if such a file is corrupt, validate it against the
-OpenDocument Relax NG Compact (RNC) syntax schema.  But first the
-@samp{.odt} files have to be decompressed using @samp{zip}.  Note that 
@samp{.odt}
-files are ZIP archives: @ref{File Archives,,,emacs,}.  The contents of
-ODT files are in XML@.  For general help with validation---and
-schema-sensitive editing---of XML files: @ref{Introduction,,,nxml-mode,}.
-
-@vindex org-export-odt-schema-dir
-Customize @code{org-odt-schema-dir} to point to a directory with
-OpenDocument RNC files and the needed schema-locating rules.  The ODT
-export back-end takes care of updating the
-@code{rng-schema-locating-files}.
-
-@node Org Export
-@section Org Export
-
-@cindex Org export
-@emph{org} export back-end creates a normalized version of the Org document
-in current buffer.  The exporter evaluates Babel code (see @ref{Evaluating 
Code Blocks}) and removes content specific to other back-ends.
-
-@anchor{Org export commands}
-@subheading Org export commands
-
-@table @asis
-@item @kbd{C-c C-e O o} (@code{org-org-export-to-org})
-@kindex C-c C-e O o
-@findex org-org-export-to-org
-Export as an Org file with a @samp{.org} extension.  For @samp{myfile.org},
-Org exports to @samp{myfile.org.org}, overwriting without warning.
-
-@item @kbd{C-c C-e O v} (~~)
-@kindex C-c C-e O v
-Export to an Org file, then open it.
-@end table
-
-@node Texinfo Export
-@section Texinfo Export
-
-@menu
-* Texinfo export commands::      Invoking commands.
-* Texinfo specific export settings:: Setting the environment.
-* Texinfo file header::          Generating the header.
-* Texinfo title and copyright page:: Creating preamble pages.
-* Info directory file::          Installing a manual in Info file hierarchy.
-* Headings and sectioning structure:: Building document structure.
-* Indices::                      Creating indices.
-* Quoting Texinfo code::         Incorporating literal Texinfo code.
-* Plain lists in Texinfo export:: List attributes.
-* Tables in Texinfo export::     Table attributes.
-* Images in Texinfo export::     Image attributes.
-* Quotations in Texinfo export:: Quote block attributes.
-* Special blocks in Texinfo export:: Special block attributes.
-* A Texinfo example::            Processing Org to Texinfo.
-@end menu
-
-@node Texinfo export commands
-@subsection Texinfo export commands
-
-@table @asis
-@item @kbd{C-c C-e i t} (@code{org-texinfo-export-to-texinfo})
-@kindex C-c C-e i t
-@findex org-texinfo-export-to-texinfo
-Export as a Texinfo file with @samp{.texi} extension.  For @samp{myfile.org},
-Org exports to @samp{myfile.texi}, overwriting without warning.
-
-@item @kbd{C-c C-e i i} (@code{org-texinfo-export-to-info})
-@kindex C-c C-e i i
-@findex org-texinfo-export-to-info
-@vindex org-texinfo-info-process
-Export to Texinfo format first and then process it to make an Info
-file.  To generate other formats, such as DocBook, customize the
-@code{org-texinfo-info-process} variable.
-@end table
-
-@node Texinfo specific export settings
-@subsection Texinfo specific export settings
-
-The Texinfo export back-end has several additional keywords for
-customizing Texinfo output.  Setting these keywords works similar to
-the general options (see @ref{Export Settings}).
-
-@table @asis
-@item @samp{SUBTITLE}
-@cindex @samp{SUBTITLE}, keyword
-The document subtitle.
-
-@item @samp{SUBAUTHOR}
-@cindex @samp{SUBAUTHOR}, keyword
-Additional authors for the document.
-
-@item @samp{TEXINFO_FILENAME}
-@cindex @samp{TEXINFO_FILENAME}, keyword
-The Texinfo filename.
-
-@item @samp{TEXINFO_CLASS}
-@cindex @samp{TEXINFO_CLASS}, keyword
-@vindex org-texinfo-default-class
-The default document class (@code{org-texinfo-default-class}), which must
-be a member of @code{org-texinfo-classes}.
-
-@item @samp{TEXINFO_HEADER}
-@cindex @samp{TEXINFO_HEADER}, keyword
-Arbitrary lines inserted at the end of the header.
-
-@item @samp{TEXINFO_POST_HEADER}
-@cindex @samp{TEXINFO_POST_HEADER}, keyword
-Arbitrary lines inserted after the end of the header.
-
-@item @samp{TEXINFO_DIR_CATEGORY}
-@cindex @samp{TEXINFO_DIR_CATEGORY}, keyword
-The directory category of the document.
-
-@item @samp{TEXINFO_DIR_TITLE}
-@cindex @samp{TEXINFO_DIR_TITLE}, keyword
-The directory title of the document.
-
-@item @samp{TEXINFO_DIR_DESC}
-@cindex @samp{TEXINFO_DIR_DESC}, keyword
-The directory description of the document.
-
-@item @samp{TEXINFO_PRINTED_TITLE}
-@cindex @samp{TEXINFO_PRINTED_TITLE}, keyword
-The printed title of the document.
-@end table
-
-@node Texinfo file header
-@subsection Texinfo file header
-
-@cindex @samp{TEXINFO_FILENAME}, keyword
-After creating the header for a Texinfo file, the Texinfo back-end
-automatically generates a name and destination path for the Info file.
-To override this default with a more sensible path and name, specify
-the @samp{TEXINFO_FILENAME} keyword.
-
-@vindex org-texinfo-coding-system
-@cindex @samp{TEXINFO_HEADER}, keyword
-Along with the output's file name, the Texinfo header also contains
-language details (see @ref{Export Settings}) and encoding system as set in
-the @code{org-texinfo-coding-system} variable.  Insert @samp{TEXINFO_HEADER}
-keywords for each additional command in the header, for example:
-
-@example
-#+TEXINFO_HEADER: @@synindex
-@end example
-
-
-@cindex @samp{TEXINFO_CLASS}, keyword
-@vindex org-texinfo-classes
-Instead of repeatedly installing the same set of commands, define
-a class in @code{org-texinfo-classes} once, and then activate it in the
-document by setting the @samp{TEXINFO_CLASS} keyword to that class.
-
-@node Texinfo title and copyright page
-@subsection Texinfo title and copyright page
-
-@cindex @samp{TEXINFO_PRINTED_TITLE}, keyword
-The default template for hard copy output has a title page with
-@samp{TITLE} and @samp{AUTHOR} keywords (see @ref{Export Settings}).  To 
replace the
-regular title with something different for the printed version, use
-the @samp{TEXINFO_PRINTED_TITLE} and @samp{SUBTITLE} keywords.  Both expect raw
-Texinfo code for setting their values.
-
-@cindex @samp{SUBAUTHOR}, keyword
-If one @samp{AUTHOR} line is not sufficient, add multiple @samp{SUBAUTHOR}
-keywords.  They have to be set in raw Texinfo code.
-
-@example
-#+AUTHOR: Jane Smith
-#+SUBAUTHOR: John Doe
-#+TEXINFO_PRINTED_TITLE: This Long Title@@@@inlinefmt@{tex,@@*@} Is Broken in 
@@TeX@{@}
-@end example
-
-@cindex @samp{COPYING}, property
-Copying material is defined in a dedicated headline with a non-@code{nil}
-@samp{COPYING} property.  The back-end inserts the contents within
-a @samp{@@copying} command at the beginning of the document.  The heading
-itself does not appear in the structure of the document.
-
-Copyright information is printed on the back of the title page.
-
-@example
-* Legalese
-  :PROPERTIES:
-  :COPYING: t
-  :END:
-
-  This is a short example of a complete Texinfo file, version 1.0.
-
-  Copyright \copy 2016 Free Software Foundation, Inc.
-@end example
-
-@node Info directory file
-@subsection Info directory file
-
-@cindex @samp{dir} file, in Texinfo export
-@cindex Info directory file, in Texinfo export
-@cindex @code{install-info}, in Texinfo export
-
-@cindex @samp{TEXINFO_DIR_CATEGORY}, keyword
-@cindex @samp{TEXINFO_DIR_TITLE}, keyword
-@cindex @samp{TEXINFO_DIR_DESC}, keyword
-The end result of the Texinfo export process is the creation of an
-Info file.  This Info file's metadata has variables for category,
-title, and description: @samp{TEXINFO_DIR_CATEGORY}, @samp{TEXINFO_DIR_TITLE},
-and @samp{TEXINFO_DIR_DESC} keywords that establish where in the Info
-hierarchy the file fits.
-
-Here is an example that writes to the Info directory file:
-
-@example
-#+TEXINFO_DIR_CATEGORY: Emacs
-#+TEXINFO_DIR_TITLE: Org Mode: (org)
-#+TEXINFO_DIR_DESC: Outline-based notes management and organizer
-@end example
-
-@node Headings and sectioning structure
-@subsection Headings and sectioning structure
-
-@vindex org-texinfo-classes
-@vindex org-texinfo-default-class
-@cindex @samp{TEXINFO_CLASS}, keyword
-The Texinfo export back-end uses a pre-defined scheme to convert Org
-headlines to equivalent Texinfo structuring commands.  A scheme like
-this maps top-level headlines to numbered chapters tagged as
-@code{@@chapter} and lower-level headlines to unnumbered chapters tagged as
-@code{@@unnumbered}.  To override such mappings to introduce @code{@@part} or
-other Texinfo structuring commands, define a new class in
-@code{org-texinfo-classes}.  Activate the new class with the
-@samp{TEXINFO_CLASS} keyword.  When no new class is defined and activated,
-the Texinfo export back-end defaults to the
-@code{org-texinfo-default-class}.
-
-If an Org headline's level has no associated Texinfo structuring
-command, or is below a certain threshold (see @ref{Export Settings}), then
-the Texinfo export back-end makes it into a list item.
-
-@cindex @samp{APPENDIX}, property
-The Texinfo export back-end makes any headline with a non-@code{nil}
-@samp{APPENDIX} property into an appendix.  This happens independent of the
-Org headline level or the @samp{TEXINFO_CLASS} keyword.
-
-@cindex @samp{ALT_TITLE}, property
-@cindex @samp{DESCRIPTION}, property
-The Texinfo export back-end creates a menu entry after the Org
-headline for each regular sectioning structure.  To override this with
-a shorter menu entry, use the @samp{ALT_TITLE} property (see @ref{Table of 
Contents}).  Texinfo menu entries also have an option for a longer
-@samp{DESCRIPTION} property.  Here's an example that uses both to override
-the default menu entry:
-
-@example
-* Controlling Screen Display
-  :PROPERTIES:
-  :ALT_TITLE: Display
-  :DESCRIPTION: Controlling Screen Display
-  :END:
-@end example
-
-@cindex Top node, in Texinfo export
-The text before the first headline belongs to the @emph{Top} node, i.e.,
-the node in which a reader enters an Info manual.  As such, it is
-expected not to appear in printed output generated from the @samp{.texi}
-file.  See @ref{The Top Node,,,texinfo,}, for more information.
-
-@node Indices
-@subsection Indices
-
-@cindex @samp{CINDEX}, keyword
-@cindex concept index, in Texinfo export
-@cindex @samp{FINDEX}, keyword
-@cindex function index, in Texinfo export
-@cindex @samp{KINDEX}, keyword
-@cindex keystroke index, in Texinfo export
-@cindex @samp{PINDEX}, keyword
-@cindex program index, in Texinfo export
-@cindex @samp{TINDEX}, keyword
-@cindex data type index, in Texinfo export
-@cindex @samp{VINDEX}, keyword
-@cindex variable index, in Texinfo export
-The Texinfo export back-end recognizes these indexing keywords if used
-in the Org file: @samp{CINDEX}, @samp{FINDEX}, @samp{KINDEX}, @samp{PINDEX}, 
@samp{TINDEX} and
-@samp{VINDEX}.  Write their value as verbatim Texinfo code; in particular,
-@samp{@{}, @samp{@}} and @samp{@@} characters need to be escaped with 
@samp{@@} if they do not
-belong to a Texinfo command.
-
-@example
-#+CINDEX: Defining indexing entries
-@end example
-
-
-@cindex @samp{INDEX}, property
-For the back-end to generate an index entry for a headline, set the
-@samp{INDEX} property to @samp{cp} or @samp{vr}.  These abbreviations come from
-Texinfo that stand for concept index and variable index.  The Texinfo
-manual has abbreviations for all other kinds of indexes.  The back-end
-exports the headline as an unnumbered chapter or section command, and
-then inserts the index after its contents.
-
-@example
-* Concept Index
-  :PROPERTIES:
-  :INDEX: cp
-  :END:
-@end example
-
-@node Quoting Texinfo code
-@subsection Quoting Texinfo code
-
-Use any of the following three methods to insert or escape raw Texinfo
-code:
-
-@cindex @samp{TEXINFO}, keyword
-@cindex @samp{BEGIN_EXPORT texinfo}
-@example
-Richard @@@@texinfo:@@sc@{@@@@Stallman@@@@texinfo:@}@@@@ commence' GNU.
-
-#+TEXINFO: @@need800
-This paragraph is preceded by...
-
-#+BEGIN_EXPORT texinfo
-  @@auindex Johnson, Mark
-  @@auindex Lakoff, George
-#+END_EXPORT
-@end example
-
-@node Plain lists in Texinfo export
-@subsection Plain lists in Texinfo export
-
-@cindex @samp{ATTR_TEXINFO}, keyword
-@cindex two-column tables, in Texinfo export
-@cindex table-type, Texinfo attribute
-The Texinfo export back-end by default converts description lists in
-the Org file using the default command @samp{@@table}, which results in
-a table with two columns.  To change this behavior, set @samp{:table-type}
-attribute to either @samp{ftable} or @samp{vtable} value.  For more 
information,
-see @ref{Two-column Tables,,,texinfo,}.
-
-@vindex org-texinfo-table-default-markup
-@cindex indic, Texinfo attribute
-The Texinfo export back-end by default also applies a text highlight
-based on the defaults stored in @code{org-texinfo-table-default-markup}.
-To override the default highlight command, specify another one with
-the @samp{:indic} attribute.
-
-@cindex multiple items in Texinfo lists
-@cindex sep, Texinfo attribute
-Org syntax is limited to one entry per list item.  Nevertheless, the
-Texinfo export back-end can split that entry according to any text
-provided through the @samp{:sep} attribute.  Each part then becomes a new
-entry in the first column of the table.
-
-The following example illustrates all the attributes above:
-
-@example
-#+ATTR_TEXINFO: :table-type vtable :sep , :indic asis
-- foo, bar :: This is the common text for variables foo and bar.
-@end example
-
-@noindent
-becomes
-
-@example
-@@vtable @@asis
-@@item foo
-@@itemx bar
-This is the common text for variables foo and bar.
-@@end table
-@end example
-
-@cindex lettered lists, in Texinfo export
-@cindex enum, Texinfo attribute
-Ordered lists are numbered when exported to Texinfo format.  Such
-numbering obeys any counter (see @ref{Plain Lists}) in the first item of
-the list.  The @samp{:enum} attribute also let you start the list at
-a specific number, or switch to a lettered list, as illustrated here
-
-@example
-#+ATTR_TEXINFO: :enum A
-1. Alpha
-2. Bravo
-3. Charlie
-@end example
-
-@node Tables in Texinfo export
-@subsection Tables in Texinfo export
-
-@cindex @samp{ATTR_TEXINFO}, keyword
-When exporting tables, the Texinfo export back-end uses the widest
-cell width in each column.  To override this and instead specify as
-fractions of line length, use the @samp{:columns} attribute.  See example
-below.
-
-@example
-#+ATTR_TEXINFO: :columns .5 .5
-| a cell | another cell |
-@end example
-
-@node Images in Texinfo export
-@subsection Images in Texinfo export
-
-@cindex @samp{ATTR_TEXINFO}, keyword
-Insert a file link to the image in the Org file, and the Texinfo
-export back-end inserts the image.  These links must have the usual
-supported image extensions and no descriptions.  To scale the image,
-use @samp{:width} and @samp{:height} attributes.  For alternate text, use 
@samp{:alt}
-and specify the text using Texinfo code, as shown in the example:
-
-@example
-#+ATTR_TEXINFO: :width 1in :alt Alternate @@i@{text@}
-[[ridt.pdf]]
-@end example
-
-@node Quotations in Texinfo export
-@subsection Quotations in Texinfo export
-
-@cindex @samp{ATTR_TEXINFO}, keyword
-You can write the text of a quotation within a quote block (see
-@ref{Paragraphs}).  You may also emphasize some text at the beginning of
-the quotation with the @samp{:tag} attribute.
-
-@example
-#+ATTR_TEXINFO: :tag Warning
-#+BEGIN_QUOTE
-Striking your thumb with a hammer may cause severe pain and discomfort.
-#+END_QUOTE
-@end example
-
-To specify the author of the quotation, use the @samp{:author} attribute.
-
-@example
-#+ATTR_TEXINFO: :author King Arthur
-#+BEGIN_QUOTE
-The Lady of the Lake, her arm clad in the purest shimmering samite,
-held aloft Excalibur from the bosom of the water, signifying by divine
-providence that I, Arthur, was to carry Excalibur. That is why I am
-your king.
-#+END_QUOTE
-@end example
-
-@node Special blocks in Texinfo export
-@subsection Special blocks in Texinfo export
-
-@cindex @samp{ATTR_TEXINFO}, keyword
-
-The Texinfo export back-end converts special blocks to commands with
-the same name.  It also adds any @samp{:options} attributes to the end of
-the command, as shown in this example:
-
-@example
-#+ATTR_TEXINFO: :options org-org-export-to-org ...
-#+BEGIN_defun
-  A somewhat obsessive function name.
-#+END_defun
-@end example
-
-@noindent
-becomes
-
-@example
-@@defun org-org-export-to-org ...
-  A somewhat obsessive function name.
-@@end defun
-@end example
-
-@node A Texinfo example
-@subsection A Texinfo example
-
-Here is a more detailed example Org file.  See
-@ref{GNU Sample Texts,,,texinfo,} for an equivalent example using
-Texinfo code.
-
-@example
-#+TITLE: GNU Sample @{@{@{version@}@}@}
-#+SUBTITLE: for version @{@{@{version@}@}@}, @{@{@{updated@}@}@}
-#+AUTHOR: A.U. Thor
-#+EMAIL: bug-sample@@gnu.org
-
-#+OPTIONS: ':t toc:t author:t email:t
-#+LANGUAGE: en
-
-#+MACRO: version 2.0
-#+MACRO: updated last updated 4 March 2014
-
-#+TEXINFO_FILENAME: sample.info
-#+TEXINFO_HEADER: @@syncodeindex pg cp
-
-#+TEXINFO_DIR_CATEGORY: Texinfo documentation system
-#+TEXINFO_DIR_TITLE: sample: (sample)
-#+TEXINFO_DIR_DESC: Invoking sample
-
-#+TEXINFO_PRINTED_TITLE: GNU Sample
-
-This manual is for GNU Sample (version @{@{@{version@}@}@},
-@{@{@{updated@}@}@}).
-
-* Copying
-  :PROPERTIES:
-  :COPYING:  t
-  :END:
-
-  This manual is for GNU Sample (version @{@{@{version@}@}@},
-  @{@{@{updated@}@}@}), which is an example in the Texinfo documentation.
-
-  Copyright \copy 2016 Free Software Foundation, Inc.
-
-  #+BEGIN_QUOTE
-  Permission is granted to copy, distribute and/or modify this
-  document under the terms of the GNU Free Documentation License,
-  Version 1.3 or any later version published by the Free Software
-  Foundation; with no Invariant Sections, with no Front-Cover Texts,
-  and with no Back-Cover Texts.  A copy of the license is included in
-  the section entitled "GNU Free Documentation License".
-  #+END_QUOTE
-
-* Invoking sample
-
-  #+PINDEX: sample
-  #+CINDEX: invoking @@command@{sample@}
-
-  This is a sample manual.  There is no sample program to invoke, but
-  if there were, you could see its basic usage and command line
-  options here.
-
-* GNU Free Documentation License
-  :PROPERTIES:
-  :APPENDIX: t
-  :END:
-
-  #+INCLUDE: fdl.org
-
-* Index
-  :PROPERTIES:
-  :INDEX:    cp
-  :END:
-@end example
-
-@node iCalendar Export
-@section iCalendar Export
-
-@cindex iCalendar export
-
-A large part of Org mode's interoperability success is its ability to
-easily export to or import from external applications.  The iCalendar
-export back-end takes calendar data from Org files and exports to the
-standard iCalendar format.
-
-@vindex org-icalendar-include-todo
-@vindex org-icalendar-use-deadline
-@vindex org-icalendar-use-scheduled
-The iCalendar export back-end can also incorporate TODO entries based
-on the configuration of the @code{org-icalendar-include-todo} variable.
-The back-end exports plain timestamps as @samp{VEVENT}, TODO items as
-@samp{VTODO}, and also create events from deadlines that are in non-TODO
-items.  The back-end uses the deadlines and scheduling dates in Org
-TODO items for setting the start and due dates for the iCalendar TODO
-entry.  Consult the @code{org-icalendar-use-deadline} and
-@code{org-icalendar-use-scheduled} variables for more details.
-
-@vindex org-icalendar-categories
-@vindex org-icalendar-alarm-time
-For tags on the headline, the iCalendar export back-end makes them
-into iCalendar categories.  To tweak the inheritance of tags and TODO
-states, configure the variable @code{org-icalendar-categories}.  To assign
-clock alarms based on time, configure the @code{org-icalendar-alarm-time}
-variable.
-
-@vindex org-icalendar-store-UID
-@cindex @samp{ID}, property
-The iCalendar format standard requires globally unique identifier---or
-UID---for each entry.  The iCalendar export back-end creates UIDs
-during export.  To save a copy of the UID in the Org file set the
-variable @code{org-icalendar-store-UID}.  The back-end looks for the @samp{ID}
-property of the entry for re-using the same UID for subsequent
-exports.
-
-Since a single Org entry can result in multiple iCalendar
-entries---timestamp, deadline, scheduled item, or TODO item---Org adds
-prefixes to the UID, depending on which part of the Org entry
-triggered the creation of the iCalendar entry.  Prefixing ensures UIDs
-remains unique, yet enable synchronization programs trace the
-connections.
-
-@table @asis
-@item @kbd{C-c C-e c f} (@code{org-icalendar-export-to-ics})
-@kindex C-c C-e c f
-@findex org-icalendar-export-to-ics
-Create iCalendar entries from the current Org buffer and store them
-in the same directory, using a file extension @samp{.ics}.
-
-@item @kbd{C-c C-e c a} (@code{org-icalendar-export-agenda-files})
-@kindex C-c C-e c a
-@findex org-icalendar-export-agenda-files
-Create iCalendar entries from Org files in @code{org-agenda-files} and
-store in a separate iCalendar file for each Org file.
-
-@item @kbd{C-c C-e c c} (@code{org-icalendar-combine-agenda-files})
-@kindex C-c C-e c c
-@findex org-icalendar-combine-agenda-files
-@vindex org-icalendar-combined-agenda-file
-Create a combined iCalendar file from Org files in
-@code{org-agenda-files} and write it to
-@code{org-icalendar-combined-agenda-file} file name.
-@end table
-
-@cindex @samp{SUMMARY}, property
-@cindex @samp{DESCRIPTION}, property
-@cindex @samp{LOCATION}, property
-@cindex @samp{TIMEZONE}, property
-@cindex @samp{CLASS}, property
-The iCalendar export back-end includes @samp{SUMMARY}, @samp{DESCRIPTION},
-@samp{LOCATION}, @samp{TIMEZONE} and @samp{CLASS} properties from the Org 
entries
-when exporting.  To force the back-end to inherit the @samp{LOCATION},
-@samp{TIMEZONE} and @samp{CLASS} properties, configure the
-@code{org-use-property-inheritance} variable.
-
-@vindex org-icalendar-include-body
-When Org entries do not have @samp{SUMMARY}, @samp{DESCRIPTION}, 
@samp{LOCATION} and
-@samp{CLASS} properties, the iCalendar export back-end derives the summary
-from the headline, and derives the description from the body of the
-Org item.  The @code{org-icalendar-include-body} variable limits the
-maximum number of characters of the content are turned into its
-description.
-
-The @samp{TIMEZONE} property can be used to specify a per-entry time zone,
-and is applied to any entry with timestamp information.  Time zones
-should be specified as per the IANA time zone database format, e.g.,
-@samp{Asia/Almaty}.  Alternately, the property value can be @samp{UTC}, to 
force
-UTC time for this entry only.
-
-The @samp{CLASS} property can be used to specify a per-entry visibility
-class or access restrictions, and is applied to any entry with class
-information.  The iCalendar standard defines three visibility classes:
-@table @asis
-@item @samp{PUBLIC}
-The entry is publicly visible (this is the default).
-@item @samp{CONFIDENTIAL}
-Only a limited group of clients get access to the
-event.
-@item @samp{PRIVATE}
-The entry can be retrieved only by its owner.
-@end table
-The server should treat unknown class properties the same as
-@samp{PRIVATE}.
-
-Exporting to iCalendar format depends in large part on the
-capabilities of the destination application.  Some are more lenient
-than others.  Consult the Org mode FAQ for advice on specific
-applications.
-
-@node Other Built-in Back-ends
-@section Other Built-in Back-ends
-
-Other export back-ends included with Org are:
-
-@itemize
-@item
-@samp{ox-man.el}: Export to a man page.
-@end itemize
-
-To activate such back-ends, either customize @code{org-export-backends} or
-load directly with @samp{(require 'ox-man)}.  On successful load, the
-back-end adds new keys in the export dispatcher (see @ref{The Export 
Dispatcher}).
-
-Follow the comment section of such files, for example, @samp{ox-man.el},
-for usage and configuration details.
-
-@node Advanced Export Configuration
-@section Advanced Export Configuration
-
-
-
-@anchor{Hooks}
-@subheading Hooks
-
-@vindex org-export-before-processing-hook
-@vindex org-export-before-parsing-hook
-The export process executes two hooks before the actual exporting
-begins.  The first hook, @code{org-export-before-processing-hook}, runs
-before any expansions of macros, Babel code, and include keywords in
-the buffer.  The second hook, @code{org-export-before-parsing-hook}, runs
-before the buffer is parsed.
-
-Functions added to these hooks are called with a single argument: the
-export back-end actually used, as a symbol.  You may use them for
-heavy duty structural modifications of the document.  For example, you
-can remove every headline in the buffer during export like this:
-
-@lisp
-(defun my-headline-removal (backend)
-  "Remove all headlines in the current buffer.
-BACKEND is the export back-end being used, as a symbol."
-  (org-map-entries
-   (lambda () (delete-region (point) (line-beginning-position 2)))))
-
-(add-hook 'org-export-before-parsing-hook 'my-headline-removal)
-@end lisp
-
-@anchor{Filters}
-@subheading Filters
-
-@cindex Filters, exporting
-Filters are lists of functions to be applied to certain parts for
-a given back-end.  The output from the first function in the filter is
-passed on to the next function in the filter.  The final output is the
-output from the final function in the filter.
-
-The Org export process has many filter sets applicable to different
-types of objects, plain text, parse trees, export options, and final
-output formats.  The filters are named after the element type or
-object type: @code{org-export-filter-TYPE-functions}, where @var{TYPE}
-is the type targeted by the filter.  Valid types are:
-
-@multitable @columnfractions 0.33 0.33 0.33
-@item body
-@tab bold
-@tab babel-call
-@item center-block
-@tab clock
-@tab code
-@item diary-sexp
-@tab drawer
-@tab dynamic-block
-@item entity
-@tab example-block
-@tab export-block
-@item export-snippet
-@tab final-output
-@tab fixed-width
-@item footnote-definition
-@tab footnote-reference
-@tab headline
-@item horizontal-rule
-@tab inline-babel-call
-@tab inline-src-block
-@item inlinetask
-@tab italic
-@tab item
-@item keyword
-@tab latex-environment
-@tab latex-fragment
-@item line-break
-@tab link
-@tab node-property
-@item options
-@tab paragraph
-@tab parse-tree
-@item plain-list
-@tab plain-text
-@tab planning
-@item property-drawer
-@tab quote-block
-@tab radio-target
-@item section
-@tab special-block
-@tab src-block
-@item statistics-cookie
-@tab strike-through
-@tab subscript
-@item superscript
-@tab table
-@tab table-cell
-@item table-row
-@tab target
-@tab timestamp
-@item underline
-@tab verbatim
-@tab verse-block
-@end multitable
-
-Here is an example filter that replaces non-breaking spaces @code{ } in the
-Org buffer with @samp{~} for the @LaTeX{} back-end.
-
-@lisp
-(defun my-latex-filter-nobreaks (text backend info)
-  "Ensure \" \" are properly handled in LaTeX export."
-  (when (org-export-derived-backend-p backend 'latex)
-    (replace-regexp-in-string " " "~" text)))
-
-(add-to-list 'org-export-filter-plain-text-functions
-             'my-latex-filter-nobreaks)
-@end lisp
-
-A filter requires three arguments: the code to be transformed, the
-name of the back-end, and some optional information about the export
-process.  The third argument can be safely ignored.  Note the use of
-@code{org-export-derived-backend-p} predicate that tests for @emph{latex}
-back-end or any other back-end, such as @emph{beamer}, derived from
-@emph{latex}.
-
-@anchor{Defining filters for individual files}
-@subheading Defining filters for individual files
-
-The Org export can filter not just for back-ends, but also for
-specific files through the @samp{BIND} keyword.  Here is an example with
-two filters; one removes brackets from time stamps, and the other
-removes strike-through text.  The filter functions are defined in
-a code block in the same Org file, which is a handy location for
-debugging.
-
-@example
-#+BIND: org-export-filter-timestamp-functions (tmp-f-timestamp)
-#+BIND: org-export-filter-strike-through-functions (tmp-f-strike-through)
-#+BEGIN_SRC emacs-lisp :exports results :results none
-  (defun tmp-f-timestamp (s backend info)
-    (replace-regexp-in-string "&[lg]t;\\|[][]" "" s))
-  (defun tmp-f-strike-through (s backend info) "")
-#+END_SRC
-@end example
-
-@anchor{Extending an existing back-end}
-@subheading Extending an existing back-end
-
-Some parts of the conversion process can be extended for certain
-elements so as to introduce a new or revised translation.  That is how
-the HTML export back-end was extended to handle Markdown format.  The
-extensions work seamlessly so any aspect of filtering not done by the
-extended back-end is handled by the original back-end.  Of all the
-export customization in Org, extending is very powerful as it operates
-at the parser level.
-
-For this example, make the @emph{ascii} back-end display the language used
-in a source code block.  Also make it display only when some attribute
-is non-@code{nil}, like the following:
-
-@example
-#+ATTR_ASCII: :language t
-@end example
-
-
-Then extend ASCII back-end with a custom ``my-ascii'' back-end.
-
-@lisp
-(defun my-ascii-src-block (src-block contents info)
-  "Transcode a SRC-BLOCK element from Org to ASCII.
-CONTENTS is nil.  INFO is a plist used as a communication
-channel."
-  (if (not (org-export-read-attribute :attr_ascii src-block :language))
-      (org-export-with-backend 'ascii src-block contents info)
-    (concat
-     (format ",--[ %s ]--\n%s`----"
-             (org-element-property :language src-block)
-             (replace-regexp-in-string
-              "^" "| "
-              (org-element-normalize-string
-               (org-export-format-code-default src-block info)))))))
-
-(org-export-define-derived-backend 'my-ascii 'ascii
-  :translate-alist '((src-block . my-ascii-src-block)))
-@end lisp
-
-The @code{my-ascii-src-block} function looks at the attribute above the
-current element.  If not true, hands over to @emph{ascii} back-end.  If
-true, which it is in this example, it creates a box around the code
-and leaves room for the inserting a string for language.  The last
-form creates the new back-end that springs to action only when
-translating @code{src-block} type elements.
-
-To use the newly defined back-end, evaluate the following from an Org
-buffer:
-
-@lisp
-(org-export-to-buffer 'my-ascii "*Org MY-ASCII Export*")
-@end lisp
-
-Further steps to consider would be an interactive function,
-self-installing an item in the export dispatcher menu, and other
-user-friendly improvements.
-
-@node Export in Foreign Buffers
-@section Export in Foreign Buffers
-
-The export back-ends in Org often include commands to convert selected
-regions.  A convenient feature of this in-place conversion is that the
-exported output replaces the original source.  Here are such
-functions:
-
-@table @asis
-@item @code{org-ascii-convert-region-to-ascii}
-@findex org-ascii-convert-region-to-ascii
-Convert the selected region into ASCII@.
-
-@item @code{org-ascii-convert-region-to-utf8}
-@findex org-ascii-convert-region-to-utf8
-Convert the selected region into UTF-8.
-
-@item @code{org-html-convert-region-to-html}
-@findex org-html-convert-region-to-html
-Convert the selected region into HTML@.
-
-@item @code{org-latex-convert-region-to-latex}
-@findex org-latex-convert-region-to-latex
-Convert the selected region into @LaTeX{}.
-
-@item @code{org-texinfo-convert-region-to-texinfo}
-@findex org-texinfo-convert-region-to-texinfo
-Convert the selected region into Texinfo.
-
-@item @code{org-md-convert-region-to-md}
-@findex org-md-convert-region-to-md
-Convert the selected region into Markdown.
-@end table
-
-In-place conversions are particularly handy for quick conversion of
-tables and lists in foreign buffers.  For example, in an HTML buffer,
-write a list in Org syntax, select it, and convert it to HTML with
-@kbd{M-x org-html-convert-region-to-html}.
-
-@menu
-* Bare HTML::                    Exporting HTML without CSS, Javascript, etc.
-@end menu
-
-@node Bare HTML
-@subsection Exporting to minimal HTML
-
-If you want to output a minimal HTML file, with no CSS, no Javascript,
-no preamble or postamble, here are the variable you would need to set:
-
-@vindex org-html-head
-@vindex org-html-head-extra
-@vindex org-html-head-include-default-style
-@vindex org-html-head-include-scripts
-@vindex org-html-preamble
-@vindex org-html-postamble
-@vindex org-html-use-infojs
-@lisp
-(setq org-html-head ""
-      org-html-head-extra ""
-      org-html-head-include-default-style nil
-      org-html-head-include-scripts nil
-      org-html-preamble nil
-      org-html-postamble nil
-      org-html-use-infojs nil)
-@end lisp
-
-@node Publishing
-@chapter Publishing
-
-@cindex publishing
-
-Org includes a publishing management system that allows you to
-configure automatic HTML conversion of @emph{projects} composed of
-interlinked Org files.  You can also configure Org to automatically
-upload your exported HTML pages and related attachments, such as
-images and source code files, to a web server.
-
-You can also use Org to convert files into PDF, or even combine HTML
-and PDF conversion so that files are available in both formats on the
-server.
-
-Publishing has been contributed to Org by David O'Toole.
-
-@menu
-* Configuration::                Defining projects.
-* Uploading Files::              How to get files up on the server.
-* Sample Configuration::         Example projects.
-* Triggering Publication::       Publication commands.
-@end menu
-
-@node Configuration
-@section Configuration
-
-Publishing needs significant configuration to specify files,
-destination and many other properties of a project.
-
-@menu
-* Project alist::                The central configuration variable.
-* Sources and destinations::     From here to there.
-* Selecting files::              What files are part of the project?
-* Publishing action::            Setting the function doing the publishing.
-* Publishing options::           Tweaking HTML/@LaTeX{} export.
-* Publishing links::             Which links keep working after publishing?
-* Site map::                     Generating a list of all pages.
-* Generating an index::          An index that reaches across pages.
-@end menu
-
-@node Project alist
-@subsection The variable @code{org-publish-project-alist}
-
-@cindex projects, for publishing
-
-@vindex org-publish-project-alist
-Publishing is configured almost entirely through setting the value of
-one variable, called @code{org-publish-project-alist}.  Each element of the
-list configures one project, and may be in one of the two following
-forms:
-
-@lisp
-("project-name" :property value :property value ...)
-@end lisp
-
-@noindent
-i.e., a well-formed property list with alternating keys and values,
-or:
-
-@lisp
-("project-name" :components ("project-name" "project-name" ...))
-@end lisp
-
-In both cases, projects are configured by specifying property values.
-A project defines the set of files that are to be published, as well
-as the publishing configuration to use when publishing those files.
-When a project takes the second form listed above, the individual
-members of the @code{:components} property are taken to be sub-projects,
-which group together files requiring different publishing options.
-When you publish such a ``meta-project'', all the components are also
-published, in the sequence given.
-
-@node Sources and destinations
-@subsection Sources and destinations for files
-
-@cindex directories, for publishing
-
-Most properties are optional, but some should always be set.  In
-particular, Org needs to know where to look for source files, and
-where to put published files.
-
-@table @asis
-@item @code{:base-directory}
-Directory containing publishing source files.
-
-@item @code{:publishing-directory}
-Directory where output files are published.  You can directly
-publish to a webserver using a file name syntax appropriate for the
-Emacs tramp package.  Or you can publish to a local directory and
-use external tools to upload your website (see @ref{Uploading Files}).
-
-@item @code{:preparation-function}
-Function or list of functions to be called before starting the
-publishing process, for example, to run @samp{make} for updating files to
-be published.  Each preparation function is called with a single
-argument, the project property list.
-
-@item @code{:completion-function}
-Function or list of functions called after finishing the publishing
-process, for example, to change permissions of the resulting files.
-Each completion function is called with a single argument, the
-project property list.
-@end table
-
-@node Selecting files
-@subsection Selecting files
-
-@cindex files, selecting for publishing
-
-By default, all files with extension @samp{.org} in the base directory are
-considered part of the project.  This can be modified by setting the
-following properties
-
-@table @asis
-@item @code{:base-extension}
-Extension---without the dot---of source files.  This actually is
-a regular expression.  Set this to the symbol @code{any} if you want to
-get all files in @code{:base-directory}, even without extension.
-
-@item @code{:exclude}
-Regular expression to match file names that should not be published,
-even though they have been selected on the basis of their extension.
-
-@item @code{:include}
-List of files to be included regardless of @code{:base-extension} and
-@code{:exclude}.
-
-@item @code{:recursive}
-Non-@code{nil} means, check base-directory recursively for files to
-publish.
-@end table
-
-@node Publishing action
-@subsection Publishing action
-
-@cindex action, for publishing
-
-Publishing means that a file is copied to the destination directory
-and possibly transformed in the process.  The default transformation
-is to export Org files as HTML files, and this is done by the function
-@code{org-publish-org-to-html} which calls the HTML exporter (see @ref{HTML 
Export}).  But you can also publish your content as PDF files using
-@code{org-publish-org-to-pdf}, or as ASCII, Texinfo, etc., using the
-corresponding functions.
-
-If you want to publish the Org file as an @samp{.org} file but with
-@emph{archived}, @emph{commented}, and @emph{tag-excluded} trees removed, use
-@code{org-publish-org-to-org}.  This produces @samp{file.org} and put it in the
-publishing directory.  If you want a htmlized version of this file,
-set the parameter @code{:htmlized-source} to @code{t}.  It produces
-@samp{file.org.html} in the publishing directory@footnote{If the publishing 
directory is the same as the source
-directory, @samp{file.org} is exported as @samp{file.org.org}, so you probably
-do not want to do this.}.
-
-Other files like images only need to be copied to the publishing
-destination; for this you can use @code{org-publish-attachment}.  For
-non-Org files, you always need to specify the publishing function:
-
-@table @asis
-@item @code{:publishing-function}
-Function executing the publication of a file.  This may also be
-a list of functions, which are all called in turn.
-
-@item @code{:htmlized-source}
-Non-@code{nil} means, publish htmlized source.
-@end table
-
-The function must accept three arguments: a property list containing
-at least a @code{:publishing-directory} property, the name of the file to
-be published, and the path to the publishing directory of the output
-file.  It should take the specified file, make the necessary
-transformation, if any, and place the result into the destination
-folder.
-
-@node Publishing options
-@subsection Options for the exporters
-
-@cindex options, for publishing
-@cindex publishing options
-
-The property list can be used to set many export options for the HTML
-and @LaTeX{} exporters.  In most cases, these properties correspond to
-user variables in Org.  The table below lists these properties along
-with the variable they belong to.  See the documentation string for
-the respective variable for details.
-
-@vindex org-publish-project-alist
-When a property is given a value in @code{org-publish-project-alist}, its
-setting overrides the value of the corresponding user variable, if
-any, during publishing.  Options set within a file (see @ref{Export 
Settings}), however, override everything.
-
-@anchor{Generic properties}
-@subsubheading Generic properties
-
-@multitable {aaaaaaaaaaaaaaaaaaaaaaa} {aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa}
-@item @code{:archived-trees}
-@tab @code{org-export-with-archived-trees}
-@item @code{:exclude-tags}
-@tab @code{org-export-exclude-tags}
-@item @code{:headline-levels}
-@tab @code{org-export-headline-levels}
-@item @code{:language}
-@tab @code{org-export-default-language}
-@item @code{:preserve-breaks}
-@tab @code{org-export-preserve-breaks}
-@item @code{:section-numbers}
-@tab @code{org-export-with-section-numbers}
-@item @code{:select-tags}
-@tab @code{org-export-select-tags}
-@item @code{:with-author}
-@tab @code{org-export-with-author}
-@item @code{:with-broken-links}
-@tab @code{org-export-with-broken-links}
-@item @code{:with-clocks}
-@tab @code{org-export-with-clocks}
-@item @code{:with-creator}
-@tab @code{org-export-with-creator}
-@item @code{:with-date}
-@tab @code{org-export-with-date}
-@item @code{:with-drawers}
-@tab @code{org-export-with-drawers}
-@item @code{:with-email}
-@tab @code{org-export-with-email}
-@item @code{:with-emphasize}
-@tab @code{org-export-with-emphasize}
-@item @code{:with-fixed-width}
-@tab @code{org-export-with-fixed-width}
-@item @code{:with-footnotes}
-@tab @code{org-export-with-footnotes}
-@item @code{:with-latex}
-@tab @code{org-export-with-latex}
-@item @code{:with-planning}
-@tab @code{org-export-with-planning}
-@item @code{:with-priority}
-@tab @code{org-export-with-priority}
-@item @code{:with-properties}
-@tab @code{org-export-with-properties}
-@item @code{:with-special-strings}
-@tab @code{org-export-with-special-strings}
-@item @code{:with-sub-superscript}
-@tab @code{org-export-with-sub-superscripts}
-@item @code{:with-tables}
-@tab @code{org-export-with-tables}
-@item @code{:with-tags}
-@tab @code{org-export-with-tags}
-@item @code{:with-tasks}
-@tab @code{org-export-with-tasks}
-@item @code{:with-timestamps}
-@tab @code{org-export-with-timestamps}
-@item @code{:with-title}
-@tab @code{org-export-with-title}
-@item @code{:with-toc}
-@tab @code{org-export-with-toc}
-@item @code{:with-todo-keywords}
-@tab @code{org-export-with-todo-keywords}
-@end multitable
-
-@anchor{ASCII specific properties}
-@subsubheading ASCII specific properties
-
-@multitable {aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa} 
{aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa}
-@item @code{:ascii-bullets}
-@tab @code{org-ascii-bullets}
-@item @code{:ascii-caption-above}
-@tab @code{org-ascii-caption-above}
-@item @code{:ascii-charset}
-@tab @code{org-ascii-charset}
-@item @code{:ascii-global-margin}
-@tab @code{org-ascii-global-margin}
-@item @code{:ascii-format-drawer-function}
-@tab @code{org-ascii-format-drawer-function}
-@item @code{:ascii-format-inlinetask-function}
-@tab @code{org-ascii-format-inlinetask-function}
-@item @code{:ascii-headline-spacing}
-@tab @code{org-ascii-headline-spacing}
-@item @code{:ascii-indented-line-width}
-@tab @code{org-ascii-indented-line-width}
-@item @code{:ascii-inlinetask-width}
-@tab @code{org-ascii-inlinetask-width}
-@item @code{:ascii-inner-margin}
-@tab @code{org-ascii-inner-margin}
-@item @code{:ascii-links-to-notes}
-@tab @code{org-ascii-links-to-notes}
-@item @code{:ascii-list-margin}
-@tab @code{org-ascii-list-margin}
-@item @code{:ascii-paragraph-spacing}
-@tab @code{org-ascii-paragraph-spacing}
-@item @code{:ascii-quote-margin}
-@tab @code{org-ascii-quote-margin}
-@item @code{:ascii-table-keep-all-vertical-lines}
-@tab @code{org-ascii-table-keep-all-vertical-lines}
-@item @code{:ascii-table-use-ascii-art}
-@tab @code{org-ascii-table-use-ascii-art}
-@item @code{:ascii-table-widen-columns}
-@tab @code{org-ascii-table-widen-columns}
-@item @code{:ascii-text-width}
-@tab @code{org-ascii-text-width}
-@item @code{:ascii-underline}
-@tab @code{org-ascii-underline}
-@item @code{:ascii-verbatim-format}
-@tab @code{org-ascii-verbatim-format}
-@end multitable
-
-@anchor{Beamer specific properties}
-@subsubheading Beamer specific properties
-
-@multitable {aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa} 
{aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa}
-@item @code{:beamer-theme}
-@tab @code{org-beamer-theme}
-@item @code{:beamer-column-view-format}
-@tab @code{org-beamer-column-view-format}
-@item @code{:beamer-environments-extra}
-@tab @code{org-beamer-environments-extra}
-@item @code{:beamer-frame-default-options}
-@tab @code{org-beamer-frame-default-options}
-@item @code{:beamer-outline-frame-options}
-@tab @code{org-beamer-outline-frame-options}
-@item @code{:beamer-outline-frame-title}
-@tab @code{org-beamer-outline-frame-title}
-@item @code{:beamer-subtitle-format}
-@tab @code{org-beamer-subtitle-format}
-@end multitable
-
-@anchor{HTML specific properties}
-@subsubheading HTML specific properties
-
-@multitable {aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa} 
{aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa}
-@item @code{:html-allow-name-attribute-in-anchors}
-@tab @code{org-html-allow-name-attribute-in-anchors}
-@item @code{:html-checkbox-type}
-@tab @code{org-html-checkbox-type}
-@item @code{:html-container}
-@tab @code{org-html-container-element}
-@item @code{:html-divs}
-@tab @code{org-html-divs}
-@item @code{:html-doctype}
-@tab @code{org-html-doctype}
-@item @code{:html-extension}
-@tab @code{org-html-extension}
-@item @code{:html-footnote-format}
-@tab @code{org-html-footnote-format}
-@item @code{:html-footnote-separator}
-@tab @code{org-html-footnote-separator}
-@item @code{:html-footnotes-section}
-@tab @code{org-html-footnotes-section}
-@item @code{:html-format-drawer-function}
-@tab @code{org-html-format-drawer-function}
-@item @code{:html-format-headline-function}
-@tab @code{org-html-format-headline-function}
-@item @code{:html-format-inlinetask-function}
-@tab @code{org-html-format-inlinetask-function}
-@item @code{:html-head-extra}
-@tab @code{org-html-head-extra}
-@item @code{:html-head-include-default-style}
-@tab @code{org-html-head-include-default-style}
-@item @code{:html-head-include-scripts}
-@tab @code{org-html-head-include-scripts}
-@item @code{:html-head}
-@tab @code{org-html-head}
-@item @code{:html-home/up-format}
-@tab @code{org-html-home/up-format}
-@item @code{:html-html5-fancy}
-@tab @code{org-html-html5-fancy}
-@item @code{:html-indent}
-@tab @code{org-html-indent}
-@item @code{:html-infojs-options}
-@tab @code{org-html-infojs-options}
-@item @code{:html-infojs-template}
-@tab @code{org-html-infojs-template}
-@item @code{:html-inline-image-rules}
-@tab @code{org-html-inline-image-rules}
-@item @code{:html-inline-images}
-@tab @code{org-html-inline-images}
-@item @code{:html-link-home}
-@tab @code{org-html-link-home}
-@item @code{:html-link-org-files-as-html}
-@tab @code{org-html-link-org-files-as-html}
-@item @code{:html-link-up}
-@tab @code{org-html-link-up}
-@item @code{:html-link-use-abs-url}
-@tab @code{org-html-link-use-abs-url}
-@item @code{:html-mathjax-options}
-@tab @code{org-html-mathjax-options}
-@item @code{:html-mathjax-template}
-@tab @code{org-html-mathjax-template}
-@item @code{:html-equation-reference-format}
-@tab @code{org-html-equation-reference-format}
-@item @code{:html-metadata-timestamp-format}
-@tab @code{org-html-metadata-timestamp-format}
-@item @code{:html-postamble-format}
-@tab @code{org-html-postamble-format}
-@item @code{:html-postamble}
-@tab @code{org-html-postamble}
-@item @code{:html-preamble-format}
-@tab @code{org-html-preamble-format}
-@item @code{:html-preamble}
-@tab @code{org-html-preamble}
-@item @code{:html-self-link-headlines}
-@tab @code{org-html-self-link-headlines}
-@item @code{:html-table-align-individual-field}
-@tab @code{de@{org-html-table-align-individual-fields}
-@item @code{:html-table-attributes}
-@tab @code{org-html-table-default-attributes}
-@item @code{:html-table-caption-above}
-@tab @code{org-html-table-caption-above}
-@item @code{:html-table-data-tags}
-@tab @code{org-html-table-data-tags}
-@item @code{:html-table-header-tags}
-@tab @code{org-html-table-header-tags}
-@item @code{:html-table-row-tags}
-@tab @code{org-html-table-row-tags}
-@item @code{:html-table-use-header-tags-for-first-column}
-@tab @code{org-html-table-use-header-tags-for-first-column}
-@item @code{:html-tag-class-prefix}
-@tab @code{org-html-tag-class-prefix}
-@item @code{:html-text-markup-alist}
-@tab @code{org-html-text-markup-alist}
-@item @code{:html-todo-kwd-class-prefix}
-@tab @code{org-html-todo-kwd-class-prefix}
-@item @code{:html-toplevel-hlevel}
-@tab @code{org-html-toplevel-hlevel}
-@item @code{:html-use-infojs}
-@tab @code{org-html-use-infojs}
-@item @code{:html-validation-link}
-@tab @code{org-html-validation-link}
-@item @code{:html-viewport}
-@tab @code{org-html-viewport}
-@item @code{:html-wrap-src-lines}
-@tab @code{org-html-wrap-src-lines}
-@item @code{:html-xml-declaration}
-@tab @code{org-html-xml-declaration}
-@end multitable
-
-@anchor{@LaTeX{} specific properties}
-@subsubheading @LaTeX{} specific properties
-
-@multitable {aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa} 
{aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa}
-@item @code{:latex-active-timestamp-format}
-@tab @code{org-latex-active-timestamp-format}
-@item @code{:latex-caption-above}
-@tab @code{org-latex-caption-above}
-@item @code{:latex-classes}
-@tab @code{org-latex-classes}
-@item @code{:latex-class}
-@tab @code{org-latex-default-class}
-@item @code{:latex-compiler}
-@tab @code{org-latex-compiler}
-@item @code{:latex-default-figure-position}
-@tab @code{org-latex-default-figure-position}
-@item @code{:latex-default-table-environment}
-@tab @code{org-latex-default-table-environment}
-@item @code{:latex-default-table-mode}
-@tab @code{org-latex-default-table-mode}
-@item @code{:latex-diary-timestamp-format}
-@tab @code{org-latex-diary-timestamp-format}
-@item @code{:latex-footnote-defined-format}
-@tab @code{org-latex-footnote-defined-format}
-@item @code{:latex-footnote-separator}
-@tab @code{org-latex-footnote-separator}
-@item @code{:latex-format-drawer-function}
-@tab @code{org-latex-format-drawer-function}
-@item @code{:latex-format-headline-function}
-@tab @code{org-latex-format-headline-function}
-@item @code{:latex-format-inlinetask-function}
-@tab @code{org-latex-format-inlinetask-function}
-@item @code{:latex-hyperref-template}
-@tab @code{org-latex-hyperref-template}
-@item @code{:latex-image-default-height}
-@tab @code{org-latex-image-default-height}
-@item @code{:latex-image-default-option}
-@tab @code{org-latex-image-default-option}
-@item @code{:latex-image-default-width}
-@tab @code{org-latex-image-default-width}
-@item @code{:latex-images-centered}
-@tab @code{org-latex-images-centered}
-@item @code{:latex-inactive-timestamp-format}
-@tab @code{org-latex-inactive-timestamp-format}
-@item @code{:latex-inline-image-rules}
-@tab @code{org-latex-inline-image-rules}
-@item @code{:latex-link-with-unknown-path-format}
-@tab @code{org-latex-link-with-unknown-path-format}
-@item @code{:latex-listings-langs}
-@tab @code{org-latex-listings-langs}
-@item @code{:latex-listings-options}
-@tab @code{org-latex-listings-options}
-@item @code{:latex-listings}
-@tab @code{org-latex-listings}
-@item @code{:latex-minted-langs}
-@tab @code{org-latex-minted-langs}
-@item @code{:latex-minted-options}
-@tab @code{org-latex-minted-options}
-@item @code{:latex-prefer-user-labels}
-@tab @code{org-latex-prefer-user-labels}
-@item @code{:latex-subtitle-format}
-@tab @code{org-latex-subtitle-format}
-@item @code{:latex-subtitle-separate}
-@tab @code{org-latex-subtitle-separate}
-@item @code{:latex-table-scientific-notation}
-@tab @code{org-latex-table-scientific-notation}
-@item @code{:latex-tables-booktabs}
-@tab @code{org-latex-tables-booktabs}
-@item @code{:latex-tables-centered}
-@tab @code{org-latex-tables-centered}
-@item @code{:latex-text-markup-alist}
-@tab @code{org-latex-text-markup-alist}
-@item @code{:latex-title-command}
-@tab @code{org-latex-title-command}
-@item @code{:latex-toc-command}
-@tab @code{org-latex-toc-command}
-@end multitable
-
-@anchor{Markdown specific properties}
-@subsubheading Markdown specific properties
-
-@multitable {aaaaaaaaaaaaaaaaaaaaaaa} {aaaaaaaaaaaaaaaaaaaaaaaaaa}
-@item @code{:md-footnote-format}
-@tab @code{org-md-footnote-format}
-@item @code{:md-footnotes-section}
-@tab @code{org-md-footnotes-section}
-@item @code{:md-headline-style}
-@tab @code{org-md-headline-style}
-@end multitable
-
-@anchor{ODT specific properties}
-@subsubheading ODT specific properties
-
-@multitable {aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa} 
{aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa}
-@item @code{:odt-content-template-file}
-@tab @code{org-odt-content-template-file}
-@item @code{:odt-display-outline-level}
-@tab @code{org-odt-display-outline-level}
-@item @code{:odt-fontify-srcblocks}
-@tab @code{org-odt-fontify-srcblocks}
-@item @code{:odt-format-drawer-function}
-@tab @code{org-odt-format-drawer-function}
-@item @code{:odt-format-headline-function}
-@tab @code{org-odt-format-headline-function}
-@item @code{:odt-format-inlinetask-function}
-@tab @code{org-odt-format-inlinetask-function}
-@item @code{:odt-inline-formula-rules}
-@tab @code{org-odt-inline-formula-rules}
-@item @code{:odt-inline-image-rules}
-@tab @code{org-odt-inline-image-rules}
-@item @code{:odt-pixels-per-inch}
-@tab @code{org-odt-pixels-per-inch}
-@item @code{:odt-styles-file}
-@tab @code{org-odt-styles-file}
-@item @code{:odt-table-styles}
-@tab @code{org-odt-table-styles}
-@item @code{:odt-use-date-fields}
-@tab @code{org-odt-use-date-fields}
-@end multitable
-
-@anchor{Texinfo specific properties}
-@subsubheading Texinfo specific properties
-
-@multitable {aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa} 
{aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa}
-@item @code{:texinfo-active-timestamp-format}
-@tab @code{org-texinfo-active-timestamp-format}
-@item @code{:texinfo-classes}
-@tab @code{org-texinfo-classes}
-@item @code{:texinfo-class}
-@tab @code{org-texinfo-default-class}
-@item @code{:texinfo-table-default-markup}
-@tab @code{org-texinfo-table-default-markup}
-@item @code{:texinfo-diary-timestamp-format}
-@tab @code{org-texinfo-diary-timestamp-format}
-@item @code{:texinfo-filename}
-@tab @code{org-texinfo-filename}
-@item @code{:texinfo-format-drawer-function}
-@tab @code{org-texinfo-format-drawer-function}
-@item @code{:texinfo-format-headline-function}
-@tab @code{org-texinfo-format-headline-function}
-@item @code{:texinfo-format-inlinetask-function}
-@tab @code{org-texinfo-format-inlinetask-function}
-@item @code{:texinfo-inactive-timestamp-format}
-@tab @code{org-texinfo-inactive-timestamp-format}
-@item @code{:texinfo-link-with-unknown-path-format}
-@tab @code{org-texinfo-link-with-unknown-path-format}
-@item @code{:texinfo-node-description-column}
-@tab @code{org-texinfo-node-description-column}
-@item @code{:texinfo-table-scientific-notation}
-@tab @code{org-texinfo-table-scientific-notation}
-@item @code{:texinfo-tables-verbatim}
-@tab @code{org-texinfo-tables-verbatim}
-@item @code{:texinfo-text-markup-alist}
-@tab @code{org-texinfo-text-markup-alist}
-@end multitable
-
-@node Publishing links
-@subsection Publishing links
-
-@cindex links, publishing
-
-To create a link from one Org file to another, you would use something
-like @samp{[[file:foo.org][The foo]]} or simply @samp{[[file:foo.org]]} (see 
@ref{External Links}).  When
-published, this link becomes a link to @samp{foo.html}.  You can thus
-interlink the pages of your ``Org web'' project and the links will work
-as expected when you publish them to HTML@.  If you also publish the
-Org source file and want to link to it, use an @samp{http} link instead of
-a @samp{file:} link, because @samp{file} links are converted to link to the
-corresponding @samp{.html} file.
-
-You may also link to related files, such as images.  Provided you are
-careful with relative file names, and provided you have also
-configured Org to upload the related files, these links will work too.
-See @ref{Complex example}, for an example of this
-usage.
-
-Eventually, links between published documents can contain some search
-options (see @ref{Search Options}), which will be resolved to
-the appropriate location in the linked file.  For example, once
-published to HTML, the following links all point to a dedicated anchor
-in @samp{foo.html}.
-
-@example
-[[file:foo.org::*heading]]
-[[file:foo.org::#custom-id]]
-[[file:foo.org::target]]
-@end example
-
-@node Site map
-@subsection Generating a sitemap
-
-@cindex sitemap, of published pages
-
-The following properties may be used to control publishing of
-a map of files for a given project.
-
-@table @asis
-@item @code{:auto-sitemap}
-When non-@code{nil}, publish a sitemap during
-@code{org-publish-current-project} or @code{org-publish-all}.
-
-@item @code{:sitemap-filename}
-Filename for output of sitemap.  Defaults to @samp{sitemap.org}, which
-becomes @samp{sitemap.html}.
-
-@item @code{:sitemap-title}
-Title of sitemap page.  Defaults to name of file.
-
-@item @code{:sitemap-format-entry}
-@findex org-publish-find-date
-@findex org-publish-find-property
-@findex org-publish-find-title
-With this option one can tell how a site-map entry is formatted in
-the site-map.  It is a function called with three arguments: the
-file or directory name relative to base directory of the project,
-the site-map style and the current project.  It is expected to
-return a string.  Default value turns file names into links and use
-document titles as descriptions.  For specific formatting needs, one
-can use @code{org-publish-find-date}, @code{org-publish-find-title} and
-@code{org-publish-find-property}, to retrieve additional information
-about published documents.
-
-@item @code{:sitemap-function}
-Plug-in function to use for generation of the sitemap.  It is called
-with two arguments: the title of the site-map and a representation
-of the files and directories involved in the project as a nested
-list, which can further be transformed using @code{org-list-to-generic},
-@code{org-list-to-subtree} and alike.  Default value generates a plain
-list of links to all files in the project.
-
-@item @code{:sitemap-sort-folders}
-Where folders should appear in the sitemap.  Set this to @code{first}
-(default) or @code{last} to display folders first or last, respectively.
-When set to @code{ignore}, folders are ignored altogether.  Any other
-value mixes files and folders.  This variable has no effect when
-site-map style is @code{tree}.
-
-@item @code{:sitemap-sort-files}
-How the files are sorted in the site map.  Set this to
-@code{alphabetically} (default), @code{chronologically} or
-@code{anti-chronologically}.  @code{chronologically} sorts the files with
-older date first while @code{anti-chronologically} sorts the files with
-newer date first.  @code{alphabetically} sorts the files alphabetically.
-The date of a file is retrieved with @code{org-publish-find-date}.
-
-@item @code{:sitemap-ignore-case}
-Should sorting be case-sensitive?  Default @code{nil}.
-
-@item @code{:sitemap-file-entry-format}
-With this option one can tell how a sitemap's entry is formatted in
-the sitemap.  This is a format string with some escape sequences:
-@code{%t} stands for the title of the file, @code{%a} stands for the author of
-the file and @code{%d} stands for the date of the file.  The date is
-retrieved with the @code{org-publish-find-date} function and formatted
-with @code{org-publish-sitemap-date-format}.  Default @code{%t}.
-
-@item @code{:sitemap-date-format}
-Format string for the @code{format-time-string} function that tells how
-a sitemap entry's date is to be formatted.  This property bypasses
-@code{org-publish-sitemap-date-format} which defaults to @code{%Y-%m-%d}.
-@end table
-
-@node Generating an index
-@subsection Generating an index
-
-@cindex index, in a publishing project
-
-Org mode can generate an index across the files of a publishing project.
-
-@table @asis
-@item @code{:makeindex}
-When non-@code{nil}, generate in index in the file @samp{theindex.org} and
-publish it as @samp{theindex.html}.
-@end table
-
-The file is created when first publishing a project with the
-@code{:makeindex} set.  The file only contains a statement @samp{#+INCLUDE:
-"theindex.inc"}.  You can then build around this include statement by
-adding a title, style information, etc.
-
-@cindex @samp{INDEX}, keyword
-Index entries are specified with @samp{INDEX} keyword.  An entry that
-contains an exclamation mark creates a sub item.
-
-@example
-*** Curriculum Vitae
-#+INDEX: CV
-#+INDEX: Application!CV
-@end example
-
-@node Uploading Files
-@section Uploading Files
-
-@cindex rsync
-@cindex unison
-
-For those people already utilizing third party sync tools such as
-Rsync or Unison, it might be preferable not to use the built-in remote
-publishing facilities of Org mode which rely heavily on Tramp.  Tramp,
-while very useful and powerful, tends not to be so efficient for
-multiple file transfer and has been known to cause problems under
-heavy usage.
-
-Specialized synchronization utilities offer several advantages.  In
-addition to timestamp comparison, they also do content and
-permissions/attribute checks.  For this reason you might prefer to
-publish your web to a local directory---possibly even @emph{in place} with
-your Org files---and then use Unison or Rsync to do the
-synchronization with the remote host.
-
-Since Unison, for example, can be configured as to which files to
-transfer to a certain remote destination, it can greatly simplify the
-project publishing definition.  Simply keep all files in the correct
-location, process your Org files with @code{org-publish} and let the
-synchronization tool do the rest.  You do not need, in this scenario,
-to include attachments such as JPG, CSS or PNG files in the project
-definition since the third-party tool syncs them.
-
-Publishing to a local directory is also much faster than to a remote
-one, so that you can afford more easily to republish entire projects.
-If you set @code{org-publish-use-timestamps-flag} to @code{nil}, you gain the
-main benefit of re-including any changed external files such as source
-example files you might include with @samp{INCLUDE} keyword.  The timestamp
-mechanism in Org is not smart enough to detect if included files have
-been modified.
-
-@node Sample Configuration
-@section Sample Configuration
-
-Below we provide two example configurations.  The first one is
-a simple project publishing only a set of Org files.  The second
-example is more complex, with a multi-component project.
-
-@menu
-* Simple example::               One-component publishing.
-* Complex example::              A multi-component publishing example.
-@end menu
-
-@node Simple example
-@subsection Example: simple publishing configuration
-
-This example publishes a set of Org files to the @samp{public_html}
-directory on the local machine.
-
-@lisp
-(setq org-publish-project-alist
-      '(("org"
-         :base-directory "~/org/"
-         :publishing-directory "~/public_html"
-         :section-numbers nil
-         :table-of-contents nil
-         :style "<link rel=\"stylesheet\"
-                href=\"../other/mystyle.css\"
-                type=\"text/css\"/>")))
-@end lisp
-
-@node Complex example
-@subsection Example: complex publishing configuration
-
-This more complicated example publishes an entire website, including
-Org files converted to HTML, image files, Emacs Lisp source code, and
-style sheets.  The publishing directory is remote and private files
-are excluded.
-
-To ensure that links are preserved, care should be taken to replicate
-your directory structure on the web server, and to use relative file
-paths.  For example, if your Org files are kept in @samp{~/org/} and your
-publishable images in @samp{~/images/}, you would link to an image with
-
-@example
-file:../images/myimage.png
-@end example
-
-
-On the web server, the relative path to the image should be the same.
-You can accomplish this by setting up an @samp{images/} folder in the right
-place on the web server, and publishing images to it.
-
-@lisp
-(setq org-publish-project-alist
-      '(("orgfiles"
-         :base-directory "~/org/"
-         :base-extension "org"
-         :publishing-directory "/ssh:user@@host:~/html/notebook/"
-         :publishing-function org-html-publish-to-html
-         :exclude "PrivatePage.org" ;; regexp
-         :headline-levels 3
-         :section-numbers nil
-         :with-toc nil
-         :html-head "<link rel=\"stylesheet\"
-                  href=\"../other/mystyle.css\" type=\"text/css\"/>"
-         :html-preamble t)
-
-        ("images"
-         :base-directory "~/images/"
-         :base-extension "jpg\\|gif\\|png"
-         :publishing-directory "/ssh:user@@host:~/html/images/"
-         :publishing-function org-publish-attachment)
-
-        ("other"
-         :base-directory "~/other/"
-         :base-extension "css\\|el"
-         :publishing-directory "/ssh:user@@host:~/html/other/"
-         :publishing-function org-publish-attachment)
-        ("website" :components ("orgfiles" "images" "other"))))
-@end lisp
-
-@node Triggering Publication
-@section Triggering Publication
-
-Once properly configured, Org can publish with the following commands:
-
-@table @asis
-@item @kbd{C-c C-e P x} (@code{org-publish})
-@kindex C-c C-e P x
-@findex org-publish
-Prompt for a specific project and publish all files that belong to
-it.
-
-@item @kbd{C-c C-e P p} (@code{org-publish-current-project})
-@kindex C-c C-e P p
-@findex org-publish-current-project
-Publish the project containing the current file.
-
-@item @kbd{C-c C-e P f} (@code{org-publish-current-file})
-@kindex C-c C-e P f
-@findex org-publish-current-file
-Publish only the current file.
-
-@item @kbd{C-c C-e P a} (@code{org-publish-all})
-@kindex C-c C-e P a
-@findex org-publish-all
-Publish every project.
-@end table
-
-@vindex org-publish-use-timestamps-flag
-Org uses timestamps to track when a file has changed.  The above
-functions normally only publish changed files.  You can override this
-and force publishing of all files by giving a prefix argument to any
-of the commands above, or by customizing the variable
-@code{org-publish-use-timestamps-flag}.  This may be necessary in
-particular if files include other files via @samp{SETUPFILE} or @samp{INCLUDE}
-keywords.
-
-@node Working with Source Code
-@chapter Working with Source Code
-
-@cindex source code, working with
-
-Source code here refers to any plain text collection of computer
-instructions, possibly with comments, written using a human-readable
-programming language.  Org can manage source code in an Org document
-when the source code is identified with begin and end markers.
-Working with source code begins with identifying source code blocks.
-A source code block can be placed almost anywhere in an Org document;
-it is not restricted to the preamble or the end of the document.
-However, Org cannot manage a source code block if it is placed inside
-an Org comment or within a fixed width section.
-
-Here is an example source code block in the Emacs Lisp language:
-
-@example
-#+BEGIN_SRC emacs-lisp
-  (defun org-xor (a b)
-     "Exclusive or."
-     (if a (not b) b))
-#+END_SRC
-@end example
-
-Source code blocks are one of many Org block types, which also include
-``center'', ``comment'', ``dynamic'', ``example'', ``export'', ``quote'',
-``special'', and ``verse''.  This section pertains to blocks between
-@samp{#+BEGIN_SRC} and @samp{#+END_SRC}.
-
-Details of Org's facilities for working with source code are described
-in the following sections.
-
-@menu
-* Features Overview::            Enjoy the versatility of source blocks.
-* Structure of Code Blocks::     Code block syntax described.
-* Using Header Arguments::       Different ways to set header arguments.
-* Environment of a Code Block::  Arguments, sessions, working directory...
-* Evaluating Code Blocks::       Place results of evaluation in the Org buffer.
-* Results of Evaluation::        Choosing a results type, post-processing...
-* Exporting Code Blocks::        Export contents and/or results.
-* Extracting Source Code::       Create pure source code files.
-* Languages::                    List of supported code block languages.
-* Editing Source Code::          Language major-mode editing.
-* Noweb Reference Syntax::       Literate programming in Org mode.
-* Library of Babel::             Use and contribute to a library of useful 
code blocks.
-* Key bindings and Useful Functions:: Work quickly with code blocks.
-* Batch Execution::              Call functions from the command line.
-@end menu
-
-@node Features Overview
-@section Features Overview
-
-Org can manage the source code in the block delimited by @samp{#+BEGIN_SRC}
-@dots{} @samp{#+END_SRC} in several ways that can simplify housekeeping tasks
-essential to modern source code maintenance.  Org can edit, format,
-extract, export, and publish source code blocks.  Org can also compile
-and execute a source code block, then capture the results.  The Org
-mode literature sometimes refers to source code blocks as @emph{live code}
-blocks because they can alter the content of the Org document or the
-material that it exports.  Users can control how live they want each
-source code block by tweaking the header arguments (see @ref{Using Header 
Arguments}) for compiling, execution, extraction, and exporting.
-
-For editing and formatting a source code block, Org uses an
-appropriate Emacs major mode that includes features specifically
-designed for source code in that language.
-
-Org can extract one or more source code blocks and write them to one
-or more source files---a process known as @emph{tangling} in literate
-programming terminology.
-
-For exporting and publishing, Org's back-ends can format a source code
-block appropriately, often with native syntax highlighting.
-
-For executing and compiling a source code block, the user can
-configure Org to select the appropriate compiler.  Org provides
-facilities to collect the result of the execution or compiler output,
-insert it into the Org document, and/or export it.  In addition to
-text results, Org can insert links to other data types, including
-audio, video, and graphics.  Org can also link a compiler error
-message to the appropriate line in the source code block.
-
-An important feature of Org's management of source code blocks is the
-ability to pass variables, functions, and results to one another using
-a common syntax for source code blocks in any language.  Although most
-literate programming facilities are restricted to one language or
-another, Org's language-agnostic approach lets the literate programmer
-match each programming task with the appropriate computer language and
-to mix them all together in a single Org document.  This
-interoperability among languages explains why Org's source code
-management facility was named @emph{Org Babel} by its originators, Eric
-Schulte and Dan Davison.
-
-Org mode fulfills the promise of easy verification and maintenance of
-publishing reproducible research by keeping text, data, code,
-configuration settings of the execution environment, the results of
-the execution, and associated narratives, claims, references, and
-internal and external links in a single Org document.
-
-@node Structure of Code Blocks
-@section Structure of Code Blocks
-
-@cindex code block, structure
-@cindex source code, block structure
-@cindex @samp{NAME} keyword, in source blocks
-@cindex @samp{BEGIN_SRC}
-
-Org offers two ways to structure source code in Org documents: in
-a source code block, and directly inline.  Both specifications are
-shown below.
-
-A source code block conforms to this structure:
-
-@example
-#+NAME: <name>
-#+BEGIN_SRC <language> <switches> <header arguments>
-  <body>
-#+END_SRC
-@end example
-
-Do not be put-off by having to remember the source block syntax.  Org
-mode offers a command for wrapping existing text in a block (see
-@ref{Structure Templates}).  Org also works with other completion systems
-in Emacs, some of which predate Org and have custom domain-specific
-languages for defining templates.  Regular use of templates reduces
-errors, increases accuracy, and maintains consistency.
-
-@cindex source code, inline
-An inline code block conforms to this structure:
-
-@example
-src_<language>@{<body>@}
-@end example
-
-
-@noindent
-or
-
-@example
-src_<language>[<header arguments>]@{<body>@}
-@end example
-
-
-@table @asis
-@item @samp{#+NAME: <name>}
-Optional.  Names the source block so it can be called, like
-a function, from other source blocks or inline code to evaluate or
-to capture the results.  Code from other blocks, other files, and
-from table formulas (see @ref{The Spreadsheet}) can use the name to
-reference a source block.  This naming serves the same purpose as
-naming Org tables.  Org mode requires unique names.  For duplicate
-names, Org mode's behavior is undefined.
-
-@item @samp{#+BEGIN_SRC} @dots{} @samp{#+END_SRC}
-Mandatory.  They mark the start and end of a block that Org
-requires.  The @samp{#+BEGIN_SRC} line takes additional arguments, as
-described next.
-
-@item @samp{<language>}
-@cindex language, in code blocks
-Mandatory.  It is the identifier of the source code language in the
-block.  See @ref{Languages}, for identifiers of supported languages.
-
-@item @samp{<switches>}
-@cindex switches, in code blocks
-Optional.  Switches provide finer control of the code execution,
-export, and format (see the discussion of switches in @ref{Literal Examples}).
-
-@item @samp{<header arguments>}
-@cindex header arguments, in code blocks
-Optional.  Heading arguments control many aspects of evaluation,
-export and tangling of code blocks (see @ref{Using Header Arguments}).
-Using Org's properties feature, header arguments can be selectively
-applied to the entire buffer or specific sub-trees of the Org
-document.
-
-@item @samp{<body>}
-Source code in the dialect of the specified language identifier.
-@end table
-
-@node Using Header Arguments
-@section Using Header Arguments
-
-Org comes with many header arguments common to all languages.  New
-header arguments are added for specific languages as they become
-available for use in source code blocks.  A header argument is
-specified with an initial colon followed by the argument's name in
-lowercase.
-
-Since header arguments can be set in several ways, Org prioritizes
-them in case of overlaps or conflicts by giving local settings
-a higher priority.  Header values in function calls, for example,
-override header values from global defaults.
-
-@anchor{System-wide header arguments}
-@subheading System-wide header arguments
-
-@vindex org-babel-default-header-args
-
-@vindex org-babel-default-header-args
-System-wide values of header arguments can be specified by customizing
-the @code{org-babel-default-header-args} variable, which defaults to the
-following values:
-
-@example
-:session    => "none"
-:results    => "replace"
-:exports    => "code"
-:cache      => "no"
-:noweb      => "no"
-@end example
-
-The example below sets @samp{:noweb} header arguments to @samp{yes}, which 
makes
-Org expand @samp{:noweb} references by default.
-
-@lisp
-(setq org-babel-default-header-args
-      (cons '(:noweb . "yes")
-            (assq-delete-all :noweb org-babel-default-header-args)))
-@end lisp
-
-@cindex language specific default header arguments
-@cindex default header arguments per language
-Each language can have separate default header arguments by
-customizing the variable @code{org-babel-default-header-args:<LANG>}, where
-@var{<LANG>} is the name of the language.  For details, see the
-language-specific online documentation at
-@uref{https://orgmode.org/worg/org-contrib/babel/}.
-
-@anchor{Header arguments in Org mode properties}
-@subheading Header arguments in Org mode properties
-
-For header arguments applicable to the buffer, use @samp{PROPERTY} keyword
-anywhere in the Org file (see @ref{Property Syntax}).
-
-The following example makes all the R code blocks execute in the same
-session.  Setting @samp{:results} to @samp{silent} ignores the results of
-executions for all blocks, not just R code blocks; no results inserted
-for any block.
-
-@example
-#+PROPERTY: header-args:R  :session *R*
-#+PROPERTY: header-args    :results silent
-@end example
-
-@vindex org-use-property-inheritance
-Header arguments set through Org's property drawers (see @ref{Property 
Syntax}) apply at the sub-tree level on down.  Since these property
-drawers can appear anywhere in the file hierarchy, Org uses outermost
-call or source block to resolve the values.  Org ignores
-@code{org-use-property-inheritance} setting.
-
-In this example, @samp{:cache} defaults to @samp{yes} for all code blocks in 
the
-sub-tree.
-
-@example
-* sample header
-  :PROPERTIES:
-  :header-args:    :cache yes
-  :END:
-@end example
-
-@kindex C-c C-x p
-@findex org-set-property
-Properties defined through @code{org-set-property} function, bound to
-@kbd{C-c C-x p}, apply to all active languages.  They override
-properties set in @code{org-babel-default-header-args}.
-
-@cindex language specific header arguments properties
-@cindex header arguments per language
-Language-specific header arguments are also read from properties
-@samp{header-args:<LANG>} where @var{<LANG>} is the language
-identifier.  For example,
-
-@example
-* Heading
-  :PROPERTIES:
-  :header-args:clojure:    :session *clojure-1*
-  :header-args:R:          :session *R*
-  :END:
-** Subheading
-  :PROPERTIES:
-  :header-args:clojure:    :session *clojure-2*
-  :END:
-@end example
-
-@noindent
-would force separate sessions for Clojure blocks in @samp{Heading} and
-@samp{Subheading}, but use the same session for all R blocks.  Blocks in
-@samp{Subheading} inherit settings from @samp{Heading}.
-
-@anchor{Code block specific header arguments}
-@subheading Code block specific header arguments
-
-Header arguments are most commonly set at the source code block level,
-on the @samp{#+BEGIN_SRC} line.  Arguments set at this level take
-precedence over those set in the @code{org-babel-default-header-args}
-variable, and also those set as header properties.
-
-In the following example, setting @samp{:results} to @samp{silent} makes it
-ignore results of the code execution.  Setting @samp{:exports} to @samp{code}
-exports only the body of the code block to HTML or @LaTeX{}.
-
-@example
-#+NAME: factorial
-#+BEGIN_SRC haskell :results silent :exports code :var n=0
-  fac 0 = 1
-  fac n = n * fac (n-1)
-#+END_SRC
-@end example
-
-The same header arguments in an inline code block:
-
-@example
-src_haskell[:exports both]@{fac 5@}
-@end example
-
-
-@cindex @samp{HEADER}, keyword
-Code block header arguments can span multiple lines using @samp{#+HEADER:}
-on each line.  Note that Org currently accepts the plural spelling of
-@samp{#+HEADER:} only as a convenience for backward-compatibility.  It may
-be removed at some point.
-
-Multi-line header arguments on an unnamed code block:
-
-@example
-#+HEADER: :var data1=1
-#+BEGIN_SRC emacs-lisp :var data2=2
-   (message "data1:%S, data2:%S" data1 data2)
-#+END_SRC
-
-#+RESULTS:
-: data1:1, data2:2
-@end example
-
-Multi-line header arguments on a named code block:
-
-@example
-#+NAME: named-block
-#+HEADER: :var data=2
-#+BEGIN_SRC emacs-lisp
-  (message "data:%S" data)
-#+END_SRC
-
-#+RESULTS: named-block
-  : data:2
-@end example
-
-@anchor{Header arguments in function calls}
-@subheading Header arguments in function calls
-
-Header arguments in function calls are the most specific and override
-all other settings in case of an overlap.  They get the highest
-priority.  Two @samp{#+CALL:} examples are shown below.  For the complete
-syntax of @samp{CALL} keyword, see @ref{Evaluating Code Blocks}.
-
-In this example, @samp{:exports results} header argument is applied to the
-evaluation of the @samp{#+CALL:} line.
-
-@example
-#+CALL: factorial(n=5) :exports results
-@end example
-
-
-In this example, @samp{:session special} header argument is applied to the
-evaluation of @samp{factorial} code block.
-
-@example
-#+CALL: factorial[:session special](n=5)
-@end example
-
-@node Environment of a Code Block
-@section Environment of a Code Block
-
-
-
-@anchor{Passing arguments}
-@subheading Passing arguments
-
-@cindex passing arguments to code blocks
-@cindex arguments, in code blocks
-@cindex @samp{var}, header argument
-Use @samp{var} for passing arguments to source code blocks.  The specifics
-of variables in code blocks vary by the source language and are
-covered in the language-specific documentation.  The syntax for @samp{var},
-however, is the same for all languages.  This includes declaring
-a variable, and assigning a default value.
-
-The following syntax is used to pass arguments to code blocks using
-the @samp{var} header argument.
-
-@example
-:var NAME=ASSIGN
-@end example
-
-
-@noindent
-@var{NAME} is the name of the variable bound in the code block
-body.  @var{ASSIGN} is a literal value, such as a string,
-a number, a reference to a table, a list, a literal example, another
-code block---with or without arguments---or the results of evaluating
-a code block.
-
-Here are examples of passing values by reference:
-
-@table @asis
-@item table
-A table named with a @samp{NAME} keyword.
-
-@example
-#+NAME: example-table
-| 1 |
-| 2 |
-| 3 |
-| 4 |
-
-#+NAME: table-length
-#+BEGIN_SRC emacs-lisp :var table=example-table
-  (length table)
-#+END_SRC
-
-#+RESULTS: table-length
-: 4
-@end example
-
-When passing a table, you can treat specially the row, or the
-column, containing labels for the columns, or the rows, in the
-table.
-
-@cindex @samp{colnames}, header argument
-The @samp{colnames} header argument accepts @samp{yes}, @samp{no}, or 
@samp{nil} values.
-The default value is @samp{nil}: if an input table has column
-names---because the second row is a horizontal rule---then Org
-removes the column names, processes the table, puts back the column
-names, and then writes the table to the results block.  Using @samp{yes},
-Org does the same to the first row, even if the initial table does
-not contain any horizontal rule.  When set to @samp{no}, Org does not
-pre-process column names at all.
-
-@example
-#+NAME: less-cols
-| a |
-|---|
-| b |
-| c |
-
-#+BEGIN_SRC python :var tab=less-cols :colnames nil
-  return [[val + '*' for val in row] for row in tab]
-#+END_SRC
-
-#+RESULTS:
-| a  |
-|----|
-| b* |
-| c* |
-@end example
-
-@cindex @samp{rownames}, header argument
-Similarly, the @samp{rownames} header argument can take two values: @samp{yes}
-or @samp{no}.  When set to @samp{yes}, Org removes the first column, processes
-the table, puts back the first column, and then writes the table to
-the results block.  The default is @samp{no}, which means Org does not
-pre-process the first column.  Note that Emacs Lisp code blocks
-ignore @samp{rownames} header argument because of the ease of
-table-handling in Emacs.
-
-@example
-#+NAME: with-rownames
-| one | 1 | 2 | 3 | 4 |  5 |
-| two | 6 | 7 | 8 | 9 | 10 |
-
-#+BEGIN_SRC python :var tab=with-rownames :rownames yes
-  return [[val + 10 for val in row] for row in tab]
-#+END_SRC
-
-#+RESULTS:
-| one | 11 | 12 | 13 | 14 | 15 |
-| two | 16 | 17 | 18 | 19 | 20 |
-@end example
-
-@item list
-A simple named list.
-
-@example
-#+NAME: example-list
-- simple
-  - not
-  - nested
-- list
-
-#+BEGIN_SRC emacs-lisp :var x=example-list
-  (print x)
-#+END_SRC
-
-#+RESULTS:
-| simple | list |
-@end example
-
-Note that only the top level list items are passed along.  Nested
-list items are ignored.
-
-@item code block without arguments
-A code block name, as assigned by @samp{NAME} keyword from the example
-above, optionally followed by parentheses.
-
-@example
-#+BEGIN_SRC emacs-lisp :var length=table-length()
-  (* 2 length)
-#+END_SRC
-
-#+RESULTS:
-: 8
-@end example
-
-@item code block with arguments
-A code block name, as assigned by @samp{NAME} keyword, followed by
-parentheses and optional arguments passed within the parentheses.
-
-@example
-#+NAME: double
-#+BEGIN_SRC emacs-lisp :var input=8
-  (* 2 input)
-#+END_SRC
-
-#+RESULTS: double
-: 16
-
-#+NAME: squared
-#+BEGIN_SRC emacs-lisp :var input=double(input=1)
-  (* input input)
-#+END_SRC
-
-#+RESULTS: squared
-: 4
-@end example
-
-@item literal example
-A literal example block named with a @samp{NAME} keyword.
-
-@example
-#+NAME: literal-example
-#+BEGIN_EXAMPLE
-  A literal example
-  on two lines
-#+END_EXAMPLE
-
-#+NAME: read-literal-example
-#+BEGIN_SRC emacs-lisp :var x=literal-example
-  (concatenate #'string x " for you.")
-#+END_SRC
-
-#+RESULTS: read-literal-example
-: A literal example
-: on two lines for you.
-@end example
-@end table
-
-Indexing variable values enables referencing portions of a variable.
-Indexes are 0 based with negative values counting backwards from the
-end.  If an index is separated by commas then each subsequent section
-indexes as the next dimension.  Note that this indexing occurs
-@emph{before} other table-related header arguments are applied, such as
-@samp{hlines}, @samp{colnames} and @samp{rownames}.  The following example 
assigns
-the last cell of the first row the table @samp{example-table} to the
-variable @samp{data}:
-
-@example
-#+NAME: example-table
-| 1 | a |
-| 2 | b |
-| 3 | c |
-| 4 | d |
-
-#+BEGIN_SRC emacs-lisp :var data=example-table[0,-1]
-  data
-#+END_SRC
-
-#+RESULTS:
-: a
-@end example
-
-Two integers separated by a colon reference a range of variable
-values.  In that case the entire inclusive range is referenced.  For
-example the following assigns the middle three rows of @samp{example-table}
-to @samp{data}.
-
-@example
-#+NAME: example-table
-| 1 | a |
-| 2 | b |
-| 3 | c |
-| 4 | d |
-| 5 | 3 |
-
-#+BEGIN_SRC emacs-lisp :var data=example-table[1:3]
-  data
-#+END_SRC
-
-#+RESULTS:
-| 2 | b |
-| 3 | c |
-| 4 | d |
-@end example
-
-To pick the entire range, use an empty index, or the single character
-@samp{*}.  @samp{0:-1} does the same thing.  Example below shows how to
-reference the first column only.
-
-@example
-#+NAME: example-table
-| 1 | a |
-| 2 | b |
-| 3 | c |
-| 4 | d |
-
-#+BEGIN_SRC emacs-lisp :var data=example-table[,0]
-  data
-#+END_SRC
-
-#+RESULTS:
-| 1 | 2 | 3 | 4 |
-@end example
-
-Index referencing can be used for tables and code blocks.  Index
-referencing can handle any number of dimensions.  Commas delimit
-multiple dimensions, as shown below.
-
-@example
-#+NAME: 3D
-#+BEGIN_SRC emacs-lisp
-  '(((1  2  3)  (4  5  6)  (7  8  9))
-    ((10 11 12) (13 14 15) (16 17 18))
-    ((19 20 21) (22 23 24) (25 26 27)))
-#+END_SRC
-
-#+BEGIN_SRC emacs-lisp :var data=3D[1,,1]
-  data
-#+END_SRC
-
-#+RESULTS:
-| 11 | 14 | 17 |
-@end example
-
-Note that row names and column names are not removed prior to variable
-indexing.  You need to take them into account, even when @samp{colnames} or
-@samp{rownames} header arguments remove them.
-
-Emacs lisp code can also set the values for variables.  To
-differentiate a value from Lisp code, Org interprets any value
-starting with @samp{(}, @samp{[}, @samp{'} or @samp{`} as Emacs Lisp code.  
The result of
-evaluating that code is then assigned to the value of that variable.
-The following example shows how to reliably query and pass the file
-name of the Org mode buffer to a code block using headers.  We need
-reliability here because the file's name could change once the code in
-the block starts executing.
-
-@example
-#+BEGIN_SRC sh :var filename=(buffer-file-name) :exports both
-  wc -w $filename
-#+END_SRC
-@end example
-
-Note that values read from tables and lists are not mistakenly
-evaluated as Emacs Lisp code, as illustrated in the following example.
-
-@example
-#+NAME: table
-| (a b c) |
-
-#+HEADER: :var data=table[0,0]
-#+BEGIN_SRC perl
-  $data
-#+END_SRC
-
-#+RESULTS:
-: (a b c)
-@end example
-
-@anchor{Using sessions}
-@subheading Using sessions
-
-@cindex using sessions in code blocks
-@cindex @samp{session}, header argument
-Two code blocks can share the same environment.  The @samp{session} header
-argument is for running multiple source code blocks under one session.
-Org runs code blocks with the same session name in the same
-interpreter process.
-
-@table @asis
-@item @samp{none}
-Default.  Each code block gets a new interpreter process to execute.
-The process terminates once the block is evaluated.
-
-@item @var{STRING}
-Any string besides @samp{none} turns that string into the name of that
-session.  For example, @samp{:session STRING} names it @samp{STRING}.  If
-@samp{session} has no value, then the session name is derived from the
-source language identifier.  Subsequent blocks with the same source
-code language use the same session.  Depending on the language,
-state variables, code from other blocks, and the overall interpreted
-environment may be shared.  Some interpreted languages support
-concurrent sessions when subsequent source code language blocks
-change session names.
-@end table
-
-Only languages that provide interactive evaluation can have session
-support.  Not all languages provide this support, such as C and ditaa.
-Even languages, such as Python and Haskell, that do support
-interactive evaluation impose limitations on allowable language
-constructs that can run interactively.  Org inherits those limitations
-for those code blocks running in a session.
-
-@anchor{Choosing a working directory}
-@subheading Choosing a working directory
-
-@cindex working directory, in a code block
-@cindex @samp{dir}, header argument
-@cindex @samp{mkdirp}, header argument
-The @samp{dir} header argument specifies the default directory during code
-block execution.  If it is absent, then the directory associated with
-the current buffer is used.  In other words, supplying @samp{:dir
-DIRECTORY} temporarily has the same effect as changing the current
-directory with @kbd{M-x cd @key{RET} DIRECTORY}, and then not setting
-@samp{dir}.  Under the surface, @samp{dir} simply sets the value of the Emacs
-variable @code{default-directory}.  Setting @samp{mkdirp} header argument to
-a non-@code{nil} value creates the directory, if necessary.
-
-For example, to save the plot file in the @samp{Work/} folder of the home
-directory---notice tilde is expanded:
-
-@example
-#+BEGIN_SRC R :file myplot.png :dir ~/Work
-  matplot(matrix(rnorm(100), 10), type="l")
-#+END_SRC
-@end example
-
-To evaluate the code block on a remote machine, supply a remote
-directory name using Tramp syntax.  For example:
-
-@example
-#+BEGIN_SRC R :file plot.png :dir /scp:dand@@yakuba.princeton.edu:
-  plot(1:10, main=system("hostname", intern=TRUE))
-#+END_SRC
-@end example
-
-Org first captures the text results as usual for insertion in the Org
-file.  Then Org also inserts a link to the remote file, thanks to
-Emacs Tramp.  Org constructs the remote path to the file name from
-@samp{dir} and @code{default-directory}, as illustrated here:
-
-@example
-[[file:/scp:dand@@yakuba.princeton.edu:/home/dand/plot.png][plot.png]]
-@end example
-
-
-When @samp{dir} is used with @samp{session}, Org sets the starting directory 
for
-a new session.  But Org does not alter the directory of an already
-existing session.
-
-Do not use @samp{dir} with @samp{:exports results} or with @samp{:exports 
both} to
-avoid Org inserting incorrect links to remote files.  That is because
-Org does not expand @code{default directory} to avoid some underlying
-portability issues.
-
-@anchor{Inserting headers and footers}
-@subheading Inserting headers and footers
-
-@cindex headers, in code blocks
-@cindex footers, in code blocks
-@cindex @samp{prologue}, header argument
-The @samp{prologue} header argument is for appending to the top of the code
-block for execution, like a reset instruction.  For example, you may
-use @samp{:prologue "reset"} in a Gnuplot code block or, for every such
-block:
-
-@lisp
-(add-to-list 'org-babel-default-header-args:gnuplot
-             '((:prologue . "reset")))
-
-@end lisp
-
-@cindex @samp{epilogue}, header argument
-Likewise, the value of the @samp{epilogue} header argument is for appending
-to the end of the code block for execution.
-
-@node Evaluating Code Blocks
-@section Evaluating Code Blocks
-
-@cindex code block, evaluating
-@cindex source code, evaluating
-@cindex @samp{RESULTS}, keyword
-
-A note about security: With code evaluation comes the risk of harm.
-Org safeguards by prompting for user's permission before executing any
-code in the source block.  To customize this safeguard, or disable it,
-see @ref{Code Evaluation Security}.
-
-@anchor{How to evaluate source code}
-@subheading How to evaluate source code
-
-Org captures the results of the code block evaluation and inserts them
-in the Org file, right after the code block.  The insertion point is
-after a newline and the @samp{RESULTS} keyword.  Org creates the @samp{RESULTS}
-keyword if one is not already there.
-
-By default, Org enables only Emacs Lisp code blocks for execution.
-See @ref{Languages} to enable other languages.
-
-@kindex C-c C-c
-@kindex C-c C-v e
-@findex org-babel-execute-src-block
-Org provides many ways to execute code blocks.  @kbd{C-c C-c} or
-@kbd{C-c C-v e} with the point on a code block@footnote{The option 
@code{org-babel-no-eval-on-ctrl-c-ctrl-c} can be used
-to remove code evaluation from the @kbd{C-c C-c} key binding.} calls the
-@code{org-babel-execute-src-block} function, which executes the code in the
-block, collects the results, and inserts them in the buffer.
-
-@cindex @samp{CALL}, keyword
-@vindex org-babel-inline-result-wrap
-By calling a named code block@footnote{Actually, the constructs 
@samp{call_<name>()} and @samp{src_<lang>@{@}}
-are not evaluated when they appear in a keyword (see @ref{In-buffer 
Settings}).} from an Org mode buffer or
-a table.  Org can call the named code blocks from the current Org mode
-buffer or from the ``Library of Babel'' (see @ref{Library of Babel}).
-
-The syntax for @samp{CALL} keyword is:
-
-@example
-#+CALL: <name>(<arguments>)
-#+CALL: <name>[<inside header arguments>](<arguments>) <end header arguments>
-@end example
-
-The syntax for inline named code blocks is:
-
-@example
-... call_<name>(<arguments>) ...
-... call_<name>[<inside header arguments>](<arguments>)[<end header 
arguments>] ...
-@end example
-
-When inline syntax is used, the result is wrapped based on the
-variable @code{org-babel-inline-result-wrap}, which by default is set to
-@code{"=%s="} to produce verbatim text suitable for markup.
-
-@table @asis
-@item @samp{<name>}
-This is the name of the code block (see @ref{Structure of Code Blocks})
-to be evaluated in the current document.  If the block is located in
-another file, start @samp{<name>} with the file name followed by
-a colon.  For example, in order to execute a block named @samp{clear-data}
-in @samp{file.org}, you can write the following:
-
-@example
-#+CALL: file.org:clear-data()
-@end example
-
-@item @samp{<arguments>}
-Org passes arguments to the code block using standard function call
-syntax.  For example, a @samp{#+CALL:} line that passes @samp{4} to a code
-block named @samp{double}, which declares the header argument @samp{:var n=2},
-would be written as:
-
-@example
-#+CALL: double(n=4)
-@end example
-
-
-@noindent
-Note how this function call syntax is different from the header
-argument syntax.
-
-@item @samp{<inside header arguments>}
-Org passes inside header arguments to the named code block using the
-header argument syntax.  Inside header arguments apply to code block
-evaluation.  For example, @samp{[:results output]} collects results
-printed to stdout during code execution of that block.  Note how
-this header argument syntax is different from the function call
-syntax.
-
-@item @samp{<end header arguments>}
-End header arguments affect the results returned by the code block.
-For example, @samp{:results html} wraps the results in a @samp{#+BEGIN_EXPORT
-  html} block before inserting the results in the Org buffer.
-@end table
-
-@anchor{Limit code block evaluation}
-@subheading Limit code block evaluation
-
-@cindex @samp{eval}, header argument
-@cindex control code block evaluation
-The @samp{eval} header argument can limit evaluation of specific code
-blocks and @samp{CALL} keyword.  It is useful for protection against
-evaluating untrusted code blocks by prompting for a confirmation.
-
-@table @asis
-@item @samp{never} or @samp{no}
-Org never evaluates the source code.
-
-@item @samp{query}
-Org prompts the user for permission to evaluate the source code.
-
-@item @samp{never-export} or @samp{no-export}
-Org does not evaluate the source code when exporting, yet the user
-can evaluate it interactively.
-
-@item @samp{query-export}
-Org prompts the user for permission to evaluate the source code
-during export.
-@end table
-
-If @samp{eval} header argument is not set, then Org determines whether to
-evaluate the source code from the @code{org-confirm-babel-evaluate}
-variable (see @ref{Code Evaluation Security}).
-
-@anchor{Cache results of evaluation}
-@subheading Cache results of evaluation
-
-@cindex @samp{cache}, header argument
-@cindex cache results of code evaluation
-The @samp{cache} header argument is for caching results of evaluating code
-blocks.  Caching results can avoid re-evaluating a code block that
-have not changed since the previous run.  To benefit from the cache
-and avoid redundant evaluations, the source block must have a result
-already present in the buffer, and neither the header
-arguments---including the value of @samp{var} references---nor the text of
-the block itself has changed since the result was last computed.  This
-feature greatly helps avoid long-running calculations.  For some edge
-cases, however, the cached results may not be reliable.
-
-The caching feature is best for when code blocks are pure functions,
-that is functions that return the same value for the same input
-arguments (see @ref{Environment of a Code Block}), and that do not have
-side effects, and do not rely on external variables other than the
-input arguments.  Functions that depend on a timer, file system
-objects, and random number generators are clearly unsuitable for
-caching.
-
-A note of warning: when @samp{cache} is used in a session, caching may
-cause unexpected results.
-
-When the caching mechanism tests for any source code changes, it does
-not expand noweb style references (see @ref{Noweb Reference Syntax}).
-
-The @samp{cache} header argument can have one of two values: @samp{yes} or 
@samp{no}.
-
-@table @asis
-@item @samp{no}
-Default.  No caching of results; code block evaluated every time.
-
-@item @samp{yes}
-Whether to run the code or return the cached results is determined
-by comparing the SHA1 hash value of the combined code block and
-arguments passed to it.  This hash value is packed on the
-@samp{#+RESULTS:} line from previous evaluation.  When hash values match,
-Org does not evaluate the code block.  When hash values mismatch,
-Org evaluates the code block, inserts the results, recalculates the
-hash value, and updates @samp{#+RESULTS:} line.
-@end table
-
-In this example, both functions are cached.  But @samp{caller} runs only if
-the result from @samp{random} has changed since the last run.
-
-@example
-#+NAME: random
-#+BEGIN_SRC R :cache yes
-  runif(1)
-#+END_SRC
-
-#+RESULTS[a2a72cd647ad44515fab62e144796432793d68e1]: random
-0.4659510825295
-
-#+NAME: caller
-#+BEGIN_SRC emacs-lisp :var x=random :cache yes
-  x
-#+END_SRC
-
-#+RESULTS[bec9c8724e397d5df3b696502df3ed7892fc4f5f]: caller
-0.254227238707244
-@end example
-
-@node Results of Evaluation
-@section Results of Evaluation
-
-@cindex code block, results of evaluation
-@cindex source code, results of evaluation
-
-@cindex @samp{results}, header argument
-How Org handles results of a code block execution depends on many
-header arguments working together.  The primary determinant, however,
-is the @samp{results} header argument.  It accepts four classes of options.
-Each code block can take only one option per class:
-
-@table @asis
-@item Collection
-For how the results should be collected from the code block;
-
-@item Type
-For which type of result the code block will return; affects how Org
-processes and inserts results in the Org buffer;
-
-@item Format
-For the result; affects how Org processes results;
-
-@item Handling
-For inserting results once they are properly formatted.
-@end table
-
-@anchor{Collection}
-@subheading Collection
-
-Collection options specify the results.  Choose one of the options;
-they are mutually exclusive.
-
-@table @asis
-@item @samp{value}
-Default for most Babel libraries@footnote{Actually, the constructs 
@samp{call_<name>()} and @samp{src_<lang>@{@}}
-are not evaluated when they appear in a keyword (see @ref{In-buffer 
Settings}).}.  Functional mode.  Org
-gets the value by wrapping the code in a function definition in the
-language of the source block.  That is why when using @samp{:results
-  value}, code should execute like a function and return a value.  For
-languages like Python, an explicit @code{return} statement is mandatory
-when using @samp{:results value}.  Result is the value returned by the
-last statement in the code block.
-
-When evaluating the code block in a session (see @ref{Environment of a Code 
Block}), Org passes the code to an interpreter running as an
-interactive Emacs inferior process.  Org gets the value from the
-source code interpreter's last statement output.  Org has to use
-language-specific methods to obtain the value.  For example, from
-the variable @code{_} in Ruby, and the value of @code{.Last.value} in R@.
-
-@item @samp{output}
-Scripting mode.  Org passes the code to an external process running
-the interpreter.  Org returns the contents of the standard output
-stream as text results.
-
-When using a session, Org passes the code to the interpreter running
-as an interactive Emacs inferior process.  Org concatenates any text
-output from the interpreter and returns the collection as a result.
-@end table
-
-@anchor{Type}
-@subheading Type
-
-Type tells what result types to expect from the execution of the code
-block.  Choose one of the options; they are mutually exclusive.  The
-default behavior is to automatically determine the result type.
-
-@table @asis
-@item @samp{table}
-@itemx @samp{vector}
-Interpret the results as an Org table.  If the result is a single
-value, create a table with one row and one column.  Usage example:
-@samp{:results value table}.
-
-@cindex @samp{hlines}, header argument
-In-between each table row or below the table headings, sometimes
-results have horizontal lines, which are also known as ``hlines''.
-The @samp{hlines} argument with the default @samp{no} value strips such lines
-from the input table.  For most code, this is desirable, or else
-those @samp{hline} symbols raise unbound variable errors.  A @samp{yes}
-accepts such lines, as demonstrated in the following example.
-
-@example
-#+NAME: many-cols
-| a | b | c |
-|---+---+---|
-| d | e | f |
-|---+---+---|
-| g | h | i |
-
-#+NAME: no-hline
-#+BEGIN_SRC python :var tab=many-cols :hlines no
-  return tab
-#+END_SRC
-
-#+RESULTS: no-hline
-| a | b | c |
-| d | e | f |
-| g | h | i |
-
-#+NAME: hlines
-#+BEGIN_SRC python :var tab=many-cols :hlines yes
-  return tab
-#+END_SRC
-
-#+RESULTS: hlines
-| a | b | c |
-|---+---+---|
-| d | e | f |
-|---+---+---|
-| g | h | i |
-@end example
-
-@item @samp{list}
-Interpret the results as an Org list.  If the result is a single
-value, create a list of one element.
-
-@item @samp{scalar}
-@itemx @samp{verbatim}
-Interpret literally and insert as quoted text.  Do not create
-a table.  Usage example: @samp{:results value verbatim}.
-
-@item @samp{file}
-Interpret as a filename.  Save the results of execution of the code
-block to that file, then insert a link to it.  You can control both
-the filename and the description associated to the link.
-
-@cindex @samp{file}, header argument
-@cindex @samp{output-dir}, header argument
-Org first tries to generate the filename from the value of the
-@samp{file} header argument and the directory specified using the
-@samp{output-dir} header arguments.  If @samp{output-dir} is not specified,
-Org assumes it is the current directory.
-
-@example
-#+BEGIN_SRC asymptote :results value file :file circle.pdf :output-dir img/
-  size(2cm);
-  draw(unitcircle);
-#+END_SRC
-@end example
-
-@cindex @samp{file-ext}, header argument
-If @samp{file} header argument is missing, Org generates the base name of
-the output file from the name of the code block, and its extension
-from the @samp{file-ext} header argument.  In that case, both the name
-and the extension are mandatory.
-
-@example
-#+name: circle
-#+BEGIN_SRC asymptote :results value file :file-ext pdf
-  size(2cm);
-  draw(unitcircle);
-#+END_SRC
-@end example
-
-@cindex @samp{file-desc}, header argument
-The @samp{file-desc} header argument defines the description (see
-@ref{Link Format}) for the link.  If @samp{file-desc} is present but has no 
value,
-the @samp{file} value is used as the link description.  When this
-argument is not present, the description is omitted.
-
-@cindex @samp{sep}, header argument
-By default, Org assumes that a table written to a file has
-TAB-delimited output.  You can choose a different separator with
-the @samp{sep} header argument.
-
-@cindex @samp{file-mode}, header argument
-The @samp{file-mode} header argument defines the file permissions.  To
-make it executable, use @samp{:file-mode (identity #o755)}.
-
-@example
-#+BEGIN_SRC shell :results file :file script.sh :file-mode (identity #o755)
-  echo "#!/bin/bash"
-  echo "echo Hello World"
-#+END_SRC
-@end example
-@end table
-
-@anchor{Format}
-@subheading Format
-
-Format pertains to the type of the result returned by the code block.
-Choose one of the options; they are mutually exclusive.  The default
-follows from the type specified above.
-
-@table @asis
-@item @samp{code}
-Result enclosed in a code block.  Useful for parsing.  Usage
-example: @samp{:results value code}.
-
-@item @samp{drawer}
-Result wrapped in a @samp{RESULTS} drawer.  Useful for containing @samp{raw}
-or @samp{org} results for later scripting and automated processing.
-Usage example: @samp{:results value drawer}.
-
-@item @samp{html}
-Results enclosed in a @samp{BEGIN_EXPORT html} block.  Usage example:
-@samp{:results value html}.
-
-@item @samp{latex}
-Results enclosed in a @samp{BEGIN_EXPORT latex} block.  Usage example:
-@samp{:results value latex}.
-
-@item @samp{link}
-@itemx @samp{graphics}
-When used along with @samp{file} type, the result is a link to the file
-specified in @samp{:file} header argument.  However, unlike plain @samp{file}
-type, nothing is written to the disk.  The block is used for its
-side-effects only, as in the following example:
-
-@example
-#+begin_src shell :results file link :file "download.tar.gz"
-wget -c "http://example.com/download.tar.gz";
-#+end_src
-@end example
-
-@item @samp{org}
-Results enclosed in a @samp{BEGIN_SRC org} block.  For comma-escape,
-either @kbd{@key{TAB}} in the block, or export the file.  Usage
-example: @samp{:results value org}.
-
-@item @samp{pp}
-Result converted to pretty-print source code.  Enclosed in a code
-block.  Languages supported: Emacs Lisp, Python, and Ruby.  Usage
-example: @samp{:results value pp}.
-
-@item @samp{raw}
-Interpreted as raw Org mode.  Inserted directly into the buffer.
-Aligned if it is a table.  Usage example: @samp{:results value raw}.
-@end table
-
-@cindex @samp{wrap}, header argument
-The @samp{wrap} header argument unconditionally marks the results block by
-appending strings to @samp{#+BEGIN_} and @samp{#+END_}.  If no string is
-specified, Org wraps the results in a @samp{#+BEGIN_results}
-@dots{} @samp{#+END_results} block.  It takes precedent over the @samp{results}
-value listed above.  E.g.,
-
-@example
-#+BEGIN_SRC emacs-lisp :results html :wrap EXPORT markdown
-"<blink>Welcome back to the 90's</blink>"
-#+END_SRC
-
-#+RESULTS:
-#+BEGIN_EXPORT markdown
-<blink>Welcome back to the 90's</blink>
-#+END_EXPORT
-@end example
-
-@anchor{Handling}
-@subheading Handling
-
-Handling options after collecting the results.
-
-@table @asis
-@item @samp{silent}
-Do not insert results in the Org mode buffer, but echo them in the
-minibuffer.  Usage example: @samp{:results output silent}.
-
-@item @samp{replace}
-Default.  Insert results in the Org buffer.  Remove previous
-results.  Usage example: @samp{:results output replace}.
-
-@item @samp{append}
-Append results to the Org buffer.  Latest results are at the bottom.
-Does not remove previous results.  Usage example: @samp{:results output
-  append}.
-
-@item @samp{prepend}
-Prepend results to the Org buffer.  Latest results are at the top.
-Does not remove previous results.  Usage example: @samp{:results output
-  prepend}.
-@end table
-
-@anchor{Post-processing}
-@subheading Post-processing
-
-@cindex @samp{post}, header argument
-@cindex @samp{*this*}, in @samp{post} header argument
-The @samp{post} header argument is for post-processing results from block
-evaluation.  When @samp{post} has any value, Org binds the results to
-@code{*this*} variable for easy passing to @samp{var} header argument
-specifications (see @ref{Environment of a Code Block}).  That makes results
-available to other code blocks, or even for direct Emacs Lisp code
-execution.
-
-The following two examples illustrate @samp{post} header argument in
-action.  The first one shows how to attach an @samp{ATTR_LATEX} keyword
-using @samp{post}.
-
-@example
-#+NAME: attr_wrap
-#+BEGIN_SRC sh :var data="" :var width="\\textwidth" :results output
-  echo "#+ATTR_LATEX: :width $width"
-  echo "$data"
-#+END_SRC
-
-#+HEADER: :file /tmp/it.png
-#+BEGIN_SRC dot :post attr_wrap(width="5cm", data=*this*) :results drawer
-  digraph@{
-          a -> b;
-          b -> c;
-          c -> a;
-  @}
-#+end_src
-
-#+RESULTS:
-:RESULTS:
-#+ATTR_LATEX :width 5cm
-[[file:/tmp/it.png]]
-:END:
-@end example
-
-The second example shows use of @samp{colnames} header argument in @samp{post}
-to pass data between code blocks.
-
-@example
-#+NAME: round-tbl
-#+BEGIN_SRC emacs-lisp :var tbl="" fmt="%.3f"
-  (mapcar (lambda (row)
-            (mapcar (lambda (cell)
-                      (if (numberp cell)
-                          (format fmt cell)
-                        cell))
-                    row))
-          tbl)
-#+end_src
-
-#+BEGIN_SRC R :colnames yes :post round-tbl[:colnames yes](*this*)
-  set.seed(42)
-  data.frame(foo=rnorm(1))
-#+END_SRC
-
-#+RESULTS:
-|   foo |
-|-------|
-| 1.371 |
-@end example
-
-@node Exporting Code Blocks
-@section Exporting Code Blocks
-
-@cindex code block, exporting
-@cindex source code, exporting
-
-It is possible to export the @emph{code} of code blocks, the @emph{results} of
-code block evaluation, @emph{both} the code and the results of code block
-evaluation, or @emph{none}.  Org defaults to exporting @emph{code} for most
-languages.  For some languages, such as ditaa, Org defaults to
-@emph{results}.  To export just the body of code blocks, see @ref{Literal 
Examples}.  To selectively export sub-trees of an Org document, see
-@ref{Exporting}.
-
-@cindex @samp{exports}, header argument
-The @samp{exports} header argument is to specify if that part of the Org
-file is exported to, say, HTML or @LaTeX{} formats.
-
-@table @asis
-@item @samp{code}
-The default.  The body of code is included into the exported file.
-Example: @samp{:exports code}.
-
-@item @samp{results}
-The results of evaluation of the code is included in the exported
-file.  Example: @samp{:exports results}.
-
-@item @samp{both}
-Both the code and results of evaluation are included in the exported
-file.  Example: @samp{:exports both}.
-
-@item @samp{none}
-Neither the code nor the results of evaluation is included in the
-exported file.  Whether the code is evaluated at all depends on
-other options.  Example: @samp{:exports none}.
-@end table
-
-@vindex org-export-use-babel
-To stop Org from evaluating code blocks to speed exports, use the
-header argument @samp{:eval never-export} (see @ref{Evaluating Code Blocks}).
-To stop Org from evaluating code blocks for greater security, set the
-@code{org-export-use-babel} variable to @code{nil}, but understand that header
-arguments will have no effect.
-
-Turning off evaluation comes in handy when batch processing.  For
-example, markup languages for wikis, which have a high risk of
-untrusted code.  Stopping code block evaluation also stops evaluation
-of all header arguments of the code block.  This may not be desirable
-in some circumstances.  So during export, to allow evaluation of just
-the header arguments but not any code evaluation in the source block,
-set @samp{:eval never-export} (see @ref{Evaluating Code Blocks}).
-
-Org never evaluates code blocks in commented sub-trees when exporting
-(see @ref{Comment Lines}).  On the other hand, Org does evaluate code
-blocks in sub-trees excluded from export (see @ref{Export Settings}).
-
-@node Extracting Source Code
-@section Extracting Source Code
-
-@cindex tangling
-@cindex source code, extracting
-@cindex code block, extracting source code
-
-Extracting source code from code blocks is a basic task in literate
-programming.  Org has features to make this easy.  In literate
-programming parlance, documents on creation are @emph{woven} with code and
-documentation, and on export, the code is tangled for execution by
-a computer.  Org facilitates weaving and tangling for producing,
-maintaining, sharing, and exporting literate programming documents.
-Org provides extensive customization options for extracting source
-code.
-
-When Org tangles code blocks, it expands, merges, and transforms them.
-Then Org recomposes them into one or more separate files, as
-configured through the options.  During this tangling process, Org
-expands variables in the source code, and resolves any noweb style
-references (see @ref{Noweb Reference Syntax}).
-
-@anchor{Header arguments}
-@subheading Header arguments
-
-@cindex @samp{tangle}, header argument
-The @samp{tangle} header argument specifies if the code block is exported
-to source file(s).
-
-@table @asis
-@item @samp{yes}
-Export the code block to source file.  The file name for the source
-file is derived from the name of the Org file, and the file
-extension is derived from the source code language identifier.
-Example: @samp{:tangle yes}.
-
-@item @samp{no}
-The default.  Do not extract the code in a source code file.
-Example: @samp{:tangle no}.
-
-@item @var{FILENAME}
-Export the code block to source file whose file name is derived from
-any string passed to the @samp{tangle} header argument.  Org derives the
-file name as being relative to the directory of the Org file's
-location.  Example: @samp{:tangle FILENAME}.
-@end table
-
-@cindex @samp{mkdirp}, header argument
-The @samp{mkdirp} header argument creates parent directories for tangled
-files if the directory does not exist.  A @samp{yes} value enables
-directory creation whereas @samp{no} inhibits it.
-
-@cindex @samp{comments}, header argument
-The @samp{comments} header argument controls inserting comments into
-tangled files.  These are above and beyond whatever comments may
-already exist in the code block.
-
-@table @asis
-@item @samp{no}
-The default.  Do not insert any extra comments during tangling.
-
-@item @samp{link}
-Wrap the code block in comments.  Include links pointing back to the
-place in the Org file from where the code was tangled.
-
-@item @samp{yes}
-Kept for backward compatibility; same as @samp{link}.
-
-@item @samp{org}
-Nearest headline text from Org file is inserted as comment.  The
-exact text that is inserted is picked from the leading context of
-the source block.
-
-@item @samp{both}
-Includes both @samp{link} and @samp{org} options.
-
-@item @samp{noweb}
-Includes @samp{link} option, expands noweb references (see @ref{Noweb 
Reference Syntax}), and wraps them in link comments inside the body
-of the code block.
-@end table
-
-@cindex @samp{padline}, header argument
-The @samp{padline} header argument controls insertion of newlines to pad
-source code in the tangled file.
-
-@table @asis
-@item @samp{yes}
-Default.  Insert a newline before and after each code block in the
-tangled file.
-
-@item @samp{no}
-Do not insert newlines to pad the tangled code blocks.
-@end table
-
-@cindex @samp{shebang}, header argument
-The @samp{shebang} header argument can turn results into executable script
-files.  By setting it to a string value---for example, @samp{:shebang
-"#!/bin/bash"}---Org inserts that string as the first line of the
-tangled file that the code block is extracted to.  Org then turns on
-the tangled file's executable permission.
-
-@cindex @samp{tangle-mode}, header argument
-The @samp{tangle-mode} header argument specifies what permissions to set
-for tangled files by @code{set-file-modes}.  For example, to make
-a read-only tangled file, use @samp{:tangle-mode (identity #o444)}.  To
-make it executable, use @samp{:tangle-mode (identity #o755)}.  It also
-overrides executable permission granted by @samp{shebang}.  When multiple
-source code blocks tangle to a single file with different and
-conflicting @samp{tangle-mode} header arguments, Org's behavior is
-undefined.
-
-@cindex @samp{no-expand}, header argument
-By default Org expands code blocks during tangling.  The @samp{no-expand}
-header argument turns off such expansions.  Note that one side-effect
-of expansion by @code{org-babel-expand-src-block} also assigns values (see
-@ref{Environment of a Code Block}) to variables.  Expansions also replace
-noweb references with their targets (see @ref{Noweb Reference Syntax}).
-Some of these expansions may cause premature assignment, hence this
-option.  This option makes a difference only for tangling.  It has no
-effect when exporting since code blocks for execution have to be
-expanded anyway.
-
-@anchor{Functions}
-@subheading Functions
-
-@table @asis
-@item @code{org-babel-tangle}
-@findex org-babel-tangle
-@kindex C-c C-v t
-Tangle the current file.  Bound to @kbd{C-c C-v t}.
-
-With prefix argument only tangle the current code block.
-
-@item @code{org-babel-tangle-file}
-@findex org-babel-tangle-file
-@kindex C-c C-v f
-Choose a file to tangle.  Bound to @kbd{C-c C-v f}.
-@end table
-
-@anchor{Hooks (1)}
-@subheading Hooks
-
-@table @asis
-@item @code{org-babel-post-tangle-hook}
-@vindex org-babel-post-tangle-hook
-This hook is run from within code files tangled by
-@code{org-babel-tangle}, making it suitable for post-processing,
-compilation, and evaluation of code in the tangled files.
-@end table
-
-@anchor{Jumping between code and Org}
-@subheading Jumping between code and Org
-
-@findex org-babel-tangle-jump-to-org
-Debuggers normally link errors and messages back to the source code.
-But for tangled files, we want to link back to the Org file, not to
-the tangled source file.  To make this extra jump, Org uses
-@code{org-babel-tangle-jump-to-org} function with two additional source
-code block header arguments:
-
-@enumerate
-@item
-Set @samp{padline} to true---this is the default setting.
-@item
-Set @samp{comments} to @samp{link}, which makes Org insert links to the Org
-file.
-@end enumerate
-
-@node Languages
-@section Languages
-
-@cindex babel, languages
-@cindex source code, languages
-@cindex code block, languages
-
-Code blocks in the following languages are supported.
-
-@multitable @columnfractions 0.25 0.25 0.25 0.20
-@headitem Language
-@tab Identifier
-@tab Language
-@tab Identifier
-@item Asymptote
-@tab @samp{asymptote}
-@tab Lisp
-@tab @samp{lisp}
-@item Awk
-@tab @samp{awk}
-@tab Lua
-@tab @samp{lua}
-@item C
-@tab @samp{C}
-@tab MATLAB
-@tab @samp{matlab}
-@item C++
-@tab @samp{C++}@footnote{C++ language is handled in @samp{ob-C.el}.  Even 
though the
-identifier for such source blocks is @samp{C++}, you activate it by loading
-the C language.}
-@tab Mscgen
-@tab @samp{mscgen}
-@item Clojure
-@tab @samp{clojure}
-@tab Objective Caml
-@tab @samp{ocaml}
-@item CSS
-@tab @samp{css}
-@tab Octave
-@tab @samp{octave}
-@item D
-@tab @samp{D}@footnote{D language is handled in @samp{ob-C.el}.  Even though 
the
-identifier for such source blocks is @samp{D}, you activate it by loading
-the C language.}
-@tab Org mode
-@tab @samp{org}
-@item ditaa
-@tab @samp{ditaa}
-@tab Oz
-@tab @samp{oz}
-@item Emacs Calc
-@tab @samp{calc}
-@tab Perl
-@tab @samp{perl}
-@item Emacs Lisp
-@tab @samp{emacs-lisp}
-@tab Plantuml
-@tab @samp{plantuml}
-@item Eshell
-@tab @samp{eshell}
-@tab Processing.js
-@tab @samp{processing}
-@item Fortran
-@tab @samp{fortran}
-@tab Python
-@tab @samp{python}
-@item Gnuplot
-@tab @samp{gnuplot}
-@tab R
-@tab @samp{R}
-@item GNU Screen
-@tab @samp{screen}
-@tab Ruby
-@tab @samp{ruby}
-@item Graphviz
-@tab @samp{dot}
-@tab Sass
-@tab @samp{sass}
-@item Haskell
-@tab @samp{haskell}
-@tab Scheme
-@tab @samp{scheme}
-@item Java
-@tab @samp{java}
-@tab Sed
-@tab @samp{sed}
-@item Javascript
-@tab @samp{js}
-@tab shell
-@tab @samp{sh}
-@item @LaTeX{}
-@tab @samp{latex}
-@tab SQL
-@tab @samp{sql}
-@item Ledger
-@tab @samp{ledger}
-@tab SQLite
-@tab @samp{sqlite}
-@item Lilypond
-@tab @samp{lilypond}
-@tab Vala
-@tab @samp{vala}
-@end multitable
-
-Additional documentation for some languages is at
-@uref{https://orgmode.org/worg/org-contrib/babel/languages.html}.
-
-@vindex org-babel-load-languages
-By default, only Emacs Lisp is enabled for evaluation.  To enable or
-disable other languages, customize the @code{org-babel-load-languages}
-variable either through the Emacs customization interface, or by
-adding code to the init file as shown next.
-
-In this example, evaluation is disabled for Emacs Lisp, and enabled
-for R@.
-
-@lisp
-(org-babel-do-load-languages
- 'org-babel-load-languages
- '((emacs-lisp . nil)
-   (R . t)))
-@end lisp
-
-Note that this is not the only way to enable a language.  Org also
-enables languages when loaded with @code{require} statement.  For example,
-the following enables execution of Clojure code blocks:
-
-@lisp
-(require 'ob-clojure)
-@end lisp
-
-@node Editing Source Code
-@section Editing Source Code
-
-@cindex code block, editing
-@cindex source code, editing
-
-@kindex C-c '
-Use @kbd{C-c '} to edit the current code block.  It opens a new
-major mode edit buffer containing the body of the source code block,
-ready for any edits.  Use @kbd{C-c '} again to close the buffer
-and return to the Org buffer.
-
-@kindex C-x C-s
-@vindex org-edit-src-auto-save-idle-delay
-@cindex auto-save, in code block editing
-@kbd{C-x C-s} saves the buffer and updates the contents of the
-Org buffer.  Set @code{org-edit-src-auto-save-idle-delay} to save the base
-buffer after a certain idle delay time.  Set
-@code{org-edit-src-turn-on-auto-save} to auto-save this buffer into
-a separate file using Auto-save mode.
-
-While editing the source code in the major mode, the Org Src minor
-mode remains active.  It provides these customization variables as
-described below.  For even more variables, look in the customization
-group @code{org-edit-structure}.
-
-@table @asis
-@item @code{org-src-lang-modes}
-@vindex org-src-lang-modes
-If an Emacs major-mode named @code{<LANG>-mode} exists, where
-@var{<LANG>} is the language identifier from code block's
-header line, then the edit buffer uses that major mode.  Use this
-variable to arbitrarily map language identifiers to major modes.
-
-@item @code{org-src-window-setup}
-@vindex org-src-window-setup
-For specifying Emacs window arrangement when the new edit buffer is
-created.
-
-@item @code{org-src-preserve-indentation}
-@cindex indentation, in code blocks
-@vindex org-src-preserve-indentation
-Default is @code{nil}.  Source code is indented.  This indentation
-applies during export or tangling, and depending on the context, may
-alter leading spaces and tabs.  When non-@code{nil}, source code is
-aligned with the leftmost column.  No lines are modified during
-export or tangling, which is very useful for white-space sensitive
-languages, such as Python.
-
-@item @code{org-src-ask-before-returning-to-edit-buffer}
-@vindex org-src-ask-before-returning-to-edit-buffer
-When @code{nil}, Org returns to the edit buffer without further prompts.
-The default prompts for a confirmation.
-@end table
-
-@vindex org-src-fontify-natively
-@vindex org-src-block-faces
-Set @code{org-src-fontify-natively} to non-@code{nil} to turn on native code
-fontification in the @emph{Org} buffer.  Fontification of code blocks can
-give visual separation of text and code on the display page.  To
-further customize the appearance of @code{org-block} for specific
-languages, customize @code{org-src-block-faces}.  The following example
-shades the background of regular blocks, and colors source blocks only
-for Python and Emacs Lisp languages.
-
-@lisp
-(require 'color)
-(set-face-attribute 'org-block nil :background
-                    (color-darken-name
-                     (face-attribute 'default :background) 3))
-
-(setq org-src-block-faces '(("emacs-lisp" (:background "#EEE2FF"))
-                            ("python" (:background "#E5FFB8"))))
-@end lisp
-
-@node Noweb Reference Syntax
-@section Noweb Reference Syntax
-
-@cindex code block, noweb reference
-@cindex syntax, noweb
-@cindex source code, noweb reference
-
-@cindex @samp{noweb-ref}, header argument
-Source code blocks can include references to other source code blocks,
-using a noweb@footnote{For noweb literate programming details, see
-@uref{http://www.cs.tufts.edu/~nr/noweb/}.} style syntax:
-
-@example
-<<CODE-BLOCK-ID>>
-@end example
-
-
-@noindent
-where @var{CODE-BLOCK-ID} refers to either the @samp{NAME} of a single
-source code block, or a collection of one or more source code blocks
-sharing the same @samp{noweb-ref} header argument (see @ref{Using Header 
Arguments}).  Org can replace such references with the source code of
-the block or blocks being referenced, or, in the case of a single
-source code block named with @samp{NAME}, with the results of an evaluation
-of that block.
-
-@cindex @samp{noweb}, header argument
-The @samp{noweb} header argument controls expansion of noweb syntax
-references.  Expansions occur when source code blocks are evaluated,
-tangled, or exported.
-
-@table @asis
-@item @samp{no}
-Default.  No expansion of noweb syntax references in the body of the
-code when evaluating, tangling, or exporting.
-
-@item @samp{yes}
-Expansion of noweb syntax references in the body of the code block
-when evaluating, tangling, or exporting.
-
-@item @samp{tangle}
-Expansion of noweb syntax references in the body of the code block
-when tangling.  No expansion when evaluating or exporting.
-
-@item @samp{no-export}
-Expansion of noweb syntax references in the body of the code block
-when evaluating or tangling.  No expansion when exporting.
-
-@item @samp{strip-export}
-Expansion of noweb syntax references in the body of the code block
-when expanding prior to evaluating or tangling.  Removes noweb
-syntax references when exporting.
-
-@item @samp{eval}
-Expansion of noweb syntax references in the body of the code block
-only before evaluating.
-@end table
-
-In the most simple case, the contents of a single source block is
-inserted within other blocks.  Thus, in following example,
-
-@example
-#+NAME: initialization
-#+BEGIN_SRC emacs-lisp
-  (setq sentence "Never a foot too far, even.")
-#+END_SRC
-
-#+BEGIN_SRC emacs-lisp :noweb yes
-  <<initialization>>
-  (reverse sentence)
-#+END_SRC
-@end example
-
-@noindent
-the second code block is expanded as
-
-@example
-#+BEGIN_SRC emacs-lisp :noweb yes
-  (setq sentence "Never a foot too far, even.")
-  (reverse sentence)
-#+END_SRC
-@end example
-
-You may also include the contents of multiple blocks sharing a common
-@samp{noweb-ref} header argument, which can be set at the file, sub-tree,
-or code block level.  In the example Org file shown next, the body of
-the source code in each block is extracted for concatenation to a pure
-code file when tangled.
-
-@example
-#+BEGIN_SRC sh :tangle yes :noweb yes :shebang #!/bin/sh
-  <<fullest-disk>>
-#+END_SRC
-* the mount point of the fullest disk
-  :PROPERTIES:
-  :header-args: :noweb-ref fullest-disk
-  :END:
-
-** query all mounted disks
-#+BEGIN_SRC sh
-  df \
-#+END_SRC
-
-** strip the header row
-#+BEGIN_SRC sh
-  |sed '1d' \
-#+END_SRC
-
-** output mount point of fullest disk
-#+BEGIN_SRC sh
-  |awk '@{if (u < +$5) @{u = +$5; m = $6@}@} END @{print m@}'
-#+END_SRC
-@end example
-
-@cindex @samp{noweb-sep}, header argument
-By default a newline separates each noweb reference concatenation.  To
-use a different separator, edit the @samp{noweb-sep} header argument.
-
-Alternatively, Org can include the results of evaluation of a single
-code block rather than its body.  Evaluation occurs when parentheses,
-possibly including arguments, are appended to the code block name, as
-shown below.
-
-@example
-<<NAME(optional arguments)>>
-@end example
-
-
-Note that in this case, a code block name set by @samp{NAME} keyword is
-required; the reference set by @samp{noweb-ref} will not work when
-evaluation is desired.
-
-Here is an example that demonstrates how the exported content changes
-when noweb style references are used with parentheses versus without.
-Given:
-
-@example
-#+NAME: some-code
-#+BEGIN_SRC python :var num=0 :results output :exports none
-  print(num*10)
-#+END_SRC
-@end example
-
-@noindent
-this code block:
-
-@example
-#+BEGIN_SRC text :noweb yes
-  <<some-code>>
-#+END_SRC
-@end example
-
-@noindent
-expands to:
-
-@example
-print(num*10)
-@end example
-
-
-Below, a similar noweb style reference is used, but with parentheses,
-while setting a variable @samp{num} to 10:
-
-@example
-#+BEGIN_SRC text :noweb yes
-  <<some-code(num=10)>>
-#+END_SRC
-@end example
-
-@noindent
-Note that the expansion now contains the results of the code block
-@samp{some-code}, not the code block itself:
-
-@example
-100
-@end example
-
-
-Noweb insertions honor prefix characters that appear before the noweb
-syntax reference.  This behavior is illustrated in the following
-example.  Because the @samp{<<example>>} noweb reference appears behind the
-SQL comment syntax, each line of the expanded noweb reference is
-commented.  With:
-
-@example
-#+NAME: example
-#+BEGIN_SRC text
-  this is the
-  multi-line body of example
-#+END_SRC
-@end example
-
-@noindent
-this code block:
-
-@example
-#+BEGIN_SRC sql :noweb yes
- ---<<example>>
-#+END_SRC
-@end example
-
-@noindent
-expands to:
-
-@example
-#+BEGIN_SRC sql :noweb yes
- ---this is the
- ---multi-line body of example
-#+END_SRC
-@end example
-
-Since this change does not affect noweb replacement text without
-newlines in them, inline noweb references are acceptable.
-
-This feature can also be used for management of indentation in
-exported code snippets.  With:
-
-@example
-#+NAME: if-true
-#+BEGIN_SRC python :exports none
-  print('do things when true')
-#+end_src
-
-#+name: if-false
-#+begin_src python :exports none
-  print('do things when false')
-#+end_src
-@end example
-
-@noindent
-this code block:
-
-@example
-#+begin_src python :noweb yes :results output
-  if true:
-      <<if-true>>
-  else:
-      <<if-false>>
-#+end_src
-@end example
-
-@noindent
-expands to:
-
-@example
-if true:
-    print('do things when true')
-else:
-    print('do things when false')
-@end example
-
-When in doubt about the outcome of a source code block expansion, you
-can preview the results with the following command:
-
-@table @asis
-@item @kbd{C-c C-v v} or @kbd{C-c C-v C-v} (@code{org-babel-expand-src-block})
-@findex org-babel-expand-src-block
-@kindex C-c C-v v
-@kindex C-c C-v C-v
-Expand the current source code block according to its header
-arguments and pop open the results in a preview buffer.
-@end table
-
-@node Library of Babel
-@section Library of Babel
-
-@cindex babel, library of
-@cindex source code, library
-@cindex code block, library
-
-The ``Library of Babel'' is a collection of code blocks.  Like
-a function library, these code blocks can be called from other Org
-files.  A collection of useful code blocks is available on 
@uref{https://orgmode.org/worg/library-of-babel.html, Worg}.  For
-remote code block evaluation syntax, see @ref{Evaluating Code Blocks}.
-
-@kindex C-c C-v i
-@findex org-babel-lob-ingest
-For any user to add code to the library, first save the code in
-regular code blocks of an Org file, and then load the Org file with
-@code{org-babel-lob-ingest}, which is bound to @kbd{C-c C-v i}.
-
-@node Key bindings and Useful Functions
-@section Key bindings and Useful Functions
-
-@cindex code block, key bindings
-
-Many common Org mode key sequences are re-bound depending on
-the context.
-
-Active key bindings in code blocks:
-
-@kindex C-c C-c
-@findex org-babel-execute-src-block
-@kindex C-c C-o
-@findex org-babel-open-src-block-result
-@kindex M-UP
-@findex org-babel-load-in-session
-@kindex M-DOWN
-@findex org-babel-pop-to-session
-@multitable @columnfractions 0.2 0.55
-@headitem Key binding
-@tab Function
-@item @kbd{C-c C-c}
-@tab @code{org-babel-execute-src-block}
-@item @kbd{C-c C-o}
-@tab @code{org-babel-open-src-block-result}
-@item @kbd{M-@key{UP}}
-@tab @code{org-babel-load-in-session}
-@item @kbd{M-@key{DOWN}}
-@tab @code{org-babel-pop-to-session}
-@end multitable
-
-Active key bindings in Org mode buffer:
-
-@kindex C-c C-v p
-@kindex C-c C-v C-p
-@kindex C-c C-v n
-@kindex C-c C-v C-n
-@kindex C-c C-v e
-@kindex C-c C-v C-e
-@kindex C-c C-v o
-@kindex C-c C-v C-o
-@kindex C-c C-v v
-@kindex C-c C-v C-v
-@kindex C-c C-v u
-@kindex C-c C-v C-u
-@kindex C-c C-v g
-@kindex C-c C-v C-g
-@kindex C-c C-v r
-@kindex C-c C-v C-r
-@kindex C-c C-v b
-@kindex C-c C-v C-b
-@kindex C-c C-v s
-@kindex C-c C-v C-s
-@kindex C-c C-v d
-@kindex C-c C-v C-d
-@kindex C-c C-v t
-@kindex C-c C-v C-t
-@kindex C-c C-v f
-@kindex C-c C-v C-f
-@kindex C-c C-v c
-@kindex C-c C-v C-c
-@kindex C-c C-v j
-@kindex C-c C-v C-j
-@kindex C-c C-v l
-@kindex C-c C-v C-l
-@kindex C-c C-v i
-@kindex C-c C-v C-i
-@kindex C-c C-v I
-@kindex C-c C-v C-I
-@kindex C-c C-v z
-@kindex C-c C-v C-z
-@kindex C-c C-v a
-@kindex C-c C-v C-a
-@kindex C-c C-v h
-@kindex C-c C-v C-h
-@kindex C-c C-v x
-@kindex C-c C-v C-x
-@findex org-babel-previous-src-block
-@findex org-babel-next-src-block
-@findex org-babel-execute-maybe
-@findex org-babel-open-src-block-result
-@findex org-babel-expand-src-block
-@findex org-babel-goto-src-block-head
-@findex org-babel-goto-named-src-block
-@findex org-babel-goto-named-result
-@findex org-babel-execute-buffer
-@findex org-babel-execute-subtree
-@findex org-babel-demarcate-block
-@findex org-babel-tangle
-@findex org-babel-tangle-file
-@findex org-babel-check-src-block
-@findex org-babel-insert-header-arg
-@findex org-babel-load-in-session
-@findex org-babel-lob-ingest
-@findex org-babel-view-src-block-info
-@findex org-babel-switch-to-session-with-code
-@findex org-babel-sha1-hash
-@findex org-babel-describe-bindings
-@findex org-babel-do-key-sequence-in-edit-buffer
-@multitable @columnfractions 0.45 0.55
-@headitem Key binding
-@tab Function
-@item @kbd{C-c C-v p} or @kbd{C-c C-v C-p}
-@tab @code{org-babel-previous-src-block}
-@item @kbd{C-c C-v n} or @kbd{C-c C-v C-n}
-@tab @code{org-babel-next-src-block}
-@item @kbd{C-c C-v e} or @kbd{C-c C-v C-e}
-@tab @code{org-babel-execute-maybe}
-@item @kbd{C-c C-v o} or @kbd{C-c C-v C-o}
-@tab @code{org-babel-open-src-block-result}
-@item @kbd{C-c C-v v} or @kbd{C-c C-v C-v}
-@tab @code{org-babel-expand-src-block}
-@item @kbd{C-c C-v u} or @kbd{C-c C-v C-u}
-@tab @code{org-babel-goto-src-block-head}
-@item @kbd{C-c C-v g} or @kbd{C-c C-v C-g}
-@tab @code{org-babel-goto-named-src-block}
-@item @kbd{C-c C-v r} or @kbd{C-c C-v C-r}
-@tab @code{org-babel-goto-named-result}
-@item @kbd{C-c C-v b} or @kbd{C-c C-v C-b}
-@tab @code{org-babel-execute-buffer}
-@item @kbd{C-c C-v s} or @kbd{C-c C-v C-s}
-@tab @code{org-babel-execute-subtree}
-@item @kbd{C-c C-v d} or @kbd{C-c C-v C-d}
-@tab @code{org-babel-demarcate-block}
-@item @kbd{C-c C-v t} or @kbd{C-c C-v C-t}
-@tab @code{org-babel-tangle}
-@item @kbd{C-c C-v f} or @kbd{C-c C-v C-f}
-@tab @code{org-babel-tangle-file}
-@item @kbd{C-c C-v c} or @kbd{C-c C-v C-c}
-@tab @code{org-babel-check-src-block}
-@item @kbd{C-c C-v j} or @kbd{C-c C-v C-j}
-@tab @code{org-babel-insert-header-arg}
-@item @kbd{C-c C-v l} or @kbd{C-c C-v C-l}
-@tab @code{org-babel-load-in-session}
-@item @kbd{C-c C-v i} or @kbd{C-c C-v C-i}
-@tab @code{org-babel-lob-ingest}
-@item @kbd{C-c C-v I} or @kbd{C-c C-v C-I}
-@tab @code{org-babel-view-src-block-info}
-@item @kbd{C-c C-v z} or @kbd{C-c C-v C-z}
-@tab @code{org-babel-switch-to-session-with-code}
-@item @kbd{C-c C-v a} or @kbd{C-c C-v C-a}
-@tab @code{org-babel-sha1-hash}
-@item @kbd{C-c C-v h} or @kbd{C-c C-v C-h}
-@tab @code{org-babel-describe-bindings}
-@item @kbd{C-c C-v x} or @kbd{C-c C-v C-x}
-@tab @code{org-babel-do-key-sequence-in-edit-buffer}
-@end multitable
-
-@node Batch Execution
-@section Batch Execution
-
-@cindex code block, batch execution
-@cindex source code, batch execution
-
-Org mode features, including working with source code facilities can
-be invoked from the command line.  This enables building shell scripts
-for batch processing, running automated system tasks, and expanding
-Org mode's usefulness.
-
-The sample script shows batch processing of multiple files using
-@code{org-babel-tangle}.
-
-@example
-#!/bin/sh
-# Tangle files with Org mode
-#
-emacs -Q --batch --eval "
-    (progn
-      (require 'ob-tangle)
-      (dolist (file command-line-args-left)
-        (with-current-buffer (find-file-noselect file)
-          (org-babel-tangle))))
-  " "$@@"
-@end example
-
-@node Miscellaneous
-@chapter Miscellaneous
-
-@menu
-* Completion::                   @kbd{M-@key{TAB}} guesses completions.
-* Structure Templates::          Quick insertion of structural elements.
-* Speed Keys::                   Electric commands at the beginning of a 
headline.
-* Clean View::                   Getting rid of leading stars in the outline.
-* Execute commands in the active region:: Execute commands on multiple items 
in Org or agenda view.
-* Dynamic Headline Numbering::   Display and update outline numbering.
-* The Very Busy @kbd{C-c C-c} Key:: When in doubt, press @kbd{C-c C-c}.
-* In-buffer Settings::           Overview of keywords.
-* Org Syntax::                   Formal description of Org's syntax.
-* Documentation Access::         Read documentation about current syntax.
-* Escape Character::             Prevent Org from interpreting your writing.
-* Code Evaluation Security::     Org files evaluate in-line code.
-* Interaction::                  With other Emacs packages.
-* TTY Keys::                     Using Org on a tty.
-* Protocols::                    External access to Emacs and Org.
-* Org Crypt::                    Encrypting Org files.
-* Org Mobile::                   Viewing and capture on a mobile device.
-@end menu
-
-@node Completion
-@section Completion
-
-@cindex completion, of @TeX{} symbols
-@cindex completion, of TODO keywords
-@cindex completion, of dictionary words
-@cindex completion, of option keywords
-@cindex completion, of tags
-@cindex completion, of property keys
-@cindex completion, of link abbreviations
-@cindex @TeX{} symbol completion
-@cindex TODO keywords completion
-@cindex dictionary word completion
-@cindex option keyword completion
-@cindex tag completion
-@cindex link abbreviations, completion of
-
-Org has in-buffer completions.  Unlike minibuffer completions, which
-are useful for quick command interactions, Org's in-buffer completions
-are more suitable for content creation in Org documents.  Type one or
-more letters and invoke the hot key to complete the text in-place.
-Depending on the context and the keys, Org offers different types of
-completions.  No minibuffer is involved.  Such mode-specific hot keys
-have become an integral part of Emacs and Org provides several
-shortcuts.
-
-@table @asis
-@item @kbd{M-@key{TAB}}
-@kindex M-TAB
-
-Complete word at point.
-
-@itemize
-@item
-At the beginning of an empty headline, complete TODO keywords.
-
-@item
-After @samp{\}, complete @TeX{} symbols supported by the exporter.
-
-@item
-After @samp{:} in a headline, complete tags.  Org deduces the list of
-tags from the @samp{TAGS} in-buffer option (see @ref{Setting Tags}), the
-variable @code{org-tag-alist}, or from all tags used in the current
-buffer.
-
-@item
-After @samp{:} and not in a headline, complete property keys.  The list
-of keys is constructed dynamically from all keys used in the
-current buffer.
-
-@item
-After @samp{[[}, complete link abbreviations (see @ref{Link Abbreviations}).
-
-@item
-After @samp{[[*}, complete headlines in the current buffer so that they
-can be used in search links like: @samp{[[*find this headline]]}
-
-@item
-After @samp{#+}, complete the special keywords like @samp{TYP_TODO} or
-file-specific @samp{OPTIONS}.  After option keyword is complete,
-pressing @kbd{M-@key{TAB}} again inserts example settings for this
-keyword.
-
-@item
-After @samp{STARTUP} keyword, complete startup items.
-
-@item
-When point is anywhere else, complete dictionary words using
-Ispell.
-@end itemize
-@end table
-
-@node Structure Templates
-@section Structure Templates
-
-@cindex template insertion
-@cindex insertion, of templates
-
-With just a few keystrokes, it is possible to insert empty structural
-blocks, such as @samp{#+BEGIN_SRC} @dots{} @samp{#+END_SRC}, or to wrap 
existing
-text in such a block.
-
-@table @asis
-@item @kbd{C-c C-,} (@code{org-insert-structure-template})
-@findex org-insert-structure-template
-@kindex C-c C-,
-Prompt for a type of block structure, and insert the block at point.
-If the region is active, it is wrapped in the block.  First prompts
-the user for keys, which are used to look up a structure type from
-the variable below.  If the key is @kbd{@key{TAB}}, @kbd{@key{RET}},
-or @kbd{@key{SPC}}, the user is prompted to enter a block type.
-@end table
-
-@vindex org-structure-template-alist
-Available structure types are defined in
-@code{org-structure-template-alist}, see the docstring for adding or
-changing values.
-
-@cindex Tempo
-@cindex template expansion
-@cindex insertion, of templates
-@vindex org-tempo-keywords-alist
-Org Tempo expands snippets to structures defined in
-@code{org-structure-template-alist} and @code{org-tempo-keywords-alist}.  For
-example, @kbd{< s @key{TAB}} creates a code block.  Enable it by
-customizing @code{org-modules} or add @samp{(require 'org-tempo)} to your Emacs
-init file@footnote{For more information, please refer to the commentary section
-in @samp{org-tempo.el}.}.
-
-@multitable @columnfractions 0.1 0.9
-@item @kbd{a}
-@tab @samp{#+BEGIN_EXPORT ascii} @dots{} @samp{#+END_EXPORT}
-@item @kbd{c}
-@tab @samp{#+BEGIN_CENTER} @dots{} @samp{#+END_CENTER}
-@item @kbd{C}
-@tab @samp{#+BEGIN_COMMENT} @dots{} @samp{#+END_COMMENT}
-@item @kbd{e}
-@tab @samp{#+BEGIN_EXAMPLE} @dots{} @samp{#+END_EXAMPLE}
-@item @kbd{E}
-@tab @samp{#+BEGIN_EXPORT} @dots{} @samp{#+END_EXPORT}
-@item @kbd{h}
-@tab @samp{#+BEGIN_EXPORT html} @dots{} @samp{#+END_EXPORT}
-@item @kbd{l}
-@tab @samp{#+BEGIN_EXPORT latex} @dots{} @samp{#+END_EXPORT}
-@item @kbd{q}
-@tab @samp{#+BEGIN_QUOTE} @dots{} @samp{#+END_QUOTE}
-@item @kbd{s}
-@tab @samp{#+BEGIN_SRC} @dots{} @samp{#+END_SRC}
-@item @kbd{v}
-@tab @samp{#+BEGIN_VERSE} @dots{} @samp{#+END_VERSE}
-@end multitable
-
-@node Speed Keys
-@section Speed Keys
-
-@cindex speed keys
-
-Single keystrokes can execute custom commands in an Org file when
-point is on a headline.  Without the extra burden of a meta or
-modifier key, Speed Keys can speed navigation or execute custom
-commands.  Besides faster navigation, Speed Keys may come in handy on
-small mobile devices that do not have full keyboards.  Speed Keys may
-also work on TTY devices known for their problems when entering Emacs
-key chords.
-
-@vindex org-use-speed-commands
-By default, Org has Speed Keys disabled.  To activate Speed Keys, set
-the variable @code{org-use-speed-commands} to a non-@code{nil} value.  To
-trigger a Speed Key, point must be at the beginning of an Org
-headline, before any of the stars.
-
-@vindex org-speed-commands-user
-@findex org-speed-command-help
-Org comes with a pre-defined list of Speed Keys.  To add or modify
-Speed Keys, customize the variable, @code{org-speed-commands-user}.  For
-more details, see the variable's docstring.  With Speed Keys
-activated, @kbd{M-x org-speed-command-help}, or @kbd{?} when
-point is at the beginning of an Org headline, shows currently active
-Speed Keys, including the user-defined ones.
-
-@node Clean View
-@section A Cleaner Outline View
-
-@cindex hiding leading stars
-@cindex dynamic indentation
-@cindex odd-levels-only outlines
-@cindex clean outline view
-
-Org's outline with stars and no indents can look cluttered for short
-documents.  For @emph{book-like} long documents, the effect is not as
-noticeable.  Org provides an alternate stars and indentation scheme,
-as shown on the right in the following table.  It displays only one
-star and indents text to line up with the heading:
-
-@example
-* Top level headline             |    * Top level headline
-** Second level                  |      * Second level
-*** Third level                  |        * Third level
-some text                        |          some text
-*** Third level                  |        * Third level
-more text                        |          more text
-* Another top level headline     |    * Another top level headline
-@end example
-
-Org can achieve this in two ways, (1) by just displaying the buffer in
-this way without changing it, or (2) by actually indenting every line
-in the desired amount with hard spaces and hiding leading stars.
-
-@menu
-* Org Indent Mode::
-* Hard indentation::
-@end menu
-
-@node Org Indent Mode
-@subsection Org Indent Mode
-
-@cindex Indent mode
-@findex org-indent-mode
-To display the buffer in the indented view, activate Org Indent minor
-mode, using @kbd{M-x org-indent-mode}.  Text lines that are not
-headlines are prefixed with virtual spaces to vertically align with
-the headline text@footnote{Org Indent mode also sets @code{wrap-prefix} 
correctly for
-indenting and wrapping long lines of headlines or text.  This minor
-mode also handles Visual Line mode and directly applied settings
-through @code{word-wrap}.}.
-
-@vindex org-indent-indentation-per-level
-To make more horizontal space, the headlines are shifted by two
-characters.  Configure @code{org-indent-indentation-per-level} variable for
-a different number.
-
-@vindex org-indent-mode-turns-on-hiding-stars
-@vindex org-indent-mode-turns-off-org-adapt-indentation
-By default, Org Indent mode turns off @code{org-adapt-indentation} and does
-hide leading stars by locally setting @code{org-hide-leading-stars} to 
@code{t}:
-only one star on each headline is visible, the rest are masked with
-the same font color as the background.  If you want to customize this
-default behavior, see @code{org-indent-mode-turns-on-hiding-stars} and
-@code{org-indent-mode-turns-off-org-adapt-indentation}.
-
-@vindex org-startup-indented
-To globally turn on Org Indent mode for all files, customize the
-variable @code{org-startup-indented}.  To control it for individual files,
-use @samp{STARTUP} keyword as follows:
-
-@example
-#+STARTUP: indent
-#+STARTUP: noindent
-@end example
-
-@node Hard indentation
-@subsection Hard indentation
-
-It is possible to use hard spaces to achieve the indentation instead,
-if the bare ASCII file should have the indented look also outside
-Emacs@footnote{This works, but requires extra effort.  Org Indent mode is
-more convenient for most applications.}.  With Org's support, you have to 
indent all lines to
-line up with the outline headers.  You would use these
-settings@footnote{@code{org-adapt-indentation} can also be set to 
@samp{'headline-data},
-in which case only data lines below the headline will be indented.}:
-
-@lisp
-(setq org-adapt-indentation t
-      org-hide-leading-stars t
-      org-odd-levels-only t)
-@end lisp
-
-@table @asis
-@item @emph{Indentation of text below headlines} (@code{org-adapt-indentation})
-@vindex org-adapt-indentation
-The first setting modifies paragraph filling, line wrapping, and
-structure editing commands to preserving or adapting the indentation
-as appropriate.
-
-@item @emph{Hiding leading stars} (@code{org-hide-leading-stars})
-@vindex org-hide-leading-stars
-@vindex org-hide, face
-The second setting makes leading stars invisible by applying the
-face @code{org-hide} to them.  For per-file preference, use these file
-@samp{STARTUP} options:
-
-@example
-#+STARTUP: hidestars
-#+STARTUP: showstars
-@end example
-
-@item @emph{Odd levels} (@code{org-odd-levels-only})
-@vindex org-odd-levels-only
-The third setting makes Org use only odd levels, 1, 3, 5, @dots{}, in
-the outline to create more indentation.  On a per-file level,
-control this with:
-
-@example
-#+STARTUP: odd
-#+STARTUP: oddeven
-@end example
-
-To convert a file between single and double stars layouts, use
-@kbd{M-x org-convert-to-odd-levels} and @kbd{M-x 
org-convert-to-oddeven-levels}.
-@end table
-
-@node Execute commands in the active region
-@section Execute commands in the active region
-
-@vindex org-loop-over-headlines-in-active-region
-When in an Org buffer and the region is active, some commands will
-apply to all the subtrees in the active region.  For example, hitting
-@kbd{C-c C-s} when multiple headlines are within the active region will
-successively prompt you for a new schedule date and time.  To disable
-this, set the option @code{org-loop-over-headlines-in-active-region} to
-non-@code{t}, activate the region and run the command normally.
-
-@vindex org-agenda-loop-over-headlines-in-active-region
-@code{org-agenda-loop-over-headlines-in-active-region} is the equivalent
-option of the agenda buffer, where you can also use @ref{Bulk remote editing 
selected entries, , bulk editing of
-selected entries}.
-
-Not all commands can loop in the active region and what subtrees or
-headlines are considered can be refined: see the docstrings of these
-options for more details.
-
-@node Dynamic Headline Numbering
-@section Dynamic Headline Numbering
-
-@cindex Org Num mode
-@cindex number headlines
-The Org Num minor mode, toggled with @kbd{M-x org-num-mode},
-displays outline numbering on top of headlines.  It also updates it
-automatically upon changes to the structure of the document.
-
-@vindex org-num-max-level
-@vindex org-num-skip-tags
-@vindex org-num-skip-commented
-@vindex org-num-skip-unnumbered
-By default, all headlines are numbered.  You can limit numbering to
-specific headlines according to their level, tags, @samp{COMMENT} keyword,
-or @samp{UNNUMBERED} property.  Set @code{org-num-max-level},
-@code{org-num-skip-tags}, @code{org-num-skip-commented},
-@code{org-num-skip-unnumbered}, or @code{org-num-skip-footnotes} accordingly.
-
-@vindex org-num-skip-footnotes
-If @code{org-num-skip-footnotes} is non-@code{nil}, footnotes sections (see
-@ref{Creating Footnotes}) are not numbered either.
-
-@vindex org-num-face
-@vindex org-num-format-function
-You can control how the numbering is displayed by setting
-@code{org-num-face} and @code{org-num-format-function}.
-
-@vindex org-startup-numerated
-You can also turn this mode globally for all Org files by setting the
-option @code{org-startup-numerated} to @samp{t}, or locally on a file by using
-@samp{#+startup: num}.
-
-@node The Very Busy @kbd{C-c C-c} Key
-@section The Very Busy @kbd{C-c C-c} Key
-
-@kindex C-c C-c
-@cindex @kbd{C-c C-c}, overview
-
-The @kbd{C-c C-c} key in Org serves many purposes depending on
-the context.  It is probably the most over-worked, multi-purpose key
-combination in Org.  Its uses are well documented throughout this
-manual, but here is a consolidated list for easy reference.
-
-@itemize
-@item
-If column view (see @ref{Column View}) is on, exit column view.
-
-@item
-If any highlights shown in the buffer from the creation of a sparse
-tree, or from clock display, remove such highlights.
-
-@item
-If point is in one of the special @samp{KEYWORD} lines, scan the buffer
-for these lines and update the information.  Also reset the Org file
-cache used to temporary store the contents of URLs used as values
-for keywords like @samp{SETUPFILE}.
-
-@item
-If point is inside a table, realign the table.
-
-@item
-If point is on a @samp{TBLFM} keyword, re-apply the formulas to the
-entire table.
-
-@item
-If the current buffer is a capture buffer, close the note and file
-it.  With a prefix argument, also jump to the target location after
-saving the note.
-
-@item
-If point is on a @samp{<<<target>>>}, update radio targets and
-corresponding links in this buffer.
-
-@item
-If point is on a property line or at the start or end of a property
-drawer, offer property commands.
-
-@item
-If point is at a footnote reference, go to the corresponding
-definition, and @emph{vice versa}.
-
-@item
-If point is on a statistics cookie, update it.
-
-@item
-If point is in a plain list item with a checkbox, toggle the status
-of the checkbox.
-
-@item
-If point is on a numbered item in a plain list, renumber the ordered
-list.
-
-@item
-If point is on the @samp{#+BEGIN} line of a dynamic block, the block is
-updated.
-
-@item
-If point is at a timestamp, fix the day name in the timestamp.
-@end itemize
-
-@node In-buffer Settings
-@section Summary of In-Buffer Settings
-
-@cindex in-buffer settings
-@cindex special keywords
-
-In-buffer settings start with @samp{#+}, followed by a keyword, a colon,
-and then a word for each setting.  Org accepts multiple settings on
-the same line.  Org also accepts multiple lines for a keyword.  This
-manual describes these settings throughout.  A summary follows here.
-
-@cindex refresh set-up
-@kbd{C-c C-c} activates any changes to the in-buffer settings.
-Closing and reopening the Org file in Emacs also activates the
-changes.
-
-@table @asis
-@item @samp{#+ARCHIVE: %s_done::}
-@cindex @samp{ARCHIVE}, keyword
-@vindex org-archive-location
-Sets the archive location of the agenda file.  The corresponding
-variable is @code{org-archive-location}.
-
-@item @samp{#+CATEGORY}
-@cindex @samp{CATEGORY}, keyword
-Sets the category of the agenda file, which applies to the entire
-document.
-
-@item @samp{#+COLUMNS: %25ITEM ...}
-@cindex @samp{COLUMNS}, property
-Set the default format for columns view.  This format applies when
-columns view is invoked in locations where no @samp{COLUMNS} property
-applies.
-
-@item @samp{#+CONSTANTS: name1=value1 ...}
-@cindex @samp{CONSTANTS}, keyword
-@vindex org-table-formula-constants
-@vindex org-table-formula
-Set file-local values for constants that table formulas can use.
-This line sets the local variable
-@code{org-table-formula-constants-local}.  The global version of this
-variable is @code{org-table-formula-constants}.
-
-@item @samp{#+FILETAGS: :tag1:tag2:tag3:}
-@cindex @samp{FILETAGS}, keyword
-Set tags that all entries in the file inherit from, including the
-top-level entries.
-
-@item @samp{#+LINK: linkword replace}
-@cindex @samp{LINK}, keyword
-@vindex org-link-abbrev-alist
-Each line specifies one abbreviation for one link.  Use multiple
-@samp{LINK} keywords for more, see @ref{Link Abbreviations}.  The
-corresponding variable is @code{org-link-abbrev-alist}.
-
-@item @samp{#+PRIORITIES: highest lowest default}
-@cindex @samp{PRIORITIES}, keyword
-@vindex org-priority-highest
-@vindex org-priority-lowest
-@vindex org-priority-default
-This line sets the limits and the default for the priorities.  All
-three must be either letters A--Z or numbers 0--9.  The highest
-priority must have a lower ASCII number than the lowest priority.
-
-@item @samp{#+PROPERTY: Property_Name Value}
-@cindex @samp{PROPERTY}, keyword
-This line sets a default inheritance value for entries in the
-current buffer, most useful for specifying the allowed values of
-a property.
-
-@item @samp{#+SETUPFILE: file}
-@cindex @samp{SETUPFILE}, keyword
-The setup file or a URL pointing to such file is for additional
-in-buffer settings.  Org loads this file and parses it for any
-settings in it only when Org opens the main file.  If URL is
-specified, the contents are downloaded and stored in a temporary
-file cache.  @kbd{C-c C-c} on the settings line parses and
-loads the file, and also resets the temporary file cache.  Org also
-parses and loads the document during normal exporting process.  Org
-parses the contents of this document as if it was included in the
-buffer.  It can be another Org file.  To visit the file---not
-a URL---use @kbd{C-c '} while point is on the line with the
-file name.
-
-@item @samp{#+STARTUP:}
-@cindex @samp{STARTUP}, keyword
-Startup options Org uses when first visiting a file.
-
-@vindex org-startup-folded
-The first set of options deals with the initial visibility of the
-outline tree.  The corresponding variable for global default
-settings is @code{org-startup-folded} with a default value of
-@code{showeverything}.
-
-@multitable {aaaaaaaaaaaaaaaa} {aaaaaaaaaaaaaaaaaaaaaaaaaa}
-@item @samp{overview}
-@tab Top-level headlines only.
-@item @samp{content}
-@tab All headlines.
-@item @samp{showall}
-@tab No folding on any entry.
-@item @samp{showeverything}
-@tab Show even drawer contents.
-@end multitable
-
-@vindex org-startup-indented
-Dynamic virtual indentation is controlled by the variable
-@code{org-startup-indented}@footnote{Note that Org Indent mode also sets the 
@code{wrap-prefix}
-property, such that Visual Line mode (or purely setting @code{word-wrap})
-wraps long lines, including headlines, correctly indented.}.
-
-@multitable {aaaaaaaaaa} {aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa}
-@item @samp{indent}
-@tab Start with Org Indent mode turned on.
-@item @samp{noindent}
-@tab Start with Org Indent mode turned off.
-@end multitable
-
-@vindex org-startup-numerated
-Dynamic virtual numeration of headlines is controlled by the variable
-@code{org-startup-numerated}.
-
-@multitable {aaaaaaa} {aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa}
-@item @samp{num}
-@tab Start with Org num mode turned on.
-@item @samp{nonum}
-@tab Start with Org num mode turned off.
-@end multitable
-
-@vindex org-startup-align-all-tables
-Aligns tables consistently upon visiting a file.  The
-corresponding variable is @code{org-startup-align-all-tables} with
-@code{nil} as default value.
-
-@multitable {aaaaaaaaa} {aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa}
-@item @samp{align}
-@tab Align all tables.
-@item @samp{noalign}
-@tab Do not align tables on startup.
-@end multitable
-
-@vindex org-startup-shrink-all-tables
-Shrink table columns with a width cookie.  The corresponding
-variable is @code{org-startup-shrink-all-tables} with @code{nil} as
-default value.
-
-@vindex org-startup-with-inline-images
-When visiting a file, inline images can be automatically
-displayed.  The corresponding variable is
-@code{org-startup-with-inline-images}, with a default value @code{nil} to
-avoid delays when visiting a file.
-
-@multitable {aaaaaaaaaaaaaaaa} {aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa}
-@item @samp{inlineimages}
-@tab Show inline images.
-@item @samp{noinlineimages}
-@tab Do not show inline images on startup.
-@end multitable
-
-@vindex org-log-done
-@vindex org-log-note-clock-out
-@vindex org-log-repeat
-Logging the closing and reopening of TODO items and clock
-intervals can be configured using these options (see variables
-@code{org-log-done}, @code{org-log-note-clock-out}, and @code{org-log-repeat}).
-
-@multitable {aaaaaaaaaaaaaaaaaaaa} 
{aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa}
-@item @samp{logdone}
-@tab Record a timestamp when an item is marked as done.
-@item @samp{lognotedone}
-@tab Record timestamp and a note when DONE@.
-@item @samp{nologdone}
-@tab Do not record when items are marked as done.
-@item @samp{logrepeat}
-@tab Record a time when reinstating a repeating item.
-@item @samp{lognoterepeat}
-@tab Record a note when reinstating a repeating item.
-@item @samp{nologrepeat}
-@tab Do not record when reinstating repeating item.
-@item @samp{lognoteclock-out}
-@tab Record a note when clocking out.
-@item @samp{nolognoteclock-out}
-@tab Do not record a note when clocking out.
-@item @samp{logreschedule}
-@tab Record a timestamp when scheduling time changes.
-@item @samp{lognotereschedule}
-@tab Record a note when scheduling time changes.
-@item @samp{nologreschedule}
-@tab Do not record when a scheduling date changes.
-@item @samp{logredeadline}
-@tab Record a timestamp when deadline changes.
-@item @samp{lognoteredeadline}
-@tab Record a note when deadline changes.
-@item @samp{nologredeadline}
-@tab Do not record when a deadline date changes.
-@item @samp{logrefile}
-@tab Record a timestamp when refiling.
-@item @samp{lognoterefile}
-@tab Record a note when refiling.
-@item @samp{nologrefile}
-@tab Do not record when refiling.
-@end multitable
-
-@vindex org-hide-leading-stars
-@vindex org-odd-levels-only
-Here are the options for hiding leading stars in outline
-headings, and for indenting outlines.  The corresponding
-variables are @code{org-hide-leading-stars} and
-@code{org-odd-levels-only}, both with a default setting @code{nil}
-(meaning @samp{showstars} and @samp{oddeven}).
-
-@multitable {aaaaaaaaaaa} 
{aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa}
-@item @samp{hidestars}
-@tab Make all but one of the stars starting a headline invisible.
-@item @samp{showstars}
-@tab Show all stars starting a headline.
-@item @samp{indent}
-@tab Virtual indentation according to outline level.
-@item @samp{noindent}
-@tab No virtual indentation according to outline level.
-@item @samp{odd}
-@tab Allow only odd outline levels (1, 3, @dots{}).
-@item @samp{oddeven}
-@tab Allow all outline levels.
-@end multitable
-
-@vindex org-put-time-stamp-overlays
-@vindex org-time-stamp-overlay-formats
-To turn on custom format overlays over timestamps (variables
-@code{org-put-time-stamp-overlays} and
-@code{org-time-stamp-overlay-formats}), use:
-
-@multitable {aaaaaaaaaaaa} {aaaaaaaaaaaaaaaaaaaaaaaaaaa}
-@item @samp{customtime}
-@tab Overlay custom time format.
-@end multitable
-
-@vindex constants-unit-system
-The following options influence the table spreadsheet (variable
-@code{constants-unit-system}).
-
-@multitable {aaaaaaaaaa} {aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa}
-@item @samp{constcgs}
-@tab @samp{constants.el} should use the c-g-s unit system.
-@item @samp{constSI}
-@tab @samp{constants.el} should use the SI unit system.
-@end multitable
-
-@vindex org-footnote-define-inline
-@vindex org-footnote-auto-label
-@vindex org-footnote-auto-adjust
-To influence footnote settings, use the following keywords.  The
-corresponding variables are @code{org-footnote-define-inline},
-@code{org-footnote-auto-label}, and @code{org-footnote-auto-adjust}.
-
-@multitable {aaaaaaaaaaaa} 
{aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa}
-@item @samp{fninline}
-@tab Define footnotes inline.
-@item @samp{fnnoinline}
-@tab Define footnotes in separate section.
-@item @samp{fnlocal}
-@tab Define footnotes near first reference, but not inline.
-@item @samp{fnprompt}
-@tab Prompt for footnote labels.
-@item @samp{fnauto}
-@tab Create @samp{[fn:1]}-like labels automatically (default).
-@item @samp{fnconfirm}
-@tab Offer automatic label for editing or confirmation.
-@item @samp{fnadjust}
-@tab Automatically renumber and sort footnotes.
-@item @samp{nofnadjust}
-@tab Do not renumber and sort automatically.
-@end multitable
-
-@vindex org-hide-block-startup
-To hide blocks on startup, use these keywords.  The
-corresponding variable is @code{org-hide-block-startup}.
-
-@multitable {aaaaaaaaaaaaaa} {aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa}
-@item @samp{hideblocks}
-@tab Hide all begin/end blocks on startup.
-@item @samp{nohideblocks}
-@tab Do not hide blocks on startup.
-@end multitable
-
-@vindex org-pretty-entities
-The display of entities as UTF-8 characters is governed by the
-variable @code{org-pretty-entities} and the keywords
-
-@multitable {aaaaaaaaaaaaaaaa} 
{aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa}
-@item @samp{entitiespretty}
-@tab Show entities as UTF-8 characters where possible.
-@item @samp{entitiesplain}
-@tab Leave entities plain.
-@end multitable
-
-@item @samp{#+TAGS: TAG1(c1) TAG2(c2)}
-@cindex @samp{TAGS}, keyword
-@vindex org-tag-alist
-These lines (several such lines are allowed) specify the valid tags
-in this file, and (potentially) the corresponding @emph{fast tag
-selection} keys.  The corresponding variable is @code{org-tag-alist}.
-
-@item @samp{#+TODO:}
-@itemx @samp{#+SEQ_TODO:}
-@itemx @samp{#+TYP_TODO:}
-@cindex @samp{SEQ_TODO}, keyword
-@cindex @samp{TODO}, keyword
-@cindex @samp{TYP_TODO}, keyword
-@vindex org-todo-keywords
-These lines set the TODO keywords and their interpretation in the
-current file.  The corresponding variable is @code{org-todo-keywords}.
-@end table
-
-@node Org Syntax
-@section Org Syntax
-
-A reference document providing a formal description of Org's syntax is
-available as @uref{https://orgmode.org/worg/dev/org-syntax.html, a draft on 
Worg}, written and maintained by Nicolas
-Goaziou.  It defines Org's core internal concepts such as ``headlines'',
-``sections'', ``affiliated keywords'', ``(greater) elements'' and ``objects''.
-Each part of an Org document belongs to one of the previous
-categories.
-
-To explore the abstract structure of an Org buffer, run this in
-a buffer:
-
-@example
-M-: (org-element-parse-buffer) <RET>
-@end example
-
-
-@noindent
-It outputs a list containing the buffer's content represented as an
-abstract structure.  The export engine relies on the information
-stored in this list.  Most interactive commands---e.g., for structure
-editing---also rely on the syntactic meaning of the surrounding
-context.
-
-@cindex syntax checker
-@cindex linter
-@findex org-lint
-You can probe the syntax of your documents with the command
-
-@example
-M-x org-lint <RET>
-@end example
-
-
-@noindent
-It runs a number of checks to find common mistakes.  It then displays
-their location in a dedicated buffer, along with a description and
-a ``trust level'', since false-positive are possible.  From there, you
-can operate on the reports with the following keys:
-
-@multitable @columnfractions 0.22 0.78
-@item @kbd{C-j}, @kbd{@key{TAB}}
-@tab Display the offending line
-@item @kbd{@key{RET}}
-@tab Move point to the offending line
-@item @kbd{g}
-@tab Check the document again
-@item @kbd{h}
-@tab Hide all reports from the same checker
-@item @kbd{i}
-@tab Also remove them from all subsequent checks
-@item @kbd{S}
-@tab Sort reports by the column at point
-@end multitable
-
-@node Documentation Access
-@section Context Dependent Documentation
-
-@cindex documentation
-@cindex Info
-
-@findex org-info-find-node
-@kindex C-c C-x I
-@kbd{C-c C-x I} in an Org file tries to open a suitable section
-of the Org manual depending on the syntax at point.  For example,
-using it on a headline displays ``Document Structure'' section.
-
-@kbd{q} closes the Info window.
-
-@node Escape Character
-@section Escape Character
-
-@cindex escape character
-@cindex zero width space
-You may sometimes want to write text that looks like Org syntax, but
-should really read as plain text.  Org may use a specific escape
-character in some situations, i.e., a backslash in macros (see @ref{Macro 
Replacement}) and links (see @ref{Link Format}), or a comma in source and
-example blocks (see @ref{Literal Examples}).  In the general case, however,
-we suggest to use the zero width space.  You can insert one with any
-of the following:
-
-@example
-C-x 8 <RET> zero width space <RET>
-C-x 8 <RET> 200B <RET>
-@end example
-
-
-For example, in order to write @samp{[[1,2]]} as-is in your document, you
-may write instead
-
-@example
-[X[1,2]]
-@end example
-
-
-where @samp{X} denotes the zero width space character.
-
-@node Code Evaluation Security
-@section Code Evaluation and Security Issues
-
-Unlike plain text, running code comes with risk.  Each source code
-block, in terms of risk, is equivalent to an executable file.  Org
-therefore puts a few confirmation prompts by default.  This is to
-alert the casual user from accidentally running untrusted code.
-
-For users who do not run code blocks or write code regularly, Org's
-default settings should suffice.  However, some users may want to
-tweak the prompts for fewer interruptions.  To weigh the risks of
-automatic execution of code blocks, here are some details about code
-evaluation.
-
-Org evaluates code in the following circumstances:
-
-@table @asis
-@item @emph{Source code blocks}
-Org evaluates source code blocks in an Org file during export.  Org
-also evaluates a source code block with the @kbd{C-c C-c} key
-chord.  Users exporting or running code blocks must load files only
-from trusted sources.  Be wary of customizing variables that remove
-or alter default security measures.
-
-@defopt org-confirm-babel-evaluate
-When @code{t}, Org prompts the user for confirmation before executing
-each code block.  When @code{nil}, Org executes code blocks without
-prompting the user for confirmation.  When this option is set to
-a custom function, Org invokes the function with these two
-arguments: the source code language and the body of the code block.
-The custom function must return either a @code{t} or @code{nil}, which
-determines if the user is prompted.  Each source code language can
-be handled separately through this function argument.
-@end defopt
-
-For example, here is how to execute ditaa code blocks without
-prompting:
-
-@lisp
-(defun my-org-confirm-babel-evaluate (lang body)
-  (not (string= lang "ditaa")))  ;don't ask for ditaa
-(setq org-confirm-babel-evaluate #'my-org-confirm-babel-evaluate)
-@end lisp
-
-@item @emph{Following @samp{shell} and @samp{elisp} links}
-Org has two link types that can directly evaluate code (see
-@ref{External Links}).  Because such code is not visible, these links
-have a potential risk.  Org therefore prompts the user when it
-encounters such links.  The customization variables are:
-
-@defopt org-link-shell-confirm-function
-Function that prompts the user before executing a shell link.
-@end defopt
-
-@defopt org-link-elisp-confirm-function
-Function that prompts the user before executing an Emacs Lisp link.
-@end defopt
-
-@item @emph{Formulas in tables}
-Formulas in tables (see @ref{The Spreadsheet}) are code that is evaluated
-either by the Calc interpreter, or by the Emacs Lisp interpreter.
-@end table
-
-@node Interaction
-@section Interaction with Other Packages
-
-@cindex packages, interaction with other
-
-Org's compatibility and the level of interaction with other Emacs
-packages are documented here.
-
-@menu
-* Cooperation::                  Packages Org cooperates with.
-* Conflicts::                    Packages that lead to conflicts.
-@end menu
-
-@node Cooperation
-@subsection Packages that Org cooperates with
-
-@table @asis
-@item @samp{calc.el} by Dave Gillespie
-@cindex @file{calc.el}
-
-Org uses the Calc package for implementing spreadsheet functionality
-in its tables (see @ref{The Spreadsheet}).  Org also uses Calc for
-embedded calculations.  See @ref{Embedded Mode,GNU Emacs Calc Manual,,calc,}.
-
-@item @samp{constants.el} by Carsten Dominik
-@cindex @file{constants.el}
-@vindex org-table-formula-constants
-
-Org can use names for constants in formulas in tables.  Org can also
-use calculation suffixes for units, such as @samp{M} for @samp{Mega}.  For
-a standard collection of such constants, install the @samp{constants}
-package.  Install version 2.0 of this package, available at
-@uref{http://www.astro.uva.nl/~dominik/Tools}.  Org checks if the function
-@code{constants-get} has been autoloaded.  Installation instructions are
-in the file @samp{constants.el}.
-
-@item @samp{cdlatex.el} by Carsten Dominik
-@cindex @file{cdlatex.el}
-
-Org mode can make use of the CD@LaTeX{} package to efficiently enter
-@LaTeX{} fragments into Org files.  See @ref{CD@LaTeX{} mode}.
-
-@item @samp{imenu.el} by Ake Stenhoff and Lars Lindberg
-@cindex @file{imenu.el}
-
-Imenu creates dynamic menus based on an index of items in a file.
-Org mode supports Imenu menus.  Enable it with a mode hook as
-follows:
-
-@lisp
-(add-hook 'org-mode-hook
-          (lambda () (imenu-add-to-menubar "Imenu")))
-@end lisp
-
-@vindex org-imenu-depth
-By default the index is two levels deep---you can modify the
-depth using the option @code{org-imenu-depth}.
-
-@item @samp{speedbar.el} by Eric@tie{}M@.@tie{}Ludlam
-@cindex @file{speedbar.el}
-
-Speedbar package creates a special Emacs frame for displaying files
-and index items in files.  Org mode supports Speedbar; users can
-drill into Org files directly from the Speedbar.  The @kbd{<}
-in the Speedbar frame tweaks the agenda commands to that file or to
-a subtree.
-
-@item @samp{table.el} by Takaaki Ota
-@cindex table editor, @file{table.el}
-@cindex @file{table.el}
-
-Complex ASCII tables with automatic line wrapping, column- and
-row-spanning, and alignment can be created using the Emacs table
-package by Takaaki Ota.  Org mode recognizes such tables and exports
-them properly.  @kbd{C-c '} to edit these tables in a special
-buffer, much like Org's code blocks.  Because of interference with
-other Org mode functionality, Takaaki Ota tables cannot be edited
-directly in the Org buffer.
-
-@table @asis
-@item @kbd{C-c '} (@code{org-edit-special})
-@kindex C-c '
-@findex org-edit-special
-Edit a @samp{table.el} table.  Works when point is in a @samp{table.el}
-table.
-
-@item @kbd{C-c ~​} (@code{org-table-create-with-table.el})
-@kindex C-c ~
-@findex org-table-create-with-table.el
-Insert a @samp{table.el} table.  If there is already a table at point,
-this command converts it between the @samp{table.el} format and the Org
-mode format.  See the documentation string of the command
-@code{org-convert-table} for the restrictions under which this is
-possible.
-@end table
-@end table
-
-@node Conflicts
-@subsection Packages that conflict with Org mode
-
-@cindex shift-selection
-@vindex org-support-shift-select
-In Emacs, shift-selection combines motions of point with shift key to
-enlarge regions.  Emacs sets this mode by default.  This conflicts
-with Org's use of @kbd{S-<cursor>} commands to change timestamps,
-TODO keywords, priorities, and item bullet types, etc.  Since
-@kbd{S-<cursor>} commands outside of specific contexts do not do
-anything, Org offers the variable @code{org-support-shift-select} for
-customization.  Org mode accommodates shift selection by (i) making it
-available outside of the special contexts where special commands
-apply, and (ii) extending an existing active region even if point
-moves across a special context.
-
-@table @asis
-@item @samp{cua.el} by Kim@tie{}F@.@tie{}Storm
-@cindex @file{cua.el}
-@vindex org-replace-disputed-keys
-Org key bindings conflict with @kbd{S-<cursor>} keys used by
-CUA mode.  For Org to relinquish these bindings to CUA mode,
-configure the variable @code{org-replace-disputed-keys}.  When set, Org
-moves the following key bindings in Org files, and in the agenda
-buffer---but not during date selection.
-
-@multitable @columnfractions 0.4 0.4
-@item @kbd{S-@key{UP}}      @result{}  @kbd{M-p}
-@tab @kbd{S-@key{DOWN}}     @result{}  @kbd{M-n}
-@item @kbd{S-@key{LEFT}}    @result{}  @kbd{M--}
-@tab @kbd{S-@key{RIGHT}}    @result{}  @kbd{M-+}
-@item @kbd{C-S-@key{LEFT}}  @result{}  @kbd{M-S--}
-@tab @kbd{C-S-@key{RIGHT}}  @result{}  @kbd{M-S-+}
-@end multitable
-
-@vindex org-disputed-keys
-Yes, these are unfortunately more difficult to remember.  If you
-want to have other replacement keys, look at the variable
-@code{org-disputed-keys}.
-
-@item @samp{ecomplete.el} by Lars Magne Ingebrigtsen
-@cindex @file{ecomplete.el}
-Ecomplete provides ``electric'' address completion in address header
-lines in message buffers.  Sadly Orgtbl mode cuts Ecomplete's power
-supply: no completion happens when Orgtbl mode is enabled in message
-buffers while entering text in address header lines.  If one wants
-to use ecomplete one should @emph{not} follow the advice to automagically
-turn on Orgtbl mode in message buffers (see @ref{Orgtbl Mode}),
-but instead---after filling in the message headers---turn on Orgtbl
-mode manually when needed in the messages body.
-
-@item @samp{filladapt.el} by Kyle Jones
-@cindex @file{filladapt.el}
-Org mode tries to do the right thing when filling paragraphs, list
-items and other elements.  Many users reported problems using both
-@samp{filladapt.el} and Org mode, so a safe thing to do is to disable
-filladapt like this:
-
-@lisp
-(add-hook 'org-mode-hook 'turn-off-filladapt-mode)
-@end lisp
-
-@item @samp{viper.el} by Michael Kifer
-@cindex @file{viper.el}
-@kindex C-c /
-
-Viper uses @kbd{C-c /} and therefore makes this key not access
-the corresponding Org mode command @code{org-sparse-tree}.  You need to
-find another key for this command, or override the key in
-@code{viper-vi-global-user-map} with
-
-@lisp
-(define-key viper-vi-global-user-map "C-c /" 'org-sparse-tree)
-@end lisp
-
-@item @samp{windmove.el} by Hovav Shacham
-@cindex @file{windmove.el}
-
-This package also uses the @kbd{S-<cursor>} keys, so everything
-written in the paragraph above about CUA mode also applies here.  If
-you want to make the windmove function active in locations where Org
-mode does not have special functionality on @kbd{S-<cursor>},
-add this to your configuration:
-
-@lisp
-;; Make windmove work in Org mode:
-(add-hook 'org-shiftup-final-hook 'windmove-up)
-(add-hook 'org-shiftleft-final-hook 'windmove-left)
-(add-hook 'org-shiftdown-final-hook 'windmove-down)
-(add-hook 'org-shiftright-final-hook 'windmove-right)
-@end lisp
-
-@item @samp{yasnippet.el}
-@cindex @file{yasnippet.el}
-The way Org mode binds the @kbd{@key{TAB}} key (binding to @code{[tab]}
-instead of @code{"\t"}) overrules YASnippet's access to this key.  The
-following code fixed this problem:
-
-@lisp
-(add-hook 'org-mode-hook
-          (lambda ()
-            (setq-local yas/trigger-key [tab])
-            (define-key yas/keymap [tab] 'yas/next-field-or-maybe-expand)))
-@end lisp
-
-The latest version of YASnippet does not play well with Org mode.
-If the above code does not fix the conflict, start by defining
-the following function:
-
-@lisp
-(defun yas/org-very-safe-expand ()
-  (let ((yas/fallback-behavior 'return-nil)) (yas/expand)))
-@end lisp
-
-Then, tell Org mode to use that function:
-
-@lisp
-(add-hook 'org-mode-hook
-          (lambda ()
-            (make-variable-buffer-local 'yas/trigger-key)
-            (setq yas/trigger-key [tab])
-            (add-to-list 'org-tab-first-hook 'yas/org-very-safe-expand)
-            (define-key yas/keymap [tab] 'yas/next-field)))
-@end lisp
-@end table
-
-@node TTY Keys
-@section Using Org on a TTY
-
-@cindex tty key bindings
-
-Org provides alternative key bindings for TTY and modern mobile
-devices that cannot perform movement commands on point and key
-bindings with modifier keys.  Some of these workarounds may be more
-cumbersome than necessary.  Users should look into customizing these
-further based on their usage needs.  For example, the normal
-@kbd{S-<cursor>} for editing timestamp might be better with
-@kbd{C-c .} chord.
-
-@multitable @columnfractions 0.2 0.28 0.15 0.21
-@headitem Default
-@tab Alternative 1
-@tab Speed key
-@tab Alternative 2
-@item @kbd{S-@key{TAB}}
-@tab @kbd{C-u @key{TAB}}
-@tab @kbd{C}
-@tab
-@item @kbd{M-@key{LEFT}}
-@tab @kbd{C-c C-x l}
-@tab @kbd{l}
-@tab @kbd{Esc @key{LEFT}}
-@item @kbd{M-S-@key{LEFT}}
-@tab @kbd{C-c C-x L}
-@tab @kbd{L}
-@tab
-@item @kbd{M-@key{RIGHT}}
-@tab @kbd{C-c C-x r}
-@tab @kbd{r}
-@tab @kbd{Esc @key{RIGHT}}
-@item @kbd{M-S-@key{RIGHT}}
-@tab @kbd{C-c C-x R}
-@tab @kbd{R}
-@tab
-@item @kbd{M-@key{UP}}
-@tab @kbd{C-c C-x u}
-@tab
-@tab @kbd{Esc @key{UP}}
-@item @kbd{M-S-@key{UP}}
-@tab @kbd{C-c C-x U}
-@tab @kbd{U}
-@tab
-@item @kbd{M-@key{DOWN}}
-@tab @kbd{C-c C-x d}
-@tab
-@tab @kbd{Esc @key{DOWN}}
-@item @kbd{M-S-@key{DOWN}}
-@tab @kbd{C-c C-x D}
-@tab @kbd{D}
-@tab
-@item @kbd{S-@key{RET}}
-@tab @kbd{C-c C-x c}
-@tab
-@tab
-@item @kbd{M-@key{RET}}
-@tab @kbd{C-c C-x m}
-@tab
-@tab @kbd{Esc @key{RET}}
-@item @kbd{M-S-@key{RET}}
-@tab @kbd{C-c C-x M}
-@tab
-@tab
-@item @kbd{S-@key{LEFT}}
-@tab @kbd{C-c @key{LEFT}}
-@tab
-@tab
-@item @kbd{S-@key{RIGHT}}
-@tab @kbd{C-c @key{RIGHT}}
-@tab
-@tab
-@item @kbd{S-@key{UP}}
-@tab @kbd{C-c @key{UP}}
-@tab
-@tab
-@item @kbd{S-@key{DOWN}}
-@tab @kbd{C-c @key{DOWN}}
-@tab
-@tab
-@item @kbd{C-S-@key{LEFT}}
-@tab @kbd{C-c C-x @key{LEFT}}
-@tab
-@tab
-@item @kbd{C-S-@key{RIGHT}}
-@tab @kbd{C-c C-x @key{RIGHT}}
-@tab
-@tab
-@end multitable
-
-@node Protocols
-@section Protocols for External Access
-
-@cindex protocols, for external access
-
-Org protocol is a tool to trigger custom actions in Emacs from
-external applications.  Any application that supports calling external
-programs with an URL as argument may be used with this functionality.
-For example, you can configure bookmarks in your web browser to send a
-link to the current page to Org and create a note from it using
-capture (see @ref{Capture}).  You can also create a bookmark that tells
-Emacs to open the local source file of a remote website you are
-browsing.
-
-@cindex Org protocol, set-up
-@cindex Installing Org protocol
-In order to use Org protocol from an application, you need to register
-@samp{org-protocol://} as a valid scheme-handler.  External calls are
-passed to Emacs through the @samp{emacsclient} command, so you also need to
-ensure an Emacs server is running.  More precisely, when the
-application calls
-
-@example
-emacsclient org-protocol://PROTOCOL?key1=val1&key2=val2
-@end example
-
-
-@noindent
-Emacs calls the handler associated to @var{PROTOCOL} with
-argument @samp{(:key1 val1 :key2 val2)}.
-
-@cindex protocol, new protocol
-@cindex defining new protocols
-Org protocol comes with three predefined protocols, detailed in the
-following sections.  Configure @code{org-protocol-protocol-alist} to define
-your own.
-
-@menu
-* The @code{store-link} protocol:: Store a link, push URL to kill-ring.
-* The @code{capture} protocol::  Fill a buffer with external information.
-* The @code{open-source} protocol:: Edit published contents.
-@end menu
-
-@node The @code{store-link} protocol
-@subsection The @code{store-link} protocol
-
-@cindex store-link protocol
-@cindex protocol, store-link
-
-Using the @code{store-link} handler, you can copy links, to that they can
-be inserted using @kbd{M-x org-insert-link} or yanking.  More
-precisely, the command
-
-@example
-emacsclient org-protocol://store-link?url=URL&title=TITLE
-@end example
-
-
-@noindent
-stores the following link:
-
-@example
-[[URL][TITLE]]
-@end example
-
-
-In addition, @var{URL} is pushed on the kill-ring for yanking.
-You need to encode @var{URL} and @var{TITLE} if they contain
-slashes, and probably quote those for the shell.
-
-To use this feature from a browser, add a bookmark with an arbitrary
-name, e.g., @samp{Org: store-link} and enter this as @emph{Location}:
-
-@example
-javascript:location.href='org-protocol://store-link?url='+
-      encodeURIComponent(location.href);
-@end example
-
-@node The @code{capture} protocol
-@subsection The @code{capture} protocol
-
-@cindex capture protocol
-@cindex protocol, capture
-
-Activating the ``capture'' handler pops up a @samp{Capture} buffer in Emacs,
-using acapture template.
-
-@example
-emacsclient org-protocol://capture?template=X?url=URL?title=TITLE?body=BODY
-@end example
-
-
-To use this feature, add a bookmark with an arbitrary name, e.g.,
-@samp{Org: capture}, and enter this as @samp{Location}:
-
-@example
-javascript:location.href='org-protocol://capture?template=x'+
-      '&url='+encodeURIComponent(window.location.href)+
-      '&title='+encodeURIComponent(document.title)+
-      '&body='+encodeURIComponent(window.getSelection());
-@end example
-
-@vindex org-protocol-default-template-key
-The capture template to be used can be specified in the bookmark (like
-@samp{X} above).  If unspecified, the template key is set in the variable
-@code{org-protocol-default-template-key}.  The following template
-placeholders are available:
-
-@example
-%:link          The URL
-%:description   The webpage title
-%:annotation    Equivalent to [[%:link][%:description]]
-%i              The selected text
-@end example
-
-@node The @code{open-source} protocol
-@subsection The @code{open-source} protocol
-
-@cindex open-source protocol
-@cindex protocol, open-source
-
-The @code{open-source} handler is designed to help with editing local
-sources when reading a document.  To that effect, you can use
-a bookmark with the following location:
-
-@example
-javascript:location.href='org-protocol://open-source?&url='+
-      encodeURIComponent(location.href)
-@end example
-
-@vindex org-protocol-project-alist
-The variable @code{org-protocol-project-alist} maps URLs to local file
-names, by stripping URL parameters from the end and replacing the
-@code{:base-url} with @code{:working-directory} and @code{:online-suffix} with
-@code{:working-suffix}.  For example, assuming you own a local copy of
-@samp{https://orgmode.org/worg/} contents at @samp{/home/user/worg}, you can 
set
-@code{org-protocol-project-alist} to the following
-
-@lisp
-(setq org-protocol-project-alist
-      '(("Worg"
-         :base-url "https://orgmode.org/worg/";
-         :working-directory "/home/user/worg/"
-         :online-suffix ".html"
-         :working-suffix ".org")))
-@end lisp
-
-@noindent
-If you are now browsing
-@samp{https://orgmode.org/worg/org-contrib/org-protocol.html} and find
-a typo or have an idea about how to enhance the documentation, simply
-click the bookmark and start editing.
-
-@cindex rewritten URL in open-source protocol
-@cindex protocol, open-source rewritten URL
-However, such mapping may not always yield the desired results.
-Suppose you maintain an online store located at @samp{http://example.com/}.
-The local sources reside in @samp{/home/user/example/}.  It is common
-practice to serve all products in such a store through one file and
-rewrite URLs that do not match an existing file on the server.  That
-way, a request to @samp{http://example.com/print/posters.html} might be
-rewritten on the server to something like
-@samp{http://example.com/shop/products.php/posters.html.php}.  The
-@code{open-source} handler probably cannot find a file named
-@samp{/home/user/example/print/posters.html.php} and fails.
-
-Such an entry in @code{org-protocol-project-alist} may hold an additional
-property @code{:rewrites}.  This property is a list of cons cells, each of
-which maps a regular expression to a path relative to the
-@code{:working-directory}.
-
-Now map the URL to the path @samp{/home/user/example/products.php} by
-adding @code{:rewrites} rules like this:
-
-@lisp
-(setq org-protocol-project-alist
-      '(("example.com"
-         :base-url "http://example.com/";
-         :working-directory "/home/user/example/"
-         :online-suffix ".php"
-         :working-suffix ".php"
-         :rewrites (("example.com/print/" . "products.php")
-                    ("example.com/$" . "index.php")))))
-@end lisp
-
-@noindent
-Since @samp{example.com/$} is used as a regular expression, it maps
-@samp{http://example.com/}, @samp{https://example.com},
-@samp{http://www.example.com/} and similar to
-@samp{/home/user/example/index.php}.
-
-The @code{:rewrites} rules are searched as a last resort if and only if no
-existing file name is matched.
-
-@cindex protocol, open-source, set-up mapping
-@cindex mappings in open-source protocol
-@findex org-protocol-create
-@findex org-protocol-create-for-org
-Two functions can help you filling @code{org-protocol-project-alist} with
-valid contents: @code{org-protocol-create} and
-@code{org-protocol-create-for-org}.  The latter is of use if you're editing
-an Org file that is part of a publishing project.
-
-@node Org Crypt
-@section Org Crypt
-
-Org Crypt encrypts the text of an entry, but not the headline, or
-properties.  Behind the scene, it uses the Emacs EasyPG library to
-encrypt and decrypt files.
-
-@vindex org-crypt-tag-matcher
-Any text below a headline that has a @samp{crypt} tag is automatically
-encrypted when the file is saved.  To use a different tag, customize
-the @code{org-crypt-tag-matcher} setting.
-
-Here is a suggestion for Org Crypt settings in Emacs init file:
-
-@lisp
-(require 'org-crypt)
-(org-crypt-use-before-save-magic)
-(setq org-tags-exclude-from-inheritance '("crypt"))
-
-(setq org-crypt-key nil)
-;; GPG key to use for encryption
-;; Either the Key ID or set to nil to use symmetric encryption.
-
-(setq auto-save-default nil)
-;; Auto-saving does not cooperate with org-crypt.el: so you need to
-;; turn it off if you plan to use org-crypt.el quite often.  Otherwise,
-;; you'll get an (annoying) message each time you start Org.
-
-;; To turn it off only locally, you can insert this:
-;;
-;; # -*- buffer-auto-save-file-name: nil; -*-
-@end lisp
-
-It's possible to use different keys for different headings by
-specifying the respective key as property @samp{CRYPTKEY}, e.g.:
-
-@example
-* Totally secret :crypt:
-  :PROPERTIES:
-  :CRYPTKEY: 0x0123456789012345678901234567890123456789
-  :END:
-@end example
-
-Excluding the @samp{crypt} tag from inheritance prevents already encrypted
-text from being encrypted again.
-
-@node Org Mobile
-@section Org Mobile
-
-@cindex smartphone
-
-Org Mobile is a protocol for synchronizing Org files between Emacs and
-other applications, e.g., on mobile devices.  It enables offline-views
-and capture support for an Org mode system that is rooted on a ``real''
-computer.  The external application can also record changes to
-existing entries.
-
-This appendix describes Org's support for agenda view formats
-compatible with Org Mobile.  It also describes synchronizing changes,
-such as to notes, between the mobile application and the computer.
-
-To change tags and TODO states in the mobile application, first
-customize the variables @code{org-todo-keywords}, @code{org-tag-alist} and
-@code{org-tag-persistent-alist}.  These should cover all the important tags
-and TODO keywords, even if Org files use only some of them.  Though
-the mobile application is expected to support in-buffer settings, it
-is required to understand TODO states @emph{sets} (see @ref{Per-file 
keywords}) and @emph{mutually exclusive} tags (see @ref{Setting Tags}) only for 
those set in these variables.
-
-@menu
-* Setting up the staging area::  For the mobile device.
-* Pushing to the mobile application:: Uploading Org files and agendas.
-* Pulling from the mobile application:: Integrating captured and flagged items.
-@end menu
-
-@node Setting up the staging area
-@subsection Setting up the staging area
-
-@vindex org-mobile-directory
-The mobile application needs access to a file directory on
-a server@footnote{For a server to host files, consider using a WebDAV server,
-such as @uref{https://nextcloud.com, Nextcloud}.  Additional help is at this 
@uref{https://orgmode.org/worg/org-faq.html#mobileorg_webdav, FAQ entry}.} to 
interact with Emacs.  Pass its location through
-the @code{org-mobile-directory} variable.  If you can mount that directory
-locally just set the variable to point to that directory:
-
-@lisp
-(setq org-mobile-directory "~/orgmobile/")
-@end lisp
-
-Alternatively, by using TRAMP (see @ref{Top,TRAMP User Manual,,tramp,}),
-@code{org-mobile-directory} may point to a remote directory accessible
-through, for example, SSH, SCP, or DAVS:
-
-@lisp
-(setq org-mobile-directory "/davs:user@@remote.host:/org/webdav/")
-@end lisp
-
-@vindex org-mobile-encryption
-With a public server, consider encrypting the files.  Org also
-requires OpenSSL installed on the local computer.  To turn on
-encryption, set the same password in the mobile application and in
-Emacs.  Set the password in the variable
-@code{org-mobile-use-encryption}@footnote{If Emacs is configured for safe 
storing of passwords, then
-configure the variable @code{org-mobile-encryption-password}; please read
-the docstring of that variable.}.  Note that even after the mobile
-application encrypts the file contents, the file name remains visible
-on the file systems of the local computer, the server, and the mobile
-device.
-
-@node Pushing to the mobile application
-@subsection Pushing to the mobile application
-
-@findex org-mobile-push
-@vindex org-mobile-files
-The command @code{org-mobile-push} copies files listed in
-@code{org-mobile-files} into the staging area.  Files include agenda files
-(as listed in @code{org-agenda-files}).  Customize @code{org-mobile-files} to
-add other files.  File names are staged with paths relative to
-@code{org-directory}, so all files should be inside this 
directory@footnote{Symbolic links in @code{org-directory} need to have the same 
name
-as their targets.}.
-
-Push creates a special Org file @samp{agendas.org} with custom agenda views
-defined by the user@footnote{While creating the agendas, Org mode forces 
@samp{ID} properties
-on all referenced entries, so that these entries can be uniquely
-identified if Org Mobile flags them for further action.  To avoid
-setting properties configure the variable
-@code{org-mobile-force-id-on-agenda-items} to @code{nil}.  Org mode then relies
-on outline paths, assuming they are unique.}.
-
-Finally, Org writes the file @samp{index.org}, containing links to other
-files.  The mobile application reads this file first from the server
-to determine what other files to download for agendas.  For faster
-downloads, it is expected to only read files whose 
checksums@footnote{Checksums are stored automatically in the file
-@samp{checksums.dat}.}
-have changed.
-
-@node Pulling from the mobile application
-@subsection Pulling from the mobile application
-
-@findex org-mobile-pull
-The command @code{org-mobile-pull} synchronizes changes with the server.
-More specifically, it first pulls the Org files for viewing.  It then
-appends captured entries and pointers to flagged or changed entries to
-the file @samp{mobileorg.org} on the server.  Org ultimately integrates its
-data in an inbox file format, through the following steps:
-
-@enumerate
-@item
-@vindex org-mobile-inbox-for-pull
-Org moves all entries found in @samp{mobileorg.org}@footnote{The file will be 
empty after this operation.} and appends
-them to the file pointed to by the variable
-@code{org-mobile-inbox-for-pull}.  It should reside neither in the
-staging area nor on the server.  Each captured entry and each
-editing event is a top-level entry in the inbox file.
-
-@item
-@cindex @samp{FLAGGED}, tag
-After moving the entries, Org processes changes to the shared
-files.  Some of them are applied directly and without user
-interaction.  Examples include changes to tags, TODO state,
-headline and body text.  Entries requiring further action are
-tagged as @samp{FLAGGED}.  Org marks entries with problems with an error
-message in the inbox.  They have to be resolved manually.
-
-@item
-Org generates an agenda view for flagged entries for user
-intervention to clean up.  For notes stored in flagged entries, Org
-displays them in the echo area when point is on the corresponding
-agenda item.
-
-@table @asis
-@item @kbd{?}
-Pressing @kbd{?} displays the entire flagged note in another
-window.  Org also pushes it to the kill ring.  To store flagged
-note as a normal note, use @kbd{? z C-y C-c C-c}.  Pressing
-@kbd{?} twice does these things: first it removes the
-@samp{FLAGGED} tag; second, it removes the flagged note from the
-property drawer; third, it signals that manual editing of the
-flagged entry is now finished.
-@end table
-@end enumerate
-
-@kindex ? @r{(Agenda dispatcher)}
-From the agenda dispatcher, @kbd{?} returns to the view to finish
-processing flagged entries.  Note that these entries may not be the
-most recent since the mobile application searches files that were last
-pulled.  To get an updated agenda view with changes since the last
-pull, pull again.
-
-@node Hacking
-@appendix Hacking
-
-@cindex hacking
-
-This appendix describes some ways a user can extend the functionality
-of Org.
-
-@menu
-* Hooks: Hooks (2).              How to reach into Org's internals.
-* Add-on Packages::              Available extensions.
-* Adding Hyperlink Types::       New custom link types.
-* Adding Export Back-ends::      How to write new export back-ends.
-* Tables in Arbitrary Syntax::   Orgtbl for LaTeX and other programs.
-* Dynamic Blocks::               Automatically filled blocks.
-* Special Agenda Views::         Customized views.
-* Speeding Up Your Agendas::     Tips on how to speed up your agendas.
-* Extracting Agenda Information:: Post-processing agenda information.
-* Using the Property API::       Writing programs that use entry properties.
-* Using the Mapping API::        Mapping over all or selected entries.
-@end menu
-
-@node Hooks (2)
-@appendixsec Hooks
-
-@cindex hooks
-
-Org has a large number of hook variables for adding functionality.
-This appendix illustrates using a few.  A complete list of hooks with
-documentation is maintained by the Worg project at
-@uref{https://orgmode.org/worg/doc.html#hooks}.
-
-@node Add-on Packages
-@appendixsec Add-on Packages
-
-@cindex add-on packages
-
-Various authors wrote a large number of add-on packages for Org.
-
-These packages are not part of Emacs, but they are distributed as
-contributed packages with the separate release available at
-@uref{https://orgmode.org}.  See the @samp{contrib/README} file in the source 
code
-directory for a list of contributed files.  Worg page with more
-information is at: @uref{https://orgmode.org/worg/org-contrib/}.
-
-@node Adding Hyperlink Types
-@appendixsec Adding Hyperlink Types
-
-@cindex hyperlinks, adding new types
-
-Org has many built-in hyperlink types (see @ref{Hyperlinks}), and an
-interface for adding new link types.  The following example shows the
-process of adding Org links to Unix man pages, which look like this
-
-@example
-[[man:printf][The printf manual]]
-@end example
-
-
-@noindent
-The following @samp{ol-man.el} file implements it
-
-@lisp
-;;; ol-man.el - Support for links to man pages in Org mode
-(require 'ol)
-
-(org-link-set-parameters "man"
-                         :follow #'org-man-open
-                         :export #'org-man-export
-                         :store #'org-man-store-link)
-
-(defcustom org-man-command 'man
-  "The Emacs command to be used to display a man page."
-  :group 'org-link
-  :type '(choice (const man) (const woman)))
-
-(defun org-man-open (path _)
-  "Visit the manpage on PATH.
-PATH should be a topic that can be thrown at the man command."
-  (funcall org-man-command path))
-
-(defun org-man-store-link ()
-  "Store a link to a man page."
-  (when (memq major-mode '(Man-mode woman-mode))
-    ;; This is a man page, we do make this link.
-    (let* ((page (org-man-get-page-name))
-           (link (concat "man:" page))
-           (description (format "Man page for %s" page)))
-      (org-link-store-props
-       :type "man"
-       :link link
-       :description description))))
-
-(defun org-man-get-page-name ()
-  "Extract the page name from the buffer name."
-  ;; This works for both `Man-mode' and `woman-mode'.
-  (if (string-match " \\(\\S-+\\)\\*" (buffer-name))
-      (match-string 1 (buffer-name))
-    (error "Cannot create link to this man page")))
-
-(defun org-man-export (link description format _)
-  "Export a man page link from Org files."
-  (let ((path (format "http://man.he.net/?topic=%s&section=all"; link))
-        (desc (or description link)))
-    (pcase format
-      (`html (format "<a target=\"_blank\" href=\"%s\">%s</a>" path desc))
-      (`latex (format "\\href@{%s@}@{%s@}" path desc))
-      (`texinfo (format "@@uref@{%s,%s@}" path desc))
-      (`ascii (format "%s (%s)" desc path))
-      (t path))))
-
-(provide ol-man)
-;;; ol-man.el ends here
-@end lisp
-
-@noindent
-To activate links to man pages in Org, enter this in the Emacs init
-file:
-
-@lisp
-(require 'ol-man)
-@end lisp
-
-@noindent
-A review of @samp{ol-man.el}:
-
-@enumerate
-@item
-First, @samp{(require 'ol)} ensures that @samp{ol.el} is loaded.
-
-@item
-@findex org-link-set-parameters
-@vindex org-link-parameters
-Then @code{org-link-set-parameters} defines a new link type with @samp{man}
-prefix and associates functions for following, exporting and
-storing such links.  See the variable @code{org-link-parameters} for
-a complete list of possible associations.
-
-@item
-The rest of the file implements necessary variables and functions.
-
-For example, @code{org-man-store-link} is responsible for storing a link
-when @code{org-store-link} (see @ref{Handling Links}) is called from a buffer
-displaying a man page.  It first checks if the major mode is
-appropriate.  If check fails, the function returns @code{nil}, which
-means it isn't responsible for creating a link to the current
-buffer.  Otherwise the function makes a link string by combining
-the @samp{man:} prefix with the man topic.  It also provides a default
-description.  The function @code{org-insert-link} can insert it back
-into an Org buffer later on.
-@end enumerate
-
-@node Adding Export Back-ends
-@appendixsec Adding Export Back-ends
-
-@cindex Export, writing back-ends
-
-Org's export engine makes it easy for writing new back-ends.  The
-framework on which the engine was built makes it easy to derive new
-back-ends from existing ones.
-
-@findex org-export-define-backend
-@findex org-export-define-derived-backend
-The two main entry points to the export engine are:
-@code{org-export-define-backend} and @code{org-export-define-derived-backend}.
-To grok these functions, see @samp{ox-latex.el} for an example of defining
-a new back-end from scratch, and @samp{ox-beamer.el} for an example of
-deriving from an existing engine.
-
-For creating a new back-end from scratch, first set its name as
-a symbol in an alist consisting of elements and export functions.  To
-make the back-end visible to the export dispatcher, set @code{:menu-entry}
-keyword.  For export options specific to this back-end, set the
-@code{:options-alist}.
-
-For creating a new back-end from an existing one, set
-@code{:translate-alist} to an alist of export functions.  This alist
-replaces the parent back-end functions.
-
-For complete documentation, see 
@uref{https://orgmode.org/worg/dev/org-export-reference.html, the Org Export 
Reference on Worg}.
-
-@node Tables in Arbitrary Syntax
-@appendixsec Tables in Arbitrary Syntax
-
-@cindex tables, in other modes
-@cindex lists, in other modes
-@cindex Orgtbl mode
-
-Due to Org's success in handling tables with Orgtbl, a frequently
-requested feature is the use of Org's table functions in other modes,
-e.g., @LaTeX{}.  This would be hard to do in a general way without
-complicated customization nightmares.  Moreover, that would take Org
-away from its simplicity roots that Orgtbl has proven.  There is,
-however, an alternate approach to accomplishing the same.
-
-This approach involves implementing a custom @emph{translate} function that
-operates on a native Org @emph{source table} to produce a table in another
-format.  This strategy would keep the excellently working Orgtbl
-simple and isolate complications, if any, confined to the translate
-function.  To add more alien table formats, we just add more translate
-functions.  Also the burden of developing custom translate functions
-for new table formats is in the hands of those who know those formats
-best.
-
-@menu
-* Radio tables::                 Sending and receiving radio tables.
-* A @LaTeX{} example::           Step by step, almost a tutorial.
-* Translator functions::         Copy and modify.
-@end menu
-
-@node Radio tables
-@appendixsubsec Radio tables
-
-@cindex radio tables
-
-Radio tables are target locations for translated tables that are not near
-their source.  Org finds the target location and inserts the translated
-table.
-
-The key to finding the target location is the magic words @samp{BEGIN/END
-RECEIVE ORGTBL}.  They have to appear as comments in the current mode.
-If the mode is C, then:
-
-@example
-/* BEGIN RECEIVE ORGTBL table_name */
-/* END RECEIVE ORGTBL table_name */
-@end example
-
-At the location of source, Org needs a special line to direct Orgtbl
-to translate and to find the target for inserting the translated
-table.  For example:
-
-@cindex @samp{ORGTBL}, keyword
-@example
-#+ORGTBL: SEND table_name translation_function arguments ...
-@end example
-
-
-@noindent
-@samp{table_name} is the table's reference name, which is also used in the
-receiver lines, and the @samp{translation_function} is the Lisp function
-that translates.  This line, in addition, may also contain alternating
-key and value arguments at the end.  The translation function gets
-these values as a property list.  A few standard parameters are
-already recognized and acted upon before the translation function is
-called:
-
-@table @asis
-@item @samp{:skip N}
-Skip the first N lines of the table.  Hlines do count; include them
-if they are to be skipped.
-
-@item @samp{:skipcols (n1 n2 ...)}
-List of columns to be skipped.  First Org automatically discards
-columns with calculation marks and then sends the table to the
-translator function, which then skips columns as specified in
-@samp{skipcols}.
-@end table
-
-To keep the source table intact in the buffer without being disturbed
-when the source file is compiled or otherwise being worked on, use one
-of these strategies:
-
-@itemize
-@item
-Place the table in a block comment.  For example, in C mode you
-could wrap the table between @samp{/*} and @samp{*/} lines.
-
-@item
-Put the table after an ``end'' statement.  For example @code{\bye} in @TeX{}
-and @code{\end@{document@}} in @LaTeX{}.
-
-@item
-Comment and un-comment each line of the table during edits.  The
-@kbd{M-x orgtbl-toggle-comment} command makes toggling easy.
-@end itemize
-
-@node A @LaTeX{} example
-@appendixsubsec A @LaTeX{} example of radio tables
-
-@cindex @LaTeX{}, and Orgtbl mode
-
-To wrap a source table in @LaTeX{}, use the @samp{comment} environment
-provided by 
@samp{comment.sty}@footnote{@uref{https://www.ctan.org/pkg/comment}}.  To 
activate it, put
-@code{\usepackage@{comment@}} in the document header.  Orgtbl mode inserts
-a radio table skeleton@footnote{By default this works only for @LaTeX{}, HTML, 
and Texinfo.
-Configure the variable @code{orgtbl-radio-table-templates} to install
-templates for other modes.} with the command @kbd{M-x 
orgtbl-insert-radio-table}, which prompts for a table name.  For
-example, if @samp{salesfigures} is the name, the template inserts:
-
-@example
-% BEGIN RECEIVE ORGTBL salesfigures
-% END RECEIVE ORGTBL salesfigures
-\begin@{comment@}
-#+ORGTBL: SEND salesfigures orgtbl-to-latex
-| | |
-\end@{comment@}
-@end example
-
-@vindex LaTeX-verbatim-environments
-@noindent
-The line @samp{#+ORGTBL: SEND} tells Orgtbl mode to use the function
-@code{orgtbl-to-latex} to convert the table to @LaTeX{} format, then insert
-the table at the target (receive) location named @samp{salesfigures}.  Now
-the table is ready for data entry.  It can even use spreadsheet
-features@footnote{If the @samp{TBLFM} keyword contains an odd number of dollar
-characters, this may cause problems with Font Lock in @LaTeX{} mode.  As
-shown in the example you can fix this by adding an extra line inside
-the @samp{comment} environment that is used to balance the dollar
-expressions.  If you are using AUC@TeX{} with the font-latex library,
-a much better solution is to add the @samp{comment} environment to the
-variable @code{LaTeX-verbatim-environments}.}:
-
-@example
-% BEGIN RECEIVE ORGTBL salesfigures
-% END RECEIVE ORGTBL salesfigures
-\begin@{comment@}
-#+ORGTBL: SEND salesfigures orgtbl-to-latex
-| Month | Days | Nr sold | per day |
-|-------+------+---------+---------|
-| Jan   |   23 |      55 |     2.4 |
-| Feb   |   21 |      16 |     0.8 |
-| March |   22 |     278 |    12.6 |
-#+TBLFM: $4=$3/$2;%.1f
-% $ (optional extra dollar to keep Font Lock happy, see footnote)
-\end@{comment@}
-@end example
-
-After editing, @kbd{C-c C-c} inserts the translated table at the
-target location, between the two marker lines.
-
-For hand-made custom tables, note that the translator needs to skip
-the first two lines of the source table.  Also the command has to
-@emph{splice} out the target table without the header and footer.
-
-@example
-\begin@{tabular@}@{lrrr@}
-Month & \multicolumn@{1@}@{c@}@{Days@} & Nr.\ sold & per day\\
-% BEGIN RECEIVE ORGTBL salesfigures
-% END RECEIVE ORGTBL salesfigures
-\end@{tabular@}
-%
-\begin@{comment@}
-#+ORGTBL: SEND salesfigures orgtbl-to-latex :splice t :skip 2
-| Month | Days | Nr sold | per day |
-|-------+------+---------+---------|
-| Jan   |   23 |      55 |     2.4 |
-| Feb   |   21 |      16 |     0.8 |
-| March |   22 |     278 |    12.6 |
-#+TBLFM: $4=$3/$2;%.1f
-\end@{comment@}
-@end example
-
-The @LaTeX{} translator function @code{orgtbl-to-latex} is already part of
-Orgtbl mode and uses a @samp{tabular} environment to typeset the table and
-marks horizontal lines with @code{\hline}.  For additional parameters to
-control output, see @ref{Translator functions}:
-
-@table @asis
-@item @samp{:splice BOOLEAN}
-When @{@{@{var(BOOLEAN@}@}@} is non-@code{nil}, return only table body lines;
-i.e., not wrapped in @samp{tabular} environment.  Default is @code{nil}.
-
-@item @samp{:fmt FMT}
-Format string to warp each field.  It should contain @samp{%s} for the
-original field value.  For example, to wrap each field value in
-dollar symbol, you could use @samp{:fmt "$%s$"}.  Format can also wrap
-a property list with column numbers and formats, for example @samp{:fmt
-  (2 "$%s$" 4 "%s\\%%")}.  In place of a string, a function of one
-argument can be used; the function must return a formatted string.
-
-@item @samp{:efmt EFMT}
-Format numbers as exponentials.  The spec should have @samp{%s} twice for
-inserting mantissa and exponent, for example @samp{"%s\\times10^@{%s@}"}.  This
-may also be a property list with column numbers and formats, for
-example @samp{:efmt (2 "$%s\\times10^@{%s@}$" 4 "$%s\\cdot10^@{%s@}$")}.  After
-@var{EFMT} has been applied to a value, @var{FMT}---see
-above---is also applied.  Functions with two arguments can be
-supplied instead of strings.  By default, no special formatting is
-applied.
-@end table
-
-@node Translator functions
-@appendixsubsec Translator functions
-
-@cindex HTML, and Orgtbl mode
-@cindex translator function
-
-@findex orgtbl-to-csv
-@findex orgtbl-to-tsv
-@findex orgtbl-to-latex
-@findex orgtbl-to-html
-@findex orgtbl-to-texinfo
-@findex orgtbl-to-unicode
-@findex orgtbl-to-orgtbl
-@findex orgtbl-to-generic
-Orgtbl mode has built-in translator functions: @code{orgtbl-to-csv}
-(comma-separated values), @code{orgtbl-to-tsv} (TAB-separated values),
-@code{orgtbl-to-latex}, @code{orgtbl-to-html}, @code{orgtbl-to-texinfo},
-@code{orgtbl-to-unicode} and @code{orgtbl-to-orgtbl}.  They use the generic
-translator, @code{orgtbl-to-generic}, which delegates translations to
-various export back-ends.
-
-Properties passed to the function through the @samp{ORGTBL SEND} line take
-precedence over properties defined inside the function.  For example,
-this overrides the default @LaTeX{} line endings, @code{\\}, with 
@code{\\[2mm]}:
-
-@example
-#+ORGTBL: SEND test orgtbl-to-latex :lend " \\\\[2mm]"
-@end example
-
-
-For a new language translator, define a converter function.  It can be
-a generic function, such as shown in this example.  It marks
-a beginning and ending of a table with @samp{!BTBL!} and @samp{!ETBL!};
-a beginning and ending of lines with @samp{!BL!} and @samp{!EL!}; and uses a 
TAB
-for a field separator:
-
-@lisp
-(defun orgtbl-to-language (table params)
-  "Convert the orgtbl-mode TABLE to language."
-  (orgtbl-to-generic
-   table
-   (org-combine-plists
-    '(:tstart "!BTBL!" :tend "!ETBL!" :lstart "!BL!" :lend "!EL!" :sep "\t")
-    params)))
-@end lisp
-
-@noindent
-The documentation for the @code{orgtbl-to-generic} function shows
-a complete list of parameters, each of which can be passed through to
-@code{orgtbl-to-latex}, @code{orgtbl-to-texinfo}, and any other function using
-that generic function.
-
-For complicated translations the generic translator function could be
-replaced by a custom translator function.  Such a custom function must
-take two arguments and return a single string containing the formatted
-table.  The first argument is the table whose lines are a list of
-fields or the symbol @code{hline}.  The second argument is the property
-list consisting of parameters specified in the @samp{#+ORGTBL: SEND} line.
-Please share your translator functions by posting them to the Org
-users mailing list, at @email{emacs-orgmode@@gnu.org}.
-
-@node Dynamic Blocks
-@appendixsec Dynamic Blocks
-
-@cindex dynamic blocks
-
-Org supports @emph{dynamic blocks} in Org documents.  They are inserted
-with begin and end markers like any other code block, but the contents
-are updated automatically by a user function.
-
-@kindex C-c C-x x
-@findex org-dynamic-block-insert-dblock
-You can insert a dynamic block with @code{org-dynamic-block-insert-dblock},
-which is bound to @kbd{C-c C-x x} by default.  For example,
-@kbd{C-c C-x x c l o c k t a b l e @key{RET}} inserts a table that
-updates the work time (see @ref{Clocking Work Time}).
-
-Dynamic blocks can have names and function parameters.  The syntax is
-similar to source code block specifications:
-
-@example
-#+BEGIN: myblock :parameter1 value1 :parameter2 value2 ...
-  ...
-#+END:
-@end example
-
-These commands update dynamic blocks:
-
-@table @asis
-@item @kbd{C-c C-x C-u} (@code{org-dblock-update})
-@kindex C-c C-x C-u
-@findex org-dblock-update
-Update dynamic block at point.
-
-@item @kbd{C-u C-c C-x C-u}
-@kindex C-u C-c C-x C-u
-Update all dynamic blocks in the current file.
-@end table
-
-Before updating a dynamic block, Org removes content between the
-@samp{BEGIN} and @samp{END} markers.  Org then reads the parameters on the
-@samp{BEGIN} line for passing to the writer function as a plist.  The
-previous content of the dynamic block becomes erased from the buffer
-and appended to the plist under @code{:content}.
-
-The syntax for naming a writer function with a dynamic block labeled
-@samp{myblock} is: @code{org-dblock-write:myblock}.
-
-The following is an example of a dynamic block and a block writer function
-that updates the time when the function was last run:
-
-@example
-#+BEGIN: block-update-time :format "on %m/%d/%Y at %H:%M"
-  ...
-#+END:
-@end example
-
-@noindent
-The dynamic block's writer function:
-
-@lisp
-(defun org-dblock-write:block-update-time (params)
-  (let ((fmt (or (plist-get params :format) "%d. %m. %Y")))
-    (insert "Last block update at: "
-            (format-time-string fmt))))
-@end lisp
-
-To keep dynamic blocks up-to-date in an Org file, use the function,
-@code{org-update-all-dblocks} in hook, such as @code{before-save-hook}.  The
-@code{org-update-all-dblocks} function does not run if the file is not in
-Org mode.
-
-@findex org-narrow-to-block
-Dynamic blocks, like any other block, can be narrowed with
-@code{org-narrow-to-block}.
-
-@node Special Agenda Views
-@appendixsec Special Agenda Views
-
-@cindex agenda views, user-defined
-
-@vindex org-agenda-skip-function
-@vindex org-agenda-skip-function-global
-Org provides a special hook to further limit items in agenda views:
-@code{agenda}, @code{agenda*}@footnote{The @code{agenda*} view is the same as 
@code{agenda} except that it
-only considers @emph{appointments}, i.e., scheduled and deadline items that
-have a time specification @samp{[h]h:mm} in their time-stamps.}, @code{todo}, 
@code{alltodo}, @code{tags}, @code{tags-todo},
-@code{tags-tree}.  Specify a custom function that tests inclusion of every
-matched item in the view.  This function can also skip as much as is
-needed.
-
-For a global condition applicable to agenda views, use the
-@code{org-agenda-skip-function-global} variable.  Org uses a global
-condition with @code{org-agenda-skip-function} for custom searching.
-
-This example defines a function for a custom view showing TODO items
-with @samp{waiting} status.  Manually this is a multi-step search process,
-but with a custom view, this can be automated as follows:
-
-The custom function searches the subtree for the @samp{waiting} tag and
-returns @code{nil} on match.  Otherwise it gives the location from where
-the search continues.
-
-@lisp
-(defun my-skip-unless-waiting ()
-  "Skip trees that are not waiting"
-  (let ((subtree-end (save-excursion (org-end-of-subtree t))))
-    (if (re-search-forward ":waiting:" subtree-end t)
-        nil          ; tag found, do not skip
-      subtree-end))) ; tag not found, continue after end of subtree
-@end lisp
-
-To use this custom function in a custom agenda command:
-
-@lisp
-(org-add-agenda-custom-command
- '("b" todo "PROJECT"
-   ((org-agenda-skip-function 'my-skip-unless-waiting)
-    (org-agenda-overriding-header "Projects waiting for something: "))))
-@end lisp
-
-@vindex org-agenda-overriding-header
-Note that this also binds @code{org-agenda-overriding-header} to a more
-meaningful string suitable for the agenda view.
-
-@vindex org-odd-levels-only
-@vindex org-agenda-skip-function
-Search for entries with a limit set on levels for the custom search.
-This is a general approach to creating custom searches in Org.  To
-include all levels, use @samp{LEVEL>0}@footnote{Note that, for 
@code{org-odd-levels-only}, a level number
-corresponds to order in the hierarchy, not to the number of stars.}.  Then to 
selectively pick
-the matched entries, use @code{org-agenda-skip-function}, which also
-accepts Lisp forms, such as @code{org-agenda-skip-entry-if} and
-@code{org-agenda-skip-subtree-if}.  For example:
-
-@table @asis
-@item @samp{(org-agenda-skip-entry-if 'scheduled)}
-Skip current entry if it has been scheduled.
-
-@item @samp{(org-agenda-skip-entry-if 'notscheduled)}
-Skip current entry if it has not been scheduled.
-
-@item @samp{(org-agenda-skip-entry-if 'deadline)}
-Skip current entry if it has a deadline.
-
-@item @samp{(org-agenda-skip-entry-if 'scheduled 'deadline)}
-Skip current entry if it has a deadline, or if it is scheduled.
-
-@item @samp{(org-agenda-skip-entry-if 'todo '("TODO" "WAITING"))}
-Skip current entry if the TODO keyword is TODO or WAITING@.
-
-@item @samp{(org-agenda-skip-entry-if 'todo 'done)}
-Skip current entry if the TODO keyword marks a DONE state.
-
-@item @samp{(org-agenda-skip-entry-if 'timestamp)}
-Skip current entry if it has any timestamp, may also be deadline or
-scheduled.
-
-@item @samp{(org-agenda-skip-entry-if 'regexp "regular expression")}
-Skip current entry if the regular expression matches in the entry.
-
-@item @samp{(org-agenda-skip-entry-if 'notregexp "regular expression")}
-Skip current entry unless the regular expression matches.
-
-@item @samp{(org-agenda-skip-subtree-if 'regexp "regular expression")}
-Same as above, but check and skip the entire subtree.
-@end table
-
-The following is an example of a search for @samp{waiting} without the
-special function:
-
-@lisp
-(org-add-agenda-custom-command
- '("b" todo "PROJECT"
-   ((org-agenda-skip-function '(org-agenda-skip-subtree-if
-                                'regexp ":waiting:"))
-    (org-agenda-overriding-header "Projects waiting for something: "))))
-@end lisp
-
-@node Speeding Up Your Agendas
-@appendixsec Speeding Up Your Agendas
-
-@cindex agenda views, optimization
-
-Some agenda commands slow down when the Org files grow in size or
-number.  Here are tips to speed up:
-
-@itemize
-@item
-Reduce the number of Org agenda files to avoid slowdowns due to hard drive
-accesses.
-
-@item
-Reduce the number of DONE and archived headlines so agenda
-operations that skip over these can finish faster.
-
-@item
-Do not dim blocked tasks:
-@vindex org-agenda-dim-blocked-tasks
-
-@lisp
-(setq org-agenda-dim-blocked-tasks nil)
-@end lisp
-
-@item
-Stop preparing agenda buffers on startup:
-@vindex org-startup-folded
-@vindex org-agenda-inhibit-startup
-
-@lisp
-(setq org-agenda-inhibit-startup t)
-@end lisp
-
-@item
-Disable tag inheritance for agendas:
-@vindex org-agenda-show-inherited-tags
-@vindex org-agenda-use-tag-inheritance
-
-@lisp
-(setq org-agenda-use-tag-inheritance nil)
-@end lisp
-@end itemize
-
-These options can be applied to selected agenda views.  For more
-details about generation of agenda views, see the docstrings for the
-relevant variables, and this 
@uref{https://orgmode.org/worg/agenda-optimization.html, dedicated Worg page} 
for agenda
-optimization.
-
-@node Extracting Agenda Information
-@appendixsec Extracting Agenda Information
-
-@cindex agenda, pipe
-@cindex scripts, for agenda processing
-
-Org provides commands to access agendas through Emacs batch mode.
-Through this command-line interface, agendas are automated for further
-processing or printing.
-
-@vindex org-agenda-custom-commands
-@findex org-batch-agenda
-@code{org-batch-agenda} creates an agenda view in ASCII and outputs to
-standard output.  This command takes one string parameter.  When
-string consists of a single character, Org uses it as a key to
-@code{org-agenda-custom-commands}.  These are the same ones available
-through the agenda dispatcher (see @ref{Agenda Dispatcher}).
-
-This example command line directly prints the TODO list to the printer:
-
-@example
-emacs -batch -l ~/.emacs -eval '(org-batch-agenda "t")' | lpr
-@end example
-
-
-When the string parameter length is two or more characters, Org
-matches it with tags/TODO strings.  For example, this example command
-line prints items tagged with @samp{shop}, but excludes items tagged with
-@samp{NewYork}:
-
-@example
-emacs -batch -l ~/.emacs                                      \
-      -eval '(org-batch-agenda "+shop-NewYork")' | lpr
-@end example
-
-@noindent
-An example showing on-the-fly parameter modifications:
-
-@example
-emacs -batch -l ~/.emacs                                      \
-   -eval '(org-batch-agenda "a"                               \
-           org-agenda-span (quote month)                      \
-           org-agenda-include-diary nil                       \
-           org-agenda-files (quote ("~/org/project.org")))'   \
-   | lpr
-@end example
-
-@noindent
-which produces an agenda for the next 30 days from just the
-@samp{~/org/projects.org} file.
-
-@findex org-batch-agenda-csv
-For structured processing of agenda output, use @code{org-batch-agenda-csv}
-with the following fields:
-
-@table @asis
-@item category
-The category of the item
-@item head
-The headline, without TODO keyword, TAGS and PRIORITY
-@item type
-The type of the agenda entry, can be
-
-@multitable {aaaaaaaaaaaaaaaaaaa} {aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa}
-@item @code{todo}
-@tab selected in TODO match
-@item @code{tagsmatch}
-@tab selected in tags match
-@item @code{diary}
-@tab imported from diary
-@item @code{deadline}
-@tab a deadline
-@item @code{scheduled}
-@tab scheduled
-@item @code{timestamp}
-@tab appointment, selected by timestamp
-@item @code{closed}
-@tab entry was closed on date
-@item @code{upcoming-deadline}
-@tab warning about nearing deadline
-@item @code{past-scheduled}
-@tab forwarded scheduled item
-@item @code{block}
-@tab entry has date block including date
-@end multitable
-
-@item todo
-The TODO keyword, if any
-@item tags
-All tags including inherited ones, separated by colons
-@item date
-The relevant date, like @samp{2007-2-14}
-@item time
-The time, like @samp{15:00-16:50}
-@item extra
-String with extra planning info
-@item priority-l
-The priority letter if any was given
-@item priority-n
-The computed numerical priority
-@end table
-
-If the selection of the agenda item was based on a timestamp,
-including those items with @samp{DEADLINE} and @samp{SCHEDULED} keywords, then
-Org includes date and time in the output.
-
-If the selection of the agenda item was based on a timestamp  (or
-deadline/scheduled), then Org includes date and time in the output.
-
-Here is an example of a post-processing script in Perl.  It takes the
-CSV output from Emacs and prints with a checkbox:
-
-@example
-#!/usr/bin/perl
-
-# define the Emacs command to run
-$cmd = "emacs -batch -l ~/.emacs -eval '(org-batch-agenda-csv \"t\")'";
-
-# run it and capture the output
-$agenda = qx@{$cmd 2>/dev/null@};
-
-# loop over all lines
-foreach $line (split(/\n/,$agenda)) @{
-    # get the individual values
-    ($category,$head,$type,$todo,$tags,$date,$time,$extra,
-     $priority_l,$priority_n) = split(/,/,$line);
-    # process and print
-    print "[ ] $head\n";
-@}
-@end example
-
-@node Using the Property API
-@appendixsec Using the Property API
-
-@cindex API, for properties
-@cindex properties, API
-
-Here is a description of the functions that can be used to work with
-properties.
-
-@defun org-entry-properties &optional pom which
-Get all properties of the entry at point-or-marker @var{POM}.
-This includes the TODO keyword, the tags, time strings for deadline,
-scheduled, and clocking, and any additional properties defined in the
-entry.  The return value is an alist.  Keys may occur multiple times
-if the property key was used several times.  @var{POM} may also
-be @code{nil}, in which case the current entry is used.  If
-@var{WHICH} is @code{nil} or @code{all}, get all properties.  If
-@var{WHICH} is @code{special} or @code{standard}, only get that subclass.
-@end defun
-
-@vindex org-use-property-inheritance
-@findex org-insert-property-drawer
-@defun org-entry-get pom property &optional inherit
-Get value of @var{PROPERTY} for entry at point-or-marker
-@var{POM}.  By default, this only looks at properties defined
-locally in the entry.  If @var{INHERIT} is non-@code{nil} and the
-entry does not have the property, then also check higher levels of the
-hierarchy.  If @var{INHERIT} is the symbol @code{selective}, use
-inheritance if and only if the setting of
-@code{org-use-property-inheritance} selects @var{PROPERTY} for
-inheritance.
-@end defun
-
-@defun org-entry-delete pom property
-Delete the property @var{PROPERTY} from entry at point-or-marker
-@var{POM}.
-@end defun
-
-@defun org-entry-put pom property value
-Set @var{PROPERTY} to @var{VALUES} for entry at
-point-or-marker POM@.
-@end defun
-
-@defun org-buffer-property-keys &optional include-specials
-Get all property keys in the current buffer.
-@end defun
-
-@defun org-insert-property-drawer
-Insert a property drawer for the current entry.  Also
-@end defun
-
-@defun org-entry-put-multivalued-property pom property &rest values
-Set @var{PROPERTY} at point-or-marker @var{POM} to
-@var{VALUES}.  @var{VALUES} should be a list of strings.
-They are concatenated, with spaces as separators.
-@end defun
-
-@defun org-entry-get-multivalued-property pom property
-Treat the value of the property @var{PROPERTY} as
-a whitespace-separated list of values and return the values as a list
-of strings.
-@end defun
-
-@defun org-entry-add-to-multivalued-property pom property value
-Treat the value of the property @var{PROPERTY} as
-a whitespace-separated list of values and make sure that
-@var{VALUE} is in this list.
-@end defun
-
-@defun org-entry-remove-from-multivalued-property pom property value
-Treat the value of the property @var{PROPERTY} as
-a whitespace-separated list of values and make sure that
-@var{VALUE} is @emph{not} in this list.
-@end defun
-
-@defun org-entry-member-in-multivalued-property pom property value
-Treat the value of the property @var{PROPERTY} as
-a whitespace-separated list of values and check if @var{VALUE} is
-in this list.
-@end defun
-
-@defopt org-property-allowed-value-functions
-Hook for functions supplying allowed values for a specific property.
-The functions must take a single argument, the name of the property,
-and return a flat list of allowed values.  If @samp{:ETC} is one of the
-values, use the values as completion help, but allow also other values
-to be entered.  The functions must return @code{nil} if they are not
-responsible for this property.
-@end defopt
-
-@node Using the Mapping API
-@appendixsec Using the Mapping API
-
-@cindex API, for mapping
-@cindex mapping entries, API
-
-Org has sophisticated mapping capabilities to find all entries
-satisfying certain criteria.  Internally, this functionality is used
-to produce agenda views, but there is also an API that can be used to
-execute arbitrary functions for each or selected entries.  The main
-entry point for this API is:
-
-@defun org-map-entries func &optional match scope &rest skip
-Call @var{FUNC} at each headline selected by @var{MATCH} in
-@var{SCOPE}.
-
-@var{FUNC} is a function or a Lisp form.  With point positioned
-at the beginning of the headline, call the function without arguments.
-Org returns an alist of return values of calls to the function.
-
-To avoid preserving point, Org wraps the call to @var{FUNC} in
-@code{save-excursion} form.  After evaluation, Org moves point to the end
-of the line that was just processed.  Search continues from that point
-forward.  This may not always work as expected under some conditions,
-such as if the current sub-tree was removed by a previous archiving
-operation.  In such rare circumstances, Org skips the next entry
-entirely when it should not.  To stop Org from such skips, make
-@var{FUNC} set the variable @code{org-map-continue-from} to a specific
-buffer position.
-
-@var{MATCH} is a tags/property/TODO match.  Org iterates only
-matched headlines.  Org iterates over all headlines when
-@var{MATCH} is @code{nil} or @code{t}.
-
-@var{SCOPE} determines the scope of this command.  It can be any
-of:
-
-@table @asis
-@item @code{nil}
-The current buffer, respecting the restriction, if any.
-
-@item @code{tree}
-The subtree started with the entry at point.
-
-@item @code{region}
-The entries within the active region, if any.
-
-@item @code{file}
-The current buffer, without restriction.
-
-@item @code{file-with-archives}
-The current buffer, and any archives associated with it.
-
-@item @code{agenda}
-All agenda files.
-
-@item @code{agenda-with-archives}
-All agenda files with any archive files associated with them.
-
-@item list of filenames
-If this is a list, all files in the list are scanned.
-@end table
-
-@noindent
-The remaining arguments are treated as settings for the scanner's
-skipping facilities.  Valid arguments are:
-
-@table @asis
-@item @code{archive}
-Skip trees with the @samp{ARCHIVE} tag.
-
-@item @code{comment}
-Skip trees with the COMMENT keyword.
-
-@item function or Lisp form
-@vindex org-agenda-skip-function
-Used as value for @code{org-agenda-skip-function}, so whenever the
-function returns @code{t}, @var{FUNC} is called for that entry and
-search continues from the point where the function leaves it.
-@end table
-@end defun
-
-The mapping routine can call any arbitrary function, even functions
-that change meta data or query the property API (see @ref{Using the Property 
API}).  Here are some handy functions:
-
-@defun org-todo &optional arg
-Change the TODO state of the entry.  See the docstring of the
-functions for the many possible values for the argument
-@var{ARG}.
-@end defun
-
-@defun org-priority &optional action
-Change the priority of the entry.  See the docstring of this function
-for the possible values for @var{ACTION}.
-@end defun
-
-@defun org-toggle-tag tag &optional onoff
-Toggle the tag @var{TAG} in the current entry.  Setting
-@var{ONOFF} to either @code{on} or @code{off} does not toggle tag, but
-ensure that it is either on or off.
-@end defun
-
-@defun org-promote
-Promote the current entry.
-@end defun
-
-@defun org-demote
-Demote the current entry.
-@end defun
-
-This example turns all entries tagged with @samp{TOMORROW} into TODO
-entries with keyword @samp{UPCOMING}.  Org ignores entries in comment trees
-and archive trees.
-
-@lisp
-(org-map-entries '(org-todo "UPCOMING")
-                 "+TOMORROW" 'file 'archive 'comment)
-@end lisp
-
-The following example counts the number of entries with TODO keyword
-@samp{WAITING}, in all agenda files.
-
-@lisp
-(length (org-map-entries t "/+WAITING" 'agenda))
-@end lisp
-
-@node History and Acknowledgments
-@appendix History and Acknowledgments
-
-
-
-@anchor{From Carsten}
-@appendixsec From Carsten
-
-Org was born in 2003, out of frustration over the user interface of
-the Emacs Outline mode.  I was trying to organize my notes and
-projects, and using Emacs seemed to be the natural way to go.
-However, having to remember eleven different commands with two or
-three keys per command, only to hide and show parts of the outline
-tree, that seemed entirely unacceptable to me.  Also, when using
-outlines to take notes, I constantly wanted to restructure the tree,
-organizing it parallel to my thoughts and plans.  @emph{Visibility cycling}
-and @emph{structure editing} were originally implemented in the package
-@samp{outline-magic.el}, but quickly moved to the more general @samp{org.el}.
-As this environment became comfortable for project planning, the next
-step was adding @emph{TODO entries}, basic @emph{timestamps}, and @emph{table
-support}.  These areas highlighted the two main goals that Org still
-has today: to be a new, outline-based, plain text mode with innovative
-and intuitive editing features, and to incorporate project planning
-functionality directly into a notes file.
-
-Since the first release, literally thousands of emails to me or to the
-@email{emacs-orgmode@@gnu.org, mailing list} have provided a constant stream 
of bug reports, feedback,
-new ideas, and sometimes patches and add-on code.  Many thanks to
-everyone who has helped to improve this package.  I am trying to keep
-here a list of the people who had significant influence in shaping one
-or more aspects of Org.  The list may not be complete, if I have
-forgotten someone, please accept my apologies and let me know.
-
-Before I get to this list, a few special mentions are in order:
-
-@table @asis
-@item Bastien Guerry
-Bastien has written a large number of extensions to Org (most of
-them integrated into the core by now), including the @LaTeX{} exporter
-and the plain list parser.  His support during the early days was
-central to the success of this project.  Bastien also invented Worg,
-helped establishing the Web presence of Org, and sponsored hosting
-costs for the orgmode.org website.  Bastien stepped in as maintainer
-of Org between 2011 and 2013, at a time when I desperately needed
-a break.
-
-@item Eric Schulte and Dan Davison
-Eric and Dan are jointly responsible for the Org Babel system, which
-turns Org into a multi-language environment for evaluating code and
-doing literate programming and reproducible research.  This has
-become one of Org's killer features that define what Org is today.
-
-@item John Wiegley
-John has contributed a number of great ideas and patches directly to
-Org, including the attachment system (@samp{org-attach.el}), integration
-with Apple Mail (@samp{org-mac-message.el}), hierarchical dependencies of
-TODO items, habit tracking (@samp{org-habits.el}), and encryption
-(@samp{org-crypt.el}).  Also, the capture system is really an extended
-copy of his great @samp{remember.el}.
-
-@item Sebastian Rose
-Without Sebastian, the HTML/XHTML publishing of Org would be the
-pitiful work of an ignorant amateur.  Sebastian has pushed this part
-of Org onto a much higher level.  He also wrote @samp{org-info.js},
-a JavaScript program for displaying webpages derived from Org using
-an Info-like or a folding interface with single-key navigation.
-@end table
-
-See below for the full list of contributions!  Again, please let me
-know what I am missing here!
-
-@anchor{From Bastien}
-@appendixsec From Bastien
-
-I (Bastien) have been maintaining Org between 2011 and 2013.  This
-appendix would not be complete without adding a few more
-acknowledgments and thanks.
-
-I am first grateful to Carsten for his trust while handing me over the
-maintainership of Org.  His unremitting support is what really helped
-me getting more confident over time, with both the community and the
-code.
-
-When I took over maintainership, I knew I would have to make Org more
-collaborative than ever, as I would have to rely on people that are
-more knowledgeable than I am on many parts of the code.  Here is
-a list of the persons I could rely on, they should really be
-considered co-maintainers, either of the code or the community:
-
-@table @asis
-@item Eric Schulte
-Eric is maintaining the Babel parts of Org.  His reactivity here
-kept me away from worrying about possible bugs here and let me focus
-on other parts.
-
-@item Nicolas Goaziou
-Nicolas is maintaining the consistency of the deepest parts of Org.
-His work on @samp{org-element.el} and @samp{ox.el} has been outstanding, and
-it opened the doors for many new ideas and features.  He rewrote
-many of the old exporters to use the new export engine, and helped
-with documenting this major change.  More importantly (if that's
-possible), he has been more than reliable during all the work done
-for Org 8.0, and always very reactive on the mailing list.
-
-@item Achim Gratz
-Achim rewrote the building process of Org, turning some @emph{ad hoc}
-tools into a flexible and conceptually clean process.  He patiently
-coped with the many hiccups that such a change can create for users.
-
-@item Nick Dokos
-The Org mode mailing list would not be such a nice place without
-Nick, who patiently helped users so many times.  It is impossible to
-overestimate such a great help, and the list would not be so active
-without him.
-@end table
-
-I received support from so many users that it is clearly impossible to
-be fair when shortlisting a few of them, but Org's history would not
-be complete if the ones above were not mentioned in this manual.
-
-@anchor{List of Contributions}
-@appendixsec List of Contributions
-
-@itemize
-@item
-Russell Adams came up with the idea for drawers.
-
-@item
-Thomas Baumann wrote @samp{ol-bbdb.el} and @samp{ol-mhe.el}.
-
-@item
-Christophe Bataillon created the great unicorn logo that we use on
-the Org mode website.
-
-@item
-Alex Bochannek provided a patch for rounding timestamps.
-
-@item
-Jan Böcker wrote @samp{ol-docview.el}.
-
-@item
-Brad Bozarth showed how to pull RSS feed data into Org files.
-
-@item
-Tom Breton wrote @samp{org-choose.el}.
-
-@item
-Charles Cave's suggestion sparked the implementation of templates
-for Remember, which are now templates for capture.
-
-@item
-Pavel Chalmoviansky influenced the agenda treatment of items with
-specified time.
-
-@item
-Gregory Chernov patched support for Lisp forms into table
-calculations and improved XEmacs compatibility, in particular by
-porting @samp{nouline.el} to XEmacs.
-
-@item
-Sacha Chua suggested copying some linking code from Planner.
-
-@item
-Baoqiu Cui contributed the DocBook exporter.
-
-@item
-Eddward DeVilla proposed and tested checkbox statistics.  He also
-came up with the idea of properties, and that there should be an API
-for them.
-
-@item
-Nick Dokos tracked down several nasty bugs.
-
-@item
-Kees Dullemond used to edit projects lists directly in HTML and so
-inspired some of the early development, including HTML export.  He
-also asked for a way to narrow wide table columns.
-
-@item
-Thomas@tie{}S@.@tie{}Dye contributed documentation on Worg and helped
-integrating the Org Babel documentation into the manual.
-
-@item
-Christian Egli converted the documentation into Texinfo format,
-inspired the agenda, patched CSS formatting into the HTML exporter,
-and wrote @samp{org-taskjuggler.el}.
-
-@item
-David Emery provided a patch for custom CSS support in exported HTML
-agendas.
-
-@item
-Nic Ferrier contributed mailcap and XOXO support.
-
-@item
-Miguel@tie{}A@.@tie{}Figueroa-Villanueva implemented hierarchical checkboxes.
-
-@item
-John Foerch figured out how to make incremental search show context
-around a match in a hidden outline tree.
-
-@item
-Raimar Finken wrote @samp{org-git-line.el}.
-
-@item
-Mikael Fornius works as a mailing list moderator.
-
-@item
-Austin Frank works as a mailing list moderator.
-
-@item
-Eric Fraga drove the development of Beamer export with ideas and
-testing.
-
-@item
-Barry Gidden did proofreading the manual in preparation for the book
-publication through Network Theory Ltd.
-
-@item
-Niels Giesen had the idea to automatically archive DONE trees.
-
-@item
-Nicolas Goaziou rewrote much of the plain list code.
-
-@item
-Kai Grossjohann pointed out key-binding conflicts with other
-packages.
-
-@item
-Brian Gough of Network Theory Ltd publishes the Org mode manual as
-a book.
-
-@item
-Bernt Hansen has driven much of the support for auto-repeating
-tasks, task state change logging, and the clocktable.  His clear
-explanations have been critical when we started to adopt the Git
-version control system.
-
-@item
-Manuel Hermenegildo has contributed various ideas, small fixes and
-patches.
-
-@item
-Phil Jackson wrote @samp{ol-irc.el}.
-
-@item
-Scott Jaderholm proposed footnotes, control over whitespace between
-folded entries, and column view for properties.
-
-@item
-Matt Jones wrote MobileOrg Android.
-
-@item
-Tokuya Kameshima wrote @samp{org-wl.el} and @samp{org-mew.el}.
-
-@item
-Shidai Liu (``Leo'') asked for embedded @LaTeX{} and tested it.  He also
-provided frequent feedback and some patches.
-
-@item
-Matt Lundin has proposed last-row references for table formulas and
-named invisible anchors.  He has also worked a lot on the FAQ@.
-
-@item
-David Maus wrote @samp{org-atom.el}, maintains the issues file for Org,
-and is a prolific contributor on the mailing list with competent
-replies, small fixes and patches.
-
-@item
-Jason@tie{}F@.@tie{}McBrayer suggested agenda export to CSV format.
-
-@item
-Max Mikhanosha came up with the idea of refiling.
-
-@item
-Dmitri Minaev sent a patch to set priority limits on a per-file
-basis.
-
-@item
-Stefan Monnier provided a patch to keep the Emacs Lisp compiler
-happy.
-
-@item
-Richard Moreland wrote MobileOrg for the iPhone.
-
-@item
-Rick Moynihan proposed allowing multiple TODO sequences in a file
-and being able to quickly restrict the agenda to a subtree.
-
-@item
-Todd Neal provided patches for links to Info files and Elisp forms.
-
-@item
-Greg Newman refreshed the unicorn logo into its current form.
-
-@item
-Tim O'Callaghan suggested in-file links, search options for general
-file links, and tags.
-
-@item
-Osamu Okano wrote @samp{orgcard2ref.pl}, a Perl program to create a text
-version of the reference card.
-
-@item
-Takeshi Okano translated the manual and David O'Toole's tutorial
-into Japanese.
-
-@item
-Oliver Oppitz suggested multi-state TODO items.
-
-@item
-Scott Otterson sparked the introduction of descriptive text for
-links, among other things.
-
-@item
-Pete Phillips helped during the development of the TAGS feature,
-and provided frequent feedback.
-
-@item
-Martin Pohlack provided the code snippet to bundle character
-insertion into bundles of 20 for undo.
-
-@item
-T@.@tie{}V@.@tie{}Raman reported bugs and suggested improvements.
-
-@item
-Matthias Rempe (Oelde) provided ideas, Windows support, and quality
-control.
-
-@item
-Paul Rivier provided the basic implementation of named footnotes.
-He also acted as mailing list moderator for some time.
-
-@item
-Kevin Rogers contributed code to access VM files on remote hosts.
-
-@item
-Frank Ruell solved the mystery of the @samp{keymapp nil} bug, a conflict
-with @samp{allout.el}.
-
-@item
-Jason Riedy generalized the send-receive mechanism for Orgtbl
-tables with extensive patches.
-
-@item
-Philip Rooke created the Org reference card, provided lots of
-feedback, developed and applied standards to the Org documentation.
-
-@item
-Christian Schlauer proposed angular brackets around links, among
-other things.
-
-@item
-Paul Sexton wrote @samp{org-ctags.el}.
-
-@item
-Tom Shannon's @samp{organizer-mode.el} inspired linking to VM/BBDB/Gnus.
-
-@item
-Ilya Shlyakhter proposed the Archive Sibling, line numbering in
-literal examples, and remote highlighting for referenced code lines.
-
-@item
-Stathis Sideris wrote the @samp{ditaa.jar} ASCII to PNG converter that is
-now packaged into Org's @samp{contrib/} directory.
-
-@item
-Daniel Sinder came up with the idea of internal archiving by locking
-subtrees.
-
-@item
-Dale Smith proposed link abbreviations.
-
-@item
-James TD Smith has contributed a large number of patches for
-useful tweaks and features.
-
-@item
-Adam Spiers asked for global linking commands, inspired the link
-extension system, added support for Mairix, and proposed the mapping
-API@.
-
-@item
-Ulf Stegemann created the table to translate special symbols to
-HTML, @LaTeX{}, UTF-8, Latin-1 and ASCII@.
-
-@item
-Andy Stewart contributed code to @samp{ol-w3m.el}, to copy
-HTML content with links transformation to Org syntax.
-
-@item
-David O'Toole wrote @samp{org-publish.el} and drafted the
-manual chapter about publishing.
-
-@item
-Jambunathan@tie{}K@.@tie{}contributed the ODT exporter.
-
-@item
-Sebastien Vauban reported many issues with @LaTeX{} and Beamer export
-and enabled source code highlighting in Gnus.
-
-@item
-Stefan Vollmar organized a video-recorded talk at the
-Max-Planck-Institute for Neurology.  He also inspired the creation
-of a concept index for HTML export.
-
-@item
-Jürgen Vollmer contributed code generating the table of contents in
-HTML output.
-
-@item
-Samuel Wales has provided important feedback and bug reports.
-
-@item
-Chris Wallace provided a patch implementing the @samp{QUOTE} block.
-
-@item
-David Wainberg suggested archiving, and improvements to the
-linking system.
-
-@item
-Carsten Wimmer suggested some changes and helped fix a bug in
-linking to Gnus.
-
-@item
-Roland Winkler requested additional key bindings to make Org work on
-a TTY@.
-
-@item
-Piotr Zielinski wrote @samp{org-mouse.el}, proposed agenda
-blocks and contributed various ideas and code snippets.
-
-@item
-Marco Wahl wrote @samp{ol-eww.el}.
-@end itemize
-
-@node GNU Free Documentation License
-@appendix GNU Free Documentation License
-
-@center Version 1.3, 3 November 2008
-
-@display
-Copyright @copyright{} 2000, 2001, 2002, 2007, 2008 Free Software Foundation, 
Inc.
-@uref{https://fsf.org/}
-
-Everyone is permitted to copy and distribute verbatim copies
-of this license document, but changing it is not allowed.
-@end display
-
-@enumerate 0
-@item
-PREAMBLE
-
-The purpose of this License is to make a manual, textbook, or other
-functional and useful document @dfn{free}
-in the sense of freedom: to assure everyone the effective freedom
-to copy and redistribute it, with or without modifying it, either
-commercially or noncommercially. Secondarily, this License
-preserves for the author and publisher a way to get credit for
-their work, while not being considered responsible for
-modifications made by others.
-
-This License is a kind of ``copyleft'', which means that derivative
-works of the document must themselves be free in the same sense.
-It complements the GNU General Public License, which is a copyleft
-license designed for free software.
-
-We have designed this License in order to use it for manuals for
-free software, because free software needs free documentation:
-a free program should come with manuals providing the same freedoms
-that the software does.  But this License is not limited to
-software manuals; it can be used for any textual work, regardless
-of subject matter or whether it is published as a printed book.  We
-recommend this License principally for works whose purpose is
-instruction or reference.
-
-@item
-APPLICABILITY AND DEFINITIONS
-
-This License applies to any manual or other work, in any medium,
-that contains a notice placed by the copyright holder saying it can
-be distributed under the terms of this License.  Such a notice
-grants a world-wide, royalty-free license, unlimited in duration,
-to use that work under the conditions stated herein.  The
-``Document'', below, refers to any such manual or work.  Any member
-of the public is a licensee, and is addressed as ``you''.  You accept
-the license if you copy, modify or distribute the work in a way
-requiring permission under copyright law.
-
-A ``Modified Version'' of the Document means any work containing the
-Document or a portion of it, either copied verbatim, or with
-modifications and/or translated into another language.
-
-A ``Secondary Section'' is a named appendix or a front-matter section
-of the Document that deals exclusively with the relationship of the
-publishers or authors of the Document to the Document's overall
-subject (or to related matters) and contains nothing that could
-fall directly within that overall subject.  (Thus, if the Document
-is in part a textbook of mathematics, a Secondary Section may not
-explain any mathematics.)  The relationship could be a matter of
-historical connection with the subject or with related matters, or
-of legal, commercial, philosophical, ethical or political position
-regarding them.
-
-The ``Invariant Sections'' are certain Secondary Sections whose
-titles are designated, as being those of Invariant Sections, in the
-notice that says that the Document is released under this License.
-If a section does not fit the above definition of Secondary then it
-is not allowed to be designated as Invariant.  The Document may
-contain zero Invariant Sections.  If the Document does not identify
-any Invariant Sections then there are none.
-
-The ``Cover Texts'' are certain short passages of text that are
-listed, as Front-Cover Texts or Back-Cover Texts, in the notice
-that says that the Document is released under this License.
-A Front-Cover Text may be at most 5 words, and a Back-Cover Text
-may be at most 25 words.
-
-A ``Transparent'' copy of the Document means a machine-readable copy,
-represented in a format whose specification is available to the
-general public, that is suitable for revising the document
-straightforwardly with generic text editors or (for images composed
-of pixels) generic paint programs or (for drawings) some widely
-available drawing editor, and that is suitable for input to text
-formatters or for automatic translation to a variety of formats
-suitable for input to text formatters.  A copy made in an otherwise
-Transparent file format whose markup, or absence of markup, has
-been arranged to thwart or discourage subsequent modification by
-readers is not Transparent.  An image format is not Transparent if
-used for any substantial amount of text.  A copy that is not
-``Transparent'' is called ``Opaque''.
-
-Examples of suitable formats for Transparent copies include plain
-ASCII without markup, Texinfo input format, @LaTeX{} input format,
-SGML or XML using a publicly available DTD, and standard-conforming
-simple HTML, PostScript or PDF designed for human modification.
-Examples of transparent image formats include PNG, XCF and JPG@.
-Opaque formats include proprietary formats that can be read and
-edited only by proprietary word processors, SGML or XML for which
-the DTD and/or processing tools are not generally available, and
-the machine-generated HTML, PostScript or PDF produced by some word
-processors for output purposes only.
-
-The ``Title Page'' means, for a printed book, the title page itself,
-plus such following pages as are needed to hold, legibly, the
-material this License requires to appear in the title page.  For
-works in formats which do not have any title page as such, ``Title
-Page'' means the text near the most prominent appearance of the
-work's title, preceding the beginning of the body of the text.
-
-The ``publisher'' means any person or entity that distributes copies
-of the Document to the public.
-
-A section ``Entitled XYZ'' means a named subunit of the Document
-whose title either is precisely XYZ or contains XYZ in parentheses
-following text that translates XYZ in another language.  (Here XYZ
-stands for a specific section name mentioned below, such as
-``Acknowledgements'', ``Dedications'', ``Endorsements'', or ``History''.)
-To ``Preserve the Title'' of such a section when you modify the
-Document means that it remains a section ``Entitled XYZ'' according
-to this definition.
-
-The Document may include Warranty Disclaimers next to the notice
-which states that this License applies to the Document.  These
-Warranty Disclaimers are considered to be included by reference in
-this License, but only as regards disclaiming warranties: any other
-implication that these Warranty Disclaimers may have is void and
-has no effect on the meaning of this License.
-
-@item
-VERBATIM COPYING
-
-You may copy and distribute the Document in any medium, either
-commercially or noncommercially, provided that this License, the
-copyright notices, and the license notice saying this License
-applies to the Document are reproduced in all copies, and that you
-add no other conditions whatsoever to those of this License.  You
-may not use technical measures to obstruct or control the reading
-or further copying of the copies you make or distribute.  However,
-you may accept compensation in exchange for copies.  If you
-distribute a large enough number of copies you must also follow the
-conditions in section 3.
-
-You may also lend copies, under the same conditions stated above,
-and you may publicly display copies.
-
-@item
-COPYING IN QUANTITY
-
-If you publish printed copies (or copies in media that commonly
-have printed covers) of the Document, numbering more than 100, and
-the Document's license notice requires Cover Texts, you must
-enclose the copies in covers that carry, clearly and legibly, all
-these Cover Texts: Front-Cover Texts on the front cover, and
-Back-Cover Texts on the back cover.  Both covers must also clearly
-and legibly identify you as the publisher of these copies.  The
-front cover must present the full title with all words of the title
-equally prominent and visible.  You may add other material on the
-covers in addition.  Copying with changes limited to the covers, as
-long as they preserve the title of the Document and satisfy these
-conditions, can be treated as verbatim copying in other respects.
-
-If the required texts for either cover are too voluminous to fit
-legibly, you should put the first ones listed (as many as fit
-reasonably) on the actual cover, and continue the rest onto
-adjacent pages.
-
-If you publish or distribute Opaque copies of the Document
-numbering more than 100, you must either include a machine-readable
-Transparent copy along with each Opaque copy, or state in or with
-each Opaque copy a computer-network location from which the general
-network-using public has access to download using public-standard
-network protocols a complete Transparent copy of the Document, free
-of added material.  If you use the latter option, you must take
-reasonably prudent steps, when you begin distribution of Opaque
-copies in quantity, to ensure that this Transparent copy will
-remain thus accessible at the stated location until at least one
-year after the last time you distribute an Opaque copy (directly or
-through your agents or retailers) of that edition to the public.
-
-It is requested, but not required, that you contact the authors of
-the Document well before redistributing any large number of copies,
-to give them a chance to provide you with an updated version of the
-Document.
-
-@item
-MODIFICATIONS
-
-You may copy and distribute a Modified Version of the Document
-under the conditions of sections 2 and 3 above, provided that you
-release the Modified Version under precisely this License, with the
-Modified Version filling the role of the Document, thus licensing
-distribution and modification of the Modified Version to whoever
-possesses a copy of it.  In addition, you must do these things in
-the Modified Version:
-
-@enumerate A
-@item
-Use in the Title Page (and on the covers, if any) a title
-distinct from that of the Document, and from those of previous
-versions (which should, if there were any, be listed in the
-History section of the Document). You may use the same title as
-a previous version if the original publisher of that version
-gives permission.
-
-@item
-List on the Title Page, as authors, one or more persons or
-entities responsible for authorship of the modifications in the
-Modified Version, together with at least five of the principal
-authors of the Document (all of its principal authors, if it has
-fewer than five), unless they release you from this requirement.
-
-@item
-State on the Title page the name of the publisher of the
-Modified Version, as the publisher.
-
-@item
-Preserve all the copyright notices of the Document.
-
-@item
-Add an appropriate copyright notice for your modifications
-adjacent to the other copyright notices.
-
-@item
-Include, immediately after the copyright notices, a license
-notice giving the public permission to use the Modified Version
-under the terms of this License, in the form shown in the
-Addendum below.
-
-@item
-Preserve in that license notice the full lists of Invariant
-Sections and required Cover Texts given in the Document's
-license notice.
-
-@item
-Include an unaltered copy of this License.
-
-@item
-Preserve the section Entitled ``History'', Preserve its Title, and
-add to it an item stating at least the title, year, new authors,
-and publisher of the Modified Version as given on the Title
-Page. If there is no section Entitled ``History'' in the Document,
-create one stating the title, year, authors, and publisher of
-the Document as given on its Title Page, then add an item
-describing the Modified Version as stated in the previous
-sentence.
-
-@item
-Preserve the network location, if any, given in the Document
-for public access to a Transparent copy of the Document, and
-likewise the network locations given in the Document for
-previous versions it was based on. These may be placed in the
-``History'' section. You may omit a network location for a work
-that was published at least four years before the Document
-itself, or if the original publisher of the version it refers
-to gives permission.
-
-@item
-For any section Entitled ``Acknowledgements'' or ``Dedications'',
-Preserve the Title of the section, and preserve in the section
-all the substance and tone of each of the contributor
-acknowledgements and/or dedications given therein.
-
-@item
-Preserve all the Invariant Sections of the Document, unaltered
-in their text and in their titles. Section numbers or the
-equivalent are not considered part of the section titles.
-
-@item
-Delete any section Entitled ``Endorsements''. Such a section may
-not be included in the Modified Version.
-
-@item
-Do not retitle any existing section to be Entitled
-``Endorsements'' or to conflict in title with any Invariant
-Section.
-
-@item
-Preserve any Warranty Disclaimers.
-@end enumerate
-
-If the Modified Version includes new front-matter sections or
-appendices that qualify as Secondary Sections and contain no material
-copied from the Document, you may at your option designate some or all
-of these sections as invariant.  To do this, add their titles to the
-list of Invariant Sections in the Modified Version's license notice.
-These titles must be distinct from any other section titles.
-
-You may add a section Entitled ``Endorsements'', provided it contains
-nothing but endorsements of your Modified Version by various
-parties---for example, statements of peer review or that the text has
-been approved by an organization as the authoritative definition of a
-standard.
-
-You may add a passage of up to five words as a Front-Cover Text, and a
-passage of up to 25 words as a Back-Cover Text, to the end of the list
-of Cover Texts in the Modified Version.  Only one passage of
-Front-Cover Text and one of Back-Cover Text may be added by (or
-through arrangements made by) any one entity.  If the Document already
-includes a cover text for the same cover, previously added by you or
-by arrangement made by the same entity you are acting on behalf of,
-you may not add another; but you may replace the old one, on explicit
-permission from the previous publisher that added the old one.
-
-The author(s) and publisher(s) of the Document do not by this License
-give permission to use their names for publicity for or to assert or
-imply endorsement of any Modified Version.
-
-@item
-COMBINING DOCUMENTS
-
-You may combine the Document with other documents released under
-this License, under the terms defined in section 4 above for
-modified versions, provided that you include in the combination all
-of the Invariant Sections of all of the original documents,
-unmodified, and list them all as Invariant Sections of your
-combined work in its license notice, and that you preserve all
-their Warranty Disclaimers.
-
-The combined work need only contain one copy of this License, and
-multiple identical Invariant Sections may be replaced with a single
-copy.  If there are multiple Invariant Sections with the same name
-but different contents, make the title of each such section unique
-by adding at the end of it, in parentheses, the name of the
-original author or publisher of that section if known, or else
-a unique number.  Make the same adjustment to the section titles in
-the list of Invariant Sections in the license notice of the
-combined work.
-
-In the combination, you must combine any sections Entitled
-``History'' in the various original documents, forming one section
-Entitled ``History''; likewise combine any sections Entitled
-``Acknowledgements'', and any sections Entitled ``Dedications''.  You
-must delete all sections Entitled ``Endorsements.''
-
-@item
-COLLECTIONS OF DOCUMENTS
-
-You may make a collection consisting of the Document and other
-documents released under this License, and replace the individual
-copies of this License in the various documents with a single copy
-that is included in the collection, provided that you follow the
-rules of this License for verbatim copying of each of the documents
-in all other respects.
-
-You may extract a single document from such a collection, and
-distribute it individually under this License, provided you insert
-a copy of this License into the extracted document, and follow this
-License in all other respects regarding verbatim copying of that
-document.
-
-@item
-AGGREGATION WITH INDEPENDENT WORKS
-
-A compilation of the Document or its derivatives with other
-separate and independent documents or works, in or on a volume of
-a storage or distribution medium, is called an ``aggregate'' if the
-copyright resulting from the compilation is not used to limit the
-legal rights of the compilation's users beyond what the individual
-works permit.  When the Document is included in an aggregate, this
-License does not apply to the other works in the aggregate which
-are not themselves derivative works of the Document.
-
-If the Cover Text requirement of section 3 is applicable to these
-copies of the Document, then if the Document is less than one half
-of the entire aggregate, the Document's Cover Texts may be placed
-on covers that bracket the Document within the aggregate, or the
-electronic equivalent of covers if the Document is in electronic
-form.  Otherwise they must appear on printed covers that bracket
-the whole aggregate.
-
-@item
-TRANSLATION
-
-Translation is considered a kind of modification, so you may
-distribute translations of the Document under the terms of
-section 4.  Replacing Invariant Sections with translations requires
-special permission from their copyright holders, but you may
-include translations of some or all Invariant Sections in addition
-to the original versions of these Invariant Sections.  You may
-include a translation of this License, and all the license notices
-in the Document, and any Warranty Disclaimers, provided that you
-also include the original English version of this License and the
-original versions of those notices and disclaimers.  In case of
-a disagreement between the translation and the original version of
-this License or a notice or disclaimer, the original version will
-prevail.
-
-If a section in the Document is Entitled ``Acknowledgements'',
-``Dedications'', or ``History'', the requirement (section 4) to
-Preserve its Title (section 1) will typically require changing the
-actual title.
-
-@item
-TERMINATION
-
-You may not copy, modify, sublicense, or distribute the Document
-except as expressly provided under this License.  Any attempt
-otherwise to copy, modify, sublicense, or distribute it is void,
-and will automatically terminate your rights under this License.
-
-However, if you cease all violation of this License, then your
-license from a particular copyright holder is reinstated (a)
-provisionally, unless and until the copyright holder explicitly and
-finally terminates your license, and (b) permanently, if the
-copyright holder fails to notify you of the violation by some
-reasonable means prior to 60 days after the cessation.
-
-Moreover, your license from a particular copyright holder is
-reinstated permanently if the copyright holder notifies you of the
-violation by some reasonable means, this is the first time you have
-received notice of violation of this License (for any work) from
-that copyright holder, and you cure the violation prior to 30 days
-after your receipt of the notice.
-
-Termination of your rights under this section does not terminate
-the licenses of parties who have received copies or rights from you
-under this License.  If your rights have been terminated and not
-permanently reinstated, receipt of a copy of some or all of the
-same material does not give you any rights to use it.
-
-@item
-FUTURE REVISIONS OF THIS LICENSE
-
-The Free Software Foundation may publish new, revised versions of
-the GNU Free Documentation License from time to time.  Such new
-versions will be similar in spirit to the present version, but may
-differ in detail to address new problems or concerns.  See
-@uref{https://www.gnu.org/copyleft/}.
-
-Each version of the License is given a distinguishing version
-number.  If the Document specifies that a particular numbered
-version of this License ``or any later version'' applies to it, you
-have the option of following the terms and conditions either of
-that specified version or of any later version that has been
-published (not as a draft) by the Free Software Foundation.  If
-the Document does not specify a version number of this License,
-you may choose any version ever published (not as a draft) by the
-Free Software Foundation.  If the Document specifies that a proxy
-can decide which future versions of this License can be used, that
-proxy's public statement of acceptance of a version permanently
-authorizes you to choose that version for the Document.
-
-@item
-RELICENSING
-
-``Massive Multiauthor Collaboration Site'' (or ``MMC Site'') means any
-World Wide Web server that publishes copyrightable works and also
-provides prominent facilities for anybody to edit those works.
-A public wiki that anybody can edit is an example of such
-a server.  A ``Massive Multiauthor Collaboration'' (or ``MMC'')
-contained in the site means any set of copyrightable works thus
-published on the MMC site.
-
-``CC-BY-SA'' means the Creative Commons Attribution-Share Alike 3.0
-license published by Creative Commons Corporation,
-a not-for-profit corporation with a principal place of business in
-San Francisco, California, as well as future copyleft versions of
-that license published by that same organization.
-
-``Incorporate'' means to publish or republish a Document, in whole
-or in part, as part of another Document.
-
-An MMC is ``eligible for relicensing'' if it is licensed under this
-License, and if all works that were first published under this
-License somewhere other than this MMC, and subsequently
-incorporated in whole or in part into the MMC, (1) had no cover
-texts or invariant sections, and (2) were thus incorporated prior
-to November 1, 2008.
-
-The operator of an MMC Site may republish an MMC contained in the
-site under CC-BY-SA on the same site at any time before August 1,
-2009, provided the MMC is eligible for relicensing.
-@end enumerate
-
-@page
-
-@anchor{ADDENDUM How to use this License for your documents}
-@appendixsec ADDENDUM: How to use this License for your documents
-
-To use this License in a document you have written, include a copy of
-the License in the document and put the following copyright and
-license notices just after the title page:
-
-@example
-Copyright (C)  YEAR  YOUR NAME.
-Permission is granted to copy, distribute and/or modify this document
-under the terms of the GNU Free Documentation License, Version 1.3
-or any later version published by the Free Software Foundation;
-with no Invariant Sections, no Front-Cover Texts, and no Back-Cover
-Texts.  A copy of the license is included in the section entitled ``GNU
-Free Documentation License''.
-@end example
-
-If you have Invariant Sections, Front-Cover Texts and Back-Cover Texts,
-replace the ``with@dots{}Texts.''@tie{}line with this:
-
-@example
-with the Invariant Sections being LIST THEIR TITLES, with
-the Front-Cover Texts being LIST, and with the Back-Cover Texts
-being LIST.
-@end example
-
-If you have Invariant Sections without Cover Texts, or some other
-combination of the three, merge those two alternatives to suit the
-situation.
-
-If your document contains nontrivial examples of program code, we
-recommend releasing these examples in parallel under your choice of
-free software license, such as the GNU General Public License, to
-permit their use in free software.
-
-@node Main Index
-@chapter Main Index
-
-@printindex cp
-
-@node Key Index
-@chapter Key Index
-
-@printindex ky
-
-@node Command and Function Index
-@chapter Command and Function Index
-
-@printindex fn
-
-@node Variable Index
-@chapter Variable Index
-
-This is not a complete index of variables and faces, only the ones
-that are mentioned in the manual.  For a more complete list, use
-@kbd{M-x org-customize} and then click yourself through the tree.
-
-@printindex vr
-
-@bye
diff --git a/doc/misc/remember.texi b/doc/misc/remember.texi
index 80065be..91e67a8 100644
--- a/doc/misc/remember.texi
+++ b/doc/misc/remember.texi
@@ -3,11 +3,12 @@
 @setfilename ../../info/remember.info
 @settitle Remember Manual
 @include docstyle.texi
+@include emacsver.texi
 @syncodeindex fn cp
 @c %**end of header
 
 @copying
-This manual is for Remember Mode, version 2.0
+This manual is for Remember Mode, as distributed with Emacs @value{EMACSVER}.
 
 Copyright @copyright{} 2001, 2004--2005, 2007--2021 Free Software
 Foundation, Inc.
diff --git a/doc/misc/texinfo.tex b/doc/misc/texinfo.tex
index dac7ae3..a91181b 100644
--- a/doc/misc/texinfo.tex
+++ b/doc/misc/texinfo.tex
@@ -1181,7 +1181,7 @@ where each line of input produces a line of output.}
 % double any backslashes.  Otherwise, a name like "\node" will be
 % interpreted as a newline (\n), followed by o, d, e.  Not good.
 %
-% See http://www.ntg.nl/pipermail/ntg-pdftex/2004-July/000654.html and
+% See https://mailman.ntg.nl/pipermail/ntg-pdftex/2004-July/000654.html and
 % related messages.  The final outcome is that it is up to the TeX user
 % to double the backslashes and otherwise make the string valid, so
 % that's what we do.  pdftex 1.30.0 (ca.2005) introduced a primitive to
@@ -3539,7 +3539,7 @@ $$%
 % We use the free feym* fonts from the eurosym package by Henrik
 % Theiling, which support regular, slanted, bold and bold slanted (and
 % "outlined" (blackboard board, sort of) versions, which we don't need).
-% It is available from http://www.ctan.org/tex-archive/fonts/eurosym.
+% It is available from https://www.ctan.org/tex-archive/fonts/eurosym.
 %
 % Although only regular is the truly official Euro symbol, we ignore
 % that.  The Euro is designed to be slightly taller than the regular
diff --git a/doc/misc/tramp.texi b/doc/misc/tramp.texi
index c2e9fe6..5ea0275 100644
--- a/doc/misc/tramp.texi
+++ b/doc/misc/tramp.texi
@@ -126,6 +126,7 @@ Configuring @value{tramp} for use
 * Inline methods::              Inline methods.
 * External methods::            External methods.
 * GVFS-based methods::          @acronym{GVFS}-based external methods.
+* FUSE-based methods::          @acronym{FUSE}-based external methods.
 * Default Method::              Selecting a default method.
 * Default User::                Selecting a default user.
 * Default Host::                Selecting a default host.
@@ -139,6 +140,7 @@ Configuring @value{tramp} for use
                                 Setting own connection related information.
 * Remote programs::             How @value{tramp} finds and uses programs on 
the remote host.
 * Remote shell setup::          Remote shell setup hints.
+* FUSE setup::                  @acronym{FUSE} setup hints.
 * Android shell setup::         Android shell setup hints.
 * Auto-save and Backup::        Auto-save and Backup.
 * Keeping files encrypted::     Protect remote files by encryption.
@@ -223,7 +225,7 @@ presented here to illustrate the steps involved:
 
 @kbd{C-x C-f} to initiate find-file, enter part of the @value{tramp}
 file name, then hit @kbd{@key{TAB}} for completion.  If this is the
-first time connection to that host, here's what happens:
+first time connecting to that host, here's what happens:
 
 @itemize
 @item
@@ -250,17 +252,17 @@ message.
 
 If @value{tramp} does not receive any messages within a timeout period
 (a minute, for example), then @value{tramp} responds with an error
-message about not finding the remote shell prompt.  If any messages
-from the remote host, @value{tramp} displays them in the buffer.
+message about not finding the remote shell prompt.  If there are any
+messages from the remote host, @value{tramp} displays them in the
+buffer.
 
 For any @samp{login failed} message from the remote host,
-@value{tramp} aborts the login attempt, and repeats the login steps
-again.
+@value{tramp} aborts the login attempt, and repeats the login steps.
 
 @item
-Upon successful login and @value{tramp} recognizes the shell prompt
+Upon successful login, if @value{tramp} recognizes the shell prompt
 from the remote host, @value{tramp} prepares the shell environment by
-turning off echoing, setting shell prompt, and other housekeeping
+turning off echoing, setting the shell prompt, and other housekeeping
 chores.
 
 @strong{Note} that for the remote shell, @value{tramp} invokes
@@ -282,8 +284,8 @@ contents from the remote host.
 
 For inline transfers, @value{tramp} sends a command, such as
 @samp{mimencode -b /path/to/remote/file}, waits until the output has
-accumulated in the buffer, decodes that output to produce the file's
-contents.
+accumulated in the buffer, then decodes that output to produce the
+file's contents.
 
 For external transfers, @value{tramp} sends a command as follows:
 @example
@@ -335,7 +337,7 @@ versions packaged with Emacs can be retrieved by
 @end lisp
 
 @value{tramp} is also available as @uref{https://elpa.gnu.org, GNU
-ELPA} package.  Besides the standalone releases, further minor version
+ELPA} package.  Besides the standalone releases, further minor versions
 of @value{tramp} will appear on GNU ELPA, until the next @value{tramp}
 release appears.  These minor versions have a four-number string, like
 ``2.4.5.1''.
@@ -345,7 +347,7 @@ Development versions contain new and incomplete features.  
The
 development version of @value{tramp} is always the version number of
 the next release, plus the suffix ``-pre'', like ``2.4.4-pre''.
 
-One way to obtain @value{tramp} from Git server is to visit the
+One way to obtain @value{tramp} from the Git server is to visit the
 Savannah project page at the following URL and then clicking on the
 Git link in the navigation bar at the top.
 
@@ -363,7 +365,7 @@ $ git clone git://git.savannah.gnu.org/tramp.git
 @end example
 
 @noindent
-From behind a firewall:
+From behind a proxy:
 
 @example
 @group
@@ -411,7 +413,7 @@ $ autoconf
 @end ifset
 @ifclear installchapter
 See the file @file{INSTALL} in that directory for further information
-how to install @value{tramp}.
+on how to install @value{tramp}.
 @end ifclear
 
 
@@ -419,47 +421,47 @@ how to install @value{tramp}.
 @chapter Short introduction how to use @value{tramp}
 @cindex quick start guide
 
-@value{tramp} extends the Emacs file name syntax by a remote
-component.  A remote file name looks always like
+@value{tramp} extends the Emacs file name syntax by adding a remote
+component.  A remote file name always looks like
 @file{@trampfn{method,user@@host,/path/to/file}}.
 
 You can use remote files exactly like ordinary files, that means you
-could open a file or directory by @kbd{C-x C-f
+can open a file or directory by @kbd{C-x C-f
 @trampfn{method,user@@host,/path/to/file} @key{RET}}, edit the file,
 and save it.  You can also mix local files and remote files in file
 operations with two arguments, like @code{copy-file} or
-@code{rename-file}.  And finally, you can run even processes on a
+@code{rename-file}.  And finally, you can even run processes on a
 remote host, when the buffer you call the process from has a remote
 @code{default-directory}.
 
 
-@anchor{Quick Start Guide: File name syntax}
+@anchor{Quick Start Guide File name syntax}
 @section File name syntax
 @cindex file name syntax
 
-Remote file names are prepended by the @code{method}, @code{user} and
-@code{host} parts.  All of them, and also the local file name part,
-are optional, in case of a missing part a default value is assumed.
-The default value for an empty local file name part is the remote
-user's home directory.  The shortest remote file name is
-@file{@trampfn{-,,}}, therefore.  The @samp{-} notation for the
-default method is used for syntactical reasons, @ref{Default Method}.
+Remote file names have @code{method}, @code{user} and @code{host}
+parts prepended.  All of them, and also the local file name part, are
+optional, in case of a missing part a default value is assumed.  The
+default value for an empty local file name part is the remote user's
+home directory.  The shortest remote file name is thus
+@file{@trampfn{-,,}}.  The @samp{-} notation for the default method is
+used for syntactical reasons, @ref{Default Method}.
 
 The @code{method} part describes the connection method used to reach
 the remote host, see below.
 
 The @code{user} part is the user name for accessing the remote host.
 For the @option{smb} method, this could also require a domain name, in
-this case it is written as @code{user%domain}.
+which case it is written as @code{user%domain}.
 
-The @code{host} part must be a host name which could be resolved on
+The @code{host} part must be a host name which can be resolved on
 your local host.  It could be a short host name, a fully qualified
 domain name, an IPv4 or IPv6 address, @ref{File name syntax}.  Some
-connection methods support also a notation of the port to be used, in
-this case it is written as @code{host#port}.
+connection methods also support a notation for the port to be used, in
+which case it is written as @code{host#port}.
 
 
-@anchor{Quick Start Guide: @option{ssh} and @option{plink} methods}
+@anchor{Quick Start Guide ssh and plink methods}
 @section Using @option{ssh} and @option{plink}
 @cindex method @option{ssh}
 @cindex @option{ssh} method
@@ -470,36 +472,39 @@ If your local host runs an SSH client, and the remote 
host runs an SSH
 server, the simplest remote file name is
 @file{@trampfn{ssh,user@@host,/path/to/file}}.  The remote file name
 @file{@trampfn{ssh,,}} opens a remote connection to yourself on the
-local host, and is taken often for testing @value{tramp}.
+local host, and is often used for testing @value{tramp}.
 
-On MS Windows, PuTTY is often used as SSH client.  Its @command{plink}
+On MS Windows, PuTTY is often used as the SSH client.  Its @command{plink}
 method can be used there to open a connection to a remote host running
 an @command{ssh} server:
 @file{@trampfn{plink,user@@host,/path/to/file}}.
 
 
-@anchor{Quick Start Guide: @option{su}, @option{sudo} and @option{sg} methods}
-@section Using @option{su}, @option{sudo} and @option{sg}
+@anchor{Quick Start Guide su, sudo, doas and sg methods}
+@section Using @option{su}, @option{sudo}, @option{doas} and @option{sg}
 @cindex method @option{su}
 @cindex @option{su} method
 @cindex method @option{sudo}
 @cindex @option{sudo} method
+@cindex method @option{doas}
+@cindex @option{doas} method
 @cindex method @option{sg}
 @cindex @option{sg} method
 
 Sometimes, it is necessary to work on your local host under different
-permissions.  For this, you could use the @option{su} or @option{sudo}
-connection method.  Both methods use @samp{root} as default user name
-and the return value of @code{(system-name)} as default host name.
-Therefore, it is convenient to open a file as
+permissions.  For this, you can use the @option{su} or @option{sudo}
+connection method.  On OpenBSD systems, the @option{doas} connection
+method offers the same functionality.  These methods use @samp{root}
+as default user name and the return value of @code{(system-name)} as
+default host name.  Therefore, it is convenient to open a file as
 @file{@trampfn{sudo,,/path/to/file}}.
 
-The method @option{sg} stands for ``switch group''; the changed group
-must be used here as user name.  The default host name is the same.
+The method @option{sg} stands for ``switch group''; here the user name
+is used as the group to change to.  The default host name is the same.
 
 
-@anchor{Quick Start Guide: @option{ssh}, @option{plink}, @option{su}, 
@option{sudo} and @option{sg} methods}
-@section Combining @option{ssh} or @option{plink} with @option{su} or 
@option{sudo}
+@anchor{Quick Start Guide Combining ssh, plink, su, sudo and doas methods}
+@section Combining @option{ssh} or @option{plink} with @option{su}, 
@option{sudo} or @option{doas}
 @cindex method @option{ssh}
 @cindex @option{ssh} method
 @cindex method @option{plink}
@@ -508,18 +513,20 @@ must be used here as user name.  The default host name is 
the same.
 @cindex @option{su} method
 @cindex method @option{sudo}
 @cindex @option{sudo} method
+@cindex method @option{doas}
+@cindex @option{doas} method
 
-If the @option{su} or @option{sudo} option shall be performed on
-another host, it could be comnbined with a leading @option{ssh} or
-@option{plink} option.  That means, @value{tramp} connects first to
-the other host with non-administrative credentials, and changes to
-administrative credentials on that host afterwards.  In a simple case,
-the syntax looks like
+If the @option{su}, @option{sudo} or @option{doas} option should be
+performed on another host, it can be comnbined with a leading
+@option{ssh} or @option{plink} option.  That means that @value{tramp}
+connects first to the other host with non-administrative credentials,
+and changes to administrative credentials on that host afterwards.  In
+a simple case, the syntax looks like
 
@file{@value{prefix}ssh@value{postfixhop}user@@host|sudo@value{postfixhop}@value{postfix}/path/to/file}.
 @xref{Ad-hoc multi-hops}.
 
 
-@anchor{Quick Start Guide: @option{sudoedit} method}
+@anchor{Quick Start Guide sudoedit method}
 @section Using @command{sudoedit}
 @cindex method @option{sudoedit}
 @cindex @option{sudoedit} method
@@ -527,12 +534,12 @@ the syntax looks like
 The @option{sudoedit} method is similar to the @option{sudo} method.
 However, it is a different implementation: it does not keep an open
 session running in the background.  This is for security reasons; on
-the backside this method is less performant than the @option{sudo}
-method, it is restricted to the @samp{localhost} only, and it does not
+the backside this method has worse performance than the @option{sudo}
+method, it is restricted to @samp{localhost} only, and it does not
 support external processes.
 
 
-@anchor{Quick Start Guide: @option{smb} method}
+@anchor{Quick Start Guide smb method}
 @section Using @command{smbclient}
 @cindex method @option{smb}
 @cindex @option{smb} method
@@ -546,7 +553,7 @@ of the local file name is the share exported by the remote 
host,
 @samp{path} in this example.
 
 
-@anchor{Quick Start Guide: GVFS-based methods}
+@anchor{Quick Start Guide GVFS-based methods}
 @section Using @acronym{GVFS}-based methods
 @cindex methods, gvfs
 @cindex gvfs-based methods
@@ -561,16 +568,16 @@ of the local file name is the share exported by the 
remote host,
 @cindex method @option{mtp}
 @cindex @option{mtp} method
 
-On systems, which have installed @acronym{GVFS, the GNOME Virtual File
-System}, its offered methods could be used by @value{tramp}.  Examples
-are @file{@trampfn{sftp,user@@host,/path/to/file}},
+On systems which have @acronym{GVFS, the GNOME Virtual File System}
+installed, its offered methods can be used by @value{tramp}.
+Examples are @file{@trampfn{sftp,user@@host,/path/to/file}},
 @file{@trampfn{afp,user@@host,/path/to/file}} (accessing Apple's AFP
 file system), @file{@trampfn{dav,user@@host,/path/to/file}},
 @file{@trampfn{davs,user@@host,/path/to/file}} (for WebDAV shares) and
 @file{@trampfn{mtp,device,/path/to/file}} (for media devices).
 
 
-@anchor{Quick Start Guide: GNOME Online Accounts based methods}
+@anchor{Quick Start Guide GNOME Online Accounts based methods}
 @section Using @acronym{GNOME} Online Accounts based methods
 @cindex @acronym{GNOME} Online Accounts
 @cindex method @option{gdrive}
@@ -580,17 +587,44 @@ file system), 
@file{@trampfn{dav,user@@host,/path/to/file}},
 @cindex @option{nextcloud} method
 @cindex nextcloud
 
-@acronym{GVFS}-based methods include also @acronym{GNOME} Online
+@acronym{GVFS}-based methods also include @acronym{GNOME} Online
 Accounts, which support the @option{Files} service.  These are the
 Google Drive file system, and the OwnCloud/NextCloud file system.  The
-file name syntax is here always
+file name syntax here is always
 @file{@trampfn{gdrive,john.doe@@gmail.com,/path/to/file}}
 (@samp{john.doe@@gmail.com} stands here for your Google Drive
 account), or @file{@trampfn{nextcloud,user@@host#8081,/path/to/file}}
 (@samp{8081} stands for the port number) for OwnCloud/NextCloud files.
 
 
-@anchor{Quick Start Guide: Android}
+@anchor{Quick Start Guide FUSE-based methods}
+@section Using @acronym{FUSE}-based methods
+@cindex methods, fuse
+@cindex fuse-based methods
+@cindex method @option{rclone}
+@cindex @option{rclone} method
+@cindex method @option{sshfs}
+@cindex @option{sshfs} method
+
+@acronym{FUSE, Filesystem in Userspace} allows users to mount a
+virtual file system.  It is also used by @acronym{GVFS} internally,
+but here we discuss methods which do not use the @acronym{GVFS} API.
+
+A convenient way to access system storages is the @command{rclone}
+program.  If you have configured a storage in @command{rclone} under a
+name @samp{storage} (for example), you can access it via the remote
+file name syntax @file{@trampfn{rclone,storage,/path/to/file}}.  User
+names are not needed.
+
+On local hosts which have installed the @command{sshfs} client for
+mounting a file system based on @command{sftp}, this method can be
+used.  All remote files are available via the local mount point.
+@value{tramp} aids in mounting the file system if it isn't mounted
+yet, and it supports the access with the usual file name syntax
+@file{@trampfn{sshfs,user@@host,/path/to/file}}.
+
+
+@anchor{Quick Start Guide Android}
 @section Using Android
 @cindex method @option{adb}
 @cindex @option{adb} method
@@ -601,18 +635,6 @@ be accessed via the @command{adb} command.  No user or 
host name is
 needed.  The file name syntax is @file{@trampfn{adb,,/path/to/file}}.
 
 
-@anchor{Quick Start Guide: @option{rclone} method}
-@section Using @command{rclone}
-@cindex method @option{rclone}
-@cindex @option{rclone} method
-
-A convenient way to access system storages is the @command{rclone}
-program.  If you have configured a storage in @command{rclone} under a
-name @samp{storage} (for example), you could access it via the remote
-file name syntax @file{@trampfn{rclone,storage,/path/to/file}}.  User
-names are not needed.
-
-
 @node Configuration
 @chapter Configuring @value{tramp}
 @cindex configuration
@@ -630,7 +652,7 @@ For changing the connection type and file access method 
from the
 defaults to one of several other options, @xref{Connection types}.
 
 @strong{Note} that some user options described in these examples are
-not auto loaded by Emacs.  All examples require @value{tramp} is
+not auto loaded by Emacs.  All examples require @value{tramp} to be
 installed and loaded:
 
 @lisp
@@ -638,7 +660,7 @@ installed and loaded:
 @end lisp
 
 For functions used to configure @value{tramp}, the following clause
-might be used in your init file:
+may be used in your init file:
 
 @lisp
 (with-eval-after-load 'tramp (tramp-change-syntax 'simplified))
@@ -650,6 +672,7 @@ might be used in your init file:
 * Inline methods::              Inline methods.
 * External methods::            External methods.
 * GVFS-based methods::          @acronym{GVFS}-based external methods.
+* FUSE-based methods::          @acronym{FUSE}-based external methods.
 * Default Method::              Selecting a default method.
                                   Here we also try to help those who
                                   don't have the foggiest which method
@@ -666,6 +689,7 @@ might be used in your init file:
                                 Setting own connection related information.
 * Remote programs::             How @value{tramp} finds and uses programs on 
the remote host.
 * Remote shell setup::          Remote shell setup hints.
+* FUSE setup::                  @acronym{FUSE} setup hints.
 * Android shell setup::         Android shell setup hints.
 * Auto-save and Backup::        Auto-save and Backup.
 * Keeping files encrypted::     Protect remote files by encryption.
@@ -693,13 +717,13 @@ methods.  While these methods do see better performance 
when actually
 transferring files, the overhead of the cryptographic negotiation at
 startup may drown out the improvement in file transfer times.
 
-External methods should be configured such a way that they don't
-require a password (with @command{ssh-agent}, or such alike).  Modern
+External methods should be configured in such a way that they don't
+require a password (with @command{ssh-agent}, or similar).  Modern
 @command{scp} implementations offer options to reuse existing
-@command{ssh} connections, which will be enabled by default if
-available.  If it isn't possible, you should consider @ref{Password
-handling}, otherwise you will be prompted for a password every copy
-action.
+@command{ssh} connections, which @value{tramp} enables by default if
+available.  If that is not possible, you should consider @ref{Password
+handling}, otherwise you will be prompted for a password for every
+copy action.
 
 
 @node Inline methods
@@ -727,17 +751,17 @@ usability of one of the commands defined in
 reliable command it finds.  @value{tramp}'s search path can be
 customized, see @ref{Remote programs}.
 
-In case none of the commands are unavailable, @value{tramp} first
-transfers a small Perl program to the remote host, and then tries that
-program for encoding and decoding.
+In case none of the commands are available, @value{tramp} first
+transfers a small Perl program to the remote host, and then tries to
+use that program for encoding and decoding.
 
 @vindex tramp-inline-compress-start-size
 @vindex tramp-inline-compress-commands
-To increase transfer speeds for large text files, use compression
-before encoding.  The user option
-@code{tramp-inline-compress-start-size} specifies the file size for
-such optimization.  This feature depends on the availability and
-usability of one of the commands defined in
+To increase transfer speeds for large text files, @value{tramp} can
+use compression before encoding.  The user option
+@code{tramp-inline-compress-start-size} specifies the file size above
+which to use this optimization.  This feature depends on the
+availability and usability of one of the commands defined in
 @code{tramp-inline-compress-commands}.
 
 @table @asis
@@ -747,6 +771,8 @@ usability of one of the commands defined in
 
 @command{rsh} is an option for connecting to hosts within local
 networks since @command{rsh} is not as secure as other methods.
+There should be no reason to use it, as @command{ssh} is a both a
+complete replacement and ubiquitous.
 
 @item @option{ssh}
 @cindex method @option{ssh}
@@ -784,7 +810,7 @@ Similar to @option{su} method, @option{sudo} uses 
@command{sudo}.
 @command{sudo} must have sufficient rights to start a shell.
 
 For security reasons, a @option{sudo} connection is disabled after a
-predefined timeout (5 minutes per default).  This can be changed, see
+predefined timeout (5 minutes by default).  This can be changed, see
 @ref{Predefined connection information}.
 
 @item @option{doas}
@@ -1108,7 +1134,6 @@ UNC file name specification does not allow the 
specification of a
 different user name for authentication like the @command{smbclient}
 can.
 
-
 @item @option{adb}
 @cindex method @option{adb}
 @cindex @option{adb} method
@@ -1148,45 +1173,6 @@ specified using @file{device#42} host name syntax or 
@value{tramp} can
 use the default value as declared in @command{adb} command.  Port
 numbers are not applicable to Android devices connected through USB@.
 
-
-@item @option{rclone}
-@cindex method @option{rclone}
-@cindex @option{rclone} method
-
-@vindex tramp-rclone-program
-The program @command{rclone} allows to access different system
-storages in the cloud, see @url{https://rclone.org/} for a list of
-supported systems.  If the @command{rclone} program isn't found in
-your @env{PATH} environment variable, you can tell @value{tramp} its
-absolute path via the user option @code{tramp-rclone-program}.
-
-A system storage must be configured via the @command{rclone config}
-command, outside Emacs.  If you have configured a storage in
-@command{rclone} under a name @samp{storage} (for example), you could
-access it via the remote file name
-
-@example
-@trampfn{rclone,storage,/path/to/file}
-@end example
-
-User names are part of the @command{rclone} configuration, and not
-needed in the remote file name.  If a user name is contained in the
-remote file name, it is ignored.
-
-Internally, @value{tramp} mounts the remote system storage at location
-@file{/tmp/tramp.rclone.storage}, with @file{storage} being the name
-of the configured system storage.
-
-Optional flags to the different @option{rclone} operations could be
-passed as connection property, @xref{Predefined connection
-information}.  Supported properties are @t{"mount-args"},
-@t{"copyto-args"} and @t{"moveto-args"}.
-
-Access via @option{rclone} is slow.  If you have an alternative method
-for accessing the system storage, you shall prefer this.
-@ref{GVFS-based methods} for example, methods @option{gdrive} and
-@option{nextcloud}.
-
 @end table
 
 
@@ -1198,8 +1184,8 @@ for accessing the system storage, you shall prefer this.
 
 @acronym{GVFS} is the virtual file system for the @acronym{GNOME}
 Desktop, @uref{https://en.wikipedia.org/wiki/GVFS}.  Remote files on
-@acronym{GVFS} are mounted locally through FUSE and @value{tramp} uses
-this locally mounted directory internally.
+@acronym{GVFS} are mounted locally through @acronym{FUSE} and
+@value{tramp} uses this locally mounted directory internally.
 
 Emacs uses the D-Bus mechanism to communicate with @acronym{GVFS}@.
 Emacs must have the message bus system, D-Bus integration active,
@@ -1315,6 +1301,88 @@ respectively:
 @end defopt
 
 
+@node FUSE-based methods
+@section @acronym{FUSE}-based external methods
+@cindex methods, fuse
+@cindex fuse-based methods
+
+Besides @acronym{GVFS}, there are other virtual file systems using the
+@acronym{FUSE} interface.  Remote files are mounted locally through
+@acronym{FUSE} and @value{tramp} uses this locally mounted directory
+internally.  When possible, @value{tramp} maps the remote file names
+to their respective local file name, and applies the file name
+operation on them.  For some of the file name operations this is not
+possible, @value{tramp} emulates those operations otherwise.
+
+@table @asis
+@item @option{rclone}
+@cindex method @option{rclone}
+@cindex @option{rclone} method
+
+@vindex tramp-rclone-program
+The program @command{rclone} allows to access different system
+storages in the cloud, see @url{https://rclone.org/} for a list of
+supported systems.  If the @command{rclone} program isn't found in
+your @env{PATH} environment variable, you can tell @value{tramp} its
+absolute path via the user option @code{tramp-rclone-program}.
+
+A system storage must be configured via the @command{rclone config}
+command, outside Emacs.  If you have configured a storage in
+@command{rclone} under a name @samp{storage} (for example), you could
+access it via the remote file name
+
+@example
+@trampfn{rclone,storage,/path/to/file}
+@end example
+
+User names are part of the @command{rclone} configuration, and not
+needed in the remote file name.  If a user name is contained in the
+remote file name, it is ignored.
+
+Internally, @value{tramp} mounts the remote system storage at location
+@file{/tmp/tramp.rclone.storage}, with @file{storage} being the name
+of the configured system storage.
+
+The mount point and optional flags to the different @option{rclone}
+operations could be passed as connection properties, @xref{Setup of
+rclone method}.
+
+Access via @option{rclone} is slow.  If you have an alternative method
+for accessing the system storage, you should use it.
+@ref{GVFS-based methods} for example, methods @option{gdrive} and
+@option{nextcloud}.
+
+@item @option{sshfs}
+@cindex method @option{sshfs}
+@cindex @option{sshfs} method
+
+@vindex tramp-sshfs-program
+On local hosts which have installed the @command{sshfs} client for
+mounting a file system based on @command{sftp}, this method can be
+used, see
+@url{https://github.com/libfuse/sshfs/blob/master/README.rst/}.  If
+the @command{sshfs} program isn't found in your @env{PATH} environment
+variable, you can tell @value{tramp} its absolute path via the user
+option @code{tramp-sshfs-program}.
+
+All remote files are available via the local mount point.
+@value{tramp} aids in mounting the file system if it isn't mounted
+yet.  The remote file name syntax is
+
+@example
+@trampfn{sshfs,user@@host#port,/path/to/file}
+@end example
+
+User name and port number are optional.  This method does not support
+password handling, the file system must either be mounted already, or
+the connection must be established passwordless via ssh keys.
+
+The mount point and mount arguments could be passed as connection
+properties, @xref{Setup of sshfs method}.
+
+@end table
+
+
 @node Default Method
 @section Selecting a default method
 @cindex default method
@@ -1908,10 +1976,10 @@ machine melancholia#4711 port davs login daniel%BIZARRE 
password geheim
 @end example
 
 @vindex auth-source-save-behavior
-If there doesn't exist a proper entry, the password is read
+If no proper entry exists, the password is read
 interactively.  After successful login (verification of the password),
-it is offered to save a corresponding entry for further use by
-@code{auth-source} backends which support this.  This could be changed
+Emacs offers to save a corresponding entry for further use by
+@code{auth-source} backends which support this.  This can be changed
 by setting the user option @code{auth-source-save-behavior} to @code{nil}.
 
 @vindex auth-source-debug
@@ -1927,6 +1995,25 @@ file, you must customize @code{ange-ftp-netrc-filename}:
 (customize-set-variable 'ange-ftp-netrc-filename "~/.authinfo.gpg")
 @end lisp
 
+In case you do not want to use an authentication file for
+@value{tramp} passwords, use connection-local variables
+@ifinfo
+(@pxref{Connection Variables, , , emacs})
+@end ifinfo
+like this:
+
+@lisp
+@group
+(connection-local-set-profile-variables
+ 'remote-without-auth-sources '((auth-sources . nil)))
+@end group
+
+@group
+(connection-local-set-profiles
+ '(:application tramp) 'remote-without-auth-sources)
+@end group
+@end lisp
+
 
 @anchor{Caching passwords}
 @subsection Caching passwords
@@ -2018,10 +2105,10 @@ properties are listed here:
 @itemize
 @item @t{"login-program"}
 
-The property @t{"login-program"} keeps the program to be called in
-order to connect the remote host.  Sometimes, the program might have
-another name on your host, or it is located on another path.  In this
-case, you can overwrite the default value, which is special for every
+The property @t{"login-program"} stores the program to be used to
+connect to the remote host.  Sometimes, the program might have another
+name on your host, or it might be located in another path.  In this case,
+you can overwrite the default value, which is special for every
 connection method.  It is used in all connection methods of
 @file{tramp-sh.el}.
 
@@ -2074,19 +2161,28 @@ Connections using the @option{smb} method check, 
whether the remote
 host supports posix commands.  If the remote host runs Samba, it
 confirms this capability.  However, some very old Samba versions have
 errors in their implementation.  In order to suppress the posix
-commands for those hosts, the property @t{"posix"} shall be set to
+commands for those hosts, the property @t{"posix"} should be set to
 @code{nil}.
 
 The default value of this property is @code{t} (not specified in
 @code{tramp-methods}).  If the remote host runs native MS Windows,
-there is no effect of this property.
+this propery has no effect.
+
+@item @t{"mount-point"}
+
+The directory file name an @acronym{FUSE}-based file system is mounted
+on.  The default value of this property is
+@t{"/tmp/tramp.method.user@@host#port"} (not specified in
+@code{tramp-methods}).
 
 @item @t{"mount-args"}@*
 @t{"copyto-args"}@*
-@t{"moveto-args"}
+@t{"moveto-args"}@*
+@t{"about-args"}
 
 These properties keep optional flags to the different @option{rclone}
-operations.  Their default value is @code{nil}.
+operations.  See their default values in @code{tramp-methods} if you
+want to change their values.
 @end itemize
 
 
@@ -2186,16 +2282,16 @@ be recomputed.  To force @value{tramp} to recompute 
afresh, call
 @subsection Changing the default remote or local shell
 @cindex zsh setup
 
-Per default, @value{tramp} uses the command @command{/bin/sh} for
+By default, @value{tramp} uses the command @command{/bin/sh} for
 starting a shell on the remote host.  This can be changed by setting
-the connection property @t{"remote-shell"}; see @pxref{Predefined
+the connection property @t{"remote-shell"}; see @ref{Predefined
 connection information}.  If you want, for example, use
 @command{/usr/bin/zsh} on a remote host, you might apply
 
 @lisp
 @group
 (add-to-list 'tramp-connection-properties
-             (list (regexp-quote "@trampfn{ssh,user@@host,}")
+             (list (regexp-quote "@trampfn{sshx,user@@host,}")
                    "remote-shell" "/usr/bin/zsh"))
 @end group
 @end lisp
@@ -2209,9 +2305,11 @@ which support this.
 This approach has also the advantage, that settings in
 @code{tramp-sh-extra-args} will be applied.  For @command{zsh}, the
 trouble with the shell prompt due to set zle options will be avoided.
+For @command{bash}, loading @file{~/.editrc} or @file{~/.inputrc} is
+suppressed.
 
 Similar problems can happen with the local shell Tramp uses to create
-a process.  Per default, it uses the command @command{/bin/sh} for
+a process.  By default, it uses the command @command{/bin/sh} for
 this, which could also be a link to another shell.  In order to
 overwrite this, you might apply
 
@@ -2311,7 +2409,7 @@ prompts, for which @value{tramp} uses 
@code{tramp-wrong-passwd-regexp}.
 
 @value{tramp} uses the user option @code{tramp-terminal-type} to set
 the remote environment variable @env{TERM} for the shells it runs.
-Per default, it is @t{"dumb"}, but this could be changed.  A dumb
+By default, it is @t{"dumb"}, but this could be changed.  A dumb
 terminal is best suited to run the background sessions of
 @value{tramp}.  However, running interactive remote shells might
 require a different setting.  This could be achieved by tweaking the
@@ -2343,10 +2441,16 @@ fi
 
 Another possibility is to check the environment variable
 @env{INSIDE_EMACS}.  Like for all subprocesses of Emacs, this is set
-to the version of the parent Emacs process, @xref{Interactive Shell, ,
-, emacs}.  @value{tramp} adds its own package version to this string,
-which could be used for further tests in an inferior shell.  The
-string of that environment variable looks always like
+to the version of the parent Emacs
+@ifinfo
+process, @xref{Interactive Shell, , , emacs}.
+@end ifinfo
+@ifnotinfo
+process.
+@end ifnotinfo
+@value{tramp} adds its own package version to this string, which could
+be used for further tests in an inferior shell.  The string of that
+environment variable looks always like
 
 @example
 @group
@@ -2401,7 +2505,6 @@ match the end of the connection buffer.  Due to 
performance reasons,
 this search starts at the end of the buffer, and it is limited to 256
 characters backwards.
 
-
 @item Conflicting names for users and variables in @file{.profile}
 
 When a user name is the same as a variable name in a local file, such
@@ -2411,7 +2514,6 @@ variable name to something different from the user name.  
For example,
 if the user name is @env{FRUMPLE}, then change the variable name to
 @env{FRUMPLE_DIR}.
 
-
 @item Non-Bourne commands in @file{.profile}
 
 When the remote host's @file{.profile} is also used for shells other
@@ -2436,7 +2538,6 @@ To accommodate using non-Bourne shells on that remote, 
use other
 shell-specific config files.  For example, bash can use
 @file{~/.bash_profile} and ignore @file{.profile}.
 
-
 @item Interactive shell prompt
 
 @vindex INSIDE_EMACS@r{, environment variable}
@@ -2504,6 +2605,60 @@ where @samp{192.168.0.1} is the remote host IP address
 @end table
 
 
+@node FUSE setup
+@section @acronym{FUSE} setup hints
+
+The @acronym{FUSE} file systems are mounted per default at
+@file{/tmp/tramp.method.user@@host#port}.  The user name and port
+number are optional.  If the file system is already mounted, it will
+be used as it is.  If the mount point does not exist yet,
+@value{tramp} creates this directory.
+
+The mount point can be overwritten by the connection property
+@t{"mount-point"}, @ref{Predefined connection information}.
+Example:
+
+@lisp
+@group
+(add-to-list 'tramp-connection-properties
+             `(,(regexp-quote "@trampfn{sshfs,user@@host,}")
+               "mount-point"
+               ,(expand-file-name "sshfs.user@@host" user-emacs-directory)))
+@end group
+@end lisp
+
+
+@anchor{Setup of rclone method}
+@subsection @option{rclone} setup
+@cindex rclone setup
+
+The default arguments of the @command{rclone} operations
+@command{mount}, @command{coopyto}, @command{moveto} and
+@command{about} are declared in the variable @code{tramp-methods} as
+method specific parameters.  Usually, they don't need to be overwritten.
+
+If needed, these parameters can be overwritten as connection
+properties @t{"mount-args"}, @t{"copyto-args"}, @t{"moveto-args"} and
+@t{"about-args"}, @xref{Predefined connection information}.  All of
+them are list of strings.
+
+Be careful changing @t{"--dir-cache-time"}, this could delay
+visibility of files.
+
+
+@anchor{Setup of sshfs method}
+@subsection @option{sshfs} setup
+@cindex sshfs setup
+
+The method @option{sshfs} declares the mount arguments in the variable
+@code{tramp-methods}, passed to the @command{sshfs} command.  This is
+a list of list of strings, and can be overwritten by the connection
+property @t{"mount-args"}, @xref{Predefined connection information}.
+
+Additionally, it declares also the arguments for running remote
+processes, using the @command{ssh} command.  These don't need to be
+changed.
+
 @node Android shell setup
 @section Android shell setup hints
 @cindex android shell setup for ssh
@@ -3189,19 +3344,19 @@ host when the variable @code{default-directory} is 
remote:
 @end lisp
 
 @vindex process-file-return-signal-string
-@code{process-file} shall return either the exit code of the process,
-or a string describing the signal, when the process has been
-interrupted.  Since it cannot be determined reliably whether a remote
-process has been interrupted, @code{process-file} returns always the
-exit code.  When the user option
+For a local process, @code{process-file} returns either the exit code
+of the process, or a string describing a signal, when the process has
+been interrupted.  Since it cannot be determined reliably whether a
+remote process has been interrupted, @code{process-file} will always
+returns the exit code for it.  When the user option
 @code{process-file-return-signal-string} is non-@code{nil},
-@code{process-file} regards all exit codes greater than 128 as an
+@code{process-file} treats all exit codes greater than 128 as an
 indication that the process has been interrupted, and returns a
-respective string.
+corresponding string.
 
-Remote processes do not apply to @acronym{GVFS} (see @ref{GVFS-based
-methods}) because the remote file system is mounted on the local host
-and @value{tramp} just accesses by changing the
+This remote process handling does not apply to @acronym{GVFS} (see
+@ref{GVFS-based methods}) because the remote file system is mounted on
+the local host and @value{tramp} accesses it by changing the
 @code{default-directory}.
 
 @value{tramp} starts a remote process when a command is executed in a
@@ -3212,7 +3367,7 @@ integrated to work with @value{tramp}: @file{shell.el},
 
 @vindex INSIDE_EMACS@r{, environment variable}
 @value{tramp} always modifies the @env{INSIDE_EMACS} environment
-variable for remote processes.  Per default, this environment variable
+variable for remote processes.  By default, this environment variable
 shows the Emacs version.  @value{tramp} adds its own version string,
 so it looks like @samp{27.2,tramp:2.4.5.1}.  However, other packages
 might also add their name to this environment variable, like
@@ -3267,8 +3422,8 @@ local @file{.emacs} file:
 
 @vindex ENV@r{, environment variable}
 Setting the @env{ENV} environment variable instructs some shells to
-read an initialization file.  Per default, @value{tramp} has disabled
-this.  You could overwrite this behavior by evaluating
+read an initialization file.  By default, @value{tramp} disables
+this.  You can override this behavior by evaluating
 
 @lisp
 @group
@@ -3471,10 +3626,13 @@ uid=0(root) gid=0(root) groups=0(root)
 @cindex @code{gdb}
 @cindex @code{perldb}
 
-@file{gud.el} provides a unified interface to symbolic debuggers
+@file{gud.el} provides a unified interface to symbolic
 @ifinfo
-(@ref{Debuggers, , , emacs}).
+debuggers (@pxref{Debuggers, , , emacs}).
 @end ifinfo
+@ifnotinfo
+debuggers.
+@end ifnotinfo
 @value{tramp} can run debug on remote hosts by calling @code{gdb}
 with a remote file name:
 
@@ -3635,9 +3793,15 @@ minibuffer.  Each connection is of the format
 
 Flushing remote connections also cleans the password cache
 (@pxref{Password handling}), file cache, connection cache
-(@pxref{Connection caching}), and recentf cache (@pxref{File
-Conveniences, , , emacs}).  It also deletes session timers
-(@pxref{Predefined connection information}) and connection buffers.
+(@pxref{Connection caching}), and recentf
+@ifinfo
+cache (@pxref{File Conveniences, , , emacs}).
+@end ifinfo
+@ifnotinfo
+cache.
+@end ifnotinfo
+It also deletes session timers (@pxref{Predefined connection
+information}) and connection buffers.
 
 If @var{keep-debug} is non-@code{nil}, the debug buffer is kept.  A
 non-@code{nil} @var{keep-password} preserves the password cache.
@@ -4159,6 +4323,7 @@ Disable excessive traces.  Set @code{tramp-verbose} to 3 
or lower,
 default being 3.  Increase trace levels temporarily when hunting for
 bugs.
 
+
 @item
 @value{tramp} does not connect to the remote host
 
@@ -4349,7 +4514,7 @@ this @code{nil} setting:
 
 @vindex ProxyCommand@r{, ssh option}
 @vindex ProxyJump@r{, ssh option}
-This shall also be set to @code{nil} if you use the
+This should also be set to @code{nil} if you use the
 @option{ProxyCommand} or @option{ProxyJump} options in your
 @command{ssh} configuration.
 
@@ -4410,6 +4575,7 @@ disable @samp{--color=yes} or @samp{--color=auto} in the 
remote host's
 @file{.bashrc} or @file{.profile}.  Turn this alias on and off to see
 if file name completion works.
 
+
 @item
 File name completion does not work in directories with large number of
 files
@@ -4542,10 +4708,16 @@ HISTFILE=/dev/null
 @item
 Where are remote files trashed to?
 
-Emacs can trash file instead of deleting them, @ref{Misc File Ops,
-Trashing , , emacs}.  Remote files are always trashed to the local
-trash, except remote encrypted files (@pxref{Keeping files
-encrypted}), which are deleted anyway.
+Emacs can trash file instead of deleting
+@ifinfo
+them, @ref{Misc File Ops, Trashing , , emacs}.
+@end ifinfo
+@ifnotinfo
+them.
+@end ifnotinfo
+Remote files are always trashed to the local trash, except remote
+encrypted files (@pxref{Keeping files encrypted}), which are deleted
+anyway.
 
 If Emacs is configured to use the XDG conventions for the trash
 directory, remote files cannot be restored with the respective tools,
@@ -4802,6 +4974,7 @@ In BBDB buffer, access an entry by pressing the key 
@kbd{F}.
 
 Thanks to @value{tramp} users for contributing to these recipes.
 
+
 @item
 Why saved multi-hop file names do not work in a new Emacs session?
 
@@ -4906,6 +5079,24 @@ In case you have installed it from its Git repository, 
@ref{Recompilation}.
 
 
 @item
+I get an error @samp{tramp-file-name-handler: Invalid function:
+tramp-compat-with-mutex}
+
+Likely, you have a running Emacs session with loaded @value{tramp},
+and you try to upgrade it to another version from GNU ELPA.  Since
+@value{tramp} is not forward compatible, you must unload / reload it.
+Try the following steps:
+
+@example
+@kbd{M-x tramp-unload-tramp @key{RET}}
+@kbd{M-x load-library @key{RET} tramp @key{RET}}
+@end example
+
+If this doesn't work, you must restart Emacs with proper
+@code{load-path} for the new @value{tramp} version.
+
+
+@item
 I get an error @samp{Remote file error: Forbidden reentrant call of Tramp}
 
 @vindex remote-file-error
@@ -4913,9 +5104,9 @@ I get an error @samp{Remote file error: Forbidden 
reentrant call of Tramp}
 Timers, process filters and sentinels, and other event based functions
 can run at any time, when a remote file operation is still running.
 This can cause @value{tramp} to block.  When such a situation is
-detected, this error is triggered.  It shall be fixed in the
-respective function (an error report will help), but for the time
-being you can suppress this error by the following code in your
+detected, this error is triggered.  It should be fixed in the
+respective function (sending an error report will help), but for the
+time being you can suppress this error by the following code in your
 @file{~/.emacs}:
 
 @lisp
@@ -5098,9 +5289,9 @@ sending a string to a process, or waiting for process 
output.  They
 can run any remote file operation, which would conflict with the
 already running remote file operation, if the same connection is
 affected.  @value{tramp} detects this situation, and raises the
-@code{remote-file-error} error.  A timer function shall avoid this
-situation.  At least, it shall protect itself against this error, by
-wrapping the timer function body with
+@code{remote-file-error} error.  A timer function should avoid this
+situation.  As a minimum, it should protect itself against this error, by
+wrapping the timer function body as follows:
 
 @lisp
 @group
@@ -5152,8 +5343,8 @@ Other navigation keys are described in
 @ref{Outline Visibility, , , emacs}.
 @end ifinfo
 
-@value{tramp} handles errors internally.  But to get a Lisp backtrace,
-both the error and the signal have to be set as follows:
+@value{tramp} handles errors internally.  Hence, to get a Lisp backtrace,
+the following settings are required:
 
 @lisp
 @group
@@ -5167,15 +5358,15 @@ backtraces are also added to the @value{tramp} debug 
buffer in case of
 errors.
 
 In very rare cases it could happen, that @value{tramp} blocks Emacs.
-Killing Emacs does not allow to inspect the debug buffer.  In that
-case, you might instruct @value{tramp} to mirror the debug buffer to
-file:
+Killing Emacs does not allow inspecting the debug buffer.  In that
+case, you can instruct @value{tramp} to mirror the debug buffer to
+a file:
 
 @lisp
 (customize-set-variable 'tramp-debug-to-file t)
 @end lisp
 
-The debug buffer is written as file in your
+The debug buffer is written as a file in your
 @code{temporary-file-directory}, which is usually @file{/tmp/}.  Use
 this option with care, because it could decrease the performance of
 @value{tramp} actions.
diff --git a/etc/HISTORY b/etc/HISTORY
index a6b9f57..1d6425e 100644
--- a/etc/HISTORY
+++ b/etc/HISTORY
@@ -222,6 +222,8 @@ GNU Emacs 26.3 (2019-08-28) emacs-26.3
 
 GNU Emacs 27.1 (2020-08-10) emacs-27.1
 
+GNU Emacs 27.2 (2021-03-25) emacs-27.2
+
 
 ----------------------------------------------------------------------
 This file is part of GNU Emacs.
diff --git a/etc/NEWS b/etc/NEWS
index 3cbf2a0..2d66a93 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -24,6 +24,9 @@ applies, and please also update docstrings as needed.
 
 * Installation Changes in Emacs 28.1
 
+---
+** Support for building with Motif has been removed.
+
 ** Cairo graphics library is now used by default if found.
 '--with-cairo' is now the default, if the appropriate development files
 are found by 'configure'.  Note that building with Cairo means using
@@ -64,6 +67,11 @@ shaping, so 'configure' now recommends that combination.
 It was declared obsolete in Emacs 27.1.
 
 ---
+** The configure option '--without-makeinfo' has been removed.
+This was only ever relevant when building from a repository checkout.
+This now requires makeinfo, which is part of the texinfo package.
+
+---
 ** Support for building with '-fcheck-pointer-bounds' has been removed.
 GCC has withdrawn the '-fcheck-pointer-bounds' option and support for
 its implementation has been removed from the Linux kernel.
@@ -85,6 +93,10 @@ useful on systems such as FreeBSD which ships only with 
"etc/termcap".
 
 * Changes in Emacs 28.1
 
++++
+** New command 'font-lock-update', bound to 'C-x x f'.
+This command updates the syntax highlighting in this buffer.
+
 ** The new NonGNU ELPA archive is enabled by default alongside GNU ELPA.
 
 +++
@@ -242,12 +254,32 @@ search buffer due to too many matches being highlighted.
 The 'C-x x' keymap now holds keystrokes for various buffer-oriented
 commands.  The new keystrokes are 'C-x x g' ('revert-buffer'),
 'C-x x r' ('rename-buffer'), 'C-x x u' ('rename-uniquely'), 'C-x x n'
-('clone-buffer'), 'C-x x i' ('insert-buffer') and 'C-x x t'
-('toggle-truncate-lines').
+('clone-buffer'), 'C-x x i' ('insert-buffer'), 'C-x x t'
+('toggle-truncate-lines') and 'C-x x f' ('font-lock-update').
+
+---
+** Commands 'set-frame-width' and 'set-frame-height' can now get their
+input using the minibuffer.
 
 
 * Editing Changes in Emacs 28.1
 
++++
+** New command 'execute-extended-command-for-buffer'.
+This new command, bound to 'M-S-x', works like
+'execute-extended-command', but limits the set of commands to the
+commands that have been determined to be particularly useful with the
+current mode.
+
++++
+** New user option 'read-extended-command-predicate'.
+This user option controls how 'M-x' performs completion of commands when
+you type 'TAB'.  By default, any command that matches what you have
+typed is considered a completion candidate, but you can customize this
+option to exclude commands that are not applicable to the current
+buffer's major and minor modes, and respect the command's completion
+predicate (if any).
+
 ---
 ** 'eval-expression' now no longer signals an error on incomplete expressions.
 Previously, typing 'M-: ( RET' would result in Emacs saying "End of
@@ -286,10 +318,12 @@ Additionally, the function now accepts a HIST argument 
which can be
 used to specify a custom history variable.
 
 +++
-** Input history for 'goto-line' is now local to every buffer.
-Each buffer will keep a separate history of line numbers used with
-'goto-line'.  This should help making faster the process of finding
-line numbers that were previously jumped to.
+** Input history for 'goto-line' can now be made local to every buffer.
+In any event, line numbers used with 'goto-line' are kept in their own
+history list.  This should help make faster the process of finding
+line numbers that were previously jumped to.  By default, all buffers
+share a single history list.  To make every buffer have its own
+history list, customize the user option 'goto-line-history-local'.
 
 +++
 ** New command 'goto-line-relative' to use in a narrowed buffer.
@@ -337,25 +371,71 @@ summary of where Emacs is using memory currently.
 
 +++
 *** New commands to cycle heading visibility.
-Typing 'TAB' on a heading cycles the current section between "hide
-all", "subheadings", and "show all" state.  Typing 'S-TAB' anywhere in
-the buffer cycles the whole buffer between "only top-level headings",
-"all headings and subheadings", and "show all" states.
+Typing 'TAB' on a heading line cycles the current section between
+"hide all", "subheadings", and "show all" states.  Typing 'S-TAB'
+anywhere in the buffer cycles the whole buffer between "only top-level
+headings", "all headings and subheadings", and "show all" states.
+
+*** New user option 'outline-minor-mode-cycle'.
+This user option customizes 'outline-minor-mode', with the difference
+that 'TAB' and 'S-TAB' on heading lines cycle heading visibility.
+Typing 'TAB' on a heading line cycles the current section between
+"hide all", "subheadings", and "show all" states.  Typing 'S-TAB' on a
+heading line cycles the whole buffer between "only top-level
+headings", "all headings and subheadings", and "show all" states.
+
+*** New user option 'outline-minor-mode-highlight'.
+This user option customizes 'outline-minor-mode'.  It puts
+highlighting on heading lines using standard outline faces.  This
+works well only when there are no conflicts with faces used by the
+major mode.
 
 
 * Changes in Specialized Modes and Packages in Emacs 28.1
 
+** Benchmark
+*** New function 'benchmark-call' to measure the execution time of a function.
+Additionally, the number of repetitions can be expressed as a minimal duration
+in seconds.
+
+** Macroexp
+---
+*** New function 'macroexp-file-name' to know the name of the current file.
+---
+*** New function 'macroexp-compiling-p' to know if we're compiling.
+---
+*** New function 'macroexp-warn-and-return' to help emit warnings.
+This used to be named 'macroexp--warn-and-return' and has proved useful
+and well-behaved enough to lose the "internal" marker.
+
 ** 'blink-cursor-mode' is now enabled by default regardless of the UI.
 It used to be enabled when Emacs is started in GUI mode but not when started
 in text mode.  The cursor still only actually blinks in GUI frames.
 
+** Bindat
+
++++
+*** New 'Bindat type expression' description language.
+This new system is provided by the new macro 'bindat-type' and
+obsoletes the old data layout specifications.  It supports
+arbitrary-size integers, recursive types, and more.  See the Info node
+"(elisp) Byte Packing" in the ELisp manual for more details.
+
 ** pcase
 
 +++
+*** The 'or' pattern now binds the union of the vars of its sub-patterns.
+If a variable is not bound by the subpattern that matched, it gets bound
+to nil.  This was already sometimes the case, but it is now guaranteed.
+
++++
 *** The 'pred' pattern can now take the form '(pred (not FUN))'.
 This is like '(pred (lambda (x) (not (FUN x))))' but results
 in better code.
 
+---
+*** New function 'pcase-compile-patterns' to write other macros.
+
 +++
 ** profiler.el
 The results displayed by 'profiler-report' now have the usage figures
@@ -455,9 +535,44 @@ It can be used to enable/disable the tab bar individually 
on each frame
 independently from the value of 'tab-bar-mode' and 'tab-bar-show'.
 
 ---
+*** New user option 'tab-bar-format' defines a list of tab bar items.
+When it contains 'tab-bar-format-global' (possibly appended after
+'tab-bar-format-align-right'), then after enabling 'display-time-mode'
+(or any other mode that uses 'global-mode-string') it displays time
+aligned to the right on the tab bar instead of the mode line.
+When 'tab-bar-format-tabs' is replaced with 'tab-bar-format-tabs-groups',
+then the tab bar displays tab groups.
+
+---
+*** 'Mod-9' bound to 'tab-last' now switches to the last tab.
+It also supports a negative argument.
+
+---
+*** New command 'tab-duplicate' bound to 'C-x t n'.
+
+---
+*** 'C-x t N' creates a new tab at the specified absolute position.
+It also supports a negative argument.
+
+---
+*** 'C-x t M' moves the current tab to the specified absolute position.
+It also supports a negative argument.
+
+---
+*** 'C-x t G' assigns a group name to the tab.
+'tab-close-group' can close all tabs that belong to the selected group.
+The user option 'tab-bar-new-tab-group' defines the default group of a
+new tab.  After customizing 'tab-bar-tab-post-change-group-functions'
+to 'tab-bar-move-tab-to-group', changing the tab group will also move it
+closer to other tabs in the same group.
+
+---
 *** New user option 'tab-bar-tab-name-format-function'.
 
 ---
+*** New user option 'tab-line-tab-name-format-function'.
+
+---
 *** The tabs in the tab line can now be scrolled using horizontal scroll.
 If your mouse or trackpad supports it, you can now scroll tabs when
 the mouse pointer is in the tab line by scrolling left or right.
@@ -786,10 +901,12 @@ instances.
 Emacs can be defined as a handler for the "x-scheme-handler/mailto"
 MIME type with the following command: "emacs -f message-mailto %u".
 An "emacs-mail.desktop" file has been included, suitable for
-installing in desktop directories like "/usr/share/applications".
+installing in desktop directories like "/usr/share/applications" or
+"~/.local/share/applications".
 Clicking on a 'mailto:' link in other applications will then open
 Emacs with headers filled out according to the link, e.g.
-"mailto:larsi@gnus.org?subject=This+is+a+test";.
+"mailto:larsi@gnus.org?subject=This+is+a+test";.  If you prefer
+emacsclient, use "emacsclient -e '(message-mailto "%u")'"
 
 ---
 *** Change to default value of 'message-draft-headers' user option.
@@ -830,6 +947,15 @@ skipped.
 ** Help
 
 ---
+*** Keybindings in 'help-mode' use the new 'help-key-binding' face.
+This face is added by 'substitute-command-keys' to any "\[command]"
+substitution.  The return value of that function should consequently
+be assumed to be a propertized string.
+
+Note that the new face will also be used in tooltips.  When using the
+GTK toolkit, this is only true if 'x-gtk-use-system-tooltips' is t.
+
+---
 *** 'g' ('revert-buffer') in 'help-mode' no longer requires confirmation.
 
 +++
@@ -932,21 +1058,41 @@ To customize obsolete user options, use 
'customize-option' or
 
 ** Edebug
 
+*** Obsoletions
+---
+**** 'get-edebug-spec' is obsolete, replaced by 'edebug-get-spec'.
++++
+**** The spec operator ':name NAME' is obsolete, use '&name' instead.
++++
+**** The spec element 'function-form' is obsolete, use 'form' instead.
+
 +++
-*** Edebug specification lists can use the new keyword '&error', which
-unconditionally aborts the current edebug instrumentation with the
-supplied error message.
+*** New function 'def-edebug-elem-spec' to define Edebug spec elements.
+These used to be defined with 'def-edebug-spec' thus conflating the
+two name spaces, which lead to name collisions.
+The use of 'def-edebug-spec' to define Edebug spec elements is
+declared obsolete.
 
-*** Edebug specification lists can use the new keyword ':unique',
-which appends a unique suffix to the Edebug name of the current
-definition.
+*** Edebug specification lists can use some new keywords:
+
++++
+**** '&interpose SPEC FUN ARGS..' lets FUN control parsing after SPEC.
+More specifically, FUN is called with 'HEAD PF ARGS..' where
+PF is a parsing function that expects a single argument (the specs to
+use) and HEAD is the code that matched SPEC.
+
++++
+**** '&error MSG' unconditionally aborts the current edebug instrumentation.
+
++++
+**** '&name SPEC FUN' extracts the current name from the code matching SPEC.
 
 ** ElDoc
 
 +++
 *** New user option 'eldoc-echo-area-display-truncation-message'.
 If non-nil (the default), eldoc will display a message saying
-something like "(Documentation truncated. Use `M-x eldoc-doc-buffer'
+something like "(Documentation truncated.  Use `M-x eldoc-doc-buffer'
 to see rest)" when a message has been truncated.  If nil, truncated
 messages will be marked with just "..." at the end.
 
@@ -969,7 +1115,7 @@ separate buffer, or a tooltip.
 *** New user option 'eldoc-documentation-strategy'.
 The built-in choices available for this user option let users compose
 the results of 'eldoc-documentation-functions' in various ways, even
-if some of those functions are sychronous and some asynchchronous.
+if some of those functions are synchronous and some asynchronous.
 The user option replaces 'eldoc-documentation-function', which is now
 obsolete.
 
@@ -1015,6 +1161,10 @@ preferred over the eudcb-mab.el backend.
 like cell phones, tablets or cameras.
 
 +++
+*** New connection method "sshfs", which allows accessing remote files
+via a file system mounted with 'sshfs'.
+
++++
 *** Trashed remote files are moved to the local trash directory.
 All remote files, which are trashed, are moved to the local trash
 directory.  Except remote encrypted files, which are always deleted.
@@ -1054,9 +1204,19 @@ effect.
 A pattern like '(map :sym)' binds the map's value for ':sym' to 'sym',
 equivalent to '(map (:sym sym))'.
 
+---
+*** The function 'map-copy' now uses 'copy-alist' on alists.
+This is a slightly deeper copy than the previous 'copy-sequence'.
+
+---
+*** The function 'map-contains-key' now supports plists.
+
 ** Package
 
 +++
+*** New command 'package-browse-url' and keystroke 'w'.
+
++++
 *** New commands to filter the package list.
 The filter commands are bound to the following keys:
 
@@ -1303,9 +1463,9 @@ decaying average of delays, and if this number gets too 
high, the
 animation is stopped.
 
 +++
-*** The 'n' and 'p' commands (next/previous image) now respects dired order.
+*** The 'n' and 'p' commands (next/previous image) now respect Dired order.
 These commands would previously display the next/previous image in
-alphabetical order, but will now find the "parent" dired buffer and
+lexicographic order, but will now find the "parent" Dired buffer and
 select the next/previous image file according to how the files are
 sorted there.  The commands have also been extended to work when the
 "parent" buffer is an archive mode (i.e., zip file or the like) or tar
@@ -1335,6 +1495,22 @@ To load images with the default frame colors use the 
':foreground' and
 This change only affects image types that support foreground and
 background colors or transparency, such as xbm, pbm, svg, png and gif.
 
++++
+*** Image smoothing can now be explicitly enabled or disabled.
+Smoothing applies a bilinear filter while scaling or rotating an image
+to prevent aliasing and other unwanted effects.  The new image
+property ':transform-smoothing' can be set to t to force smoothing
+and nil to disable smoothing.
+
+The default behaviour of smoothing on down-scaling and not smoothing
+on up-scaling remains unchanged.
+
++++
+*** New user option 'image-transform-smoothing'.
+This controls whether to use smoothing or not for an image.  Values
+include nil (no smoothing), t (do smoothing) or a predicate function
+that's called with the image object and should return nil/t.
+
 ** EWW
 
 +++
@@ -1399,6 +1575,11 @@ project's root directory, respectively.
 +++
 *** New user option 'project-list-file'.
 
++++
+*** New command 'project-remove-known-project'.
+This command lets you interactively remove an entry from the list of projects
+in 'project-list-file'.
+
 ** xref
 
 ---
@@ -1425,7 +1606,7 @@ have been renamed to have "proper" public names and 
documented
 'xref-show-definitions-buffer-at-bottom').
 
 *** New command 'xref-quit-and-pop-marker-stack' and a binding for it
-in "*xref*" buffers ('M-,'). This combination is easy to press
+in "*xref*" buffers ('M-,').  This combination is easy to press
 semi-accidentally if the user wants to go back in the middle of
 choosing the exact definition to go to, and this should do TRT.
 
@@ -1443,6 +1624,16 @@ component are now rejected by 'json-read' and friends.  
This makes
 them more compliant with the JSON specification and consistent with
 the native JSON parsing functions.
 
+---
+*** Some JSON encoding functions are now obsolete.
+The functions 'json-encode-number', 'json-encode-hash-table',
+'json-encode-key', and 'json-encode-list' are now obsolete.
+
+The first two are kept as aliases of 'json-encode', which should be
+used instead.  Uses of 'json-encode-list' should be changed to call
+one of 'json-encode', 'json-encode-alist', 'json-encode-plist', or
+'json-encode-array' instead.
+
 ** xml.el
 
 *** XML serialization functions now reject invalid characters.
@@ -1664,6 +1855,10 @@ If this is bound to something non-nil, functions like
 This is a plain 2D button, but uses the background color instead of
 the foreground color.
 
+---
+*** New face 'shortdoc-heading'.
+Applies to headings of shortdoc sections.
+
 +++
 *** New predicate functions 'length<', 'length>' and 'length='.
 Using these functions may be more efficient than using 'length' (if
@@ -1749,6 +1944,12 @@ highlight the current error message in the 'next-error' 
buffer.
 This user option can be also customized to keep highlighting on all
 visited errors, so you can have an overview what errors were already visited.
 
+---
+*** New choice 'next-error-quit-window' for 'next-error-found-function'.
+When 'next-error-found-function' is customized to 'next-error-quit-window',
+then typing the numeric prefix argument 0 before the command 'next-error'
+will quit the source window after visiting the next occurrence.
+
 +++
 *** New user option 'tab-first-completion'.
 If 'tab-always-indent' is 'complete', this new user option can be used to
@@ -1994,7 +2195,7 @@ messages, contain the error name of that message now.
 +++
 *** D-Bus events have changed their internal structure.
 They carry now the destination and the error-name of an event.  They
-also keep the type information of their arguments. Use the
+also keep the type information of their arguments.  Use the
 'dbus-event-*' accessor functions.
 
 ** CPerl Mode
@@ -2018,6 +2219,26 @@ could have saved enough typing by using an abbrev, a 
hint will be
 displayed in the echo area, mentioning the abbrev that could have been
 used instead.
 
+** Octave Mode
+
++++
+*** Line continuations in double-quoted strings now use a backslash.
+Typing 'C-M-j' (bound to 'octave-indent-new-comment-line') now follows
+the behavior introduced in Octave 3.8 of using a backslash as a line
+continuation marker within double-quoted strings, and an ellipsis
+everywhere else.
+
+** Repeat
+
++++
+*** New transient mode 'repeat-mode' to allow shorter key sequences.
+You can type 'C-x u u' instead of 'C-x u C-x u' to undo many changes,
+'C-x o o' instead of 'C-x o C-x o' to switch several windows,
+'C-x { { } } ^ ^ v v' to resize the selected window interactively,
+'M-g n n p p' to navigate next-error matches.  Any other key exits
+transient mode and then is executed normally.  'repeat-exit-key'
+defines an additional key to exit mode like 'isearch-exit' ('RET').
+
 
 * New Modes and Packages in Emacs 28.1
 
@@ -2048,6 +2269,30 @@ first).
 
 * Incompatible Editing Changes in Emacs 28.1
 
+** The 'M-o' ('facemenu-keymap') global binding has been removed.
+To restore the old binding, say something like:
+
+    (require 'facemenu)
+    (define-key global-map "\M-o" 'facemenu-keymap)
+    (define-key facemenu-keymap "\es" 'center-line)
+    (define-key facemenu-keymap "\eS" 'center-paragraph)
+
+The last two lines are not strictly necessary if you don't care about
+having those two commands on the 'M-o' keymap; see the next section.
+
+** The 'M-o M-s' and 'M-o M-S' global bindings have been removed.
+Use 'M-x center-line' and 'M-x center-paragraph' instead.  See the
+previous section for how to get back the old bindings.  Alternatively,
+if you only want these two commands to have global bindings they had
+before, you can add the following to your init file:
+
+  (define-key global-map "\M-o\M-s" 'center-line)
+  (define-key global-map "\M-o\M-S" 'center-paragraph)
+
+** The 'M-o M-o' global binding has been removed.
+Use 'M-x font-lock-fontify-block' instead, or the new 'C-x x f'
+command, which updates the syntax highlighting in the current buffer.
+
 ** In 'f90-mode', the backslash character ('\') no longer escapes.
 For about a decade, the backslash character has no longer had a
 special escape syntax in Fortran F90.  To get the old behaviour back,
@@ -2062,9 +2307,19 @@ since the latter uses 'M-s' as a prefix key of the 
search prefix map.
 ** 'vc-print-branch-log' shows the change log for BRANCH from its root
 directory instead of the default directory.
 
+---
+** 'project-shell' and 'shell' now use 'pop-to-buffer-same-window'.
+This is to keep the same behavior as Eshell.
+
 
 * Incompatible Lisp Changes in Emacs 28.1
 
+** 'facemenu-color-alist' is now obsolete, and is not used.
+
+** 'facemenu.el' is no longer preloaded.
+To use functions/variables from the package, you now have to say
+'(require 'facemenu)' or similar.
+
 ** 'pcomplete-ignore-case' is now an obsolete alias of 
'completion-ignore-case'.
 
 ** 'completions-annotations' face is not used when the caller puts own face.
@@ -2124,7 +2379,7 @@ by mistake and were not useful to Lisp code.
 
 ---
 ** Loading 'generic-x' unconditionally loads all modes.
-The user option `generic-extras-enable-list' is now obsolete, and
+The user option 'generic-extras-enable-list' is now obsolete, and
 setting it has no effect.
 
 ---
@@ -2138,7 +2393,10 @@ This is no longer supported, and setting this variable 
has no effect.
 Use macro 'with-current-buffer-window' with action alist entry 'body-function'.
 
 ---
-** The metamail.el library is now marked obsolete.
+** The inversion.el library is now obsolete.
+
+---
+** The metamail.el library is now obsolete.
 
 ---
 ** Some obsolete variable and function aliases in dbus.el have been removed.
@@ -2168,18 +2426,21 @@ ledit.el, lmenu.el, lucid.el and old-whitespace.el.
 'dirtrack-debug-toggle', 'dynamic-completion-table',
 'easy-menu-precalculate-equivalent-keybindings',
 'epa-display-verify-result', 'epg-passphrase-callback-function',
-'eshell-report-bug', 'eval-next-after-load', 'exchange-dot-and-mark',
-'ffap-bug', 'ffap-submit-bug', 'ffap-version',
-'file-cache-choose-completion', 'forward-point', 'generic-char-p',
-'global-highlight-changes', 'hi-lock-face-history',
-'hi-lock-regexp-history', 'highlight-changes-active-string',
-'highlight-changes-initial-state', 'highlight-changes-passive-string',
-'image-mode-maybe', 'imenu-example--name-and-position',
-'ispell-aspell-supports-utf8', 'lisp-mode-auto-fill',
-'locate-file-completion', 'make-coding-system',
+'erc-announced-server-name', 'erc-default-coding-system',
+'erc-process', 'erc-send-command', 'eshell-report-bug',
+'eval-next-after-load', 'exchange-dot-and-mark', 'ffap-bug',
+'ffap-submit-bug', 'ffap-version', 'file-cache-choose-completion',
+'forward-point', 'generic-char-p', 'global-highlight-changes',
+'hi-lock-face-history', 'hi-lock-regexp-history',
+'highlight-changes-active-string', 'highlight-changes-initial-state',
+'highlight-changes-passive-string',
+'icalendar--datetime-to-noneuropean-date', 'image-mode-maybe',
+'imenu-example--name-and-position', 'ispell-aspell-supports-utf8',
+'lisp-mode-auto-fill', 'locate-file-completion', 'make-coding-system',
 'minibuffer-local-must-match-filename-map', 'mouse-choose-completion',
 'mouse-major-mode-menu', 'mouse-popup-menubar',
 'mouse-popup-menubar-stuff', 'newsticker-groups-filename',
+'nnir-swish-e-index-file', 'nnmail-fix-eudora-headers',
 'non-iso-charset-alist', 'nonascii-insert-offset',
 'nonascii-translation-table', 'password-read-and-add',
 'pre-abbrev-expand-hook', 'princ-list', 'print-help-return-message',
@@ -2212,7 +2473,8 @@ ledit.el, lmenu.el, lucid.el and old-whitespace.el.
 'semantic-token-type-parent', 'semantic-toplevel-bovine-cache',
 'semantic-toplevel-bovine-table', 'semanticdb-mode-hooks',
 'set-coding-priority', 'set-process-filter-multibyte',
-'shadows-compare-text-p', 'shell-dirtrack-toggle', 't-mouse-mode',
+'shadows-compare-text-p', 'shell-dirtrack-toggle',
+'speedbar-navigating-speed', 'speedbar-update-speed', 't-mouse-mode',
 'term-dynamic-simple-complete', 'tooltip-hook', 'tpu-have-ispell',
 'url-generate-unique-filename', 'url-temporary-directory',
 'vc-arch-command', 'vc-default-working-revision' (variable),
@@ -2220,6 +2482,12 @@ ledit.el, lmenu.el, lucid.el and old-whitespace.el.
 'vcursor-toggle-vcursor-map', 'w32-focus-frame', 'w32-select-font',
 'wisent-lex-make-token-table'.
 
+---
+** Some functions and variables obsolete since Emacs 22 have been removed:
+'gnus-article-hide-pgp-hook', 'gnus-inews-mark-gcc-as-read',
+'gnus-treat-display-xface', 'gnus-treat-strip-pgp',
+'nnmail-spool-file'.
+
 ** The WHEN argument of 'make-obsolete' and related functions is mandatory.
 The use of those functions without a WHEN argument was marked obsolete
 back in Emacs 23.1.  The affected functions are: 'make-obsolete',
@@ -2228,10 +2496,63 @@ back in Emacs 23.1.  The affected functions are: 
'make-obsolete',
 
 ** The variable 'keyboard-type' is obsolete and not dynamically scoped any 
more.
 
+** The 'values' variable is now obsolete.
+
 
 * Lisp Changes in Emacs 28.1
 
-** The 'values' variable is now obsolete.
++++
+** 'unlock-buffer' displays warnings instead of signaling.
+Instead of signaling 'file-error' conditions for file system level
+errors, the function now calls 'display-warning' and continues as if
+the error did not occur.
+
++++
+** New function 'always'.
+This is identical to 'ignore', but returns t instead.
+
++++
+** New forms to declare how completion should happen has been added.
+'(declare (completion PREDICATE))' can be used as a general predicate
+to say whether the command should be present when completing with
+'M-x TAB'.  '(declare (modes MODE...))' can be used as a short-hand
+way of saying that the command should be present when completing from
+buffers in major modes derived from MODE..., or, if it's a minor mode,
+whether that minor mode is enabled in the current buffer.
+
++++
+** The 'interactive' syntax has been extended to allow listing applicable 
modes.
+Forms like '(interactive "p" dired-mode)' can be used to annotate the
+commands as being applicable for modes derived from 'dired-mode',
+or if the mode is a minor mode, that the current buffer has that
+minor mode activated.  Note that using this form will create byte code
+that is not compatible with byte code in previous Emacs versions.
+
++++
+** New buffer-local variable 'local-minor-modes'.
+This permanently buffer-local variable holds a list of currently
+enabled non-global minor modes in the current buffer (as a list of
+symbols).
+
++++
+** New variable 'global-minor-modes'.
+This variable holds a list of currently enabled global minor modes (as
+a list of symbols).
+
++++
+** 'define-minor-mode'  now takes an ':interactive' argument.
+This can be used for specifying which modes this minor mode is meant
+for, or to make the new minor mode non-interactive.  The default value
+is t.
+
++++
+** 'define-derived-mode' now takes an ':interactive' argument.
+This can be used to control whether the defined mode is a command
+or not, and is useful when defining commands that aren't meant to be
+used by users directly.
+
+---
+** The 'easymenu' library is now preloaded.
 
 ---
 ** New variable 'indent-line-ignored-functions'.
@@ -2262,6 +2583,13 @@ and display the result.
 When non-nil, then functions 'read-char-choice' and 'y-or-n-p' (respectively)
 use the function 'read-key' to read a character instead of using the 
minibuffer.
 
+---
+** New user option 'use-short-answers'.
+When non-nil, the function 'y-or-n-p' is used instead of
+'yes-or-no-p'.  This eliminates the need to define an alias that maps
+one to another in the init file.  The same user option also controls
+whether the function 'read-answer' accepts short answers.
+
 +++
 ** 'set-window-configuration' now takes an optional 'dont-set-frame'
 parameter which, when non-nil, instructs the function not to select
@@ -2338,6 +2666,12 @@ This function can be used by modes to add elements to the
 'choice' customization type of a variable.
 
 +++
+** New function 'require-theme'.
+This function is like 'require', but searches 'custom-theme-load-path'
+instead of 'load-path'.  It can be used by Custom themes to load
+supporting Lisp files when 'require' is unsuitable.
+
++++
 ** New function 'file-modes-number-to-symbolic' to convert a numeric
 file mode specification into symbolic form.
 
@@ -2456,7 +2790,7 @@ menu handling.
 It is meant as an (experimental) aid for converting Emacs Lisp code
 to lexical binding, where dynamic (special) variables bound in one
 file can affect code in another.  For details, see the manual section
-"(Elisp) Converting to Lexical Binding".
+"(elisp) Converting to Lexical Binding".
 
 +++
 *** 'byte-recompile-directory' can now compile symlinked ".el" files.
@@ -2527,6 +2861,17 @@ locales.  They are also available as aliases 
'ebcdic-cp-*' (e.g.,
 'cp278' for 'ibm278').  There are also new charsets 'ibm2xx' to
 support these coding-systems.
 
+** The JSON functions 'json-serialize', 'json-insert',
+'json-parse-string', and 'json-parse-buffer' now implement some of the
+semantics of RFC 8259 instead of the earlier RFC 4627.  In particular,
+these functions now accept top-level JSON values that are neither
+arrays nor objects.
+
+---
+** 'while-no-input-ignore-events' accepts more special events.
+The special events 'dbus-event' and 'file-notify' are now ignored in
+'while-no-input' when added to this variable.
+
 
 * Changes in Emacs 28.1 on Non-Free Operating Systems
 
diff --git a/etc/NEWS.19 b/etc/NEWS.19
index f2cef62..fd91c08 100644
--- a/etc/NEWS.19
+++ b/etc/NEWS.19
@@ -4011,6 +4011,7 @@ The third component is now determined on the basis of the 
names of the
 existing executable files.  This means that version.el is not altered
 by building Emacs.
 
+** New macro 'easy-menu-define'
 
 
 * Changes in 19.22.
diff --git a/etc/NEWS.27 b/etc/NEWS.27
index 9232a30..55045d1 100644
--- a/etc/NEWS.27
+++ b/etc/NEWS.27
@@ -15,18 +15,6 @@ in older Emacs versions.
 You can narrow news to a specific version by calling 'view-emacs-news'
 with a prefix argument or by typing 'C-u C-h C-n'.
 
-Temporary note:
-+++ indicates that all relevant manuals in doc/ have been updated.
---- means no change in the manuals is needed.
-When you add a new item, use the appropriate mark if you are sure it
-applies, and please also update docstrings as needed.
-
-
-* Installation Changes in Emacs 27.2
-
-
-* Startup Changes in Emacs 27.2
-
 
 * Changes in Emacs 27.2
 
@@ -41,9 +29,6 @@ frame using the new function 'fit-mini-frame-to-buffer' which 
won't
 skip leading or trailing empty lines of the buffer.
 
 
-* Editing Changes in Emacs 27.2
-
-
 * Changes in Specialized Modes and Packages in Emacs 27.2
 
 ** Tramp
@@ -51,15 +36,6 @@ skip leading or trailing empty lines of the buffer.
 *** The user option 'tramp-completion-reread-directory-timeout' is now 
obsolete.
 
 
-* New Modes and Packages in Emacs 27.2
-
-
-* Incompatible Lisp Changes in Emacs 27.2
-
-
-* Lisp Changes in Emacs 27.2
-
-
 * Changes in Emacs 27.2 on Non-Free Operating Systems
 
 ** Emacs now ignores modifier keys when IME input is used.
@@ -990,7 +966,6 @@ the entire list as before.  An integer value limits the 
list length
 
 *** 'vc-git-stash' is now bound to 'C' in the stash headers.
 
---
 *** Some stash keybindings are now available in the stash button.
 'vc-git-stash' and 'vc-git-stash-snapshot' can now be run using 'C'
 and 'S' respectively, including when there are no stashes.
diff --git a/etc/ORG-NEWS b/etc/ORG-NEWS
index 2cae8b9..2b9cbf3 100644
--- a/etc/ORG-NEWS
+++ b/etc/ORG-NEWS
@@ -747,7 +747,7 @@ removed.
 For those who hate breaking changes, even though the changes are made
 to clean things up; fear not.  ATTACH_DIR will still continue to work.
 It's just not documented any longer.  When you get the chance, run the
-code above to clean things up anyways!
+code above to clean things up anyway!
 
 **** New hooks
 Two hooks are added to org-attach:
diff --git a/etc/compilation.txt b/etc/compilation.txt
index e56d3b6..01d4df1b0 100644
--- a/etc/compilation.txt
+++ b/etc/compilation.txt
@@ -692,3 +692,11 @@ COPYING PERMISSIONS:
 
     You should have received a copy of the GNU General Public License
     along with this program.  If not, see <https://www.gnu.org/licenses/>.
+
+
+;;; Local Variables:
+;;; outline-regexp: "\\*\\_>"
+;;; outline-minor-mode-cycle: t
+;;; outline-minor-mode-highlight: t
+;;; eval: (outline-minor-mode 1)
+;;; End:
diff --git a/etc/emacs-mail.desktop b/etc/emacs-mail.desktop
index 3a96b9e..0c5fab1 100644
--- a/etc/emacs-mail.desktop
+++ b/etc/emacs-mail.desktop
@@ -2,6 +2,8 @@
 Categories=Network;Email;
 Comment=GNU Emacs is an extensible, customizable text editor - and more
 Exec=emacs -f message-mailto %u
+# If you prefer to use emacsclient, use this instead
+#Exec=emacsclient -e '(message-mailto "%u")'
 Icon=emacs
 Name=Emacs (Mail)
 MimeType=x-scheme-handler/mailto;
diff --git a/etc/facemenu-removal.txt b/etc/facemenu-removal.txt
new file mode 100644
index 0000000..9a969df
--- /dev/null
+++ b/etc/facemenu-removal.txt
@@ -0,0 +1,20 @@
+`facemenu-keymap' (normally bound to `M-o') has been disabled.
+==============================================================
+
+We've disabled the normal `M-o' keymap for a month (until March the
+10th, 2021) in the development version of Emacs to see whether anybody
+uses this feature.
+
+If the removal of this key binding doesn't annoy too many people, the
+plan is to then leave the it unbound, for usage by third-party
+packages and users.
+
+If you wish to restore the binding during the trial period, you can
+put the following in your .emacs file:
+
+(facemenu-keymap-restore)
+
+After the trial period is over, the function will be removed.
+
+If you wish to protest the removal of the `M-o' key binding, please
+send your thoughts to the emacs-devel@gnu.org mailing list.
diff --git a/etc/grep.txt b/etc/grep.txt
index b5b7845..0370ae4 100644
--- a/etc/grep.txt
+++ b/etc/grep.txt
@@ -102,6 +102,7 @@ grep -nH -e "xyzxyz" ../info/*
 ../info/emacs-2 1205 inserts `xyzxyzxyzxyz' in the current buffer.
 
 
+* Miscellaneous
 
 Copyright (C) 2005-2021 Free Software Foundation, Inc.
 
@@ -124,4 +125,7 @@ COPYING PERMISSIONS:
 ;;; Local Variables:
 ;;; eval: (let ((inhibit-read-only t) (compilation-filter-start (point-min))) 
(save-excursion (goto-char (point-max)) (grep-filter) (set-buffer-modified-p 
nil)))
 ;;; buffer-read-only: t
+;;; outline-minor-mode-cycle: t
+;;; outline-minor-mode-highlight: t
+;;; eval: (outline-minor-mode 1)
 ;;; End:
diff --git a/etc/schema/OpenDocument-schema-v1.3+libreoffice.rnc 
b/etc/schema/OpenDocument-schema-v1.3+libreoffice.rnc
new file mode 100644
index 0000000..5239c84
--- /dev/null
+++ b/etc/schema/OpenDocument-schema-v1.3+libreoffice.rnc
@@ -0,0 +1,892 @@
+# Open Document Format for Office Applications (OpenDocument) Version 1.3
+# OASIS Standard, In progress
+# Relax-NG Schema
+# Source: https://tools.oasis-open.org/version-control/svn/office/
+# Copyright (c) OASIS Open 2002-2015. All Rights Reserved.
+#
+# All capitalized terms in the following text have the meanings assigned to 
them
+# in the OASIS Intellectual Property Rights Policy (the "OASIS IPR Policy"). 
The
+# full Policy may be found at the OASIS website.
+#
+# This document and translations of it may be copied and furnished to others, 
and
+# derivative works that comment on or otherwise explain it or assist in its
+# implementation may be prepared, copied, published, and distributed, in whole 
or
+# in part, without restriction of any kind, provided that the above copyright
+# notice and this section are included on all such copies and derivative works.
+# However, this document itself may not be modified in any way, including by
+# removing the copyright notice or references to OASIS, except as needed for 
the
+# purpose of developing any document or deliverable produced by an OASIS
+# Technical Committee (in which case the rules applicable to copyrights, as set
+# forth in the OASIS IPR Policy, must be followed) or as required to translate 
it
+# into languages other than English.
+#
+# The limited permissions granted above are perpetual and will not be revoked 
by
+# OASIS or its successors or assigns.
+#
+# This document and the information contained herein is provided on an "AS IS"
+# basis and OASIS DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT 
NOT
+# LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION HEREIN WILL NOT
+# INFRINGE ANY OWNERSHIP RIGHTS OR ANY IMPLIED WARRANTIES OF MERCHANTABILITY OR
+# FITNESS FOR A PARTICULAR PURPOSE.
+
+namespace anim = "urn:oasis:names:tc:opendocument:xmlns:animation:1.0"
+namespace calcext =
+  "urn:org:documentfoundation:names:experimental:calc:xmlns:calcext:1.0"
+namespace chart = "urn:oasis:names:tc:opendocument:xmlns:chart:1.0"
+namespace chartooo = "http://openoffice.org/2010/chart";
+namespace config = "urn:oasis:names:tc:opendocument:xmlns:config:1.0"
+namespace css3t = "http://www.w3.org/TR/css3-text/";
+namespace db = "urn:oasis:names:tc:opendocument:xmlns:database:1.0"
+namespace dc = "http://purl.org/dc/elements/1.1/";
+namespace dr3d = "urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0"
+namespace draw = "urn:oasis:names:tc:opendocument:xmlns:drawing:1.0"
+namespace drawooo = "http://openoffice.org/2010/draw";
+namespace field =
+  "urn:openoffice:names:experimental:ooo-ms-interop:xmlns:field:1.0"
+namespace fo =
+  "urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0"
+namespace form = "urn:oasis:names:tc:opendocument:xmlns:form:1.0"
+namespace grddl = "http://www.w3.org/2003/g/data-view#";
+namespace loext =
+  "urn:org:documentfoundation:names:experimental:office:xmlns:loext:1.0"
+namespace math = "http://www.w3.org/1998/Math/MathML";
+namespace meta = "urn:oasis:names:tc:opendocument:xmlns:meta:1.0"
+namespace number = "urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0"
+namespace office = "urn:oasis:names:tc:opendocument:xmlns:office:1.0"
+namespace officeooo = "http://openoffice.org/2009/office";
+namespace presentation =
+  "urn:oasis:names:tc:opendocument:xmlns:presentation:1.0"
+namespace rng = "http://relaxng.org/ns/structure/1.0";
+namespace script = "urn:oasis:names:tc:opendocument:xmlns:script:1.0"
+namespace smil =
+  "urn:oasis:names:tc:opendocument:xmlns:smil-compatible:1.0"
+namespace style = "urn:oasis:names:tc:opendocument:xmlns:style:1.0"
+namespace svg =
+  "urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0"
+namespace table = "urn:oasis:names:tc:opendocument:xmlns:table:1.0"
+namespace tableooo = "http://openoffice.org/2009/table";
+namespace text = "urn:oasis:names:tc:opendocument:xmlns:text:1.0"
+namespace xforms = "http://www.w3.org/2002/xforms";
+namespace xhtml = "http://www.w3.org/1999/xhtml";
+namespace xlink = "http://www.w3.org/1999/xlink";
+
+include "OpenDocument-schema-v1.3.rnc" {
+  office-document-common-attrs =
+    attribute office:version {
+      # FIXME remove this hack once we write 1.3
+      "1.3" | "1.2"
+    }
+    & attribute grddl:transformation {
+        list { anyIRI* }
+      }?
+  style-graphic-properties-attlist =
+    attribute draw:stroke { "none" | "dash" | "solid" }?
+    & attribute draw:stroke-dash { styleNameRef }?
+    & attribute draw:stroke-dash-names { styleNameRefs }?
+    & attribute svg:stroke-width { length }?
+    & attribute svg:stroke-color { color }?
+    & attribute draw:marker-start { styleNameRef }?
+    & attribute draw:marker-end { styleNameRef }?
+    & attribute draw:marker-start-width { length }?
+    & attribute draw:marker-end-width { length }?
+    & attribute draw:marker-start-center { boolean }?
+    & attribute draw:marker-end-center { boolean }?
+    & attribute svg:stroke-opacity {
+        xsd:double { minInclusive = "0" maxInclusive = "1" }
+        | zeroToHundredPercent
+      }?
+    & attribute draw:stroke-linejoin {
+        "miter" | "round" | "bevel" | "middle" | "none"
+      }?
+    & attribute svg:stroke-linecap { "butt" | "square" | "round" }?
+    & attribute draw:symbol-color { color }?
+    & attribute text:animation {
+        "none" | "scroll" | "alternate" | "slide"
+      }?
+    & attribute text:animation-direction {
+        "left" | "right" | "up" | "down"
+      }?
+    & attribute text:animation-start-inside { boolean }?
+    & attribute text:animation-stop-inside { boolean }?
+    & attribute text:animation-repeat { nonNegativeInteger }?
+    & attribute text:animation-delay { duration }?
+    & attribute text:animation-steps { length }?
+    & attribute draw:auto-grow-width { boolean }?
+    & attribute draw:auto-grow-height { boolean }?
+    & # FIXME remove this once the export bug is fixed
+      attribute draw:fit-to-size {
+        "true" | "false" | "all" | "shrink-to-fit"
+      }?
+    & attribute draw:fit-to-contour { boolean }?
+    & attribute draw:textarea-vertical-align {
+        "top" | "middle" | "bottom" | "justify"
+      }?
+    & attribute draw:textarea-horizontal-align {
+        "left" | "center" | "right" | "justify"
+      }?
+    & attribute fo:wrap-option { "no-wrap" | "wrap" }?
+    & attribute style:shrink-to-fit { boolean }?
+    & attribute draw:color-mode {
+        "greyscale" | "mono" | "watermark" | "standard"
+      }?
+    & attribute draw:color-inversion { boolean }?
+    & attribute draw:luminance { signedZeroToHundredPercent }
+      # https://issues.oasis-open.org/browse/OFFICE-3821
+      ?
+    & attribute draw:contrast { percent }?
+    & attribute draw:gamma { percent }?
+    & attribute draw:red { signedZeroToHundredPercent }?
+    & attribute draw:green { signedZeroToHundredPercent }?
+    & attribute draw:blue { signedZeroToHundredPercent }?
+    & attribute draw:image-opacity { zeroToHundredPercent }?
+    & attribute draw:shadow { "visible" | "hidden" }?
+    & attribute draw:shadow-offset-x { length }?
+    & attribute draw:shadow-offset-y { length }?
+    & attribute draw:shadow-color { color }?
+    & attribute draw:shadow-opacity { zeroToHundredPercent }?
+    & # TODO: no proposal for loext:shadow-blur
+      attribute loext:shadow-blur { length }?
+    & attribute draw:start-line-spacing-horizontal { distance }?
+    & attribute draw:start-line-spacing-vertical { distance }?
+    & attribute draw:end-line-spacing-horizontal { distance }?
+    & attribute draw:end-line-spacing-vertical { distance }?
+    & attribute draw:line-distance { distance }?
+    & attribute draw:guide-overhang { length }?
+    & attribute draw:guide-distance { distance }?
+    & attribute draw:start-guide { length }?
+    & attribute draw:end-guide { length }?
+    & attribute draw:placing { "below" | "above" }?
+    & attribute draw:parallel { boolean }?
+    & attribute draw:measure-align {
+        "automatic" | "left-outside" | "inside" | "right-outside"
+      }?
+    & attribute draw:measure-vertical-align {
+        "automatic" | "above" | "below" | "center"
+      }?
+    & attribute draw:unit {
+        "automatic"
+        | "mm"
+        | "cm"
+        | "m"
+        | "km"
+        | "pt"
+        | "pc"
+        | "inch"
+        | "ft"
+        | "mi"
+      }?
+    & attribute draw:show-unit { boolean }?
+    & attribute draw:decimal-places { nonNegativeInteger }?
+    & attribute draw:caption-type {
+        "straight-line" | "angled-line" | "angled-connector-line"
+      }?
+    & attribute draw:caption-angle-type { "fixed" | "free" }?
+    & attribute draw:caption-angle { angle }?
+    & attribute draw:caption-gap { distance }?
+    & attribute draw:caption-escape-direction {
+        "horizontal" | "vertical" | "auto"
+      }?
+    & attribute draw:caption-escape { length | percent }?
+    & attribute draw:caption-line-length { length }?
+    & attribute draw:caption-fit-line-length { boolean }?
+    & attribute dr3d:horizontal-segments { nonNegativeInteger }?
+    & attribute dr3d:vertical-segments { nonNegativeInteger }?
+    & attribute dr3d:edge-rounding { percent }?
+    & attribute dr3d:edge-rounding-mode { "correct" | "attractive" }?
+    & attribute dr3d:back-scale { percent }?
+    & attribute dr3d:depth { length }?
+    & attribute dr3d:backface-culling { "enabled" | "disabled" }?
+    & attribute dr3d:end-angle { angle }?
+    & attribute dr3d:close-front { boolean }?
+    & attribute dr3d:close-back { boolean }?
+    & attribute dr3d:lighting-mode { "standard" | "double-sided" }?
+    & attribute dr3d:normals-kind { "object" | "flat" | "sphere" }?
+    & attribute dr3d:normals-direction { "normal" | "inverse" }?
+    & attribute dr3d:texture-generation-mode-x {
+        "object" | "parallel" | "sphere"
+      }?
+    & attribute dr3d:texture-generation-mode-y {
+        "object" | "parallel" | "sphere"
+      }?
+    & attribute dr3d:texture-kind {
+        "luminance" | "intensity" | "color"
+      }?
+    & attribute dr3d:texture-filter { "enabled" | "disabled" }?
+    & attribute dr3d:texture-mode { "replace" | "modulate" | "blend" }?
+    & attribute dr3d:ambient-color { color }?
+    & attribute dr3d:emissive-color { color }?
+    & attribute dr3d:specular-color { color }?
+    & attribute dr3d:diffuse-color { color }?
+    & attribute dr3d:shininess { percent }?
+    & attribute dr3d:shadow { "visible" | "hidden" }?
+    & common-draw-rel-size-attlist
+    & attribute fo:min-width { length | percent }?
+    & attribute fo:min-height { length | percent }?
+    & attribute fo:max-height { length | percent }?
+    & attribute fo:max-width { length | percent }?
+    & common-horizontal-margin-attlist
+    & common-vertical-margin-attlist
+    & common-margin-attlist
+    & attribute style:print-content { boolean }?
+    & attribute style:protect {
+        "none"
+        | list { ("content" | "position" | "size")+ }
+      }?
+    & attribute style:horizontal-pos {
+        "left"
+        | "center"
+        | "right"
+        | "from-left"
+        | "inside"
+        | "outside"
+        | "from-inside"
+      }?
+    & attribute svg:x { coordinate }?
+    & attribute style:horizontal-rel {
+        "page"
+        | "page-content"
+        | "page-start-margin"
+        | "page-end-margin"
+        | "frame"
+        | "frame-content"
+        | "frame-start-margin"
+        | "frame-end-margin"
+        | "paragraph"
+        | "paragraph-content"
+        | "paragraph-start-margin"
+        | "paragraph-end-margin"
+        | "char"
+      }?
+    & common-vertical-pos-attlist
+    & common-vertical-rel-attlist
+    & common-text-anchor-attlist
+    & common-border-attlist
+    & common-border-line-width-attlist
+    & common-padding-attlist
+    & common-shadow-attlist
+    & common-background-color-attlist
+    & common-background-transparency-attlist
+    & common-editable-attlist
+    & attribute style:wrap {
+        "none"
+        | "left"
+        | "right"
+        | "parallel"
+        | "dynamic"
+        | "run-through"
+        | "biggest"
+      }?
+    & attribute style:wrap-dynamic-threshold { nonNegativeLength }?
+    & attribute style:number-wrapped-paragraphs {
+        "no-limit" | positiveInteger
+      }?
+    & attribute style:wrap-contour { boolean }?
+    & attribute style:wrap-contour-mode { "full" | "outside" }?
+    & attribute style:run-through { "foreground" | "background" }?
+    & attribute style:flow-with-text { boolean }?
+    & attribute style:overflow-behavior {
+        "clip" | "auto-create-new-frame"
+      }?
+    & attribute style:mirror {
+        "none"
+        | "vertical"
+        | horizontal-mirror
+        | list { "vertical", horizontal-mirror }
+        | list { horizontal-mirror, "vertical" }
+      }?
+    & attribute fo:clip { "auto" | clipShape }?
+    & attribute draw:wrap-influence-on-position {
+        "iterative" | "once-concurrent" | "once-successive"
+      }?
+    & common-writing-mode-attlist
+    & attribute draw:frame-display-scrollbar { boolean }?
+    & attribute draw:frame-display-border { boolean }?
+    & attribute draw:frame-margin-horizontal { nonNegativePixelLength }?
+    & attribute draw:frame-margin-vertical { nonNegativePixelLength }?
+    & attribute draw:visible-area-left { nonNegativeLength }?
+    & attribute draw:visible-area-top { nonNegativeLength }?
+    & attribute draw:visible-area-width { positiveLength }?
+    & attribute draw:visible-area-height { positiveLength }?
+    & attribute draw:draw-aspect {
+        "content" | "thumbnail" | "icon" | "print-view"
+      }?
+    & attribute draw:ole-draw-aspect { nonNegativeInteger }?
+    & # https://issues.oasis-open.org/browse/OFFICE-4047
+      attribute loext:allow-overlap { boolean }?
+    & # TODO: no proposal for loext:glow*
+      attribute loext:glow-radius { length }?
+    & attribute loext:glow-color { color }?
+    & attribute loext:glow-transparency { zeroToHundredPercent }?
+    & # TODO: no proposal for loext:softedge-radius
+      attribute loext:softedge-radius { length }?
+  draw-text =
+    (text-p
+     | text-list
+     | # https://issues.oasis-open.org/browse/OFFICE-3761
+       loext-table)*
+  office-annotation-attlist &=
+    attribute office:display { boolean }?
+    & common-office-annotation-name-attlist?
+    & attribute loext:resolved { boolean }?
+  style-style-content =
+    (attribute style:family { "text" },
+     style-text-properties?)
+    | (attribute style:family { "paragraph" },
+       # TODO no proposal
+       loext-graphic-properties?,
+       style-paragraph-properties?,
+       style-text-properties?)
+    | (attribute style:family { "section" },
+       style-section-properties?)
+    | (attribute style:family { "ruby" },
+       style-ruby-properties?)
+    | (attribute style:family { "table" },
+       style-table-properties?)
+    | (attribute style:family { "table-column" },
+       style-table-column-properties?)
+    | (attribute style:family { "table-row" },
+       style-table-row-properties?)
+    | (attribute style:family { "table-cell" },
+       # TODO no proposal
+       loext-graphic-properties?,
+       style-table-cell-properties?,
+       style-paragraph-properties?,
+       style-text-properties?)
+    | (attribute style:family { "graphic" | "presentation" },
+       style-graphic-properties?,
+       style-paragraph-properties?,
+       style-text-properties?)
+    | (attribute style:family { "drawing-page" },
+       style-drawing-page-properties?)
+    | (attribute style:family { "chart" },
+       style-chart-properties?,
+       style-graphic-properties?,
+       style-paragraph-properties?,
+       style-text-properties?)
+  table-table-template =
+    element table:table-template {
+      table-table-template-attlist,
+      table-first-row?,
+      table-last-row?,
+      table-first-column?,
+      table-last-column?,
+      table-body,
+      table-even-rows?,
+      table-odd-rows?,
+      table-even-columns?,
+      table-odd-columns?,
+      table-background?,
+      # TODO no proposal
+      table-first-row-even-column?,
+      table-last-row-even-column?,
+      table-first-row-end-column?,
+      table-first-row-start-column?,
+      table-last-row-end-column?,
+      table-last-row-start-column?
+    }
+  draw-frame =
+    element draw:frame {
+      common-draw-shape-with-text-and-styles-attlist,
+      common-draw-position-attlist,
+      common-draw-rel-size-attlist,
+      common-draw-caption-id-attlist,
+      presentation-shape-attlist,
+      draw-frame-attlist,
+      (draw-text-box
+       | draw-image
+       | draw-object
+       | draw-object-ole
+       | draw-applet
+       | draw-floating-frame
+       | draw-plugin
+       | table-table)*,
+      office-event-listeners?,
+      draw-glue-point*,
+      draw-image-map?,
+      svg-title?,
+      svg-desc?,
+      (draw-contour-polygon | draw-contour-path)?,
+      # TODO no proposal
+      loext-signatureline?,
+      loext-qrcode?
+    }
+  common-value-and-type-attlist =
+    (attribute office:value-type { "float" },
+     attribute calcext:value-type { "float" }?,
+     attribute office:value { double })
+    | (attribute office:value-type { "percentage" },
+       attribute calcext:value-type { "percentage" }?,
+       attribute office:value { double })
+    | (attribute office:value-type { "currency" },
+       attribute calcext:value-type { "currency" }?,
+       attribute office:value { double },
+       attribute office:currency { \string }?)
+    | (attribute office:value-type { "date" },
+       attribute calcext:value-type { "date" }?,
+       attribute office:date-value { dateOrDateTime })
+    | (attribute office:value-type { "time" },
+       attribute calcext:value-type { "time" }?,
+       attribute office:time-value { duration })
+    | (attribute office:value-type { "boolean" },
+       attribute calcext:value-type { "boolean" }?,
+       attribute office:boolean-value { boolean })
+    | (attribute office:value-type { "string" },
+       # OFFICE-3759
+       attribute calcext:value-type { "string" | "error" }?,
+       attribute office:string-value { \string }?)
+  chart-axis =
+    element chart:axis {
+      chart-axis-attlist,
+      # OFFICE-2119
+      ((attribute chartooo:axis-type { "auto" },
+        chartooo-date-scale?)
+       | (attribute chartooo:axis-type { "date" },
+          chartooo-date-scale)
+       | attribute chartooo:axis-type { "text" })?,
+      chart-title?,
+      chart-categories?,
+      chart-grid*
+    }
+  table-table =
+    element table:table {
+      table-table-attlist,
+      table-title?,
+      table-desc?,
+      # TODO add to proposal, OFFICE-2112
+      table-table-protection?,
+      table-table-source?,
+      office-dde-source?,
+      table-scenario?,
+      office-forms?,
+      table-shapes?,
+      table-columns-and-groups,
+      table-rows-and-groups,
+      table-named-expressions?,
+      # TODO no proposal, this is wild guessing, OFFICE-3785
+      element calcext:conditional-formats {
+        element calcext:conditional-format {
+          attribute calcext:target-range-address { cellRangeAddress },
+          (element calcext:condition {
+             attribute calcext:apply-style-name { styleNameRef },
+             attribute calcext:value { \string },
+             attribute calcext:base-cell-address { cellAddress }
+           }+
+           | element calcext:data-bar {
+               attribute calcext:max-length { \string },
+               attribute calcext:negative-color { color },
+               attribute calcext:positive-color { color },
+               attribute calcext:axis-color { color },
+               attribute calcext:axis-position { "middle" }?,
+               element calcext:formatting-entry {
+                 attribute calcext:value { \string },
+                 attribute calcext:type {
+                   "auto-minimum"
+                   | "auto-maximum"
+                   | "minimum"
+                   | "maximum"
+                   | "percent"
+                   | "percentile"
+                   | "number"
+                   | "formula"
+                 }
+               },
+               element calcext:formatting-entry {
+                 attribute calcext:value { \string },
+                 attribute calcext:type {
+                   "auto-minimum"
+                   | "auto-maximum"
+                   | "minimum"
+                   | "maximum"
+                   | "percent"
+                   | "percentile"
+                   | "number"
+                   | "formula"
+                 }
+               }
+             }
+           | element calcext:color-scale {
+               element calcext:color-scale-entry {
+                 attribute calcext:value { \string },
+                 attribute calcext:type {
+                   "minimum"
+                   | "maximum"
+                   | "percent"
+                   | "percentile"
+                   | "number"
+                   | "formula"
+                 },
+                 attribute calcext:color { color }
+               },
+               element calcext:color-scale-entry {
+                 attribute calcext:value { \string },
+                 attribute calcext:type {
+                   "minimum"
+                   | "maximum"
+                   | "percent"
+                   | "percentile"
+                   | "number"
+                   | "formula"
+                 },
+                 attribute calcext:color { color }
+               },
+               element calcext:color-scale-entry {
+                 attribute calcext:value { \string },
+                 attribute calcext:type {
+                   "minimum"
+                   | "maximum"
+                   | "percent"
+                   | "percentile"
+                   | "number"
+                   | "formula"
+                 },
+                 attribute calcext:color { color }
+               }?
+             })
+        }+
+      }?
+    }
+  # TODO no proposal
+  draw-object =
+    element draw:object {
+      draw-object-attlist,
+      loext-text,
+      (common-draw-data-attlist | office-document | math-math)
+    }
+  draw-object-ole =
+    element draw:object-ole {
+      draw-object-ole-attlist,
+      loext-text,
+      (common-draw-data-attlist | office-binary-data)
+    }
+  # FIXME: one test exports 250 here, which is probably a bug
+  fontWeight =
+    "normal"
+    | "bold"
+    | "100"
+    | "200"
+    | "250"
+    | "300"
+    | "400"
+    | "500"
+    | "600"
+    | "700"
+    | "800"
+    | "900"
+}
+# TODO no proposal
+loext-p =
+  element loext:p { paragraph-attrs, paragraph-content-or-hyperlink* }
+loext-text = (loext-p | text-list | loext-table)*
+# OFFICE-2119
+chartooo-date-scale =
+  element chartooo:date-scale {
+    attribute chart:base-time-unit { chart-time-unit }?
+    & (attribute chart:major-interval-value { positiveInteger },
+       attribute chart:major-interval-unit { chart-time-unit })?
+    & (attribute chart:minor-interval-value { positiveInteger },
+       attribute chart:minor-interval-unit { chart-time-unit })?
+  }
+chart-time-unit = "days" | "months" | "years"
+# TODO no proposal
+loext-signatureline =
+  element loext:signatureline {
+    attribute loext:id { \string },
+    attribute loext:suggested-signer-name { \string },
+    attribute loext:suggested-signer-title { \string },
+    attribute loext:suggested-signer-email { \string },
+    attribute loext:signing-instructions { \string },
+    attribute loext:show-sign-date { boolean },
+    attribute loext:can-add-comment { boolean }
+  }
+loext-qrcode =
+  element loext:qrcode {
+    attribute office:string-value { \string },
+    attribute loext:qrcode-errorcorrection {
+      "low" | "medium" | "quartile" | "high"
+    },
+    attribute loext:qrcode-border { nonNegativeInteger }
+  }
+# https://issues.oasis-open.org/browse/OFFICE-3761
+loext-table =
+  element loext:table {
+    table-table-attlist,
+    table-title?,
+    table-desc?,
+    table-table-source?,
+    office-dde-source?,
+    table-scenario?,
+    office-forms?,
+    table-shapes?,
+    loext-columns-and-groups,
+    loext-rows-and-groups,
+    table-named-expressions?
+  }
+loext-rows-and-groups = (table-table-row-group | loext-rows-no-group)+
+loext-rows-no-group =
+  (loext-rows, (table-table-header-rows, loext-rows?)?)
+  | (table-table-header-rows, loext-rows?)
+loext-rows =
+  table-table-rows | (text-soft-page-break?, loext-table-row)+
+loext-table-row =
+  element loext:table-row {
+    table-table-row-attlist,
+    (loext-table-cell | loext-covered-table-cell)+
+  }
+loext-table-cell =
+  element loext:table-cell {
+    table-table-cell-attlist,
+    table-table-cell-attlist-extra,
+    table-table-cell-content
+  }
+loext-covered-table-cell =
+  element loext:covered-table-cell {
+    table-table-cell-attlist, table-table-cell-content
+  }
+loext-columns-and-groups =
+  (table-table-column-group | loext-columns-no-group)+
+loext-columns-no-group =
+  (loext-columns, (table-table-header-columns, loext-columns?)?)
+  | (table-table-header-columns, loext-columns?)
+loext-columns = loext-table-columns | loext-table-column+
+loext-table-columns =
+  element loext:table-columns { loext-table-column+ }
+loext-table-column =
+  element loext:table-column { table-table-column-attlist, empty }
+loext-graphic-properties =
+  element loext:graphic-properties {
+    style-graphic-properties-content-strict
+  }
+table-first-row-even-column =
+  element loext:first-row-even-column {
+    common-table-template-attlist, empty
+  }
+table-last-row-even-column =
+  element loext:last-row-even-column {
+    common-table-template-attlist, empty
+  }
+table-first-row-end-column =
+  element loext:first-row-end-column {
+    common-table-template-attlist, empty
+  }
+table-first-row-start-column =
+  element loext:first-row-start-column {
+    common-table-template-attlist, empty
+  }
+table-last-row-end-column =
+  element loext:last-row-end-column {
+    common-table-template-attlist, empty
+  }
+table-last-row-start-column =
+  element loext:last-row-start-column {
+    common-table-template-attlist, empty
+  }
+common-draw-rel-size-attlist &=
+  # OFFICE-3854
+  attribute loext:rel-width-rel {
+    "page"
+    | [
+        # TODO layout-environment ?
+
+      ]
+      "paragraph"
+  }?,
+  attribute loext:rel-height-rel { "page" | "paragraph" }?
+common-svg-font-face-xlink-attlist &=
+  # TODO no proposal
+  attribute loext:font-style { fontStyle }?,
+  attribute loext:font-weight { fontWeight }?
+# TODO no proposal
+
+# there's no ref-attrs so add it here
+text-common-ref-content &=
+  attribute loext:reference-language { language }?
+style-list-level-label-alignment-attlist &=
+  # TODO no proposal
+  attribute loext:label-followed-by {
+    "listtab" | "space" | "nothing" | "newline"
+  }?
+style-ruby-properties-attlist &=
+  # TODO proposal, OFFICE-3944
+  attribute loext:ruby-position {
+    "above" | "below" | "inter-character"
+  }?
+style-text-properties-attlist &=
+  # TODO no proposal
+  attribute officeooo:rsid { \string }?,
+  attribute officeooo:paragraph-rsid { \string }?,
+  # https://issues.oasis-open.org/browse/OFFICE-4049
+  attribute loext:opacity { zeroToHundredPercent }?
+style-text-properties-attlist &=
+  # OFFICE-3843
+  attribute loext:padding { nonNegativeLength }?,
+  attribute loext:padding-left { nonNegativeLength }?,
+  attribute loext:padding-right { nonNegativeLength }?,
+  attribute loext:padding-top { nonNegativeLength }?,
+  attribute loext:padding-bottom { nonNegativeLength }?,
+  attribute loext:border { \string }?,
+  attribute loext:border-left { \string }?,
+  attribute loext:border-right { \string }?,
+  attribute loext:border-top { \string }?,
+  attribute loext:border-bottom { \string }?,
+  attribute loext:shadow { shadowType }?
+# TODO no proposal
+style-chart-properties-attlist &=
+  attribute loext:try-staggering-first { boolean }?
+# TODO no proposal
+style-chart-properties-attlist &=
+  attribute loext:std-weight { \string }?
+# TODO no proposal
+chart-series-attlist &= attribute loext:label-string { \string }?
+# OFFICE-1148
+style-chart-properties-attlist &=
+  attribute loext:regression-max-degree { positiveInteger }?,
+  attribute loext:regression-force-intercept { boolean }?,
+  attribute loext:regression-intercept-value { double }?,
+  attribute loext:regression-name { \string }?,
+  attribute loext:regression-period { \string }?,
+  attribute loext:regression-extrapolate-forward { \string }?,
+  attribute loext:regression-extrapolate-backward { \string }?
+# TODO no proposal
+table-data-pilot-field-attlist &=
+  attribute tableooo:display-name { \string }?
+# TODO no proposal, 9009663d
+chart-chart-attlist &= attribute loext:data-pilot-source { \string }?
+# OFFICE-2112, TODO half of this missing in proposal
+table-table-protection =
+  element loext:table-protection {
+    attribute loext:select-protected-cells { boolean }?,
+    attribute loext:select-unprotected-cells { boolean }?,
+    attribute loext:insert-columns { boolean }?,
+    attribute loext:insert-rows { boolean }?,
+    attribute loext:delete-columns { boolean }?,
+    attribute loext:delete-rows { boolean }?
+  }
+office-spreadsheet-attlist &=
+  attribute loext:protection-key-digest-algorithm-2 { anyURI }?
+table-table-attlist &=
+  attribute loext:protection-key-digest-algorithm-2 { anyURI }?
+# https://issues.oasis-open.org/browse/OFFICE-2317
+vertJustifyValues = "auto" | "distribute"
+common-text-justify =
+  attribute css3t:text-justify { vertJustifyValues }?
+style-vertical-justify =
+  attribute loext:vertical-justify { vertJustifyValues }?,
+  attribute style:vertical-justify { vertJustifyValues }?
+style-paragraph-properties-attlist &=
+  (common-text-justify, style-vertical-justify)?
+style-table-cell-properties-attlist &=
+  (common-text-justify, style-vertical-justify)?
+number-fraction-attlist &=
+  # OFFICE-3695
+
+  # TODO no proposal, 1544a26ac9f7dd60605dd21e9cbe29d490aafdce
+  attribute loext:max-numerator-digits { positiveInteger }?
+# TODO no proposal
+table-data-pilot-level-attlist &=
+  attribute calcext:repeat-item-labels { boolean }?
+# TODO no proposal
+draw-enhanced-geometry-attlist &=
+  attribute drawooo:sub-view-size { \string }?,
+  attribute drawooo:enhanced-path { \string }?
+# TODO no proposal
+draw-custom-shape-attlist &= common-draw-rel-size-attlist
+# TODO no proposal
+style-page-layout-properties-attlist &=
+  style-graphic-fill-properties-attlist
+style-header-footer-properties-attlist &=
+  style-graphic-fill-properties-attlist
+# TODO no proposal
+text-index-entry-tab-stop-attrs &= attribute style:with-tab { boolean }?
+# TODO no proposal
+style-text-properties-attlist &=
+  attribute loext:char-shading-value { \string }?
+# TODO no proposal
+text-bookmark-start-attlist &=
+  (attribute loext:hidden { boolean },
+   attribute loext:condition { \string }?)?
+# TODO no proposal; see 7a5d79f2297a43d0a854e304b0792164272edfe0
+
+# FIXME this is almost certainly incomplete: need to figure out which elements 
can have this and which named pattern can be extended with it to get exactly 
these elements
+form-checkbox-attlist &= attribute form:input-required { boolean }?
+# https://issues.oasis-open.org/browse/OFFICE-4030
+common-writing-mode-attlist &= attribute loext:writing-mode { "bt-lr" }?
+# https://issues.oasis-open.org/browse/OFFICE-4073
+common-vertical-rel-attlist &=
+  attribute loext:vertical-rel {
+    "page-content-top" | "page-content-bottom"
+  }?
+# https://issues.oasis-open.org/browse/OFFICE-4105
+style-page-layout-properties-attlist &=
+  attribute loext:margin-gutter { length }?
+# just a test-case for user-defined attributes, move along, nothing to see 
here...
+style-table-cell-properties-attlist &= attribute proName { \string }?
+# TODO no proposal
+chart-data-point-attlist &=
+  attribute loext:custom-label-field { \string }?
+# TODO no proposal
+style-text-properties-attlist &=
+  attribute loext:hyphenation-no-caps { boolean }?
+# TODO no proposal
+chart-data-point-attlist &=
+  (attribute loext:custom-label-pos-x { double },
+   attribute loext:custom-label-pos-y { double })?
+# TODO no proposal
+chart-legend-attlist &= attribute loext:overlay { boolean }?
+# https://issues.oasis-open.org/browse/OFFICE-3936
+style-chart-properties-attlist &=
+  attribute loext:major-origin { double }?
+# TODO no proposal
+text-index-entry-chapter-attrs &=
+  attribute loext:outline-content-visible { boolean }?
+# https://issues.oasis-open.org/browse/OFFICE-2096
+paragraph-content |=
+  element field:fieldmark-start {
+    attribute text:name { \string },
+    attribute field:type {
+      # TODO <rng:ref name="namespacedToken"/>
+      \string
+    },
+    element field:param {
+      attribute field:name { \string },
+      attribute field:value { \string }
+    }*
+  }
+paragraph-content |= element field:fieldmark-end { empty }
+paragraph-content |=
+  element field:fieldmark {
+    attribute text:name { \string },
+    attribute field:type {
+      # TODO <rng:ref name="namespacedToken"/>
+      \string
+    },
+    element field:param {
+      attribute field:name { \string },
+      attribute field:value { \string }
+    }*
+  }
+# TODO no proposal
+animation-element |=
+  element loext:animatePhysics {
+    common-anim-target-attlist,
+    common-timing-attlist,
+    animate-physics-attlist
+  }
+animate-physics-attlist =
+  # default value: 0
+  attribute loext:velocity-x { double }?,
+  # default value: 0
+  attribute loext:velocity-y { double }?,
+  # default value: 0.1
+  attribute loext:bounciness {
+    xsd:double { minInclusive = "0" maxInclusive = "1" }
+  }?,
+  # default value: 1
+  attribute loext:density {
+    xsd:double { minInclusive = "0" }
+  }?
+# TODO no proposal
+style-chart-properties-attlist &=
+  attribute loext:custom-leader-lines { boolean }?
+# TODO no proposal
+style-chart-properties-attlist &=
+  attribute loext:external-data { \string }?
diff --git a/etc/schema/od-schema-v1.2-os.rnc 
b/etc/schema/OpenDocument-schema-v1.3.rnc
similarity index 96%
rename from etc/schema/od-schema-v1.2-os.rnc
rename to etc/schema/OpenDocument-schema-v1.3.rnc
index 8d679d6..2a78679 100644
--- a/etc/schema/od-schema-v1.2-os.rnc
+++ b/etc/schema/OpenDocument-schema-v1.3.rnc
@@ -1,33 +1,16 @@
-# Open Document Format for Office Applications (OpenDocument) Version 1.2
-# OASIS Standard, 29 September 2011
-# Relax-NG Schema
-# Source: http://docs.oasis-open.org/office/v1.2/os/
-# Copyright (c) OASIS Open 2002-2011, 2013. All Rights Reserved.
+# Open Document Format for Office Applications (OpenDocument) Version 1.3
+# Committee Specification 02
+# 30 October 2020
+# Copyright (c) OASIS Open 2020. All Rights Reserved.
+# Source: https://docs.oasis-open.org/office/OpenDocument/v1.3/cs02/schemas/
+# Latest stage of specification: 
https://docs.oasis-open.org/office/OpenDocument/v1.3/OpenDocument-v1.3-part1-introduction.html
+# TC IPR Statement: https://www.oasis-open.org/committees/office/ipr.php
 #
-# All capitalized terms in the following text have the meanings assigned to 
them
-# in the OASIS Intellectual Property Rights Policy (the "OASIS IPR Policy"). 
The
-# full Policy may be found at the OASIS website.
-#
-# This document and translations of it may be copied and furnished to others, 
and
-# derivative works that comment on or otherwise explain it or assist in its
-# implementation may be prepared, copied, published, and distributed, in whole 
or
-# in part, without restriction of any kind, provided that the above copyright
-# notice and this section are included on all such copies and derivative works.
-# However, this document itself may not be modified in any way, including by
-# removing the copyright notice or references to OASIS, except as needed for 
the
-# purpose of developing any document or deliverable produced by an OASIS
-# Technical Committee (in which case the rules applicable to copyrights, as set
-# forth in the OASIS IPR Policy, must be followed) or as required to translate 
it
-# into languages other than English.
-#
-# The limited permissions granted above are perpetual and will not be revoked 
by
-# OASIS or its successors or assigns.
-#
-# This document and the information contained herein is provided on an "AS IS"
-# basis and OASIS DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT 
NOT
-# LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION HEREIN WILL NOT
-# INFRINGE ANY OWNERSHIP RIGHTS OR ANY IMPLIED WARRANTIES OF MERCHANTABILITY OR
-# FITNESS FOR A PARTICULAR PURPOSE.
+#    Open Document Format for Office Applications (OpenDocument) Version 1.3
+#    Relax-NG Schema
+#    OpenDocument-v1.3-schema.rng
+
+# https://issues.oasis-open.org/browse/OFFICE-2153
 
 namespace anim = "urn:oasis:names:tc:opendocument:xmlns:animation:1.0"
 namespace chart = "urn:oasis:names:tc:opendocument:xmlns:chart:1.0"
@@ -46,6 +29,7 @@ namespace number = 
"urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0"
 namespace office = "urn:oasis:names:tc:opendocument:xmlns:office:1.0"
 namespace presentation =
   "urn:oasis:names:tc:opendocument:xmlns:presentation:1.0"
+namespace rng = "http://relaxng.org/ns/structure/1.0";
 namespace script = "urn:oasis:names:tc:opendocument:xmlns:script:1.0"
 namespace smil =
   "urn:oasis:names:tc:opendocument:xmlns:smil-compatible:1.0"
@@ -58,2090 +42,1874 @@ namespace xforms = "http://www.w3.org/2002/xforms";
 namespace xhtml = "http://www.w3.org/1999/xhtml";
 namespace xlink = "http://www.w3.org/1999/xlink";
 
-office-process-content = attribute office:process-content { boolean }?
 start =
   office-document
   | office-document-content
   | office-document-styles
   | office-document-meta
   | office-document-settings
-office-document =
-  element office:document {
-    office-document-attrs,
-    office-document-common-attrs,
-    office-meta,
-    office-settings,
-    office-scripts,
-    office-font-face-decls,
-    office-styles,
-    office-automatic-styles,
-    office-master-styles,
-    office-body
-  }
-office-document-content =
-  element office:document-content {
-    office-document-common-attrs,
-    office-scripts,
-    office-font-face-decls,
-    office-automatic-styles,
-    office-body
-  }
-office-document-styles =
-  element office:document-styles {
-    office-document-common-attrs,
-    office-font-face-decls,
-    office-styles,
-    office-automatic-styles,
-    office-master-styles
-  }
-office-document-meta =
-  element office:document-meta {
-    office-document-common-attrs, office-meta
-  }
-office-document-settings =
-  element office:document-settings {
-    office-document-common-attrs, office-settings
+CURIE =
+  xsd:string { pattern = "(([\i-[:]][\c-[:]]*)?:)?.+" minLength = "1" }
+CURIEs = list { CURIE+ }
+ID = xsd:ID
+IDREF = xsd:IDREF
+IDREFS = xsd:IDREFS
+NCName = xsd:NCName
+SafeCURIE =
+  xsd:string {
+    pattern = "\[(([\i-[:]][\c-[:]]*)?:)?.+\]"
+    minLength = "3"
   }
-office-document-common-attrs =
-  attribute office:version { "1.2" }
-  & attribute grddl:transformation {
-      list { anyIRI* }
+URIorSafeCURIE = anyURI | SafeCURIE
+angle = xsd:string
+anim-animate-color-attlist =
+  attribute anim:color-interpolation { "rgb" | "hsl" }?
+  & attribute anim:color-interpolation-direction {
+      "clockwise" | "counter-clockwise"
     }?
-office-document-attrs = attribute office:mimetype { \string }
-office-meta = element office:meta { office-meta-content-strict }?
-office-meta-content-strict = office-meta-data*
-office-body = element office:body { office-body-content }
-office-body-content =
-  element office:text {
-    office-text-attlist,
-    office-text-content-prelude,
-    office-text-content-main,
-    office-text-content-epilogue
+anim-animate-motion-attlist =
+  attribute svg:path { pathData }?
+  & attribute svg:origin { \string }?
+  & attribute smil:calcMode {
+      "discrete" | "linear" | "paced" | "spline"
+    }?
+anim-animate-transform-attlist =
+  attribute svg:type {
+    "translate" | "scale" | "rotate" | "skewX" | "skewY"
   }
-  | element office:drawing {
-      office-drawing-attlist,
-      office-drawing-content-prelude,
-      office-drawing-content-main,
-      office-drawing-content-epilogue
+anim-audio-attlist =
+  attribute xlink:href { anyIRI }?
+  & attribute anim:audio-level { double }?
+anim-command-attlist = attribute anim:command { \string }
+anim-iterate-attlist =
+  common-anim-target-attlist
+  & attribute anim:iterate-type { \string }?
+  & attribute anim:iterate-interval { duration }?
+anim-transition-filter-attlist =
+  attribute smil:type { \string }
+  & attribute smil:subtype { \string }?
+  & attribute smil:direction { "forward" | "reverse" }?
+  & attribute smil:fadeColor { color }?
+  & attribute smil:mode { "in" | "out" }?
+animation-element =
+  element anim:animate {
+    common-anim-target-attlist,
+    common-anim-named-target-attlist,
+    common-anim-values-attlist,
+    common-anim-spline-mode-attlist,
+    common-spline-anim-value-attlist,
+    common-timing-attlist,
+    common-anim-add-accum-attlist
+  }
+  | element anim:set {
+      common-anim-target-attlist,
+      common-anim-named-target-attlist,
+      common-anim-set-values-attlist,
+      common-timing-attlist,
+      common-anim-add-accum-attlist
     }
-  | element office:presentation {
-      office-presentation-attlist,
-      office-presentation-content-prelude,
-      office-presentation-content-main,
-      office-presentation-content-epilogue
+  | element anim:animateMotion {
+      anim-animate-motion-attlist,
+      common-anim-target-attlist,
+      common-anim-named-target-attlist,
+      common-anim-add-accum-attlist,
+      common-anim-values-attlist,
+      common-timing-attlist,
+      common-spline-anim-value-attlist
     }
-  | element office:spreadsheet {
-      office-spreadsheet-attlist,
-      office-spreadsheet-content-prelude,
-      office-spreadsheet-content-main,
-      office-spreadsheet-content-epilogue
+  | element anim:animateColor {
+      common-anim-target-attlist,
+      common-anim-named-target-attlist,
+      common-anim-add-accum-attlist,
+      common-anim-values-attlist,
+      common-anim-spline-mode-attlist,
+      common-spline-anim-value-attlist,
+      anim-animate-color-attlist,
+      common-timing-attlist
     }
-  | element office:chart {
-      office-chart-attlist,
-      office-chart-content-prelude,
-      office-chart-content-main,
-      office-chart-content-epilogue
+  | element anim:animateTransform {
+      common-anim-target-attlist,
+      common-anim-named-target-attlist,
+      common-anim-add-accum-attlist,
+      common-anim-values-attlist,
+      anim-animate-transform-attlist,
+      common-timing-attlist
     }
-  | element office:image {
-      office-image-attlist,
-      office-image-content-prelude,
-      office-image-content-main,
-      office-image-content-epilogue
+  | element anim:transitionFilter {
+      common-anim-target-attlist,
+      common-anim-add-accum-attlist,
+      common-anim-values-attlist,
+      common-anim-spline-mode-attlist,
+      anim-transition-filter-attlist,
+      common-timing-attlist
     }
-  | office-database
-office-text-content-prelude =
-  office-forms, text-tracked-changes, text-decls, table-decls
-office-text-content-main =
-  text-content*
-  | (text-page-sequence, (shape)*)
-text-content =
-  text-h
-  | text-p
-  | text-list
-  | text-numbered-paragraph
-  | table-table
-  | text-section
-  | text-soft-page-break
-  | text-table-of-content
-  | text-illustration-index
-  | text-table-index
-  | text-object-index
-  | text-user-index
-  | text-alphabetical-index
-  | text-bibliography
-  | shape
-  | change-marks
-office-text-content-epilogue = table-functions
-office-text-attlist =
-  attribute text:global { boolean }?
-  & attribute text:use-soft-page-breaks { boolean }?
-office-drawing-attlist = empty
-office-drawing-content-prelude = text-decls, table-decls
-office-drawing-content-main = draw-page*
-office-drawing-content-epilogue = table-functions
-office-presentation-attlist = empty
-office-presentation-content-prelude =
-  text-decls, table-decls, presentation-decls
-office-presentation-content-main = draw-page*
-office-presentation-content-epilogue =
-  presentation-settings, table-functions
-office-spreadsheet-content-prelude =
-  table-tracked-changes?, text-decls, table-decls
-table-decls =
-  table-calculation-settings?,
-  table-content-validations?,
-  table-label-ranges?
-office-spreadsheet-content-main = table-table*
-office-spreadsheet-content-epilogue = table-functions
-table-functions =
-  table-named-expressions?,
-  table-database-ranges?,
-  table-data-pilot-tables?,
-  table-consolidation?,
-  table-dde-links?
-office-chart-attlist = empty
-office-chart-content-prelude = text-decls, table-decls
-office-chart-content-main = chart-chart
-office-chart-content-epilogue = table-functions
-office-image-attlist = empty
-office-image-content-prelude = empty
-office-image-content-main = draw-frame
-office-image-content-epilogue = empty
-office-settings = element office:settings { config-config-item-set+ }?
-config-config-item-set =
-  element config:config-item-set {
-    config-config-item-set-attlist, config-items
-  }
-config-items =
-  (config-config-item
-   | config-config-item-set
-   | config-config-item-map-named
-   | config-config-item-map-indexed)+
-config-config-item-set-attlist = attribute config:name { \string }
-config-config-item =
-  element config:config-item { config-config-item-attlist, text }
-config-config-item-attlist =
-  attribute config:name { \string }
-  & attribute config:type {
-      "boolean"
-      | "short"
-      | "int"
-      | "long"
-      | "double"
-      | "string"
-      | "datetime"
-      | "base64Binary"
+  | element anim:par {
+      common-anim-attlist,
+      common-timing-attlist,
+      common-endsync-timing-attlist,
+      animation-element*
     }
-config-config-item-map-indexed =
-  element config:config-item-map-indexed {
-    config-config-item-map-indexed-attlist,
-    config-config-item-map-entry+
-  }
-config-config-item-map-indexed-attlist =
-  attribute config:name { \string }
-config-config-item-map-entry =
-  element config:config-item-map-entry {
-    config-config-item-map-entry-attlist, config-items
-  }
-config-config-item-map-entry-attlist =
-  attribute config:name { \string }?
-config-config-item-map-named =
-  element config:config-item-map-named {
-    config-config-item-map-named-attlist, config-config-item-map-entry+
-  }
-config-config-item-map-named-attlist = attribute config:name { \string }
-office-scripts =
-  element office:scripts { office-script*, office-event-listeners? }?
-office-script =
-  element office:script {
-    office-script-attlist,
-    mixed { anyElements }
-  }
-office-script-attlist = attribute script:language { \string }
-office-font-face-decls =
-  element office:font-face-decls { style-font-face* }?
-office-styles =
-  element office:styles {
-    styles
-    & style-default-style*
-    & style-default-page-layout?
-    & text-outline-style?
-    & text-notes-configuration*
-    & text-bibliography-configuration?
-    & text-linenumbering-configuration?
-    & draw-gradient*
-    & svg-linearGradient*
-    & svg-radialGradient*
-    & draw-hatch*
-    & draw-fill-image*
-    & draw-marker*
-    & draw-stroke-dash*
-    & draw-opacity*
-    & style-presentation-page-layout*
-    & table-table-template*
-  }?
-office-automatic-styles =
-  element office:automatic-styles { styles & style-page-layout* }?
-office-master-styles =
-  element office:master-styles {
-    style-master-page* & style-handout-master? & draw-layer-set?
-  }?
-styles =
-  style-style*
-  & text-list-style*
-  & number-number-style*
-  & number-currency-style*
-  & number-percentage-style*
-  & number-date-style*
-  & number-time-style*
-  & number-boolean-style*
-  & number-text-style*
-office-meta-data =
-  element meta:generator { \string }
-  | element dc:title { \string }
-  | element dc:description { \string }
-  | element dc:subject { \string }
-  | element meta:keyword { \string }
-  | element meta:initial-creator { \string }
-  | dc-creator
-  | element meta:printed-by { \string }
-  | element meta:creation-date { dateTime }
-  | dc-date
-  | element meta:print-date { dateTime }
-  | element meta:template {
-      attribute xlink:type { "simple" },
-      attribute xlink:href { anyIRI },
-      attribute xlink:actuate { "onRequest" }?,
-      attribute xlink:title { \string }?,
-      attribute meta:date { dateTime }?
-    }
-  | element meta:auto-reload {
-      (attribute xlink:type { "simple" },
-       attribute xlink:href { anyIRI },
-       attribute xlink:show { "replace" }?,
-       attribute xlink:actuate { "onLoad" }?)?,
-      attribute meta:delay { duration }?
+  | element anim:seq {
+      common-anim-attlist,
+      common-endsync-timing-attlist,
+      common-timing-attlist,
+      animation-element*
     }
-  | element meta:hyperlink-behaviour {
-      attribute office:target-frame-name { targetFrameName }?,
-      attribute xlink:show { "new" | "replace" }?
+  | element anim:iterate {
+      common-anim-attlist,
+      anim-iterate-attlist,
+      common-timing-attlist,
+      common-endsync-timing-attlist,
+      animation-element*
     }
-  | element dc:language { language }
-  | element meta:editing-cycles { nonNegativeInteger }
-  | element meta:editing-duration { duration }
-  | element meta:document-statistic {
-      attribute meta:page-count { nonNegativeInteger }?,
-      attribute meta:table-count { nonNegativeInteger }?,
-      attribute meta:draw-count { nonNegativeInteger }?,
-      attribute meta:image-count { nonNegativeInteger }?,
-      attribute meta:ole-object-count { nonNegativeInteger }?,
-      attribute meta:object-count { nonNegativeInteger }?,
-      attribute meta:paragraph-count { nonNegativeInteger }?,
-      attribute meta:word-count { nonNegativeInteger }?,
-      attribute meta:character-count { nonNegativeInteger }?,
-      attribute meta:frame-count { nonNegativeInteger }?,
-      attribute meta:sentence-count { nonNegativeInteger }?,
-      attribute meta:syllable-count { nonNegativeInteger }?,
-      attribute meta:non-whitespace-character-count {
-        nonNegativeInteger
-      }?,
-      attribute meta:row-count { nonNegativeInteger }?,
-      attribute meta:cell-count { nonNegativeInteger }?
+  | element anim:audio {
+      common-anim-attlist,
+      anim-audio-attlist,
+      common-basic-timing-attlist
     }
-  | element meta:user-defined {
-      attribute meta:name { \string },
-      ((attribute meta:value-type { "float" },
-        double)
-       | (attribute meta:value-type { "date" },
-          dateOrDateTime)
-       | (attribute meta:value-type { "time" },
-          duration)
-       | (attribute meta:value-type { "boolean" },
-          boolean)
-       | (attribute meta:value-type { "string" },
-          \string)
-       | text)
+  | element anim:command {
+      common-anim-attlist,
+      anim-command-attlist,
+      common-begin-end-timing-attlist,
+      common-anim-target-attlist,
+      element anim:param {
+        attribute anim:name { \string },
+        attribute anim:value { \string }
+      }*
     }
-dc-creator = element dc:creator { \string }
-dc-date = element dc:date { dateTime }
-text-h =
-  element text:h {
-    heading-attrs,
-    paragraph-attrs,
-    text-number?,
-    paragraph-content-or-hyperlink*
+any-date =
+  number-day
+  | number-month
+  | number-year
+  | number-era
+  | number-day-of-week
+  | number-week-of-year
+  | number-quarter
+  | number-hours
+  | number-am-pm
+  | number-minutes
+  | number-seconds
+any-number = number-number | number-scientific-number | number-fraction
+any-time = number-hours | number-am-pm | number-minutes | number-seconds
+anyAttListOrElements =
+  attribute * { text }*,
+  anyElements
+anyElements =
+  element * {
+    mixed { anyAttListOrElements }
+  }*
+anyIRI =
+  xsd:anyURI
+  >> dc:description [
+       "An IRI-reference as defined in [RFC3987]. See ODF 1.3 Part 3 section 
18.3."
+     ]
+anyURI = xsd:anyURI
+base64Binary = xsd:base64Binary
+boolean = "true" | "false"
+borderWidths = list { positiveLength, positiveLength, positiveLength }
+bound-column = attribute form:bound-column { \string }?
+button-type = attribute form:button-type { types }?
+cellAddress =
+  xsd:string {
+    pattern = "($?([^\. ']+|'([^']|'')+'))?\.$?[A-Z]+$?[0-9]+"
   }
-heading-attrs =
-  attribute text:outline-level { positiveInteger }
-  & attribute text:restart-numbering { boolean }?
-  & attribute text:start-value { nonNegativeInteger }?
-  & attribute text:is-list-header { boolean }?
-text-number = element text:number { \string }
-text-p =
-  element text:p { paragraph-attrs, paragraph-content-or-hyperlink* }
-paragraph-attrs =
-  attribute text:style-name { styleNameRef }?
-  & attribute text:class-names { styleNameRefs }?
-  & attribute text:cond-style-name { styleNameRef }?
-  & (xml-id,
-     attribute text:id { NCName }?)?
-  & common-in-content-meta-attlist?
-text-page-sequence = element text:page-sequence { text-page+ }
-text-page = element text:page { text-page-attlist, empty }
-text-page-attlist = attribute text:master-page-name { styleNameRef }
-text-list =
-  element text:list {
-    text-list-attr, text-list-header?, text-list-item*
+cellRangeAddress =
+  xsd:string {
+    pattern =
+      "($?([^\. ']+|'([^']|'')+'))?\.$?[A-Z]+$?[0-9]+(:($?([^\. 
']+|'([^']|'')+'))?\.$?[A-Z]+$?[0-9]+)?"
   }
-text-list-attr =
-  attribute text:style-name { styleNameRef }?
-  & attribute text:continue-numbering { boolean }?
-  & attribute text:continue-list { IDREF }?
-  & xml-id?
-text-list-item =
-  element text:list-item { text-list-item-attr, text-list-item-content }
-text-list-item-content =
-  text-number?, (text-p | text-h | text-list | text-soft-page-break)*
-text-list-item-attr =
-  attribute text:start-value { nonNegativeInteger }?
-  & attribute text:style-override { styleNameRef }?
-  & xml-id?
-text-list-header =
-  element text:list-header {
-    text-list-header-attr, text-list-item-content
+  | xsd:string {
+      pattern =
+        "($?([^\. ']+|'([^']|'')+'))?\.$?[0-9]+:($?([^\. 
']+|'([^']|'')+'))?\.$?[0-9]+"
+    }
+  | xsd:string {
+      pattern =
+        "($?([^\. ']+|'([^']|'')+'))?\.$?[A-Z]+:($?([^\. 
']+|'([^']|'')+'))?\.$?[A-Z]+"
+    }
+cellRangeAddressList =
+  xsd:string
+  >> dc:description [
+       'Value is a space separated list of "cellRangeAddress" patterns'
+     ]
+change-mark-attr = attribute text:change-id { IDREF }
+change-marks =
+  element text:change { change-mark-attr }
+  | element text:change-start { change-mark-attr }
+  | element text:change-end { change-mark-attr }
+character = xsd:string { length = "1" }
+chart-axis =
+  element chart:axis {
+    chart-axis-attlist, chart-title?, chart-categories?, chart-grid*
   }
-text-list-header-attr = xml-id?
-text-numbered-paragraph =
-  element text:numbered-paragraph {
-    text-numbered-paragraph-attr, text-number?, (text-p | text-h)
+chart-axis-attlist =
+  attribute chart:dimension { chart-dimension }
+  & attribute chart:name { \string }?
+  & attribute chart:style-name { styleNameRef }?
+chart-categories =
+  element chart:categories {
+    attribute table:cell-range-address { cellRangeAddressList }?
   }
-text-numbered-paragraph-attr =
-  attribute text:list-id { NCName }
-  & attribute text:level { positiveInteger }?
-  & (attribute text:style-name { styleNameRef },
-     attribute text:continue-numbering { boolean },
-     attribute text:start-value { nonNegativeInteger })?
+chart-chart =
+  element chart:chart {
+    chart-chart-attlist,
+    chart-title?,
+    chart-subtitle?,
+    chart-footer?,
+    chart-legend?,
+    chart-plot-area,
+    shape*,
+    # https://issues.oasis-open.org/browse/OFFICE-2123
+    table-table?
+  }
+chart-chart-attlist =
+  attribute chart:class { namespacedToken }
+  & common-draw-size-attlist
+  & attribute chart:column-mapping { \string }?
+  & attribute chart:row-mapping { \string }?
+  & attribute chart:style-name { styleNameRef }?
+  & (attribute xlink:type { "simple" },
+     attribute xlink:href { anyIRI })?
   & xml-id?
-text-section =
-  element text:section {
-    text-section-attlist,
-    (text-section-source | text-section-source-dde | empty),
-    text-content*
+chart-coordinate-region =
+  element chart:coordinate-region {
+    chart-coordinate-region-attlist, empty
   }
-text-section-attlist =
-  common-section-attlist
-  & (attribute text:display { "true" | "none" }
-     | (attribute text:display { "condition" },
-        attribute text:condition { \string })
+chart-coordinate-region-attlist =
+  common-draw-position-attlist, common-draw-size-attlist
+# https://issues.oasis-open.org/browse/OFFICE-3928
+chart-data-label =
+  element chart:data-label { chart-data-label-attlist, text-p? }
+chart-data-label-attlist =
+  common-draw-position-attlist
+  & attribute chart:style-name { styleNameRef }?
+chart-data-point =
+  element chart:data-point {
+    chart-data-point-attlist, chart-data-label?
+  }
+chart-data-point-attlist =
+  attribute chart:repeated { positiveInteger }?
+  & attribute chart:style-name { styleNameRef }?
+  & xml-id?
+chart-dimension = "x" | "y" | "z"
+chart-domain =
+  element chart:domain {
+    attribute table:cell-range-address { cellRangeAddressList }?
+  }
+chart-equation =
+  element chart:equation { chart-equation-attlist, text-p? }
+chart-equation-attlist =
+  attribute chart:automatic-content { boolean }?
+  & attribute chart:display-r-square { boolean }?
+  & attribute chart:display-equation { boolean }?
+  & common-draw-position-attlist
+  & attribute chart:style-name { styleNameRef }?
+chart-error-indicator =
+  element chart:error-indicator { chart-error-indicator-attlist, empty }
+chart-error-indicator-attlist =
+  attribute chart:style-name { styleNameRef }?
+  & attribute chart:dimension { chart-dimension }
+chart-floor = element chart:floor { chart-floor-attlist, empty }
+chart-floor-attlist =
+  attribute svg:width { length }?
+  & attribute chart:style-name { styleNameRef }?
+chart-footer = element chart:footer { chart-title-attlist, text-p? }
+chart-grid = element chart:grid { chart-grid-attlist }
+chart-grid-attlist =
+  attribute chart:class { "major" | "minor" }?
+  & attribute chart:style-name { styleNameRef }?
+chart-legend = element chart:legend { chart-legend-attlist, text-p? }
+chart-legend-attlist =
+  ((attribute chart:legend-position {
+      "start" | "end" | "top" | "bottom"
+    },
+    attribute chart:legend-align { "start" | "center" | "end" }?)
+   | attribute chart:legend-position {
+       "top-start" | "bottom-start" | "top-end" | "bottom-end"
+     }
+   | empty)
+  & common-draw-position-attlist
+  & (attribute style:legend-expansion { "wide" | "high" | "balanced" }
+     | (attribute style:legend-expansion { "custom" },
+        attribute style:legend-expansion-aspect-ratio { double },
+        common-draw-size-attlist
+        # https://issues.oasis-open.org/browse/OFFICE-3883
+        )
      | empty)
-common-section-attlist =
-  attribute text:style-name { styleNameRef }?
-  & attribute text:name { \string }
-  & attribute text:protected { boolean }?
-  & attribute text:protection-key { \string }?
-  & attribute text:protection-key-digest-algorithm { anyIRI }?
+  & attribute chart:style-name { styleNameRef }?
+chart-mean-value =
+  element chart:mean-value { chart-mean-value-attlist, empty }
+chart-mean-value-attlist = attribute chart:style-name { styleNameRef }?
+chart-plot-area =
+  element chart:plot-area {
+    chart-plot-area-attlist,
+    # https://issues.oasis-open.org/browse/OFFICE-3928
+    chart-coordinate-region?,
+    dr3d-light*,
+    chart-axis*,
+    chart-series*,
+    chart-stock-gain-marker?,
+    chart-stock-loss-marker?,
+    chart-stock-range-line?,
+    chart-wall?,
+    chart-floor?
+  }
+chart-plot-area-attlist =
+  common-draw-position-attlist
+  & common-draw-size-attlist
+  & attribute chart:style-name { styleNameRef }?
+  & attribute table:cell-range-address { cellRangeAddressList }?
+  & attribute chart:data-source-has-labels {
+      "none" | "row" | "column" | "both"
+    }?
+  & dr3d-scene-attlist
+  & common-dr3d-transform-attlist
   & xml-id?
-text-section-source =
-  element text:section-source { text-section-source-attr }
-text-section-source-attr =
-  (attribute xlink:type { "simple" },
-   attribute xlink:href { anyIRI },
-   attribute xlink:show { "embed" }?)?
-  & attribute text:section-name { \string }?
-  & attribute text:filter-name { \string }?
-text-section-source-dde = office-dde-source
-text-tracked-changes =
-  element text:tracked-changes {
-    text-tracked-changes-attr, text-changed-region*
-  }?
-text-tracked-changes-attr = attribute text:track-changes { boolean }?
-text-changed-region =
-  element text:changed-region {
-    text-changed-region-attr, text-changed-region-content
+chart-regression-curve =
+  element chart:regression-curve {
+    chart-regression-curve-attlist, chart-equation?
   }
-text-changed-region-attr =
-  xml-id,
-  attribute text:id { NCName }?
-text-changed-region-content =
-  element text:insertion { office-change-info }
-  | element text:deletion { office-change-info, text-content* }
-  | element text:format-change { office-change-info }
-change-marks =
-  element text:change { change-mark-attr }
-  | element text:change-start { change-mark-attr }
-  | element text:change-end { change-mark-attr }
-change-mark-attr = attribute text:change-id { IDREF }
-text-soft-page-break = element text:soft-page-break { empty }
-text-decls =
-  element text:variable-decls { text-variable-decl* }?,
-  element text:sequence-decls { text-sequence-decl* }?,
-  element text:user-field-decls { text-user-field-decl* }?,
-  element text:dde-connection-decls { text-dde-connection-decl* }?,
-  text-alphabetical-index-auto-mark-file?
-paragraph-content-or-hyperlink = paragraph-content | text-a
-paragraph-content =
-  text
-  | element text:s {
-      attribute text:c { nonNegativeInteger }?
+chart-regression-curve-attlist =
+  attribute chart:style-name { styleNameRef }?
+chart-series =
+  element chart:series {
+    chart-series-attlist,
+    chart-domain*,
+    chart-mean-value?,
+    chart-regression-curve*,
+    chart-error-indicator*,
+    chart-data-point*,
+    chart-data-label?
+  }
+chart-series-attlist =
+  attribute chart:values-cell-range-address { cellRangeAddressList }?
+  & attribute chart:label-cell-address { cellRangeAddressList }?
+  & attribute chart:class { namespacedToken }?
+  & attribute chart:attached-axis { \string }?
+  & attribute chart:style-name { styleNameRef }?
+  & xml-id?
+chart-stock-gain-marker =
+  element chart:stock-gain-marker { common-stock-marker-attlist }
+chart-stock-loss-marker =
+  element chart:stock-loss-marker { common-stock-marker-attlist }
+chart-stock-range-line =
+  element chart:stock-range-line { common-stock-marker-attlist }
+chart-subtitle = element chart:subtitle { chart-title-attlist, text-p? }
+chart-title = element chart:title { chart-title-attlist, text-p? }
+chart-title-attlist =
+  attribute table:cell-range { cellRangeAddressList }?
+  & common-draw-position-attlist
+  & attribute chart:style-name { styleNameRef }?
+chart-wall = element chart:wall { chart-wall-attlist, empty }
+chart-wall-attlist =
+  attribute svg:width { length }?
+  & attribute chart:style-name { styleNameRef }?
+clipShape =
+  xsd:string {
+    pattern =
+      "rect\([ 
]*((-?([0-9]+(\.[0-9]*)?|\.[0-9]+)((cm)|(mm)|(in)|(pt)|(pc)))|(auto))([ ]*,[ 
]*((-?([0-9]+(\.[0-9]*)?|\.[0-9]+)((cm)|(mm)|(in)|(pt)|(pc))))|(auto)){3}[ ]*\)"
+  }
+color = xsd:string { pattern = "#[0-9a-fA-F]{6}" }
+column-controls =
+  element form:text { form-text-attlist, common-form-control-content }
+  | element form:textarea {
+      form-textarea-attlist, common-form-control-content, text-p*
     }
-  | element text:tab { text-tab-attr }
-  | element text:line-break { empty }
-  | text-soft-page-break
-  | element text:span {
-      attribute text:style-name { styleNameRef }?,
-      attribute text:class-names { styleNameRefs }?,
-      paragraph-content-or-hyperlink*
+  | element form:formatted-text {
+      form-formatted-text-attlist, common-form-control-content
     }
-  | element text:meta {
-      text-meta-attlist, paragraph-content-or-hyperlink*
+  | element form:number {
+      form-number-attlist,
+      common-numeric-control-attlist,
+      common-form-control-content,
+      common-linked-cell,
+      common-spin-button,
+      common-repeat,
+      common-delay-for-repeat
     }
-  | (text-bookmark | text-bookmark-start | text-bookmark-end)
-  | element text:reference-mark {
-      attribute text:name { \string }
+  | element form:date {
+      form-date-attlist,
+      common-numeric-control-attlist,
+      common-form-control-content,
+      common-linked-cell,
+      common-spin-button,
+      common-repeat,
+      common-delay-for-repeat
     }
-  | (element text:reference-mark-start {
-       attribute text:name { \string }
-     }
-     | element text:reference-mark-end {
-         attribute text:name { \string }
-       })
-  | element text:note {
-      text-note-class,
-      attribute text:id { \string }?,
-      element text:note-citation {
-        attribute text:label { \string }?,
-        text
-      },
-      element text:note-body { text-content* }
-    }
-  | element text:ruby {
-      attribute text:style-name { styleNameRef }?,
-      element text:ruby-base { paragraph-content-or-hyperlink* },
-      element text:ruby-text {
-        attribute text:style-name { styleNameRef }?,
-        text
-      }
-    }
-  | (office-annotation | office-annotation-end)
-  | change-marks
-  | shape
-  | element text:date { text-date-attlist, text }
-  | element text:time { text-time-attlist, text }
-  | element text:page-number { text-page-number-attlist, text }
-  | element text:page-continuation {
-      text-page-continuation-attlist, text
-    }
-  | element text:sender-firstname { common-field-fixed-attlist, text }
-  | element text:sender-lastname { common-field-fixed-attlist, text }
-  | element text:sender-initials { common-field-fixed-attlist, text }
-  | element text:sender-title { common-field-fixed-attlist, text }
-  | element text:sender-position { common-field-fixed-attlist, text }
-  | element text:sender-email { common-field-fixed-attlist, text }
-  | element text:sender-phone-private {
-      common-field-fixed-attlist, text
-    }
-  | element text:sender-fax { common-field-fixed-attlist, text }
-  | element text:sender-company { common-field-fixed-attlist, text }
-  | element text:sender-phone-work { common-field-fixed-attlist, text }
-  | element text:sender-street { common-field-fixed-attlist, text }
-  | element text:sender-city { common-field-fixed-attlist, text }
-  | element text:sender-postal-code { common-field-fixed-attlist, text }
-  | element text:sender-country { common-field-fixed-attlist, text }
-  | element text:sender-state-or-province {
-      common-field-fixed-attlist, text
-    }
-  | element text:author-name { common-field-fixed-attlist, text }
-  | element text:author-initials { common-field-fixed-attlist, text }
-  | element text:chapter { text-chapter-attlist, text }
-  | element text:file-name { text-file-name-attlist, text }
-  | element text:template-name { text-template-name-attlist, text }
-  | element text:sheet-name { text }
-  | element text:variable-set {
-      (common-field-name-attlist
-       & common-field-formula-attlist
-       & common-value-and-type-attlist
-       & common-field-display-value-none-attlist
-       & common-field-data-style-name-attlist),
-      text
-    }
-  | element text:variable-get {
-      (common-field-name-attlist
-       & common-field-display-value-formula-attlist
-       & common-field-data-style-name-attlist),
-      text
-    }
-  | element text:variable-input {
-      (common-field-name-attlist
-       & common-field-description-attlist
-       & common-value-type-attlist
-       & common-field-display-value-none-attlist
-       & common-field-data-style-name-attlist),
-      text
-    }
-  | element text:user-field-get {
-      (common-field-name-attlist
-       & common-field-display-value-formula-none-attlist
-       & common-field-data-style-name-attlist),
-      text
-    }
-  | element text:user-field-input {
-      (common-field-name-attlist
-       & common-field-description-attlist
-       & common-field-data-style-name-attlist),
-      text
-    }
-  | element text:sequence {
-      (common-field-name-attlist
-       & common-field-formula-attlist
-       & common-field-num-format-attlist
-       & text-sequence-ref-name),
-      text
-    }
-  | element text:expression {
-      (common-field-formula-attlist
-       & common-value-and-type-attlist?
-       & common-field-display-value-formula-attlist
-       & common-field-data-style-name-attlist),
-      text
-    }
-  | element text:text-input { common-field-description-attlist, text }
-  | element text:initial-creator { common-field-fixed-attlist, text }
-  | element text:creation-date {
-      (common-field-fixed-attlist
-       & common-field-data-style-name-attlist
-       & attribute text:date-value { dateOrDateTime }?),
-      text
-    }
-  | element text:creation-time {
-      (common-field-fixed-attlist
-       & common-field-data-style-name-attlist
-       & attribute text:time-value { timeOrDateTime }?),
-      text
-    }
-  | element text:description { common-field-fixed-attlist, text }
-  | element text:user-defined {
-      (common-field-fixed-attlist
-       & attribute text:name { \string }
-       & common-field-data-style-name-attlist
-       & attribute office:value { double }?
-       & attribute office:date-value { dateOrDateTime }?
-       & attribute office:time-value { duration }?
-       & attribute office:boolean-value { boolean }?
-       & attribute office:string-value { \string }?),
-      text
-    }
-  | element text:print-time {
-      (common-field-fixed-attlist
-       & common-field-data-style-name-attlist
-       & attribute text:time-value { time }?),
-      text
-    }
-  | element text:print-date {
-      (common-field-fixed-attlist
-       & common-field-data-style-name-attlist
-       & attribute text:date-value { date }?),
-      text
-    }
-  | element text:printed-by { common-field-fixed-attlist, text }
-  | element text:title { common-field-fixed-attlist, text }
-  | element text:subject { common-field-fixed-attlist, text }
-  | element text:keywords { common-field-fixed-attlist, text }
-  | element text:editing-cycles { common-field-fixed-attlist, text }
-  | element text:editing-duration {
-      (common-field-fixed-attlist
-       & common-field-data-style-name-attlist
-       & attribute text:duration { duration }?),
-      text
-    }
-  | element text:modification-time {
-      (common-field-fixed-attlist
-       & common-field-data-style-name-attlist
-       & attribute text:time-value { time }?),
-      text
-    }
-  | element text:modification-date {
-      (common-field-fixed-attlist
-       & common-field-data-style-name-attlist
-       & attribute text:date-value { date }?),
-      text
-    }
-  | element text:creator { common-field-fixed-attlist, text }
-  | element text:page-count
-            | text:paragraph-count
-            | text:word-count
-            | text:character-count
-            | text:table-count
-            | text:image-count
-            | text:object-count {
-      common-field-num-format-attlist, text
-    }
-  | element text:database-display {
-      text-database-display-attlist, text
-    }
-  | element text:database-next { text-database-next-attlist }
-  | element text:database-row-select {
-      text-database-row-select-attlist
-    }
-  | element text:database-row-number {
-      (common-field-database-table
-       & common-field-num-format-attlist
-       & attribute text:value { nonNegativeInteger }?),
-      text
-    }
-  | element text:database-name { common-field-database-table, text }
-  | element text:page-variable-set {
-      text-set-page-variable-attlist, text
-    }
-  | element text:page-variable-get {
-      text-get-page-variable-attlist, text
-    }
-  | element text:placeholder { text-placeholder-attlist, text }
-  | element text:conditional-text {
-      text-conditional-text-attlist, text
-    }
-  | element text:hidden-text { text-hidden-text-attlist, text }
-  | element text:reference-ref | text:bookmark-ref {
-      text-common-ref-content & text-bookmark-ref-content
-    }
-  | element text:note-ref {
-      text-common-ref-content & text-note-ref-content
-    }
-  | element text:sequence-ref {
-      text-common-ref-content & text-sequence-ref-content
-    }
-  | element text:script {
-      ((attribute xlink:type { "simple" },
-        attribute xlink:href { anyIRI })
-       | text)
-      & attribute script:language { \string }?
-    }
-  | element text:execute-macro {
-      attribute text:name { \string }?,
-      office-event-listeners?,
-      text
-    }
-  | element text:hidden-paragraph {
-      text-hidden-paragraph-attlist, text
-    }
-  | element text:dde-connection {
-      attribute text:connection-name { \string },
-      text
-    }
-  | element text:measure {
-      attribute text:kind { "value" | "unit" | "gap" },
-      text
-    }
-  | element text:table-formula {
-      (common-field-formula-attlist
-       & common-field-display-value-formula-attlist
-       & common-field-data-style-name-attlist),
-      text
-    }
-  | element text:meta-field {
-      text-meta-field-attlist, paragraph-content-or-hyperlink*
+  | element form:time {
+      form-time-attlist,
+      common-numeric-control-attlist,
+      common-form-control-content,
+      common-linked-cell,
+      common-spin-button,
+      common-repeat,
+      common-delay-for-repeat
     }
-  | element text:toc-mark-start { text-toc-mark-start-attrs }
-  | element text:toc-mark-end { text-id }
-  | element text:toc-mark {
-      attribute text:string-value { \string },
-      text-outline-level
+  | element form:combobox {
+      form-combobox-attlist, common-form-control-content, form-item*
     }
-  | element text:user-index-mark-start {
-      text-id, text-outline-level, text-index-name
+  | element form:listbox {
+      form-listbox-attlist, common-form-control-content, form-option*
     }
-  | element text:user-index-mark-end { text-id }
-  | element text:user-index-mark {
-      attribute text:string-value { \string },
-      text-outline-level,
-      text-index-name
+  | element form:checkbox {
+      form-checkbox-attlist, common-form-control-content
     }
-  | element text:alphabetical-index-mark-start {
-      text-id, text-alphabetical-index-mark-attrs
-    }
-  | element text:alphabetical-index-mark-end { text-id }
-  | element text:alphabetical-index-mark {
-      attribute text:string-value { \string },
-      text-alphabetical-index-mark-attrs
-    }
-  | element text:bibliography-mark {
-      attribute text:bibliography-type { text-bibliography-types },
-      attribute text:identifier
-                | text:address
-                | text:annote
-                | text:author
-                | text:booktitle
-                | text:chapter
-                | text:edition
-                | text:editor
-                | text:howpublished
-                | text:institution
-                | text:journal
-                | text:month
-                | text:note
-                | text:number
-                | text:organizations
-                | text:pages
-                | text:publisher
-                | text:school
-                | text:series
-                | text:title
-                | text:report-type
-                | text:volume
-                | text:year
-                | text:url
-                | text:custom1
-                | text:custom2
-                | text:custom3
-                | text:custom4
-                | text:custom5
-                | text:isbn
-                | text:issn { \string }*,
-      text
-    }
-  | element presentation:header { empty }
-  | element presentation:footer { empty }
-  | element presentation:date-time { empty }
-text-tab-attr = attribute text:tab-ref { nonNegativeInteger }?
-text-a =
-  element text:a {
-    text-a-attlist, office-event-listeners?, paragraph-content*
-  }
-text-a-attlist =
-  attribute office:name { \string }?
-  & attribute office:title { \string }?
-  & attribute xlink:type { "simple" }
-  & attribute xlink:href { anyIRI }
-  & attribute xlink:actuate { "onRequest" }?
-  & attribute office:target-frame-name { targetFrameName }?
-  & attribute xlink:show { "new" | "replace" }?
-  & attribute text:style-name { styleNameRef }?
-  & attribute text:visited-style-name { styleNameRef }?
-text-meta-attlist = common-in-content-meta-attlist? & xml-id?
-text-bookmark = element text:bookmark { text-bookmark-attlist, empty }
-text-bookmark-start =
-  element text:bookmark-start { text-bookmark-start-attlist, empty }
-text-bookmark-end =
-  element text:bookmark-end { text-bookmark-end-attlist, empty }
-text-bookmark-attlist =
-  attribute text:name { \string }
-  & xml-id?
-text-bookmark-start-attlist =
-  attribute text:name { \string }
-  & xml-id?
-  & common-in-content-meta-attlist?
-text-bookmark-end-attlist = attribute text:name { \string }
-text-note-class = attribute text:note-class { "footnote" | "endnote" }
-text-date-attlist =
-  (common-field-fixed-attlist & common-field-data-style-name-attlist)
-  & attribute text:date-value { dateOrDateTime }?
-  & attribute text:date-adjust { duration }?
-text-time-attlist =
-  (common-field-fixed-attlist & common-field-data-style-name-attlist)
-  & attribute text:time-value { timeOrDateTime }?
-  & attribute text:time-adjust { duration }?
-text-page-number-attlist =
-  (common-field-num-format-attlist & common-field-fixed-attlist)
-  & attribute text:page-adjust { integer }?
-  & attribute text:select-page { "previous" | "current" | "next" }?
-text-page-continuation-attlist =
-  attribute text:select-page { "previous" | "next" }
-  & attribute text:string-value { \string }?
-text-chapter-attlist =
-  attribute text:display {
-    "name"
-    | "number"
-    | "number-and-name"
-    | "plain-number-and-name"
-    | "plain-number"
-  }
-  & attribute text:outline-level { nonNegativeInteger }
-text-file-name-attlist =
-  attribute text:display {
-    "full" | "path" | "name" | "name-and-extension"
+common-anim-add-accum-attlist =
+  attribute smil:accumulate { "none" | "sum" }?
+  & attribute smil:additive { "replace" | "sum" }?
+common-anim-attlist =
+  attribute presentation:node-type {
+    "default"
+    | "on-click"
+    | "with-previous"
+    | "after-previous"
+    | "timing-root"
+    | "main-sequence"
+    | "interactive-sequence"
   }?
-  & common-field-fixed-attlist
-text-template-name-attlist =
-  attribute text:display {
-    "full" | "path" | "name" | "name-and-extension" | "area" | "title"
+  & attribute presentation:preset-id { \string }?
+  & attribute presentation:preset-sub-type { \string }?
+  & attribute presentation:preset-class {
+      "custom"
+      | "entrance"
+      | "exit"
+      | "emphasis"
+      | "motion-path"
+      | "ole-action"
+      | "media-call"
+    }?
+  & attribute presentation:master-element { IDREF }?
+  & attribute presentation:group-id { \string }?
+  & (xml-id,
+     attribute anim:id { NCName }?)?
+common-anim-named-target-attlist =
+  attribute smil:attributeName { \string }
+common-anim-set-values-attlist = attribute smil:to { \string }?
+common-anim-spline-mode-attlist =
+  attribute smil:calcMode {
+    "discrete" | "linear" | "paced" | "spline"
   }?
-text-variable-decl =
-  element text:variable-decl {
-    common-field-name-attlist, common-value-type-attlist
-  }
-text-user-field-decl =
-  element text:user-field-decl {
-    common-field-name-attlist,
-    common-field-formula-attlist?,
-    common-value-and-type-attlist
-  }
-text-sequence-decl =
-  element text:sequence-decl { text-sequence-decl-attlist }
-text-sequence-decl-attlist =
-  common-field-name-attlist
-  & attribute text:display-outline-level { nonNegativeInteger }
-  & attribute text:separation-character { character }?
-text-sequence-ref-name = attribute text:ref-name { \string }?
-common-field-database-table =
-  common-field-database-table-attlist, common-field-database-name
-common-field-database-name =
-  attribute text:database-name { \string }?
-  | form-connection-resource
-common-field-database-table-attlist =
-  attribute text:table-name { \string }
-  & attribute text:table-type { "table" | "query" | "command" }?
-text-database-display-attlist =
-  common-field-database-table
-  & common-field-data-style-name-attlist
-  & attribute text:column-name { \string }
-text-database-next-attlist =
-  common-field-database-table
-  & attribute text:condition { \string }?
-text-database-row-select-attlist =
-  common-field-database-table
-  & attribute text:condition { \string }?
-  & attribute text:row-number { nonNegativeInteger }?
-text-set-page-variable-attlist =
-  attribute text:active { boolean }?
-  & attribute text:page-adjust { integer }?
-text-get-page-variable-attlist = common-field-num-format-attlist
-text-placeholder-attlist =
-  attribute text:placeholder-type {
-    "text" | "table" | "text-box" | "image" | "object"
-  }
-  & common-field-description-attlist
-text-conditional-text-attlist =
-  attribute text:condition { \string }
-  & attribute text:string-value-if-true { \string }
-  & attribute text:string-value-if-false { \string }
-  & attribute text:current-value { boolean }?
-text-hidden-text-attlist =
-  attribute text:condition { \string }
-  & attribute text:string-value { \string }
-  & attribute text:is-hidden { boolean }?
-text-common-ref-content =
-  text
-  & attribute text:ref-name { \string }?
-text-bookmark-ref-content =
-  attribute text:reference-format {
-    common-ref-format-values
-    | "number-no-superior"
-    | "number-all-superior"
-    | "number"
+common-anim-target-attlist =
+  attribute smil:targetElement { IDREF }?
+  & attribute anim:sub-item { \string }?
+common-anim-values-attlist =
+  attribute smil:values { \string }?
+  & attribute anim:formula { \string }?
+  & common-anim-set-values-attlist
+  & attribute smil:from { \string }?
+  & attribute smil:by { \string }?
+common-auto-reorder-attlist =
+  attribute number:automatic-order { boolean }?
+common-background-color-attlist =
+  attribute fo:background-color { "transparent" | color }?
+common-background-transparency-attlist =
+  attribute style:background-transparency { zeroToHundredPercent }?
+common-basic-timing-attlist =
+  common-begin-end-timing-attlist,
+  common-dur-timing-attlist,
+  common-repeat-timing-attlist,
+  common-restart-timing-attlist,
+  common-restart-default-attlist,
+  common-fill-timing-attlist,
+  common-fill-default-attlist
+common-begin-end-timing-attlist =
+  attribute smil:begin { \string }?
+  & attribute smil:end { \string }?
+common-border-attlist =
+  attribute fo:border { \string }?,
+  attribute fo:border-top { \string }?,
+  attribute fo:border-bottom { \string }?,
+  attribute fo:border-left { \string }?,
+  attribute fo:border-right { \string }?
+common-border-line-width-attlist =
+  attribute style:border-line-width { borderWidths }?,
+  attribute style:border-line-width-top { borderWidths }?,
+  attribute style:border-line-width-bottom { borderWidths }?,
+  attribute style:border-line-width-left { borderWidths }?,
+  attribute style:border-line-width-right { borderWidths }?
+common-break-attlist =
+  attribute fo:break-before { "auto" | "column" | "page" }?,
+  attribute fo:break-after { "auto" | "column" | "page" }?
+common-calendar-attlist =
+  attribute number:calendar {
+    "gregorian"
+    | "gengou"
+    | "ROC"
+    | "hanja_yoil"
+    | "hanja"
+    | "hijri"
+    | "jewish"
+    | "buddhist"
+    | \string
   }?
-text-note-ref-content =
-  attribute text:reference-format { common-ref-format-values }?
-  & text-note-class
-text-sequence-ref-content =
-  attribute text:reference-format {
-    common-ref-format-values
-    | "category-and-value"
-    | "caption"
-    | "value"
-  }?
-common-ref-format-values = "page" | "chapter" | "direction" | "text"
-text-hidden-paragraph-attlist =
-  attribute text:condition { \string }
-  & attribute text:is-hidden { boolean }?
-text-meta-field-attlist = xml-id & common-field-data-style-name-attlist
-common-value-type-attlist = attribute office:value-type { valueType }
-common-value-and-type-attlist =
-  (attribute office:value-type { "float" },
-   attribute office:value { double })
-  | (attribute office:value-type { "percentage" },
-     attribute office:value { double })
-  | (attribute office:value-type { "currency" },
-     attribute office:value { double },
-     attribute office:currency { \string }?)
-  | (attribute office:value-type { "date" },
-     attribute office:date-value { dateOrDateTime })
-  | (attribute office:value-type { "time" },
-     attribute office:time-value { duration })
-  | (attribute office:value-type { "boolean" },
-     attribute office:boolean-value { boolean })
-  | (attribute office:value-type { "string" },
-     attribute office:string-value { \string }?)
-common-field-fixed-attlist = attribute text:fixed { boolean }?
-common-field-name-attlist = attribute text:name { variableName }
+common-contour-attlist = attribute draw:recreate-on-edit { boolean }
+common-control-id-attlist =
+  xml-id,
+  attribute form:id { NCName }?
+common-convert-empty-attlist =
+  attribute form:convert-empty-to-null { boolean }?
+common-current-value-attlist = attribute form:current-value { \string }?
+common-data-field-attlist = attribute form:data-field { \string }?
+common-data-style-attlist =
+  attribute style:name { styleName }
+  & attribute style:display-name { \string }?
+  & attribute number:language { languageCode }?
+  & attribute number:country { countryCode }?
+  & attribute number:script { scriptCode }?
+  & attribute number:rfc-language-tag { language }?
+  & attribute number:title { \string }?
+  & attribute style:volatile { boolean }?
+  & attribute number:transliteration-format { \string }?
+  & attribute number:transliteration-language { countryCode }?
+  & attribute number:transliteration-country { countryCode }?
+  & attribute number:transliteration-style {
+      "short" | "medium" | "long"
+    }?
+common-db-default-value = common-value-and-type-attlist?
+common-db-object-description = attribute db:description { \string }?
+common-db-object-name = attribute db:name { \string }
+common-db-object-title = attribute db:title { \string }?
+common-db-table-name-attlist =
+  attribute db:name { \string }
+  & attribute db:catalog-name { \string }?
+  & attribute db:schema-name { \string }?
+common-db-table-style-name =
+  attribute db:style-name { styleNameRef }?
+  & attribute db:default-row-style-name { styleNameRef }?
+common-dde-connection-decl-attlist =
+  attribute office:dde-application { \string }
+  & attribute office:dde-topic { \string }
+  & attribute office:dde-item { \string }
+  & attribute office:automatic-update { boolean }?
+common-decimal-places-attlist =
+  attribute number:decimal-places { integer }?,
+  (attribute number:min-decimal-places { integer }?)
+  # https://issues.oasis-open.org/browse/OFFICE-3860  added 
number:min-decimal-places
+
+common-delay-for-repeat = attribute form:delay-for-repeat { duration }?
+common-disabled-attlist = attribute form:disabled { boolean }?
+common-dr3d-transform-attlist = attribute dr3d:transform { \string }?
+common-draw-area-attlist =
+  (attribute xlink:type { "simple" },
+   attribute xlink:href { anyIRI },
+   attribute office:target-frame-name { targetFrameName }?,
+   attribute xlink:show { "new" | "replace" }?)?
+  & attribute office:name { \string }?
+  & attribute draw:nohref { "nohref" }?
+common-draw-caption-id-attlist = attribute draw:caption-id { IDREF }?
+common-draw-circle-ellipse-attlist =
+  attribute draw:kind { "full" | "section" | "cut" | "arc" }?
+  & attribute draw:start-angle { angle }?
+  & attribute draw:end-angle { angle }?
+common-draw-circle-ellipse-pos-attlist =
+  attribute svg:cx { coordinate },
+  attribute svg:cy { coordinate }
+common-draw-data-attlist =
+  attribute xlink:type { "simple" },
+  attribute xlink:href { anyIRI },
+  attribute xlink:show { "embed" }?,
+  attribute xlink:actuate { "onLoad" }?
+common-draw-gradient-attlist =
+  attribute draw:name { styleName }?
+  & attribute draw:display-name { \string }?
+  & attribute draw:style { gradient-style }
+  & attribute draw:cx { percent }?
+  & attribute draw:cy { percent }?
+  & attribute draw:angle { angle }?
+  & attribute draw:border { percent }?
+common-draw-id-attlist =
+  (xml-id,
+   attribute draw:id { NCName }?)?
+common-draw-layer-name-attlist = attribute draw:layer { \string }?
+common-draw-mime-type-attlist = attribute draw:mime-type { \string }?
+# https://issues.oasis-open.org/browse/OFFICE-3943
+common-draw-name-attlist = attribute draw:name { \string }?
+common-draw-path-data-attlist = attribute svg:d { pathData }
+common-draw-points-attlist = attribute draw:points { points }
+common-draw-position-attlist =
+  attribute svg:x { coordinate }?,
+  attribute svg:y { coordinate }?
+common-draw-rel-size-attlist =
+  common-draw-size-attlist,
+  attribute style:rel-width { percent | "scale" | "scale-min" }?,
+  attribute style:rel-height { percent | "scale" | "scale-min" }?
+common-draw-shape-with-styles-attlist =
+  common-draw-z-index-attlist,
+  common-draw-id-attlist,
+  common-draw-layer-name-attlist,
+  common-draw-style-name-attlist,
+  common-draw-transform-attlist,
+  common-draw-name-attlist,
+  common-text-spreadsheet-shape-attlist
+common-draw-shape-with-text-and-styles-attlist =
+  common-draw-shape-with-styles-attlist,
+  common-draw-text-style-name-attlist
+common-draw-size-attlist =
+  attribute svg:width { length }?,
+  attribute svg:height { length }?
+common-draw-style-name-attlist =
+  (attribute draw:style-name { styleNameRef }?,
+   attribute draw:class-names { styleNameRefs }?)
+  | (attribute presentation:style-name { styleNameRef }?,
+     attribute presentation:class-names { styleNameRefs }?)
+common-draw-text-style-name-attlist =
+  attribute draw:text-style-name { styleNameRef }?
+common-draw-transform-attlist = attribute draw:transform { \string }?
+common-draw-viewbox-attlist =
+  attribute svg:viewBox {
+    list { integer, integer, integer, integer }
+  }
+common-draw-z-index-attlist =
+  attribute draw:z-index { nonNegativeInteger }?
+common-dur-timing-attlist = attribute smil:dur { \string }?
+common-editable-attlist = attribute style:editable { boolean }?
+common-endsync-timing-attlist =
+  attribute smil:endsync { "first" | "last" | "all" | "media" | IDREF }?
+common-field-data-style-name-attlist =
+  attribute style:data-style-name { styleNameRef }?
+common-field-database-name =
+  attribute text:database-name { \string }?
+  | form-connection-resource
+common-field-database-table =
+  common-field-database-table-attlist, common-field-database-name
+common-field-database-table-attlist =
+  attribute text:table-name { \string }
+  & attribute text:table-type { "table" | "query" | "command" }?
 common-field-description-attlist =
   attribute text:description { \string }?
-common-field-display-value-none-attlist =
-  attribute text:display { "value" | "none" }?
-common-field-display-value-formula-none-attlist =
-  attribute text:display { "value" | "formula" | "none" }?
 common-field-display-value-formula-attlist =
   attribute text:display { "value" | "formula" }?
+common-field-display-value-formula-none-attlist =
+  attribute text:display { "value" | "formula" | "none" }?
+common-field-display-value-none-attlist =
+  attribute text:display { "value" | "none" }?
+common-field-fixed-attlist = attribute text:fixed { boolean }?
 common-field-formula-attlist = attribute text:formula { \string }?
-common-field-data-style-name-attlist =
-  attribute style:data-style-name { styleNameRef }?
+common-field-name-attlist = attribute text:name { variableName }
 common-field-num-format-attlist = common-num-format-attlist?
-text-toc-mark-start-attrs = text-id, text-outline-level
-text-outline-level = attribute text:outline-level { positiveInteger }?
-text-id = attribute text:id { \string }
-text-index-name = attribute text:index-name { \string }
-text-alphabetical-index-mark-attrs =
-  attribute text:key1 { \string }?
-  & attribute text:key2 { \string }?
-  & attribute text:string-value-phonetic { \string }?
-  & attribute text:key1-phonetic { \string }?
-  & attribute text:key2-phonetic { \string }?
-  & attribute text:main-entry { boolean }?
-text-bibliography-types =
-  "article"
-  | "book"
-  | "booklet"
-  | "conference"
-  | "custom1"
-  | "custom2"
-  | "custom3"
-  | "custom4"
-  | "custom5"
-  | "email"
-  | "inbook"
-  | "incollection"
-  | "inproceedings"
-  | "journal"
-  | "manual"
-  | "mastersthesis"
-  | "misc"
-  | "phdthesis"
-  | "proceedings"
-  | "techreport"
-  | "unpublished"
-  | "www"
-text-index-body = element text:index-body { index-content-main* }
-index-content-main = text-content | text-index-title
-text-index-title =
-  element text:index-title {
-    common-section-attlist, index-content-main*
-  }
-text-table-of-content =
-  element text:table-of-content {
-    common-section-attlist,
-    text-table-of-content-source,
-    text-index-body
-  }
-text-table-of-content-source =
-  element text:table-of-content-source {
-    text-table-of-content-source-attlist,
-    text-index-title-template?,
-    text-table-of-content-entry-template*,
-    text-index-source-styles*
-  }
-text-table-of-content-source-attlist =
-  attribute text:outline-level { positiveInteger }?
-  & attribute text:use-outline-level { boolean }?
-  & attribute text:use-index-marks { boolean }?
-  & attribute text:use-index-source-styles { boolean }?
-  & attribute text:index-scope { "document" | "chapter" }?
-  & attribute text:relative-tab-stop-position { boolean }?
-text-table-of-content-entry-template =
-  element text:table-of-content-entry-template {
-    text-table-of-content-entry-template-attlist,
-    text-table-of-content-children*
-  }
-text-table-of-content-children =
-  text-index-entry-chapter
-  | text-index-entry-page-number
-  | text-index-entry-text
-  | text-index-entry-span
-  | text-index-entry-tab-stop
-  | text-index-entry-link-start
-  | text-index-entry-link-end
-text-table-of-content-entry-template-attlist =
-  attribute text:outline-level { positiveInteger }
-  & attribute text:style-name { styleNameRef }
-text-illustration-index =
-  element text:illustration-index {
-    common-section-attlist,
-    text-illustration-index-source,
-    text-index-body
-  }
-text-illustration-index-source =
-  element text:illustration-index-source {
-    text-illustration-index-source-attrs,
-    text-index-title-template?,
-    text-illustration-index-entry-template?
-  }
-text-illustration-index-source-attrs =
-  text-index-scope-attr
-  & text-relative-tab-stop-position-attr
-  & attribute text:use-caption { boolean }?
-  & attribute text:caption-sequence-name { \string }?
-  & attribute text:caption-sequence-format {
-      "text" | "category-and-value" | "caption"
+common-fill-default-attlist =
+  attribute smil:fillDefault {
+    "remove" | "freeze" | "hold" | "transition" | "auto" | "inherit"
+  }?
+common-fill-timing-attlist =
+  attribute smil:fill {
+    "remove" | "freeze" | "hold" | "auto" | "default" | "transition"
+  }?
+common-form-control-attlist =
+  attribute form:name { \string }?
+  & attribute form:control-implementation { namespacedToken }?
+common-form-control-content = form-properties?, office-event-listeners?
+common-form-relative-image-position-attlist =
+  attribute form:image-position { "center" }?
+  | (attribute form:image-position {
+       "start" | "end" | "top" | "bottom"
+     },
+     attribute form:image-align { "start" | "center" | "end" }?)
+common-form-visual-effect-attlist =
+  attribute form:visual-effect { "flat" | "3d" }?
+common-format-source-attlist =
+  attribute number:format-source { "fixed" | "language" }?
+common-horizontal-margin-attlist =
+  attribute fo:margin-left { length | percent }?,
+  attribute fo:margin-right { length | percent }?
+common-in-content-meta-attlist =
+  attribute xhtml:about { URIorSafeCURIE },
+  attribute xhtml:property { CURIEs },
+  common-meta-literal-attlist
+common-keep-with-next-attlist =
+  attribute fo:keep-with-next { "auto" | "always" }?
+common-linked-cell =
+  attribute form:linked-cell { cellAddress | \string }?
+common-margin-attlist =
+  attribute fo:margin { nonNegativeLength | percent }?
+common-maxlength-attlist =
+  attribute form:max-length { nonNegativeInteger }?
+common-meta-literal-attlist =
+  attribute xhtml:datatype { CURIE }?,
+  attribute xhtml:content { \string }?
+common-num-format-attlist =
+  attribute style:num-format { "1" | "i" | "I" | \string | empty }
+  | (attribute style:num-format { "a" | "A" },
+     style-num-letter-sync-attlist)
+  | empty
+common-num-format-prefix-suffix-attlist =
+  attribute style:num-prefix { \string }?,
+  attribute style:num-suffix { \string }?
+common-number-attlist =
+  attribute number:min-integer-digits { integer }?
+  & attribute number:grouping { boolean }?
+common-numeric-control-attlist =
+  form-control-attlist,
+  common-disabled-attlist,
+  common-maxlength-attlist,
+  common-printable-attlist,
+  common-readonly-attlist,
+  common-tab-attlist,
+  common-title-attlist,
+  common-convert-empty-attlist,
+  common-data-field-attlist
+common-office-annotation-name-attlist =
+  attribute office:name { \string }
+common-padding-attlist =
+  attribute fo:padding { nonNegativeLength }?,
+  attribute fo:padding-top { nonNegativeLength }?,
+  attribute fo:padding-bottom { nonNegativeLength }?,
+  attribute fo:padding-left { nonNegativeLength }?,
+  attribute fo:padding-right { nonNegativeLength }?
+common-page-number-attlist =
+  attribute style:page-number {
+    (nonNegativeInteger | "auto")
+    # https://issues.oasis-open.org/browse/OFFICE-3923
+
+  }?
+common-presentation-effect-attlist =
+  attribute draw:shape-id { IDREF }
+  & attribute presentation:effect { presentationEffects }?
+  & attribute presentation:direction { presentationEffectDirections }?
+  & attribute presentation:speed { presentationSpeeds }?
+  & attribute presentation:delay { duration }?
+  & attribute presentation:start-scale { percent }?
+  & attribute presentation:path-id { \string }?
+common-presentation-header-footer-attlist =
+  attribute presentation:use-header-name { \string }?
+  & attribute presentation:use-footer-name { \string }?
+  & attribute presentation:use-date-time-name { \string }?
+common-printable-attlist = attribute form:printable { boolean }?
+common-readonly-attlist = attribute form:readonly { boolean }?
+common-ref-format-values = "page" | "chapter" | "direction" | "text"
+common-repeat = attribute form:repeat { boolean }?
+common-repeat-timing-attlist =
+  attribute smil:repeatDur { \string }?,
+  attribute smil:repeatCount { nonNegativeDecimal | "indefinite" }?
+common-restart-default-attlist =
+  attribute smil:restartDefault {
+    "never" | "always" | "whenNotActive" | "inherit"
+  }?
+common-restart-timing-attlist =
+  attribute smil:restart {
+    "never" | "always" | "whenNotActive" | "default"
+  }?
+common-rotation-angle-attlist =
+  attribute style:rotation-angle { angle }?
+common-section-attlist =
+  attribute text:style-name { styleNameRef }?
+  & attribute text:name { \string }
+  & attribute text:protected { boolean }?
+  & attribute text:protection-key { \string }?
+  & attribute text:protection-key-digest-algorithm { anyIRI }?
+  & xml-id?
+common-shadow-attlist = attribute style:shadow { shadowType }?
+common-source-cell-range =
+  attribute form:source-cell-range { cellRangeAddress | \string }?
+common-spin-button = attribute form:spin-button { boolean }?
+common-spline-anim-value-attlist =
+  attribute smil:keyTimes { \string }?
+  & attribute smil:keySplines { \string }?
+common-stock-marker-attlist =
+  attribute chart:style-name { styleNameRef }?
+common-style-direction-attlist =
+  attribute style:direction { "ltr" | "ttb" }?
+common-style-header-footer-attlist =
+  attribute style:display { boolean }?
+common-svg-font-face-xlink-attlist =
+  attribute xlink:type { "simple" },
+  attribute xlink:href { anyIRI },
+  attribute xlink:actuate { "onRequest" }?
+common-svg-gradient-attlist =
+  attribute svg:gradientUnits { "objectBoundingBox" }?
+  & attribute svg:gradientTransform { \string }?
+  & attribute svg:spreadMethod { "pad" | "reflect" | "repeat" }?
+  & attribute draw:name { styleName }
+  & attribute draw:display-name { \string }?
+common-tab-attlist =
+  attribute form:tab-index { nonNegativeInteger }?
+  & attribute form:tab-stop { boolean }?
+common-table-cell-address-attlist =
+  attribute table:column { integer },
+  attribute table:row { integer },
+  attribute table:table { integer }
+common-table-cell-range-address-attlist =
+  attribute table:start-column { integer },
+  attribute table:start-row { integer },
+  attribute table:start-table { integer },
+  attribute table:end-column { integer },
+  attribute table:end-row { integer },
+  attribute table:end-table { integer }
+common-table-change-attlist =
+  attribute table:id { \string }
+  & attribute table:acceptance-state {
+      "accepted" | "rejected" | "pending"
     }?
-text-index-scope-attr =
-  attribute text:index-scope { "document" | "chapter" }?
-text-relative-tab-stop-position-attr =
-  attribute text:relative-tab-stop-position { boolean }?
-text-illustration-index-entry-template =
-  element text:illustration-index-entry-template {
-    text-illustration-index-entry-content
+  & attribute table:rejecting-change-id { \string }?
+common-table-range-attlist =
+  common-table-cell-address-attlist
+  | common-table-cell-range-address-attlist
+common-table-template-attlist =
+  attribute table:style-name { styleNameRef },
+  attribute table:paragraph-style-name { styleNameRef }?
+common-text-align =
+  attribute fo:text-align {
+    "start" | "end" | "left" | "right" | "center" | "justify"
+  }?
+common-text-anchor-attlist =
+  attribute text:anchor-type {
+    "page" | "frame" | "paragraph" | "char" | "as-char"
+  }?
+  & attribute text:anchor-page-number { positiveInteger }?
+common-text-spreadsheet-shape-attlist =
+  attribute table:end-cell-address { cellAddress }?
+  & attribute table:end-x { coordinate }?
+  & attribute table:end-y { coordinate }?
+  & attribute table:table-background { boolean }?
+  & common-text-anchor-attlist
+common-time-manip-attlist =
+  attribute smil:accelerate { zeroToOneDecimal }?
+  & attribute smil:decelerate { zeroToOneDecimal }?
+  & attribute smil:autoReverse { boolean }?
+common-timing-attlist =
+  common-basic-timing-attlist, common-time-manip-attlist
+common-title-attlist = attribute form:title { \string }?
+common-value-and-type-attlist =
+  (attribute office:value-type { "float" },
+   attribute office:value { double })
+  | (attribute office:value-type { "percentage" },
+     attribute office:value { double })
+  | (attribute office:value-type { "currency" },
+     attribute office:value { double },
+     attribute office:currency { \string }?)
+  | (attribute office:value-type { "date" },
+     attribute office:date-value { dateOrDateTime })
+  | (attribute office:value-type { "time" },
+     attribute office:time-value { duration })
+  | (attribute office:value-type { "boolean" },
+     attribute office:boolean-value { boolean })
+  | (attribute office:value-type { "string" },
+     attribute office:string-value { \string }?)
+common-value-attlist = attribute form:value { \string }?
+common-value-type-attlist = attribute office:value-type { valueType }
+common-vertical-margin-attlist =
+  attribute fo:margin-top { nonNegativeLength | percent }?,
+  attribute fo:margin-bottom { nonNegativeLength | percent }?
+common-vertical-pos-attlist =
+  attribute style:vertical-pos {
+    "top" | "middle" | "bottom" | "from-top" | "below"
+  }?,
+  attribute svg:y { coordinate }?
+common-vertical-rel-attlist =
+  attribute style:vertical-rel {
+    "page"
+    | "page-content"
+    | "frame"
+    | "frame-content"
+    | "paragraph"
+    | "paragraph-content"
+    | "char"
+    | "line"
+    | "baseline"
+    | "text"
+  }?
+common-writing-mode-attlist =
+  attribute style:writing-mode {
+    "lr-tb" | "rl-tb" | "tb-rl" | "tb-lr" | "lr" | "rl" | "tb" | "page"
+  }?
+config-config-item =
+  element config:config-item { config-config-item-attlist, text }
+config-config-item-attlist =
+  attribute config:name { \string }
+  & attribute config:type {
+      "boolean"
+      | "short"
+      | "int"
+      | "long"
+      | "double"
+      | "string"
+      | "datetime"
+      | "base64Binary"
+    }
+config-config-item-map-entry =
+  element config:config-item-map-entry {
+    config-config-item-map-entry-attlist, config-items
   }
-text-illustration-index-entry-content =
-  text-illustration-index-entry-template-attrs,
-  (text-index-entry-chapter
-   | text-index-entry-page-number
-   | text-index-entry-text
-   | text-index-entry-span
-   | text-index-entry-tab-stop)*
-text-illustration-index-entry-template-attrs =
-  attribute text:style-name { styleNameRef }
-text-table-index =
-  element text:table-index {
-    common-section-attlist, text-table-index-source, text-index-body
-  }
-text-table-index-source =
-  element text:table-index-source {
-    text-illustration-index-source-attrs,
-    text-index-title-template?,
-    text-table-index-entry-template?
+config-config-item-map-entry-attlist =
+  attribute config:name { \string }?
+config-config-item-map-indexed =
+  element config:config-item-map-indexed {
+    config-config-item-map-indexed-attlist,
+    config-config-item-map-entry+
   }
-text-table-index-entry-template =
-  element text:table-index-entry-template {
-    text-illustration-index-entry-content
+config-config-item-map-indexed-attlist =
+  attribute config:name { \string }
+config-config-item-map-named =
+  element config:config-item-map-named {
+    config-config-item-map-named-attlist, config-config-item-map-entry+
   }
-text-object-index =
-  element text:object-index {
-    common-section-attlist, text-object-index-source, text-index-body
+config-config-item-map-named-attlist = attribute config:name { \string }
+config-config-item-set =
+  element config:config-item-set {
+    config-config-item-set-attlist, config-items
   }
-text-object-index-source =
-  element text:object-index-source {
-    text-object-index-source-attrs,
-    text-index-title-template?,
-    text-object-index-entry-template?
+config-config-item-set-attlist = attribute config:name { \string }
+config-items =
+  (config-config-item
+   | config-config-item-set
+   | config-config-item-map-named
+   | config-config-item-map-indexed)+
+controls =
+  column-controls
+  | element form:password {
+      form-password-attlist, common-form-control-content
+    }
+  | element form:file { form-file-attlist, common-form-control-content }
+  | element form:fixed-text {
+      form-fixed-text-attlist, common-form-control-content
+    }
+  | element form:button {
+      form-button-attlist, common-form-control-content
+    }
+  | element form:image {
+      form-image-attlist, common-form-control-content
+    }
+  | element form:radio {
+      form-radio-attlist, common-form-control-content
+    }
+  | element form:frame {
+      form-frame-attlist, common-form-control-content
+    }
+  | element form:image-frame {
+      form-image-frame-attlist, common-form-control-content
+    }
+  | element form:hidden {
+      form-hidden-attlist, common-form-control-content
+    }
+  | element form:grid {
+      form-grid-attlist, common-form-control-content, form-column*
+    }
+  | element form:value-range {
+      form-value-range-attlist, common-form-control-content
+    }
+  | element form:generic-control {
+      form-generic-control-attlist, common-form-control-content
+    }
+coordinate = length
+countryCode = xsd:token { pattern = "[A-Za-z0-9]{1,8}" }
+currency-symbol-and-text =
+  number-currency-symbol,
+  number-text-with-fillchar
+  # https://issues.oasis-open.org/browse/OFFICE-3765
+  ?
+current-selected = attribute form:current-selected { boolean }?
+custom-shape-type = "non-primitive" | \string
+date = xsd:date
+dateOrDateTime = xsd:date | xsd:dateTime
+dateTime = xsd:dateTime
+db-application-connection-settings =
+  element db:application-connection-settings {
+    db-application-connection-settings-attlist,
+    db-table-filter?,
+    db-table-type-filter?,
+    db-data-source-settings?
   }
-text-object-index-source-attrs =
-  text-index-scope-attr
-  & text-relative-tab-stop-position-attr
-  & attribute text:use-spreadsheet-objects { boolean }?
-  & attribute text:use-math-objects { boolean }?
-  & attribute text:use-draw-objects { boolean }?
-  & attribute text:use-chart-objects { boolean }?
-  & attribute text:use-other-objects { boolean }?
-text-object-index-entry-template =
-  element text:object-index-entry-template {
-    text-illustration-index-entry-content
+db-application-connection-settings-attlist =
+  attribute db:is-table-name-length-limited { boolean }?
+  & attribute db:enable-sql92-check { boolean }?
+  & attribute db:append-table-alias-name { boolean }?
+  & attribute db:ignore-driver-privileges { boolean }?
+  & attribute db:boolean-comparison-mode {
+      "equal-integer"
+      | "is-boolean"
+      | "equal-boolean"
+      | "equal-use-only-zero"
+    }?
+  & attribute db:use-catalog { boolean }?
+  & attribute db:max-row-count { integer }?
+  & attribute db:suppress-version-columns { boolean }?
+db-apply-command = attribute db:apply-command { boolean }?
+db-auto-increment =
+  element db:auto-increment { db-auto-increment-attlist, empty }
+db-auto-increment-attlist =
+  attribute db:additional-column-statement { \string }?
+  & attribute db:row-retrieving-statement { \string }?
+db-character-set =
+  element db:character-set { db-character-set-attlist, empty }
+db-character-set-attlist = attribute db:encoding { textEncoding }?
+db-column =
+  element db:column {
+    db-column-attlist,
+    common-db-object-name,
+    common-db-object-title,
+    common-db-object-description,
+    common-db-default-value
   }
-text-user-index =
-  element text:user-index {
-    common-section-attlist, text-user-index-source, text-index-body
+db-column-attlist =
+  attribute db:visible { boolean }?
+  & attribute db:style-name { styleNameRef }?
+  & attribute db:default-cell-style-name { styleNameRef }?
+db-column-definition =
+  element db:column-definition {
+    db-column-definition-attlist, common-db-default-value
   }
-text-user-index-source =
-  element text:user-index-source {
-    text-user-index-source-attr,
-    text-index-title-template?,
-    text-user-index-entry-template*,
-    text-index-source-styles*
+db-column-definition-attlist =
+  attribute db:name { \string }
+  & attribute db:data-type { db-data-types }?
+  & attribute db:type-name { \string }?
+  & attribute db:precision { positiveInteger }?
+  & attribute db:scale { positiveInteger }?
+  & attribute db:is-nullable { "no-nulls" | "nullable" }?
+  & attribute db:is-empty-allowed { boolean }?
+  & attribute db:is-autoincrement { boolean }?
+db-column-definitions =
+  element db:column-definitions {
+    db-column-definitions-attlist, db-column-definition+
   }
-text-user-index-source-attr =
-  text-index-scope-attr
-  & text-relative-tab-stop-position-attr
-  & attribute text:use-index-marks { boolean }?
-  & attribute text:use-index-source-styles { boolean }?
-  & attribute text:use-graphics { boolean }?
-  & attribute text:use-tables { boolean }?
-  & attribute text:use-floating-frames { boolean }?
-  & attribute text:use-objects { boolean }?
-  & attribute text:copy-outline-levels { boolean }?
-  & attribute text:index-name { \string }
-text-user-index-entry-template =
-  element text:user-index-entry-template {
-    text-user-index-entry-template-attrs,
-    (text-index-entry-chapter
-     | text-index-entry-page-number
-     | text-index-entry-text
-     | text-index-entry-span
-     | text-index-entry-tab-stop)*
+db-column-definitions-attlist = empty
+db-columns = element db:columns { db-columns-attlist, db-column+ }
+db-columns-attlist = empty
+db-command = attribute db:command { \string }
+db-component =
+  element db:component {
+    db-component-attlist,
+    common-db-object-name,
+    common-db-object-title,
+    common-db-object-description,
+    (office-document | math-math)?
   }
-text-user-index-entry-template-attrs =
-  attribute text:outline-level { positiveInteger }
-  & attribute text:style-name { styleNameRef }
-text-alphabetical-index =
-  element text:alphabetical-index {
-    common-section-attlist,
-    text-alphabetical-index-source,
-    text-index-body
+db-component-attlist =
+  (attribute xlink:type { "simple" },
+   attribute xlink:href { anyIRI },
+   attribute xlink:show { "none" }?,
+   attribute xlink:actuate { "onRequest" }?)?
+  & attribute db:as-template { boolean }?
+db-component-collection =
+  element db:component-collection {
+    db-component-collection-attlist,
+    common-db-object-name,
+    common-db-object-title,
+    common-db-object-description,
+    (db-component | db-component-collection)*
   }
-text-alphabetical-index-source =
-  element text:alphabetical-index-source {
-    text-alphabetical-index-source-attrs,
-    text-index-title-template?,
-    text-alphabetical-index-entry-template*
+db-component-collection-attlist = empty
+db-connection-data =
+  element db:connection-data {
+    db-connection-data-attlist,
+    (db-database-description | db-connection-resource),
+    db-login?
   }
-text-alphabetical-index-source-attrs =
-  text-index-scope-attr
-  & text-relative-tab-stop-position-attr
-  & attribute text:ignore-case { boolean }?
-  & attribute text:main-entry-style-name { styleNameRef }?
-  & attribute text:alphabetical-separators { boolean }?
-  & attribute text:combine-entries { boolean }?
-  & attribute text:combine-entries-with-dash { boolean }?
-  & attribute text:combine-entries-with-pp { boolean }?
-  & attribute text:use-keys-as-entries { boolean }?
-  & attribute text:capitalize-entries { boolean }?
-  & attribute text:comma-separated { boolean }?
-  & attribute fo:language { languageCode }?
-  & attribute fo:country { countryCode }?
-  & attribute fo:script { scriptCode }?
-  & attribute style:rfc-language-tag { language }?
-  & attribute text:sort-algorithm { \string }?
-text-alphabetical-index-auto-mark-file =
-  element text:alphabetical-index-auto-mark-file {
-    attribute xlink:type { "simple" },
-    attribute xlink:href { anyIRI }
+db-connection-data-attlist = empty
+db-connection-resource =
+  element db:connection-resource {
+    db-connection-resource-attlist, empty
   }
-text-alphabetical-index-entry-template =
-  element text:alphabetical-index-entry-template {
-    text-alphabetical-index-entry-template-attrs,
-    (text-index-entry-chapter
-     | text-index-entry-page-number
-     | text-index-entry-text
-     | text-index-entry-span
-     | text-index-entry-tab-stop)*
+db-connection-resource-attlist =
+  attribute xlink:type { "simple" },
+  attribute xlink:href { anyIRI },
+  attribute xlink:show { "none" }?,
+  attribute xlink:actuate { "onRequest" }?
+db-data-source =
+  element db:data-source {
+    db-data-source-attlist,
+    db-connection-data,
+    db-driver-settings?,
+    db-application-connection-settings?
   }
-text-alphabetical-index-entry-template-attrs =
-  attribute text:outline-level { "1" | "2" | "3" | "separator" }
-  & attribute text:style-name { styleNameRef }
-text-bibliography =
-  element text:bibliography {
-    common-section-attlist, text-bibliography-source, text-index-body
+db-data-source-attlist = empty
+db-data-source-setting =
+  element db:data-source-setting {
+    db-data-source-setting-attlist, db-data-source-setting-value+
   }
-text-bibliography-source =
-  element text:bibliography-source {
-    text-index-title-template?, text-bibliography-entry-template*
+db-data-source-setting-attlist =
+  attribute db:data-source-setting-is-list { boolean }?
+  & attribute db:data-source-setting-name { \string }
+  & attribute db:data-source-setting-type {
+      db-data-source-setting-types
+    }
+db-data-source-setting-types =
+  "boolean" | "short" | "int" | "long" | "double" | "string"
+db-data-source-setting-value =
+  element db:data-source-setting-value {
+    db-data-source-setting-value-attlist, \string
   }
-text-bibliography-entry-template =
-  element text:bibliography-entry-template {
-    text-bibliography-entry-template-attrs,
-    (text-index-entry-span
-     | text-index-entry-tab-stop
-     | text-index-entry-bibliography)*
+db-data-source-setting-value-attlist = empty
+db-data-source-settings =
+  element db:data-source-settings {
+    db-data-source-settings-attlist, db-data-source-setting+
   }
-text-bibliography-entry-template-attrs =
-  attribute text:bibliography-type { text-bibliography-types }
-  & attribute text:style-name { styleNameRef }
-text-index-source-styles =
-  element text:index-source-styles {
-    attribute text:outline-level { positiveInteger },
-    text-index-source-style*
+db-data-source-settings-attlist = empty
+db-data-types =
+  "bit"
+  | "boolean"
+  | "tinyint"
+  | "smallint"
+  | "integer"
+  | "bigint"
+  | "float"
+  | "real"
+  | "double"
+  | "numeric"
+  | "decimal"
+  | "char"
+  | "varchar"
+  | "longvarchar"
+  | "date"
+  | "time"
+  | "timestmp"
+  | "binary"
+  | "varbinary"
+  | "longvarbinary"
+  | "sqlnull"
+  | "other"
+  | "object"
+  | "distinct"
+  | "struct"
+  | "array"
+  | "blob"
+  | "clob"
+  | "ref"
+db-database-description =
+  element db:database-description {
+    db-database-description-attlist,
+    (db-file-based-database | db-server-database)
   }
-text-index-source-style =
-  element text:index-source-style {
-    attribute text:style-name { styleName },
-    empty
+db-database-description-attlist = empty
+db-delimiter = element db:delimiter { db-delimiter-attlist, empty }
+db-delimiter-attlist =
+  attribute db:field { \string }?
+  & attribute db:string { \string }?
+  & attribute db:decimal { \string }?
+  & attribute db:thousand { \string }?
+db-driver-settings =
+  element db:driver-settings {
+    db-driver-settings-attlist,
+    db-auto-increment?,
+    db-delimiter?,
+    db-character-set?,
+    db-table-settings?
   }
-text-index-title-template =
-  element text:index-title-template {
-    attribute text:style-name { styleNameRef }?,
-    text
+db-driver-settings-attlist =
+  db-show-deleted
+  & attribute db:system-driver-settings { \string }?
+  & attribute db:base-dn { \string }?
+  & db-is-first-row-header-line
+  & attribute db:parameter-name-substitution { boolean }?
+db-file-based-database =
+  element db:file-based-database { db-file-based-database-attlist }
+db-file-based-database-attlist =
+  attribute xlink:type { "simple" }
+  & attribute xlink:href { anyIRI }
+  & attribute db:media-type { \string }
+  & attribute db:extension { \string }?
+db-filter-statement =
+  element db:filter-statement { db-command, db-apply-command, empty }
+db-forms =
+  element db:forms {
+    db-forms-attlist, (db-component | db-component-collection)*
   }
-text-index-entry-chapter =
-  element text:index-entry-chapter {
-    attribute text:style-name { styleNameRef }?,
-    text-index-entry-chapter-attrs
+db-forms-attlist = empty
+db-host-and-port =
+  attribute db:hostname { \string },
+  attribute db:port { positiveInteger }?
+db-index = element db:index { db-index-attlist, db-index-columns+ }
+db-index-attlist =
+  attribute db:name { \string }
+  & attribute db:catalog-name { \string }?
+  & attribute db:is-unique { boolean }?
+  & attribute db:is-clustered { boolean }?
+db-index-column =
+  element db:index-column { db-index-column-attlist, empty }
+db-index-column-attlist =
+  attribute db:name { \string }
+  & attribute db:is-ascending { boolean }?
+db-index-columns = element db:index-columns { db-index-column+ }
+db-indices = element db:indices { db-indices-attlist, db-index+ }
+db-indices-attlist = empty
+db-is-first-row-header-line =
+  attribute db:is-first-row-header-line { boolean }?
+db-key = element db:key { db-key-attlist, db-key-columns+ }
+db-key-attlist =
+  attribute db:name { \string }?
+  & attribute db:type { "primary" | "unique" | "foreign" }
+  & attribute db:referenced-table-name { \string }?
+  & attribute db:update-rule {
+      "cascade" | "restrict" | "set-null" | "no-action" | "set-default"
+    }?
+  & attribute db:delete-rule {
+      "cascade" | "restrict" | "set-null" | "no-action" | "set-default"
+    }?
+db-key-column = element db:key-column { db-key-column-attlist, empty }
+db-key-column-attlist =
+  attribute db:name { \string }?
+  & attribute db:related-column-name { \string }?
+db-key-columns =
+  element db:key-columns { db-key-columns-attlist, db-key-column+ }
+db-key-columns-attlist = empty
+db-keys = element db:keys { db-keys-attlist, db-key+ }
+db-keys-attlist = empty
+db-local-socket-name = attribute db:local-socket { \string }?
+db-login = element db:login { db-login-attlist, empty }
+db-login-attlist =
+  (attribute db:user-name { \string }
+   | attribute db:use-system-user { boolean })?
+  & attribute db:is-password-required { boolean }?
+  & attribute db:login-timeout { positiveInteger }?
+db-order-statement =
+  element db:order-statement { db-command, db-apply-command, empty }
+db-queries =
+  element db:queries {
+    db-queries-attlist, (db-query | db-query-collection)*
   }
-text-index-entry-chapter-attrs =
-  attribute text:display {
-    "name"
-    | "number"
-    | "number-and-name"
-    | "plain-number"
-    | "plain-number-and-name"
-  }?
-  & attribute text:outline-level { positiveInteger }?
-text-index-entry-text =
-  element text:index-entry-text {
-    attribute text:style-name { styleNameRef }?
+db-queries-attlist = empty
+db-query =
+  element db:query {
+    db-query-attlist,
+    common-db-object-name,
+    common-db-object-title,
+    common-db-object-description,
+    common-db-table-style-name,
+    db-order-statement?,
+    db-filter-statement?,
+    db-columns?,
+    db-update-table?
   }
-text-index-entry-page-number =
-  element text:index-entry-page-number {
-    attribute text:style-name { styleNameRef }?
+db-query-attlist =
+  attribute db:command { \string }
+  & attribute db:escape-processing { boolean }?
+db-query-collection =
+  element db:query-collection {
+    db-query-collection-attlist,
+    common-db-object-name,
+    common-db-object-title,
+    common-db-object-description,
+    (db-query | db-query-collection)*
   }
-text-index-entry-span =
-  element text:index-entry-span {
-    attribute text:style-name { styleNameRef }?,
-    text
+db-query-collection-attlist = empty
+db-reports =
+  element db:reports {
+    db-reports-attlist, (db-component | db-component-collection)*
   }
-text-index-entry-bibliography =
-  element text:index-entry-bibliography {
-    text-index-entry-bibliography-attrs
+db-reports-attlist = empty
+db-schema-definition =
+  element db:schema-definition {
+    db-schema-definition-attlist, db-table-definitions
   }
-text-index-entry-bibliography-attrs =
-  attribute text:style-name { styleNameRef }?
-  & attribute text:bibliography-data-field {
-      "address"
-      | "annote"
-      | "author"
-      | "bibliography-type"
-      | "booktitle"
-      | "chapter"
-      | "custom1"
-      | "custom2"
-      | "custom3"
-      | "custom4"
-      | "custom5"
-      | "edition"
-      | "editor"
-      | "howpublished"
-      | "identifier"
-      | "institution"
-      | "isbn"
-      | "issn"
-      | "journal"
-      | "month"
-      | "note"
-      | "number"
-      | "organizations"
-      | "pages"
-      | "publisher"
-      | "report-type"
-      | "school"
-      | "series"
-      | "title"
-      | "url"
-      | "volume"
-      | "year"
-    }
-text-index-entry-tab-stop =
-  element text:index-entry-tab-stop {
-    attribute text:style-name { styleNameRef }?,
-    text-index-entry-tab-stop-attrs
+db-schema-definition-attlist = empty
+db-server-database =
+  element db:server-database { db-server-database-attlist, empty }
+db-server-database-attlist =
+  attribute db:type { namespacedToken }
+  & (db-host-and-port | db-local-socket-name)
+  & attribute db:database-name { \string }?
+db-show-deleted = attribute db:show-deleted { boolean }?
+db-table-definition =
+  element db:table-definition {
+    common-db-table-name-attlist,
+    db-table-definition-attlist,
+    db-column-definitions,
+    db-keys?,
+    db-indices?
   }
-text-index-entry-tab-stop-attrs =
-  attribute style:leader-char { character }?
-  & (attribute style:type { "right" }
-     | (attribute style:type { "left" },
-        attribute style:position { length }))
-text-index-entry-link-start =
-  element text:index-entry-link-start {
-    attribute text:style-name { styleNameRef }?
+db-table-definition-attlist = attribute db:type { \string }?
+db-table-definitions =
+  element db:table-definitions {
+    db-table-definitions-attlist, db-table-definition*
   }
-text-index-entry-link-end =
-  element text:index-entry-link-end {
-    attribute text:style-name { styleNameRef }?
+db-table-definitions-attlist = empty
+db-table-exclude-filter =
+  element db:table-exclude-filter {
+    db-table-exclude-filter-attlist, db-table-filter-pattern+
   }
-table-table =
-  element table:table {
-    table-table-attlist,
-    table-title?,
-    table-desc?,
-    table-table-source?,
-    office-dde-source?,
-    table-scenario?,
-    office-forms?,
-    table-shapes?,
-    table-columns-and-groups,
-    table-rows-and-groups,
-    table-named-expressions?
+db-table-exclude-filter-attlist = empty
+db-table-filter =
+  element db:table-filter {
+    db-table-filter-attlist,
+    db-table-include-filter?,
+    db-table-exclude-filter?
   }
-table-columns-and-groups =
-  (table-table-column-group | table-columns-no-group)+
-table-columns-no-group =
-  (table-columns, (table-table-header-columns, table-columns?)?)
-  | (table-table-header-columns, table-columns?)
-table-columns = table-table-columns | table-table-column+
-table-rows-and-groups = (table-table-row-group | table-rows-no-group)+
-table-rows-no-group =
-  (table-rows, (table-table-header-rows, table-rows?)?)
-  | (table-table-header-rows, table-rows?)
-table-rows =
-  table-table-rows | (text-soft-page-break?, table-table-row)+
-table-table-attlist =
-  attribute table:name { \string }?
-  & attribute table:style-name { styleNameRef }?
-  & attribute table:template-name { \string }?
-  & attribute table:use-first-row-styles { boolean }?
-  & attribute table:use-last-row-styles { boolean }?
-  & attribute table:use-first-column-styles { boolean }?
-  & attribute table:use-last-column-styles { boolean }?
-  & attribute table:use-banding-rows-styles { boolean }?
-  & attribute table:use-banding-columns-styles { boolean }?
-  & attribute table:protected { boolean }?
-  & attribute table:protection-key { \string }?
-  & attribute table:protection-key-digest-algorithm { anyIRI }?
-  & attribute table:print { boolean }?
-  & attribute table:print-ranges { cellRangeAddressList }?
-  & xml-id?
-  & attribute table:is-sub-table { boolean }?
-table-title = element table:title { text }
-table-desc = element table:desc { text }
-table-table-row =
-  element table:table-row {
-    table-table-row-attlist,
-    (table-table-cell | table-covered-table-cell)+
+db-table-filter-attlist = empty
+db-table-filter-pattern =
+  element db:table-filter-pattern {
+    db-table-filter-pattern-attlist, \string
   }
-table-table-row-attlist =
-  attribute table:number-rows-repeated { positiveInteger }?
-  & attribute table:style-name { styleNameRef }?
-  & attribute table:default-cell-style-name { styleNameRef }?
-  & attribute table:visibility { table-visibility-value }?
-  & xml-id?
-table-visibility-value = "visible" | "collapse" | "filter"
-table-table-cell =
-  element table:table-cell {
-    table-table-cell-attlist,
-    table-table-cell-attlist-extra,
-    table-table-cell-content
+db-table-filter-pattern-attlist = empty
+db-table-include-filter =
+  element db:table-include-filter {
+    db-table-include-filter-attlist, db-table-filter-pattern+
   }
-table-covered-table-cell =
-  element table:covered-table-cell {
-    table-table-cell-attlist, table-table-cell-content
+db-table-include-filter-attlist = empty
+db-table-presentation =
+  element db:table-representation {
+    db-table-presentation-attlist,
+    common-db-table-name-attlist,
+    common-db-object-title,
+    common-db-object-description,
+    common-db-table-style-name,
+    db-order-statement?,
+    db-filter-statement?,
+    db-columns?
   }
-table-table-cell-content =
-  table-cell-range-source?,
-  office-annotation?,
-  table-detective?,
-  text-content*
-table-table-cell-attlist =
-  attribute table:number-columns-repeated { positiveInteger }?
-  & attribute table:style-name { styleNameRef }?
-  & attribute table:content-validation-name { \string }?
-  & attribute table:formula { \string }?
-  & common-value-and-type-attlist?
-  & attribute table:protect { boolean }?
-  & attribute table:protected { boolean }?
-  & xml-id?
-  & common-in-content-meta-attlist?
-table-table-cell-attlist-extra =
-  attribute table:number-columns-spanned { positiveInteger }?
-  & attribute table:number-rows-spanned { positiveInteger }?
-  & attribute table:number-matrix-columns-spanned { positiveInteger }?
-  & attribute table:number-matrix-rows-spanned { positiveInteger }?
-table-table-column =
-  element table:table-column { table-table-column-attlist, empty }
-table-table-column-attlist =
-  attribute table:number-columns-repeated { positiveInteger }?
-  & attribute table:style-name { styleNameRef }?
-  & attribute table:visibility { table-visibility-value }?
-  & attribute table:default-cell-style-name { styleNameRef }?
-  & xml-id?
-table-table-header-columns =
-  element table:table-header-columns { table-table-column+ }
-table-table-columns =
-  element table:table-columns { table-table-column+ }
-table-table-column-group =
-  element table:table-column-group {
-    table-table-column-group-attlist, table-columns-and-groups
+db-table-presentation-attlist = empty
+db-table-presentations =
+  element db:table-representations {
+    db-table-presentations-attlist, db-table-presentation*
   }
-table-table-column-group-attlist = attribute table:display { boolean }?
-table-table-header-rows =
-  element table:table-header-rows {
-    (text-soft-page-break?, table-table-row)+
+db-table-presentations-attlist = empty
+db-table-setting =
+  element db:table-setting {
+    db-table-setting-attlist, db-delimiter?, db-character-set?, empty
   }
-table-table-rows =
-  element table:table-rows { (text-soft-page-break?, table-table-row)+ }
-table-table-row-group =
-  element table:table-row-group {
-    table-table-row-group-attlist, table-rows-and-groups
+db-table-setting-attlist = db-is-first-row-header-line, db-show-deleted
+db-table-settings = element db:table-settings { db-table-setting* }
+db-table-type = element db:table-type { db-table-type-attlist, \string }
+db-table-type-attlist = empty
+db-table-type-filter =
+  element db:table-type-filter {
+    db-table-type-filter-attlist, db-table-type*
   }
-table-table-row-group-attlist = attribute table:display { boolean }?
-cellAddress =
-  xsd:string {
-    pattern = "($?([^\. ']+|'([^']|'')+'))?\.$?[A-Z]+$?[0-9]+"
+db-table-type-filter-attlist = empty
+db-update-table =
+  element db:update-table { common-db-table-name-attlist }
+dc-creator = element dc:creator { \string }
+dc-date = element dc:date { dateTime }
+distance = length
+double = xsd:double
+dr3d-cube =
+  element dr3d:cube {
+    dr3d-cube-attlist,
+    common-draw-z-index-attlist,
+    common-draw-id-attlist,
+    common-draw-layer-name-attlist,
+    common-draw-style-name-attlist,
+    common-dr3d-transform-attlist,
+    empty
   }
-cellRangeAddress =
-  xsd:string {
-    pattern =
-      "($?([^\. ']+|'([^']|'')+'))?\.$?[A-Z]+$?[0-9]+(:($?([^\. 
']+|'([^']|'')+'))?\.$?[A-Z]+$?[0-9]+)?"
+dr3d-cube-attlist =
+  attribute dr3d:min-edge { vector3D }?,
+  attribute dr3d:max-edge { vector3D }?
+dr3d-extrude =
+  element dr3d:extrude {
+    common-draw-path-data-attlist,
+    common-draw-viewbox-attlist,
+    common-draw-id-attlist,
+    common-draw-z-index-attlist,
+    common-draw-layer-name-attlist,
+    common-draw-style-name-attlist,
+    common-dr3d-transform-attlist,
+    empty
   }
-  | xsd:string {
-      pattern =
-        "($?([^\. ']+|'([^']|'')+'))?\.$?[0-9]+:($?([^\. 
']+|'([^']|'')+'))?\.$?[0-9]+"
-    }
-  | xsd:string {
-      pattern =
-        "($?([^\. ']+|'([^']|'')+'))?\.$?[A-Z]+:($?([^\. 
']+|'([^']|'')+'))?\.$?[A-Z]+"
-    }
-cellRangeAddressList =
-  xsd:string
-  >> dc:description [
-       'Value is a space separated list of "cellRangeAddress" patterns'
-     ]
-table-table-source =
-  element table:table-source {
-    table-table-source-attlist, table-linked-source-attlist, empty
-  }
-table-table-source-attlist =
-  attribute table:mode { "copy-all" | "copy-results-only" }?
-  & attribute table:table-name { \string }?
-table-linked-source-attlist =
-  attribute xlink:type { "simple" }
-  & attribute xlink:href { anyIRI }
-  & attribute xlink:actuate { "onRequest" }?
-  & attribute table:filter-name { \string }?
-  & attribute table:filter-options { \string }?
-  & attribute table:refresh-delay { duration }?
-table-scenario =
-  element table:scenario { table-scenario-attlist, empty }
-table-scenario-attlist =
-  attribute table:scenario-ranges { cellRangeAddressList }
-  & attribute table:is-active { boolean }
-  & attribute table:display-border { boolean }?
-  & attribute table:border-color { color }?
-  & attribute table:copy-back { boolean }?
-  & attribute table:copy-styles { boolean }?
-  & attribute table:copy-formulas { boolean }?
-  & attribute table:comment { \string }?
-  & attribute table:protected { boolean }?
-table-shapes = element table:shapes { shape+ }
-table-cell-range-source =
-  element table:cell-range-source {
-    table-table-cell-range-source-attlist,
-    table-linked-source-attlist,
-    empty
-  }
-table-table-cell-range-source-attlist =
-  attribute table:name { \string }
-  & attribute table:last-column-spanned { positiveInteger }
-  & attribute table:last-row-spanned { positiveInteger }
-table-detective =
-  element table:detective { table-highlighted-range*, table-operation* }
-table-operation =
-  element table:operation { table-operation-attlist, empty }
-table-operation-attlist =
-  attribute table:name {
-    "trace-dependents"
-    | "remove-dependents"
-    | "trace-precedents"
-    | "remove-precedents"
-    | "trace-errors"
-  }
-  & attribute table:index { nonNegativeInteger }
-table-highlighted-range =
-  element table:highlighted-range {
-    (table-highlighted-range-attlist
-     | table-highlighted-range-attlist-invalid),
+dr3d-light = element dr3d:light { dr3d-light-attlist, empty }
+dr3d-light-attlist =
+  attribute dr3d:diffuse-color { color }?
+  & attribute dr3d:direction { vector3D }
+  & attribute dr3d:enabled { boolean }?
+  & attribute dr3d:specular { boolean }?
+dr3d-rotate =
+  element dr3d:rotate {
+    common-draw-viewbox-attlist,
+    common-draw-path-data-attlist,
+    common-draw-z-index-attlist,
+    common-draw-id-attlist,
+    common-draw-layer-name-attlist,
+    common-draw-style-name-attlist,
+    common-dr3d-transform-attlist,
     empty
   }
-table-highlighted-range-attlist =
-  attribute table:cell-range-address { cellRangeAddress }?
-  & attribute table:direction {
-      "from-another-table" | "to-another-table" | "from-same-table"
-    }
-  & attribute table:contains-error { boolean }?
-table-highlighted-range-attlist-invalid =
-  attribute table:marked-invalid { boolean }
-office-spreadsheet-attlist =
-  attribute table:structure-protected { boolean }?,
-  attribute table:protection-key { \string }?,
-  attribute table:protection-key-digest-algorithm { anyIRI }?
-table-calculation-settings =
-  element table:calculation-settings {
-    table-calculation-setting-attlist,
-    table-null-date?,
-    table-iteration?
+dr3d-scene =
+  element dr3d:scene {
+    dr3d-scene-attlist,
+    common-draw-position-attlist,
+    common-draw-size-attlist,
+    common-draw-style-name-attlist,
+    common-draw-z-index-attlist,
+    common-draw-id-attlist,
+    common-draw-layer-name-attlist,
+    common-text-spreadsheet-shape-attlist,
+    common-dr3d-transform-attlist,
+    common-draw-caption-id-attlist,
+    svg-title?,
+    svg-desc?,
+    dr3d-light*,
+    shapes3d*,
+    draw-glue-point*
   }
-table-calculation-setting-attlist =
-  attribute table:case-sensitive { boolean }?
-  & attribute table:precision-as-shown { boolean }?
-  & attribute table:search-criteria-must-apply-to-whole-cell {
-      boolean
+dr3d-scene-attlist =
+  attribute dr3d:vrp { vector3D }?
+  & attribute dr3d:vpn { vector3D }?
+  & attribute dr3d:vup { vector3D }?
+  & attribute dr3d:projection { "parallel" | "perspective" }?
+  & attribute dr3d:distance { length }?
+  & attribute dr3d:focal-length { length }?
+  & attribute dr3d:shadow-slant { angle }?
+  & attribute dr3d:shade-mode {
+      "flat" | "phong" | "gouraud" | "draft"
     }?
-  & attribute table:automatic-find-labels { boolean }?
-  & attribute table:use-regular-expressions { boolean }?
-  & attribute table:use-wildcards { boolean }?
-  & attribute table:null-year { positiveInteger }?
-table-null-date =
-  element table:null-date {
-    attribute table:value-type { "date" }?,
-    attribute table:date-value { date }?,
-    empty
-  }
-table-iteration =
-  element table:iteration {
-    attribute table:status { "enable" | "disable" }?,
-    attribute table:steps { positiveInteger }?,
-    attribute table:maximum-difference { double }?,
+  & attribute dr3d:ambient-color { color }?
+  & attribute dr3d:lighting-mode { boolean }?
+dr3d-sphere =
+  element dr3d:sphere {
+    dr3d-sphere-attlist,
+    common-draw-z-index-attlist,
+    common-draw-id-attlist,
+    common-draw-layer-name-attlist,
+    common-draw-style-name-attlist,
+    common-dr3d-transform-attlist,
     empty
   }
-table-content-validations =
-  element table:content-validations { table-content-validation+ }
-table-content-validation =
-  element table:content-validation {
-    table-validation-attlist,
-    table-help-message?,
-    (table-error-message | (table-error-macro, office-event-listeners))?
+dr3d-sphere-attlist =
+  attribute dr3d:center { vector3D }?
+  & attribute dr3d:size { vector3D }?
+draw-a = element draw:a { draw-a-attlist, shape-instance }
+draw-a-attlist =
+  attribute xlink:type { "simple" }
+  & attribute xlink:href { anyIRI }
+  & attribute xlink:actuate { "onRequest" }?
+  & attribute office:target-frame-name { targetFrameName }?
+  & attribute xlink:show { "new" | "replace" }?
+  & attribute office:name { \string }?
+  & attribute office:title { \string }?
+  & attribute office:server-map { boolean }?
+  & xml-id?
+draw-applet =
+  element draw:applet {
+    draw-applet-attlist, common-draw-data-attlist?, draw-param*
   }
-table-validation-attlist =
-  attribute table:name { \string }
-  & attribute table:condition { \string }?
-  & attribute table:base-cell-address { cellAddress }?
-  & attribute table:allow-empty-cell { boolean }?
-  & attribute table:display-list {
-      "none" | "unsorted" | "sort-ascending"
-    }?
-table-help-message =
-  element table:help-message {
-    attribute table:title { \string }?,
-    attribute table:display { boolean }?,
-    text-p*
+draw-applet-attlist =
+  attribute draw:code { \string }?
+  & attribute draw:object { \string }?
+  & attribute draw:archive { \string }?
+  & attribute draw:may-script { boolean }?
+  & xml-id?
+draw-area-circle =
+  element draw:area-circle {
+    common-draw-area-attlist,
+    attribute svg:cx { coordinate },
+    attribute svg:cy { coordinate },
+    attribute svg:r { length },
+    svg-title?,
+    svg-desc?,
+    office-event-listeners?
   }
-table-error-message =
-  element table:error-message {
-    attribute table:title { \string }?,
-    attribute table:display { boolean }?,
-    attribute table:message-type {
-      "stop" | "warning" | "information"
-    }?,
-    text-p*
+draw-area-polygon =
+  element draw:area-polygon {
+    common-draw-area-attlist,
+    attribute svg:x { coordinate },
+    attribute svg:y { coordinate },
+    attribute svg:width { length },
+    attribute svg:height { length },
+    common-draw-viewbox-attlist,
+    common-draw-points-attlist,
+    svg-title?,
+    svg-desc?,
+    office-event-listeners?
   }
-table-error-macro =
-  element table:error-macro {
-    attribute table:execute { boolean }?
+draw-area-rectangle =
+  element draw:area-rectangle {
+    common-draw-area-attlist,
+    attribute svg:x { coordinate },
+    attribute svg:y { coordinate },
+    attribute svg:width { length },
+    attribute svg:height { length },
+    svg-title?,
+    svg-desc?,
+    office-event-listeners?
   }
-table-label-ranges = element table:label-ranges { table-label-range* }
-table-label-range =
-  element table:label-range { table-label-range-attlist, empty }
-table-label-range-attlist =
-  attribute table:label-cell-range-address { cellRangeAddress }
-  & attribute table:data-cell-range-address { cellRangeAddress }
-  & attribute table:orientation { "column" | "row" }
-table-named-expressions =
-  element table:named-expressions {
-    (table-named-range | table-named-expression)*
+draw-caption =
+  element draw:caption {
+    draw-caption-attlist,
+    common-draw-position-attlist,
+    common-draw-size-attlist,
+    common-draw-shape-with-text-and-styles-attlist,
+    common-draw-caption-id-attlist,
+    svg-title?,
+    svg-desc?,
+    office-event-listeners?,
+    draw-glue-point*,
+    draw-text
   }
-table-named-range =
-  element table:named-range { table-named-range-attlist, empty }
-table-named-range-attlist =
-  attribute table:name { \string },
-  attribute table:cell-range-address { cellRangeAddress },
-  attribute table:base-cell-address { cellAddress }?,
-  attribute table:range-usable-as {
-    "none"
-    | list {
-        ("print-range" | "filter" | "repeat-row" | "repeat-column")+
-      }
-  }?
-table-named-expression =
-  element table:named-expression {
-    table-named-expression-attlist, empty
-  }
-table-named-expression-attlist =
-  attribute table:name { \string },
-  attribute table:expression { \string },
-  attribute table:base-cell-address { cellAddress }?
-table-database-ranges =
-  element table:database-ranges { table-database-range* }
-table-database-range =
-  element table:database-range {
-    table-database-range-attlist,
-    (table-database-source-sql
-     | table-database-source-table
-     | table-database-source-query)?,
-    table-filter?,
-    table-sort?,
-    table-subtotal-rules?
-  }
-table-database-range-attlist =
-  attribute table:name { \string }?
-  & attribute table:is-selection { boolean }?
-  & attribute table:on-update-keep-styles { boolean }?
-  & attribute table:on-update-keep-size { boolean }?
-  & attribute table:has-persistent-data { boolean }?
-  & attribute table:orientation { "column" | "row" }?
-  & attribute table:contains-header { boolean }?
-  & attribute table:display-filter-buttons { boolean }?
-  & attribute table:target-range-address { cellRangeAddress }
-  & attribute table:refresh-delay { boolean }?
-table-database-source-sql =
-  element table:database-source-sql {
-    table-database-source-sql-attlist, empty
-  }
-table-database-source-sql-attlist =
-  attribute table:database-name { \string }
-  & attribute table:sql-statement { \string }
-  & attribute table:parse-sql-statement { boolean }?
-table-database-source-query =
-  element table:database-source-table {
-    table-database-source-table-attlist, empty
+draw-caption-attlist =
+  (attribute draw:caption-point-x { coordinate },
+   attribute draw:caption-point-y { coordinate })?
+  & attribute draw:corner-radius { nonNegativeLength }?
+draw-circle =
+  element draw:circle {
+    ((draw-circle-attlist, common-draw-circle-ellipse-pos-attlist)
+     | (common-draw-position-attlist, common-draw-size-attlist)),
+    common-draw-circle-ellipse-attlist,
+    common-draw-shape-with-text-and-styles-attlist,
+    common-draw-caption-id-attlist,
+    svg-title?,
+    svg-desc?,
+    office-event-listeners?,
+    draw-glue-point*,
+    draw-text
   }
-table-database-source-table-attlist =
-  attribute table:database-name { \string }
-  & attribute table:database-table-name { \string }
-table-database-source-table =
-  element table:database-source-query {
-    table-database-source-query-attlist, empty
+draw-circle-attlist = attribute svg:r { length }
+draw-connector =
+  element draw:connector {
+    draw-connector-attlist,
+    common-draw-shape-with-text-and-styles-attlist,
+    common-draw-caption-id-attlist,
+    common-draw-viewbox-attlist,
+    svg-title?,
+    svg-desc?,
+    office-event-listeners?,
+    draw-glue-point*,
+    draw-text
   }
-table-database-source-query-attlist =
-  attribute table:database-name { \string }
-  & attribute table:query-name { \string }
-table-sort = element table:sort { table-sort-attlist, table-sort-by+ }
-table-sort-attlist =
-  attribute table:bind-styles-to-content { boolean }?
-  & attribute table:target-range-address { cellRangeAddress }?
-  & attribute table:case-sensitive { boolean }?
-  & attribute table:language { languageCode }?
-  & attribute table:country { countryCode }?
-  & attribute table:script { scriptCode }?
-  & attribute table:rfc-language-tag { language }?
-  & attribute table:algorithm { \string }?
-  & attribute table:embedded-number-behavior {
-      "alpha-numeric" | "integer" | "double"
-    }?
-table-sort-by = element table:sort-by { table-sort-by-attlist, empty }
-table-sort-by-attlist =
-  attribute table:field-number { nonNegativeInteger }
-  & attribute table:data-type {
-      "text" | "number" | "automatic" | \string
+draw-connector-attlist =
+  attribute draw:type { "standard" | "lines" | "line" | "curve" }?
+  & (attribute svg:x1 { coordinate },
+     attribute svg:y1 { coordinate })?
+  & attribute draw:start-shape { IDREF }?
+  & attribute draw:start-glue-point { nonNegativeInteger }?
+  & (attribute svg:x2 { coordinate },
+     attribute svg:y2 { coordinate })?
+  & attribute draw:end-shape { IDREF }?
+  & attribute draw:end-glue-point { nonNegativeInteger }?
+  & attribute draw:line-skew {
+      list { length, (length, length?)? }
     }?
-  & attribute table:order { "ascending" | "descending" }?
-table-subtotal-rules =
-  element table:subtotal-rules {
-    table-subtotal-rules-attlist,
-    table-sort-groups?,
-    table-subtotal-rule*
-  }
-table-subtotal-rules-attlist =
-  attribute table:bind-styles-to-content { boolean }?
-  & attribute table:case-sensitive { boolean }?
-  & attribute table:page-breaks-on-group-change { boolean }?
-table-sort-groups =
-  element table:sort-groups { table-sort-groups-attlist, empty }
-table-sort-groups-attlist =
-  attribute table:data-type {
-    "text" | "number" | "automatic" | \string
-  }?
-  & attribute table:order { "ascending" | "descending" }?
-table-subtotal-rule =
-  element table:subtotal-rule {
-    table-subtotal-rule-attlist, table-subtotal-field*
-  }
-table-subtotal-rule-attlist =
-  attribute table:group-by-field-number { nonNegativeInteger }
-table-subtotal-field =
-  element table:subtotal-field { table-subtotal-field-attlist, empty }
-table-subtotal-field-attlist =
-  attribute table:field-number { nonNegativeInteger }
-  & attribute table:function {
-      "average"
-      | "count"
-      | "countnums"
-      | "max"
-      | "min"
-      | "product"
-      | "stdev"
-      | "stdevp"
-      | "sum"
-      | "var"
-      | "varp"
-      | \string
-    }
-table-filter =
-  element table:filter {
-    table-filter-attlist,
-    (table-filter-condition | table-filter-and | table-filter-or)
+  & attribute svg:d { pathData }?
+draw-contour-path =
+  element draw:contour-path {
+    common-contour-attlist,
+    common-draw-size-attlist,
+    common-draw-viewbox-attlist,
+    common-draw-path-data-attlist,
+    empty
   }
-table-filter-attlist =
-  attribute table:target-range-address { cellRangeAddress }?
-  & attribute table:condition-source { "self" | "cell-range" }?
-  & attribute table:condition-source-range-address { cellRangeAddress }?
-  & attribute table:display-duplicates { boolean }?
-table-filter-and =
-  element table:filter-and {
-    (table-filter-or | table-filter-condition)+
+draw-contour-polygon =
+  element draw:contour-polygon {
+    common-contour-attlist,
+    common-draw-size-attlist,
+    common-draw-viewbox-attlist,
+    common-draw-points-attlist,
+    empty
   }
-table-filter-or =
-  element table:filter-or {
-    (table-filter-and | table-filter-condition)+
+draw-control =
+  element draw:control {
+    draw-control-attlist,
+    common-draw-position-attlist,
+    common-draw-size-attlist,
+    common-draw-shape-with-text-and-styles-attlist,
+    common-draw-caption-id-attlist,
+    svg-title?,
+    svg-desc?,
+    draw-glue-point*
   }
-table-filter-condition =
-  element table:filter-condition {
-    table-filter-condition-attlist, table-filter-set-item*
+draw-control-attlist = attribute draw:control { IDREF }
+draw-custom-shape =
+  element draw:custom-shape {
+    draw-custom-shape-attlist,
+    common-draw-position-attlist,
+    common-draw-size-attlist,
+    common-draw-shape-with-text-and-styles-attlist,
+    common-draw-caption-id-attlist,
+    svg-title?,
+    svg-desc?,
+    office-event-listeners?,
+    draw-glue-point*,
+    draw-text,
+    draw-enhanced-geometry?
   }
-table-filter-condition-attlist =
-  attribute table:field-number { nonNegativeInteger }
-  & attribute table:value { \string | double }
-  & attribute table:operator { \string }
-  & attribute table:case-sensitive { \string }?
-  & attribute table:data-type { "text" | "number" }?
-table-filter-set-item =
-  element table:filter-set-item {
-    attribute table:value { \string },
-    empty
+draw-custom-shape-attlist =
+  attribute draw:engine { namespacedToken }?
+  & attribute draw:data { \string }?
+draw-ellipse =
+  element draw:ellipse {
+    ((draw-ellipse-attlist, common-draw-circle-ellipse-pos-attlist)
+     | (common-draw-position-attlist, common-draw-size-attlist)),
+    common-draw-circle-ellipse-attlist,
+    common-draw-shape-with-text-and-styles-attlist,
+    common-draw-caption-id-attlist,
+    svg-title?,
+    svg-desc?,
+    office-event-listeners?,
+    draw-glue-point*,
+    draw-text
   }
-table-data-pilot-tables =
-  element table:data-pilot-tables { table-data-pilot-table* }
-table-data-pilot-table =
-  element table:data-pilot-table {
-    table-data-pilot-table-attlist,
-    (table-database-source-sql
-     | table-database-source-table
-     | table-database-source-query
-     | table-source-service
-     | table-source-cell-range)?,
-    table-data-pilot-field+
+draw-ellipse-attlist =
+  attribute svg:rx { length },
+  attribute svg:ry { length }
+draw-enhanced-geometry =
+  element draw:enhanced-geometry {
+    draw-enhanced-geometry-attlist, draw-equation*, draw-handle*
   }
-table-data-pilot-table-attlist =
-  attribute table:name { \string }
-  & attribute table:application-data { \string }?
-  & attribute table:grand-total { "none" | "row" | "column" | "both" }?
-  & attribute table:ignore-empty-rows { boolean }?
-  & attribute table:identify-categories { boolean }?
-  & attribute table:target-range-address { cellRangeAddress }
-  & attribute table:buttons { cellRangeAddressList }?
-  & attribute table:show-filter-button { boolean }?
-  & attribute table:drill-down-on-double-click { boolean }?
-table-source-cell-range =
-  element table:source-cell-range {
-    table-source-cell-range-attlist, table-filter?
-  }
-table-source-cell-range-attlist =
-  attribute table:cell-range-address { cellRangeAddress }
-table-source-service =
-  element table:source-service { table-source-service-attlist, empty }
-table-source-service-attlist =
-  attribute table:name { \string }
-  & attribute table:source-name { \string }
-  & attribute table:object-name { \string }
-  & attribute table:user-name { \string }?
-  & attribute table:password { \string }?
-table-data-pilot-field =
-  element table:data-pilot-field {
-    table-data-pilot-field-attlist,
-    table-data-pilot-level?,
-    table-data-pilot-field-reference?,
-    table-data-pilot-groups?
-  }
-table-data-pilot-field-attlist =
-  attribute table:source-field-name { \string }
-  & (attribute table:orientation {
-       "row" | "column" | "data" | "hidden"
-     }
-     | (attribute table:orientation { "page" },
-        attribute table:selected-page { \string }))
-  & attribute table:is-data-layout-field { \string }?
-  & attribute table:function {
-      "auto"
-      | "average"
-      | "count"
-      | "countnums"
-      | "max"
-      | "min"
-      | "product"
-      | "stdev"
-      | "stdevp"
-      | "sum"
-      | "var"
-      | "varp"
-      | \string
+draw-enhanced-geometry-attlist =
+  attribute draw:type { custom-shape-type }?
+  & attribute svg:viewBox {
+      list { integer, integer, integer, integer }
     }?
-  & attribute table:used-hierarchy { integer }?
-table-data-pilot-level =
-  element table:data-pilot-level {
-    table-data-pilot-level-attlist,
-    table-data-pilot-subtotals?,
-    table-data-pilot-members?,
-    table-data-pilot-display-info?,
-    table-data-pilot-sort-info?,
-    table-data-pilot-layout-info?
-  }
-table-data-pilot-level-attlist = attribute table:show-empty { boolean }?
-table-data-pilot-subtotals =
-  element table:data-pilot-subtotals { table-data-pilot-subtotal* }
-table-data-pilot-subtotal =
-  element table:data-pilot-subtotal {
-    table-data-pilot-subtotal-attlist, empty
-  }
-table-data-pilot-subtotal-attlist =
-  attribute table:function {
-    "auto"
-    | "average"
-    | "count"
-    | "countnums"
-    | "max"
-    | "min"
-    | "product"
-    | "stdev"
-    | "stdevp"
-    | "sum"
-    | "var"
-    | "varp"
-    | \string
+  & attribute draw:mirror-vertical { boolean }?
+  & attribute draw:mirror-horizontal { boolean }?
+  & attribute draw:text-rotate-angle { angle }?
+  & attribute draw:extrusion-allowed { boolean }?
+  & attribute draw:text-path-allowed { boolean }?
+  & attribute draw:concentric-gradient-fill-allowed { boolean }?
+  & attribute draw:extrusion { boolean }?
+  & attribute draw:extrusion-brightness { zeroToHundredPercent }?
+  & attribute draw:extrusion-depth {
+      list { length, double }
+    }?
+  & attribute draw:extrusion-diffusion { percent }?
+  & attribute draw:extrusion-number-of-line-segments { integer }?
+  & attribute draw:extrusion-light-face { boolean }?
+  & attribute draw:extrusion-first-light-harsh { boolean }?
+  & attribute draw:extrusion-second-light-harsh { boolean }?
+  & attribute draw:extrusion-first-light-level { zeroToHundredPercent }?
+  & attribute draw:extrusion-second-light-level {
+      zeroToHundredPercent
+    }?
+  & attribute draw:extrusion-first-light-direction { vector3D }?
+  & attribute draw:extrusion-second-light-direction { vector3D }?
+  & attribute draw:extrusion-metal { boolean }?
+  & attribute dr3d:shade-mode {
+      "flat" | "phong" | "gouraud" | "draft"
+    }?
+  & attribute draw:extrusion-rotation-angle {
+      list { angle, angle }
+    }?
+  & attribute draw:extrusion-rotation-center { vector3D }?
+  & attribute draw:extrusion-shininess { zeroToHundredPercent }?
+  & attribute draw:extrusion-skew {
+      list { double, angle }
+    }?
+  & attribute draw:extrusion-specularity { zeroToHundredPercent }?
+  & attribute dr3d:projection { "parallel" | "perspective" }?
+  & attribute draw:extrusion-viewpoint { point3D }?
+  & attribute draw:extrusion-origin {
+      list { extrusionOrigin, extrusionOrigin }
+    }?
+  & attribute draw:extrusion-color { boolean }?
+  & attribute draw:enhanced-path { \string }?
+  & attribute draw:path-stretchpoint-x { double }?
+  & attribute draw:path-stretchpoint-y { double }?
+  & attribute draw:text-areas { \string }?
+  & attribute draw:glue-points { \string }?
+  & attribute draw:glue-point-type {
+      "none" | "segments" | "rectangle"
+    }?
+  & attribute draw:glue-point-leaving-directions { \string }?
+  & attribute draw:text-path { boolean }?
+  & attribute draw:text-path-mode { "normal" | "path" | "shape" }?
+  & attribute draw:text-path-scale { "path" | "shape" }?
+  & attribute draw:text-path-same-letter-heights { boolean }?
+  & attribute draw:modifiers { \string }?
+draw-equation = element draw:equation { draw-equation-attlist, empty }
+draw-equation-attlist =
+  attribute draw:name { \string }?
+  & attribute draw:formula { \string }?
+draw-fill-image =
+  element draw:fill-image {
+    draw-fill-image-attlist,
+    # XLink duplicate declaration removed. see common-draw-data-attlist
+    ((common-draw-data-attlist, empty) | office-binary-data)
+    # https://issues.oasis-open.org/browse/OFFICE-3933
+
   }
-table-data-pilot-members =
-  element table:data-pilot-members { table-data-pilot-member* }
-table-data-pilot-member =
-  element table:data-pilot-member {
-    table-data-pilot-member-attlist, empty
+draw-fill-image-attlist =
+  attribute draw:name { styleName }
+  & attribute draw:display-name { \string }?
+  & attribute svg:width { length }?
+  & attribute svg:height { length }?
+draw-floating-frame =
+  element draw:floating-frame {
+    draw-floating-frame-attlist, common-draw-data-attlist
   }
-table-data-pilot-member-attlist =
-  attribute table:name { \string }
-  & attribute table:display { boolean }?
-  & attribute table:show-details { boolean }?
-table-data-pilot-display-info =
-  element table:data-pilot-display-info {
-    table-data-pilot-display-info-attlist, empty
+draw-floating-frame-attlist =
+  attribute draw:frame-name { \string }?
+  & xml-id?
+draw-frame =
+  element draw:frame {
+    common-draw-shape-with-text-and-styles-attlist,
+    common-draw-position-attlist,
+    common-draw-rel-size-attlist,
+    common-draw-caption-id-attlist,
+    presentation-shape-attlist,
+    draw-frame-attlist,
+    (draw-text-box
+     | draw-image
+     | draw-object
+     | draw-object-ole
+     | draw-applet
+     | draw-floating-frame
+     | draw-plugin
+     | table-table)*,
+    office-event-listeners?,
+    draw-glue-point*,
+    draw-image-map?,
+    svg-title?,
+    svg-desc?,
+    (draw-contour-polygon | draw-contour-path)?
   }
-table-data-pilot-display-info-attlist =
-  attribute table:enabled { boolean }
-  & attribute table:data-field { \string }
-  & attribute table:member-count { nonNegativeInteger }
-  & attribute table:display-member-mode { "from-top" | "from-bottom" }
-table-data-pilot-sort-info =
-  element table:data-pilot-sort-info {
-    table-data-pilot-sort-info-attlist, empty
+draw-frame-attlist = attribute draw:copy-of { \string }?
+draw-g =
+  element draw:g {
+    draw-g-attlist,
+    common-draw-z-index-attlist,
+    common-draw-name-attlist,
+    common-draw-id-attlist,
+    common-draw-style-name-attlist,
+    common-text-spreadsheet-shape-attlist,
+    common-draw-caption-id-attlist,
+    svg-title?,
+    svg-desc?,
+    office-event-listeners?,
+    draw-glue-point*,
+    shape*
   }
-table-data-pilot-sort-info-attlist =
-  ((attribute table:sort-mode { "data" },
-    attribute table:data-field { \string })
-   | attribute table:sort-mode { "none" | "manual" | "name" })
-  & attribute table:order { "ascending" | "descending" }
-table-data-pilot-layout-info =
-  element table:data-pilot-layout-info {
-    table-data-pilot-layout-info-attlist, empty
+draw-g-attlist = attribute svg:y { coordinate }?
+draw-glue-point =
+  element draw:glue-point { draw-glue-point-attlist, empty }
+draw-glue-point-attlist =
+  attribute draw:id { nonNegativeInteger }
+  & attribute svg:x { distance | percent }
+  & attribute svg:y { distance | percent }
+  & attribute draw:align {
+      "top-left"
+      | "top"
+      | "top-right"
+      | "left"
+      | "center"
+      | "right"
+      | "bottom-left"
+      | "bottom-right"
+    }?
+  & attribute draw:escape-direction {
+      "auto"
+      | "left"
+      | "right"
+      | "up"
+      | "down"
+      | "horizontal"
+      | "vertical"
+    }
+draw-gradient =
+  element draw:gradient {
+    common-draw-gradient-attlist, draw-gradient-attlist, empty
   }
-table-data-pilot-layout-info-attlist =
-  attribute table:layout-mode {
-    "tabular-layout"
-    | "outline-subtotals-top"
-    | "outline-subtotals-bottom"
-  }
-  & attribute table:add-empty-lines { boolean }
-table-data-pilot-field-reference =
-  element table:data-pilot-field-reference {
-    table-data-pilot-field-reference-attlist
-  }
-table-data-pilot-field-reference-attlist =
-  attribute table:field-name { \string }
-  & ((attribute table:member-type { "named" },
-      attribute table:member-name { \string })
-     | attribute table:member-type { "previous" | "next" })
-  & attribute table:type {
-      "none"
-      | "member-difference"
-      | "member-percentage"
-      | "member-percentage-difference"
-      | "running-total"
-      | "row-percentage"
-      | "column-percentage"
-      | "total-percentage"
-      | "index"
-    }
-table-data-pilot-groups =
-  element table:data-pilot-groups {
-    table-data-pilot-groups-attlist, table-data-pilot-group+
-  }
-table-data-pilot-groups-attlist =
-  attribute table:source-field-name { \string }
-  & (attribute table:date-start { dateOrDateTime | "auto" }
-     | attribute table:start { double | "auto" })
-  & (attribute table:date-end { dateOrDateTime | "auto" }
-     | attribute table:end { double | "auto" })
-  & attribute table:step { double }
-  & attribute table:grouped-by {
-      "seconds"
-      | "minutes"
-      | "hours"
-      | "days"
-      | "months"
-      | "quarters"
-      | "years"
-    }
-table-data-pilot-group =
-  element table:data-pilot-group {
-    table-data-pilot-group-attlist, table-data-pilot-group-member+
-  }
-table-data-pilot-group-attlist = attribute table:name { \string }
-table-data-pilot-group-member =
-  element table:data-pilot-group-member {
-    table-data-pilot-group-member-attlist
-  }
-table-data-pilot-group-member-attlist = attribute table:name { \string }
-table-consolidation =
-  element table:consolidation { table-consolidation-attlist, empty }
-table-consolidation-attlist =
-  attribute table:function {
-    "average"
-    | "count"
-    | "countnums"
-    | "max"
-    | "min"
-    | "product"
-    | "stdev"
-    | "stdevp"
-    | "sum"
-    | "var"
-    | "varp"
-    | \string
+draw-gradient-attlist =
+  attribute draw:start-color { color }?
+  & attribute draw:end-color { color }?
+  & attribute draw:start-intensity { zeroToHundredPercent }?
+  & attribute draw:end-intensity { zeroToHundredPercent }?
+draw-handle = element draw:handle { draw-handle-attlist, empty }
+draw-handle-attlist =
+  attribute draw:handle-mirror-vertical { boolean }?
+  & attribute draw:handle-mirror-horizontal { boolean }?
+  & attribute draw:handle-switched { boolean }?
+  & attribute draw:handle-position { \string }
+  & attribute draw:handle-range-x-minimum { \string }?
+  & attribute draw:handle-range-x-maximum { \string }?
+  & attribute draw:handle-range-y-minimum { \string }?
+  & attribute draw:handle-range-y-maximum { \string }?
+  & attribute draw:handle-polar { \string }?
+  & attribute draw:handle-radius-range-minimum { \string }?
+  & attribute draw:handle-radius-range-maximum { \string }?
+draw-hatch = element draw:hatch { draw-hatch-attlist, empty }
+draw-hatch-attlist =
+  attribute draw:name { styleName }
+  & attribute draw:display-name { \string }?
+  & attribute draw:style { "single" | "double" | "triple" }
+  & attribute draw:color { color }?
+  & attribute draw:distance { length }?
+  & attribute draw:rotation { angle }?
+draw-image =
+  element draw:image {
+    draw-image-attlist,
+    (common-draw-data-attlist | office-binary-data),
+    draw-text
   }
-  & attribute table:source-cell-range-addresses { cellRangeAddressList }
-  & attribute table:target-cell-address { cellAddress }
-  & attribute table:use-labels { "none" | "row" | "column" | "both" }?
-  & attribute table:link-to-source-data { boolean }?
-table-dde-links = element table:dde-links { table-dde-link+ }
-table-tracked-changes =
-  element table:tracked-changes {
-    table-tracked-changes-attlist,
-    (table-cell-content-change
-     | table-insertion
-     | table-deletion
-     | table-movement)*
+draw-image-attlist =
+  attribute draw:filter-name { \string }?
+  & common-draw-mime-type-attlist
+  & # https://issues.oasis-open.org/browse/OFFICE-3943
+    xml-id?
+draw-image-map =
+  element draw:image-map {
+    (draw-area-rectangle | draw-area-circle | draw-area-polygon)*
   }
-table-tracked-changes-attlist =
-  attribute table:track-changes { boolean }?
-table-insertion =
-  element table:insertion {
-    table-insertion-attlist,
-    common-table-change-attlist,
-    office-change-info,
-    table-dependencies?,
-    table-deletions?
+draw-layer =
+  element draw:layer { draw-layer-attlist, svg-title?, svg-desc? }
+draw-layer-attlist =
+  attribute draw:name { \string }
+  & attribute draw:protected { boolean }?
+  & attribute draw:display { "always" | "screen" | "printer" | "none" }?
+draw-layer-set = element draw:layer-set { draw-layer* }
+draw-line =
+  element draw:line {
+    draw-line-attlist,
+    common-draw-shape-with-text-and-styles-attlist,
+    common-draw-caption-id-attlist,
+    svg-title?,
+    svg-desc?,
+    office-event-listeners?,
+    draw-glue-point*,
+    draw-text
   }
-table-insertion-attlist =
-  attribute table:type { "row" | "column" | "table" }
-  & attribute table:position { integer }
-  & attribute table:count { positiveInteger }?
-  & attribute table:table { integer }?
-table-dependencies = element table:dependencies { table-dependency+ }
-table-dependency =
-  element table:dependency {
-    attribute table:id { \string },
+draw-line-attlist =
+  attribute svg:x1 { coordinate }
+  & attribute svg:y1 { coordinate }
+  & attribute svg:x2 { coordinate }
+  & attribute svg:y2 { coordinate }
+draw-marker =
+  element draw:marker {
+    draw-marker-attlist,
+    common-draw-viewbox-attlist,
+    common-draw-path-data-attlist,
     empty
   }
-table-deletions =
-  element table:deletions {
-    (table-cell-content-deletion | table-change-deletion)+
-  }
-table-cell-content-deletion =
-  element table:cell-content-deletion {
-    attribute table:id { \string }?,
-    table-cell-address?,
-    table-change-track-table-cell?
-  }
-table-change-deletion =
-  element table:change-deletion {
-    attribute table:id { \string }?,
-    empty
+draw-marker-attlist =
+  attribute draw:name { styleName }
+  & attribute draw:display-name { \string }?
+draw-measure =
+  element draw:measure {
+    draw-measure-attlist,
+    common-draw-shape-with-text-and-styles-attlist,
+    common-draw-caption-id-attlist,
+    svg-title?,
+    svg-desc?,
+    office-event-listeners?,
+    draw-glue-point*,
+    draw-text
   }
-table-deletion =
-  element table:deletion {
-    table-deletion-attlist,
-    common-table-change-attlist,
-    office-change-info,
-    table-dependencies?,
-    table-deletions?,
-    table-cut-offs?
+draw-measure-attlist =
+  attribute svg:x1 { coordinate }
+  & attribute svg:y1 { coordinate }
+  & attribute svg:x2 { coordinate }
+  & attribute svg:y2 { coordinate }
+draw-object =
+  element draw:object {
+    draw-object-attlist,
+    (common-draw-data-attlist | office-document | math-math)
   }
-table-deletion-attlist =
-  attribute table:type { "row" | "column" | "table" }
-  & attribute table:position { integer }
-  & attribute table:table { integer }?
-  & attribute table:multi-deletion-spanned { integer }?
-table-cut-offs =
-  element table:cut-offs {
-    table-movement-cut-off+
-    | (table-insertion-cut-off, table-movement-cut-off*)
+draw-object-attlist =
+  attribute draw:notify-on-update-of-ranges {
+    cellRangeAddressList | \string
+  }?
+  & xml-id?
+draw-object-ole =
+  element draw:object-ole {
+    draw-object-ole-attlist,
+    (common-draw-data-attlist | office-binary-data)
   }
-table-insertion-cut-off =
-  element table:insertion-cut-off {
-    table-insertion-cut-off-attlist, empty
+draw-object-ole-attlist =
+  attribute draw:class-id { \string }?
+  & xml-id?
+draw-opacity =
+  element draw:opacity {
+    common-draw-gradient-attlist, draw-opacity-attlist, empty
   }
-table-insertion-cut-off-attlist =
-  attribute table:id { \string }
-  & attribute table:position { integer }
-table-movement-cut-off =
-  element table:movement-cut-off {
-    table-movement-cut-off-attlist, empty
-  }
-table-movement-cut-off-attlist =
-  attribute table:position { integer }
-  | (attribute table:start-position { integer },
-     attribute table:end-position { integer })
-table-movement =
-  element table:movement {
-    common-table-change-attlist,
-    table-source-range-address,
-    table-target-range-address,
-    office-change-info,
-    table-dependencies?,
-    table-deletions?
-  }
-table-source-range-address =
-  element table:source-range-address {
-    common-table-range-attlist, empty
-  }
-table-target-range-address =
-  element table:target-range-address {
-    common-table-range-attlist, empty
-  }
-common-table-range-attlist =
-  common-table-cell-address-attlist
-  | common-table-cell-range-address-attlist
-common-table-cell-address-attlist =
-  attribute table:column { integer },
-  attribute table:row { integer },
-  attribute table:table { integer }
-common-table-cell-range-address-attlist =
-  attribute table:start-column { integer },
-  attribute table:start-row { integer },
-  attribute table:start-table { integer },
-  attribute table:end-column { integer },
-  attribute table:end-row { integer },
-  attribute table:end-table { integer }
-table-change-track-table-cell =
-  element table:change-track-table-cell {
-    table-change-track-table-cell-attlist, text-p*
-  }
-table-change-track-table-cell-attlist =
-  attribute table:cell-address { cellAddress }?
-  & attribute table:matrix-covered { boolean }?
-  & attribute table:formula { \string }?
-  & attribute table:number-matrix-columns-spanned { positiveInteger }?
-  & attribute table:number-matrix-rows-spanned { positiveInteger }?
-  & common-value-and-type-attlist?
-table-cell-content-change =
-  element table:cell-content-change {
-    common-table-change-attlist,
-    table-cell-address,
-    office-change-info,
-    table-dependencies?,
-    table-deletions?,
-    table-previous
-  }
-table-cell-address =
-  element table:cell-address {
-    common-table-cell-address-attlist, empty
-  }
-table-previous =
-  element table:previous {
-    attribute table:id { \string }?,
-    table-change-track-table-cell
-  }
-common-table-change-attlist =
-  attribute table:id { \string }
-  & attribute table:acceptance-state {
-      "accepted" | "rejected" | "pending"
-    }?
-  & attribute table:rejecting-change-id { \string }?
-style-handout-master =
-  element style:handout-master {
-    common-presentation-header-footer-attlist,
-    style-handout-master-attlist,
-    shape*
-  }
-style-handout-master-attlist =
-  attribute presentation:presentation-page-layout-name { styleNameRef }?
-  & attribute style:page-layout-name { styleNameRef }
-  & attribute draw:style-name { styleNameRef }?
-draw-layer-set = element draw:layer-set { draw-layer* }
-draw-layer =
-  element draw:layer { draw-layer-attlist, svg-title?, svg-desc? }
-draw-layer-attlist =
-  attribute draw:name { \string }
-  & attribute draw:protected { boolean }?
-  & attribute draw:display { "always" | "screen" | "printer" | "none" }?
-draw-page =
-  element draw:page {
-    common-presentation-header-footer-attlist,
-    draw-page-attlist,
-    svg-title?,
-    svg-desc?,
-    draw-layer-set?,
-    office-forms?,
-    shape*,
-    (presentation-animations | animation-element)?,
-    presentation-notes?
+draw-opacity-attlist =
+  attribute draw:start { zeroToHundredPercent }?,
+  attribute draw:end { zeroToHundredPercent }?
+draw-page =
+  element draw:page {
+    common-presentation-header-footer-attlist,
+    draw-page-attlist,
+    svg-title?,
+    svg-desc?,
+    draw-layer-set?,
+    office-forms?,
+    shape*,
+    (presentation-animations | animation-element)?,
+    presentation-notes?
   }
 draw-page-attlist =
   attribute draw:name { \string }?
@@ -2153,34 +1921,29 @@ draw-page-attlist =
   & (xml-id,
      attribute draw:id { NCName }?)?
   & attribute draw:nav-order { IDREFS }?
-common-presentation-header-footer-attlist =
-  attribute presentation:use-header-name { \string }?
-  & attribute presentation:use-footer-name { \string }?
-  & attribute presentation:use-date-time-name { \string }?
-shape = shape-instance | draw-a
-shape-instance =
-  draw-rect
-  | draw-line
-  | draw-polyline
-  | draw-polygon
-  | draw-regular-polygon
-  | draw-path
-  | draw-circle
-  | draw-ellipse
-  | draw-g
-  | draw-page-thumbnail
-  | draw-frame
-  | draw-measure
-  | draw-caption
-  | draw-connector
-  | draw-control
-  | dr3d-scene
-  | draw-custom-shape
-draw-rect =
-  element draw:rect {
-    draw-rect-attlist,
+draw-page-thumbnail =
+  element draw:page-thumbnail {
+    draw-page-thumbnail-attlist,
+    common-draw-position-attlist,
+    common-draw-size-attlist,
+    presentation-shape-attlist,
+    common-draw-shape-with-styles-attlist,
+    common-draw-caption-id-attlist,
+    svg-title?,
+    svg-desc?
+  }
+draw-page-thumbnail-attlist =
+  attribute draw:page-number { positiveInteger }?
+draw-param = element draw:param { draw-param-attlist, empty }
+draw-param-attlist =
+  attribute draw:name { \string }?
+  & attribute draw:value { \string }?
+draw-path =
+  element draw:path {
+    common-draw-path-data-attlist,
     common-draw-position-attlist,
     common-draw-size-attlist,
+    common-draw-viewbox-attlist,
     common-draw-shape-with-text-and-styles-attlist,
     common-draw-caption-id-attlist,
     svg-title?,
@@ -2189,13 +1952,18 @@ draw-rect =
     draw-glue-point*,
     draw-text
   }
-draw-rect-attlist =
-  attribute draw:corner-radius { nonNegativeLength }?
-  | (attribute svg:rx { nonNegativeLength }?,
-     attribute svg:ry { nonNegativeLength }?)
-draw-line =
-  element draw:line {
-    draw-line-attlist,
+draw-plugin =
+  element draw:plugin {
+    draw-plugin-attlist, common-draw-data-attlist, draw-param*
+  }
+draw-plugin-attlist = common-draw-mime-type-attlist & xml-id?
+# https://issues.oasis-open.org/browse/OFFICE-3943
+draw-polygon =
+  element draw:polygon {
+    common-draw-points-attlist,
+    common-draw-position-attlist,
+    common-draw-size-attlist,
+    common-draw-viewbox-attlist,
     common-draw-shape-with-text-and-styles-attlist,
     common-draw-caption-id-attlist,
     svg-title?,
@@ -2204,11 +1972,6 @@ draw-line =
     draw-glue-point*,
     draw-text
   }
-draw-line-attlist =
-  attribute svg:x1 { coordinate }
-  & attribute svg:y1 { coordinate }
-  & attribute svg:x2 { coordinate }
-  & attribute svg:y2 { coordinate }
 draw-polyline =
   element draw:polyline {
     common-draw-points-attlist,
@@ -2223,13 +1986,11 @@ draw-polyline =
     draw-glue-point*,
     draw-text
   }
-common-draw-points-attlist = attribute draw:points { points }
-draw-polygon =
-  element draw:polygon {
-    common-draw-points-attlist,
+draw-rect =
+  element draw:rect {
+    draw-rect-attlist,
     common-draw-position-attlist,
     common-draw-size-attlist,
-    common-draw-viewbox-attlist,
     common-draw-shape-with-text-and-styles-attlist,
     common-draw-caption-id-attlist,
     svg-title?,
@@ -2238,6 +1999,10 @@ draw-polygon =
     draw-glue-point*,
     draw-text
   }
+draw-rect-attlist =
+  attribute draw:corner-radius { nonNegativeLength }?
+  | (attribute svg:rx { nonNegativeLength }?,
+     attribute svg:ry { nonNegativeLength }?)
 draw-regular-polygon =
   element draw:regular-polygon {
     draw-regular-polygon-attlist,
@@ -2258,262 +2023,18 @@ draw-regular-polygon-attlist =
   & attribute draw:corners { positiveInteger }
 draw-regular-polygon-sharpness-attlist =
   attribute draw:sharpness { percent }
-draw-path =
-  element draw:path {
-    common-draw-path-data-attlist,
-    common-draw-position-attlist,
-    common-draw-size-attlist,
-    common-draw-viewbox-attlist,
-    common-draw-shape-with-text-and-styles-attlist,
-    common-draw-caption-id-attlist,
-    svg-title?,
-    svg-desc?,
-    office-event-listeners?,
-    draw-glue-point*,
-    draw-text
-  }
-common-draw-path-data-attlist = attribute svg:d { pathData }
-draw-circle =
-  element draw:circle {
-    ((draw-circle-attlist, common-draw-circle-ellipse-pos-attlist)
-     | (common-draw-position-attlist, common-draw-size-attlist)),
-    common-draw-circle-ellipse-attlist,
-    common-draw-shape-with-text-and-styles-attlist,
-    common-draw-caption-id-attlist,
-    svg-title?,
-    svg-desc?,
-    office-event-listeners?,
-    draw-glue-point*,
-    draw-text
-  }
-common-draw-circle-ellipse-pos-attlist =
-  attribute svg:cx { coordinate },
-  attribute svg:cy { coordinate }
-draw-circle-attlist = attribute svg:r { length }
-common-draw-circle-ellipse-attlist =
-  attribute draw:kind { "full" | "section" | "cut" | "arc" }?
-  & attribute draw:start-angle { angle }?
-  & attribute draw:end-angle { angle }?
-draw-ellipse =
-  element draw:ellipse {
-    ((draw-ellipse-attlist, common-draw-circle-ellipse-pos-attlist)
-     | (common-draw-position-attlist, common-draw-size-attlist)),
-    common-draw-circle-ellipse-attlist,
-    common-draw-shape-with-text-and-styles-attlist,
-    common-draw-caption-id-attlist,
-    svg-title?,
-    svg-desc?,
-    office-event-listeners?,
-    draw-glue-point*,
-    draw-text
-  }
-draw-ellipse-attlist =
-  attribute svg:rx { length },
-  attribute svg:ry { length }
-draw-connector =
-  element draw:connector {
-    draw-connector-attlist,
-    common-draw-shape-with-text-and-styles-attlist,
-    common-draw-caption-id-attlist,
-    common-draw-viewbox-attlist,
-    svg-title?,
-    svg-desc?,
-    office-event-listeners?,
-    draw-glue-point*,
-    draw-text
-  }
-draw-connector-attlist =
-  attribute draw:type { "standard" | "lines" | "line" | "curve" }?
-  & (attribute svg:x1 { coordinate },
-     attribute svg:y1 { coordinate })?
-  & attribute draw:start-shape { IDREF }?
-  & attribute draw:start-glue-point { nonNegativeInteger }?
-  & (attribute svg:x2 { coordinate },
-     attribute svg:y2 { coordinate })?
-  & attribute draw:end-shape { IDREF }?
-  & attribute draw:end-glue-point { nonNegativeInteger }?
-  & attribute draw:line-skew {
-      list { length, (length, length?)? }
-    }?
-  & attribute svg:d { pathData }?
-draw-caption =
-  element draw:caption {
-    draw-caption-attlist,
-    common-draw-position-attlist,
-    common-draw-size-attlist,
-    common-draw-shape-with-text-and-styles-attlist,
-    common-draw-caption-id-attlist,
-    svg-title?,
-    svg-desc?,
-    office-event-listeners?,
-    draw-glue-point*,
-    draw-text
-  }
-draw-caption-attlist =
-  (attribute draw:caption-point-x { coordinate },
-   attribute draw:caption-point-y { coordinate })?
-  & attribute draw:corner-radius { nonNegativeLength }?
-draw-measure =
-  element draw:measure {
-    draw-measure-attlist,
-    common-draw-shape-with-text-and-styles-attlist,
-    common-draw-caption-id-attlist,
-    svg-title?,
-    svg-desc?,
-    office-event-listeners?,
-    draw-glue-point*,
-    draw-text
-  }
-draw-measure-attlist =
-  attribute svg:x1 { coordinate }
-  & attribute svg:y1 { coordinate }
-  & attribute svg:x2 { coordinate }
-  & attribute svg:y2 { coordinate }
-draw-control =
-  element draw:control {
-    draw-control-attlist,
-    common-draw-position-attlist,
-    common-draw-size-attlist,
-    common-draw-shape-with-text-and-styles-attlist,
-    common-draw-caption-id-attlist,
-    svg-title?,
-    svg-desc?,
-    draw-glue-point*
-  }
-draw-control-attlist = attribute draw:control { IDREF }
-draw-page-thumbnail =
-  element draw:page-thumbnail {
-    draw-page-thumbnail-attlist,
-    common-draw-position-attlist,
-    common-draw-size-attlist,
-    presentation-shape-attlist,
-    common-draw-shape-with-styles-attlist,
-    common-draw-caption-id-attlist,
-    svg-title?,
-    svg-desc?
-  }
-draw-page-thumbnail-attlist =
-  attribute draw:page-number { positiveInteger }?
-draw-g =
-  element draw:g {
-    draw-g-attlist,
-    common-draw-z-index-attlist,
-    common-draw-name-attlist,
-    common-draw-id-attlist,
-    common-draw-style-name-attlist,
-    common-text-spreadsheet-shape-attlist,
-    common-draw-caption-id-attlist,
-    svg-title?,
-    svg-desc?,
-    office-event-listeners?,
-    draw-glue-point*,
-    shape*
-  }
-draw-g-attlist = attribute svg:y { coordinate }?
-common-draw-name-attlist = attribute draw:name { \string }?
-common-draw-caption-id-attlist = attribute draw:caption-id { IDREF }?
-common-draw-position-attlist =
-  attribute svg:x { coordinate }?,
-  attribute svg:y { coordinate }?
-common-draw-size-attlist =
-  attribute svg:width { length }?,
-  attribute svg:height { length }?
-common-draw-transform-attlist = attribute draw:transform { \string }?
-common-draw-viewbox-attlist =
-  attribute svg:viewBox {
-    list { integer, integer, integer, integer }
-  }
-common-draw-style-name-attlist =
-  (attribute draw:style-name { styleNameRef }?,
-   attribute draw:class-names { styleNameRefs }?)
-  | (attribute presentation:style-name { styleNameRef }?,
-     attribute presentation:class-names { styleNameRefs }?)
-common-draw-text-style-name-attlist =
-  attribute draw:text-style-name { styleNameRef }?
-common-draw-layer-name-attlist = attribute draw:layer { \string }?
-common-draw-id-attlist =
-  (xml-id,
-   attribute draw:id { NCName }?)?
-common-draw-z-index-attlist =
-  attribute draw:z-index { nonNegativeInteger }?
-common-text-spreadsheet-shape-attlist =
-  attribute table:end-cell-address { cellAddress }?
-  & attribute table:end-x { coordinate }?
-  & attribute table:end-y { coordinate }?
-  & attribute table:table-background { boolean }?
-  & common-text-anchor-attlist
-common-text-anchor-attlist =
-  attribute text:anchor-type {
-    "page" | "frame" | "paragraph" | "char" | "as-char"
-  }?
-  & attribute text:anchor-page-number { positiveInteger }?
+draw-stroke-dash =
+  element draw:stroke-dash { draw-stroke-dash-attlist, empty }
+draw-stroke-dash-attlist =
+  attribute draw:name { styleName }
+  & attribute draw:display-name { \string }?
+  & attribute draw:style { "rect" | "round" }?
+  & attribute draw:dots1 { integer }?
+  & attribute draw:dots1-length { length | percent }?
+  & attribute draw:dots2 { integer }?
+  & attribute draw:dots2-length { length | percent }?
+  & attribute draw:distance { length | percent }?
 draw-text = (text-p | text-list)*
-common-draw-shape-with-styles-attlist =
-  common-draw-z-index-attlist,
-  common-draw-id-attlist,
-  common-draw-layer-name-attlist,
-  common-draw-style-name-attlist,
-  common-draw-transform-attlist,
-  common-draw-name-attlist,
-  common-text-spreadsheet-shape-attlist
-common-draw-shape-with-text-and-styles-attlist =
-  common-draw-shape-with-styles-attlist,
-  common-draw-text-style-name-attlist
-draw-glue-point =
-  element draw:glue-point { draw-glue-point-attlist, empty }
-draw-glue-point-attlist =
-  attribute draw:id { nonNegativeInteger }
-  & attribute svg:x { distance | percent }
-  & attribute svg:y { distance | percent }
-  & attribute draw:align {
-      "top-left"
-      | "top"
-      | "top-right"
-      | "left"
-      | "center"
-      | "right"
-      | "bottom-left"
-      | "bottom-right"
-    }?
-  & attribute draw:escape-direction {
-      "auto"
-      | "left"
-      | "right"
-      | "up"
-      | "down"
-      | "horizontal"
-      | "vertical"
-    }
-svg-title = element svg:title { text }
-svg-desc = element svg:desc { text }
-draw-frame =
-  element draw:frame {
-    common-draw-shape-with-text-and-styles-attlist,
-    common-draw-position-attlist,
-    common-draw-rel-size-attlist,
-    common-draw-caption-id-attlist,
-    presentation-shape-attlist,
-    draw-frame-attlist,
-    (draw-text-box
-     | draw-image
-     | draw-object
-     | draw-object-ole
-     | draw-applet
-     | draw-floating-frame
-     | draw-plugin
-     | table-table)*,
-    office-event-listeners?,
-    draw-glue-point*,
-    draw-image-map?,
-    svg-title?,
-    svg-desc?,
-    (draw-contour-polygon | draw-contour-path)?
-  }
-common-draw-rel-size-attlist =
-  common-draw-size-attlist,
-  attribute style:rel-width { percent | "scale" | "scale-min" }?,
-  attribute style:rel-height { percent | "scale" | "scale-min" }?
-draw-frame-attlist = attribute draw:copy-of { \string }?
 draw-text-box =
   element draw:text-box { draw-text-box-attlist, text-content* }
 draw-text-box-attlist =
@@ -2525,2177 +2046,539 @@ draw-text-box-attlist =
   & attribute fo:max-width { length | percent }?
   & (xml-id,
      attribute text:id { NCName }?)?
-draw-image =
-  element draw:image {
-    draw-image-attlist,
-    (common-draw-data-attlist | office-binary-data),
-    draw-text
-  }
-common-draw-data-attlist =
-  attribute xlink:type { "simple" },
-  attribute xlink:href { anyIRI },
-  attribute xlink:show { "embed" }?,
-  attribute xlink:actuate { "onLoad" }?
-office-binary-data = element office:binary-data { base64Binary }
-draw-image-attlist =
-  attribute draw:filter-name { \string }?
-  & xml-id?
-draw-object =
-  element draw:object {
-    draw-object-attlist,
-    (common-draw-data-attlist | office-document | math-math)
-  }
-draw-object-ole =
-  element draw:object-ole {
-    draw-object-ole-attlist,
-    (common-draw-data-attlist | office-binary-data)
-  }
-draw-object-attlist =
-  attribute draw:notify-on-update-of-ranges {
-    cellRangeAddressList | \string
-  }?
-  & xml-id?
-draw-object-ole-attlist =
-  attribute draw:class-id { \string }?
-  & xml-id?
-draw-applet =
-  element draw:applet {
-    draw-applet-attlist, common-draw-data-attlist?, draw-param*
-  }
-draw-applet-attlist =
-  attribute draw:code { \string }?
-  & attribute draw:object { \string }?
-  & attribute draw:archive { \string }?
-  & attribute draw:may-script { boolean }?
-  & xml-id?
-draw-plugin =
-  element draw:plugin {
-    draw-plugin-attlist, common-draw-data-attlist, draw-param*
-  }
-draw-plugin-attlist =
-  attribute draw:mime-type { \string }?
-  & xml-id?
-draw-param = element draw:param { draw-param-attlist, empty }
-draw-param-attlist =
-  attribute draw:name { \string }?
-  & attribute draw:value { \string }?
-draw-floating-frame =
-  element draw:floating-frame {
-    draw-floating-frame-attlist, common-draw-data-attlist
-  }
-draw-floating-frame-attlist =
-  attribute draw:frame-name { \string }?
-  & xml-id?
-draw-contour-polygon =
-  element draw:contour-polygon {
-    common-contour-attlist,
-    common-draw-size-attlist,
-    common-draw-viewbox-attlist,
-    common-draw-points-attlist,
-    empty
-  }
-draw-contour-path =
-  element draw:contour-path {
-    common-contour-attlist,
-    common-draw-size-attlist,
-    common-draw-viewbox-attlist,
-    common-draw-path-data-attlist,
+dropdown = attribute form:dropdown { boolean }?
+duration = xsd:duration
+extrusionOrigin =
+  xsd:double { minInclusive = "-0.5" maxInclusive = "0.5" }
+fontFamilyGeneric =
+  "roman" | "swiss" | "modern" | "decorative" | "script" | "system"
+fontPitch = "fixed" | "variable"
+fontStyle = "normal" | "italic" | "oblique"
+fontVariant = "normal" | "small-caps"
+fontWeight =
+  "normal"
+  | "bold"
+  | "100"
+  | "200"
+  | "300"
+  | "400"
+  | "500"
+  | "600"
+  | "700"
+  | "800"
+  | "900"
+for = attribute form:for { \string }?
+form-button-attlist =
+  form-control-attlist
+  & button-type
+  & common-disabled-attlist
+  & label
+  & image-data
+  & common-printable-attlist
+  & common-tab-attlist
+  & target-frame
+  & target-location
+  & common-title-attlist
+  & common-value-attlist
+  & common-form-relative-image-position-attlist
+  & common-repeat
+  & common-delay-for-repeat
+  & attribute form:default-button { boolean }?
+  & attribute form:toggle { boolean }?
+  & attribute form:focus-on-click { boolean }?
+  & attribute form:xforms-submission { \string }?
+form-checkbox-attlist =
+  form-control-attlist
+  & common-disabled-attlist
+  & label
+  & common-printable-attlist
+  & common-tab-attlist
+  & common-title-attlist
+  & common-value-attlist
+  & common-data-field-attlist
+  & common-form-visual-effect-attlist
+  & common-form-relative-image-position-attlist
+  & common-linked-cell
+  & attribute form:current-state { states }?
+  & attribute form:is-tristate { boolean }?
+  & attribute form:state { states }?
+form-column =
+  element form:column { form-column-attlist, column-controls+ }
+form-column-attlist =
+  common-form-control-attlist, label, text-style-name
+form-combobox-attlist =
+  form-control-attlist
+  & common-current-value-attlist
+  & common-disabled-attlist
+  & dropdown
+  & common-maxlength-attlist
+  & common-printable-attlist
+  & common-readonly-attlist
+  & size
+  & common-tab-attlist
+  & common-title-attlist
+  & common-value-attlist
+  & common-convert-empty-attlist
+  & common-data-field-attlist
+  & list-source
+  & list-source-type
+  & common-linked-cell
+  & common-source-cell-range
+  & attribute form:auto-complete { boolean }?
+form-connection-resource =
+  element form:connection-resource {
+    attribute xlink:href { anyIRI },
     empty
   }
-common-contour-attlist = attribute draw:recreate-on-edit { boolean }
-draw-a = element draw:a { draw-a-attlist, shape-instance }
-draw-a-attlist =
-  attribute xlink:type { "simple" }
-  & attribute xlink:href { anyIRI }
-  & attribute xlink:actuate { "onRequest" }?
-  & attribute office:target-frame-name { targetFrameName }?
-  & attribute xlink:show { "new" | "replace" }?
-  & attribute office:name { \string }?
-  & attribute office:title { \string }?
-  & attribute office:server-map { boolean }?
-  & xml-id?
-draw-image-map =
-  element draw:image-map {
-    (draw-area-rectangle | draw-area-circle | draw-area-polygon)*
-  }
-draw-area-rectangle =
-  element draw:area-rectangle {
-    common-draw-area-attlist,
-    attribute svg:x { coordinate },
-    attribute svg:y { coordinate },
-    attribute svg:width { length },
-    attribute svg:height { length },
-    svg-title?,
-    svg-desc?,
-    office-event-listeners?
-  }
-draw-area-circle =
-  element draw:area-circle {
-    common-draw-area-attlist,
-    attribute svg:cx { coordinate },
-    attribute svg:cy { coordinate },
-    attribute svg:r { length },
-    svg-title?,
-    svg-desc?,
-    office-event-listeners?
-  }
-draw-area-polygon =
-  element draw:area-polygon {
-    common-draw-area-attlist,
-    attribute svg:x { coordinate },
-    attribute svg:y { coordinate },
-    attribute svg:width { length },
-    attribute svg:height { length },
-    common-draw-viewbox-attlist,
-    common-draw-points-attlist,
-    svg-title?,
-    svg-desc?,
-    office-event-listeners?
+form-control-attlist =
+  common-form-control-attlist,
+  common-control-id-attlist,
+  xforms-bind-attlist
+form-date-attlist =
+  attribute form:value { date }?
+  & attribute form:current-value { date }?
+  & attribute form:min-value { date }?
+  & attribute form:max-value { date }?
+form-file-attlist =
+  form-control-attlist,
+  common-current-value-attlist,
+  common-disabled-attlist,
+  common-maxlength-attlist,
+  common-printable-attlist,
+  common-readonly-attlist,
+  common-tab-attlist,
+  common-title-attlist,
+  common-value-attlist,
+  common-linked-cell
+form-fixed-text-attlist =
+  form-control-attlist
+  & for
+  & common-disabled-attlist
+  & label
+  & common-printable-attlist
+  & common-title-attlist
+  & attribute form:multi-line { boolean }?
+form-form =
+  element form:form {
+    common-form-control-attlist,
+    form-form-attlist,
+    form-properties?,
+    office-event-listeners?,
+    (controls | form-form)*,
+    form-connection-resource?
   }
-common-draw-area-attlist =
+form-form-attlist =
   (attribute xlink:type { "simple" },
    attribute xlink:href { anyIRI },
-   attribute office:target-frame-name { targetFrameName }?,
-   attribute xlink:show { "new" | "replace" }?)?
-  & attribute office:name { \string }?
-  & attribute draw:nohref { "nohref" }?
-dr3d-scene =
-  element dr3d:scene {
-    dr3d-scene-attlist,
-    common-draw-position-attlist,
-    common-draw-size-attlist,
-    common-draw-style-name-attlist,
-    common-draw-z-index-attlist,
-    common-draw-id-attlist,
-    common-draw-layer-name-attlist,
-    common-text-spreadsheet-shape-attlist,
-    common-dr3d-transform-attlist,
-    common-draw-caption-id-attlist,
-    svg-title?,
-    svg-desc?,
-    dr3d-light*,
-    shapes3d*,
-    draw-glue-point*
-  }
-shapes3d =
-  dr3d-scene | dr3d-extrude | dr3d-sphere | dr3d-rotate | dr3d-cube
-dr3d-scene-attlist =
-  attribute dr3d:vrp { vector3D }?
-  & attribute dr3d:vpn { vector3D }?
-  & attribute dr3d:vup { vector3D }?
-  & attribute dr3d:projection { "parallel" | "perspective" }?
-  & attribute dr3d:distance { length }?
-  & attribute dr3d:focal-length { length }?
-  & attribute dr3d:shadow-slant { angle }?
-  & attribute dr3d:shade-mode {
-      "flat" | "phong" | "gouraud" | "draft"
-    }?
-  & attribute dr3d:ambient-color { color }?
-  & attribute dr3d:lighting-mode { boolean }?
-common-dr3d-transform-attlist = attribute dr3d:transform { \string }?
-dr3d-light = element dr3d:light { dr3d-light-attlist, empty }
-dr3d-light-attlist =
-  attribute dr3d:diffuse-color { color }?
-  & attribute dr3d:direction { vector3D }
-  & attribute dr3d:enabled { boolean }?
-  & attribute dr3d:specular { boolean }?
-dr3d-cube =
-  element dr3d:cube {
-    dr3d-cube-attlist,
-    common-draw-z-index-attlist,
-    common-draw-id-attlist,
-    common-draw-layer-name-attlist,
-    common-draw-style-name-attlist,
-    common-dr3d-transform-attlist,
-    empty
-  }
-dr3d-cube-attlist =
-  attribute dr3d:min-edge { vector3D }?,
-  attribute dr3d:max-edge { vector3D }?
-dr3d-sphere =
-  element dr3d:sphere {
-    dr3d-sphere-attlist,
-    common-draw-z-index-attlist,
-    common-draw-id-attlist,
-    common-draw-layer-name-attlist,
-    common-draw-style-name-attlist,
-    common-dr3d-transform-attlist,
-    empty
-  }
-dr3d-sphere-attlist =
-  attribute dr3d:center { vector3D }?
-  & attribute dr3d:size { vector3D }?
-dr3d-extrude =
-  element dr3d:extrude {
-    common-draw-path-data-attlist,
-    common-draw-viewbox-attlist,
-    common-draw-id-attlist,
-    common-draw-z-index-attlist,
-    common-draw-layer-name-attlist,
-    common-draw-style-name-attlist,
-    common-dr3d-transform-attlist,
-    empty
-  }
-dr3d-rotate =
-  element dr3d:rotate {
-    common-draw-viewbox-attlist,
-    common-draw-path-data-attlist,
-    common-draw-z-index-attlist,
-    common-draw-id-attlist,
-    common-draw-layer-name-attlist,
-    common-draw-style-name-attlist,
-    common-dr3d-transform-attlist,
-    empty
-  }
-draw-custom-shape =
-  element draw:custom-shape {
-    draw-custom-shape-attlist,
-    common-draw-position-attlist,
-    common-draw-size-attlist,
-    common-draw-shape-with-text-and-styles-attlist,
-    common-draw-caption-id-attlist,
-    svg-title?,
-    svg-desc?,
-    office-event-listeners?,
-    draw-glue-point*,
-    draw-text,
-    draw-enhanced-geometry?
-  }
-draw-custom-shape-attlist =
-  attribute draw:engine { namespacedToken }?
-  & attribute draw:data { \string }?
-draw-enhanced-geometry =
-  element draw:enhanced-geometry {
-    draw-enhanced-geometry-attlist, draw-equation*, draw-handle*
-  }
-draw-enhanced-geometry-attlist =
-  attribute draw:type { custom-shape-type }?
-  & attribute svg:viewBox {
-      list { integer, integer, integer, integer }
-    }?
-  & attribute draw:mirror-vertical { boolean }?
-  & attribute draw:mirror-horizontal { boolean }?
-  & attribute draw:text-rotate-angle { angle }?
-  & attribute draw:extrusion-allowed { boolean }?
-  & attribute draw:text-path-allowed { boolean }?
-  & attribute draw:concentric-gradient-fill-allowed { boolean }?
-  & attribute draw:extrusion { boolean }?
-  & attribute draw:extrusion-brightness { zeroToHundredPercent }?
-  & attribute draw:extrusion-depth {
-      list { length, double }
-    }?
-  & attribute draw:extrusion-diffusion { percent }?
-  & attribute draw:extrusion-number-of-line-segments { integer }?
-  & attribute draw:extrusion-light-face { boolean }?
-  & attribute draw:extrusion-first-light-harsh { boolean }?
-  & attribute draw:extrusion-second-light-harsh { boolean }?
-  & attribute draw:extrusion-first-light-level { zeroToHundredPercent }?
-  & attribute draw:extrusion-second-light-level {
-      zeroToHundredPercent
-    }?
-  & attribute draw:extrusion-first-light-direction { vector3D }?
-  & attribute draw:extrusion-second-light-direction { vector3D }?
-  & attribute draw:extrusion-metal { boolean }?
-  & attribute dr3d:shade-mode {
-      "flat" | "phong" | "gouraud" | "draft"
-    }?
-  & attribute draw:extrusion-rotation-angle {
-      list { angle, angle }
-    }?
-  & attribute draw:extrusion-rotation-center { vector3D }?
-  & attribute draw:extrusion-shininess { zeroToHundredPercent }?
-  & attribute draw:extrusion-skew {
-      list { double, angle }
-    }?
-  & attribute draw:extrusion-specularity { zeroToHundredPercent }?
-  & attribute dr3d:projection { "parallel" | "perspective" }?
-  & attribute draw:extrusion-viewpoint { point3D }?
-  & attribute draw:extrusion-origin {
-      list { extrusionOrigin, extrusionOrigin }
-    }?
-  & attribute draw:extrusion-color { boolean }?
-  & attribute draw:enhanced-path { \string }?
-  & attribute draw:path-stretchpoint-x { double }?
-  & attribute draw:path-stretchpoint-y { double }?
-  & attribute draw:text-areas { \string }?
-  & attribute draw:glue-points { \string }?
-  & attribute draw:glue-point-type {
-      "none" | "segments" | "rectangle"
-    }?
-  & attribute draw:glue-point-leaving-directions { \string }?
-  & attribute draw:text-path { boolean }?
-  & attribute draw:text-path-mode { "normal" | "path" | "shape" }?
-  & attribute draw:text-path-scale { "path" | "shape" }?
-  & attribute draw:text-path-same-letter-heights { boolean }?
-  & attribute draw:modifiers { \string }?
-custom-shape-type = "non-primitive" | \string
-point3D =
-  xsd:string {
-    pattern =
-      "\([ ]*-?([0-9]+(\.[0-9]*)?|\.[0-9]+)((cm)|(mm)|(in)|(pt)|(pc))([ 
]+-?([0-9]+(\.[0-9]*)?|\.[0-9]+)((cm)|(mm)|(in)|(pt)|(pc))){2}[ ]*\)"
-  }
-extrusionOrigin =
-  xsd:double { minInclusive = "-0.5" maxInclusive = "0.5" }
-draw-equation = element draw:equation { draw-equation-attlist, empty }
-draw-equation-attlist =
-  attribute draw:name { \string }?
-  & attribute draw:formula { \string }?
-draw-handle = element draw:handle { draw-handle-attlist, empty }
-draw-handle-attlist =
-  attribute draw:handle-mirror-vertical { boolean }?
-  & attribute draw:handle-mirror-horizontal { boolean }?
-  & attribute draw:handle-switched { boolean }?
-  & attribute draw:handle-position { \string }
-  & attribute draw:handle-range-x-minimum { \string }?
-  & attribute draw:handle-range-x-maximum { \string }?
-  & attribute draw:handle-range-y-minimum { \string }?
-  & attribute draw:handle-range-y-maximum { \string }?
-  & attribute draw:handle-polar { \string }?
-  & attribute draw:handle-radius-range-minimum { \string }?
-  & attribute draw:handle-radius-range-maximum { \string }?
-presentation-shape-attlist =
-  attribute presentation:class { presentation-classes }?
-  & attribute presentation:placeholder { boolean }?
-  & attribute presentation:user-transformed { boolean }?
-presentation-classes =
-  "title"
-  | "outline"
-  | "subtitle"
-  | "text"
-  | "graphic"
-  | "object"
-  | "chart"
-  | "table"
-  | "orgchart"
-  | "page"
-  | "notes"
-  | "handout"
-  | "header"
-  | "footer"
-  | "date-time"
-  | "page-number"
-presentation-animations =
-  element presentation:animations {
-    (presentation-animation-elements | presentation-animation-group)*
-  }
-presentation-animation-elements =
-  presentation-show-shape
-  | presentation-show-text
-  | presentation-hide-shape
-  | presentation-hide-text
-  | presentation-dim
-  | presentation-play
-presentation-sound =
-  element presentation:sound {
-    presentation-sound-attlist,
-    attribute xlink:type { "simple" },
-    attribute xlink:href { anyIRI },
-    attribute xlink:actuate { "onRequest" }?,
-    attribute xlink:show { "new" | "replace" }?,
-    empty
-  }
-presentation-sound-attlist =
-  attribute presentation:play-full { boolean }?
-  & xml-id?
-presentation-show-shape =
-  element presentation:show-shape {
-    common-presentation-effect-attlist, presentation-sound?
-  }
-common-presentation-effect-attlist =
-  attribute draw:shape-id { IDREF }
-  & attribute presentation:effect { presentationEffects }?
-  & attribute presentation:direction { presentationEffectDirections }?
-  & attribute presentation:speed { presentationSpeeds }?
-  & attribute presentation:delay { duration }?
-  & attribute presentation:start-scale { percent }?
-  & attribute presentation:path-id { \string }?
-presentationEffects =
-  "none"
-  | "fade"
-  | "move"
-  | "stripes"
-  | "open"
-  | "close"
-  | "dissolve"
-  | "wavyline"
-  | "random"
-  | "lines"
-  | "laser"
-  | "appear"
-  | "hide"
-  | "move-short"
-  | "checkerboard"
-  | "rotate"
-  | "stretch"
-presentationEffectDirections =
-  "none"
-  | "from-left"
-  | "from-top"
-  | "from-right"
-  | "from-bottom"
-  | "from-center"
-  | "from-upper-left"
-  | "from-upper-right"
-  | "from-lower-left"
-  | "from-lower-right"
-  | "to-left"
-  | "to-top"
-  | "to-right"
-  | "to-bottom"
-  | "to-upper-left"
-  | "to-upper-right"
-  | "to-lower-right"
-  | "to-lower-left"
-  | "path"
-  | "spiral-inward-left"
-  | "spiral-inward-right"
-  | "spiral-outward-left"
-  | "spiral-outward-right"
-  | "vertical"
-  | "horizontal"
-  | "to-center"
-  | "clockwise"
-  | "counter-clockwise"
-presentationSpeeds = "slow" | "medium" | "fast"
-presentation-show-text =
-  element presentation:show-text {
-    common-presentation-effect-attlist, presentation-sound?
-  }
-presentation-hide-shape =
-  element presentation:hide-shape {
-    common-presentation-effect-attlist, presentation-sound?
-  }
-presentation-hide-text =
-  element presentation:hide-text {
-    common-presentation-effect-attlist, presentation-sound?
-  }
-presentation-dim =
-  element presentation:dim {
-    presentation-dim-attlist, presentation-sound?
-  }
-presentation-dim-attlist =
-  attribute draw:shape-id { IDREF }
-  & attribute draw:color { color }
-presentation-play =
-  element presentation:play { presentation-play-attlist, empty }
-presentation-play-attlist =
-  attribute draw:shape-id { IDREF },
-  attribute presentation:speed { presentationSpeeds }?
-presentation-animation-group =
-  element presentation:animation-group {
-    presentation-animation-elements*
-  }
-common-anim-attlist =
-  attribute presentation:node-type {
-    "default"
-    | "on-click"
-    | "with-previous"
-    | "after-previous"
-    | "timing-root"
-    | "main-sequence"
-    | "interactive-sequence"
-  }?
-  & attribute presentation:preset-id { \string }?
-  & attribute presentation:preset-sub-type { \string }?
-  & attribute presentation:preset-class {
-      "custom"
-      | "entrance"
-      | "exit"
-      | "emphasis"
-      | "motion-path"
-      | "ole-action"
-      | "media-call"
-    }?
-  & attribute presentation:master-element { IDREF }?
-  & attribute presentation:group-id { \string }?
-  & (xml-id,
-     attribute anim:id { NCName }?)?
-presentation-event-listener =
-  element presentation:event-listener {
-    presentation-event-listener-attlist, presentation-sound?
-  }
-presentation-event-listener-attlist =
-  attribute script:event-name { \string }
-  & attribute presentation:action {
-      "none"
-      | "previous-page"
-      | "next-page"
-      | "first-page"
-      | "last-page"
-      | "hide"
-      | "stop"
-      | "execute"
-      | "show"
-      | "verb"
-      | "fade-out"
-      | "sound"
-      | "last-visited-page"
-    }
-  & attribute presentation:effect { presentationEffects }?
-  & attribute presentation:direction { presentationEffectDirections }?
-  & attribute presentation:speed { presentationSpeeds }?
-  & attribute presentation:start-scale { percent }?
-  & (attribute xlink:type { "simple" },
-     attribute xlink:href { anyIRI },
-     attribute xlink:show { "embed" }?,
-     attribute xlink:actuate { "onRequest" }?)?
-  & attribute presentation:verb { nonNegativeInteger }?
-presentation-decls = presentation-decl*
-presentation-decl =
-  element presentation:header-decl {
-    presentation-header-decl-attlist, text
-  }
-  | element presentation:footer-decl {
-      presentation-footer-decl-attlist, text
-    }
-  | element presentation:date-time-decl {
-      presentation-date-time-decl-attlist, text
-    }
-presentation-header-decl-attlist =
-  attribute presentation:name { \string }
-presentation-footer-decl-attlist =
-  attribute presentation:name { \string }
-presentation-date-time-decl-attlist =
-  attribute presentation:name { \string }
-  & attribute presentation:source { "fixed" | "current-date" }
-  & attribute style:data-style-name { styleNameRef }?
-presentation-settings =
-  element presentation:settings {
-    presentation-settings-attlist, presentation-show*
-  }?
-presentation-settings-attlist =
-  attribute presentation:start-page { \string }?
-  & attribute presentation:show { \string }?
-  & attribute presentation:full-screen { boolean }?
-  & attribute presentation:endless { boolean }?
-  & attribute presentation:pause { duration }?
-  & attribute presentation:show-logo { boolean }?
-  & attribute presentation:force-manual { boolean }?
-  & attribute presentation:mouse-visible { boolean }?
-  & attribute presentation:mouse-as-pen { boolean }?
-  & attribute presentation:start-with-navigator { boolean }?
-  & attribute presentation:animations { "enabled" | "disabled" }?
-  & attribute presentation:transition-on-click {
-      "enabled" | "disabled"
-    }?
-  & attribute presentation:stay-on-top { boolean }?
-  & attribute presentation:show-end-of-presentation-slide { boolean }?
-presentation-show =
-  element presentation:show { presentation-show-attlist, empty }
-presentation-show-attlist =
-  attribute presentation:name { \string }
-  & attribute presentation:pages { \string }
-chart-chart =
-  element chart:chart {
-    chart-chart-attlist,
-    chart-title?,
-    chart-subtitle?,
-    chart-footer?,
-    chart-legend?,
-    chart-plot-area,
-    table-table?
-  }
-chart-chart-attlist =
-  attribute chart:class { namespacedToken }
-  & common-draw-size-attlist
-  & attribute chart:column-mapping { \string }?
-  & attribute chart:row-mapping { \string }?
-  & attribute chart:style-name { styleNameRef }?
-  & (attribute xlink:type { "simple" },
-     attribute xlink:href { anyIRI })?
-  & xml-id?
-chart-title = element chart:title { chart-title-attlist, text-p? }
-chart-title-attlist =
-  attribute table:cell-range { cellRangeAddressList }?
-  & common-draw-position-attlist
-  & attribute chart:style-name { styleNameRef }?
-chart-subtitle = element chart:subtitle { chart-title-attlist, text-p? }
-chart-footer = element chart:footer { chart-title-attlist, text-p? }
-chart-legend = element chart:legend { chart-legend-attlist, text-p? }
-chart-legend-attlist =
-  ((attribute chart:legend-position {
-      "start" | "end" | "top" | "bottom"
-    },
-    attribute chart:legend-align { "start" | "center" | "end" }?)
-   | attribute chart:legend-position {
-       "top-start" | "bottom-start" | "top-end" | "bottom-end"
-     }
-   | empty)
-  & common-draw-position-attlist
-  & (attribute style:legend-expansion { "wide" | "high" | "balanced" }
-     | (attribute style:legend-expansion { "custom" },
-        attribute style:legend-expansion-aspect-ratio { double })
-     | empty)
-  & attribute chart:style-name { styleNameRef }?
-chart-plot-area =
-  element chart:plot-area {
-    chart-plot-area-attlist,
-    dr3d-light*,
-    chart-axis*,
-    chart-series*,
-    chart-stock-gain-marker?,
-    chart-stock-loss-marker?,
-    chart-stock-range-line?,
-    chart-wall?,
-    chart-floor?
-  }
-chart-plot-area-attlist =
-  common-draw-position-attlist
-  & common-draw-size-attlist
-  & attribute chart:style-name { styleNameRef }?
-  & attribute table:cell-range-address { cellRangeAddressList }?
-  & attribute chart:data-source-has-labels {
-      "none" | "row" | "column" | "both"
-    }?
-  & dr3d-scene-attlist
-  & common-dr3d-transform-attlist
-  & xml-id?
-chart-wall = element chart:wall { chart-wall-attlist, empty }
-chart-wall-attlist =
-  attribute svg:width { length }?
-  & attribute chart:style-name { styleNameRef }?
-chart-floor = element chart:floor { chart-floor-attlist, empty }
-chart-floor-attlist =
-  attribute svg:width { length }?
-  & attribute chart:style-name { styleNameRef }?
-chart-axis =
-  element chart:axis {
-    chart-axis-attlist, chart-title?, chart-categories?, chart-grid*
-  }
-chart-axis-attlist =
-  attribute chart:dimension { chart-dimension }
-  & attribute chart:name { \string }?
-  & attribute chart:style-name { styleNameRef }?
-chart-dimension = "x" | "y" | "z"
-chart-categories =
-  element chart:categories {
-    attribute table:cell-range-address { cellRangeAddressList }?
-  }
-chart-grid = element chart:grid { chart-grid-attlist }
-chart-grid-attlist =
-  attribute chart:class { "major" | "minor" }?
-  & attribute chart:style-name { styleNameRef }?
-chart-series =
-  element chart:series {
-    chart-series-attlist,
-    chart-domain*,
-    chart-mean-value?,
-    chart-regression-curve*,
-    chart-error-indicator*,
-    chart-data-point*,
-    chart-data-label?
-  }
-chart-series-attlist =
-  attribute chart:values-cell-range-address { cellRangeAddressList }?
-  & attribute chart:label-cell-address { cellRangeAddressList }?
-  & attribute chart:class { namespacedToken }?
-  & attribute chart:attached-axis { \string }?
-  & attribute chart:style-name { styleNameRef }?
-  & xml-id?
-chart-domain =
-  element chart:domain {
-    attribute table:cell-range-address { cellRangeAddressList }?
-  }
-chart-data-point =
-  element chart:data-point {
-    chart-data-point-attlist, chart-data-label?
-  }
-chart-data-point-attlist =
-  attribute chart:repeated { positiveInteger }?
-  & attribute chart:style-name { styleNameRef }?
-  & xml-id?
-chart-data-label =
-  element chart:data-label { chart-data-label-attlist, text-p? }
-chart-data-label-attlist =
-  common-draw-position-attlist
-  & attribute chart:style-name { styleNameRef }?
-chart-mean-value =
-  element chart:mean-value { chart-mean-value-attlist, empty }
-chart-mean-value-attlist = attribute chart:style-name { styleNameRef }?
-chart-error-indicator =
-  element chart:error-indicator { chart-error-indicator-attlist, empty }
-chart-error-indicator-attlist =
-  attribute chart:style-name { styleNameRef }?
-  & attribute chart:dimension { chart-dimension }
-chart-regression-curve =
-  element chart:regression-curve {
-    chart-regression-curve-attlist, chart-equation?
-  }
-chart-regression-curve-attlist =
-  attribute chart:style-name { styleNameRef }?
-chart-equation =
-  element chart:equation { chart-equation-attlist, text-p? }
-chart-equation-attlist =
-  attribute chart:automatic-content { boolean }?
-  & attribute chart:display-r-square { boolean }?
-  & attribute chart:display-equation { boolean }?
-  & common-draw-position-attlist
-  & attribute chart:style-name { styleNameRef }?
-chart-stock-gain-marker =
-  element chart:stock-gain-marker { common-stock-marker-attlist }
-chart-stock-loss-marker =
-  element chart:stock-loss-marker { common-stock-marker-attlist }
-chart-stock-range-line =
-  element chart:stock-range-line { common-stock-marker-attlist }
-common-stock-marker-attlist =
-  attribute chart:style-name { styleNameRef }?
-office-database =
-  element office:database {
-    db-data-source,
-    db-forms?,
-    db-reports?,
-    db-queries?,
-    db-table-presentations?,
-    db-schema-definition?
-  }
-db-data-source =
-  element db:data-source {
-    db-data-source-attlist,
-    db-connection-data,
-    db-driver-settings?,
-    db-application-connection-settings?
-  }
-db-data-source-attlist = empty
-db-connection-data =
-  element db:connection-data {
-    db-connection-data-attlist,
-    (db-database-description | db-connection-resource),
-    db-login?
-  }
-db-connection-data-attlist = empty
-db-database-description =
-  element db:database-description {
-    db-database-description-attlist,
-    (db-file-based-database | db-server-database)
-  }
-db-database-description-attlist = empty
-db-file-based-database =
-  element db:file-based-database { db-file-based-database-attlist }
-db-file-based-database-attlist =
-  attribute xlink:type { "simple" }
-  & attribute xlink:href { anyIRI }
-  & attribute db:media-type { \string }
-  & attribute db:extension { \string }?
-db-server-database =
-  element db:server-database { db-server-database-attlist, empty }
-db-server-database-attlist =
-  attribute db:type { namespacedToken }
-  & (db-host-and-port | db-local-socket-name)
-  & attribute db:database-name { \string }?
-db-host-and-port =
-  attribute db:hostname { \string },
-  attribute db:port { positiveInteger }?
-db-local-socket-name = attribute db:local-socket { \string }?
-db-connection-resource =
-  element db:connection-resource {
-    db-connection-resource-attlist, empty
-  }
-db-connection-resource-attlist =
-  attribute xlink:type { "simple" },
-  attribute xlink:href { anyIRI },
-  attribute xlink:show { "none" }?,
-  attribute xlink:actuate { "onRequest" }?
-db-login = element db:login { db-login-attlist, empty }
-db-login-attlist =
-  (attribute db:user-name { \string }
-   | attribute db:use-system-user { boolean })?
-  & attribute db:is-password-required { boolean }?
-  & attribute db:login-timeout { positiveInteger }?
-db-driver-settings =
-  element db:driver-settings {
-    db-driver-settings-attlist,
-    db-auto-increment?,
-    db-delimiter?,
-    db-character-set?,
-    db-table-settings?
-  }
-db-driver-settings-attlist =
-  db-show-deleted
-  & attribute db:system-driver-settings { \string }?
-  & attribute db:base-dn { \string }?
-  & db-is-first-row-header-line
-  & attribute db:parameter-name-substitution { boolean }?
-db-show-deleted = attribute db:show-deleted { boolean }?
-db-is-first-row-header-line =
-  attribute db:is-first-row-header-line { boolean }?
-db-auto-increment =
-  element db:auto-increment { db-auto-increment-attlist, empty }
-db-auto-increment-attlist =
-  attribute db:additional-column-statement { \string }?
-  & attribute db:row-retrieving-statement { \string }?
-db-delimiter = element db:delimiter { db-delimiter-attlist, empty }
-db-delimiter-attlist =
-  attribute db:field { \string }?
-  & attribute db:string { \string }?
-  & attribute db:decimal { \string }?
-  & attribute db:thousand { \string }?
-db-character-set =
-  element db:character-set { db-character-set-attlist, empty }
-db-character-set-attlist = attribute db:encoding { textEncoding }?
-db-table-settings = element db:table-settings { db-table-setting* }
-db-table-setting =
-  element db:table-setting {
-    db-table-setting-attlist, db-delimiter?, db-character-set?, empty
-  }
-db-table-setting-attlist = db-is-first-row-header-line, db-show-deleted
-db-application-connection-settings =
-  element db:application-connection-settings {
-    db-application-connection-settings-attlist,
-    db-table-filter?,
-    db-table-type-filter?,
-    db-data-source-settings?
-  }
-db-application-connection-settings-attlist =
-  attribute db:is-table-name-length-limited { boolean }?
-  & attribute db:enable-sql92-check { boolean }?
-  & attribute db:append-table-alias-name { boolean }?
-  & attribute db:ignore-driver-privileges { boolean }?
-  & attribute db:boolean-comparison-mode {
-      "equal-integer"
-      | "is-boolean"
-      | "equal-boolean"
-      | "equal-use-only-zero"
-    }?
-  & attribute db:use-catalog { boolean }?
-  & attribute db:max-row-count { integer }?
-  & attribute db:suppress-version-columns { boolean }?
-db-table-filter =
-  element db:table-filter {
-    db-table-filter-attlist,
-    db-table-include-filter?,
-    db-table-exclude-filter?
-  }
-db-table-filter-attlist = empty
-db-table-include-filter =
-  element db:table-include-filter {
-    db-table-include-filter-attlist, db-table-filter-pattern+
-  }
-db-table-include-filter-attlist = empty
-db-table-exclude-filter =
-  element db:table-exclude-filter {
-    db-table-exclude-filter-attlist, db-table-filter-pattern+
-  }
-db-table-exclude-filter-attlist = empty
-db-table-filter-pattern =
-  element db:table-filter-pattern {
-    db-table-filter-pattern-attlist, \string
-  }
-db-table-filter-pattern-attlist = empty
-db-table-type-filter =
-  element db:table-type-filter {
-    db-table-type-filter-attlist, db-table-type*
-  }
-db-table-type-filter-attlist = empty
-db-table-type = element db:table-type { db-table-type-attlist, \string }
-db-table-type-attlist = empty
-db-data-source-settings =
-  element db:data-source-settings {
-    db-data-source-settings-attlist, db-data-source-setting+
-  }
-db-data-source-settings-attlist = empty
-db-data-source-setting =
-  element db:data-source-setting {
-    db-data-source-setting-attlist, db-data-source-setting-value+
-  }
-db-data-source-setting-attlist =
-  attribute db:data-source-setting-is-list { boolean }?
-  & attribute db:data-source-setting-name { \string }
-  & attribute db:data-source-setting-type {
-      db-data-source-setting-types
-    }
-db-data-source-setting-types =
-  "boolean" | "short" | "int" | "long" | "double" | "string"
-db-data-source-setting-value =
-  element db:data-source-setting-value {
-    db-data-source-setting-value-attlist, \string
-  }
-db-data-source-setting-value-attlist = empty
-db-forms =
-  element db:forms {
-    db-forms-attlist, (db-component | db-component-collection)*
-  }
-db-forms-attlist = empty
-db-reports =
-  element db:reports {
-    db-reports-attlist, (db-component | db-component-collection)*
-  }
-db-reports-attlist = empty
-db-component-collection =
-  element db:component-collection {
-    db-component-collection-attlist,
-    common-db-object-name,
-    common-db-object-title,
-    common-db-object-description,
-    (db-component | db-component-collection)*
-  }
-db-component-collection-attlist = empty
-db-component =
-  element db:component {
-    db-component-attlist,
-    common-db-object-name,
-    common-db-object-title,
-    common-db-object-description,
-    (office-document | math-math)?
-  }
-db-component-attlist =
-  (attribute xlink:type { "simple" },
-   attribute xlink:href { anyIRI },
-   attribute xlink:show { "none" }?,
-   attribute xlink:actuate { "onRequest" }?)?
-  & attribute db:as-template { boolean }?
-db-queries =
-  element db:queries {
-    db-queries-attlist, (db-query | db-query-collection)*
-  }
-db-queries-attlist = empty
-db-query-collection =
-  element db:query-collection {
-    db-query-collection-attlist,
-    common-db-object-name,
-    common-db-object-title,
-    common-db-object-description,
-    (db-query | db-query-collection)*
-  }
-db-query-collection-attlist = empty
-db-query =
-  element db:query {
-    db-query-attlist,
-    common-db-object-name,
-    common-db-object-title,
-    common-db-object-description,
-    common-db-table-style-name,
-    db-order-statement?,
-    db-filter-statement?,
-    db-columns?,
-    db-update-table?
-  }
-db-query-attlist =
-  attribute db:command { \string }
-  & attribute db:escape-processing { boolean }?
-db-order-statement =
-  element db:order-statement { db-command, db-apply-command, empty }
-db-filter-statement =
-  element db:filter-statement { db-command, db-apply-command, empty }
-db-update-table =
-  element db:update-table { common-db-table-name-attlist }
-db-table-presentations =
-  element db:table-representations {
-    db-table-presentations-attlist, db-table-presentation*
-  }
-db-table-presentations-attlist = empty
-db-table-presentation =
-  element db:table-representation {
-    db-table-presentation-attlist,
-    common-db-table-name-attlist,
-    common-db-object-title,
-    common-db-object-description,
-    common-db-table-style-name,
-    db-order-statement?,
-    db-filter-statement?,
-    db-columns?
-  }
-db-table-presentation-attlist = empty
-db-columns = element db:columns { db-columns-attlist, db-column+ }
-db-columns-attlist = empty
-db-column =
-  element db:column {
-    db-column-attlist,
-    common-db-object-name,
-    common-db-object-title,
-    common-db-object-description,
-    common-db-default-value
-  }
-db-column-attlist =
-  attribute db:visible { boolean }?
-  & attribute db:style-name { styleNameRef }?
-  & attribute db:default-cell-style-name { styleNameRef }?
-db-command = attribute db:command { \string }
-db-apply-command = attribute db:apply-command { boolean }?
-common-db-table-name-attlist =
-  attribute db:name { \string }
-  & attribute db:catalog-name { \string }?
-  & attribute db:schema-name { \string }?
-common-db-object-name = attribute db:name { \string }
-common-db-object-title = attribute db:title { \string }?
-common-db-object-description = attribute db:description { \string }?
-common-db-table-style-name =
-  attribute db:style-name { styleNameRef }?
-  & attribute db:default-row-style-name { styleNameRef }?
-common-db-default-value = common-value-and-type-attlist?
-db-schema-definition =
-  element db:schema-definition {
-    db-schema-definition-attlist, db-table-definitions
-  }
-db-schema-definition-attlist = empty
-db-table-definitions =
-  element db:table-definitions {
-    db-table-definitions-attlist, db-table-definition*
-  }
-db-table-definitions-attlist = empty
-db-table-definition =
-  element db:table-definition {
-    common-db-table-name-attlist,
-    db-table-definition-attlist,
-    db-column-definitions,
-    db-keys?,
-    db-indices?
-  }
-db-table-definition-attlist = attribute db:type { \string }?
-db-column-definitions =
-  element db:column-definitions {
-    db-column-definitions-attlist, db-column-definition+
-  }
-db-column-definitions-attlist = empty
-db-column-definition =
-  element db:column-definition {
-    db-column-definition-attlist, common-db-default-value
-  }
-db-column-definition-attlist =
-  attribute db:name { \string }
-  & attribute db:data-type { db-data-types }?
-  & attribute db:type-name { \string }?
-  & attribute db:precision { positiveInteger }?
-  & attribute db:scale { positiveInteger }?
-  & attribute db:is-nullable { "no-nulls" | "nullable" }?
-  & attribute db:is-empty-allowed { boolean }?
-  & attribute db:is-autoincrement { boolean }?
-db-data-types =
-  "bit"
-  | "boolean"
-  | "tinyint"
-  | "smallint"
-  | "integer"
-  | "bigint"
-  | "float"
-  | "real"
-  | "double"
-  | "numeric"
-  | "decimal"
-  | "char"
-  | "varchar"
-  | "longvarchar"
-  | "date"
-  | "time"
-  | "timestmp"
-  | "binary"
-  | "varbinary"
-  | "longvarbinary"
-  | "sqlnull"
-  | "other"
-  | "object"
-  | "distinct"
-  | "struct"
-  | "array"
-  | "blob"
-  | "clob"
-  | "ref"
-db-keys = element db:keys { db-keys-attlist, db-key+ }
-db-keys-attlist = empty
-db-key = element db:key { db-key-attlist, db-key-columns+ }
-db-key-attlist =
-  attribute db:name { \string }?
-  & attribute db:type { "primary" | "unique" | "foreign" }
-  & attribute db:referenced-table-name { \string }?
-  & attribute db:update-rule {
-      "cascade" | "restrict" | "set-null" | "no-action" | "set-default"
-    }?
-  & attribute db:delete-rule {
-      "cascade" | "restrict" | "set-null" | "no-action" | "set-default"
-    }?
-db-key-columns =
-  element db:key-columns { db-key-columns-attlist, db-key-column+ }
-db-key-columns-attlist = empty
-db-key-column = element db:key-column { db-key-column-attlist, empty }
-db-key-column-attlist =
-  attribute db:name { \string }?
-  & attribute db:related-column-name { \string }?
-db-indices = element db:indices { db-indices-attlist, db-index+ }
-db-indices-attlist = empty
-db-index = element db:index { db-index-attlist, db-index-columns+ }
-db-index-attlist =
-  attribute db:name { \string }
-  & attribute db:catalog-name { \string }?
-  & attribute db:is-unique { boolean }?
-  & attribute db:is-clustered { boolean }?
-db-index-columns = element db:index-columns { db-index-column+ }
-db-index-column =
-  element db:index-column { db-index-column-attlist, empty }
-db-index-column-attlist =
-  attribute db:name { \string }
-  & attribute db:is-ascending { boolean }?
-office-forms =
-  element office:forms {
-    office-forms-attlist, (form-form | xforms-model)*
-  }?
-office-forms-attlist =
-  attribute form:automatic-focus { boolean }?
-  & attribute form:apply-design-mode { boolean }?
-form-form =
-  element form:form {
-    common-form-control-attlist,
-    form-form-attlist,
-    form-properties?,
-    office-event-listeners?,
-    (controls | form-form)*,
-    form-connection-resource?
-  }
-form-form-attlist =
-  (attribute xlink:type { "simple" },
-   attribute xlink:href { anyIRI },
-   attribute xlink:actuate { "onRequest" }?)?
-  & attribute office:target-frame { targetFrameName }?
-  & attribute form:method { "get" | "post" | \string }?
-  & attribute form:enctype { \string }?
-  & attribute form:allow-deletes { boolean }?
-  & attribute form:allow-inserts { boolean }?
-  & attribute form:allow-updates { boolean }?
-  & attribute form:apply-filter { boolean }?
-  & attribute form:command-type { "table" | "query" | "command" }?
-  & attribute form:command { \string }?
-  & attribute form:datasource { anyIRI | \string }?
-  & attribute form:master-fields { \string }?
-  & attribute form:detail-fields { \string }?
-  & attribute form:escape-processing { boolean }?
-  & attribute form:filter { \string }?
-  & attribute form:ignore-result { boolean }?
-  & attribute form:navigation-mode { navigation }?
-  & attribute form:order { \string }?
-  & attribute form:tab-cycle { tab-cycles }?
-navigation = "none" | "current" | "parent"
-tab-cycles = "records" | "current" | "page"
-form-connection-resource =
-  element form:connection-resource {
-    attribute xlink:href { anyIRI },
-    empty
-  }
-xforms-model = element xforms:model { anyAttListOrElements }
-column-controls =
-  element form:text { form-text-attlist, common-form-control-content }
-  | element form:textarea {
-      form-textarea-attlist, common-form-control-content, text-p*
-    }
-  | element form:formatted-text {
-      form-formatted-text-attlist, common-form-control-content
-    }
-  | element form:number {
-      form-number-attlist,
-      common-numeric-control-attlist,
-      common-form-control-content,
-      common-linked-cell,
-      common-spin-button,
-      common-repeat,
-      common-delay-for-repeat
-    }
-  | element form:date {
-      form-date-attlist,
-      common-numeric-control-attlist,
-      common-form-control-content,
-      common-linked-cell,
-      common-spin-button,
-      common-repeat,
-      common-delay-for-repeat
-    }
-  | element form:time {
-      form-time-attlist,
-      common-numeric-control-attlist,
-      common-form-control-content,
-      common-linked-cell,
-      common-spin-button,
-      common-repeat,
-      common-delay-for-repeat
-    }
-  | element form:combobox {
-      form-combobox-attlist, common-form-control-content, form-item*
-    }
-  | element form:listbox {
-      form-listbox-attlist, common-form-control-content, form-option*
-    }
-  | element form:checkbox {
-      form-checkbox-attlist, common-form-control-content
-    }
-controls =
-  column-controls
-  | element form:password {
-      form-password-attlist, common-form-control-content
-    }
-  | element form:file { form-file-attlist, common-form-control-content }
-  | element form:fixed-text {
-      form-fixed-text-attlist, common-form-control-content
-    }
-  | element form:button {
-      form-button-attlist, common-form-control-content
-    }
-  | element form:image {
-      form-image-attlist, common-form-control-content
-    }
-  | element form:radio {
-      form-radio-attlist, common-form-control-content
-    }
-  | element form:frame {
-      form-frame-attlist, common-form-control-content
-    }
-  | element form:image-frame {
-      form-image-frame-attlist, common-form-control-content
-    }
-  | element form:hidden {
-      form-hidden-attlist, common-form-control-content
-    }
-  | element form:grid {
-      form-grid-attlist, common-form-control-content, form-column*
-    }
-  | element form:value-range {
-      form-value-range-attlist, common-form-control-content
-    }
-  | element form:generic-control {
-      form-generic-control-attlist, common-form-control-content
-    }
-form-text-attlist =
-  form-control-attlist,
-  common-current-value-attlist,
-  common-disabled-attlist,
-  common-maxlength-attlist,
-  common-printable-attlist,
-  common-readonly-attlist,
-  common-tab-attlist,
-  common-title-attlist,
-  common-value-attlist,
-  common-convert-empty-attlist,
-  common-data-field-attlist,
-  common-linked-cell
-form-control-attlist =
-  common-form-control-attlist,
-  common-control-id-attlist,
-  xforms-bind-attlist
-common-form-control-content = form-properties?, office-event-listeners?
-form-textarea-attlist =
-  form-control-attlist,
-  common-current-value-attlist,
-  common-disabled-attlist,
-  common-maxlength-attlist,
-  common-printable-attlist,
-  common-readonly-attlist,
-  common-tab-attlist,
-  common-title-attlist,
-  common-value-attlist,
-  common-convert-empty-attlist,
-  common-data-field-attlist,
-  common-linked-cell
-form-password-attlist =
-  form-control-attlist
-  & common-disabled-attlist
-  & common-maxlength-attlist
-  & common-printable-attlist
-  & common-tab-attlist
-  & common-title-attlist
-  & common-value-attlist
-  & common-convert-empty-attlist
-  & common-linked-cell
-  & attribute form:echo-char { character }?
-form-file-attlist =
-  form-control-attlist,
-  common-current-value-attlist,
-  common-disabled-attlist,
-  common-maxlength-attlist,
-  common-printable-attlist,
-  common-readonly-attlist,
-  common-tab-attlist,
-  common-title-attlist,
-  common-value-attlist,
-  common-linked-cell
-form-formatted-text-attlist =
-  form-control-attlist
-  & common-current-value-attlist
-  & common-disabled-attlist
-  & common-maxlength-attlist
-  & common-printable-attlist
-  & common-readonly-attlist
-  & common-tab-attlist
-  & common-title-attlist
-  & common-value-attlist
-  & common-convert-empty-attlist
-  & common-data-field-attlist
-  & common-linked-cell
-  & common-spin-button
-  & common-repeat
-  & common-delay-for-repeat
-  & attribute form:max-value { \string }?
-  & attribute form:min-value { \string }?
-  & attribute form:validation { boolean }?
-common-numeric-control-attlist =
-  form-control-attlist,
-  common-disabled-attlist,
-  common-maxlength-attlist,
-  common-printable-attlist,
-  common-readonly-attlist,
-  common-tab-attlist,
-  common-title-attlist,
-  common-convert-empty-attlist,
-  common-data-field-attlist
-form-number-attlist =
-  attribute form:value { double }?
-  & attribute form:current-value { double }?
-  & attribute form:min-value { double }?
-  & attribute form:max-value { double }?
-form-date-attlist =
-  attribute form:value { date }?
-  & attribute form:current-value { date }?
-  & attribute form:min-value { date }?
-  & attribute form:max-value { date }?
-form-time-attlist =
-  attribute form:value { time }?
-  & attribute form:current-value { time }?
-  & attribute form:min-value { time }?
-  & attribute form:max-value { time }?
-form-fixed-text-attlist =
-  form-control-attlist
-  & for
-  & common-disabled-attlist
-  & label
-  & common-printable-attlist
-  & common-title-attlist
-  & attribute form:multi-line { boolean }?
-form-combobox-attlist =
-  form-control-attlist
-  & common-current-value-attlist
-  & common-disabled-attlist
-  & dropdown
-  & common-maxlength-attlist
-  & common-printable-attlist
-  & common-readonly-attlist
-  & size
-  & common-tab-attlist
-  & common-title-attlist
-  & common-value-attlist
-  & common-convert-empty-attlist
-  & common-data-field-attlist
-  & list-source
-  & list-source-type
-  & common-linked-cell
-  & common-source-cell-range
-  & attribute form:auto-complete { boolean }?
-form-item = element form:item { form-item-attlist, text }
-form-item-attlist = label
-form-listbox-attlist =
-  form-control-attlist
-  & common-disabled-attlist
-  & dropdown
-  & common-printable-attlist
-  & size
-  & common-tab-attlist
-  & common-title-attlist
-  & bound-column
-  & common-data-field-attlist
-  & list-source
-  & list-source-type
-  & common-linked-cell
-  & list-linkage-type
-  & common-source-cell-range
-  & attribute form:multiple { boolean }?
-  & attribute form:xforms-list-source { \string }?
-list-linkage-type =
-  attribute form:list-linkage-type {
-    "selection" | "selection-indices"
-  }?
-form-option = element form:option { form-option-attlist, text }
-form-option-attlist =
-  current-selected, selected, label, common-value-attlist
-form-button-attlist =
-  form-control-attlist
-  & button-type
-  & common-disabled-attlist
-  & label
-  & image-data
-  & common-printable-attlist
-  & common-tab-attlist
-  & target-frame
-  & target-location
-  & common-title-attlist
-  & common-value-attlist
-  & common-form-relative-image-position-attlist
-  & common-repeat
-  & common-delay-for-repeat
-  & attribute form:default-button { boolean }?
-  & attribute form:toggle { boolean }?
-  & attribute form:focus-on-click { boolean }?
-  & attribute form:xforms-submission { \string }?
-form-image-attlist =
-  form-control-attlist,
-  button-type,
-  common-disabled-attlist,
-  image-data,
-  common-printable-attlist,
-  common-tab-attlist,
-  target-frame,
-  target-location,
-  common-title-attlist,
-  common-value-attlist
-form-checkbox-attlist =
-  form-control-attlist
-  & common-disabled-attlist
-  & label
-  & common-printable-attlist
-  & common-tab-attlist
-  & common-title-attlist
-  & common-value-attlist
-  & common-data-field-attlist
-  & common-form-visual-effect-attlist
-  & common-form-relative-image-position-attlist
-  & common-linked-cell
-  & attribute form:current-state { states }?
-  & attribute form:is-tristate { boolean }?
-  & attribute form:state { states }?
-states = "unchecked" | "checked" | "unknown"
-form-radio-attlist =
-  form-control-attlist,
-  current-selected,
-  common-disabled-attlist,
-  label,
-  common-printable-attlist,
-  selected,
-  common-tab-attlist,
-  common-title-attlist,
-  common-value-attlist,
-  common-data-field-attlist,
-  common-form-visual-effect-attlist,
-  common-form-relative-image-position-attlist,
-  common-linked-cell
-form-frame-attlist =
-  form-control-attlist,
-  common-disabled-attlist,
-  for,
-  label,
-  common-printable-attlist,
-  common-title-attlist
-form-image-frame-attlist =
-  form-control-attlist,
-  common-disabled-attlist,
-  image-data,
-  common-printable-attlist,
-  common-readonly-attlist,
-  common-title-attlist,
-  common-data-field-attlist
-form-hidden-attlist = form-control-attlist, common-value-attlist
-form-grid-attlist =
-  form-control-attlist,
-  common-disabled-attlist,
-  common-printable-attlist,
-  common-tab-attlist,
-  common-title-attlist
-form-column =
-  element form:column { form-column-attlist, column-controls+ }
-form-column-attlist =
-  common-form-control-attlist, label, text-style-name
-text-style-name = attribute form:text-style-name { styleNameRef }?
-form-value-range-attlist =
-  form-control-attlist
-  & common-disabled-attlist
-  & common-printable-attlist
-  & common-tab-attlist
-  & common-title-attlist
-  & common-value-attlist
-  & common-linked-cell
-  & common-repeat
-  & common-delay-for-repeat
-  & attribute form:max-value { integer }?
-  & attribute form:min-value { integer }?
-  & attribute form:step-size { positiveInteger }?
-  & attribute form:page-step-size { positiveInteger }?
-  & attribute form:orientation { "horizontal" | "vertical" }?
-form-generic-control-attlist = form-control-attlist
-common-form-control-attlist =
-  attribute form:name { \string }?
-  & attribute form:control-implementation { namespacedToken }?
-xforms-bind-attlist = attribute xforms:bind { \string }?
-types = "submit" | "reset" | "push" | "url"
-button-type = attribute form:button-type { types }?
-common-control-id-attlist =
-  xml-id,
-  attribute form:id { NCName }?
-current-selected = attribute form:current-selected { boolean }?
-common-value-attlist = attribute form:value { \string }?
-common-current-value-attlist = attribute form:current-value { \string }?
-common-disabled-attlist = attribute form:disabled { boolean }?
-dropdown = attribute form:dropdown { boolean }?
-for = attribute form:for { \string }?
-image-data = attribute form:image-data { anyIRI }?
-label = attribute form:label { \string }?
-common-maxlength-attlist =
-  attribute form:max-length { nonNegativeInteger }?
-common-printable-attlist = attribute form:printable { boolean }?
-common-readonly-attlist = attribute form:readonly { boolean }?
-selected = attribute form:selected { boolean }?
-size = attribute form:size { nonNegativeInteger }?
-common-tab-attlist =
-  attribute form:tab-index { nonNegativeInteger }?
-  & attribute form:tab-stop { boolean }?
-target-frame = attribute office:target-frame { targetFrameName }?
-target-location = attribute xlink:href { anyIRI }?
-common-title-attlist = attribute form:title { \string }?
-common-form-visual-effect-attlist =
-  attribute form:visual-effect { "flat" | "3d" }?
-common-form-relative-image-position-attlist =
-  attribute form:image-position { "center" }?
-  | (attribute form:image-position {
-       "start" | "end" | "top" | "bottom"
-     },
-     attribute form:image-align { "start" | "center" | "end" }?)
-bound-column = attribute form:bound-column { \string }?
-common-convert-empty-attlist =
-  attribute form:convert-empty-to-null { boolean }?
-common-data-field-attlist = attribute form:data-field { \string }?
-list-source = attribute form:list-source { \string }?
-list-source-type =
-  attribute form:list-source-type {
-    "table"
-    | "query"
-    | "sql"
-    | "sql-pass-through"
-    | "value-list"
-    | "table-fields"
-  }?
-common-linked-cell =
-  attribute form:linked-cell { cellAddress | \string }?
-common-source-cell-range =
-  attribute form:source-cell-range { cellRangeAddress | \string }?
-common-spin-button = attribute form:spin-button { boolean }?
-common-repeat = attribute form:repeat { boolean }?
-common-delay-for-repeat = attribute form:delay-for-repeat { duration }?
-form-properties = element form:properties { form-property+ }
-form-property =
-  element form:property {
-    form-property-name, form-property-value-and-type-attlist
-  }
-  | element form:list-property {
-      form-property-name, form-property-type-and-value-list
-    }
-form-property-name = attribute form:property-name { \string }
-form-property-value-and-type-attlist =
-  common-value-and-type-attlist
-  | attribute office:value-type { "void" }
-form-property-type-and-value-list =
-  (attribute office:value-type { "float" },
-   element form:list-value {
-     attribute office:value { double }
-   }*)
-  | (attribute office:value-type { "percentage" },
-     element form:list-value {
-       attribute office:value { double }
-     }*)
-  | (attribute office:value-type { "currency" },
-     element form:list-value {
-       attribute office:value { double },
-       attribute office:currency { \string }?
-     }*)
-  | (attribute office:value-type { "date" },
-     element form:list-value {
-       attribute office:date-value { dateOrDateTime }
-     }*)
-  | (attribute office:value-type { "time" },
-     element form:list-value {
-       attribute office:time-value { duration }
-     }*)
-  | (attribute office:value-type { "boolean" },
-     element form:list-value {
-       attribute office:boolean-value { boolean }
-     }*)
-  | (attribute office:value-type { "string" },
-     element form:list-value {
-       attribute office:string-value { \string }
-     }*)
-  | attribute office:value-type { "void" }
-office-annotation =
-  element office:annotation {
-    office-annotation-attlist,
-    draw-caption-attlist,
-    common-draw-position-attlist,
-    common-draw-size-attlist,
-    common-draw-shape-with-text-and-styles-attlist,
-    dc-creator?,
-    dc-date?,
-    meta-date-string?,
-    (text-p | text-list)*
-  }
-office-annotation-end =
-  element office:annotation-end { office-annotation-end-attlist }
-office-annotation-attlist =
-  attribute office:display { boolean }?
-  & common-office-annotation-name-attlist?
-office-annotation-end-attlist = common-office-annotation-name-attlist
-common-office-annotation-name-attlist =
-  attribute office:name { \string }
-meta-date-string = element meta:date-string { \string }
-common-num-format-prefix-suffix-attlist =
-  attribute style:num-prefix { \string }?,
-  attribute style:num-suffix { \string }?
-common-num-format-attlist =
-  attribute style:num-format { "1" | "i" | "I" | \string | empty }
-  | (attribute style:num-format { "a" | "A" },
-     style-num-letter-sync-attlist)
-  | empty
-style-num-letter-sync-attlist =
-  attribute style:num-letter-sync { boolean }?
-office-change-info =
-  element office:change-info { dc-creator, dc-date, text-p* }
-office-event-listeners =
-  element office:event-listeners {
-    (script-event-listener | presentation-event-listener)*
-  }
-script-event-listener =
-  element script:event-listener { script-event-listener-attlist, empty }
-script-event-listener-attlist =
-  attribute script:event-name { \string }
-  & attribute script:language { \string }
-  & (attribute script:macro-name { \string }
-     | (attribute xlink:type { "simple" },
-        attribute xlink:href { anyIRI },
-        attribute xlink:actuate { "onRequest" }?))
-math-math = element math:math { mathMarkup }
-[
-  dc:description [
-    "To avoid inclusion of the complete MathML schema, anything is allowed 
within a math:math top-level element"
-  ]
-]
-mathMarkup =
-  (attribute * { text }
-   | text
-   | element * { mathMarkup })*
-text-dde-connection-decl =
-  element text:dde-connection-decl {
-    text-dde-connection-decl-attlist, common-dde-connection-decl-attlist
-  }
-text-dde-connection-decl-attlist = attribute office:name { \string }
-common-dde-connection-decl-attlist =
-  attribute office:dde-application { \string }
-  & attribute office:dde-topic { \string }
-  & attribute office:dde-item { \string }
-  & attribute office:automatic-update { boolean }?
-table-dde-link =
-  element table:dde-link { office-dde-source, table-table }
-office-dde-source =
-  element office:dde-source {
-    office-dde-source-attlist, common-dde-connection-decl-attlist
-  }
-office-dde-source-attlist =
-  attribute office:name { \string }?
-  & attribute office:conversion-mode {
-      "into-default-style-data-style"
-      | "into-english-number"
-      | "keep-text"
-    }?
-animation-element =
-  element anim:animate {
-    common-anim-target-attlist,
-    common-anim-named-target-attlist,
-    common-anim-values-attlist,
-    common-anim-spline-mode-attlist,
-    common-spline-anim-value-attlist,
-    common-timing-attlist,
-    common-anim-add-accum-attlist
-  }
-  | element anim:set {
-      common-anim-target-attlist,
-      common-anim-named-target-attlist,
-      common-anim-set-values-attlist,
-      common-timing-attlist,
-      common-anim-add-accum-attlist
-    }
-  | element anim:animateMotion {
-      anim-animate-motion-attlist,
-      common-anim-target-attlist,
-      common-anim-named-target-attlist,
-      common-anim-add-accum-attlist,
-      common-anim-values-attlist,
-      common-timing-attlist,
-      common-spline-anim-value-attlist
-    }
-  | element anim:animateColor {
-      common-anim-target-attlist,
-      common-anim-named-target-attlist,
-      common-anim-add-accum-attlist,
-      common-anim-values-attlist,
-      common-anim-spline-mode-attlist,
-      common-spline-anim-value-attlist,
-      anim-animate-color-attlist,
-      common-timing-attlist
-    }
-  | element anim:animateTransform {
-      common-anim-target-attlist,
-      common-anim-named-target-attlist,
-      common-anim-add-accum-attlist,
-      common-anim-values-attlist,
-      anim-animate-transform-attlist,
-      common-timing-attlist
-    }
-  | element anim:transitionFilter {
-      common-anim-target-attlist,
-      common-anim-add-accum-attlist,
-      common-anim-values-attlist,
-      common-anim-spline-mode-attlist,
-      anim-transition-filter-attlist,
-      common-timing-attlist
-    }
-  | element anim:par {
-      common-anim-attlist,
-      common-timing-attlist,
-      common-endsync-timing-attlist,
-      animation-element*
-    }
-  | element anim:seq {
-      common-anim-attlist,
-      common-endsync-timing-attlist,
-      common-timing-attlist,
-      animation-element*
-    }
-  | element anim:iterate {
-      common-anim-attlist,
-      anim-iterate-attlist,
-      common-timing-attlist,
-      common-endsync-timing-attlist,
-      animation-element*
-    }
-  | element anim:audio {
-      common-anim-attlist,
-      anim-audio-attlist,
-      common-basic-timing-attlist
-    }
-  | element anim:command {
-      common-anim-attlist,
-      anim-command-attlist,
-      common-begin-end-timing-attlist,
-      common-anim-target-attlist,
-      element anim:param {
-        attribute anim:name { \string },
-        attribute anim:value { \string }
-      }*
-    }
-anim-animate-motion-attlist =
-  attribute svg:path { pathData }?
-  & attribute svg:origin { \string }?
-  & attribute smil:calcMode {
-      "discrete" | "linear" | "paced" | "spline"
-    }?
-anim-animate-color-attlist =
-  attribute anim:color-interpolation { "rgb" | "hsl" }?
-  & attribute anim:color-interpolation-direction {
-      "clockwise" | "counter-clockwise"
-    }?
-anim-animate-transform-attlist =
-  attribute svg:type {
-    "translate" | "scale" | "rotate" | "skewX" | "skewY"
-  }
-anim-transition-filter-attlist =
-  attribute smil:type { \string }
-  & attribute smil:subtype { \string }?
-  & attribute smil:direction { "forward" | "reverse" }?
-  & attribute smil:fadeColor { color }?
-  & attribute smil:mode { "in" | "out" }?
-common-anim-target-attlist =
-  attribute smil:targetElement { IDREF }?
-  & attribute anim:sub-item { \string }?
-common-anim-named-target-attlist =
-  attribute smil:attributeName { \string }
-common-anim-values-attlist =
-  attribute smil:values { \string }?
-  & attribute anim:formula { \string }?
-  & common-anim-set-values-attlist
-  & attribute smil:from { \string }?
-  & attribute smil:by { \string }?
-common-anim-spline-mode-attlist =
-  attribute smil:calcMode {
-    "discrete" | "linear" | "paced" | "spline"
-  }?
-common-spline-anim-value-attlist =
-  attribute smil:keyTimes { \string }?
-  & attribute smil:keySplines { \string }?
-common-anim-add-accum-attlist =
-  attribute smil:accumulate { "none" | "sum" }?
-  & attribute smil:additive { "replace" | "sum" }?
-common-anim-set-values-attlist = attribute smil:to { \string }?
-common-begin-end-timing-attlist =
-  attribute smil:begin { \string }?
-  & attribute smil:end { \string }?
-common-dur-timing-attlist = attribute smil:dur { \string }?
-common-endsync-timing-attlist =
-  attribute smil:endsync { "first" | "last" | "all" | "media" | IDREF }?
-common-repeat-timing-attlist =
-  attribute smil:repeatDur { \string }?,
-  attribute smil:repeatCount { nonNegativeDecimal | "indefinite" }?
-nonNegativeDecimal = xsd:decimal { minInclusive = "0.0" }
-common-fill-timing-attlist =
-  attribute smil:fill {
-    "remove" | "freeze" | "hold" | "auto" | "default" | "transition"
-  }?
-common-fill-default-attlist =
-  attribute smil:fillDefault {
-    "remove" | "freeze" | "hold" | "transition" | "auto" | "inherit"
-  }?
-common-restart-timing-attlist =
-  attribute smil:restart {
-    "never" | "always" | "whenNotActive" | "default"
-  }?
-common-restart-default-attlist =
-  attribute smil:restartDefault {
-    "never" | "always" | "whenNotActive" | "inherit"
-  }?
-common-time-manip-attlist =
-  attribute smil:accelerate { zeroToOneDecimal }?
-  & attribute smil:decelerate { zeroToOneDecimal }?
-  & attribute smil:autoReverse { boolean }?
-zeroToOneDecimal = xsd:decimal { minInclusive = "0" maxInclusive = "1" }
-common-basic-timing-attlist =
-  common-begin-end-timing-attlist,
-  common-dur-timing-attlist,
-  common-repeat-timing-attlist,
-  common-restart-timing-attlist,
-  common-restart-default-attlist,
-  common-fill-timing-attlist,
-  common-fill-default-attlist
-common-timing-attlist =
-  common-basic-timing-attlist, common-time-manip-attlist
-anim-iterate-attlist =
-  common-anim-target-attlist
-  & attribute anim:iterate-type { \string }?
-  & attribute anim:iterate-interval { duration }?
-anim-audio-attlist =
-  attribute xlink:href { anyIRI }?
-  & attribute anim:audio-level { double }?
-anim-command-attlist = attribute anim:command { \string }
-style-style =
-  element style:style {
-    style-style-attlist, style-style-content, style-map*
-  }
-common-in-content-meta-attlist =
-  attribute xhtml:about { URIorSafeCURIE },
-  attribute xhtml:property { CURIEs },
-  common-meta-literal-attlist
-common-meta-literal-attlist =
-  attribute xhtml:datatype { CURIE }?,
-  attribute xhtml:content { \string }?
-xml-id = attribute xml:id { ID }
-style-style-attlist =
-  attribute style:name { styleName }
-  & attribute style:display-name { \string }?
-  & attribute style:parent-style-name { styleNameRef }?
-  & attribute style:next-style-name { styleNameRef }?
-  & attribute style:list-level { positiveInteger | empty }?
-  & attribute style:list-style-name { styleName | empty }?
-  & attribute style:master-page-name { styleNameRef }?
-  & attribute style:auto-update { boolean }?
-  & attribute style:data-style-name { styleNameRef }?
-  & attribute style:percentage-data-style-name { styleNameRef }?
-  & attribute style:class { \string }?
-  & attribute style:default-outline-level { positiveInteger | empty }?
-style-map = element style:map { style-map-attlist, empty }
-style-map-attlist =
-  attribute style:condition { \string }
-  & attribute style:apply-style-name { styleNameRef }
-  & attribute style:base-cell-address { cellAddress }?
-style-default-style =
-  element style:default-style { style-style-content }
-style-page-layout =
-  element style:page-layout {
-    style-page-layout-attlist, style-page-layout-content
-  }
-style-page-layout-content =
-  style-page-layout-properties?,
-  style-header-style?,
-  style-footer-style?
-style-page-layout-attlist =
-  attribute style:name { styleName }
-  & attribute style:page-usage {
-      "all" | "left" | "right" | "mirrored"
-    }?
-style-header-style =
-  element style:header-style { style-header-footer-properties? }
-style-footer-style =
-  element style:footer-style { style-header-footer-properties? }
-style-default-page-layout =
-  element style:default-page-layout { style-page-layout-content }
-style-master-page =
-  element style:master-page {
-    style-master-page-attlist,
-    (style-header, style-header-left?)?,
-    (style-footer, style-footer-left?)?,
-    draw-layer-set?,
-    office-forms?,
-    shape*,
-    animation-element?,
-    presentation-notes?
-  }
-style-master-page-attlist =
-  attribute style:name { styleName }
-  & attribute style:display-name { \string }?
-  & attribute style:page-layout-name { styleNameRef }
-  & attribute draw:style-name { styleNameRef }?
-  & attribute style:next-style-name { styleNameRef }?
-style-header =
-  element style:header {
-    common-style-header-footer-attlist, header-footer-content
-  }
-style-footer =
-  element style:footer {
-    common-style-header-footer-attlist, header-footer-content
-  }
-style-header-left =
-  element style:header-left {
-    common-style-header-footer-attlist, header-footer-content
-  }
-style-footer-left =
-  element style:footer-left {
-    common-style-header-footer-attlist, header-footer-content
-  }
-header-footer-content =
-  (text-tracked-changes,
-   text-decls,
-   (text-h
-    | text-p
-    | text-list
-    | table-table
-    | text-section
-    | text-table-of-content
-    | text-illustration-index
-    | text-table-index
-    | text-object-index
-    | text-user-index
-    | text-alphabetical-index
-    | text-bibliography
-    | text-index-title
-    | change-marks)*)
-  | (style-region-left?, style-region-center?, style-region-right?)
-common-style-header-footer-attlist =
-  attribute style:display { boolean }?
-style-region-left = element style:region-left { region-content }
-style-region-center = element style:region-center { region-content }
-style-region-right = element style:region-right { region-content }
-region-content = text-p*
-presentation-notes =
-  element presentation:notes {
-    common-presentation-header-footer-attlist,
-    presentation-notes-attlist,
-    office-forms,
-    shape*
-  }
-presentation-notes-attlist =
-  attribute style:page-layout-name { styleNameRef }?
-  & attribute draw:style-name { styleNameRef }?
-table-table-template =
-  element table:table-template {
-    table-table-template-attlist,
-    table-first-row?,
-    table-last-row?,
-    table-first-column?,
-    table-last-column?,
-    table-body,
-    table-even-rows?,
-    table-odd-rows?,
-    table-even-columns?,
-    table-odd-columns?,
-    table-background?
-  }
-table-table-template-attlist =
-  attribute table:name { \string }
-  & attribute table:first-row-start-column { rowOrCol }
-  & attribute table:first-row-end-column { rowOrCol }
-  & attribute table:last-row-start-column { rowOrCol }
-  & attribute table:last-row-end-column { rowOrCol }
-rowOrCol = "row" | "column"
-table-first-row =
-  element table:first-row { common-table-template-attlist, empty }
-table-last-row =
-  element table:last-row { common-table-template-attlist, empty }
-table-first-column =
-  element table:first-column { common-table-template-attlist, empty }
-table-last-column =
-  element table:last-column { common-table-template-attlist, empty }
-table-body = element table:body { common-table-template-attlist, empty }
-table-even-rows =
-  element table:even-rows { common-table-template-attlist, empty }
-table-odd-rows =
-  element table:odd-rows { common-table-template-attlist, empty }
-table-even-columns =
-  element table:even-columns { common-table-template-attlist, empty }
-table-odd-columns =
-  element table:odd-columns { common-table-template-attlist, empty }
-common-table-template-attlist =
-  attribute table:style-name { styleNameRef },
-  attribute table:paragraph-style-name { styleNameRef }?
-table-background =
-  element table:background { table-background-attlist, empty }
-table-background-attlist = attribute table:style-name { styleNameRef }
-style-font-face =
-  element style:font-face {
-    style-font-face-attlist, svg-font-face-src?, svg-definition-src?
-  }
-style-font-face-attlist =
-  attribute svg:font-family { \string }?
-  & attribute svg:font-style { fontStyle }?
-  & attribute svg:font-variant { fontVariant }?
-  & attribute svg:font-weight { fontWeight }?
-  & attribute svg:font-stretch {
-      "normal"
-      | "ultra-condensed"
-      | "extra-condensed"
-      | "condensed"
-      | "semi-condensed"
-      | "semi-expanded"
-      | "expanded"
-      | "extra-expanded"
-      | "ultra-expanded"
-    }?
-  & attribute svg:font-size { positiveLength }?
-  & attribute svg:unicode-range { \string }?
-  & attribute svg:units-per-em { integer }?
-  & attribute svg:panose-1 { \string }?
-  & attribute svg:stemv { integer }?
-  & attribute svg:stemh { integer }?
-  & attribute svg:slope { integer }?
-  & attribute svg:cap-height { integer }?
-  & attribute svg:x-height { integer }?
-  & attribute svg:accent-height { integer }?
-  & attribute svg:ascent { integer }?
-  & attribute svg:descent { integer }?
-  & attribute svg:widths { \string }?
-  & attribute svg:bbox { \string }?
-  & attribute svg:ideographic { integer }?
-  & attribute svg:alphabetic { integer }?
-  & attribute svg:mathematical { integer }?
-  & attribute svg:hanging { integer }?
-  & attribute svg:v-ideographic { integer }?
-  & attribute svg:v-alphabetic { integer }?
-  & attribute svg:v-mathematical { integer }?
-  & attribute svg:v-hanging { integer }?
-  & attribute svg:underline-position { integer }?
-  & attribute svg:underline-thickness { integer }?
-  & attribute svg:strikethrough-position { integer }?
-  & attribute svg:strikethrough-thickness { integer }?
-  & attribute svg:overline-position { integer }?
-  & attribute svg:overline-thickness { integer }?
-  & attribute style:name { \string }
-  & attribute style:font-adornments { \string }?
-  & attribute style:font-family-generic { fontFamilyGeneric }?
-  & attribute style:font-pitch { fontPitch }?
-  & attribute style:font-charset { textEncoding }?
-svg-font-face-src =
-  element svg:font-face-src {
-    (svg-font-face-uri | svg-font-face-name)+
-  }
-svg-font-face-uri =
-  element svg:font-face-uri {
-    common-svg-font-face-xlink-attlist, svg-font-face-format*
-  }
-svg-font-face-format =
-  element svg:font-face-format {
-    attribute svg:string { \string }?,
-    empty
+   attribute xlink:actuate { "onRequest" }?)?
+  & attribute office:target-frame { targetFrameName }?
+  & attribute form:method { "get" | "post" | \string }?
+  & attribute form:enctype { \string }?
+  & attribute form:allow-deletes { boolean }?
+  & attribute form:allow-inserts { boolean }?
+  & attribute form:allow-updates { boolean }?
+  & attribute form:apply-filter { boolean }?
+  & attribute form:command-type { "table" | "query" | "command" }?
+  & attribute form:command { \string }?
+  & attribute form:datasource { anyIRI | \string }?
+  & attribute form:master-fields { \string }?
+  & attribute form:detail-fields { \string }?
+  & attribute form:escape-processing { boolean }?
+  & attribute form:filter { \string }?
+  & attribute form:ignore-result { boolean }?
+  & attribute form:navigation-mode { navigation }?
+  & attribute form:order { \string }?
+  & attribute form:tab-cycle { tab-cycles }?
+form-formatted-text-attlist =
+  form-control-attlist
+  & common-current-value-attlist
+  & common-disabled-attlist
+  & common-maxlength-attlist
+  & common-printable-attlist
+  & common-readonly-attlist
+  & common-tab-attlist
+  & common-title-attlist
+  & common-value-attlist
+  & common-convert-empty-attlist
+  & common-data-field-attlist
+  & common-linked-cell
+  & common-spin-button
+  & common-repeat
+  & common-delay-for-repeat
+  & attribute form:max-value { \string }?
+  & attribute form:min-value { \string }?
+  & attribute form:validation { boolean }?
+form-frame-attlist =
+  form-control-attlist,
+  common-disabled-attlist,
+  for,
+  label,
+  common-printable-attlist,
+  common-title-attlist
+form-generic-control-attlist = form-control-attlist
+form-grid-attlist =
+  form-control-attlist,
+  common-disabled-attlist,
+  common-printable-attlist,
+  common-tab-attlist,
+  common-title-attlist
+form-hidden-attlist = form-control-attlist, common-value-attlist
+form-image-attlist =
+  form-control-attlist,
+  button-type,
+  common-disabled-attlist,
+  image-data,
+  common-printable-attlist,
+  common-tab-attlist,
+  target-frame,
+  target-location,
+  common-title-attlist,
+  common-value-attlist
+form-image-frame-attlist =
+  form-control-attlist,
+  common-disabled-attlist,
+  image-data,
+  common-printable-attlist,
+  common-readonly-attlist,
+  common-title-attlist,
+  common-data-field-attlist
+form-item = element form:item { form-item-attlist, text }
+form-item-attlist = label
+form-listbox-attlist =
+  form-control-attlist
+  & common-disabled-attlist
+  & dropdown
+  & common-printable-attlist
+  & size
+  & common-tab-attlist
+  & common-title-attlist
+  & bound-column
+  & common-data-field-attlist
+  & list-source
+  & list-source-type
+  & common-linked-cell
+  & list-linkage-type
+  & common-source-cell-range
+  & attribute form:multiple { boolean }?
+  & attribute form:xforms-list-source { \string }?
+form-number-attlist =
+  attribute form:value { double }?
+  & attribute form:current-value { double }?
+  & attribute form:min-value { double }?
+  & attribute form:max-value { double }?
+form-option = element form:option { form-option-attlist, text }
+form-option-attlist =
+  current-selected, selected, label, common-value-attlist
+form-password-attlist =
+  form-control-attlist
+  & common-disabled-attlist
+  & common-maxlength-attlist
+  & common-printable-attlist
+  & common-tab-attlist
+  & common-title-attlist
+  & common-value-attlist
+  & common-convert-empty-attlist
+  & common-linked-cell
+  & attribute form:echo-char { character }?
+form-properties = element form:properties { form-property+ }
+form-property =
+  element form:property {
+    form-property-name, form-property-value-and-type-attlist
   }
-svg-font-face-name =
-  element svg:font-face-name {
-    attribute svg:name { \string }?,
-    empty
+  | element form:list-property {
+      form-property-name, form-property-type-and-value-list
+    }
+form-property-name = attribute form:property-name { \string }
+form-property-type-and-value-list =
+  (attribute office:value-type { "float" },
+   element form:list-value {
+     attribute office:value { double }
+   }*)
+  | (attribute office:value-type { "percentage" },
+     element form:list-value {
+       attribute office:value { double }
+     }*)
+  | (attribute office:value-type { "currency" },
+     element form:list-value {
+       attribute office:value { double },
+       attribute office:currency { \string }?
+     }*)
+  | (attribute office:value-type { "date" },
+     element form:list-value {
+       attribute office:date-value { dateOrDateTime }
+     }*)
+  | (attribute office:value-type { "time" },
+     element form:list-value {
+       attribute office:time-value { duration }
+     }*)
+  | (attribute office:value-type { "boolean" },
+     element form:list-value {
+       attribute office:boolean-value { boolean }
+     }*)
+  | (attribute office:value-type { "string" },
+     element form:list-value {
+       attribute office:string-value { \string }
+     }*)
+  | attribute office:value-type { "void" }
+form-property-value-and-type-attlist =
+  common-value-and-type-attlist
+  | attribute office:value-type { "void" }
+form-radio-attlist =
+  form-control-attlist,
+  current-selected,
+  common-disabled-attlist,
+  label,
+  common-printable-attlist,
+  selected,
+  common-tab-attlist,
+  common-title-attlist,
+  common-value-attlist,
+  common-data-field-attlist,
+  common-form-visual-effect-attlist,
+  common-form-relative-image-position-attlist,
+  common-linked-cell
+form-text-attlist =
+  form-control-attlist,
+  common-current-value-attlist,
+  common-disabled-attlist,
+  common-maxlength-attlist,
+  common-printable-attlist,
+  common-readonly-attlist,
+  common-tab-attlist,
+  common-title-attlist,
+  common-value-attlist,
+  common-convert-empty-attlist,
+  common-data-field-attlist,
+  common-linked-cell
+form-textarea-attlist =
+  form-control-attlist,
+  common-current-value-attlist,
+  common-disabled-attlist,
+  common-maxlength-attlist,
+  common-printable-attlist,
+  common-readonly-attlist,
+  common-tab-attlist,
+  common-title-attlist,
+  common-value-attlist,
+  common-convert-empty-attlist,
+  common-data-field-attlist,
+  common-linked-cell
+form-time-attlist =
+  attribute form:value { time }?
+  & attribute form:current-value { time }?
+  & attribute form:min-value { time }?
+  & attribute form:max-value { time }?
+form-value-range-attlist =
+  form-control-attlist
+  & common-disabled-attlist
+  & common-printable-attlist
+  & common-tab-attlist
+  & common-title-attlist
+  & common-value-attlist
+  & common-linked-cell
+  & common-repeat
+  & common-delay-for-repeat
+  & attribute form:max-value { integer }?
+  & attribute form:min-value { integer }?
+  & attribute form:step-size { positiveInteger }?
+  & attribute form:page-step-size { positiveInteger }?
+  & attribute form:orientation { "horizontal" | "vertical" }?
+gradient-style =
+  "linear" | "axial" | "radial" | "ellipsoid" | "square" | "rectangular"
+header-footer-content =
+  (text-tracked-changes,
+   text-decls,
+   (text-h
+    | text-p
+    | text-list
+    | table-table
+    | text-section
+    | text-table-of-content
+    | text-illustration-index
+    | text-table-index
+    | text-object-index
+    | text-user-index
+    | text-alphabetical-index
+    | text-bibliography
+    | text-index-title
+    | change-marks)*)
+  | (style-region-left?, style-region-center?, style-region-right?)
+heading-attrs =
+  attribute text:outline-level { positiveInteger }
+  & attribute text:restart-numbering { boolean }?
+  & attribute text:start-value { nonNegativeInteger }?
+  & attribute text:is-list-header { boolean }?
+horiBackPos = "left" | "center" | "right"
+horizontal-mirror =
+  "horizontal" | "horizontal-on-odd" | "horizontal-on-even"
+image-data = attribute form:image-data { anyIRI }?
+index-content-main = text-content | text-index-title
+integer = xsd:integer
+label = attribute form:label { \string }?
+labelPositions =
+  "avoid-overlap"
+  | "center"
+  | "top"
+  | "top-right"
+  | "right"
+  | "bottom-right"
+  | "bottom"
+  | "bottom-left"
+  | "left"
+  | "top-left"
+  | "inside"
+  | "outside"
+  | "near-origin"
+language = xsd:language
+languageCode = xsd:token { pattern = "[A-Za-z]{1,8}" }
+length =
+  xsd:string {
+    pattern =
+      "-?([0-9]+(\.[0-9]*)?|\.[0-9]+)((cm)|(mm)|(in)|(pt)|(pc)|(px))"
   }
-svg-definition-src =
-  element svg:definition-src {
-    common-svg-font-face-xlink-attlist, empty
+lineMode = "continuous" | "skip-white-space"
+lineStyle =
+  "none"
+  | "solid"
+  | "dotted"
+  | "dash"
+  | "long-dash"
+  | "dot-dash"
+  | "dot-dot-dash"
+  | "wave"
+lineType = "none" | "single" | "double"
+lineWidth =
+  "auto"
+  | "normal"
+  | "bold"
+  | "thin"
+  | "medium"
+  | "thick"
+  | positiveInteger
+  | percent
+  | positiveLength
+list-linkage-type =
+  attribute form:list-linkage-type {
+    "selection" | "selection-indices"
+  }?
+list-source = attribute form:list-source { \string }?
+list-source-type =
+  attribute form:list-source-type {
+    "table"
+    | "query"
+    | "sql"
+    | "sql-pass-through"
+    | "value-list"
+    | "table-fields"
+  }?
+math-math = element math:math { mathMarkup }
+[
+  dc:description [
+    "To avoid inclusion of the complete MathML schema, anything is allowed 
within a math:math top-level element"
+  ]
+]
+mathMarkup =
+  (attribute * { text }
+   | text
+   | element * { mathMarkup })*
+meta-date-string = element meta:date-string { \string }
+namespacedToken = xsd:QName { pattern = "[^:]+:[^:]+" }
+navigation = "none" | "current" | "parent"
+nonNegativeDecimal = xsd:decimal { minInclusive = "0.0" }
+nonNegativeInteger = xsd:nonNegativeInteger
+nonNegativeLength =
+  xsd:string {
+    pattern =
+      "([0-9]+(\.[0-9]*)?|\.[0-9]+)((cm)|(mm)|(in)|(pt)|(pc)|(px))"
   }
-common-svg-font-face-xlink-attlist =
-  attribute xlink:type { "simple" },
-  attribute xlink:href { anyIRI },
-  attribute xlink:actuate { "onRequest" }?
-number-number-style =
-  element number:number-style {
+nonNegativePixelLength =
+  xsd:string { pattern = "([0-9]+(\.[0-9]*)?|\.[0-9]+)(px)" }
+number-am-pm = element number:am-pm { empty }
+number-and-text =
+  number-number,
+  (number-text-with-fillchar?)
+  # https://issues.oasis-open.org/browse/OFFICE-3765
+
+number-boolean = element number:boolean { empty }
+number-boolean-style =
+  element number:boolean-style {
     common-data-style-attlist,
     style-text-properties?,
     number-text?,
-    (any-number, number-text?)?,
+    (number-boolean, number-text?)?,
     style-map*
   }
-any-number = number-number | number-scientific-number | number-fraction
-number-number =
-  element number:number {
-    number-number-attlist,
-    common-decimal-places-attlist,
-    common-number-attlist,
-    number-embedded-text*
-  }
-number-number-attlist =
-  attribute number:decimal-replacement { \string }?
-  & attribute number:display-factor { double }?
-number-embedded-text =
-  element number:embedded-text { number-embedded-text-attlist, text }
-number-embedded-text-attlist = attribute number:position { integer }
-number-scientific-number =
-  element number:scientific-number {
-    number-scientific-number-attlist,
-    common-decimal-places-attlist,
-    common-number-attlist,
-    empty
-  }
-number-scientific-number-attlist =
-  attribute number:min-exponent-digits { integer }?
-number-fraction =
-  element number:fraction {
-    number-fraction-attlist, common-number-attlist, empty
-  }
-number-fraction-attlist =
-  attribute number:min-numerator-digits { integer }?
-  & attribute number:min-denominator-digits { integer }?
-  & attribute number:denominator-value { integer }?
 number-currency-style =
   element number:currency-style {
     common-data-style-attlist,
     common-auto-reorder-attlist,
     style-text-properties?,
-    number-text?,
+    number-text-with-fillchar?,
+    # https://issues.oasis-open.org/browse/OFFICE-3765
     ((number-and-text, currency-symbol-and-text?)
      | (currency-symbol-and-text, number-and-text?))?,
     style-map*
   }
-currency-symbol-and-text = number-currency-symbol, number-text?
-number-and-text = number-number, number-text?
 number-currency-symbol =
-  element number:currency-symbol {
-    number-currency-symbol-attlist, text
-  }
-number-currency-symbol-attlist =
-  attribute number:language { languageCode }?,
-  attribute number:country { countryCode }?,
-  attribute number:script { scriptCode }?,
-  attribute number:rfc-language-tag { language }?
-number-percentage-style =
-  element number:percentage-style {
-    common-data-style-attlist,
-    style-text-properties?,
-    number-text?,
-    number-and-text?,
-    style-map*
+  element number:currency-symbol {
+    number-currency-symbol-attlist, text
   }
+number-currency-symbol-attlist =
+  attribute number:language { languageCode }?,
+  attribute number:country { countryCode }?,
+  attribute number:script { scriptCode }?,
+  attribute number:rfc-language-tag { language }?
 number-date-style =
   element number:date-style {
     common-data-style-attlist,
     common-auto-reorder-attlist,
     common-format-source-attlist,
     style-text-properties?,
-    number-text?,
-    (any-date, number-text?)+,
+    number-text-with-fillchar?,
+    # https://issues.oasis-open.org/browse/OFFICE-3765
+    (any-date,
+     (number-text-with-fillchar?)
+     # https://issues.oasis-open.org/browse/OFFICE-3765
+     )+,
     style-map*
   }
-any-date =
-  number-day
-  | number-month
-  | number-year
-  | number-era
-  | number-day-of-week
-  | number-week-of-year
-  | number-quarter
-  | number-hours
-  | number-am-pm
-  | number-minutes
-  | number-seconds
 number-day =
   element number:day {
     number-day-attlist, common-calendar-attlist, empty
   }
 number-day-attlist = attribute number:style { "short" | "long" }?
+number-day-of-week =
+  element number:day-of-week {
+    number-day-of-week-attlist, common-calendar-attlist, empty
+  }
+number-day-of-week-attlist =
+  attribute number:style { "short" | "long" }?
+number-embedded-text =
+  element number:embedded-text { number-embedded-text-attlist, text }
+number-embedded-text-attlist = attribute number:position { integer }
+number-era =
+  element number:era {
+    number-era-attlist, common-calendar-attlist, empty
+  }
+number-era-attlist = attribute number:style { "short" | "long" }?
+number-fill-character = element number:fill-character { text }
+# https://issues.oasis-open.org/browse/OFFICE-3765
+number-fraction =
+  element number:fraction {
+    number-fraction-attlist, common-number-attlist, empty
+  }
+number-fraction-attlist =
+  attribute number:min-numerator-digits { integer }?
+  & attribute number:min-denominator-digits { integer }?
+  & attribute number:denominator-value { integer }?
+  & (attribute number:max-denominator-value { positiveInteger }?)
+    # https://issues.oasis-open.org/browse/OFFICE-3695 max-denominator-value
+
+number-hours = element number:hours { number-hours-attlist, empty }
+number-hours-attlist = attribute number:style { "short" | "long" }?
+number-minutes =
+  element number:minutes { number-minutes-attlist, empty }
+number-minutes-attlist = attribute number:style { "short" | "long" }?
 number-month =
   element number:month {
     number-month-attlist, common-calendar-attlist, empty
@@ -4704,743 +2587,991 @@ number-month-attlist =
   attribute number:textual { boolean }?
   & attribute number:possessive-form { boolean }?
   & attribute number:style { "short" | "long" }?
-number-year =
-  element number:year {
-    number-year-attlist, common-calendar-attlist, empty
+number-number =
+  element number:number {
+    number-number-attlist,
+    common-decimal-places-attlist,
+    common-number-attlist,
+    number-embedded-text*
   }
-number-year-attlist = attribute number:style { "short" | "long" }?
-number-era =
-  element number:era {
-    number-era-attlist, common-calendar-attlist, empty
+number-number-attlist =
+  attribute number:decimal-replacement { \string }?
+  & attribute number:display-factor { double }?
+number-number-style =
+  element number:number-style {
+    common-data-style-attlist,
+    style-text-properties?,
+    number-text-with-fillchar?,
+    # https://issues.oasis-open.org/browse/OFFICE-3765
+    (any-number, number-text-with-fillchar?)?,
+    # https://issues.oasis-open.org/browse/OFFICE-3765
+    style-map*
   }
-number-era-attlist = attribute number:style { "short" | "long" }?
-number-day-of-week =
-  element number:day-of-week {
-    number-day-of-week-attlist, common-calendar-attlist, empty
+number-percentage-style =
+  element number:percentage-style {
+    common-data-style-attlist,
+    style-text-properties?,
+    number-text-with-fillchar?,
+    # https://issues.oasis-open.org/browse/OFFICE-3765
+    number-and-text?,
+    style-map*
   }
-number-day-of-week-attlist =
-  attribute number:style { "short" | "long" }?
-number-week-of-year =
-  element number:week-of-year { common-calendar-attlist, empty }
 number-quarter =
   element number:quarter {
     number-quarter-attlist, common-calendar-attlist, empty
   }
 number-quarter-attlist = attribute number:style { "short" | "long" }?
-number-time-style =
-  element number:time-style {
-    number-time-style-attlist,
-    common-data-style-attlist,
-    common-format-source-attlist,
-    style-text-properties?,
-    number-text?,
-    (any-time, number-text?)+,
-    style-map*
+number-scientific-number =
+  element number:scientific-number {
+    number-scientific-number-attlist,
+    common-decimal-places-attlist,
+    common-number-attlist,
+    empty
   }
-any-time = number-hours | number-am-pm | number-minutes | number-seconds
-number-time-style-attlist =
-  attribute number:truncate-on-overflow { boolean }?
-number-hours = element number:hours { number-hours-attlist, empty }
-number-hours-attlist = attribute number:style { "short" | "long" }?
-number-minutes =
-  element number:minutes { number-minutes-attlist, empty }
-number-minutes-attlist = attribute number:style { "short" | "long" }?
+number-scientific-number-attlist =
+  attribute number:min-exponent-digits { integer }?
+  & attribute number:exponent-interval { positiveInteger }?
+  & # https://issues.oasis-open.org/browse/OFFICE-1828 exponent-interval
+    attribute number:forced-exponent-sign { boolean }
+    # https://issues.oasis-open.org/browse/OFFICE-3860 added 
number:forced-exponent-sign
+    ?
 number-seconds =
   element number:seconds { number-seconds-attlist, empty }
 number-seconds-attlist =
   attribute number:style { "short" | "long" }?
   & attribute number:decimal-places { integer }?
-number-am-pm = element number:am-pm { empty }
-number-boolean-style =
-  element number:boolean-style {
+number-text = element number:text { text }
+number-text-content = element number:text-content { empty }
+number-text-style =
+  element number:text-style {
     common-data-style-attlist,
     style-text-properties?,
-    number-text?,
-    (number-boolean, number-text?)?,
+    number-text-with-fillchar?,
+    # https://issues.oasis-open.org/browse/OFFICE-3765
+    (number-text-content,
+     (number-text-with-fillchar?)
+     # https://issues.oasis-open.org/browse/OFFICE-3765
+     )*,
     style-map*
   }
-number-boolean = element number:boolean { empty }
-number-text-style =
-  element number:text-style {
+number-text-with-fillchar =
+  number-text?, (number-fill-character, number-text?)?
+# https://issues.oasis-open.org/browse/OFFICE-3765
+number-time-style =
+  element number:time-style {
+    number-time-style-attlist,
     common-data-style-attlist,
+    common-format-source-attlist,
     style-text-properties?,
-    number-text?,
-    (number-text-content, number-text?)*,
+    number-text-with-fillchar?,
+    # https://issues.oasis-open.org/browse/OFFICE-3765
+    (any-time,
+     (number-text-with-fillchar?)
+     # https://issues.oasis-open.org/browse/OFFICE-3765
+     )+,
     style-map*
   }
-number-text = element number:text { text }
-number-text-content = element number:text-content { empty }
-common-data-style-attlist =
-  attribute style:name { styleName }
-  & attribute style:display-name { \string }?
-  & attribute number:language { languageCode }?
-  & attribute number:country { countryCode }?
-  & attribute number:script { scriptCode }?
-  & attribute number:rfc-language-tag { language }?
-  & attribute number:title { \string }?
-  & attribute style:volatile { boolean }?
-  & attribute number:transliteration-format { \string }?
-  & attribute number:transliteration-language { countryCode }?
-  & attribute number:transliteration-country { countryCode }?
-  & attribute number:transliteration-style {
-      "short" | "medium" | "long"
-    }?
-common-auto-reorder-attlist =
-  attribute number:automatic-order { boolean }?
-common-format-source-attlist =
-  attribute number:format-source { "fixed" | "language" }?
-common-decimal-places-attlist =
-  attribute number:decimal-places { integer }?
-common-number-attlist =
-  attribute number:min-integer-digits { integer }?
-  & attribute number:grouping { boolean }?
-common-calendar-attlist =
-  attribute number:calendar {
-    "gregorian"
-    | "gengou"
-    | "ROC"
-    | "hanja_yoil"
-    | "hanja"
-    | "hijri"
-    | "jewish"
-    | "buddhist"
-    | \string
-  }?
-style-style-content =
-  (attribute style:family { "text" },
-   style-text-properties?)
-  | (attribute style:family { "paragraph" },
-     style-paragraph-properties?,
-     style-text-properties?)
-  | (attribute style:family { "section" },
-     style-section-properties?)
-  | (attribute style:family { "ruby" },
-     style-ruby-properties?)
-  | (attribute style:family { "table" },
-     style-table-properties?)
-  | (attribute style:family { "table-column" },
-     style-table-column-properties?)
-  | (attribute style:family { "table-row" },
-     style-table-row-properties?)
-  | (attribute style:family { "table-cell" },
-     style-table-cell-properties?,
-     style-paragraph-properties?,
-     style-text-properties?)
-  | (attribute style:family { "graphic" | "presentation" },
-     style-graphic-properties?,
-     style-paragraph-properties?,
-     style-text-properties?)
-  | (attribute style:family { "drawing-page" },
-     style-drawing-page-properties?)
-  | (attribute style:family { "chart" },
-     style-chart-properties?,
-     style-graphic-properties?,
-     style-paragraph-properties?,
-     style-text-properties?)
-text-linenumbering-configuration =
-  element text:linenumbering-configuration {
-    text-linenumbering-configuration-attlist,
-    text-linenumbering-separator?
+number-time-style-attlist =
+  attribute number:truncate-on-overflow { boolean }?
+number-week-of-year =
+  element number:week-of-year { common-calendar-attlist, empty }
+number-year =
+  element number:year {
+    number-year-attlist, common-calendar-attlist, empty
+  }
+number-year-attlist = attribute number:style { "short" | "long" }?
+office-annotation =
+  element office:annotation {
+    office-annotation-attlist,
+    draw-caption-attlist,
+    common-draw-position-attlist,
+    common-draw-size-attlist,
+    common-draw-shape-with-text-and-styles-attlist,
+    dc-creator?,
+    dc-date?,
+    meta-date-string?,
+    element meta:creator-initials { text }?,
+    # https://issues.oasis-open.org/browse/OFFICE-3776
+    (text-p | text-list)*
+  }
+office-annotation-attlist =
+  attribute office:display { boolean }?
+  & common-office-annotation-name-attlist?
+office-annotation-end =
+  element office:annotation-end { office-annotation-end-attlist }
+office-annotation-end-attlist = common-office-annotation-name-attlist
+office-automatic-styles =
+  element office:automatic-styles { styles & style-page-layout* }?
+office-binary-data = element office:binary-data { base64Binary }
+office-body = element office:body { office-body-content }
+office-body-content =
+  element office:text {
+    office-text-attlist,
+    office-text-content-prelude,
+    office-text-content-main,
+    office-text-content-epilogue
+  }
+  | element office:drawing {
+      office-drawing-attlist,
+      office-drawing-content-prelude,
+      office-drawing-content-main,
+      office-drawing-content-epilogue
+    }
+  | element office:presentation {
+      office-presentation-attlist,
+      office-presentation-content-prelude,
+      office-presentation-content-main,
+      office-presentation-content-epilogue
+    }
+  | element office:spreadsheet {
+      office-spreadsheet-attlist,
+      office-spreadsheet-content-prelude,
+      office-spreadsheet-content-main,
+      office-spreadsheet-content-epilogue
+    }
+  | element office:chart {
+      office-chart-attlist,
+      office-chart-content-prelude,
+      office-chart-content-main,
+      office-chart-content-epilogue
+    }
+  | element office:image {
+      office-image-attlist,
+      office-image-content-prelude,
+      office-image-content-main,
+      office-image-content-epilogue
+    }
+  | office-database
+office-change-info =
+  element office:change-info { dc-creator, dc-date, text-p* }
+office-chart-attlist = empty
+office-chart-content-epilogue = table-functions
+office-chart-content-main = chart-chart
+office-chart-content-prelude = text-decls, table-decls
+office-database =
+  element office:database {
+    db-data-source,
+    db-forms?,
+    db-reports?,
+    db-queries?,
+    db-table-presentations?,
+    db-schema-definition?
   }
-text-linenumbering-configuration-attlist =
-  attribute text:number-lines { boolean }?
-  & common-num-format-attlist?
-  & attribute text:style-name { styleNameRef }?
-  & attribute text:increment { nonNegativeInteger }?
-  & attribute text:number-position {
-      "left" | "right" | "inner" | "outer"
-    }?
-  & attribute text:offset { nonNegativeLength }?
-  & attribute text:count-empty-lines { boolean }?
-  & attribute text:count-in-text-boxes { boolean }?
-  & attribute text:restart-on-page { boolean }?
-text-linenumbering-separator =
-  element text:linenumbering-separator {
-    attribute text:increment { nonNegativeInteger }?,
-    text
+office-dde-source =
+  element office:dde-source {
+    office-dde-source-attlist, common-dde-connection-decl-attlist
   }
-text-notes-configuration =
-  element text:notes-configuration { text-notes-configuration-content }
-text-notes-configuration-content =
-  text-note-class
-  & attribute text:citation-style-name { styleNameRef }?
-  & attribute text:citation-body-style-name { styleNameRef }?
-  & attribute text:default-style-name { styleNameRef }?
-  & attribute text:master-page-name { styleNameRef }?
-  & attribute text:start-value { nonNegativeInteger }?
-  & common-num-format-prefix-suffix-attlist
-  & common-num-format-attlist?
-  & attribute text:start-numbering-at {
-      "document" | "chapter" | "page"
+office-dde-source-attlist =
+  attribute office:name { \string }?
+  & attribute office:conversion-mode {
+      "into-default-style-data-style"
+      | "into-english-number"
+      | "keep-text"
     }?
-  & attribute text:footnotes-position {
-      "text" | "page" | "section" | "document"
+office-document =
+  element office:document {
+    office-document-attrs,
+    office-document-common-attrs,
+    office-meta,
+    office-settings,
+    office-scripts,
+    office-font-face-decls,
+    office-styles,
+    office-automatic-styles,
+    office-master-styles,
+    office-body
+  }
+office-document-attrs = attribute office:mimetype { \string }
+office-document-common-attrs =
+  attribute office:version { "1.3" }
+  & attribute grddl:transformation {
+      list { anyIRI* }
     }?
-  & element text:note-continuation-notice-forward { text }?
-  & element text:note-continuation-notice-backward { text }?
-text-bibliography-configuration =
-  element text:bibliography-configuration {
-    text-bibliography-configuration-attlist, text-sort-key*
+office-document-content =
+  element office:document-content {
+    office-document-common-attrs,
+    office-scripts,
+    office-font-face-decls,
+    office-automatic-styles,
+    office-body
   }
-text-bibliography-configuration-attlist =
-  attribute text:prefix { \string }?
-  & attribute text:suffix { \string }?
-  & attribute text:numbered-entries { boolean }?
-  & attribute text:sort-by-position { boolean }?
-  & attribute fo:language { languageCode }?
-  & attribute fo:country { countryCode }?
-  & attribute fo:script { scriptCode }?
-  & attribute style:rfc-language-tag { language }?
-  & attribute text:sort-algorithm { \string }?
-text-sort-key = element text:sort-key { text-sort-key-attlist, empty }
-text-sort-key-attlist =
-  attribute text:key {
-    "address"
-    | "annote"
-    | "author"
-    | "bibliography-type"
-    | "booktitle"
-    | "chapter"
-    | "custom1"
-    | "custom2"
-    | "custom3"
-    | "custom4"
-    | "custom5"
-    | "edition"
-    | "editor"
-    | "howpublished"
-    | "identifier"
-    | "institution"
-    | "isbn"
-    | "issn"
-    | "journal"
-    | "month"
-    | "note"
-    | "number"
-    | "organizations"
-    | "pages"
-    | "publisher"
-    | "report-type"
-    | "school"
-    | "series"
-    | "title"
-    | "url"
-    | "volume"
-    | "year"
-  },
-  attribute text:sort-ascending { boolean }?
-text-list-style =
-  element text:list-style {
-    text-list-style-attr, text-list-style-content*
+office-document-meta =
+  element office:document-meta {
+    office-document-common-attrs, office-meta
   }
-text-list-style-attr =
-  attribute style:name { styleName }
-  & attribute style:display-name { \string }?
-  & attribute text:consecutive-numbering { boolean }?
-text-list-style-content =
-  element text:list-level-style-number {
-    text-list-level-style-attr,
-    text-list-level-style-number-attr,
-    style-list-level-properties?,
-    style-text-properties?
+office-document-settings =
+  element office:document-settings {
+    office-document-common-attrs, office-settings
+  }
+office-document-styles =
+  element office:document-styles {
+    office-document-common-attrs,
+    office-font-face-decls,
+    office-styles,
+    office-automatic-styles,
+    office-master-styles
+  }
+office-drawing-attlist = empty
+office-drawing-content-epilogue = table-functions
+office-drawing-content-main = draw-page*
+office-drawing-content-prelude = text-decls, table-decls
+office-event-listeners =
+  element office:event-listeners {
+    (script-event-listener | presentation-event-listener)*
+  }
+office-font-face-decls =
+  element office:font-face-decls { style-font-face* }?
+office-forms =
+  element office:forms {
+    office-forms-attlist, (form-form | xforms-model)*
+  }?
+office-forms-attlist =
+  attribute form:automatic-focus { boolean }?
+  & attribute form:apply-design-mode { boolean }?
+office-image-attlist = empty
+office-image-content-epilogue = empty
+office-image-content-main = draw-frame
+office-image-content-prelude = empty
+office-master-styles =
+  element office:master-styles {
+    style-master-page* & style-handout-master? & draw-layer-set?
+  }?
+office-meta = element office:meta { office-meta-content-strict }?
+office-meta-content-strict = office-meta-data*
+office-meta-data =
+  element meta:generator { \string }
+  | element dc:title { \string }
+  | element dc:description { \string }
+  | element dc:subject { \string }
+  | element meta:keyword { \string }
+  | element meta:initial-creator { \string }
+  | dc-creator
+  | element meta:printed-by { \string }
+  | element meta:creation-date { dateTime }
+  | dc-date
+  | element meta:print-date { dateTime }
+  | element meta:template {
+      attribute xlink:type { "simple" },
+      attribute xlink:href { anyIRI },
+      attribute xlink:actuate { "onRequest" }?,
+      attribute xlink:title { \string }?,
+      attribute meta:date { dateTime }?
+    }
+  | element meta:auto-reload {
+      (attribute xlink:type { "simple" },
+       attribute xlink:href { anyIRI },
+       attribute xlink:show { "replace" }?,
+       attribute xlink:actuate { "onLoad" }?)?,
+      attribute meta:delay { duration }?
+    }
+  | element meta:hyperlink-behaviour {
+      attribute office:target-frame-name { targetFrameName }?,
+      attribute xlink:show { "new" | "replace" }?
+    }
+  | element dc:language { language }
+  | element meta:editing-cycles { nonNegativeInteger }
+  | element meta:editing-duration { duration }
+  | element meta:document-statistic {
+      attribute meta:page-count { nonNegativeInteger }?,
+      attribute meta:table-count { nonNegativeInteger }?,
+      attribute meta:draw-count { nonNegativeInteger }?,
+      attribute meta:image-count { nonNegativeInteger }?,
+      attribute meta:ole-object-count { nonNegativeInteger }?,
+      attribute meta:object-count { nonNegativeInteger }?,
+      attribute meta:paragraph-count { nonNegativeInteger }?,
+      attribute meta:word-count { nonNegativeInteger }?,
+      attribute meta:character-count { nonNegativeInteger }?,
+      attribute meta:frame-count { nonNegativeInteger }?,
+      attribute meta:sentence-count { nonNegativeInteger }?,
+      attribute meta:syllable-count { nonNegativeInteger }?,
+      attribute meta:non-whitespace-character-count {
+        nonNegativeInteger
+      }?,
+      attribute meta:row-count { nonNegativeInteger }?,
+      attribute meta:cell-count { nonNegativeInteger }?
+    }
+  | element meta:user-defined {
+      attribute meta:name { \string },
+      ((attribute meta:value-type { "float" },
+        double)
+       | (attribute meta:value-type { "date" },
+          dateOrDateTime)
+       | (attribute meta:value-type { "time" },
+          duration)
+       | (attribute meta:value-type { "boolean" },
+          boolean)
+       | (attribute meta:value-type { "string" },
+          \string)
+       | text)
+    }
+office-presentation-attlist = empty
+office-presentation-content-epilogue =
+  presentation-settings, table-functions
+office-presentation-content-main = draw-page*
+office-presentation-content-prelude =
+  text-decls, table-decls, presentation-decls
+# removed from text as well
+# <rng:define name="office-process-content">
+#   <rng:optional>
+#     <rng:attribute name="office:process-content">
+#       <rng:ref name="boolean"/>
+#     </rng:attribute>
+#   </rng:optional>
+# </rng:define>
+office-script =
+  element office:script {
+    office-script-attlist,
+    mixed { anyElements }
   }
-  | element text:list-level-style-bullet {
-      text-list-level-style-attr,
-      text-list-level-style-bullet-attr,
-      style-list-level-properties?,
-      style-text-properties?
+office-script-attlist = attribute script:language { \string }
+office-scripts =
+  element office:scripts { office-script*, office-event-listeners? }?
+office-settings = element office:settings { config-config-item-set+ }?
+office-spreadsheet-attlist =
+  attribute table:structure-protected { boolean }?,
+  attribute table:protection-key { \string }?,
+  attribute table:protection-key-digest-algorithm { anyIRI }?
+office-spreadsheet-content-epilogue = table-functions
+office-spreadsheet-content-main = table-table*
+office-spreadsheet-content-prelude =
+  table-tracked-changes?, text-decls, table-decls
+office-styles =
+  element office:styles {
+    styles
+    & style-default-style*
+    & style-default-page-layout?
+    & text-outline-style?
+    & text-notes-configuration*
+    & text-bibliography-configuration?
+    & text-linenumbering-configuration?
+    & draw-gradient*
+    & svg-linearGradient*
+    & svg-radialGradient*
+    & draw-hatch*
+    & draw-fill-image*
+    & draw-marker*
+    & draw-stroke-dash*
+    & draw-opacity*
+    & style-presentation-page-layout*
+    & table-table-template*
+  }?
+office-text-attlist =
+  attribute text:global { boolean }?
+  & attribute text:use-soft-page-breaks { boolean }?
+office-text-content-epilogue = table-functions
+office-text-content-main =
+  text-content*
+  | (text-page-sequence, (shape)*)
+office-text-content-prelude =
+  office-forms, text-tracked-changes, text-decls, table-decls
+paragraph-attrs =
+  attribute text:style-name { styleNameRef }?
+  & attribute text:class-names { styleNameRefs }?
+  & attribute text:cond-style-name { styleNameRef }?
+  & (xml-id,
+     attribute text:id { NCName }?)?
+  & common-in-content-meta-attlist?
+paragraph-content =
+  text
+  | element text:s {
+      attribute text:c { nonNegativeInteger }?
+    }
+  | element text:tab { text-tab-attr }
+  | element text:line-break { empty }
+  | text-soft-page-break
+  | element text:span {
+      attribute text:style-name { styleNameRef }?,
+      attribute text:class-names { styleNameRefs }?,
+      paragraph-content-or-hyperlink*
+    }
+  | element text:meta {
+      text-meta-attlist, paragraph-content-or-hyperlink*
+    }
+  | (text-bookmark | text-bookmark-start | text-bookmark-end)
+  | element text:reference-mark {
+      attribute text:name { \string }
+    }
+  | (element text:reference-mark-start {
+       attribute text:name { \string }
+     }
+     | element text:reference-mark-end {
+         attribute text:name { \string }
+       })
+  | element text:note {
+      text-note-class,
+      attribute text:id { \string }?,
+      element text:note-citation {
+        attribute text:label { \string }?,
+        text
+      },
+      element text:note-body { text-content* }
+    }
+  | element text:ruby {
+      attribute text:style-name { styleNameRef }?,
+      element text:ruby-base { paragraph-content-or-hyperlink* },
+      element text:ruby-text {
+        attribute text:style-name { styleNameRef }?,
+        text
+      }
+    }
+  | (office-annotation | office-annotation-end)
+  | change-marks
+  | shape
+  | element text:date { text-date-attlist, text }
+  | element text:time { text-time-attlist, text }
+  | element text:page-number { text-page-number-attlist, text }
+  | element text:page-continuation {
+      text-page-continuation-attlist, text
+    }
+  | element text:sender-firstname { common-field-fixed-attlist, text }
+  | element text:sender-lastname { common-field-fixed-attlist, text }
+  | element text:sender-initials { common-field-fixed-attlist, text }
+  | element text:sender-title { common-field-fixed-attlist, text }
+  | element text:sender-position { common-field-fixed-attlist, text }
+  | element text:sender-email { common-field-fixed-attlist, text }
+  | element text:sender-phone-private {
+      common-field-fixed-attlist, text
+    }
+  | element text:sender-fax { common-field-fixed-attlist, text }
+  | element text:sender-company { common-field-fixed-attlist, text }
+  | element text:sender-phone-work { common-field-fixed-attlist, text }
+  | element text:sender-street { common-field-fixed-attlist, text }
+  | element text:sender-city { common-field-fixed-attlist, text }
+  | element text:sender-postal-code { common-field-fixed-attlist, text }
+  | element text:sender-country { common-field-fixed-attlist, text }
+  | element text:sender-state-or-province {
+      common-field-fixed-attlist, text
+    }
+  | element text:author-name { common-field-fixed-attlist, text }
+  | element text:author-initials { common-field-fixed-attlist, text }
+  | element text:chapter { text-chapter-attlist, text }
+  | element text:file-name { text-file-name-attlist, text }
+  | element text:template-name { text-template-name-attlist, text }
+  | element text:sheet-name { text }
+  | element text:variable-set {
+      (common-field-name-attlist
+       & common-field-formula-attlist
+       & common-value-and-type-attlist
+       & common-field-display-value-none-attlist
+       & common-field-data-style-name-attlist),
+      text
+    }
+  | element text:variable-get {
+      (common-field-name-attlist
+       & common-field-display-value-formula-attlist
+       & common-field-data-style-name-attlist),
+      text
+    }
+  | element text:variable-input {
+      (common-field-name-attlist
+       & common-field-description-attlist
+       & common-value-type-attlist
+       & common-field-display-value-none-attlist
+       & common-field-data-style-name-attlist),
+      text
+    }
+  | element text:user-field-get {
+      (common-field-name-attlist
+       & common-field-display-value-formula-none-attlist
+       & common-field-data-style-name-attlist),
+      text
+    }
+  | element text:user-field-input {
+      (common-field-name-attlist
+       & common-field-description-attlist
+       & common-field-data-style-name-attlist),
+      text
+    }
+  | element text:sequence {
+      (common-field-name-attlist
+       & common-field-formula-attlist
+       & common-field-num-format-attlist
+       & text-sequence-ref-name),
+      text
+    }
+  | element text:expression {
+      (common-field-formula-attlist
+       & common-value-and-type-attlist?
+       & common-field-display-value-formula-attlist
+       & common-field-data-style-name-attlist),
+      text
+    }
+  | element text:text-input { common-field-description-attlist, text }
+  | text-drop-down
+  | # OFFICE-3881
+    element text:initial-creator { common-field-fixed-attlist, text }
+  | element text:creation-date {
+      (common-field-fixed-attlist
+       & common-field-data-style-name-attlist
+       & attribute text:date-value { dateOrDateTime }?),
+      text
+    }
+  | element text:creation-time {
+      (common-field-fixed-attlist
+       & common-field-data-style-name-attlist
+       & attribute text:time-value { timeOrDateTime }?),
+      text
+    }
+  | element text:description { common-field-fixed-attlist, text }
+  | element text:user-defined {
+      (common-field-fixed-attlist
+       & attribute text:name { \string }
+       & common-field-data-style-name-attlist
+       & attribute office:value { double }?
+       & attribute office:date-value { dateOrDateTime }?
+       & attribute office:time-value { duration }?
+       & attribute office:boolean-value { boolean }?
+       & attribute office:string-value { \string }?),
+      text
+    }
+  | element text:print-time {
+      (common-field-fixed-attlist
+       & common-field-data-style-name-attlist
+       & attribute text:time-value { time }?),
+      text
+    }
+  | element text:print-date {
+      (common-field-fixed-attlist
+       & common-field-data-style-name-attlist
+       & attribute text:date-value { date }?),
+      text
+    }
+  | element text:printed-by { common-field-fixed-attlist, text }
+  | element text:title { common-field-fixed-attlist, text }
+  | element text:subject { common-field-fixed-attlist, text }
+  | element text:keywords { common-field-fixed-attlist, text }
+  | element text:editing-cycles { common-field-fixed-attlist, text }
+  | element text:editing-duration {
+      (common-field-fixed-attlist
+       & common-field-data-style-name-attlist
+       & attribute text:duration { duration }?),
+      text
+    }
+  | element text:modification-time {
+      (common-field-fixed-attlist
+       & common-field-data-style-name-attlist
+       & attribute text:time-value { time }?),
+      text
+    }
+  | element text:modification-date {
+      (common-field-fixed-attlist
+       & common-field-data-style-name-attlist
+       & attribute text:date-value { date }?),
+      text
+    }
+  | element text:creator { common-field-fixed-attlist, text }
+  | element text:page-count
+            | text:paragraph-count
+            | text:word-count
+            | text:character-count
+            | text:table-count
+            | text:image-count
+            | text:object-count {
+      common-field-num-format-attlist, text
     }
-  | element text:list-level-style-image {
-      text-list-level-style-attr,
-      text-list-level-style-image-attr,
-      style-list-level-properties?
+  | element text:database-display {
+      text-database-display-attlist, text
     }
-text-list-level-style-number-attr =
-  attribute text:style-name { styleNameRef }?
-  & common-num-format-attlist
-  & common-num-format-prefix-suffix-attlist
-  & attribute text:display-levels { positiveInteger }?
-  & attribute text:start-value { positiveInteger }?
-text-list-level-style-bullet-attr =
-  attribute text:style-name { styleNameRef }?
-  & attribute text:bullet-char { character }
-  & common-num-format-prefix-suffix-attlist
-  & attribute text:bullet-relative-size { percent }?
-text-list-level-style-image-attr =
-  common-draw-data-attlist | office-binary-data
-text-list-level-style-attr = attribute text:level { positiveInteger }
-text-outline-style =
-  element text:outline-style {
-    text-outline-style-attr, text-outline-level-style+
-  }
-text-outline-style-attr = attribute style:name { styleName }
-text-outline-level-style =
-  element text:outline-level-style {
-    text-outline-level-style-attlist,
-    style-list-level-properties?,
-    style-text-properties?
-  }
-text-outline-level-style-attlist =
-  attribute text:level { positiveInteger }
-  & attribute text:style-name { styleNameRef }?
-  & common-num-format-attlist
-  & common-num-format-prefix-suffix-attlist
-  & attribute text:display-levels { positiveInteger }?
-  & attribute text:start-value { positiveInteger }?
-style-graphic-properties =
-  element style:graphic-properties {
-    style-graphic-properties-content-strict
-  }
-style-graphic-properties-content-strict =
-  style-graphic-properties-attlist,
-  style-graphic-fill-properties-attlist,
-  style-graphic-properties-elements
-style-drawing-page-properties =
-  element style:drawing-page-properties {
-    style-drawing-page-properties-content-strict
-  }
-style-drawing-page-properties-content-strict =
-  style-graphic-fill-properties-attlist,
-  style-drawing-page-properties-attlist,
-  style-drawing-page-properties-elements
-draw-gradient =
-  element draw:gradient {
-    common-draw-gradient-attlist, draw-gradient-attlist, empty
-  }
-common-draw-gradient-attlist =
-  attribute draw:name { styleName }?
-  & attribute draw:display-name { \string }?
-  & attribute draw:style { gradient-style }
-  & attribute draw:cx { percent }?
-  & attribute draw:cy { percent }?
-  & attribute draw:angle { angle }?
-  & attribute draw:border { percent }?
-gradient-style =
-  "linear" | "axial" | "radial" | "ellipsoid" | "square" | "rectangular"
-draw-gradient-attlist =
-  attribute draw:start-color { color }?
-  & attribute draw:end-color { color }?
-  & attribute draw:start-intensity { zeroToHundredPercent }?
-  & attribute draw:end-intensity { zeroToHundredPercent }?
-svg-linearGradient =
-  element svg:linearGradient {
-    common-svg-gradient-attlist,
-    attribute svg:x1 { coordinate | percent }?,
-    attribute svg:y1 { coordinate | percent }?,
-    attribute svg:x2 { coordinate | percent }?,
-    attribute svg:y2 { coordinate | percent }?,
-    svg-stop*
-  }
-svg-radialGradient =
-  element svg:radialGradient {
-    common-svg-gradient-attlist,
-    attribute svg:cx { coordinate | percent }?,
-    attribute svg:cy { coordinate | percent }?,
-    attribute svg:r { coordinate | percent }?,
-    attribute svg:fx { coordinate | percent }?,
-    attribute svg:fy { coordinate | percent }?,
-    svg-stop*
-  }
-svg-stop =
-  element svg:stop {
-    attribute svg:offset { double | percent },
-    attribute svg:stop-color { color }?,
-    attribute svg:stop-opacity { double }?
-  }
-common-svg-gradient-attlist =
-  attribute svg:gradientUnits { "objectBoundingBox" }?
-  & attribute svg:gradientTransform { \string }?
-  & attribute svg:spreadMethod { "pad" | "reflect" | "repeat" }?
-  & attribute draw:name { styleName }
-  & attribute draw:display-name { \string }?
-draw-hatch = element draw:hatch { draw-hatch-attlist, empty }
-draw-hatch-attlist =
-  attribute draw:name { styleName }
-  & attribute draw:display-name { \string }?
-  & attribute draw:style { "single" | "double" | "triple" }
-  & attribute draw:color { color }?
-  & attribute draw:distance { length }?
-  & attribute draw:rotation { angle }?
-draw-fill-image =
-  element draw:fill-image {
-    draw-fill-image-attlist,
-    attribute xlink:type { "simple" },
-    attribute xlink:href { anyIRI },
-    attribute xlink:show { "embed" }?,
-    attribute xlink:actuate { "onLoad" }?,
-    empty
-  }
-draw-fill-image-attlist =
-  attribute draw:name { styleName }
-  & attribute draw:display-name { \string }?
-  & attribute svg:width { length }?
-  & attribute svg:height { length }?
-draw-opacity =
-  element draw:opacity {
-    common-draw-gradient-attlist, draw-opacity-attlist, empty
-  }
-draw-opacity-attlist =
-  attribute draw:start { zeroToHundredPercent }?,
-  attribute draw:end { zeroToHundredPercent }?
-draw-marker =
-  element draw:marker {
-    draw-marker-attlist,
-    common-draw-viewbox-attlist,
-    common-draw-path-data-attlist,
-    empty
-  }
-draw-marker-attlist =
-  attribute draw:name { styleName }
-  & attribute draw:display-name { \string }?
-draw-stroke-dash =
-  element draw:stroke-dash { draw-stroke-dash-attlist, empty }
-draw-stroke-dash-attlist =
-  attribute draw:name { styleName }
-  & attribute draw:display-name { \string }?
-  & attribute draw:style { "rect" | "round" }?
-  & attribute draw:dots1 { integer }?
-  & attribute draw:dots1-length { length | percent }?
-  & attribute draw:dots2 { integer }?
-  & attribute draw:dots2-length { length | percent }?
-  & attribute draw:distance { length | percent }?
-style-presentation-page-layout =
-  element style:presentation-page-layout {
-    attribute style:name { styleName },
-    attribute style:display-name { \string }?,
-    presentation-placeholder*
+  | element text:database-next { text-database-next-attlist }
+  | element text:database-row-select {
+      text-database-row-select-attlist
+    }
+  | element text:database-row-number {
+      (common-field-database-table
+       & common-field-num-format-attlist
+       & attribute text:value { nonNegativeInteger }?),
+      text
+    }
+  | element text:database-name { common-field-database-table, text }
+  | element text:page-variable-set {
+      text-set-page-variable-attlist, text
+    }
+  | element text:page-variable-get {
+      text-get-page-variable-attlist, text
+    }
+  | element text:placeholder { text-placeholder-attlist, text }
+  | element text:conditional-text {
+      text-conditional-text-attlist, text
+    }
+  | element text:hidden-text { text-hidden-text-attlist, text }
+  | element text:reference-ref | text:bookmark-ref {
+      text-common-ref-content & text-bookmark-ref-content
+    }
+  | element text:note-ref {
+      text-common-ref-content & text-note-ref-content
+    }
+  | element text:sequence-ref {
+      text-common-ref-content & text-sequence-ref-content
+    }
+  | element text:script {
+      ((attribute xlink:type { "simple" },
+        attribute xlink:href { anyIRI })
+       | text)
+      & attribute script:language { \string }?
+    }
+  | element text:execute-macro {
+      attribute text:name { \string }?,
+      office-event-listeners?,
+      text
+    }
+  | element text:hidden-paragraph {
+      text-hidden-paragraph-attlist, text
+    }
+  | element text:dde-connection {
+      attribute text:connection-name { \string },
+      text
+    }
+  | element text:measure {
+      attribute text:kind { "value" | "unit" | "gap" },
+      text
+    }
+  | element text:table-formula {
+      (common-field-formula-attlist
+       & common-field-display-value-formula-attlist
+       & common-field-data-style-name-attlist),
+      text
+    }
+  | element text:meta-field {
+      text-meta-field-attlist, paragraph-content-or-hyperlink*
+    }
+  | element text:toc-mark-start { text-toc-mark-start-attrs }
+  | element text:toc-mark-end { text-id }
+  | element text:toc-mark {
+      attribute text:string-value { \string },
+      text-outline-level
+    }
+  | element text:user-index-mark-start {
+      text-id, text-outline-level, text-index-name
+    }
+  | element text:user-index-mark-end { text-id }
+  | element text:user-index-mark {
+      attribute text:string-value { \string },
+      text-outline-level,
+      text-index-name
+    }
+  | element text:alphabetical-index-mark-start {
+      text-id, text-alphabetical-index-mark-attrs
+    }
+  | element text:alphabetical-index-mark-end { text-id }
+  | element text:alphabetical-index-mark {
+      attribute text:string-value { \string },
+      text-alphabetical-index-mark-attrs
+    }
+  | element text:bibliography-mark {
+      attribute text:bibliography-type { text-bibliography-types },
+      attribute text:identifier
+                | text:address
+                | text:annote
+                | text:author
+                | text:booktitle
+                | text:chapter
+                | text:edition
+                | text:editor
+                | text:howpublished
+                | text:institution
+                | text:journal
+                | text:month
+                | text:note
+                | text:number
+                | text:organizations
+                | text:pages
+                | text:publisher
+                | text:school
+                | text:series
+                | text:title
+                | text:report-type
+                | text:volume
+                | text:year
+                | text:url
+                | text:custom1
+                | text:custom2
+                | text:custom3
+                | text:custom4
+                | text:custom5
+                | text:isbn
+                | text:issn { \string }*,
+      text
+    }
+  | element presentation:header { empty }
+  | element presentation:footer { empty }
+  | element presentation:date-time { empty }
+paragraph-content-or-hyperlink = paragraph-content | text-a
+pathData = xsd:string
+percent = xsd:string { pattern = "-?([0-9]+(\.[0-9]*)?|\.[0-9]+)%" }
+point3D =
+  xsd:string {
+    pattern =
+      "\([ ]*-?([0-9]+(\.[0-9]*)?|\.[0-9]+)((cm)|(mm)|(in)|(pt)|(pc))([ 
]+-?([0-9]+(\.[0-9]*)?|\.[0-9]+)((cm)|(mm)|(in)|(pt)|(pc))){2}[ ]*\)"
   }
-presentation-placeholder =
-  element presentation:placeholder {
-    attribute presentation:object { presentation-classes },
-    attribute svg:x { coordinate | percent },
-    attribute svg:y { coordinate | percent },
-    attribute svg:width { length | percent },
-    attribute svg:height { length | percent },
-    empty
+points =
+  xsd:string { pattern = "-?[0-9]+,-?[0-9]+([ ]+-?[0-9]+,-?[0-9]+)*" }
+positiveInteger = xsd:positiveInteger
+positiveLength =
+  xsd:string {
+    pattern =
+      
"([0-9]*[1-9][0-9]*(\.[0-9]*)?|0+\.[0-9]*[1-9][0-9]*|\.[0-9]*[1-9][0-9]*)((cm)|(mm)|(in)|(pt)|(pc)|(px))"
   }
-style-page-layout-properties =
-  element style:page-layout-properties {
-    style-page-layout-properties-content-strict
+presentation-animation-elements =
+  presentation-show-shape
+  | presentation-show-text
+  | presentation-hide-shape
+  | presentation-hide-text
+  | presentation-dim
+  | presentation-play
+presentation-animation-group =
+  element presentation:animation-group {
+    presentation-animation-elements*
   }
-style-page-layout-properties-content-strict =
-  style-page-layout-properties-attlist,
-  style-page-layout-properties-elements
-style-page-layout-properties-attlist =
-  attribute fo:page-width { length }?
-  & attribute fo:page-height { length }?
-  & common-num-format-attlist?
-  & common-num-format-prefix-suffix-attlist
-  & attribute style:paper-tray-name { "default" | \string }?
-  & attribute style:print-orientation { "portrait" | "landscape" }?
-  & common-horizontal-margin-attlist
-  & common-vertical-margin-attlist
-  & common-margin-attlist
-  & common-border-attlist
-  & common-border-line-width-attlist
-  & common-padding-attlist
-  & common-shadow-attlist
-  & common-background-color-attlist
-  & attribute style:register-truth-ref-style-name { styleNameRef }?
-  & attribute style:print {
-      list {
-        ("headers"
-         | "grid"
-         | "annotations"
-         | "objects"
-         | "charts"
-         | "drawings"
-         | "formulas"
-         | "zero-values")*
-      }
-    }?
-  & attribute style:print-page-order { "ttb" | "ltr" }?
-  & attribute style:first-page-number { positiveInteger | "continue" }?
-  & attribute style:scale-to { percent }?
-  & attribute style:scale-to-pages { positiveInteger }?
-  & attribute style:table-centering {
-      "horizontal" | "vertical" | "both" | "none"
-    }?
-  & attribute style:footnote-max-height { length }?
-  & common-writing-mode-attlist
-  & attribute style:layout-grid-mode { "none" | "line" | "both" }?
-  & attribute style:layout-grid-standard-mode { boolean }?
-  & attribute style:layout-grid-base-height { length }?
-  & attribute style:layout-grid-ruby-height { length }?
-  & attribute style:layout-grid-lines { positiveInteger }?
-  & attribute style:layout-grid-base-width { length }?
-  & attribute style:layout-grid-color { color }?
-  & attribute style:layout-grid-ruby-below { boolean }?
-  & attribute style:layout-grid-print { boolean }?
-  & attribute style:layout-grid-display { boolean }?
-  & attribute style:layout-grid-snap-to { boolean }?
-style-page-layout-properties-elements =
-  style-background-image & style-columns & style-footnote-sep
-style-footnote-sep =
-  element style:footnote-sep { style-footnote-sep-attlist, empty }?
-style-footnote-sep-attlist =
-  attribute style:width { length }?,
-  attribute style:rel-width { percent }?,
-  attribute style:color { color }?,
-  attribute style:line-style { lineStyle }?,
-  attribute style:adjustment { "left" | "center" | "right" }?,
-  attribute style:distance-before-sep { length }?,
-  attribute style:distance-after-sep { length }?
-style-header-footer-properties =
-  element style:header-footer-properties {
-    style-header-footer-properties-content-strict
+presentation-animations =
+  element presentation:animations {
+    (presentation-animation-elements | presentation-animation-group)*
   }
-style-header-footer-properties-content-strict =
-  style-header-footer-properties-attlist,
-  style-header-footer-properties-elements
-style-header-footer-properties-attlist =
-  attribute svg:height { length }?
-  & attribute fo:min-height { length }?
-  & common-horizontal-margin-attlist
-  & common-vertical-margin-attlist
-  & common-margin-attlist
-  & common-border-attlist
-  & common-border-line-width-attlist
-  & common-padding-attlist
-  & common-background-color-attlist
-  & common-shadow-attlist
-  & attribute style:dynamic-spacing { boolean }?
-style-header-footer-properties-elements = style-background-image
-style-text-properties =
-  element style:text-properties { style-text-properties-content-strict }
-style-text-properties-content-strict =
-  style-text-properties-attlist, style-text-properties-elements
-style-text-properties-elements = empty
-style-text-properties-attlist =
-  attribute fo:font-variant { fontVariant }?
-  & attribute fo:text-transform {
-      "none" | "lowercase" | "uppercase" | "capitalize"
-    }?
-  & attribute fo:color { color }?
-  & attribute style:use-window-font-color { boolean }?
-  & attribute style:text-outline { boolean }?
-  & attribute style:text-line-through-type { lineType }?
-  & attribute style:text-line-through-style { lineStyle }?
-  & attribute style:text-line-through-width { lineWidth }?
-  & attribute style:text-line-through-color { "font-color" | color }?
-  & attribute style:text-line-through-text { \string }?
-  & attribute style:text-line-through-text-style { styleNameRef }?
-  & attribute style:text-position {
-      list { (percent | "super" | "sub"), percent? }
-    }?
-  & attribute style:font-name { \string }?
-  & attribute style:font-name-asian { \string }?
-  & attribute style:font-name-complex { \string }?
-  & attribute fo:font-family { \string }?
-  & attribute style:font-family-asian { \string }?
-  & attribute style:font-family-complex { \string }?
-  & attribute style:font-family-generic { fontFamilyGeneric }?
-  & attribute style:font-family-generic-asian { fontFamilyGeneric }?
-  & attribute style:font-family-generic-complex { fontFamilyGeneric }?
-  & attribute style:font-style-name { \string }?
-  & attribute style:font-style-name-asian { \string }?
-  & attribute style:font-style-name-complex { \string }?
-  & attribute style:font-pitch { fontPitch }?
-  & attribute style:font-pitch-asian { fontPitch }?
-  & attribute style:font-pitch-complex { fontPitch }?
-  & attribute style:font-charset { textEncoding }?
-  & attribute style:font-charset-asian { textEncoding }?
-  & attribute style:font-charset-complex { textEncoding }?
-  & attribute fo:font-size { positiveLength | percent }?
-  & attribute style:font-size-asian { positiveLength | percent }?
-  & attribute style:font-size-complex { positiveLength | percent }?
-  & attribute style:font-size-rel { length }?
-  & attribute style:font-size-rel-asian { length }?
-  & attribute style:font-size-rel-complex { length }?
-  & attribute style:script-type {
-      "latin" | "asian" | "complex" | "ignore"
-    }?
-  & attribute fo:letter-spacing { length | "normal" }?
-  & attribute fo:language { languageCode }?
-  & attribute style:language-asian { languageCode }?
-  & attribute style:language-complex { languageCode }?
-  & attribute fo:country { countryCode }?
-  & attribute style:country-asian { countryCode }?
-  & attribute style:country-complex { countryCode }?
-  & attribute fo:script { scriptCode }?
-  & attribute style:script-asian { scriptCode }?
-  & attribute style:script-complex { scriptCode }?
-  & attribute style:rfc-language-tag { language }?
-  & attribute style:rfc-language-tag-asian { language }?
-  & attribute style:rfc-language-tag-complex { language }?
-  & attribute fo:font-style { fontStyle }?
-  & attribute style:font-style-asian { fontStyle }?
-  & attribute style:font-style-complex { fontStyle }?
-  & attribute style:font-relief { "none" | "embossed" | "engraved" }?
-  & attribute fo:text-shadow { shadowType }?
-  & attribute style:text-underline-type { lineType }?
-  & attribute style:text-underline-style { lineStyle }?
-  & attribute style:text-underline-width { lineWidth }?
-  & attribute style:text-underline-color { "font-color" | color }?
-  & attribute style:text-overline-type { lineType }?
-  & attribute style:text-overline-style { lineStyle }?
-  & attribute style:text-overline-width { lineWidth }?
-  & attribute style:text-overline-color { "font-color" | color }?
-  & attribute style:text-overline-mode { lineMode }?
-  & attribute fo:font-weight { fontWeight }?
-  & attribute style:font-weight-asian { fontWeight }?
-  & attribute style:font-weight-complex { fontWeight }?
-  & attribute style:text-underline-mode { lineMode }?
-  & attribute style:text-line-through-mode { lineMode }?
-  & attribute style:letter-kerning { boolean }?
-  & attribute style:text-blinking { boolean }?
-  & common-background-color-attlist
-  & attribute style:text-combine { "none" | "letters" | "lines" }?
-  & attribute style:text-combine-start-char { character }?
-  & attribute style:text-combine-end-char { character }?
-  & attribute style:text-emphasize {
+presentation-classes =
+  "title"
+  | "outline"
+  | "subtitle"
+  | "text"
+  | "graphic"
+  | "object"
+  | "chart"
+  | "table"
+  | "orgchart"
+  | "page"
+  | "notes"
+  | "handout"
+  | "header"
+  | "footer"
+  | "date-time"
+  | "page-number"
+presentation-date-time-decl-attlist =
+  attribute presentation:name { \string }
+  & attribute presentation:source { "fixed" | "current-date" }
+  & attribute style:data-style-name { styleNameRef }?
+presentation-decl =
+  element presentation:header-decl {
+    presentation-header-decl-attlist, text
+  }
+  | element presentation:footer-decl {
+      presentation-footer-decl-attlist, text
+    }
+  | element presentation:date-time-decl {
+      presentation-date-time-decl-attlist, text
+    }
+presentation-decls = presentation-decl*
+presentation-dim =
+  element presentation:dim {
+    presentation-dim-attlist, presentation-sound?
+  }
+presentation-dim-attlist =
+  attribute draw:shape-id { IDREF }
+  & attribute draw:color { color }
+presentation-event-listener =
+  element presentation:event-listener {
+    presentation-event-listener-attlist, presentation-sound?
+  }
+presentation-event-listener-attlist =
+  attribute script:event-name { \string }
+  & attribute presentation:action {
       "none"
-      | list {
-          ("none" | "accent" | "dot" | "circle" | "disc"),
-          ("above" | "below")
-        }
+      | "previous-page"
+      | "next-page"
+      | "first-page"
+      | "last-page"
+      | "hide"
+      | "stop"
+      | "execute"
+      | "show"
+      | "verb"
+      | "fade-out"
+      | "sound"
+      | "last-visited-page"
+    }
+  & attribute presentation:effect { presentationEffects }?
+  & attribute presentation:direction { presentationEffectDirections }?
+  & attribute presentation:speed { presentationSpeeds }?
+  & attribute presentation:start-scale { percent }?
+  & (attribute xlink:type { "simple" },
+     attribute xlink:href { anyIRI },
+     attribute xlink:show { "embed" }?,
+     attribute xlink:actuate { "onRequest" }?)?
+  & attribute presentation:verb { nonNegativeInteger }?
+presentation-footer-decl-attlist =
+  attribute presentation:name { \string }
+presentation-header-decl-attlist =
+  attribute presentation:name { \string }
+presentation-hide-shape =
+  element presentation:hide-shape {
+    common-presentation-effect-attlist, presentation-sound?
+  }
+presentation-hide-text =
+  element presentation:hide-text {
+    common-presentation-effect-attlist, presentation-sound?
+  }
+presentation-notes =
+  element presentation:notes {
+    common-presentation-header-footer-attlist,
+    presentation-notes-attlist,
+    office-forms,
+    shape*
+  }
+presentation-notes-attlist =
+  attribute style:page-layout-name { styleNameRef }?
+  & attribute draw:style-name { styleNameRef }?
+presentation-placeholder =
+  element presentation:placeholder {
+    attribute presentation:object { presentation-classes },
+    attribute svg:x { coordinate | percent },
+    attribute svg:y { coordinate | percent },
+    attribute svg:width { length | percent },
+    attribute svg:height { length | percent },
+    empty
+  }
+presentation-play =
+  element presentation:play { presentation-play-attlist, empty }
+presentation-play-attlist =
+  attribute draw:shape-id { IDREF },
+  attribute presentation:speed { presentationSpeeds }?
+presentation-settings =
+  element presentation:settings {
+    presentation-settings-attlist, presentation-show*
+  }?
+presentation-settings-attlist =
+  attribute presentation:start-page { \string }?
+  & attribute presentation:show { \string }?
+  & attribute presentation:full-screen { boolean }?
+  & attribute presentation:endless { boolean }?
+  & attribute presentation:pause { duration }?
+  & attribute presentation:show-logo { boolean }?
+  & attribute presentation:force-manual { boolean }?
+  & attribute presentation:mouse-visible { boolean }?
+  & attribute presentation:mouse-as-pen { boolean }?
+  & attribute presentation:start-with-navigator { boolean }?
+  & attribute presentation:animations { "enabled" | "disabled" }?
+  & attribute presentation:transition-on-click {
+      "enabled" | "disabled"
     }?
-  & attribute style:text-scale { percent }?
-  & attribute style:text-rotation-angle { angle }?
-  & attribute style:text-rotation-scale { "fixed" | "line-height" }?
-  & attribute fo:hyphenate { boolean }?
-  & attribute fo:hyphenation-remain-char-count { positiveInteger }?
-  & attribute fo:hyphenation-push-char-count { positiveInteger }?
-  & (attribute text:display { "true" }
-     | attribute text:display { "none" }
-     | (attribute text:display { "condition" },
-        attribute text:condition { "none" })
-     | empty)
-fontVariant = "normal" | "small-caps"
-fontFamilyGeneric =
-  "roman" | "swiss" | "modern" | "decorative" | "script" | "system"
-fontPitch = "fixed" | "variable"
-textEncoding = xsd:string { pattern = "[A-Za-z][A-Za-z0-9._\-]*" }
-fontStyle = "normal" | "italic" | "oblique"
-shadowType = "none" | \string
-lineType = "none" | "single" | "double"
-lineStyle =
+  & attribute presentation:stay-on-top { boolean }?
+  & attribute presentation:show-end-of-presentation-slide { boolean }?
+presentation-shape-attlist =
+  attribute presentation:class { presentation-classes }?
+  & attribute presentation:placeholder { boolean }?
+  & attribute presentation:user-transformed { boolean }?
+presentation-show =
+  element presentation:show { presentation-show-attlist, empty }
+presentation-show-attlist =
+  attribute presentation:name { \string }
+  & attribute presentation:pages { \string }
+presentation-show-shape =
+  element presentation:show-shape {
+    common-presentation-effect-attlist, presentation-sound?
+  }
+presentation-show-text =
+  element presentation:show-text {
+    common-presentation-effect-attlist, presentation-sound?
+  }
+presentation-sound =
+  element presentation:sound {
+    presentation-sound-attlist,
+    attribute xlink:type { "simple" },
+    attribute xlink:href { anyIRI },
+    attribute xlink:actuate { "onRequest" }?,
+    attribute xlink:show { "new" | "replace" }?,
+    empty
+  }
+presentation-sound-attlist =
+  attribute presentation:play-full { boolean }?
+  & xml-id?
+presentationEffectDirections =
   "none"
-  | "solid"
-  | "dotted"
-  | "dash"
-  | "long-dash"
-  | "dot-dash"
-  | "dot-dot-dash"
-  | "wave"
-lineWidth =
-  "auto"
-  | "normal"
-  | "bold"
-  | "thin"
-  | "medium"
-  | "thick"
-  | positiveInteger
-  | percent
-  | positiveLength
-fontWeight =
-  "normal"
-  | "bold"
-  | "100"
-  | "200"
-  | "300"
-  | "400"
-  | "500"
-  | "600"
-  | "700"
-  | "800"
-  | "900"
-lineMode = "continuous" | "skip-white-space"
-style-paragraph-properties =
-  element style:paragraph-properties {
-    style-paragraph-properties-content-strict
+  | "from-left"
+  | "from-top"
+  | "from-right"
+  | "from-bottom"
+  | "from-center"
+  | "from-upper-left"
+  | "from-upper-right"
+  | "from-lower-left"
+  | "from-lower-right"
+  | "to-left"
+  | "to-top"
+  | "to-right"
+  | "to-bottom"
+  | "to-upper-left"
+  | "to-upper-right"
+  | "to-lower-right"
+  | "to-lower-left"
+  | "path"
+  | "spiral-inward-left"
+  | "spiral-inward-right"
+  | "spiral-outward-left"
+  | "spiral-outward-right"
+  | "vertical"
+  | "horizontal"
+  | "to-center"
+  | "clockwise"
+  | "counter-clockwise"
+presentationEffects =
+  "none"
+  | "fade"
+  | "move"
+  | "stripes"
+  | "open"
+  | "close"
+  | "dissolve"
+  | "wavyline"
+  | "random"
+  | "lines"
+  | "laser"
+  | "appear"
+  | "hide"
+  | "move-short"
+  | "checkerboard"
+  | "rotate"
+  | "stretch"
+presentationSpeeds = "slow" | "medium" | "fast"
+region-content = text-p*
+relativeLength = xsd:string { pattern = "[0-9]+\*" }
+rowOrCol = "row" | "column"
+script-event-listener =
+  element script:event-listener { script-event-listener-attlist, empty }
+script-event-listener-attlist =
+  attribute script:event-name { \string }
+  & attribute script:language { \string }
+  & (attribute script:macro-name { \string }
+     | (attribute xlink:type { "simple" },
+        attribute xlink:href { anyIRI },
+        attribute xlink:actuate { "onRequest" }?))
+scriptCode = xsd:token { pattern = "[A-Za-z0-9]{1,8}" }
+selected = attribute form:selected { boolean }?
+shadowType = "none" | \string
+shape = shape-instance | draw-a
+shape-instance =
+  draw-rect
+  | draw-line
+  | draw-polyline
+  | draw-polygon
+  | draw-regular-polygon
+  | draw-path
+  | draw-circle
+  | draw-ellipse
+  | draw-g
+  | draw-page-thumbnail
+  | draw-frame
+  | draw-measure
+  | draw-caption
+  | draw-connector
+  | draw-control
+  | dr3d-scene
+  | draw-custom-shape
+shapes3d =
+  dr3d-scene | dr3d-extrude | dr3d-sphere | dr3d-rotate | dr3d-cube
+signedZeroToHundredPercent =
+  xsd:string {
+    pattern = "-?([0-9]?[0-9](\.[0-9]*)?|100(\.0*)?|\.[0-9]+)%"
   }
-style-paragraph-properties-content-strict =
-  style-paragraph-properties-attlist,
-  style-paragraph-properties-elements
-style-paragraph-properties-attlist =
-  attribute fo:line-height { "normal" | nonNegativeLength | percent }?
-  & attribute style:line-height-at-least { nonNegativeLength }?
-  & attribute style:line-spacing { length }?
-  & attribute style:font-independent-line-spacing { boolean }?
-  & common-text-align
-  & attribute fo:text-align-last { "start" | "center" | "justify" }?
-  & attribute style:justify-single-word { boolean }?
-  & attribute fo:keep-together { "auto" | "always" }?
-  & attribute fo:widows { nonNegativeInteger }?
-  & attribute fo:orphans { nonNegativeInteger }?
-  & attribute style:tab-stop-distance { nonNegativeLength }?
-  & attribute fo:hyphenation-keep { "auto" | "page" }?
-  & attribute fo:hyphenation-ladder-count {
-      "no-limit" | positiveInteger
-    }?
-  & attribute style:register-true { boolean }?
-  & common-horizontal-margin-attlist
-  & attribute fo:text-indent { length | percent }?
-  & attribute style:auto-text-indent { boolean }?
-  & common-vertical-margin-attlist
-  & common-margin-attlist
-  & common-break-attlist
-  & common-background-color-attlist
-  & common-border-attlist
-  & common-border-line-width-attlist
-  & attribute style:join-border { boolean }?
-  & common-padding-attlist
-  & common-shadow-attlist
-  & common-keep-with-next-attlist
-  & attribute text:number-lines { boolean }?
-  & attribute text:line-number { nonNegativeInteger }?
-  & attribute style:text-autospace { "none" | "ideograph-alpha" }?
-  & attribute style:punctuation-wrap { "simple" | "hanging" }?
-  & attribute style:line-break { "normal" | "strict" }?
-  & attribute style:vertical-align {
-      "top" | "middle" | "bottom" | "auto" | "baseline"
-    }?
-  & common-writing-mode-attlist
-  & attribute style:writing-mode-automatic { boolean }?
-  & attribute style:snap-to-layout-grid { boolean }?
-  & common-page-number-attlist
-  & common-background-transparency-attlist
-common-text-align =
-  attribute fo:text-align {
-    "start" | "end" | "left" | "right" | "center" | "justify"
-  }?
-style-paragraph-properties-elements =
-  style-tab-stops & style-drop-cap & style-background-image
-style-tab-stops = element style:tab-stops { style-tab-stop* }?
-style-tab-stop =
-  element style:tab-stop { style-tab-stop-attlist, empty }
-style-tab-stop-attlist =
-  attribute style:position { length }
-  & (attribute style:type { "left" | "center" | "right" }?
-     | (attribute style:type { "char" },
-        style-tab-stop-char-attlist))
-  & attribute style:leader-type { lineType }?
-  & attribute style:leader-style { lineStyle }?
-  & attribute style:leader-width { lineWidth }?
-  & attribute style:leader-color { "font-color" | color }?
-  & attribute style:leader-text { character }?
-  & attribute style:leader-text-style { styleNameRef }?
-style-tab-stop-char-attlist = attribute style:char { character }
-style-drop-cap =
-  element style:drop-cap { style-drop-cap-attlist, empty }?
-style-drop-cap-attlist =
-  attribute style:length { "word" | positiveInteger }?
-  & attribute style:lines { positiveInteger }?
-  & attribute style:distance { length }?
-  & attribute style:style-name { styleNameRef }?
-common-horizontal-margin-attlist =
-  attribute fo:margin-left { length | percent }?,
-  attribute fo:margin-right { length | percent }?
-common-vertical-margin-attlist =
-  attribute fo:margin-top { nonNegativeLength | percent }?,
-  attribute fo:margin-bottom { nonNegativeLength | percent }?
-common-margin-attlist =
-  attribute fo:margin { nonNegativeLength | percent }?
-common-break-attlist =
-  attribute fo:break-before { "auto" | "column" | "page" }?,
-  attribute fo:break-after { "auto" | "column" | "page" }?
-common-background-color-attlist =
-  attribute fo:background-color { "transparent" | color }?
+size = attribute form:size { nonNegativeInteger }?
+states = "unchecked" | "checked" | "unknown"
+\string = xsd:string
 style-background-image =
   element style:background-image {
     style-background-image-attlist,
@@ -5459,74 +3590,159 @@ style-background-image-attlist =
     }?
   & attribute style:filter-name { \string }?
   & attribute draw:opacity { zeroToHundredPercent }?
-horiBackPos = "left" | "center" | "right"
-vertBackPos = "top" | "center" | "bottom"
-common-border-attlist =
-  attribute fo:border { \string }?,
-  attribute fo:border-top { \string }?,
-  attribute fo:border-bottom { \string }?,
-  attribute fo:border-left { \string }?,
-  attribute fo:border-right { \string }?
-common-border-line-width-attlist =
-  attribute style:border-line-width { borderWidths }?,
-  attribute style:border-line-width-top { borderWidths }?,
-  attribute style:border-line-width-bottom { borderWidths }?,
-  attribute style:border-line-width-left { borderWidths }?,
-  attribute style:border-line-width-right { borderWidths }?
-borderWidths = list { positiveLength, positiveLength, positiveLength }
-common-padding-attlist =
-  attribute fo:padding { nonNegativeLength }?,
-  attribute fo:padding-top { nonNegativeLength }?,
-  attribute fo:padding-bottom { nonNegativeLength }?,
-  attribute fo:padding-left { nonNegativeLength }?,
-  attribute fo:padding-right { nonNegativeLength }?
-common-shadow-attlist = attribute style:shadow { shadowType }?
-common-keep-with-next-attlist =
-  attribute fo:keep-with-next { "auto" | "always" }?
-common-writing-mode-attlist =
-  attribute style:writing-mode {
-    "lr-tb" | "rl-tb" | "tb-rl" | "tb-lr" | "lr" | "rl" | "tb" | "page"
-  }?
-common-page-number-attlist =
-  attribute style:page-number { positiveInteger | "auto" }?
-common-background-transparency-attlist =
-  attribute style:background-transparency { zeroToHundredPercent }?
-style-ruby-properties =
-  element style:ruby-properties { style-ruby-properties-content-strict }
-style-ruby-properties-content-strict =
-  style-ruby-properties-attlist, style-ruby-properties-elements
-style-ruby-properties-elements = empty
-style-ruby-properties-attlist =
-  attribute style:ruby-position { "above" | "below" }?
-  & attribute style:ruby-align {
-      "left"
-      | "center"
-      | "right"
-      | "distribute-letter"
-      | "distribute-space"
+style-chart-properties =
+  element style:chart-properties {
+    style-chart-properties-content-strict
+  }
+style-chart-properties-attlist =
+  attribute chart:scale-text { boolean }?
+  & attribute chart:three-dimensional { boolean }?
+  & attribute chart:deep { boolean }?
+  & attribute chart:right-angled-axes { boolean }?
+  & (attribute chart:symbol-type { "none" }
+     | attribute chart:symbol-type { "automatic" }
+     | (attribute chart:symbol-type { "named-symbol" },
+        attribute chart:symbol-name {
+          "square"
+          | "diamond"
+          | "arrow-down"
+          | "arrow-up"
+          | "arrow-right"
+          | "arrow-left"
+          | "bow-tie"
+          | "hourglass"
+          | "circle"
+          | "star"
+          | "x"
+          | "plus"
+          | "asterisk"
+          | "horizontal-bar"
+          | "vertical-bar"
+        })
+     | (attribute chart:symbol-type { "image" },
+        element chart:symbol-image {
+          attribute xlink:href { anyIRI }
+        })
+     | empty)
+  & attribute chart:symbol-width { nonNegativeLength }?
+  & attribute chart:symbol-height { nonNegativeLength }?
+  & attribute chart:sort-by-x-values { boolean }?
+  & attribute chart:vertical { boolean }?
+  & attribute chart:connect-bars { boolean }?
+  & attribute chart:gap-width { integer }?
+  & attribute chart:overlap { integer }?
+  & attribute chart:group-bars-per-axis { boolean }?
+  & attribute chart:japanese-candle-stick { boolean }?
+  & attribute chart:interpolation {
+      "none"
+      | "cubic-spline"
+      | "b-spline"
+      | "step-start"
+      | "step-end"
+      | "step-center-x"
+      | "step-center-y"
+    }?
+  & attribute chart:spline-order { positiveInteger }?
+  & attribute chart:spline-resolution { positiveInteger }?
+  & attribute chart:pie-offset { nonNegativeInteger }?
+  & attribute chart:angle-offset { angle }?
+  & attribute chart:hole-size { percent }?
+  & attribute chart:lines { boolean }?
+  & attribute chart:solid-type {
+      "cuboid" | "cylinder" | "cone" | "pyramid"
+    }?
+  & attribute chart:stacked { boolean }?
+  & attribute chart:percentage { boolean }?
+  & attribute chart:treat-empty-cells {
+      "use-zero" | "leave-gap" | "ignore"
+    }?
+  & attribute chart:link-data-style-to-source { boolean }?
+  & attribute chart:logarithmic { boolean }?
+  & attribute chart:maximum { double }?
+  & attribute chart:minimum { double }?
+  & attribute chart:origin { double }?
+  & attribute chart:interval-major { double }?
+  & attribute chart:interval-minor-divisor { positiveInteger }?
+  & attribute chart:tick-marks-major-inner { boolean }?
+  & attribute chart:tick-marks-major-outer { boolean }?
+  & attribute chart:tick-marks-minor-inner { boolean }?
+  & attribute chart:tick-marks-minor-outer { boolean }?
+  & attribute chart:reverse-direction { boolean }?
+  & attribute chart:display-label { boolean }?
+  & attribute chart:text-overlap { boolean }?
+  & attribute text:line-break { boolean }?
+  & attribute chart:label-arrangement {
+      "side-by-side" | "stagger-even" | "stagger-odd"
+    }?
+  & common-style-direction-attlist
+  & common-rotation-angle-attlist
+  & attribute chart:data-label-number {
+      "none" | "value" | "percentage" | "value-and-percentage"
+    }?
+  & attribute chart:data-label-text { boolean }?
+  & attribute chart:data-label-symbol { boolean }?
+  & element chart:label-separator { text-p }?
+  & attribute chart:label-position { labelPositions }?
+  & attribute chart:label-position-negative { labelPositions }?
+  & attribute chart:visible { boolean }?
+  & attribute chart:auto-position { boolean }?
+  & attribute chart:auto-size { boolean }?
+  & attribute chart:mean-value { boolean }?
+  & attribute chart:error-category {
+      "none"
+      | "variance"
+      | "standard-deviation"
+      | "percentage"
+      | "error-margin"
+      | "constant"
+      | "standard-error"
+      | "cell-range"
+    }?
+  & attribute chart:error-percentage { double }?
+  & attribute chart:error-margin { double }?
+  & attribute chart:error-lower-limit { double }?
+  & attribute chart:error-upper-limit { double }?
+  & attribute chart:error-upper-indicator { boolean }?
+  & attribute chart:error-lower-indicator { boolean }?
+  & attribute chart:error-lower-range { cellRangeAddressList }?
+  & attribute chart:error-upper-range { cellRangeAddressList }?
+  & attribute chart:series-source { "columns" | "rows" }?
+  & attribute chart:regression-type {
+      "none"
+      | "linear"
+      | "logarithmic"
+      | "moving-average"
+      | "exponential"
+      | "power"
+      | "polynomial"
     }?
-style-section-properties =
-  element style:section-properties {
-    style-section-properties-content-strict
-  }
-style-section-properties-content-strict =
-  style-section-properties-attlist, style-section-properties-elements
-style-section-properties-attlist =
-  common-background-color-attlist
-  & common-horizontal-margin-attlist
-  & attribute style:protect { boolean }?
-  & common-editable-attlist
-  & attribute text:dont-balance-text-columns { boolean }?
-  & common-writing-mode-attlist
-style-section-properties-elements =
-  style-background-image & style-columns & text-notes-configuration*
-style-columns =
-  element style:columns {
-    style-columns-attlist, style-column-sep?, style-column*
-  }?
-style-columns-attlist =
-  attribute fo:column-count { positiveInteger }
-  & attribute fo:column-gap { length }?
+  & attribute chart:regression-max-degree { positiveInteger }?
+  & attribute chart:regression-force-intercept { boolean }?
+  & attribute chart:regression-intercept-value { double }?
+  & attribute chart:regression-name { \string }?
+  & # https://issues.oasis-open.org/browse/OFFICE-3958
+    attribute chart:regression-period { positiveInteger }?
+  & attribute chart:regression-moving-type {
+      "prior" | "central" | "averaged-abscissa"
+    }?
+  & # https://issues.oasis-open.org/browse/OFFICE-3959
+    attribute chart:axis-position { "start" | "end" | double }?
+  & attribute chart:axis-label-position {
+      "near-axis"
+      | "near-axis-other-side"
+      | "outside-start"
+      | "outside-end"
+    }?
+  & attribute chart:tick-mark-position {
+      "at-labels" | "at-axis" | "at-labels-and-axis"
+    }?
+  & attribute chart:include-hidden-cells { boolean }?
+  & (attribute chart:data-label-series { boolean }?)
+    # https://issues.oasis-open.org/browse/OFFICE-2117
+
+style-chart-properties-content-strict =
+  style-chart-properties-attlist, style-chart-properties-elements
+style-chart-properties-elements = empty
 style-column = element style:column { style-column-attlist }
 style-column-attlist =
   attribute style:rel-width { relativeLength }
@@ -5543,132 +3759,235 @@ style-column-sep-attlist =
   & attribute style:height { zeroToHundredPercent }?
   & attribute style:vertical-align { "top" | "middle" | "bottom" }?
   & attribute style:color { color }?
-style-table-properties =
-  element style:table-properties {
-    style-table-properties-content-strict
-  }
-style-table-properties-content-strict =
-  style-table-properties-attlist, style-table-properties-elements
-style-table-properties-attlist =
-  attribute style:width { positiveLength }?
-  & attribute style:rel-width { percent }?
-  & attribute table:align { "left" | "center" | "right" | "margins" }?
-  & common-horizontal-margin-attlist
-  & common-vertical-margin-attlist
-  & common-margin-attlist
-  & common-page-number-attlist
-  & common-break-attlist
-  & common-background-color-attlist
-  & common-shadow-attlist
-  & common-keep-with-next-attlist
-  & attribute style:may-break-between-rows { boolean }?
-  & attribute table:border-model { "collapsing" | "separating" }?
-  & common-writing-mode-attlist
-  & attribute table:display { boolean }?
-style-table-properties-elements = style-background-image
-style-table-column-properties =
-  element style:table-column-properties {
-    style-table-column-properties-content-strict
+style-columns =
+  element style:columns {
+    style-columns-attlist, style-column-sep?, style-column*
+  }?
+style-columns-attlist =
+  attribute fo:column-count { positiveInteger }
+  & attribute fo:column-gap { length }?
+style-default-page-layout =
+  element style:default-page-layout { style-page-layout-content }
+style-default-style =
+  element style:default-style { style-style-content }
+style-drawing-page-properties =
+  element style:drawing-page-properties {
+    style-drawing-page-properties-content-strict
   }
-style-table-column-properties-content-strict =
-  style-table-column-properties-attlist,
-  style-table-column-properties-elements
-style-table-column-properties-elements = empty
-style-table-column-properties-attlist =
-  attribute style:column-width { positiveLength }?
-  & attribute style:rel-column-width { relativeLength }?
-  & attribute style:use-optimal-column-width { boolean }?
-  & common-break-attlist
-style-table-row-properties =
-  element style:table-row-properties {
-    style-table-row-properties-content-strict
+style-drawing-page-properties-attlist =
+  attribute presentation:transition-type {
+    "manual" | "automatic" | "semi-automatic"
+  }?
+  & attribute presentation:transition-style {
+      "none"
+      | "fade-from-left"
+      | "fade-from-top"
+      | "fade-from-right"
+      | "fade-from-bottom"
+      | "fade-from-upperleft"
+      | "fade-from-upperright"
+      | "fade-from-lowerleft"
+      | "fade-from-lowerright"
+      | "move-from-left"
+      | "move-from-top"
+      | "move-from-right"
+      | "move-from-bottom"
+      | "move-from-upperleft"
+      | "move-from-upperright"
+      | "move-from-lowerleft"
+      | "move-from-lowerright"
+      | "uncover-to-left"
+      | "uncover-to-top"
+      | "uncover-to-right"
+      | "uncover-to-bottom"
+      | "uncover-to-upperleft"
+      | "uncover-to-upperright"
+      | "uncover-to-lowerleft"
+      | "uncover-to-lowerright"
+      | "fade-to-center"
+      | "fade-from-center"
+      | "vertical-stripes"
+      | "horizontal-stripes"
+      | "clockwise"
+      | "counterclockwise"
+      | "open-vertical"
+      | "open-horizontal"
+      | "close-vertical"
+      | "close-horizontal"
+      | "wavyline-from-left"
+      | "wavyline-from-top"
+      | "wavyline-from-right"
+      | "wavyline-from-bottom"
+      | "spiralin-left"
+      | "spiralin-right"
+      | "spiralout-left"
+      | "spiralout-right"
+      | "roll-from-top"
+      | "roll-from-left"
+      | "roll-from-right"
+      | "roll-from-bottom"
+      | "stretch-from-left"
+      | "stretch-from-top"
+      | "stretch-from-right"
+      | "stretch-from-bottom"
+      | "vertical-lines"
+      | "horizontal-lines"
+      | "dissolve"
+      | "random"
+      | "vertical-checkerboard"
+      | "horizontal-checkerboard"
+      | "interlocking-horizontal-left"
+      | "interlocking-horizontal-right"
+      | "interlocking-vertical-top"
+      | "interlocking-vertical-bottom"
+      | "fly-away"
+      | "open"
+      | "close"
+      | "melt"
+    }?
+  & attribute presentation:transition-speed { presentationSpeeds }?
+  & attribute smil:type { \string }?
+  & attribute smil:subtype { \string }?
+  & attribute smil:direction { "forward" | "reverse" }?
+  & attribute smil:fadeColor { color }?
+  & attribute presentation:duration { duration }?
+  & attribute presentation:visibility { "visible" | "hidden" }?
+  & attribute draw:background-size { "full" | "border" }?
+  & attribute presentation:background-objects-visible { boolean }?
+  & attribute presentation:background-visible { boolean }?
+  & attribute presentation:display-header { boolean }?
+  & attribute presentation:display-footer { boolean }?
+  & attribute presentation:display-page-number { boolean }?
+  & attribute presentation:display-date-time { boolean }?
+style-drawing-page-properties-content-strict =
+  style-graphic-fill-properties-attlist,
+  style-drawing-page-properties-attlist,
+  style-drawing-page-properties-elements
+style-drawing-page-properties-elements = presentation-sound?
+style-drop-cap =
+  element style:drop-cap { style-drop-cap-attlist, empty }?
+style-drop-cap-attlist =
+  attribute style:length { "word" | positiveInteger }?
+  & attribute style:lines { positiveInteger }?
+  & attribute style:distance { length }?
+  & attribute style:style-name { styleNameRef }?
+style-font-face =
+  element style:font-face {
+    style-font-face-attlist, svg-font-face-src?, svg-definition-src?
   }
-style-table-row-properties-content-strict =
-  style-table-row-properties-attlist,
-  style-table-row-properties-elements
-style-table-row-properties-attlist =
-  attribute style:row-height { positiveLength }?
-  & attribute style:min-row-height { nonNegativeLength }?
-  & attribute style:use-optimal-row-height { boolean }?
-  & common-background-color-attlist
-  & common-break-attlist
-  & attribute fo:keep-together { "auto" | "always" }?
-style-table-row-properties-elements = style-background-image
-style-table-cell-properties =
-  element style:table-cell-properties {
-    style-table-cell-properties-content-strict
+style-font-face-attlist =
+  attribute svg:font-family { \string }?
+  & attribute svg:font-style { fontStyle }?
+  & attribute svg:font-variant { fontVariant }?
+  & attribute svg:font-weight { fontWeight }?
+  & attribute svg:font-stretch {
+      "normal"
+      | "ultra-condensed"
+      | "extra-condensed"
+      | "condensed"
+      | "semi-condensed"
+      | "semi-expanded"
+      | "expanded"
+      | "extra-expanded"
+      | "ultra-expanded"
+    }?
+  & attribute svg:font-size { positiveLength }?
+  & attribute svg:unicode-range { \string }?
+  & attribute svg:units-per-em { integer }?
+  & attribute svg:panose-1 { \string }?
+  & attribute svg:stemv { integer }?
+  & attribute svg:stemh { integer }?
+  & attribute svg:slope { integer }?
+  & attribute svg:cap-height { integer }?
+  & attribute svg:x-height { integer }?
+  & attribute svg:accent-height { integer }?
+  & attribute svg:ascent { integer }?
+  & attribute svg:descent { integer }?
+  & attribute svg:widths { \string }?
+  & attribute svg:bbox { \string }?
+  & attribute svg:ideographic { integer }?
+  & attribute svg:alphabetic { integer }?
+  & attribute svg:mathematical { integer }?
+  & attribute svg:hanging { integer }?
+  & attribute svg:v-ideographic { integer }?
+  & attribute svg:v-alphabetic { integer }?
+  & attribute svg:v-mathematical { integer }?
+  & attribute svg:v-hanging { integer }?
+  & attribute svg:underline-position { integer }?
+  & attribute svg:underline-thickness { integer }?
+  & attribute svg:strikethrough-position { integer }?
+  & attribute svg:strikethrough-thickness { integer }?
+  & attribute svg:overline-position { integer }?
+  & attribute svg:overline-thickness { integer }?
+  & attribute style:name { \string }
+  & attribute style:font-adornments { \string }?
+  & attribute style:font-family-generic { fontFamilyGeneric }?
+  & attribute style:font-pitch { fontPitch }?
+  & attribute style:font-charset { textEncoding }?
+style-footer =
+  element style:footer {
+    common-style-header-footer-attlist, header-footer-content
   }
-style-table-cell-properties-content-strict =
-  style-table-cell-properties-attlist,
-  style-table-cell-properties-elements
-style-table-cell-properties-attlist =
-  attribute style:vertical-align {
-    "top" | "middle" | "bottom" | "automatic"
+style-footer-first =
+  element style:footer-first {
+    common-style-header-footer-attlist,
+    header-footer-content
+    # https://issues.oasis-open.org/browse/OFFICE-3789
+
+  }
+style-footer-left =
+  element style:footer-left {
+    common-style-header-footer-attlist, header-footer-content
+  }
+style-footer-style =
+  element style:footer-style { style-header-footer-properties? }
+style-footnote-sep =
+  element style:footnote-sep { style-footnote-sep-attlist, empty }?
+style-footnote-sep-attlist =
+  attribute style:width { length }?,
+  attribute style:rel-width { percent }?,
+  attribute style:color { color }?,
+  attribute style:line-style { lineStyle }?,
+  attribute style:adjustment { "left" | "center" | "right" }?,
+  attribute style:distance-before-sep { length }?,
+  attribute style:distance-after-sep { length }?
+style-graphic-fill-properties-attlist =
+  attribute draw:fill {
+    "none" | "solid" | "bitmap" | "gradient" | "hatch"
   }?
-  & attribute style:text-align-source { "fix" | "value-type" }?
-  & common-style-direction-attlist
-  & attribute style:glyph-orientation-vertical {
-      "auto" | "0" | "0deg" | "0rad" | "0grad"
-    }?
-  & common-writing-mode-attlist
-  & common-shadow-attlist
-  & common-background-color-attlist
-  & common-border-attlist
-  & attribute style:diagonal-tl-br { \string }?
-  & attribute style:diagonal-tl-br-widths { borderWidths }?
-  & attribute style:diagonal-bl-tr { \string }?
-  & attribute style:diagonal-bl-tr-widths { borderWidths }?
-  & common-border-line-width-attlist
-  & common-padding-attlist
-  & attribute fo:wrap-option { "no-wrap" | "wrap" }?
-  & common-rotation-angle-attlist
-  & attribute style:rotation-align {
-      "none" | "bottom" | "top" | "center"
+  & attribute draw:fill-color { color }?
+  & attribute draw:secondary-fill-color { color }?
+  & attribute draw:fill-gradient-name { styleNameRef }?
+  & attribute draw:gradient-step-count { nonNegativeInteger }?
+  & attribute draw:fill-hatch-name { styleNameRef }?
+  & attribute draw:fill-hatch-solid { boolean }?
+  & attribute draw:fill-image-name { styleNameRef }?
+  & attribute style:repeat { "no-repeat" | "repeat" | "stretch" }?
+  & attribute draw:fill-image-width { length | percent }?
+  & attribute draw:fill-image-height { length | percent }?
+  & attribute draw:fill-image-ref-point-x { percent }?
+  & attribute draw:fill-image-ref-point-y { percent }?
+  & attribute draw:fill-image-ref-point {
+      "top-left"
+      | "top"
+      | "top-right"
+      | "left"
+      | "center"
+      | "right"
+      | "bottom-left"
+      | "bottom"
+      | "bottom-right"
     }?
-  & attribute style:cell-protect {
-      "none"
-      | "hidden-and-protected"
-      | list { ("protected" | "formula-hidden")+ }
+  & attribute draw:tile-repeat-offset {
+      list { zeroToHundredPercent, ("horizontal" | "vertical") }
     }?
-  & attribute style:print-content { boolean }?
-  & attribute style:decimal-places { nonNegativeInteger }?
-  & attribute style:repeat-content { boolean }?
-  & attribute style:shrink-to-fit { boolean }?
-common-style-direction-attlist =
-  attribute style:direction { "ltr" | "ttb" }?
-style-table-cell-properties-elements = style-background-image
-common-rotation-angle-attlist =
-  attribute style:rotation-angle { angle }?
-style-list-level-properties =
-  element style:list-level-properties {
-    style-list-level-properties-content-strict
+  & attribute draw:opacity { zeroToHundredPercent }?
+  & attribute draw:opacity-name { styleNameRef }?
+  & attribute svg:fill-rule { "nonzero" | "evenodd" }?
+style-graphic-properties =
+  element style:graphic-properties {
+    style-graphic-properties-content-strict
   }
-style-list-level-properties-content-strict =
-  style-list-level-properties-attlist,
-  style-list-level-properties-elements
-style-list-level-properties-attlist =
-  common-text-align
-  & attribute text:space-before { length }?
-  & attribute text:min-label-width { nonNegativeLength }?
-  & attribute text:min-label-distance { nonNegativeLength }?
-  & attribute style:font-name { \string }?
-  & attribute fo:width { positiveLength }?
-  & attribute fo:height { positiveLength }?
-  & common-vertical-rel-attlist
-  & common-vertical-pos-attlist
-  & attribute text:list-level-position-and-space-mode {
-      "label-width-and-position" | "label-alignment"
-    }?
-style-list-level-properties-elements = style-list-level-label-alignment
-style-list-level-label-alignment =
-  element style:list-level-label-alignment {
-    style-list-level-label-alignment-attlist, empty
-  }?
-style-list-level-label-alignment-attlist =
-  attribute text:label-followed-by { "listtab" | "space" | "nothing" }
-  & attribute text:list-tab-stop-position { length }?
-  & attribute fo:text-indent { length }?
-  & attribute fo:margin-left { length }?
 style-graphic-properties-attlist =
   attribute draw:stroke { "none" | "dash" | "solid" }?
   & attribute draw:stroke-dash { styleNameRef }?
@@ -5717,7 +4036,9 @@ style-graphic-properties-attlist =
       "greyscale" | "mono" | "watermark" | "standard"
     }?
   & attribute draw:color-inversion { boolean }?
-  & attribute draw:luminance { zeroToHundredPercent }?
+  & attribute draw:luminance { signedZeroToHundredPercent }
+    # https://issues.oasis-open.org/browse/OFFICE-3821
+    ?
   & attribute draw:contrast { percent }?
   & attribute draw:gamma { percent }?
   & attribute draw:red { signedZeroToHundredPercent }?
@@ -5758,497 +4079,2316 @@ style-graphic-properties-attlist =
       | "ft"
       | "mi"
     }?
-  & attribute draw:show-unit { boolean }?
-  & attribute draw:decimal-places { nonNegativeInteger }?
-  & attribute draw:caption-type {
-      "straight-line" | "angled-line" | "angled-connector-line"
+  & attribute draw:show-unit { boolean }?
+  & attribute draw:decimal-places { nonNegativeInteger }?
+  & attribute draw:caption-type {
+      "straight-line" | "angled-line" | "angled-connector-line"
+    }?
+  & attribute draw:caption-angle-type { "fixed" | "free" }?
+  & attribute draw:caption-angle { angle }?
+  & attribute draw:caption-gap { distance }?
+  & attribute draw:caption-escape-direction {
+      "horizontal" | "vertical" | "auto"
+    }?
+  & attribute draw:caption-escape { length | percent }?
+  & attribute draw:caption-line-length { length }?
+  & attribute draw:caption-fit-line-length { boolean }?
+  & attribute dr3d:horizontal-segments { nonNegativeInteger }?
+  & attribute dr3d:vertical-segments { nonNegativeInteger }?
+  & attribute dr3d:edge-rounding { percent }?
+  & attribute dr3d:edge-rounding-mode { "correct" | "attractive" }?
+  & attribute dr3d:back-scale { percent }?
+  & attribute dr3d:depth { length }?
+  & attribute dr3d:backface-culling { "enabled" | "disabled" }?
+  & attribute dr3d:end-angle { angle }?
+  & attribute dr3d:close-front { boolean }?
+  & attribute dr3d:close-back { boolean }?
+  & attribute dr3d:lighting-mode { "standard" | "double-sided" }?
+  & attribute dr3d:normals-kind { "object" | "flat" | "sphere" }?
+  & attribute dr3d:normals-direction { "normal" | "inverse" }?
+  & attribute dr3d:texture-generation-mode-x {
+      "object" | "parallel" | "sphere"
+    }?
+  & attribute dr3d:texture-generation-mode-y {
+      "object" | "parallel" | "sphere"
+    }?
+  & attribute dr3d:texture-kind { "luminance" | "intensity" | "color" }?
+  & attribute dr3d:texture-filter { "enabled" | "disabled" }?
+  & attribute dr3d:texture-mode { "replace" | "modulate" | "blend" }?
+  & attribute dr3d:ambient-color { color }?
+  & attribute dr3d:emissive-color { color }?
+  & attribute dr3d:specular-color { color }?
+  & attribute dr3d:diffuse-color { color }?
+  & attribute dr3d:shininess { percent }?
+  & attribute dr3d:shadow { "visible" | "hidden" }?
+  & common-draw-rel-size-attlist
+  & attribute fo:min-width { length | percent }?
+  & attribute fo:min-height { length | percent }?
+  & attribute fo:max-height { length | percent }?
+  & attribute fo:max-width { length | percent }?
+  & common-horizontal-margin-attlist
+  & common-vertical-margin-attlist
+  & common-margin-attlist
+  & attribute style:print-content { boolean }?
+  & attribute style:protect {
+      "none"
+      | list { ("content" | "position" | "size")+ }
+    }?
+  & attribute style:horizontal-pos {
+      "left"
+      | "center"
+      | "right"
+      | "from-left"
+      | "inside"
+      | "outside"
+      | "from-inside"
+    }?
+  & attribute svg:x { coordinate }?
+  & attribute style:horizontal-rel {
+      "page"
+      | "page-content"
+      | "page-start-margin"
+      | "page-end-margin"
+      | "frame"
+      | "frame-content"
+      | "frame-start-margin"
+      | "frame-end-margin"
+      | "paragraph"
+      | "paragraph-content"
+      | "paragraph-start-margin"
+      | "paragraph-end-margin"
+      | "char"
+    }?
+  & common-vertical-pos-attlist
+  & common-vertical-rel-attlist
+  & common-text-anchor-attlist
+  & common-border-attlist
+  & common-border-line-width-attlist
+  & common-padding-attlist
+  & common-shadow-attlist
+  & common-background-color-attlist
+  & common-background-transparency-attlist
+  & common-editable-attlist
+  & attribute style:wrap {
+      "none"
+      | "left"
+      | "right"
+      | "parallel"
+      | "dynamic"
+      | "run-through"
+      | "biggest"
+    }?
+  & attribute style:wrap-dynamic-threshold { nonNegativeLength }?
+  & attribute style:number-wrapped-paragraphs {
+      "no-limit" | positiveInteger
+    }?
+  & attribute style:wrap-contour { boolean }?
+  & attribute style:wrap-contour-mode { "full" | "outside" }?
+  & attribute style:run-through { "foreground" | "background" }?
+  & attribute style:flow-with-text { boolean }?
+  & attribute style:overflow-behavior {
+      "clip" | "auto-create-new-frame"
+    }?
+  & attribute style:mirror {
+      "none"
+      | "vertical"
+      | horizontal-mirror
+      | list { "vertical", horizontal-mirror }
+      | list { horizontal-mirror, "vertical" }
+    }?
+  & attribute fo:clip { "auto" | clipShape }?
+  & attribute draw:wrap-influence-on-position {
+      "iterative" | "once-concurrent" | "once-successive"
+    }?
+  & common-writing-mode-attlist
+  & attribute draw:frame-display-scrollbar { boolean }?
+  & attribute draw:frame-display-border { boolean }?
+  & attribute draw:frame-margin-horizontal { nonNegativePixelLength }?
+  & attribute draw:frame-margin-vertical { nonNegativePixelLength }?
+  & attribute draw:visible-area-left { nonNegativeLength }?
+  & attribute draw:visible-area-top { nonNegativeLength }?
+  & attribute draw:visible-area-width { positiveLength }?
+  & attribute draw:visible-area-height { positiveLength }?
+  & attribute draw:draw-aspect {
+      "content" | "thumbnail" | "icon" | "print-view"
+    }?
+  & attribute draw:ole-draw-aspect { nonNegativeInteger }?
+style-graphic-properties-content-strict =
+  style-graphic-properties-attlist,
+  style-graphic-fill-properties-attlist,
+  style-graphic-properties-elements
+style-graphic-properties-elements =
+  text-list-style? & style-background-image & style-columns
+style-handout-master =
+  element style:handout-master {
+    common-presentation-header-footer-attlist,
+    style-handout-master-attlist,
+    shape*
+  }
+style-handout-master-attlist =
+  attribute presentation:presentation-page-layout-name { styleNameRef }?
+  & attribute style:page-layout-name { styleNameRef }
+  & attribute draw:style-name { styleNameRef }?
+style-header =
+  element style:header {
+    common-style-header-footer-attlist, header-footer-content
+  }
+style-header-first =
+  element style:header-first {
+    common-style-header-footer-attlist,
+    header-footer-content
+    # https://issues.oasis-open.org/browse/OFFICE-3789
+
+  }
+style-header-footer-properties =
+  element style:header-footer-properties {
+    style-header-footer-properties-content-strict
+  }
+style-header-footer-properties-attlist =
+  attribute svg:height { length }?
+  & attribute fo:min-height { length }?
+  & common-horizontal-margin-attlist
+  & common-vertical-margin-attlist
+  & common-margin-attlist
+  & common-border-attlist
+  & common-border-line-width-attlist
+  & common-padding-attlist
+  & common-background-color-attlist
+  & common-shadow-attlist
+  & attribute style:dynamic-spacing { boolean }?
+style-header-footer-properties-content-strict =
+  style-header-footer-properties-attlist,
+  style-header-footer-properties-elements
+style-header-footer-properties-elements = style-background-image
+style-header-left =
+  element style:header-left {
+    common-style-header-footer-attlist, header-footer-content
+  }
+style-header-style =
+  element style:header-style { style-header-footer-properties? }
+style-list-level-label-alignment =
+  element style:list-level-label-alignment {
+    style-list-level-label-alignment-attlist, empty
+  }?
+style-list-level-label-alignment-attlist =
+  attribute text:label-followed-by { "listtab" | "space" | "nothing" }
+  & attribute text:list-tab-stop-position { length }?
+  & attribute fo:text-indent { length }?
+  & attribute fo:margin-left { length }?
+style-list-level-properties =
+  element style:list-level-properties {
+    style-list-level-properties-content-strict
+  }
+style-list-level-properties-attlist =
+  common-text-align
+  & attribute text:space-before { length }?
+  & attribute text:min-label-width { nonNegativeLength }?
+  & attribute text:min-label-distance { nonNegativeLength }?
+  & attribute style:font-name { \string }?
+  & attribute fo:width { positiveLength }?
+  & attribute fo:height { positiveLength }?
+  & common-vertical-rel-attlist
+  & common-vertical-pos-attlist
+  & attribute text:list-level-position-and-space-mode {
+      "label-width-and-position" | "label-alignment"
     }?
-  & attribute draw:caption-angle-type { "fixed" | "free" }?
-  & attribute draw:caption-angle { angle }?
-  & attribute draw:caption-gap { distance }?
-  & attribute draw:caption-escape-direction {
-      "horizontal" | "vertical" | "auto"
+style-list-level-properties-content-strict =
+  style-list-level-properties-attlist,
+  style-list-level-properties-elements
+style-list-level-properties-elements = style-list-level-label-alignment
+style-map = element style:map { style-map-attlist, empty }
+style-map-attlist =
+  attribute style:condition { \string }
+  & attribute style:apply-style-name { styleNameRef }
+  & attribute style:base-cell-address { cellAddress }?
+style-master-page =
+  element style:master-page {
+    style-master-page-attlist,
+    (style-header,
+     style-header-left?,
+     (style-header-first?)
+     # https://issues.oasis-open.org/browse/OFFICE-3789
+     )?,
+    (style-footer,
+     style-footer-left?,
+     (style-footer-first?)
+     # https://issues.oasis-open.org/browse/OFFICE-3789
+     )?,
+    draw-layer-set?,
+    office-forms?,
+    shape*,
+    animation-element?,
+    presentation-notes?
+  }
+style-master-page-attlist =
+  attribute style:name { styleName }
+  & attribute style:display-name { \string }?
+  & attribute style:page-layout-name { styleNameRef }
+  & attribute draw:style-name { styleNameRef }?
+  & attribute style:next-style-name { styleNameRef }?
+style-num-letter-sync-attlist =
+  attribute style:num-letter-sync { boolean }?
+style-page-layout =
+  element style:page-layout {
+    style-page-layout-attlist, style-page-layout-content
+  }
+style-page-layout-attlist =
+  attribute style:name { styleName }
+  & attribute style:page-usage {
+      "all" | "left" | "right" | "mirrored"
     }?
-  & attribute draw:caption-escape { length | percent }?
-  & attribute draw:caption-line-length { length }?
-  & attribute draw:caption-fit-line-length { boolean }?
-  & attribute dr3d:horizontal-segments { nonNegativeInteger }?
-  & attribute dr3d:vertical-segments { nonNegativeInteger }?
-  & attribute dr3d:edge-rounding { percent }?
-  & attribute dr3d:edge-rounding-mode { "correct" | "attractive" }?
-  & attribute dr3d:back-scale { percent }?
-  & attribute dr3d:depth { length }?
-  & attribute dr3d:backface-culling { "enabled" | "disabled" }?
-  & attribute dr3d:end-angle { angle }?
-  & attribute dr3d:close-front { boolean }?
-  & attribute dr3d:close-back { boolean }?
-  & attribute dr3d:lighting-mode { "standard" | "double-sided" }?
-  & attribute dr3d:normals-kind { "object" | "flat" | "sphere" }?
-  & attribute dr3d:normals-direction { "normal" | "inverse" }?
-  & attribute dr3d:texture-generation-mode-x {
-      "object" | "parallel" | "sphere"
+style-page-layout-content =
+  style-page-layout-properties?,
+  style-header-style?,
+  style-footer-style?
+style-page-layout-properties =
+  element style:page-layout-properties {
+    style-page-layout-properties-content-strict
+  }
+style-page-layout-properties-attlist =
+  attribute fo:page-width { length }?
+  & attribute fo:page-height { length }?
+  & common-num-format-attlist?
+  & common-num-format-prefix-suffix-attlist
+  & attribute style:paper-tray-name { "default" | \string }?
+  & attribute style:print-orientation { "portrait" | "landscape" }?
+  & common-horizontal-margin-attlist
+  & common-vertical-margin-attlist
+  & common-margin-attlist
+  & common-border-attlist
+  & common-border-line-width-attlist
+  & common-padding-attlist
+  & common-shadow-attlist
+  & common-background-color-attlist
+  & attribute style:register-truth-ref-style-name { styleNameRef }?
+  & attribute style:print {
+      list {
+        ("headers"
+         | "grid"
+         | "annotations"
+         | "objects"
+         | "charts"
+         | "drawings"
+         | "formulas"
+         | "zero-values")*
+      }
     }?
-  & attribute dr3d:texture-generation-mode-y {
-      "object" | "parallel" | "sphere"
+  & attribute style:print-page-order { "ttb" | "ltr" }?
+  & attribute style:first-page-number { positiveInteger | "continue" }?
+  & (attribute style:scale-to { percent }?
+     | attribute style:scale-to-pages { positiveInteger }?
+     | (attribute style:scale-to-X { positiveInteger }?,
+        attribute style:scale-to-Y { positiveInteger }?))
+  & # https://issues.oasis-open.org/browse/OFFICE-3857
+    attribute style:table-centering {
+      "horizontal" | "vertical" | "both" | "none"
     }?
-  & attribute dr3d:texture-kind { "luminance" | "intensity" | "color" }?
-  & attribute dr3d:texture-filter { "enabled" | "disabled" }?
-  & attribute dr3d:texture-mode { "replace" | "modulate" | "blend" }?
-  & attribute dr3d:ambient-color { color }?
-  & attribute dr3d:emissive-color { color }?
-  & attribute dr3d:specular-color { color }?
-  & attribute dr3d:diffuse-color { color }?
-  & attribute dr3d:shininess { percent }?
-  & attribute dr3d:shadow { "visible" | "hidden" }?
-  & common-draw-rel-size-attlist
-  & attribute fo:min-width { length | percent }?
-  & attribute fo:min-height { length | percent }?
-  & attribute fo:max-height { length | percent }?
-  & attribute fo:max-width { length | percent }?
+  & attribute style:footnote-max-height { length }?
+  & common-writing-mode-attlist
+  & attribute style:layout-grid-mode { "none" | "line" | "both" }?
+  & attribute style:layout-grid-standard-mode { boolean }?
+  & attribute style:layout-grid-base-height { length }?
+  & attribute style:layout-grid-ruby-height { length }?
+  & attribute style:layout-grid-lines { positiveInteger }?
+  & attribute style:layout-grid-base-width { length }?
+  & attribute style:layout-grid-color { color }?
+  & attribute style:layout-grid-ruby-below { boolean }?
+  & attribute style:layout-grid-print { boolean }?
+  & attribute style:layout-grid-display { boolean }?
+  & attribute style:layout-grid-snap-to { boolean }?
+style-page-layout-properties-content-strict =
+  style-page-layout-properties-attlist,
+  style-page-layout-properties-elements
+style-page-layout-properties-elements =
+  style-background-image & style-columns & style-footnote-sep
+style-paragraph-properties =
+  element style:paragraph-properties {
+    style-paragraph-properties-content-strict
+  }
+style-paragraph-properties-attlist =
+  attribute style:contextual-spacing { boolean }?
+  & # https://issues.oasis-open.org/browse/OFFICE-3767
+    attribute fo:line-height { "normal" | nonNegativeLength | percent }?
+  & attribute style:line-height-at-least { nonNegativeLength }?
+  & attribute style:line-spacing { length }?
+  & attribute style:font-independent-line-spacing { boolean }?
+  & common-text-align
+  & attribute fo:text-align-last { "start" | "center" | "justify" }?
+  & attribute style:justify-single-word { boolean }?
+  & attribute fo:keep-together { "auto" | "always" }?
+  & attribute fo:widows { nonNegativeInteger }?
+  & attribute fo:orphans { nonNegativeInteger }?
+  & attribute style:tab-stop-distance { nonNegativeLength }?
+  & attribute fo:hyphenation-keep { "auto" | "page" }?
+  & attribute fo:hyphenation-ladder-count {
+      "no-limit" | positiveInteger
+    }?
+  & attribute style:register-true { boolean }?
   & common-horizontal-margin-attlist
+  & attribute fo:text-indent { length | percent }?
+  & attribute style:auto-text-indent { boolean }?
   & common-vertical-margin-attlist
   & common-margin-attlist
-  & attribute style:print-content { boolean }?
-  & attribute style:protect {
-      "none"
-      | list { ("content" | "position" | "size")+ }
+  & common-break-attlist
+  & common-background-color-attlist
+  & common-border-attlist
+  & common-border-line-width-attlist
+  & attribute style:join-border { boolean }?
+  & common-padding-attlist
+  & common-shadow-attlist
+  & common-keep-with-next-attlist
+  & attribute text:number-lines { boolean }?
+  & attribute text:line-number { nonNegativeInteger }?
+  & attribute style:text-autospace { "none" | "ideograph-alpha" }?
+  & attribute style:punctuation-wrap { "simple" | "hanging" }?
+  & attribute style:line-break { "normal" | "strict" }?
+  & attribute style:vertical-align {
+      "top" | "middle" | "bottom" | "auto" | "baseline"
     }?
-  & attribute style:horizontal-pos {
+  & common-writing-mode-attlist
+  & attribute style:writing-mode-automatic { boolean }?
+  & attribute style:snap-to-layout-grid { boolean }?
+  & common-page-number-attlist
+  & common-background-transparency-attlist
+style-paragraph-properties-content-strict =
+  style-paragraph-properties-attlist,
+  style-paragraph-properties-elements
+style-paragraph-properties-elements =
+  style-tab-stops & style-drop-cap & style-background-image
+style-presentation-page-layout =
+  element style:presentation-page-layout {
+    attribute style:name { styleName },
+    attribute style:display-name { \string }?,
+    presentation-placeholder*
+  }
+style-region-center = element style:region-center { region-content }
+style-region-left = element style:region-left { region-content }
+style-region-right = element style:region-right { region-content }
+style-ruby-properties =
+  element style:ruby-properties { style-ruby-properties-content-strict }
+style-ruby-properties-attlist =
+  attribute style:ruby-position { "above" | "below" }?
+  & attribute style:ruby-align {
       "left"
       | "center"
       | "right"
-      | "from-left"
-      | "inside"
-      | "outside"
-      | "from-inside"
+      | "distribute-letter"
+      | "distribute-space"
     }?
-  & attribute svg:x { coordinate }?
-  & attribute style:horizontal-rel {
-      "page"
-      | "page-content"
-      | "page-start-margin"
-      | "page-end-margin"
-      | "frame"
-      | "frame-content"
-      | "frame-start-margin"
-      | "frame-end-margin"
-      | "paragraph"
-      | "paragraph-content"
-      | "paragraph-start-margin"
-      | "paragraph-end-margin"
-      | "char"
+style-ruby-properties-content-strict =
+  style-ruby-properties-attlist, style-ruby-properties-elements
+style-ruby-properties-elements = empty
+style-section-properties =
+  element style:section-properties {
+    style-section-properties-content-strict
+  }
+style-section-properties-attlist =
+  common-background-color-attlist
+  & common-horizontal-margin-attlist
+  & attribute style:protect { boolean }?
+  & common-editable-attlist
+  & attribute text:dont-balance-text-columns { boolean }?
+  & common-writing-mode-attlist
+style-section-properties-content-strict =
+  style-section-properties-attlist, style-section-properties-elements
+style-section-properties-elements =
+  style-background-image & style-columns & text-notes-configuration*
+style-style =
+  element style:style {
+    style-style-attlist, style-style-content, style-map*
+  }
+style-style-attlist =
+  attribute style:name { styleName }
+  & attribute style:display-name { \string }?
+  & attribute style:parent-style-name { styleNameRef }?
+  & attribute style:next-style-name { styleNameRef }?
+  & attribute style:list-level { positiveInteger | empty }?
+  & attribute style:list-style-name { styleName | empty }?
+  & attribute style:master-page-name { styleNameRef }?
+  & attribute style:auto-update { boolean }?
+  & attribute style:data-style-name { styleNameRef }?
+  & attribute style:percentage-data-style-name { styleNameRef }?
+  & attribute style:class { \string }?
+  & attribute style:default-outline-level { positiveInteger | empty }?
+style-style-content =
+  (attribute style:family { "text" },
+   style-text-properties?)
+  | (attribute style:family { "paragraph" },
+     style-paragraph-properties?,
+     style-text-properties?)
+  | (attribute style:family { "section" },
+     style-section-properties?)
+  | (attribute style:family { "ruby" },
+     style-ruby-properties?)
+  | (attribute style:family { "table" },
+     style-table-properties?)
+  | (attribute style:family { "table-column" },
+     style-table-column-properties?)
+  | (attribute style:family { "table-row" },
+     style-table-row-properties?)
+  | (attribute style:family { "table-cell" },
+     style-table-cell-properties?,
+     style-paragraph-properties?,
+     style-text-properties?)
+  | (attribute style:family { "graphic" | "presentation" },
+     style-graphic-properties?,
+     style-paragraph-properties?,
+     style-text-properties?)
+  | (attribute style:family { "drawing-page" },
+     style-drawing-page-properties?)
+  | (attribute style:family { "chart" },
+     style-chart-properties?,
+     style-graphic-properties?,
+     style-paragraph-properties?,
+     style-text-properties?)
+style-tab-stop =
+  element style:tab-stop { style-tab-stop-attlist, empty }
+style-tab-stop-attlist =
+  attribute style:position { length }
+  & (attribute style:type { "left" | "center" | "right" }?
+     | (attribute style:type { "char" },
+        style-tab-stop-char-attlist))
+  & attribute style:leader-type { lineType }?
+  & attribute style:leader-style { lineStyle }?
+  & attribute style:leader-width { lineWidth }?
+  & attribute style:leader-color { "font-color" | color }?
+  & attribute style:leader-text { character }?
+  & attribute style:leader-text-style { styleNameRef }?
+style-tab-stop-char-attlist = attribute style:char { character }
+style-tab-stops = element style:tab-stops { style-tab-stop* }?
+style-table-cell-properties =
+  element style:table-cell-properties {
+    style-table-cell-properties-content-strict
+  }
+style-table-cell-properties-attlist =
+  attribute style:vertical-align {
+    "top" | "middle" | "bottom" | "automatic"
+  }?
+  & attribute style:text-align-source { "fix" | "value-type" }?
+  & common-style-direction-attlist
+  & attribute style:glyph-orientation-vertical {
+      "auto" | "0" | "0deg" | "0rad" | "0grad"
     }?
-  & common-vertical-pos-attlist
-  & common-vertical-rel-attlist
-  & common-text-anchor-attlist
+  & common-writing-mode-attlist
+  & common-shadow-attlist
+  & common-background-color-attlist
   & common-border-attlist
+  & attribute style:diagonal-tl-br { \string }?
+  & attribute style:diagonal-tl-br-widths { borderWidths }?
+  & attribute style:diagonal-bl-tr { \string }?
+  & attribute style:diagonal-bl-tr-widths { borderWidths }?
   & common-border-line-width-attlist
   & common-padding-attlist
+  & attribute fo:wrap-option { "no-wrap" | "wrap" }?
+  & common-rotation-angle-attlist
+  & attribute style:rotation-align {
+      "none" | "bottom" | "top" | "center"
+    }?
+  & attribute style:cell-protect {
+      "none"
+      | "hidden-and-protected"
+      | list { ("protected" | "formula-hidden")+ }
+    }?
+  & attribute style:print-content { boolean }?
+  & attribute style:decimal-places { nonNegativeInteger }?
+  & attribute style:repeat-content { boolean }?
+  & attribute style:shrink-to-fit { boolean }?
+style-table-cell-properties-content-strict =
+  style-table-cell-properties-attlist,
+  style-table-cell-properties-elements
+style-table-cell-properties-elements = style-background-image
+style-table-column-properties =
+  element style:table-column-properties {
+    style-table-column-properties-content-strict
+  }
+style-table-column-properties-attlist =
+  attribute style:column-width { positiveLength }?
+  & attribute style:rel-column-width { relativeLength }?
+  & attribute style:use-optimal-column-width { boolean }?
+  & common-break-attlist
+style-table-column-properties-content-strict =
+  style-table-column-properties-attlist,
+  style-table-column-properties-elements
+style-table-column-properties-elements = empty
+style-table-properties =
+  element style:table-properties {
+    style-table-properties-content-strict
+  }
+style-table-properties-attlist =
+  attribute style:width { positiveLength }?
+  & attribute style:rel-width { percent }?
+  & attribute table:align { "left" | "center" | "right" | "margins" }?
+  & common-horizontal-margin-attlist
+  & common-vertical-margin-attlist
+  & common-margin-attlist
+  & common-page-number-attlist
+  & common-break-attlist
+  & common-background-color-attlist
   & common-shadow-attlist
+  & common-keep-with-next-attlist
+  & attribute style:may-break-between-rows { boolean }?
+  & attribute table:border-model { "collapsing" | "separating" }?
+  & common-writing-mode-attlist
+  & attribute table:display { boolean }?
+  & (attribute table:tab-color { color }?)
+    # https://issues.oasis-open.org/browse/OFFICE-2173
+
+style-table-properties-content-strict =
+  style-table-properties-attlist, style-table-properties-elements
+style-table-properties-elements = style-background-image
+style-table-row-properties =
+  element style:table-row-properties {
+    style-table-row-properties-content-strict
+  }
+style-table-row-properties-attlist =
+  attribute style:row-height { positiveLength }?
+  & attribute style:min-row-height { nonNegativeLength }?
+  & attribute style:use-optimal-row-height { boolean }?
+  & common-background-color-attlist
+  & common-break-attlist
+  & attribute fo:keep-together { "auto" | "always" }?
+style-table-row-properties-content-strict =
+  style-table-row-properties-attlist,
+  style-table-row-properties-elements
+style-table-row-properties-elements = style-background-image
+style-text-properties =
+  element style:text-properties { style-text-properties-content-strict }
+style-text-properties-attlist =
+  attribute fo:font-variant { fontVariant }?
+  & attribute fo:text-transform {
+      "none" | "lowercase" | "uppercase" | "capitalize"
+    }?
+  & attribute fo:color { color }?
+  & attribute style:use-window-font-color { boolean }?
+  & attribute style:text-outline { boolean }?
+  & attribute style:text-line-through-type { lineType }?
+  & attribute style:text-line-through-style { lineStyle }?
+  & attribute style:text-line-through-width { lineWidth }?
+  & attribute style:text-line-through-color { "font-color" | color }?
+  & attribute style:text-line-through-text { \string }?
+  & attribute style:text-line-through-text-style { styleNameRef }?
+  & attribute style:text-position {
+      list { (percent | "super" | "sub"), percent? }
+    }?
+  & attribute style:font-name { \string }?
+  & attribute style:font-name-asian { \string }?
+  & attribute style:font-name-complex { \string }?
+  & attribute fo:font-family { \string }?
+  & attribute style:font-family-asian { \string }?
+  & attribute style:font-family-complex { \string }?
+  & attribute style:font-family-generic { fontFamilyGeneric }?
+  & attribute style:font-family-generic-asian { fontFamilyGeneric }?
+  & attribute style:font-family-generic-complex { fontFamilyGeneric }?
+  & attribute style:font-style-name { \string }?
+  & attribute style:font-style-name-asian { \string }?
+  & attribute style:font-style-name-complex { \string }?
+  & attribute style:font-pitch { fontPitch }?
+  & attribute style:font-pitch-asian { fontPitch }?
+  & attribute style:font-pitch-complex { fontPitch }?
+  & attribute style:font-charset { textEncoding }?
+  & attribute style:font-charset-asian { textEncoding }?
+  & attribute style:font-charset-complex { textEncoding }?
+  & attribute fo:font-size { positiveLength | percent }?
+  & attribute style:font-size-asian { positiveLength | percent }?
+  & attribute style:font-size-complex { positiveLength | percent }?
+  & attribute style:font-size-rel { length }?
+  & attribute style:font-size-rel-asian { length }?
+  & attribute style:font-size-rel-complex { length }?
+  & attribute style:script-type {
+      "latin" | "asian" | "complex" | "ignore"
+    }?
+  & attribute fo:letter-spacing { length | "normal" }?
+  & attribute fo:language { languageCode }?
+  & attribute style:language-asian { languageCode }?
+  & attribute style:language-complex { languageCode }?
+  & attribute fo:country { countryCode }?
+  & attribute style:country-asian { countryCode }?
+  & attribute style:country-complex { countryCode }?
+  & attribute fo:script { scriptCode }?
+  & attribute style:script-asian { scriptCode }?
+  & attribute style:script-complex { scriptCode }?
+  & attribute style:rfc-language-tag { language }?
+  & attribute style:rfc-language-tag-asian { language }?
+  & attribute style:rfc-language-tag-complex { language }?
+  & attribute fo:font-style { fontStyle }?
+  & attribute style:font-style-asian { fontStyle }?
+  & attribute style:font-style-complex { fontStyle }?
+  & attribute style:font-relief { "none" | "embossed" | "engraved" }?
+  & attribute fo:text-shadow { shadowType }?
+  & attribute style:text-underline-type { lineType }?
+  & attribute style:text-underline-style { lineStyle }?
+  & attribute style:text-underline-width { lineWidth }?
+  & attribute style:text-underline-color { "font-color" | color }?
+  & attribute style:text-overline-type { lineType }?
+  & attribute style:text-overline-style { lineStyle }?
+  & attribute style:text-overline-width { lineWidth }?
+  & attribute style:text-overline-color { "font-color" | color }?
+  & attribute style:text-overline-mode { lineMode }?
+  & attribute fo:font-weight { fontWeight }?
+  & attribute style:font-weight-asian { fontWeight }?
+  & attribute style:font-weight-complex { fontWeight }?
+  & attribute style:text-underline-mode { lineMode }?
+  & attribute style:text-line-through-mode { lineMode }?
+  & attribute style:letter-kerning { boolean }?
+  & attribute style:text-blinking { boolean }?
   & common-background-color-attlist
-  & common-background-transparency-attlist
-  & common-editable-attlist
-  & attribute style:wrap {
+  & attribute style:text-combine { "none" | "letters" | "lines" }?
+  & attribute style:text-combine-start-char { character }?
+  & attribute style:text-combine-end-char { character }?
+  & attribute style:text-emphasize {
       "none"
-      | "left"
-      | "right"
-      | "parallel"
-      | "dynamic"
-      | "run-through"
-      | "biggest"
+      | list {
+          ("none" | "accent" | "dot" | "circle" | "disc"),
+          ("above" | "below")
+        }
     }?
-  & attribute style:wrap-dynamic-threshold { nonNegativeLength }?
-  & attribute style:number-wrapped-paragraphs {
-      "no-limit" | positiveInteger
+  & attribute style:text-scale { percent }?
+  & attribute style:text-rotation-angle { angle }?
+  & attribute style:text-rotation-scale { "fixed" | "line-height" }?
+  & attribute fo:hyphenate { boolean }?
+  & attribute fo:hyphenation-remain-char-count { positiveInteger }?
+  & attribute fo:hyphenation-push-char-count { positiveInteger }?
+  & (attribute text:display { "true" }
+     | attribute text:display { "none" }
+     | (attribute text:display { "condition" },
+        attribute text:condition { "none" })
+     | empty)
+style-text-properties-content-strict =
+  style-text-properties-attlist, style-text-properties-elements
+style-text-properties-elements = empty
+styleName = xsd:NCName
+styleNameRef = xsd:NCName | empty
+styleNameRefs = list { xsd:NCName* }
+styles =
+  style-style*
+  & text-list-style*
+  & number-number-style*
+  & number-currency-style*
+  & number-percentage-style*
+  & number-date-style*
+  & number-time-style*
+  & number-boolean-style*
+  & number-text-style*
+svg-definition-src =
+  element svg:definition-src {
+    common-svg-font-face-xlink-attlist, empty
+  }
+svg-desc = element svg:desc { text }
+svg-font-face-format =
+  element svg:font-face-format {
+    attribute svg:string { \string }?,
+    empty
+  }
+svg-font-face-name =
+  element svg:font-face-name {
+    attribute svg:name { \string }?,
+    empty
+  }
+svg-font-face-src =
+  element svg:font-face-src {
+    (svg-font-face-uri | svg-font-face-name)+
+  }
+svg-font-face-uri =
+  element svg:font-face-uri {
+    common-svg-font-face-xlink-attlist, svg-font-face-format*
+  }
+svg-linearGradient =
+  element svg:linearGradient {
+    common-svg-gradient-attlist,
+    attribute svg:x1 { coordinate | percent }?,
+    attribute svg:y1 { coordinate | percent }?,
+    attribute svg:x2 { coordinate | percent }?,
+    attribute svg:y2 { coordinate | percent }?,
+    svg-stop*
+  }
+svg-radialGradient =
+  element svg:radialGradient {
+    common-svg-gradient-attlist,
+    attribute svg:cx { coordinate | percent }?,
+    attribute svg:cy { coordinate | percent }?,
+    attribute svg:r { coordinate | percent }?,
+    attribute svg:fx { coordinate | percent }?,
+    attribute svg:fy { coordinate | percent }?,
+    svg-stop*
+  }
+svg-stop =
+  element svg:stop {
+    attribute svg:offset { double | percent },
+    attribute svg:stop-color { color }?,
+    attribute svg:stop-opacity { double }?
+  }
+svg-title = element svg:title { text }
+tab-cycles = "records" | "current" | "page"
+table-background =
+  element table:background { table-background-attlist, empty }
+table-background-attlist = attribute table:style-name { styleNameRef }
+table-body = element table:body { common-table-template-attlist, empty }
+table-calculation-setting-attlist =
+  attribute table:case-sensitive { boolean }?
+  & attribute table:precision-as-shown { boolean }?
+  & attribute table:search-criteria-must-apply-to-whole-cell {
+      boolean
     }?
-  & attribute style:wrap-contour { boolean }?
-  & attribute style:wrap-contour-mode { "full" | "outside" }?
-  & attribute style:run-through { "foreground" | "background" }?
-  & attribute style:flow-with-text { boolean }?
-  & attribute style:overflow-behavior {
-      "clip" | "auto-create-new-frame"
+  & attribute table:automatic-find-labels { boolean }?
+  & attribute table:use-regular-expressions { boolean }?
+  & attribute table:use-wildcards { boolean }?
+  & attribute table:null-year { positiveInteger }?
+table-calculation-settings =
+  element table:calculation-settings {
+    table-calculation-setting-attlist,
+    table-null-date?,
+    table-iteration?
+  }
+table-cell-address =
+  element table:cell-address {
+    common-table-cell-address-attlist, empty
+  }
+table-cell-content-change =
+  element table:cell-content-change {
+    common-table-change-attlist,
+    table-cell-address,
+    office-change-info,
+    table-dependencies?,
+    table-deletions?,
+    table-previous
+  }
+table-cell-content-deletion =
+  element table:cell-content-deletion {
+    attribute table:id { \string }?,
+    table-cell-address?,
+    table-change-track-table-cell?
+  }
+table-cell-range-source =
+  element table:cell-range-source {
+    table-table-cell-range-source-attlist,
+    table-linked-source-attlist,
+    empty
+  }
+table-change-deletion =
+  element table:change-deletion {
+    attribute table:id { \string }?,
+    empty
+  }
+table-change-track-table-cell =
+  element table:change-track-table-cell {
+    table-change-track-table-cell-attlist, text-p*
+  }
+table-change-track-table-cell-attlist =
+  attribute table:cell-address { cellAddress }?
+  & attribute table:matrix-covered { boolean }?
+  & attribute table:formula { \string }?
+  & attribute table:number-matrix-columns-spanned { positiveInteger }?
+  & attribute table:number-matrix-rows-spanned { positiveInteger }?
+  & common-value-and-type-attlist?
+table-columns = table-table-columns | table-table-column+
+table-columns-and-groups =
+  (table-table-column-group | table-columns-no-group)+
+table-columns-no-group =
+  (table-columns, (table-table-header-columns, table-columns?)?)
+  | (table-table-header-columns, table-columns?)
+table-consolidation =
+  element table:consolidation { table-consolidation-attlist, empty }
+table-consolidation-attlist =
+  attribute table:function {
+    "average"
+    | "count"
+    | "countnums"
+    | "max"
+    | "min"
+    | "product"
+    | "stdev"
+    | "stdevp"
+    | "sum"
+    | "var"
+    | "varp"
+    | \string
+  }
+  & attribute table:source-cell-range-addresses { cellRangeAddressList }
+  & attribute table:target-cell-address { cellAddress }
+  & attribute table:use-labels { "none" | "row" | "column" | "both" }?
+  & attribute table:link-to-source-data { boolean }?
+table-content-validation =
+  element table:content-validation {
+    table-validation-attlist,
+    table-help-message?,
+    (table-error-message | (table-error-macro, office-event-listeners))?
+  }
+table-content-validations =
+  element table:content-validations { table-content-validation+ }
+table-covered-table-cell =
+  element table:covered-table-cell {
+    table-table-cell-attlist, table-table-cell-content
+  }
+table-cut-offs =
+  element table:cut-offs {
+    table-movement-cut-off+
+    | (table-insertion-cut-off, table-movement-cut-off*)
+  }
+table-data-pilot-display-info =
+  element table:data-pilot-display-info {
+    table-data-pilot-display-info-attlist, empty
+  }
+table-data-pilot-display-info-attlist =
+  attribute table:enabled { boolean }
+  & attribute table:data-field { \string }
+  & attribute table:member-count { nonNegativeInteger }
+  & attribute table:display-member-mode { "from-top" | "from-bottom" }
+table-data-pilot-field =
+  element table:data-pilot-field {
+    table-data-pilot-field-attlist,
+    table-data-pilot-level?,
+    table-data-pilot-field-reference?,
+    table-data-pilot-groups?
+  }
+table-data-pilot-field-attlist =
+  attribute table:source-field-name { \string }
+  & (attribute table:orientation {
+       "row" | "column" | "data" | "hidden"
+     }
+     | (attribute table:orientation { "page" },
+        attribute table:selected-page { \string }))
+  & attribute table:is-data-layout-field { \string }?
+  & attribute table:function {
+      "auto"
+      | "average"
+      | "count"
+      | "countnums"
+      | "max"
+      | "min"
+      | "product"
+      | "stdev"
+      | "stdevp"
+      | "sum"
+      | "var"
+      | "varp"
+      | \string
     }?
-  & attribute style:mirror {
+  & attribute table:used-hierarchy { integer }?
+table-data-pilot-field-reference =
+  element table:data-pilot-field-reference {
+    table-data-pilot-field-reference-attlist
+  }
+table-data-pilot-field-reference-attlist =
+  attribute table:field-name { \string }
+  & ((attribute table:member-type { "named" },
+      attribute table:member-name { \string })
+     | attribute table:member-type { "previous" | "next" })
+  & attribute table:type {
       "none"
-      | "vertical"
-      | horizontal-mirror
-      | list { "vertical", horizontal-mirror }
-      | list { horizontal-mirror, "vertical" }
+      | "member-difference"
+      | "member-percentage"
+      | "member-percentage-difference"
+      | "running-total"
+      | "row-percentage"
+      | "column-percentage"
+      | "total-percentage"
+      | "index"
+    }
+table-data-pilot-group =
+  element table:data-pilot-group {
+    table-data-pilot-group-attlist, table-data-pilot-group-member+
+  }
+table-data-pilot-group-attlist = attribute table:name { \string }
+table-data-pilot-group-member =
+  element table:data-pilot-group-member {
+    table-data-pilot-group-member-attlist
+  }
+table-data-pilot-group-member-attlist = attribute table:name { \string }
+table-data-pilot-groups =
+  element table:data-pilot-groups {
+    table-data-pilot-groups-attlist, table-data-pilot-group+
+  }
+table-data-pilot-groups-attlist =
+  attribute table:source-field-name { \string }
+  & (attribute table:date-start { dateOrDateTime | "auto" }
+     | attribute table:start { double | "auto" })?
+  & (attribute table:date-end { dateOrDateTime | "auto" }
+     | attribute table:end { double | "auto" })?
+  & attribute table:step { double }?
+  & attribute table:grouped-by {
+      "seconds"
+      | "minutes"
+      | "hours"
+      | "days"
+      | "months"
+      | "quarters"
+      | "years"
+    }?
+# https://issues.oasis-open.org/browse/OFFICE-2118
+table-data-pilot-layout-info =
+  element table:data-pilot-layout-info {
+    table-data-pilot-layout-info-attlist, empty
+  }
+table-data-pilot-layout-info-attlist =
+  attribute table:layout-mode {
+    "tabular-layout"
+    | "outline-subtotals-top"
+    | "outline-subtotals-bottom"
+  }
+  & attribute table:add-empty-lines { boolean }
+table-data-pilot-level =
+  element table:data-pilot-level {
+    table-data-pilot-level-attlist,
+    table-data-pilot-subtotals?,
+    table-data-pilot-members?,
+    table-data-pilot-display-info?,
+    table-data-pilot-sort-info?,
+    table-data-pilot-layout-info?
+  }
+table-data-pilot-level-attlist = attribute table:show-empty { boolean }?
+table-data-pilot-member =
+  element table:data-pilot-member {
+    table-data-pilot-member-attlist, empty
+  }
+table-data-pilot-member-attlist =
+  attribute table:name { \string }
+  & attribute table:display { boolean }?
+  & attribute table:show-details { boolean }?
+table-data-pilot-members =
+  element table:data-pilot-members { table-data-pilot-member* }
+table-data-pilot-sort-info =
+  element table:data-pilot-sort-info {
+    table-data-pilot-sort-info-attlist, empty
+  }
+table-data-pilot-sort-info-attlist =
+  ((attribute table:sort-mode { "data" },
+    attribute table:data-field { \string })
+   | attribute table:sort-mode { "none" | "manual" | "name" })
+  & attribute table:order { "ascending" | "descending" }
+table-data-pilot-subtotal =
+  element table:data-pilot-subtotal {
+    table-data-pilot-subtotal-attlist, empty
+  }
+table-data-pilot-subtotal-attlist =
+  attribute table:function {
+    "auto"
+    | "average"
+    | "count"
+    | "countnums"
+    | "max"
+    | "min"
+    | "product"
+    | "stdev"
+    | "stdevp"
+    | "sum"
+    | "var"
+    | "varp"
+    | \string
+  }
+table-data-pilot-subtotals =
+  element table:data-pilot-subtotals { table-data-pilot-subtotal* }
+table-data-pilot-table =
+  element table:data-pilot-table {
+    table-data-pilot-table-attlist,
+    (table-database-source-sql
+     | table-database-source-table
+     | table-database-source-query
+     | table-source-service
+     | table-source-cell-range)?,
+    table-data-pilot-field+
+  }
+table-data-pilot-table-attlist =
+  attribute table:name { \string }
+  & attribute table:application-data { \string }?
+  & attribute table:grand-total { "none" | "row" | "column" | "both" }?
+  & attribute table:ignore-empty-rows { boolean }?
+  & attribute table:identify-categories { boolean }?
+  & attribute table:target-range-address { cellRangeAddress }
+  & attribute table:buttons { cellRangeAddressList }?
+  & attribute table:show-filter-button { boolean }?
+  & attribute table:drill-down-on-double-click { boolean }?
+table-data-pilot-tables =
+  element table:data-pilot-tables { table-data-pilot-table* }
+table-database-range =
+  element table:database-range {
+    table-database-range-attlist,
+    (table-database-source-sql
+     | table-database-source-table
+     | table-database-source-query)?,
+    table-filter?,
+    table-sort?,
+    table-subtotal-rules?
+  }
+table-database-range-attlist =
+  attribute table:name { \string }?
+  & attribute table:is-selection { boolean }?
+  & attribute table:on-update-keep-styles { boolean }?
+  & attribute table:on-update-keep-size { boolean }?
+  & attribute table:has-persistent-data { boolean }?
+  & attribute table:orientation { "column" | "row" }?
+  & attribute table:contains-header { boolean }?
+  & attribute table:display-filter-buttons { boolean }?
+  & attribute table:target-range-address { cellRangeAddress }
+  & attribute table:refresh-delay { boolean }?
+table-database-ranges =
+  element table:database-ranges { table-database-range* }
+table-database-source-query =
+  element table:database-source-table {
+    table-database-source-table-attlist, empty
+  }
+table-database-source-query-attlist =
+  attribute table:database-name { \string }
+  & attribute table:query-name { \string }
+table-database-source-sql =
+  element table:database-source-sql {
+    table-database-source-sql-attlist, empty
+  }
+table-database-source-sql-attlist =
+  attribute table:database-name { \string }
+  & attribute table:sql-statement { \string }
+  & attribute table:parse-sql-statement { boolean }?
+table-database-source-table =
+  element table:database-source-query {
+    table-database-source-query-attlist, empty
+  }
+table-database-source-table-attlist =
+  attribute table:database-name { \string }
+  & attribute table:database-table-name { \string }
+table-dde-link =
+  element table:dde-link { office-dde-source, table-table }
+table-dde-links = element table:dde-links { table-dde-link+ }
+table-decls =
+  table-calculation-settings?,
+  table-content-validations?,
+  table-label-ranges?
+table-deletion =
+  element table:deletion {
+    table-deletion-attlist,
+    common-table-change-attlist,
+    office-change-info,
+    table-dependencies?,
+    table-deletions?,
+    table-cut-offs?
+  }
+table-deletion-attlist =
+  attribute table:type { "row" | "column" | "table" }
+  & attribute table:position { integer }
+  & attribute table:table { integer }?
+  & attribute table:multi-deletion-spanned { integer }?
+table-deletions =
+  element table:deletions {
+    (table-cell-content-deletion | table-change-deletion)+
+  }
+table-dependencies = element table:dependencies { table-dependency+ }
+table-dependency =
+  element table:dependency {
+    attribute table:id { \string },
+    empty
+  }
+table-desc = element table:desc { text }
+table-detective =
+  element table:detective { table-highlighted-range*, table-operation* }
+table-error-macro =
+  element table:error-macro {
+    attribute table:execute { boolean }?
+  }
+table-error-message =
+  element table:error-message {
+    attribute table:title { \string }?,
+    attribute table:display { boolean }?,
+    attribute table:message-type {
+      "stop" | "warning" | "information"
+    }?,
+    text-p*
+  }
+table-even-columns =
+  element table:even-columns { common-table-template-attlist, empty }
+table-even-rows =
+  element table:even-rows { common-table-template-attlist, empty }
+table-filter =
+  element table:filter {
+    table-filter-attlist,
+    (table-filter-condition | table-filter-and | table-filter-or)
+  }
+table-filter-and =
+  element table:filter-and {
+    (table-filter-or | table-filter-condition)+
+  }
+table-filter-attlist =
+  attribute table:target-range-address { cellRangeAddress }?
+  & attribute table:condition-source { "self" | "cell-range" }?
+  & attribute table:condition-source-range-address { cellRangeAddress }?
+  & attribute table:display-duplicates { boolean }?
+table-filter-condition =
+  element table:filter-condition {
+    table-filter-condition-attlist, table-filter-set-item*
+  }
+table-filter-condition-attlist =
+  attribute table:field-number { nonNegativeInteger }
+  & attribute table:value { \string | double }
+  & attribute table:operator { \string }
+  & attribute table:case-sensitive { \string }?
+  & attribute table:data-type { "text" | "number" }?
+table-filter-or =
+  element table:filter-or {
+    (table-filter-and | table-filter-condition)+
+  }
+table-filter-set-item =
+  element table:filter-set-item {
+    attribute table:value { \string },
+    empty
+  }
+table-first-column =
+  element table:first-column { common-table-template-attlist, empty }
+table-first-row =
+  element table:first-row { common-table-template-attlist, empty }
+table-functions =
+  table-named-expressions?,
+  table-database-ranges?,
+  table-data-pilot-tables?,
+  table-consolidation?,
+  table-dde-links?
+table-help-message =
+  element table:help-message {
+    attribute table:title { \string }?,
+    attribute table:display { boolean }?,
+    text-p*
+  }
+table-highlighted-range =
+  element table:highlighted-range {
+    (table-highlighted-range-attlist
+     | table-highlighted-range-attlist-invalid),
+    empty
+  }
+table-highlighted-range-attlist =
+  attribute table:cell-range-address { cellRangeAddress }?
+  & attribute table:direction {
+      "from-another-table" | "to-another-table" | "from-same-table"
+    }
+  & attribute table:contains-error { boolean }?
+table-highlighted-range-attlist-invalid =
+  attribute table:marked-invalid { boolean }
+table-insertion =
+  element table:insertion {
+    table-insertion-attlist,
+    common-table-change-attlist,
+    office-change-info,
+    table-dependencies?,
+    table-deletions?
+  }
+table-insertion-attlist =
+  attribute table:type { "row" | "column" | "table" }
+  & attribute table:position { integer }
+  & attribute table:count { positiveInteger }?
+  & attribute table:table { integer }?
+table-insertion-cut-off =
+  element table:insertion-cut-off {
+    table-insertion-cut-off-attlist, empty
+  }
+table-insertion-cut-off-attlist =
+  attribute table:id { \string }
+  & attribute table:position { integer }
+table-iteration =
+  element table:iteration {
+    attribute table:status { "enable" | "disable" }?,
+    attribute table:steps { positiveInteger }?,
+    attribute table:maximum-difference { double }?,
+    empty
+  }
+table-label-range =
+  element table:label-range { table-label-range-attlist, empty }
+table-label-range-attlist =
+  attribute table:label-cell-range-address { cellRangeAddress }
+  & attribute table:data-cell-range-address { cellRangeAddress }
+  & attribute table:orientation { "column" | "row" }
+table-label-ranges = element table:label-ranges { table-label-range* }
+table-last-column =
+  element table:last-column { common-table-template-attlist, empty }
+table-last-row =
+  element table:last-row { common-table-template-attlist, empty }
+table-linked-source-attlist =
+  attribute xlink:type { "simple" }
+  & attribute xlink:href { anyIRI }
+  & attribute xlink:actuate { "onRequest" }?
+  & attribute table:filter-name { \string }?
+  & attribute table:filter-options { \string }?
+  & attribute table:refresh-delay { duration }?
+table-movement =
+  element table:movement {
+    common-table-change-attlist,
+    table-source-range-address,
+    table-target-range-address,
+    office-change-info,
+    table-dependencies?,
+    table-deletions?
+  }
+table-movement-cut-off =
+  element table:movement-cut-off {
+    table-movement-cut-off-attlist, empty
+  }
+table-movement-cut-off-attlist =
+  attribute table:position { integer }
+  | (attribute table:start-position { integer },
+     attribute table:end-position { integer })
+table-named-expression =
+  element table:named-expression {
+    table-named-expression-attlist, empty
+  }
+table-named-expression-attlist =
+  attribute table:name { \string },
+  attribute table:expression { \string },
+  attribute table:base-cell-address { cellAddress }?
+table-named-expressions =
+  element table:named-expressions {
+    (table-named-range | table-named-expression)*
+  }
+table-named-range =
+  element table:named-range { table-named-range-attlist, empty }
+table-named-range-attlist =
+  attribute table:name { \string },
+  attribute table:cell-range-address { cellRangeAddress },
+  attribute table:base-cell-address { cellAddress }?,
+  attribute table:range-usable-as {
+    "none"
+    | list {
+        ("print-range" | "filter" | "repeat-row" | "repeat-column")+
+      }
+  }?
+table-null-date =
+  element table:null-date {
+    attribute table:value-type { "date" }?,
+    attribute table:date-value { date }?,
+    empty
+  }
+table-odd-columns =
+  element table:odd-columns { common-table-template-attlist, empty }
+table-odd-rows =
+  element table:odd-rows { common-table-template-attlist, empty }
+table-operation =
+  element table:operation { table-operation-attlist, empty }
+table-operation-attlist =
+  attribute table:name {
+    "trace-dependents"
+    | "remove-dependents"
+    | "trace-precedents"
+    | "remove-precedents"
+    | "trace-errors"
+  }
+  & attribute table:index { nonNegativeInteger }
+table-previous =
+  element table:previous {
+    attribute table:id { \string }?,
+    table-change-track-table-cell
+  }
+table-rows =
+  table-table-rows | (text-soft-page-break?, table-table-row)+
+table-rows-and-groups = (table-table-row-group | table-rows-no-group)+
+table-rows-no-group =
+  (table-rows, (table-table-header-rows, table-rows?)?)
+  | (table-table-header-rows, table-rows?)
+table-scenario =
+  element table:scenario { table-scenario-attlist, empty }
+table-scenario-attlist =
+  attribute table:scenario-ranges { cellRangeAddressList }
+  & attribute table:is-active { boolean }
+  & attribute table:display-border { boolean }?
+  & attribute table:border-color { color }?
+  & attribute table:copy-back { boolean }?
+  & attribute table:copy-styles { boolean }?
+  & attribute table:copy-formulas { boolean }?
+  & attribute table:comment { \string }?
+  & attribute table:protected { boolean }?
+table-shapes = element table:shapes { shape+ }
+table-sort = element table:sort { table-sort-attlist, table-sort-by+ }
+table-sort-attlist =
+  attribute table:bind-styles-to-content { boolean }?
+  & attribute table:target-range-address { cellRangeAddress }?
+  & attribute table:case-sensitive { boolean }?
+  & attribute table:language { languageCode }?
+  & attribute table:country { countryCode }?
+  & attribute table:script { scriptCode }?
+  & attribute table:rfc-language-tag { language }?
+  & attribute table:algorithm { \string }?
+  & attribute table:embedded-number-behavior {
+      "alpha-numeric" | "integer" | "double"
     }?
-  & attribute fo:clip { "auto" | clipShape }?
-  & attribute draw:wrap-influence-on-position {
-      "iterative" | "once-concurrent" | "once-successive"
+table-sort-by = element table:sort-by { table-sort-by-attlist, empty }
+table-sort-by-attlist =
+  attribute table:field-number { nonNegativeInteger }
+  & attribute table:data-type {
+      "text" | "number" | "automatic" | \string
     }?
-  & common-writing-mode-attlist
-  & attribute draw:frame-display-scrollbar { boolean }?
-  & attribute draw:frame-display-border { boolean }?
-  & attribute draw:frame-margin-horizontal { nonNegativePixelLength }?
-  & attribute draw:frame-margin-vertical { nonNegativePixelLength }?
-  & attribute draw:visible-area-left { nonNegativeLength }?
-  & attribute draw:visible-area-top { nonNegativeLength }?
-  & attribute draw:visible-area-width { positiveLength }?
-  & attribute draw:visible-area-height { positiveLength }?
-  & attribute draw:draw-aspect {
-      "content" | "thumbnail" | "icon" | "print-view"
+  & attribute table:order { "ascending" | "descending" }?
+table-sort-groups =
+  element table:sort-groups { table-sort-groups-attlist, empty }
+table-sort-groups-attlist =
+  attribute table:data-type {
+    "text" | "number" | "automatic" | \string
+  }?
+  & attribute table:order { "ascending" | "descending" }?
+table-source-cell-range =
+  element table:source-cell-range {
+    table-source-cell-range-attlist, table-filter?
+  }
+table-source-cell-range-attlist =
+  # OFFICE-3665
+  (attribute table:cell-range-address { cellRangeAddress }
+   | (attribute table:name { \string },
+      attribute table:cell-range-address { cellRangeAddress }?))
+table-source-range-address =
+  element table:source-range-address {
+    common-table-range-attlist, empty
+  }
+table-source-service =
+  element table:source-service { table-source-service-attlist, empty }
+table-source-service-attlist =
+  attribute table:name { \string }
+  & attribute table:source-name { \string }
+  & attribute table:object-name { \string }
+  & attribute table:user-name { \string }?
+  & attribute table:password { \string }?
+table-subtotal-field =
+  element table:subtotal-field { table-subtotal-field-attlist, empty }
+table-subtotal-field-attlist =
+  attribute table:field-number { nonNegativeInteger }
+  & attribute table:function {
+      "average"
+      | "count"
+      | "countnums"
+      | "max"
+      | "min"
+      | "product"
+      | "stdev"
+      | "stdevp"
+      | "sum"
+      | "var"
+      | "varp"
+      | \string
+    }
+table-subtotal-rule =
+  element table:subtotal-rule {
+    table-subtotal-rule-attlist, table-subtotal-field*
+  }
+table-subtotal-rule-attlist =
+  attribute table:group-by-field-number { nonNegativeInteger }
+table-subtotal-rules =
+  element table:subtotal-rules {
+    table-subtotal-rules-attlist,
+    table-sort-groups?,
+    table-subtotal-rule*
+  }
+table-subtotal-rules-attlist =
+  attribute table:bind-styles-to-content { boolean }?
+  & attribute table:case-sensitive { boolean }?
+  & attribute table:page-breaks-on-group-change { boolean }?
+table-table =
+  element table:table {
+    table-table-attlist,
+    table-title?,
+    table-desc?,
+    table-table-source?,
+    office-dde-source?,
+    table-scenario?,
+    office-forms?,
+    table-shapes?,
+    table-columns-and-groups,
+    table-rows-and-groups,
+    table-named-expressions?
+  }
+table-table-attlist =
+  attribute table:name { \string }?
+  & attribute table:style-name { styleNameRef }?
+  & attribute table:template-name { \string }?
+  & attribute table:use-first-row-styles { boolean }?
+  & attribute table:use-last-row-styles { boolean }?
+  & attribute table:use-first-column-styles { boolean }?
+  & attribute table:use-last-column-styles { boolean }?
+  & attribute table:use-banding-rows-styles { boolean }?
+  & attribute table:use-banding-columns-styles { boolean }?
+  & attribute table:protected { boolean }?
+  & attribute table:protection-key { \string }?
+  & attribute table:protection-key-digest-algorithm { anyIRI }?
+  & attribute table:print { boolean }?
+  & attribute table:print-ranges { cellRangeAddressList }?
+  & xml-id?
+  & attribute table:is-sub-table { boolean }?
+table-table-cell =
+  element table:table-cell {
+    table-table-cell-attlist,
+    table-table-cell-attlist-extra,
+    table-table-cell-content
+  }
+table-table-cell-attlist =
+  attribute table:number-columns-repeated { positiveInteger }?
+  & attribute table:style-name { styleNameRef }?
+  & attribute table:content-validation-name { \string }?
+  & attribute table:formula { \string }?
+  & common-value-and-type-attlist?
+  & attribute table:protect { boolean }?
+  & attribute table:protected { boolean }?
+  & xml-id?
+  & common-in-content-meta-attlist?
+table-table-cell-attlist-extra =
+  attribute table:number-columns-spanned { positiveInteger }?
+  & attribute table:number-rows-spanned { positiveInteger }?
+  & attribute table:number-matrix-columns-spanned { positiveInteger }?
+  & attribute table:number-matrix-rows-spanned { positiveInteger }?
+table-table-cell-content =
+  table-cell-range-source?,
+  office-annotation?,
+  table-detective?,
+  text-content*
+table-table-cell-range-source-attlist =
+  attribute table:name { \string }
+  & attribute table:last-column-spanned { positiveInteger }
+  & attribute table:last-row-spanned { positiveInteger }
+table-table-column =
+  element table:table-column { table-table-column-attlist, empty }
+table-table-column-attlist =
+  attribute table:number-columns-repeated { positiveInteger }?
+  & attribute table:style-name { styleNameRef }?
+  & attribute table:visibility { table-visibility-value }?
+  & attribute table:default-cell-style-name { styleNameRef }?
+  & xml-id?
+table-table-column-group =
+  element table:table-column-group {
+    table-table-column-group-attlist, table-columns-and-groups
+  }
+table-table-column-group-attlist = attribute table:display { boolean }?
+table-table-columns =
+  element table:table-columns { table-table-column+ }
+table-table-header-columns =
+  element table:table-header-columns { table-table-column+ }
+table-table-header-rows =
+  element table:table-header-rows {
+    (text-soft-page-break?, table-table-row)+
+  }
+table-table-row =
+  element table:table-row {
+    table-table-row-attlist,
+    (table-table-cell | table-covered-table-cell)+
+  }
+table-table-row-attlist =
+  attribute table:number-rows-repeated { positiveInteger }?
+  & attribute table:style-name { styleNameRef }?
+  & attribute table:default-cell-style-name { styleNameRef }?
+  & attribute table:visibility { table-visibility-value }?
+  & xml-id?
+table-table-row-group =
+  element table:table-row-group {
+    table-table-row-group-attlist, table-rows-and-groups
+  }
+table-table-row-group-attlist = attribute table:display { boolean }?
+table-table-rows =
+  element table:table-rows { (text-soft-page-break?, table-table-row)+ }
+table-table-source =
+  element table:table-source {
+    table-table-source-attlist, table-linked-source-attlist, empty
+  }
+table-table-source-attlist =
+  attribute table:mode { "copy-all" | "copy-results-only" }?
+  & attribute table:table-name { \string }?
+table-table-template =
+  element table:table-template {
+    table-table-template-attlist,
+    table-first-row?,
+    table-last-row?,
+    table-first-column?,
+    table-last-column?,
+    table-body,
+    table-even-rows?,
+    table-odd-rows?,
+    table-even-columns?,
+    table-odd-columns?,
+    table-background?
+  }
+table-table-template-attlist =
+  attribute table:name { \string }
+  & attribute table:first-row-start-column { rowOrCol }
+  & attribute table:first-row-end-column { rowOrCol }
+  & attribute table:last-row-start-column { rowOrCol }
+  & attribute table:last-row-end-column { rowOrCol }
+table-target-range-address =
+  element table:target-range-address {
+    common-table-range-attlist, empty
+  }
+table-title = element table:title { text }
+table-tracked-changes =
+  element table:tracked-changes {
+    table-tracked-changes-attlist,
+    (table-cell-content-change
+     | table-insertion
+     | table-deletion
+     | table-movement)*
+  }
+table-tracked-changes-attlist =
+  attribute table:track-changes { boolean }?
+table-validation-attlist =
+  attribute table:name { \string }
+  & attribute table:condition { \string }?
+  & attribute table:base-cell-address { cellAddress }?
+  & attribute table:allow-empty-cell { boolean }?
+  & attribute table:display-list {
+      "none" | "unsorted" | "sort-ascending"
     }?
-  & attribute draw:ole-draw-aspect { nonNegativeInteger }?
-style-graphic-fill-properties-attlist =
-  attribute draw:fill {
-    "none" | "solid" | "bitmap" | "gradient" | "hatch"
+table-visibility-value = "visible" | "collapse" | "filter"
+target-frame = attribute office:target-frame { targetFrameName }?
+target-location = attribute xlink:href { anyIRI }?
+targetFrameName = "_self" | "_blank" | "_parent" | "_top" | \string
+text-a =
+  element text:a {
+    text-a-attlist, office-event-listeners?, paragraph-content*
+  }
+text-a-attlist =
+  attribute office:name { \string }?
+  & attribute office:title { \string }?
+  & attribute xlink:type { "simple" }
+  & attribute xlink:href { anyIRI }
+  & attribute xlink:actuate { "onRequest" }?
+  & attribute office:target-frame-name { targetFrameName }?
+  & attribute xlink:show { "new" | "replace" }?
+  & attribute text:style-name { styleNameRef }?
+  & attribute text:visited-style-name { styleNameRef }?
+text-alphabetical-index =
+  element text:alphabetical-index {
+    common-section-attlist,
+    text-alphabetical-index-source,
+    text-index-body
+  }
+text-alphabetical-index-auto-mark-file =
+  element text:alphabetical-index-auto-mark-file {
+    attribute xlink:type { "simple" },
+    attribute xlink:href { anyIRI }
+  }
+text-alphabetical-index-entry-template =
+  element text:alphabetical-index-entry-template {
+    text-alphabetical-index-entry-template-attrs,
+    (text-index-entry-chapter
+     | text-index-entry-page-number
+     | text-index-entry-text
+     | text-index-entry-span
+     | text-index-entry-tab-stop)*
+  }
+text-alphabetical-index-entry-template-attrs =
+  attribute text:outline-level { "1" | "2" | "3" | "separator" }
+  & attribute text:style-name { styleNameRef }
+text-alphabetical-index-mark-attrs =
+  attribute text:key1 { \string }?
+  & attribute text:key2 { \string }?
+  & attribute text:string-value-phonetic { \string }?
+  & attribute text:key1-phonetic { \string }?
+  & attribute text:key2-phonetic { \string }?
+  & attribute text:main-entry { boolean }?
+text-alphabetical-index-source =
+  element text:alphabetical-index-source {
+    text-alphabetical-index-source-attrs,
+    text-index-title-template?,
+    text-alphabetical-index-entry-template*
+  }
+text-alphabetical-index-source-attrs =
+  text-index-scope-attr
+  & text-relative-tab-stop-position-attr
+  & attribute text:ignore-case { boolean }?
+  & attribute text:main-entry-style-name { styleNameRef }?
+  & attribute text:alphabetical-separators { boolean }?
+  & attribute text:combine-entries { boolean }?
+  & attribute text:combine-entries-with-dash { boolean }?
+  & attribute text:combine-entries-with-pp { boolean }?
+  & attribute text:use-keys-as-entries { boolean }?
+  & attribute text:capitalize-entries { boolean }?
+  & attribute text:comma-separated { boolean }?
+  & attribute fo:language { languageCode }?
+  & attribute fo:country { countryCode }?
+  & attribute fo:script { scriptCode }?
+  & attribute style:rfc-language-tag { language }?
+  & attribute text:sort-algorithm { \string }?
+text-bibliography =
+  element text:bibliography {
+    common-section-attlist, text-bibliography-source, text-index-body
+  }
+text-bibliography-configuration =
+  element text:bibliography-configuration {
+    text-bibliography-configuration-attlist, text-sort-key*
+  }
+text-bibliography-configuration-attlist =
+  attribute text:prefix { \string }?
+  & attribute text:suffix { \string }?
+  & attribute text:numbered-entries { boolean }?
+  & attribute text:sort-by-position { boolean }?
+  & attribute fo:language { languageCode }?
+  & attribute fo:country { countryCode }?
+  & attribute fo:script { scriptCode }?
+  & attribute style:rfc-language-tag { language }?
+  & attribute text:sort-algorithm { \string }?
+text-bibliography-entry-template =
+  element text:bibliography-entry-template {
+    text-bibliography-entry-template-attrs,
+    (text-index-entry-span
+     | text-index-entry-tab-stop
+     | text-index-entry-bibliography)*
+  }
+text-bibliography-entry-template-attrs =
+  attribute text:bibliography-type { text-bibliography-types }
+  & attribute text:style-name { styleNameRef }
+text-bibliography-source =
+  element text:bibliography-source {
+    text-index-title-template?, text-bibliography-entry-template*
+  }
+text-bibliography-types =
+  "article"
+  | "book"
+  | "booklet"
+  | "conference"
+  | "custom1"
+  | "custom2"
+  | "custom3"
+  | "custom4"
+  | "custom5"
+  | "email"
+  | "inbook"
+  | "incollection"
+  | "inproceedings"
+  | "journal"
+  | "manual"
+  | "mastersthesis"
+  | "misc"
+  | "phdthesis"
+  | "proceedings"
+  | "techreport"
+  | "unpublished"
+  | "www"
+text-bookmark = element text:bookmark { text-bookmark-attlist, empty }
+text-bookmark-attlist =
+  attribute text:name { \string }
+  & xml-id?
+text-bookmark-end =
+  element text:bookmark-end { text-bookmark-end-attlist, empty }
+text-bookmark-end-attlist = attribute text:name { \string }
+text-bookmark-ref-content =
+  attribute text:reference-format {
+    common-ref-format-values
+    | "number-no-superior"
+    | "number-all-superior"
+    | "number"
   }?
-  & attribute draw:fill-color { color }?
-  & attribute draw:secondary-fill-color { color }?
-  & attribute draw:fill-gradient-name { styleNameRef }?
-  & attribute draw:gradient-step-count { nonNegativeInteger }?
-  & attribute draw:fill-hatch-name { styleNameRef }?
-  & attribute draw:fill-hatch-solid { boolean }?
-  & attribute draw:fill-image-name { styleNameRef }?
-  & attribute style:repeat { "no-repeat" | "repeat" | "stretch" }?
-  & attribute draw:fill-image-width { length | percent }?
-  & attribute draw:fill-image-height { length | percent }?
-  & attribute draw:fill-image-ref-point-x { percent }?
-  & attribute draw:fill-image-ref-point-y { percent }?
-  & attribute draw:fill-image-ref-point {
-      "top-left"
-      | "top"
-      | "top-right"
-      | "left"
-      | "center"
-      | "right"
-      | "bottom-left"
-      | "bottom"
-      | "bottom-right"
-    }?
-  & attribute draw:tile-repeat-offset {
-      list { zeroToHundredPercent, ("horizontal" | "vertical") }
+text-bookmark-start =
+  element text:bookmark-start { text-bookmark-start-attlist, empty }
+text-bookmark-start-attlist =
+  attribute text:name { \string }
+  & xml-id?
+  & common-in-content-meta-attlist?
+text-changed-region =
+  element text:changed-region {
+    text-changed-region-attr, text-changed-region-content
+  }
+text-changed-region-attr =
+  xml-id,
+  attribute text:id { NCName }?
+text-changed-region-content =
+  element text:insertion { office-change-info }
+  | element text:deletion { office-change-info, text-content* }
+  | element text:format-change { office-change-info }
+text-chapter-attlist =
+  attribute text:display {
+    "name"
+    | "number"
+    | "number-and-name"
+    | "plain-number-and-name"
+    | "plain-number"
+  }
+  & attribute text:outline-level { nonNegativeInteger }
+text-common-ref-content =
+  text
+  & attribute text:ref-name { \string }?
+text-conditional-text-attlist =
+  attribute text:condition { \string }
+  & attribute text:string-value-if-true { \string }
+  & attribute text:string-value-if-false { \string }
+  & attribute text:current-value { boolean }?
+text-content =
+  text-h
+  | text-p
+  | text-list
+  | text-numbered-paragraph
+  | table-table
+  | text-section
+  | text-soft-page-break
+  | text-table-of-content
+  | text-illustration-index
+  | text-table-index
+  | text-object-index
+  | text-user-index
+  | text-alphabetical-index
+  | text-bibliography
+  | shape
+  | change-marks
+text-database-display-attlist =
+  common-field-database-table
+  & common-field-data-style-name-attlist
+  & attribute text:column-name { \string }
+text-database-next-attlist =
+  common-field-database-table
+  & attribute text:condition { \string }?
+text-database-row-select-attlist =
+  common-field-database-table
+  & attribute text:condition { \string }?
+  & attribute text:row-number { nonNegativeInteger }?
+text-date-attlist =
+  (common-field-fixed-attlist & common-field-data-style-name-attlist)
+  & attribute text:date-value { dateOrDateTime }?
+  & attribute text:date-adjust { duration }?
+text-dde-connection-decl =
+  element text:dde-connection-decl {
+    text-dde-connection-decl-attlist, common-dde-connection-decl-attlist
+  }
+text-dde-connection-decl-attlist = attribute office:name { \string }
+text-decls =
+  element text:variable-decls { text-variable-decl* }?,
+  element text:sequence-decls { text-sequence-decl* }?,
+  element text:user-field-decls { text-user-field-decl* }?,
+  element text:dde-connection-decls { text-dde-connection-decl* }?,
+  text-alphabetical-index-auto-mark-file?
+text-drop-down =
+  element text:drop-down {
+    attribute text:name { \string },
+    element text:label {
+      attribute text:value { \string }?,
+      attribute text:current-selected { boolean }?
+    }*,
+    text
+  }
+text-file-name-attlist =
+  attribute text:display {
+    "full" | "path" | "name" | "name-and-extension"
+  }?
+  & common-field-fixed-attlist
+text-get-page-variable-attlist = common-field-num-format-attlist
+text-h =
+  element text:h {
+    heading-attrs,
+    paragraph-attrs,
+    text-number?,
+    paragraph-content-or-hyperlink*
+  }
+text-hidden-paragraph-attlist =
+  attribute text:condition { \string }
+  & attribute text:is-hidden { boolean }?
+text-hidden-text-attlist =
+  attribute text:condition { \string }
+  & attribute text:string-value { \string }
+  & attribute text:is-hidden { boolean }?
+text-id = attribute text:id { \string }
+text-illustration-index =
+  element text:illustration-index {
+    common-section-attlist,
+    text-illustration-index-source,
+    text-index-body
+  }
+text-illustration-index-entry-content =
+  text-illustration-index-entry-template-attrs,
+  (text-index-entry-chapter
+   | text-index-entry-page-number
+   | text-index-entry-text
+   | text-index-entry-span
+   | text-index-entry-tab-stop
+   | text-index-entry-link-start
+   | text-index-entry-link-end
+     # https://issues.oasis-open.org/browse/OFFICE-3941
+     )*
+text-illustration-index-entry-template =
+  element text:illustration-index-entry-template {
+    text-illustration-index-entry-content
+  }
+text-illustration-index-entry-template-attrs =
+  attribute text:style-name { styleNameRef }
+text-illustration-index-source =
+  element text:illustration-index-source {
+    text-illustration-index-source-attrs,
+    text-index-title-template?,
+    text-illustration-index-entry-template?
+  }
+text-illustration-index-source-attrs =
+  text-index-scope-attr
+  & text-relative-tab-stop-position-attr
+  & attribute text:use-caption { boolean }?
+  & attribute text:caption-sequence-name { \string }?
+  & attribute text:caption-sequence-format {
+      "text" | "category-and-value" | "caption"
     }?
-  & attribute draw:opacity { zeroToHundredPercent }?
-  & attribute draw:opacity-name { styleNameRef }?
-  & attribute svg:fill-rule { "nonzero" | "evenodd" }?
-style-graphic-properties-elements =
-  text-list-style? & style-background-image & style-columns
-common-vertical-pos-attlist =
-  attribute style:vertical-pos {
-    "top" | "middle" | "bottom" | "from-top" | "below"
-  }?,
-  attribute svg:y { coordinate }?
-common-vertical-rel-attlist =
-  attribute style:vertical-rel {
-    "page"
-    | "page-content"
-    | "frame"
-    | "frame-content"
-    | "paragraph"
-    | "paragraph-content"
-    | "char"
-    | "line"
-    | "baseline"
-    | "text"
+text-index-body = element text:index-body { index-content-main* }
+text-index-entry-bibliography =
+  element text:index-entry-bibliography {
+    text-index-entry-bibliography-attrs
+  }
+text-index-entry-bibliography-attrs =
+  attribute text:style-name { styleNameRef }?
+  & attribute text:bibliography-data-field {
+      "address"
+      | "annote"
+      | "author"
+      | "bibliography-type"
+      | "booktitle"
+      | "chapter"
+      | "custom1"
+      | "custom2"
+      | "custom3"
+      | "custom4"
+      | "custom5"
+      | "edition"
+      | "editor"
+      | "howpublished"
+      | "identifier"
+      | "institution"
+      | "isbn"
+      | "issn"
+      | "journal"
+      | "month"
+      | "note"
+      | "number"
+      | "organizations"
+      | "pages"
+      | "publisher"
+      | "report-type"
+      | "school"
+      | "series"
+      | "title"
+      | "url"
+      | "volume"
+      | "year"
+    }
+text-index-entry-chapter =
+  element text:index-entry-chapter {
+    attribute text:style-name { styleNameRef }?,
+    text-index-entry-chapter-attrs
+  }
+text-index-entry-chapter-attrs =
+  attribute text:display {
+    "name"
+    | "number"
+    | "number-and-name"
+    | "plain-number"
+    | "plain-number-and-name"
   }?
-common-editable-attlist = attribute style:editable { boolean }?
-horizontal-mirror =
-  "horizontal" | "horizontal-on-odd" | "horizontal-on-even"
-clipShape =
-  xsd:string {
-    pattern =
-      "rect\([ 
]*((-?([0-9]+(\.[0-9]*)?|\.[0-9]+)((cm)|(mm)|(in)|(pt)|(pc)))|(auto))([ ]*,[ 
]*((-?([0-9]+(\.[0-9]*)?|\.[0-9]+)((cm)|(mm)|(in)|(pt)|(pc))))|(auto)){3}[ ]*\)"
+  & attribute text:outline-level { positiveInteger }?
+text-index-entry-link-end =
+  element text:index-entry-link-end {
+    attribute text:style-name { styleNameRef }?
   }
-nonNegativePixelLength =
-  xsd:string { pattern = "([0-9]+(\.[0-9]*)?|\.[0-9]+)(px)" }
-style-chart-properties =
-  element style:chart-properties {
-    style-chart-properties-content-strict
+text-index-entry-link-start =
+  element text:index-entry-link-start {
+    attribute text:style-name { styleNameRef }?
   }
-style-chart-properties-content-strict =
-  style-chart-properties-attlist, style-chart-properties-elements
-style-chart-properties-elements = empty
-style-chart-properties-attlist =
-  attribute chart:scale-text { boolean }?
-  & attribute chart:three-dimensional { boolean }?
-  & attribute chart:deep { boolean }?
-  & attribute chart:right-angled-axes { boolean }?
-  & (attribute chart:symbol-type { "none" }
-     | attribute chart:symbol-type { "automatic" }
-     | (attribute chart:symbol-type { "named-symbol" },
-        attribute chart:symbol-name {
-          "square"
-          | "diamond"
-          | "arrow-down"
-          | "arrow-up"
-          | "arrow-right"
-          | "arrow-left"
-          | "bow-tie"
-          | "hourglass"
-          | "circle"
-          | "star"
-          | "x"
-          | "plus"
-          | "asterisk"
-          | "horizontal-bar"
-          | "vertical-bar"
-        })
-     | (attribute chart:symbol-type { "image" },
-        element chart:symbol-image {
-          attribute xlink:href { anyIRI }
-        })
-     | empty)
-  & attribute chart:symbol-width { nonNegativeLength }?
-  & attribute chart:symbol-height { nonNegativeLength }?
-  & attribute chart:sort-by-x-values { boolean }?
-  & attribute chart:vertical { boolean }?
-  & attribute chart:connect-bars { boolean }?
-  & attribute chart:gap-width { integer }?
-  & attribute chart:overlap { integer }?
-  & attribute chart:group-bars-per-axis { boolean }?
-  & attribute chart:japanese-candle-stick { boolean }?
-  & attribute chart:interpolation {
-      "none" | "cubic-spline" | "b-spline"
-    }?
-  & attribute chart:spline-order { positiveInteger }?
-  & attribute chart:spline-resolution { positiveInteger }?
-  & attribute chart:pie-offset { nonNegativeInteger }?
-  & attribute chart:angle-offset { angle }?
-  & attribute chart:hole-size { percent }?
-  & attribute chart:lines { boolean }?
-  & attribute chart:solid-type {
-      "cuboid" | "cylinder" | "cone" | "pyramid"
-    }?
-  & attribute chart:stacked { boolean }?
-  & attribute chart:percentage { boolean }?
-  & attribute chart:treat-empty-cells {
-      "use-zero" | "leave-gap" | "ignore"
-    }?
-  & attribute chart:link-data-style-to-source { boolean }?
-  & attribute chart:logarithmic { boolean }?
-  & attribute chart:maximum { double }?
-  & attribute chart:minimum { double }?
-  & attribute chart:origin { double }?
-  & attribute chart:interval-major { double }?
-  & attribute chart:interval-minor-divisor { positiveInteger }?
-  & attribute chart:tick-marks-major-inner { boolean }?
-  & attribute chart:tick-marks-major-outer { boolean }?
-  & attribute chart:tick-marks-minor-inner { boolean }?
-  & attribute chart:tick-marks-minor-outer { boolean }?
-  & attribute chart:reverse-direction { boolean }?
-  & attribute chart:display-label { boolean }?
-  & attribute chart:text-overlap { boolean }?
-  & attribute text:line-break { boolean }?
-  & attribute chart:label-arrangement {
-      "side-by-side" | "stagger-even" | "stagger-odd"
-    }?
-  & common-style-direction-attlist
-  & common-rotation-angle-attlist
-  & attribute chart:data-label-number {
-      "none" | "value" | "percentage" | "value-and-percentage"
-    }?
-  & attribute chart:data-label-text { boolean }?
-  & attribute chart:data-label-symbol { boolean }?
-  & element chart:label-separator { text-p }?
-  & attribute chart:label-position { labelPositions }?
-  & attribute chart:label-position-negative { labelPositions }?
-  & attribute chart:visible { boolean }?
-  & attribute chart:auto-position { boolean }?
-  & attribute chart:auto-size { boolean }?
-  & attribute chart:mean-value { boolean }?
-  & attribute chart:error-category {
-      "none"
-      | "variance"
-      | "standard-deviation"
-      | "percentage"
-      | "error-margin"
-      | "constant"
-      | "standard-error"
-      | "cell-range"
-    }?
-  & attribute chart:error-percentage { double }?
-  & attribute chart:error-margin { double }?
-  & attribute chart:error-lower-limit { double }?
-  & attribute chart:error-upper-limit { double }?
-  & attribute chart:error-upper-indicator { boolean }?
-  & attribute chart:error-lower-indicator { boolean }?
-  & attribute chart:error-lower-range { cellRangeAddressList }?
-  & attribute chart:error-upper-range { cellRangeAddressList }?
-  & attribute chart:series-source { "columns" | "rows" }?
-  & attribute chart:regression-type {
-      "none" | "linear" | "logarithmic" | "exponential" | "power"
-    }?
-  & attribute chart:axis-position { "start" | "end" | double }?
-  & attribute chart:axis-label-position {
-      "near-axis"
-      | "near-axis-other-side"
-      | "outside-start"
-      | "outside-end"
+text-index-entry-page-number =
+  element text:index-entry-page-number {
+    attribute text:style-name { styleNameRef }?
+  }
+text-index-entry-span =
+  element text:index-entry-span {
+    attribute text:style-name { styleNameRef }?,
+    text
+  }
+text-index-entry-tab-stop =
+  element text:index-entry-tab-stop {
+    attribute text:style-name { styleNameRef }?,
+    text-index-entry-tab-stop-attrs
+  }
+text-index-entry-tab-stop-attrs =
+  attribute style:leader-char { character }?
+  & (attribute style:type { "right" }
+     | (attribute style:type { "left" },
+        attribute style:position { length }))
+text-index-entry-text =
+  element text:index-entry-text {
+    attribute text:style-name { styleNameRef }?
+  }
+text-index-name = attribute text:index-name { \string }
+text-index-scope-attr =
+  attribute text:index-scope { "document" | "chapter" }?
+text-index-source-style =
+  element text:index-source-style {
+    attribute text:style-name { styleNameRef },
+    empty
+  }
+# https://issues.oasis-open.org/browse/OFFICE-3675
+text-index-source-styles =
+  element text:index-source-styles {
+    attribute text:outline-level { positiveInteger },
+    text-index-source-style*
+  }
+text-index-title =
+  element text:index-title {
+    common-section-attlist, index-content-main*
+  }
+text-index-title-template =
+  element text:index-title-template {
+    attribute text:style-name { styleNameRef }?,
+    text
+  }
+text-linenumbering-configuration =
+  element text:linenumbering-configuration {
+    text-linenumbering-configuration-attlist,
+    text-linenumbering-separator?
+  }
+text-linenumbering-configuration-attlist =
+  attribute text:number-lines { boolean }?
+  & common-num-format-attlist?
+  & attribute text:style-name { styleNameRef }?
+  & attribute text:increment { nonNegativeInteger }?
+  & attribute text:number-position {
+      "left" | "right" | "inner" | "outer"
     }?
-  & attribute chart:tick-mark-position {
-      "at-labels" | "at-axis" | "at-labels-and-axis"
+  & attribute text:offset { nonNegativeLength }?
+  & attribute text:count-empty-lines { boolean }?
+  & attribute text:count-in-text-boxes { boolean }?
+  & attribute text:restart-on-page { boolean }?
+text-linenumbering-separator =
+  element text:linenumbering-separator {
+    attribute text:increment { nonNegativeInteger }?,
+    text
+  }
+text-list =
+  element text:list {
+    text-list-attr, text-list-header?, text-list-item*
+  }
+text-list-attr =
+  attribute text:style-name { styleNameRef }?
+  & attribute text:continue-numbering { boolean }?
+  & attribute text:continue-list { IDREF }?
+  & xml-id?
+text-list-header =
+  element text:list-header {
+    text-list-header-attr, text-list-item-content
+  }
+text-list-header-attr = xml-id?
+text-list-item =
+  element text:list-item { text-list-item-attr, text-list-item-content }
+text-list-item-attr =
+  attribute text:start-value { nonNegativeInteger }?
+  & attribute text:style-override { styleNameRef }?
+  & xml-id?
+text-list-item-content =
+  text-number?, (text-p | text-h | text-list | text-soft-page-break)*
+text-list-level-style-attr = attribute text:level { positiveInteger }
+text-list-level-style-bullet-attr =
+  attribute text:style-name { styleNameRef }?
+  & attribute text:bullet-char { character }
+  & common-num-format-prefix-suffix-attlist
+  & attribute text:bullet-relative-size { percent }?
+text-list-level-style-image-attr =
+  common-draw-data-attlist | office-binary-data
+text-list-level-style-number-attr =
+  attribute text:style-name { styleNameRef }?
+  & common-num-format-attlist
+  & common-num-format-prefix-suffix-attlist
+  & attribute text:display-levels { positiveInteger }?
+  & attribute text:start-value { positiveInteger }?
+text-list-style =
+  element text:list-style {
+    text-list-style-attr, text-list-style-content*
+  }
+text-list-style-attr =
+  attribute style:name { styleName }
+  & attribute style:display-name { \string }?
+  & attribute text:consecutive-numbering { boolean }?
+text-list-style-content =
+  element text:list-level-style-number {
+    text-list-level-style-attr,
+    text-list-level-style-number-attr,
+    style-list-level-properties?,
+    style-text-properties?
+  }
+  | element text:list-level-style-bullet {
+      text-list-level-style-attr,
+      text-list-level-style-bullet-attr,
+      style-list-level-properties?,
+      style-text-properties?
+    }
+  | element text:list-level-style-image {
+      text-list-level-style-attr,
+      text-list-level-style-image-attr,
+      style-list-level-properties?
+    }
+text-meta-attlist = common-in-content-meta-attlist? & xml-id?
+text-meta-field-attlist = xml-id & common-field-data-style-name-attlist
+text-note-class = attribute text:note-class { "footnote" | "endnote" }
+text-note-ref-content =
+  attribute text:reference-format { common-ref-format-values }?
+  & text-note-class
+text-notes-configuration =
+  element text:notes-configuration { text-notes-configuration-content }
+text-notes-configuration-content =
+  text-note-class
+  & attribute text:citation-style-name { styleNameRef }?
+  & attribute text:citation-body-style-name { styleNameRef }?
+  & attribute text:default-style-name { styleNameRef }?
+  & attribute text:master-page-name { styleNameRef }?
+  & attribute text:start-value { nonNegativeInteger }?
+  & common-num-format-prefix-suffix-attlist
+  & common-num-format-attlist?
+  & attribute text:start-numbering-at {
+      "document" | "chapter" | "page"
     }?
-  & attribute chart:include-hidden-cells { boolean }?
-labelPositions =
-  "avoid-overlap"
-  | "center"
-  | "top"
-  | "top-right"
-  | "right"
-  | "bottom-right"
-  | "bottom"
-  | "bottom-left"
-  | "left"
-  | "top-left"
-  | "inside"
-  | "outside"
-  | "near-origin"
-style-drawing-page-properties-attlist =
-  attribute presentation:transition-type {
-    "manual" | "automatic" | "semi-automatic"
-  }?
-  & attribute presentation:transition-style {
-      "none"
-      | "fade-from-left"
-      | "fade-from-top"
-      | "fade-from-right"
-      | "fade-from-bottom"
-      | "fade-from-upperleft"
-      | "fade-from-upperright"
-      | "fade-from-lowerleft"
-      | "fade-from-lowerright"
-      | "move-from-left"
-      | "move-from-top"
-      | "move-from-right"
-      | "move-from-bottom"
-      | "move-from-upperleft"
-      | "move-from-upperright"
-      | "move-from-lowerleft"
-      | "move-from-lowerright"
-      | "uncover-to-left"
-      | "uncover-to-top"
-      | "uncover-to-right"
-      | "uncover-to-bottom"
-      | "uncover-to-upperleft"
-      | "uncover-to-upperright"
-      | "uncover-to-lowerleft"
-      | "uncover-to-lowerright"
-      | "fade-to-center"
-      | "fade-from-center"
-      | "vertical-stripes"
-      | "horizontal-stripes"
-      | "clockwise"
-      | "counterclockwise"
-      | "open-vertical"
-      | "open-horizontal"
-      | "close-vertical"
-      | "close-horizontal"
-      | "wavyline-from-left"
-      | "wavyline-from-top"
-      | "wavyline-from-right"
-      | "wavyline-from-bottom"
-      | "spiralin-left"
-      | "spiralin-right"
-      | "spiralout-left"
-      | "spiralout-right"
-      | "roll-from-top"
-      | "roll-from-left"
-      | "roll-from-right"
-      | "roll-from-bottom"
-      | "stretch-from-left"
-      | "stretch-from-top"
-      | "stretch-from-right"
-      | "stretch-from-bottom"
-      | "vertical-lines"
-      | "horizontal-lines"
-      | "dissolve"
-      | "random"
-      | "vertical-checkerboard"
-      | "horizontal-checkerboard"
-      | "interlocking-horizontal-left"
-      | "interlocking-horizontal-right"
-      | "interlocking-vertical-top"
-      | "interlocking-vertical-bottom"
-      | "fly-away"
-      | "open"
-      | "close"
-      | "melt"
+  & attribute text:footnotes-position {
+      "text" | "page" | "section" | "document"
     }?
-  & attribute presentation:transition-speed { presentationSpeeds }?
-  & attribute smil:type { \string }?
-  & attribute smil:subtype { \string }?
-  & attribute smil:direction { "forward" | "reverse" }?
-  & attribute smil:fadeColor { color }?
-  & attribute presentation:duration { duration }?
-  & attribute presentation:visibility { "visible" | "hidden" }?
-  & attribute draw:background-size { "full" | "border" }?
-  & attribute presentation:background-objects-visible { boolean }?
-  & attribute presentation:background-visible { boolean }?
-  & attribute presentation:display-header { boolean }?
-  & attribute presentation:display-footer { boolean }?
-  & attribute presentation:display-page-number { boolean }?
-  & attribute presentation:display-date-time { boolean }?
-style-drawing-page-properties-elements = presentation-sound?
-\string = xsd:string
-date = xsd:date
-time = xsd:time
-dateTime = xsd:dateTime
-duration = xsd:duration
-integer = xsd:integer
-nonNegativeInteger = xsd:nonNegativeInteger
-positiveInteger = xsd:positiveInteger
-double = xsd:double
-anyURI = xsd:anyURI
-base64Binary = xsd:base64Binary
-ID = xsd:ID
-IDREF = xsd:IDREF
-IDREFS = xsd:IDREFS
-NCName = xsd:NCName
-boolean = "true" | "false"
-dateOrDateTime = xsd:date | xsd:dateTime
-timeOrDateTime = xsd:time | xsd:dateTime
-language = xsd:language
-countryCode = xsd:token { pattern = "[A-Za-z0-9]{1,8}" }
-languageCode = xsd:token { pattern = "[A-Za-z]{1,8}" }
-scriptCode = xsd:token { pattern = "[A-Za-z0-9]{1,8}" }
-character = xsd:string { length = "1" }
-length =
-  xsd:string {
-    pattern =
-      "-?([0-9]+(\.[0-9]*)?|\.[0-9]+)((cm)|(mm)|(in)|(pt)|(pc)|(px))"
+  & element text:note-continuation-notice-forward { text }?
+  & element text:note-continuation-notice-backward { text }?
+text-number = element text:number { \string }
+text-numbered-paragraph =
+  element text:numbered-paragraph {
+    text-numbered-paragraph-attr, text-number?, (text-p | text-h)
+  }
+text-numbered-paragraph-attr =
+  attribute text:list-id { NCName }
+  & attribute text:level { positiveInteger }?
+  & (attribute text:style-name { styleNameRef },
+     attribute text:continue-numbering { boolean },
+     attribute text:start-value { nonNegativeInteger })?
+  & xml-id?
+text-object-index =
+  element text:object-index {
+    common-section-attlist, text-object-index-source, text-index-body
+  }
+text-object-index-entry-template =
+  element text:object-index-entry-template {
+    text-illustration-index-entry-content
+  }
+text-object-index-source =
+  element text:object-index-source {
+    text-object-index-source-attrs,
+    text-index-title-template?,
+    text-object-index-entry-template?
+  }
+text-object-index-source-attrs =
+  text-index-scope-attr
+  & text-relative-tab-stop-position-attr
+  & attribute text:use-spreadsheet-objects { boolean }?
+  & attribute text:use-math-objects { boolean }?
+  & attribute text:use-draw-objects { boolean }?
+  & attribute text:use-chart-objects { boolean }?
+  & attribute text:use-other-objects { boolean }?
+text-outline-level = attribute text:outline-level { positiveInteger }?
+text-outline-level-style =
+  element text:outline-level-style {
+    text-outline-level-style-attlist,
+    style-list-level-properties?,
+    style-text-properties?
+  }
+text-outline-level-style-attlist =
+  attribute text:level { positiveInteger }
+  & attribute text:style-name { styleNameRef }?
+  & common-num-format-attlist
+  & common-num-format-prefix-suffix-attlist
+  & attribute text:display-levels { positiveInteger }?
+  & attribute text:start-value { positiveInteger }?
+text-outline-style =
+  element text:outline-style {
+    text-outline-style-attr, text-outline-level-style+
+  }
+text-outline-style-attr = attribute style:name { styleName }
+text-p =
+  element text:p { paragraph-attrs, paragraph-content-or-hyperlink* }
+text-page = element text:page { text-page-attlist, empty }
+text-page-attlist = attribute text:master-page-name { styleNameRef }
+text-page-continuation-attlist =
+  attribute text:select-page { "previous" | "next" }
+  & attribute text:string-value { \string }?
+text-page-number-attlist =
+  (common-field-num-format-attlist & common-field-fixed-attlist)
+  & attribute text:page-adjust { integer }?
+  & attribute text:select-page { "previous" | "current" | "next" }?
+text-page-sequence = element text:page-sequence { text-page+ }
+text-placeholder-attlist =
+  attribute text:placeholder-type {
+    "text" | "table" | "text-box" | "image" | "object"
   }
-nonNegativeLength =
-  xsd:string {
-    pattern =
-      "([0-9]+(\.[0-9]*)?|\.[0-9]+)((cm)|(mm)|(in)|(pt)|(pc)|(px))"
+  & common-field-description-attlist
+text-relative-tab-stop-position-attr =
+  attribute text:relative-tab-stop-position { boolean }?
+text-section =
+  element text:section {
+    text-section-attlist,
+    (text-section-source | text-section-source-dde | empty),
+    text-content*
   }
-positiveLength =
-  xsd:string {
-    pattern =
-      
"([0-9]*[1-9][0-9]*(\.[0-9]*)?|0+\.[0-9]*[1-9][0-9]*|\.[0-9]*[1-9][0-9]*)((cm)|(mm)|(in)|(pt)|(pc)|(px))"
+text-section-attlist =
+  common-section-attlist
+  & (attribute text:display { "true" | "none" }
+     | (attribute text:display { "condition" },
+        attribute text:condition { \string })
+     | empty)
+text-section-source =
+  element text:section-source { text-section-source-attr }
+text-section-source-attr =
+  (attribute xlink:type { "simple" },
+   attribute xlink:href { anyIRI },
+   attribute xlink:show { "embed" }?)?
+  & attribute text:section-name { \string }?
+  & attribute text:filter-name { \string }?
+text-section-source-dde = office-dde-source
+text-sequence-decl =
+  element text:sequence-decl { text-sequence-decl-attlist }
+text-sequence-decl-attlist =
+  common-field-name-attlist
+  & attribute text:display-outline-level { nonNegativeInteger }
+  & attribute text:separation-character { character }?
+text-sequence-ref-content =
+  attribute text:reference-format {
+    common-ref-format-values
+    | "category-and-value"
+    | "caption"
+    | "value"
+  }?
+text-sequence-ref-name = attribute text:ref-name { \string }?
+text-set-page-variable-attlist =
+  attribute text:active { boolean }?
+  & attribute text:page-adjust { integer }?
+text-soft-page-break = element text:soft-page-break { empty }
+text-sort-key = element text:sort-key { text-sort-key-attlist, empty }
+text-sort-key-attlist =
+  attribute text:key {
+    "address"
+    | "annote"
+    | "author"
+    | "bibliography-type"
+    | "booktitle"
+    | "chapter"
+    | "custom1"
+    | "custom2"
+    | "custom3"
+    | "custom4"
+    | "custom5"
+    | "edition"
+    | "editor"
+    | "howpublished"
+    | "identifier"
+    | "institution"
+    | "isbn"
+    | "issn"
+    | "journal"
+    | "month"
+    | "note"
+    | "number"
+    | "organizations"
+    | "pages"
+    | "publisher"
+    | "report-type"
+    | "school"
+    | "series"
+    | "title"
+    | "url"
+    | "volume"
+    | "year"
+  },
+  attribute text:sort-ascending { boolean }?
+text-style-name = attribute form:text-style-name { styleNameRef }?
+text-tab-attr = attribute text:tab-ref { nonNegativeInteger }?
+text-table-index =
+  element text:table-index {
+    common-section-attlist, text-table-index-source, text-index-body
   }
-percent = xsd:string { pattern = "-?([0-9]+(\.[0-9]*)?|\.[0-9]+)%" }
-zeroToHundredPercent =
-  xsd:string {
-    pattern = "([0-9]?[0-9](\.[0-9]*)?|100(\.0*)?|\.[0-9]+)%"
+text-table-index-entry-template =
+  element text:table-index-entry-template {
+    text-illustration-index-entry-content
   }
-signedZeroToHundredPercent =
-  xsd:string {
-    pattern = "-?([0-9]?[0-9](\.[0-9]*)?|100(\.0*)?|\.[0-9]+)%"
+text-table-index-source =
+  element text:table-index-source {
+    text-illustration-index-source-attrs,
+    text-index-title-template?,
+    text-table-index-entry-template?
   }
-relativeLength = xsd:string { pattern = "[0-9]+\*" }
-coordinate = length
-distance = length
-color = xsd:string { pattern = "#[0-9a-fA-F]{6}" }
-angle = xsd:string
-CURIE =
-  xsd:string { pattern = "(([\i-[:]][\c-[:]]*)?:)?.+" minLength = "1" }
-CURIEs = list { CURIE+ }
-SafeCURIE =
-  xsd:string {
-    pattern = "\[(([\i-[:]][\c-[:]]*)?:)?.+\]"
-    minLength = "3"
+text-table-of-content =
+  element text:table-of-content {
+    common-section-attlist,
+    text-table-of-content-source,
+    text-index-body
   }
-URIorSafeCURIE = anyURI | SafeCURIE
-styleName = xsd:NCName
-styleNameRef = xsd:NCName | empty
-styleNameRefs = list { xsd:NCName* }
-variableName = xsd:string
-targetFrameName = "_self" | "_blank" | "_parent" | "_top" | \string
+text-table-of-content-children =
+  text-index-entry-chapter
+  | text-index-entry-page-number
+  | text-index-entry-text
+  | text-index-entry-span
+  | text-index-entry-tab-stop
+  | text-index-entry-link-start
+  | text-index-entry-link-end
+text-table-of-content-entry-template =
+  element text:table-of-content-entry-template {
+    text-table-of-content-entry-template-attlist,
+    text-table-of-content-children*
+  }
+text-table-of-content-entry-template-attlist =
+  attribute text:outline-level { positiveInteger }
+  & attribute text:style-name { styleNameRef }
+text-table-of-content-source =
+  element text:table-of-content-source {
+    text-table-of-content-source-attlist,
+    text-index-title-template?,
+    text-table-of-content-entry-template*,
+    text-index-source-styles*
+  }
+text-table-of-content-source-attlist =
+  attribute text:outline-level { positiveInteger }?
+  & attribute text:use-outline-level { boolean }?
+  & attribute text:use-index-marks { boolean }?
+  & attribute text:use-index-source-styles { boolean }?
+  & attribute text:index-scope { "document" | "chapter" }?
+  & attribute text:relative-tab-stop-position { boolean }?
+text-template-name-attlist =
+  attribute text:display {
+    "full" | "path" | "name" | "name-and-extension" | "area" | "title"
+  }?
+text-time-attlist =
+  (common-field-fixed-attlist & common-field-data-style-name-attlist)
+  & attribute text:time-value { timeOrDateTime }?
+  & attribute text:time-adjust { duration }?
+text-toc-mark-start-attrs = text-id, text-outline-level
+text-tracked-changes =
+  element text:tracked-changes {
+    text-tracked-changes-attr, text-changed-region*
+  }?
+text-tracked-changes-attr = attribute text:track-changes { boolean }?
+text-user-field-decl =
+  element text:user-field-decl {
+    common-field-name-attlist,
+    common-field-formula-attlist?,
+    common-value-and-type-attlist
+  }
+text-user-index =
+  element text:user-index {
+    common-section-attlist, text-user-index-source, text-index-body
+  }
+text-user-index-entry-template =
+  element text:user-index-entry-template {
+    text-user-index-entry-template-attrs,
+    (text-index-entry-chapter
+     | text-index-entry-page-number
+     | text-index-entry-text
+     | text-index-entry-span
+     | text-index-entry-tab-stop
+     | text-index-entry-link-start
+     | text-index-entry-link-end
+       # https://issues.oasis-open.org/browse/OFFICE-3941
+       )*
+  }
+text-user-index-entry-template-attrs =
+  attribute text:outline-level { positiveInteger }
+  & attribute text:style-name { styleNameRef }
+text-user-index-source =
+  element text:user-index-source {
+    text-user-index-source-attr,
+    text-index-title-template?,
+    text-user-index-entry-template*,
+    text-index-source-styles*
+  }
+text-user-index-source-attr =
+  text-index-scope-attr
+  & text-relative-tab-stop-position-attr
+  & attribute text:use-index-marks { boolean }?
+  & attribute text:use-index-source-styles { boolean }?
+  & attribute text:use-graphics { boolean }?
+  & attribute text:use-tables { boolean }?
+  & attribute text:use-floating-frames { boolean }?
+  & attribute text:use-objects { boolean }?
+  & attribute text:copy-outline-levels { boolean }?
+  & attribute text:index-name { \string }
+text-variable-decl =
+  element text:variable-decl {
+    common-field-name-attlist, common-value-type-attlist
+  }
+textEncoding = xsd:string { pattern = "[A-Za-z][A-Za-z0-9._\-]*" }
+time = xsd:time
+timeOrDateTime = xsd:time | xsd:dateTime
+types = "submit" | "reset" | "push" | "url"
 valueType =
   "float"
   | "time"
@@ -6257,24 +6397,18 @@ valueType =
   | "currency"
   | "boolean"
   | "string"
-points =
-  xsd:string { pattern = "-?[0-9]+,-?[0-9]+([ ]+-?[0-9]+,-?[0-9]+)*" }
-pathData = xsd:string
+variableName = xsd:string
 vector3D =
   xsd:string {
     pattern =
       "\([ ]*-?([0-9]+(\.[0-9]*)?|\.[0-9]+)([ 
]+-?([0-9]+(\.[0-9]*)?|\.[0-9]+)){2}[ ]*\)"
   }
-namespacedToken = xsd:QName { pattern = "[^:]+:[^:]+" }
-anyIRI =
-  xsd:anyURI
-  >> dc:description [
-       "An IRI-reference as defined in [RFC3987]. See ODF 1.2 Part 1 section 
18.3."
-     ]
-anyAttListOrElements =
-  attribute * { text }*,
-  anyElements
-anyElements =
-  element * {
-    mixed { anyAttListOrElements }
-  }*
+vertBackPos = "top" | "center" | "bottom"
+xforms-bind-attlist = attribute xforms:bind { \string }?
+xforms-model = element xforms:model { anyAttListOrElements }
+xml-id = attribute xml:id { ID }
+zeroToHundredPercent =
+  xsd:string {
+    pattern = "([0-9]?[0-9](\.[0-9]*)?|100(\.0*)?|\.[0-9]+)%"
+  }
+zeroToOneDecimal = xsd:decimal { minInclusive = "0" maxInclusive = "1" }
diff --git a/etc/schema/schemas.xml b/etc/schema/schemas.xml
index 7fd91b8..f8acb0d 100644
--- a/etc/schema/schemas.xml
+++ b/etc/schema/schemas.xml
@@ -31,6 +31,10 @@ along with GNU Emacs.  If not, see 
<https://www.gnu.org/licenses/>. -->
   <namespace ns="http://relaxng.org/ns/structure/1.0"; typeId="RELAX NG"/>
   <namespace ns="http://thaiopensource.com/ns/locating-rules/1.0";
             uri="locate.rnc"/>
+  <namespace ns="urn:oasis:names:tc:opendocument:xmlns:office:1.0" 
typeId="LibreOffice"/>
+  <namespace 
ns="urn:org:documentfoundation:names:experimental:office:xmlns:loext:1.0" 
typeId="LibreOffice"/>
+  <namespace 
ns="urn:openoffice:names:experimental:ooo-ms-interop:xmlns:field:1.0" 
typeId="LibreOffice"/>
+  <namespace ns="urn:oasis:names:tc:opendocument:xmlns:manifest:1.0" 
typeId="OpenDocument Manifest"/>
 
   <documentElement localName="stylesheet" typeId="XSLT"/>
   <documentElement prefix="xsl" localName="transform" typeId="XSLT"/>
@@ -59,7 +63,7 @@ along with GNU Emacs.  If not, see 
<https://www.gnu.org/licenses/>. -->
 
   <documentElement prefix="office" typeId="OpenDocument"/>
   <documentElement prefix="manifest" localName="manifest" typeId="OpenDocument 
Manifest"/>
-  <typeId id="OpenDocument" uri="od-schema-v1.2-os.rnc"/>
+  <typeId id="LibreOffice" uri="OpenDocument-schema-v1.3+libreoffice.rnc"/>
   <typeId id="OpenDocument Manifest" uri="od-manifest-schema-v1.2-os.rnc"/>
 
 </locatingRules>
diff --git a/etc/themes/modus-operandi-theme.el 
b/etc/themes/modus-operandi-theme.el
index 346000a..64763a1 100644
--- a/etc/themes/modus-operandi-theme.el
+++ b/etc/themes/modus-operandi-theme.el
@@ -1,4666 +1,69 @@
 ;;; modus-operandi-theme.el --- Accessible light theme (WCAG AAA) -*- 
lexical-binding:t -*-
 
-;; Copyright (C) 2019-2021 Free Software Foundation, Inc.
+;; Copyright (C) 2019-2021  Free Software Foundation, Inc.
 
 ;; Author: Protesilaos Stavrou <info@protesilaos.com>
 ;; URL: https://gitlab.com/protesilaos/modus-themes
-;; Version: 0.13.0
+;; Version: 1.2.3
 ;; Package-Requires: ((emacs "26.1"))
 ;; Keywords: faces, theme, accessibility
 
 ;; This file is part of GNU Emacs.
 
-;; GNU Emacs is free software: you can redistribute it and/or modify
+;; This program is free software; you can redistribute it and/or modify
 ;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation, either version 3 of the License, or
-;; (at your option) any later version.
-
-;; 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.
-
+;; the Free Software Foundation, either version 3 of the License, or (at
+;; your option) any later version.
+;;
+;; This program is distributed in the hope that it will be useful, but
+;; WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+;; General Public License for more details.
+;;
 ;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs.  If not, see <https://www.gnu.org/licenses/>.
+;; along with this program.  If not, see <https://www.gnu.org/licenses/>.
 
 ;;; Commentary:
 ;;
-;; This theme is designed for colour-contrast accessibility.
-;;
-;; 1. Provide a consistent minimum contrast ratio between background and
-;; foreground values of 7:1 or higher.  This meets the highest such
-;; accessibility criterion per the guidelines of the Worldwide Web
-;; Consortium's Working Group on Accessibility (WCAG AAA standard).
+;; Modus Operandi is the light variant of the Modus themes (Modus
+;; Vivendi is the dark one).  The themes are designed for color-contrast
+;; accessibility.  More specifically:
 ;;
-;; 2. Offer as close to full face coverage as possible.  The list is
-;; already quite long (see further below), with more additions to follow
-;; as part of the ongoing development process.
+;;     1. Provide a consistent minimum contrast ratio between background
+;;     and foreground values of 7:1 or higher.  This meets the highest
+;;     such accessibility criterion per the guidelines of the Worldwide
+;;     Web Consortium's Working Group on Accessibility (WCAG AAA
+;;     standard).
 ;;
-;; The theme provides the following customisation options, all of which
-;; are disabled by default:
+;;     2. Offer as close to full face coverage as possible.  The list is
+;;     already quite long, with more additions to follow as part of the
+;;     ongoing development process.
 ;;
-;;     modus-operandi-theme-slanted-constructs             (boolean)
-;;     modus-operandi-theme-bold-constructs                (boolean)
-;;     modus-operandi-theme-variable-pitch-headings        (boolean)
-;;     modus-operandi-theme-no-mixed-fonts                 (boolean)
-;;     modus-operandi-theme-headings                       (alist)
-;;     modus-operandi-theme-scale-headings                 (boolean)
-;;     modus-operandi-theme-fringes                        (choice)
-;;     modus-operandi-theme-org-blocks                     (choice)
-;;     modus-operandi-theme-prompts                        (choice)
-;;     modus-operandi-theme-mode-line                      (choice)
-;;     modus-operandi-theme-diffs                          (choice)
-;;     modus-operandi-theme-faint-syntax                   (boolean)
-;;     modus-operandi-theme-intense-hl-line                (boolean)
-;;     modus-operandi-theme-intense-paren-match            (boolean)
-;;     modus-operandi-theme-no-link-underline              (boolean)
-;;     modus-operandi-theme-completions                    (choice)
-;;     modus-operandi-theme-override-colors-alist          (alist)
+;; For a complete view of the project, also refer to the following files
+;; (should be distributed in the same repository/directory as the
+;; current item):
 ;;
-;; The default scale is as follows (it can be customised as well):
-;;
-;;     modus-operandi-theme-scale-1 1.05
-;;     modus-operandi-theme-scale-2 1.1
-;;     modus-operandi-theme-scale-3 1.15
-;;     modus-operandi-theme-scale-4 1.2
-;;     modus-operandi-theme-scale-5 1.3
-;;
-;; What follows is the list of explicitly supported packages or face
-;; groups (there are implicitly supported packages as well, which
-;; inherit from font-lock or some basic group).  You are encouraged to
-;; notify me of any missing package or change you would like to see.
-;;
-;;     ace-window
-;;     ag
-;;     alert
-;;     all-the-icons
-;;     annotate
-;;     anzu
-;;     apropos
-;;     apt-sources-list
-;;     artbollocks-mode
-;;     auctex and TeX
-;;     auto-dim-other-buffers
-;;     avy
-;;     awesome-tray
-;;     binder
-;;     bm
-;;     bongo
-;;     boon
-;;     breakpoint (provided by built-in gdb-mi.el)
-;;     buffer-expose
-;;     calendar and diary
-;;     calfw
-;;     centaur-tabs
-;;     change-log and log-view (`vc-print-log' and `vc-print-root-log')
-;;     cider
-;;     circe
-;;     color-rg
-;;     column-enforce-mode
-;;     company-mode
-;;     company-posframe
-;;     compilation-mode
-;;     completions
-;;     counsel
-;;     counsel-css
-;;     counsel-notmuch
-;;     counsel-org-capture-string
-;;     cov
-;;     cperl-mode
-;;     csv-mode
-;;     ctrlf
-;;     custom (M-x customize)
-;;     dap-mode
-;;     dashboard (emacs-dashboard)
-;;     deadgrep
-;;     debbugs
-;;     define-word
-;;     deft
-;;     dictionary
-;;     diff-hl
-;;     diff-mode
-;;     dim-autoload
-;;     dir-treeview
-;;     dired
-;;     dired-async
-;;     dired-git
-;;     dired-git-info
-;;     dired-narrow
-;;     dired-subtree
-;;     diredfl
-;;     disk-usage
-;;     doom-modeline
-;;     dynamic-ruler
-;;     easy-jekyll
-;;     easy-kill
-;;     ebdb
-;;     ediff
-;;     eglot
-;;     el-search
-;;     eldoc
-;;     eldoc-box
-;;     elfeed
-;;     elfeed-score
-;;     emms
-;;     enhanced-ruby-mode
-;;     epa
-;;     equake
-;;     erc
-;;     eros
-;;     ert
-;;     eshell
-;;     eshell-fringe-status
-;;     eshell-git-prompt
-;;     eshell-prompt-extras (epe)
-;;     eshell-syntax-highlighting
-;;     evil (evil-mode)
-;;     evil-goggles
-;;     evil-visual-mark-mode
-;;     eww
-;;     eyebrowse
-;;     fancy-dabbrev
-;;     flycheck
-;;     flycheck-color-mode-line
-;;     flycheck-indicator
-;;     flycheck-posframe
-;;     flymake
-;;     flyspell
-;;     flyspell-correct
-;;     flx
-;;     freeze-it
-;;     frog-menu
-;;     focus
-;;     fold-this
-;;     font-lock (generic syntax highlighting)
-;;     forge
-;;     fountain (fountain-mode)
-;;     geiser
-;;     git-commit
-;;     git-gutter (and variants)
-;;     git-lens
-;;     git-rebase
-;;     git-timemachine
-;;     git-walktree
-;;     gnus
-;;     golden-ratio-scroll-screen
-;;     helm
-;;     helm-ls-git
-;;     helm-switch-shell
-;;     helm-xref
-;;     helpful
-;;     highlight-blocks
-;;     highlight-defined
-;;     highlight-escape-sequences (`hes-mode')
-;;     highlight-indentation
-;;     highlight-numbers
-;;     highlight-symbol
-;;     highlight-tail
-;;     highlight-thing
-;;     hl-defined
-;;     hl-fill-column
-;;     hl-line-mode
-;;     hl-todo
-;;     hydra
-;;     hyperlist
-;;     ibuffer
-;;     icomplete
-;;     ido-mode
-;;     iedit
-;;     iflipb
-;;     imenu-list
-;;     indium
-;;     info
-;;     info-colors
-;;     interaction-log
-;;     ioccur
-;;     isearch, occur, etc.
-;;     ivy
-;;     ivy-posframe
-;;     jira (org-jira)
-;;     journalctl-mode
-;;     js2-mode
-;;     julia
-;;     jupyter
-;;     kaocha-runner
-;;     keycast
-;;     line numbers (`display-line-numbers-mode' and global variant)
-;;     lsp-mode
-;;     lsp-ui
-;;     magit
-;;     magit-imerge
-;;     man
-;;     markdown-mode
-;;     markup-faces (`adoc-mode')
-;;     mentor
-;;     messages
-;;     minibuffer-line
-;;     minimap
-;;     modeline
-;;     mood-line
-;;     mpdel
-;;     mu4e
-;;     mu4e-conversation
-;;     multiple-cursors
-;;     neotree
-;;     no-emoji
-;;     notmuch
-;;     num3-mode
-;;     nxml-mode
-;;     objed
-;;     orderless
-;;     org
-;;     org-journal
-;;     org-noter
-;;     org-pomodoro
-;;     org-recur
-;;     org-roam
-;;     org-superstar
-;;     org-table-sticky-header
-;;     org-treescope
-;;     origami
-;;     outline-mode
-;;     outline-minor-faces
-;;     package (M-x list-packages)
-;;     page-break-lines
-;;     paradox
-;;     paren-face
-;;     parrot
-;;     pass
-;;     persp-mode
-;;     perspective
-;;     phi-grep
-;;     phi-search
-;;     pkgbuild-mode
-;;     pomidor
-;;     powerline
-;;     powerline-evil
-;;     proced
-;;     prodigy
-;;     racket-mode
-;;     rainbow-blocks
-;;     rainbow-identifiers
-;;     rainbow-delimiters
-;;     rcirc
-;;     regexp-builder (also known as `re-builder')
-;;     rg
-;;     ripgrep
-;;     rmail
-;;     ruler-mode
-;;     sallet
-;;     selectrum
-;;     semantic
-;;     sesman
-;;     shell-script-mode
-;;     show-paren-mode
-;;     side-notes
-;;     skewer-mode
-;;     smart-mode-line
-;;     smartparens
-;;     smerge
-;;     spaceline
-;;     speedbar
-;;     spell-fu
-;;     stripes
-;;     suggest
-;;     switch-window
-;;     swiper
-;;     swoop
-;;     sx
-;;     symbol-overlay
-;;     tab-bar-mode
-;;     tab-line-mode
-;;     syslog-mode
-;;     table (built-in table.el)
-;;     telephone-line
-;;     term
-;;     tomatinho
-;;     transient (pop-up windows like Magit's)
-;;     trashed
-;;     treemacs
-;;     tty-menu
-;;     tuareg
-;;     typescript
-;;     undo-tree
-;;     vc (built-in mode line status for version control)
-;;     vc-annotate (C-x v g)
-;;     vdiff
-;;     vimish-fold
-;;     visible-mark
-;;     visual-regexp
-;;     volatile-highlights
-;;     vterm
-;;     wcheck-mode
-;;     web-mode
-;;     wgrep
-;;     which-function-mode
-;;     which-key
-;;     whitespace-mode
-;;     window-divider-mode
-;;     winum
-;;     writegood-mode
-;;     woman
-;;     xah-elisp-mode
-;;     xref
-;;     xterm-color (and ansi-colors)
-;;     yaml-mode
-;;     yasnippet
-;;     ztree
+;; - modus-themes.el            (Main code shared between the themes)
+;; - modus-vivendi-theme.el     (Dark theme)
 
 ;;; Code:
 
 
 
-(deftheme modus-operandi
-  "Light theme that conforms with the highest accessibility
-  standard for colour contrast between background and
-  foreground elements (WCAG AAA).")
-
-;;; Custom faces
-
-;; These faces will be inherited by actual constructs.  They are meant
-;; for those cases where a face needs to distinguish its output from
-;; the rest of the text, such as `isearch' and `occur'…  We define
-;; these separately in order to combine each colour with its
-;; appropriate foreground value.  This is to ensure a consistent
-;; contrast ratio of >= 7:1.
-(defgroup modus-theme ()
-  "Theme that ensures WCAG AAA accessibility (contrast ratio
-between foreground and background is >= 7:1)."
-  :group 'faces
-  :prefix "modus-theme-"
-  :link '(url-link :tag "GitLab" "https://gitlab.com/protesilaos/modus-themes";)
-  :tag "Modus Operandi")
-
-(defface modus-theme-subtle-red nil nil)
-(defface modus-theme-subtle-green nil nil)
-(defface modus-theme-subtle-yellow nil nil)
-(defface modus-theme-subtle-blue nil nil)
-(defface modus-theme-subtle-magenta nil nil)
-(defface modus-theme-subtle-cyan nil nil)
-(defface modus-theme-subtle-neutral nil nil)
-(defface modus-theme-intense-red nil nil)
-(defface modus-theme-intense-green nil nil)
-(defface modus-theme-intense-yellow nil nil)
-(defface modus-theme-intense-blue nil nil)
-(defface modus-theme-intense-magenta nil nil)
-(defface modus-theme-intense-cyan nil nil)
-(defface modus-theme-intense-neutral nil nil)
-(defface modus-theme-refine-red nil nil)
-(defface modus-theme-refine-green nil nil)
-(defface modus-theme-refine-yellow nil nil)
-(defface modus-theme-refine-blue nil nil)
-(defface modus-theme-refine-magenta nil nil)
-(defface modus-theme-refine-cyan nil nil)
-(defface modus-theme-active-red nil nil)
-(defface modus-theme-active-green nil nil)
-(defface modus-theme-active-yellow nil nil)
-(defface modus-theme-active-blue nil nil)
-(defface modus-theme-active-magenta nil nil)
-(defface modus-theme-active-cyan nil nil)
-(defface modus-theme-fringe-red nil nil)
-(defface modus-theme-fringe-green nil nil)
-(defface modus-theme-fringe-yellow nil nil)
-(defface modus-theme-fringe-blue nil nil)
-(defface modus-theme-fringe-magenta nil nil)
-(defface modus-theme-fringe-cyan nil nil)
-(defface modus-theme-nuanced-red nil nil)
-(defface modus-theme-nuanced-green nil nil)
-(defface modus-theme-nuanced-yellow nil nil)
-(defface modus-theme-nuanced-blue nil nil)
-(defface modus-theme-nuanced-magenta nil nil)
-(defface modus-theme-nuanced-cyan nil nil)
-(defface modus-theme-special-cold nil nil)
-(defface modus-theme-special-mild nil nil)
-(defface modus-theme-special-warm nil nil)
-(defface modus-theme-special-calm nil nil)
-(defface modus-theme-diff-added nil nil)
-(defface modus-theme-diff-changed nil nil)
-(defface modus-theme-diff-removed nil nil)
-(defface modus-theme-diff-refine-added nil nil)
-(defface modus-theme-diff-refine-changed nil nil)
-(defface modus-theme-diff-refine-removed nil nil)
-(defface modus-theme-diff-focus-added nil nil)
-(defface modus-theme-diff-focus-changed nil nil)
-(defface modus-theme-diff-focus-removed nil nil)
-(defface modus-theme-diff-heading nil nil)
-(defface modus-theme-pseudo-header nil nil)
-(defface modus-theme-mark-alt nil nil)
-(defface modus-theme-mark-del nil nil)
-(defface modus-theme-mark-sel nil nil)
-(defface modus-theme-mark-symbol nil nil)
-(defface modus-theme-heading-1 nil nil)
-(defface modus-theme-heading-2 nil nil)
-(defface modus-theme-heading-3 nil nil)
-(defface modus-theme-heading-4 nil nil)
-(defface modus-theme-heading-5 nil nil)
-(defface modus-theme-heading-6 nil nil)
-(defface modus-theme-heading-7 nil nil)
-(defface modus-theme-heading-8 nil nil)
-(defface modus-theme-hl-line nil nil)
-
-;;; Customisation options
-
-;; User-facing customisation options.  They are all deactivated by
-;; default (users must opt in).
-(defcustom modus-operandi-theme-slanted-constructs nil
-  "Use slanted text in more code constructs (italics or oblique)."
-  :type 'boolean)
-
-(defcustom modus-operandi-theme-bold-constructs nil
-  "Use bold text in more code constructs."
-  :type 'boolean)
-
-(define-obsolete-variable-alias 'modus-operandi-theme-proportional-fonts
-  'modus-operandi-theme-variable-pitch-headings "`modus-operandi-theme' 
0.11.0")
-
-(defcustom modus-operandi-theme-proportional-fonts nil
-  "Use proportional fonts (variable-pitch) in headings."
-  :type 'boolean)
-
-(defcustom modus-operandi-theme-variable-pitch-headings nil
-  "Use proportional fonts (variable-pitch) in headings."
-  :type 'boolean)
-
-(defcustom modus-operandi-theme-no-mixed-fonts nil
-  "Disable inheritance from `fixed-pitch' in some faces.
-
-This is done by default to allow spacing-sensitive constructs,
-such as Org tables and code blocks, to remain monospaced when
-users opt for something like the command `variable-pitch-mode'.
-The downside with the default is that users need to explicitly
-configure the font family of `fixed-pitch' in order to get a
-consistent experience.  That may be something they do not want to
-do.  Hence this option to disable any kind of technique for
-mixing fonts."
-  :type 'boolean)
-
-(make-obsolete 'modus-operandi-theme-rainbow-headings
-               'modus-operandi-theme-headings
-               "`modus-operandi-theme' 0.13.0")
-
-(defcustom modus-operandi-theme-rainbow-headings nil
-  "Use more saturated colours for headings."
-  :type 'boolean)
-
-(make-obsolete 'modus-operandi-theme-section-headings
-               'modus-operandi-theme-headings
-               "`modus-operandi-theme' 0.13.0")
-
-(defcustom modus-operandi-theme-section-headings nil
-  "Use a background and an overline in headings."
-  :type 'boolean)
-
-(defcustom modus-operandi-theme-headings
-  '((t . nil))
-  "Alist of styles for headings, with optional value per level.
-
-To control faces per level from 1-8, use something like this:
-
-  (setq modus-operandi-theme-headings
-        '((1 . highlight)
-          (2 . line)
-          (t . rainbow-line-no-bold)))
-
-To set a uniform value for all heading levels, use this pattern:
-
-  (setq modus-operandi-theme-headings
-        '((t . rainbow-line-no-bold)))
-
-The default uses a fairly desaturated foreground value in
-combination with a bold typographic weight.  To specify this
-style for a given level N (assuming you wish to have another
-fallback option), just specify the value t like this:
-
-  (setq modus-operandi-theme-headings
-        '((1 . t)
-          (2 . line)
-          (t . rainbow-line-no-bold)))
-
-A description of all possible values:
-
-+ `no-bold' retains the default text colour while removing
-  the typographic weight.
-
-+ `line' is the same as the default plus an overline over the
-  heading.
-
-+ `line-no-bold' is the same as `line' without bold weight.
-
-+ `rainbow' uses a more colourful foreground in combination
-  with bold weight.
-
-+ `rainbow-line' is the same as `rainbow' plus an overline.
-
-+ `rainbow-line-no-bold' is the same as `rainbow-line' without
-  the bold weight.
-
-+ `highlight' retains the default style of a fairly desaturated
-  foreground combined with a bold weight and add to it a subtle
-  accented background.
-
-+ `highlight-no-bold' is the same as `highlight' without a bold
-  weight.
-
-+ `rainbow-highlight' is the same as `highlight' but with a more
-  colourful foreground.
-
-+ `rainbow-highlight-no-bold' is the same as `rainbow-highlight'
-  without a bold weight.
-
-+ `section' retains the default looks and adds to them both an
-  overline and a slightly accented background.  It is, in effect,
-  a combination of the `line' and `highlight' values.
-
-+ `section-no-bold' is the same as `section' without a bold
-  weight.
-
-+ `rainbow-section' is the same as `section' but with a more
-  colourful foreground.
-
-+ `rainbow-section-no-bold' is the same as `rainbow-section'
-  without a bold weight."
-  :type
-  '(alist
-    :key-type symbol
-    :value-type
-    (choice (const :tag "Fairly desaturated foreground with bold weight 
(default)" t)
-            (const :tag "Like the default without bold weight" no-bold)
-            (const :tag "Like the default plus overline" line)
-            (const :tag "Like `line' without bold weight" line-no-bold)
-            (const :tag "Like the default but with more colourful foreground" 
rainbow)
-            (const :tag "Like `rainbow' plus overline" rainbow-line)
-            (const :tag "Like `rainbow' without bold weight" rainbow-no-bold)
-            (const :tag "Like `rainbow-line' without bold weight" 
rainbow-line-no-bold)
-            (const :tag "Like the default plus subtle background" highlight)
-            (const :tag "Like `highlight' without bold weight" 
highlight-no-bold)
-            (const :tag "Like `highlight' with more colourful foreground" 
rainbow-highlight)
-            (const :tag "Like `rainbow-highlight' without bold weight" 
rainbow-highlight-no-bold)
-            (const :tag "Like `highlight' plus overline" section)
-            (const :tag "Like `section' without bold weight" section-no-bold)
-            (const :tag "Like `section' with more colourful foreground" 
rainbow-section)
-            (const :tag "Like `rainbow-section' without bold weight" 
rainbow-section-no-bold))))
-
-(defcustom modus-operandi-theme-scale-headings nil
-  "Use font scaling for headings."
-  :type 'boolean)
-
-(defcustom modus-operandi-theme-scale-1 1.05
-  "Font size that is slightly larger than the base value.
-The default is a floating point that is interpreted as a multiple
-of the base font size.  However, the variable also accepts an
-integer, understood as an absolute height (e.g. a value of 140 is
-the same as setting the font at 14 point size).
-
-For more on the matter, read the documentation of
-`set-face-attribute', specifically the ':height' section."
-  :type 'number)
-
-(defcustom modus-operandi-theme-scale-2 1.1
-  "Font size slightly larger than `modus-operandi-theme-scale-1'.
-The default is a floating point that is interpreted as a multiple
-of the base font size.  However, the variable also accepts an
-integer, understood as an absolute height (e.g. a value of 140 is
-the same as setting the font at 14 point size).
-
-For more on the matter, read the documentation of
-`set-face-attribute', specifically the ':height' section."
-  :type 'number)
-
-(defcustom modus-operandi-theme-scale-3 1.15
-  "Font size slightly larger than `modus-operandi-theme-scale-2'.
-The default is a floating point that is interpreted as a multiple
-of the base font size.  However, the variable also accepts an
-integer, understood as an absolute height (e.g. a value of 140 is
-the same as setting the font at 14 point size).
-
-For more on the matter, read the documentation of
-`set-face-attribute', specifically the ':height' section."
-  :type 'number)
-
-(defcustom modus-operandi-theme-scale-4 1.2
-  "Font size slightly larger than `modus-operandi-theme-scale-3'.
-The default is a floating point that is interpreted as a multiple
-of the base font size.  However, the variable also accepts an
-integer, understood as an absolute height (e.g. a value of 140 is
-the same as setting the font at 14 point size).
-
-For more on the matter, read the documentation of
-`set-face-attribute', specifically the ':height' section."
-  :type 'number)
-
-(defcustom modus-operandi-theme-scale-5 1.3
-  "Font size slightly larger than `modus-operandi-theme-scale-4'.
-The default is a floating point that is interpreted as a multiple
-of the base font size.  However, the variable also accepts an
-integer, understood as an absolute height (e.g. a value of 140 is
-the same as setting the font at 14 point size).
-
-For more on the matter, read the documentation of
-`set-face-attribute', specifically the ':height' section."
-  :type 'number)
-
-(make-obsolete 'modus-operandi-theme-visible-fringes
-               'modus-operandi-theme-fringes
-               "`modus-operandi-theme' 0.12.0")
-
-(defcustom modus-operandi-theme-visible-fringes nil
-  "Use a visible style for fringes."
-  :type 'boolean)
-
-(defcustom modus-operandi-theme-fringes nil
-  "Define the visibility of fringes.
-
-Nil means the fringes have no background colour.  Option `subtle'
-will apply a greyscale value that is visible yet close to the
-main buffer background colour.  Option `intense' will use a more
-pronounced greyscale value."
-  :type '(choice
-          (const :tag "No visible fringes (default)" nil)
-          (const :tag "Subtle greyscale background" subtle)
-          (const :tag "Intense greyscale background" intense)))
-
-(make-obsolete 'modus-operandi-theme-distinct-org-blocks
-               'modus-operandi-theme-org-blocks
-               "`modus-operandi-theme' 0.11.0")
-
-(defcustom modus-operandi-theme-distinct-org-blocks nil
-  "Use a distinct neutral background for `org-mode' blocks."
-  :type 'boolean)
-
-(make-obsolete 'modus-operandi-theme-rainbow-org-src-blocks
-               'modus-operandi-theme-org-blocks
-               "`modus-operandi-theme' 0.11.0")
-
-(defcustom modus-operandi-theme-rainbow-org-src-blocks nil
-  "Use colour-coded backgrounds for `org-mode' source blocks.
-The colour in use depends on the language (send feedback to
-include more languages)."
-  :type 'boolean)
-
-(defcustom modus-operandi-theme-org-blocks nil
-  "Use a subtle grey or colour-coded background for Org blocks.
-
-Nil means that the block will have no background of its own and
-will use the default that applies to the rest of the buffer.
-
-Option `greyscale' will apply a subtle neutral grey background to
-the block's contents.  It also affects the begin and end lines of
-the block: their background will be extended to the edge of the
-window for Emacs version >= 27 where the ':extend' keyword is
-recognised by `set-face-attribute'.
-
-Option `rainbow' will use an accented background for the contents
-of the block.  The exact colour will depend on the programming
-language and is controlled by the `org-src-block-faces'
-variable (refer to the theme's source code for the current
-association list)."
-  :type '(choice
-          (const :tag "No Org block background (default)" nil)
-          (const :tag "Subtle grey block background" greyscale)
-          (const :tag "Colour-coded background per programming language" 
rainbow)))
-
-(make-obsolete 'modus-operandi-theme-3d-modeline
-               'modus-operandi-theme-mode-line
-               "`modus-operandi-theme' 0.13.0")
-
-(defcustom modus-operandi-theme-3d-modeline nil
-  "Use a three-dimensional style for the active mode line."
-  :type 'boolean)
-
-(defcustom modus-operandi-theme-mode-line nil
-  "Adjust the overall style of the mode line.
-
-Nil is a two-dimensional rectangle with a border around it.  The
-active and the inactive modelines use different shades of
-greyscale values for the background and foreground.
-
-A `3d' value will apply a three-dimensional effect to the active
-modeline.  The inactive modelines remain two-dimensional and are
-toned down a bit, relative to the nil value.
-
-The `moody' option is meant to optimise the modeline for use with
-the library of the same name.  This practically means to remove
-the box effect and rely on underline and overline properties
-instead.  It also tones down the inactive modelines.  Despite its
-intended purpose, this option can also be used without the
-`moody' library."
-  :type '(choice
-          (const :tag "Two-dimensional box (default)" nil)
-          (const :tag "Three-dimensional style for the active mode line" 3d)
-          (const :tag "No box effects, which are optimal for use with the 
`moody' library" moody)))
-
-(make-obsolete 'modus-operandi-theme-subtle-diffs
-               'modus-operandi-theme-diffs
-               "`modus-operandi-theme' 0.13.0")
-
-(defcustom modus-operandi-theme-subtle-diffs nil
-  "Use fewer/dim backgrounds in `diff-mode', `ediff',`magit'."
-  :type 'boolean)
-
-(defcustom modus-operandi-theme-diffs nil
-  "Adjust the overall styles of diffs.
-
-Nil means to use fairly intense colour combinations for diffs.
-For example, you get a rich green background with a green
-foreground for added lines.  Word-wise or 'refined' diffs follow
-the same pattern but use different shades of those colours to
-remain distinct.
-
-A `desaturated' value follows the same principles as with the nil
-option, while it tones down all relevant colours.
-
-Option `fg-only' will remove all accented backgrounds, except
-from word-wise changes.  It instead uses colour-coded foreground
-values to differentiate between added/removed/changed lines.  If
-a background is necessary, such as with `ediff', then a subtle
-greyscale value is used."
-  :type '(choice
-          (const :tag "Intensely coloured backgrounds (default)" nil)
-          (const :tag "Slightly accented backgrounds with tinted text" 
desaturated)
-          (const :tag "No backgrounds, except for refined diffs" fg-only)))
-
-(make-obsolete 'modus-operandi-theme-intense-standard-completions
-               'modus-operandi-theme-completions
-               "`modus-operandi-theme' 0.12.0")
-
-(defcustom modus-operandi-theme-intense-standard-completions nil
-  "Use prominent backgrounds for Icomplete, Ido, or similar."
-  :type 'boolean)
-
-(defcustom modus-operandi-theme-completions nil
-  "Apply special styles to the UI of completion frameworks.
-
-This concerns Icomplete, Ivy, Helm, Selectrum, Ido, as well as
-any other tool meant to enhance their experience.  The effect
-will vary depending on the completion framework.
-
-Nil means to remain faithful to the metaphors that each UI
-establishes.  For example, Icomplete and Ido only use foreground
-colours to style their matches, whereas Ivy or Helm rely on an
-aesthetic that combines coloured backgrounds with appropriate
-text colour.
-
-Option `moderate' will apply a combination of background and
-foreground that is fairly subtle.  For Icomplete and the like,
-this constitutes a departure from their standard style.  While
-Ivy, Helm, and the others, will use less pronounced colours for
-applicable contexts.
-
-Option `opinionated' will apply colour combinations that
-refashion the completion UI.  So Icomplete et al will now use
-styles that resemble the defaults of Ivy and co., while the
-latter group will revert to an even more nuanced aesthetic."
-  :type '(choice
-          (const :tag "Respect the framework's established aesthetic 
(default)" nil)
-          (const :tag "Subtle backgrounds for various elements" moderate)
-          (const :tag "Radical alternative to the framework's looks" 
opinionated)))
-
-(defcustom modus-operandi-theme-prompts nil
-  "Use subtle or intense styles for minibuffer and REPL prompts.
-
-Nil means to only use an accented foreground colour.
-
-Options `subtle' and `intense' will change both the background
-and the foreground values.  The latter has a more pronounced
-effect than the former."
-  :type '(choice
-          (const :tag "No prompt background (default)" nil)
-          (const :tag "Subtle accented background for the prompt" subtle)
-          (const :tag "Intense background and foreground for the prompt" 
intense)))
-
-(defcustom modus-operandi-theme-intense-hl-line nil
-  "Use more prominent background for command `hl-line-mode'."
-  :type 'boolean)
-
-(defcustom modus-operandi-theme-intense-paren-match nil
-  "Use more prominent colour for parenthesis matching."
-  :type 'boolean)
-
-(defcustom modus-operandi-theme-faint-syntax nil
-  "Use less saturated colours for code syntax highlighting."
-  :type 'boolean)
-
-(defcustom modus-operandi-theme-no-link-underline nil
-  "Do not underline links."
-  :type 'boolean)
-
-;;; Internal functions
-
-;; Helper functions that are meant to ease the implementation of the
-;; above customisation options.
-(defun modus-operandi-theme-bold-weight ()
-  "Conditional use of a heavier text weight."
-  (when modus-operandi-theme-bold-constructs
-    (list :inherit 'bold)))
-
-(defun modus-operandi-theme-mixed-fonts ()
-  "Conditional application of `fixed-pitch' inheritance."
-  (unless modus-operandi-theme-no-mixed-fonts
-    (list :inherit 'fixed-pitch)))
-
-(defun modus-operandi-theme-fringe (subtlebg intensebg)
-  "Conditional use of background colours for fringes.
-SUBTLEBG should be a subtle greyscale value.  INTENSEBG must be a
-more pronounced greyscale colour."
-  (pcase modus-operandi-theme-fringes
-    ('intense (list :background intensebg))
-    ('subtle (list :background subtlebg))
-    (_ (list :background nil))))
-
-(defun modus-operandi-theme-prompt (mainfg subtlebg subtlefg intensebg 
intensefg)
-  "Conditional use of background colours for prompts.
-MAINFG is the prompt's standard foreground.  SUBTLEBG should be a
-subtle accented background that works with SUBTLEFG.  INTENSEBG
-must be a more pronounced accented colour that should be
-combinable with INTENSEFG."
-  (pcase modus-operandi-theme-prompts
-    ('intense (list :background intensebg :foreground intensefg))
-    ('subtle (list :background subtlebg :foreground subtlefg))
-    (_ (list :background nil :foreground mainfg))))
-
-(defun modus-operandi-theme-paren (normalbg intensebg)
-  "Conditional use of intense colours for matching parentheses.
-NORMALBG should the special palette colour 'bg-paren-match' or
-something similar.  INTENSEBG must be easier to discern next to
-other backgrounds, such as the special palette colour
-'bg-paren-match-intense'."
-  (if modus-operandi-theme-intense-paren-match
-      (list :background intensebg)
-    (list :background normalbg)))
-
-(defun modus-operandi-theme-syntax-foreground (normal faint)
-  "Apply foreground value to code syntax.
-NORMAL is the more saturated colour, which should be the default.
-FAINT is the less saturated colour."
-  (if modus-operandi-theme-faint-syntax
-      (list :foreground faint)
-    (list :foreground normal)))
-
-(defun modus-operandi-theme-heading-p (key)
-  "Query style of KEY in `modus-operandi-theme-headings'."
-  (cdr (assoc key modus-operandi-theme-headings)))
-
-(defun modus-operandi-theme-heading (level fg fg-alt bg border)
-  "Conditional styles for `modus-operandi-theme-headings'.
-
-LEVEL is the heading's position in their order.  FG is the
-default text colour.  FG-ALT is an accented, more saturated value
-than the default.  BG is a nuanced, typically accented,
-background that can work well with either of the foreground
-values.  BORDER is a colour value that combines well with the
-background and alternative foreground."
-  (let* ((key (modus-operandi-theme-heading-p `,level))
-         (style (or key (modus-operandi-theme-heading-p t)))
-         (var (if modus-operandi-theme-variable-pitch-headings
-                  'variable-pitch
-                'default)))
-    (pcase style
-      ('no-bold
-       (list :inherit `,var :foreground fg))
-      ('line
-       (list :inherit `(bold ,var) :foreground fg :overline border))
-      ('line-no-bold
-       (list :inherit `,var :foreground fg :overline border))
-      ('rainbow
-       (list :inherit `(bold ,var) :foreground fg-alt))
-      ('rainbow-no-bold
-       (list :inherit `,var :foreground fg-alt))
-      ('rainbow-line
-       (list :inherit `(bold ,var) :foreground fg-alt :overline border))
-      ('rainbow-line-no-bold
-       (list :inherit `,var :foreground fg-alt :overline border))
-      ('highlight
-       (list :inherit `(bold ,var) :background bg :foreground fg))
-      ('highlight-no-bold
-       (list :inherit `,var :background bg :foreground fg))
-      ('rainbow-highlight
-       (list :inherit `(bold ,var) :background bg :foreground fg-alt))
-      ('rainbow-highlight-no-bold
-       (list :inherit `,var :background bg :foreground fg-alt))
-      ('section
-       (append
-        (and (>= emacs-major-version 27) '(:extend t))
-        (list :inherit `(bold ,var) :background bg :foreground fg :overline 
border)))
-      ('section-no-bold
-       (append
-        (and (>= emacs-major-version 27) '(:extend t))
-        (list :inherit `,var :background bg :foreground fg :overline border)))
-      ('rainbow-section
-       (append
-        (and (>= emacs-major-version 27) '(:extend t))
-        (list :inherit `(bold ,var) :background bg :foreground fg-alt 
:overline border)))
-      ('rainbow-section-no-bold
-       (append
-        (and (>= emacs-major-version 27) '(:extend t))
-        (list :inherit `,var :background bg :foreground fg-alt :overline 
border)))
-      (_
-       (list :inherit `(bold ,var) :foreground fg)))))
-
-(defun modus-operandi-theme-org-block (bgblk)
-  "Conditionally set the background of Org blocks.
-BGBLK applies to a distinct neutral background.  Else blocks have
-no background of their own (the default), so they look the same
-as the rest of the buffer.
-
-`modus-operandi-theme-org-blocks' also accepts a `rainbow' option
-which is applied conditionally to `org-src-block-faces' (see the
-theme's source code)."
-  (if (eq modus-operandi-theme-org-blocks 'greyscale)
-      (append
-       (and (>= emacs-major-version 27) '(:extend t))
-       (list :background bgblk))
-    (list :background nil)))
-
-(defun modus-operandi-theme-org-block-delim (bgaccent fgaccent bg fg)
-  "Conditionally set the styles of Org block delimiters.
-BG, FG, BGACCENT, FGACCENT apply a background and foreground
-colour respectively.
-
-The former pair is a greyscale combination that should be more
-distinct than the background of the block.  It is applied to the
-default styles or when `modus-operandi-theme-org-blocks' is set
-to `greyscale'.
-
-The latter pair should be more subtle than the background of the
-block, as it is used when `modus-operandi-theme-org-blocks' is
-set to `rainbow'."
-  (pcase modus-operandi-theme-org-blocks
-    ('greyscale (append (and (>= emacs-major-version 27) '(:extend t))
-                        (list :background bg :foreground fg)))
-    ('rainbow (list :background bgaccent :foreground fgaccent))
-    (_ (list :background bg :foreground fg))))
-
-(defun modus-operandi-theme-mode-line-attrs
-    (fg bg fg-alt bg-alt border border-3d &optional alt-style border-width 
fg-distant)
-  "Colour combinations for `modus-operandi-theme-mode-line'.
-
-FG and BG are the default colours.  FG-ALT and BG-ALT are meant
-to accommodate the options for a 3D modeline or a `moody'
-compliant one.  BORDER applies to all permutations of the
-modeline, except the three-dimensional effect, where BORDER-3D is
-used instead.
-
-Optional ALT-STYLE applies an appropriate style to the mode
-line's box property.
-
-Optional BORDER-WIDTH specifies an integer for the width of the
-rectangle that produces the box effect.
-
-Optional FG-DISTANT should be close to the main background
-values.  It is intended to be used as a distant-foreground
-property."
-  (pcase modus-operandi-theme-mode-line
-    ('3d
-     `(:background ,bg-alt :foreground ,fg-alt
-                   :box (:line-width ,(or border-width 1)
-                                     :color ,border-3d
-                                     :style ,(and alt-style 
'released-button))))
-    ('moody
-     `(:background ,bg-alt :foreground ,fg-alt :underline ,border :overline 
,border
-                   :distant-foreground ,fg-distant))
-    (_
-     `(:foreground ,fg :background ,bg :box ,border))))
-
-(defun modus-operandi-theme-diff (fg-only-bg fg-only-fg mainbg mainfg altbg 
altfg)
-  "Colour combinations for `modus-operandi-theme-diffs'.
-
-FG-ONLY-BG should be similar or the same as the main background.
-FG-ONLY-FG should be a saturated accent value that can be
-combined with the former.
-
-MAINBG must be one of the dedicated backgrounds for diffs while
-MAINFG must be the same for the foreground.
-
-ALTBG needs to be a slightly accented background that is meant to
-be combined with ALTFG.  Both must be less intense than MAINBG
-and MAINFG respectively."
-  (pcase modus-operandi-theme-diffs
-    ('fg-only (list :background fg-only-bg :foreground fg-only-fg))
-    ('desaturated (list :background altbg :foreground altfg))
-    (_ (list :background mainbg :foreground mainfg))))
-
-(defun modus-operandi-theme-standard-completions (mainfg subtlebg intensebg 
intensefg)
-  "Combinations for `modus-operandi-theme-completions'.
-
-MAINFG is an accented foreground value.  SUBTLEBG is an accented
-background value that can be combined with MAINFG.  INTENSEBG and
-INTENSEFG are accented colours that are designed to be used in
-tandem.
-
-These are intended for Icomplete, Ido, and related."
-  (pcase modus-operandi-theme-completions
-    ('opinionated (list :background intensebg :foreground intensefg))
-    ('moderate (list :background subtlebg :foreground mainfg))
-    (_ (list :foreground mainfg))))
-
-(defun modus-operandi-theme-extra-completions (subtleface intenseface altface 
&optional altfg bold)
-  "Combinations for `modus-operandi-theme-completions'.
-
-SUBTLEFACE and INTENSEFACE are custom theme faces that combine a
-background and foreground value.  The difference between the two
-is a matter of degree.
-
-ALTFACE is a combination of colours that represents a departure
-from the UI's default aesthetics.  Optional ALTFG is meant to be
-used in tandem with it.
-
-Optional BOLD will apply a heavier weight to the text.
-
-These are intended for Helm, Ivy, etc."
-  (pcase modus-operandi-theme-completions
-    ('opinionated (list :inherit (list altface bold)
-                        :foreground (or altfg 'unspecified)))
-    ('moderate (list :inherit (list subtleface bold)))
-    (_ (list :inherit (list intenseface bold)))))
-
-(defun modus-operandi-theme-scale (amount)
-  "Scale heading by AMOUNT.
-
-AMOUNT is a customisation option."
-  (when modus-operandi-theme-scale-headings
-    (list :height amount)))
-
-;;; Colour palette
-
-;; Define colour palette.  Each colour must have a >= 7:1 contrast
-;; ratio relative to the foreground/background colour it is rendered
-;; against.
-;;
-;; The design of the colour palette as a macro that maps it to faces is
-;; adapted from zenbern-theme.el, last seen at commit 7dd7968:
-;; https://github.com/bbatsov/zenburn-emacs
 (eval-and-compile
-  (defconst modus-operandi-theme-default-colors-alist
-    '(;; base values
-      ("bg-main" . "#ffffff") ("fg-main" . "#000000")
-      ("bg-alt" . "#f0f0f0") ("fg-alt" . "#505050")
-      ("bg-dim" . "#f8f8f8") ("fg-dim" . "#282828")
-      ;; specifically for on/off states (e.g. `mode-line')
-      ;;
-      ;; must be combined with themselves
-      ("bg-active" . "#d7d7d7") ("fg-active" . "#0a0a0a")
-      ("bg-inactive" . "#efefef") ("fg-inactive" . "#404148")
-      ;; special base values, used only for cases where the above
-      ;; fg-* or bg-* cannot or should not be used (to avoid confusion)
-      ;; must be combined with: {fg,bg}-{main,alt,dim}
-      ("bg-special-cold" . "#dde3f4") ("fg-special-cold" . "#093060")
-      ("bg-special-mild" . "#c4ede0") ("fg-special-mild" . "#184034")
-      ("bg-special-warm" . "#f0e0d4") ("fg-special-warm" . "#5d3026")
-      ("bg-special-calm" . "#f8ddea") ("fg-special-calm" . "#61284f")
-      ;; styles for the main constructs
-      ;;
-      ;; must be combined with: `bg-main', `bg-alt', `bg-dim'
-      ("red" . "#a60000") ("green" . "#005e00")
-      ("yellow" . "#813e00") ("blue" . "#0031a9")
-      ("magenta" . "#721045") ("cyan" . "#00538b")
-      ;; styles for common, but still specialised constructs
-      ;;
-      ;; must be combined with: `bg-main', `bg-alt', `bg-dim'
-      ("red-alt" . "#972500") ("green-alt" . "#315b00")
-      ("yellow-alt" . "#70480f") ("blue-alt" . "#2544bb")
-      ("magenta-alt" . "#8f0075") ("cyan-alt" . "#30517f")
-      ;; same purpose as above, just slight differences
-      ;;
-      ;; must be combined with: `bg-main', `bg-alt', `bg-dim'
-      ("red-alt-other" . "#a0132f") ("green-alt-other" . "#145c33")
-      ("yellow-alt-other" . "#863927") ("blue-alt-other" . "#0000c0")
-      ("magenta-alt-other" . "#5317ac") ("cyan-alt-other" . "#005a5f")
-      ;; styles for desaturated foreground text, intended for use with
-      ;; the `modus-operandi-theme-faint-syntax' option
-      ;;
-      ;; must be combined with: `bg-main', `bg-alt', `bg-dim'
-      ("red-faint" . "#7f1010") ("green-faint" . "#104410")
-      ("yellow-faint" . "#5f4400") ("blue-faint" . "#002f88")
-      ("magenta-faint" . "#752f50") ("cyan-faint" . "#12506f")
-
-      ("red-alt-faint" . "#702f00") ("green-alt-faint" . "#30440f")
-      ("yellow-alt-faint" . "#5d5000") ("blue-alt-faint" . "#003f78")
-      ("magenta-alt-faint" . "#702565") ("cyan-alt-faint" . "#354f6f")
-
-      ("red-alt-other-faint" . "#7f002f") ("green-alt-other-faint" . "#0f443f")
-      ("yellow-alt-other-faint" . "#5e3a20") ("blue-alt-other-faint" . 
"#1f2f6f")
-      ("magenta-alt-other-faint" . "#5f3f7f") ("cyan-alt-other-faint" . 
"#2e584f")
-      ;; styles for elements that should be very subtle, yet accented
-      ;;
-      ;; must be combined with: `bg-main', `bg-alt', `bg-dim' or any of
-      ;; the "nuanced" backgrounds
-      ("red-nuanced" . "#5f0000") ("green-nuanced" . "#004000")
-      ("yellow-nuanced" . "#3f3000") ("blue-nuanced" . "#201f55")
-      ("magenta-nuanced" . "#541f4f") ("cyan-nuanced" . "#0f3360")
-      ;; styles for slightly accented background
-      ;;
-      ;; must be combined with any of the above foreground values
-      ("red-nuanced-bg" . "#fff1f0") ("green-nuanced-bg" . "#ecf7ed")
-      ("yellow-nuanced-bg" . "#fff3da") ("blue-nuanced-bg" . "#f3f3ff")
-      ("magenta-nuanced-bg" . "#fdf0ff") ("cyan-nuanced-bg" . "#ebf6fa")
-      ;; styles for elements that should draw attention to themselves
-      ;;
-      ;; must be combined with: `bg-main'
-      ("red-intense" . "#b60000") ("green-intense" . "#006800")
-      ("yellow-intense" . "#904200") ("blue-intense" . "#1111ee")
-      ("magenta-intense" . "#7000e0") ("cyan-intense" . "#205b93")
-      ;; styles for background elements that should be visible yet
-      ;; subtle
-      ;;
-      ;; must be combined with: `fg-dim'
-      ("red-subtle-bg" . "#f2b0a2") ("green-subtle-bg" . "#aecf90")
-      ("yellow-subtle-bg" . "#e4c340") ("blue-subtle-bg" . "#b5d0ff")
-      ("magenta-subtle-bg" . "#f0d3ff") ("cyan-subtle-bg" . "#c0efff")
-      ;; styles for background elements that should be visible and
-      ;; distinguishable
-      ;;
-      ;; must be combined with: `fg-main'
-      ("red-intense-bg" . "#ff8892") ("green-intense-bg" . "#5ada88")
-      ("yellow-intense-bg" . "#f5df23") ("blue-intense-bg" . "#6aaeff")
-      ("magenta-intense-bg" . "#d5baff") ("cyan-intense-bg" . "#42cbd4")
-      ;; styles for refined contexts where both the foreground and the
-      ;; background need to have the same/similar hue
-      ;;
-      ;; must be combined with themselves OR the foregrounds can be
-      ;; combined with any of the base backgrounds
-      ("red-refine-bg" . "#ffcccc") ("red-refine-fg" . "#780000")
-      ("green-refine-bg" . "#aceaac") ("green-refine-fg" . "#004c00")
-      ("yellow-refine-bg" . "#fff29a") ("yellow-refine-fg" . "#604000")
-      ("blue-refine-bg" . "#8ac7ff") ("blue-refine-fg" . "#002288")
-      ("magenta-refine-bg" . "#ffccff") ("magenta-refine-fg" . "#770077")
-      ("cyan-refine-bg" . "#8eecf4") ("cyan-refine-fg" . "#004850")
-      ;; styles that are meant exclusively for the mode line
-      ;;
-      ;; must be combined with: `bg-active', `bg-inactive'
-      ("red-active" . "#8a0000") ("green-active" . "#004c2e")
-      ("yellow-active" . "#702d1f") ("blue-active" . "#0030b4")
-      ("magenta-active" . "#5c2092") ("cyan-active" . "#003f8a")
-      ;; styles that are meant exclusively for the fringes
-      ;;
-      ;; must be combined with `fg-main'
-      ("red-fringe-bg" . "#f08290") ("green-fringe-bg" . "#62c86a")
-      ("yellow-fringe-bg" . "#dbba3f") ("blue-fringe-bg" . "#82afff")
-      ("magenta-fringe-bg" . "#e0a3ff") ("cyan-fringe-bg" . "#2fcddf")
-      ;; styles reserved for specific faces
-      ;;
-      ;; `bg-hl-line' is between `bg-dim' and `bg-alt', so it should
-      ;; work with all accents that cover those two, plus `bg-main'
-      ;;
-      ;; `bg-hl-alt' and `bg-hl-alt-intense' should only be used when no
-      ;; other greyscale or fairly neutral background is available to
-      ;; properly draw attention to a given construct
-      ;;
-      ;; `bg-header' is between `bg-active' and `bg-inactive', so it
-      ;; can be combined with any of the "active" values, plus the
-      ;; "special" and base foreground colours
-      ;;
-      ;; `bg-paren-match', `bg-paren-match-intense', `bg-region' and
-      ;; `bg-tab-active' must be combined with `fg-main', while
-      ;; `bg-tab-inactive' should be combined with `fg-dim'
-      ;;
-      ;; `bg-tab-bar' is only intended for the bar that holds the tabs and
-      ;; can only be combined with `fg-main'
-      ;;
-      ;; `fg-tab-active' is meant to be combined with `bg-tab-active',
-      ;; though only for styling special elements, such as underlining
-      ;; the current tab
-      ;;
-      ;; `fg-escape-char-construct' and `fg-escape-char-backslash' can
-      ;; be combined `bg-main', `bg-dim', `bg-alt'
-      ;;
-      ;; `fg-lang-error', `fg-lang-warning', `fg-lang-note' can be
-      ;; combined with `bg-main', `bg-dim', `bg-alt'
-      ;;
-      ;; `fg-mark-sel', `fg-mark-del', `fg-mark-alt' can be combined
-      ;; with `bg-main', `bg-dim', `bg-alt', `bg-hl-line'
-      ;;
-      ;; `fg-unfocused' must be combined with `fg-main'
-      ;;
-      ;; the window divider colours apply to faces with just an fg value
-      ;;
-      ;; all pairs are combinable with themselves
-      ("bg-hl-line" . "#f2eff3")
-      ("bg-hl-line-intense" . "#e0e0e0")
-      ("bg-hl-alt" . "#fbeee0")
-      ("bg-hl-alt-intense" . "#e8dfd1")
-      ("bg-paren-match" . "#e0af82")
-      ("bg-paren-match-intense" . "#c488ff")
-      ("bg-region" . "#bcbcbc")
-
-      ("bg-tab-bar" . "#d5d5d5")
-      ("bg-tab-active" . "#f6f6f6")
-      ("bg-tab-inactive" . "#bdbdbd")
-      ("fg-tab-active" . "#30169e")
+  (unless (and (fboundp 'require-theme)
+               (require-theme 'modus-themes t))
+    (require 'modus-themes)))
 
-      ("fg-escape-char-construct" . "#8b1030")
-      ("fg-escape-char-backslash" . "#654d0f")
-
-      ("fg-lang-error" . "#9f004f")
-      ("fg-lang-warning" . "#604f0f")
-      ("fg-lang-note" . "#4040ae")
-
-      ("fg-window-divider-inner" . "#888888")
-      ("fg-window-divider-outer" . "#585858")
-
-      ("fg-unfocused" . "#56576d")
-
-      ("bg-header" . "#e5e5e5") ("fg-header" . "#2a2a2a")
-
-      ("bg-whitespace" . "#fff8fc") ("fg-whitespace" . "#645060")
-
-      ("bg-diff-heading" . "#b7c2dd") ("fg-diff-heading" . "#043355")
-      ("bg-diff-added" . "#d4fad4") ("fg-diff-added" . "#004500")
-      ("bg-diff-changed" . "#fcefcf") ("fg-diff-changed" . "#524200")
-      ("bg-diff-removed" . "#ffe8ef") ("fg-diff-removed" . "#691616")
-
-      ("bg-diff-refine-added" . "#94cf94") ("fg-diff-refine-added" . "#002a00")
-      ("bg-diff-refine-changed" . "#cccf8f") ("fg-diff-refine-changed" . 
"#302010")
-      ("bg-diff-refine-removed" . "#daa2b0") ("fg-diff-refine-removed" . 
"#400000")
-
-      ("bg-diff-focus-added" . "#bbeabb") ("fg-diff-focus-added" . "#002c00")
-      ("bg-diff-focus-changed" . "#ecdfbf") ("fg-diff-focus-changed" . 
"#392900")
-      ("bg-diff-focus-removed" . "#efcbcf") ("fg-diff-focus-removed" . 
"#4a0000")
-
-      ("bg-diff-neutral-0" . "#979797") ("fg-diff-neutral-0" . "#040404")
-      ("bg-diff-neutral-1" . "#b0b0b0") ("fg-diff-neutral-1" . "#252525")
-      ("bg-diff-neutral-2" . "#cccccc") ("fg-diff-neutral-2" . "#3a3a3a")
-
-      ("bg-mark-sel" . "#a0f0cf") ("fg-mark-sel" . "#005040")
-      ("bg-mark-del" . "#ffccbb") ("fg-mark-del" . "#840040")
-      ("bg-mark-alt" . "#f5d88f") ("fg-mark-alt" . "#782900"))
-    "The entire palette of `modus-operandi-theme'.
-Each element has the form (NAME . HEX).")
-
-  (defcustom modus-operandi-theme-override-colors-alist '()
-    "Association list of palette colour overrides.
-Values can be mapped to variables, using the same syntax as the
-one present in `modus-operandi-theme-default-colors-alist'.
-
-This is only meant for do-it-yourself usage, with the
-understanding that the user is responsible for the resulting
-contrast ratio between new and existing colours."
-    :type '(alist
-            :key-type (string :tag "Name")
-            :value-type (string :tag " Hex")))
-
-  (defmacro modus-operandi-theme-with-color-variables (&rest body)
-    "`let' bind all colours around BODY.
-Also bind `class' to ((class color) (min-colors 89))."
-    (declare (indent 0))
-    `(let ((class '((class color) (min-colors 89)))
-           ,@(mapcar (lambda (cons)
-                       (list (intern (car cons)) (cdr cons)))
-                     (append modus-operandi-theme-default-colors-alist
-                             modus-operandi-theme-override-colors-alist))
-           ;; simple conditional styles that evaluate user-facing
-           ;; customisation options
-           (modus-theme-slant
-            (if modus-operandi-theme-slanted-constructs 'italic 'normal))
-           (modus-theme-variable-pitch
-            (if modus-operandi-theme-variable-pitch-headings 'variable-pitch 
'default)))
-       ,@body)))
-
-
-
-;;; Faces
-
-(modus-operandi-theme-with-color-variables
-  (custom-theme-set-faces
-   'modus-operandi
-;;;; custom faces
-   ;; these bespoke faces are inherited by other constructs below
-;;;;; subtle coloured backgrounds
-   `(modus-theme-subtle-red ((,class :background ,red-subtle-bg :foreground 
,fg-dim)))
-   `(modus-theme-subtle-green ((,class :background ,green-subtle-bg 
:foreground ,fg-dim)))
-   `(modus-theme-subtle-yellow ((,class :background ,yellow-subtle-bg 
:foreground ,fg-dim)))
-   `(modus-theme-subtle-blue ((,class :background ,blue-subtle-bg :foreground 
,fg-dim)))
-   `(modus-theme-subtle-magenta ((,class :background ,magenta-subtle-bg 
:foreground ,fg-dim)))
-   `(modus-theme-subtle-cyan ((,class :background ,cyan-subtle-bg :foreground 
,fg-dim)))
-   `(modus-theme-subtle-neutral ((,class :background ,bg-inactive :foreground 
,fg-inactive)))
-;;;;; intense coloured backgrounds
-   `(modus-theme-intense-red ((,class :background ,red-intense-bg :foreground 
,fg-main)))
-   `(modus-theme-intense-green ((,class :background ,green-intense-bg 
:foreground ,fg-main)))
-   `(modus-theme-intense-yellow ((,class :background ,yellow-intense-bg 
:foreground ,fg-main)))
-   `(modus-theme-intense-blue ((,class :background ,blue-intense-bg 
:foreground ,fg-main)))
-   `(modus-theme-intense-magenta ((,class :background ,magenta-intense-bg 
:foreground ,fg-main)))
-   `(modus-theme-intense-cyan ((,class :background ,cyan-intense-bg 
:foreground ,fg-main)))
-   `(modus-theme-intense-neutral ((,class :background ,bg-active :foreground 
,fg-main)))
-;;;;; refined background and foreground combinations
-   ;; general purpose styles that use an accented foreground against an
-   ;; accented background
-   `(modus-theme-refine-red ((,class :background ,red-refine-bg :foreground 
,red-refine-fg)))
-   `(modus-theme-refine-green ((,class :background ,green-refine-bg 
:foreground ,green-refine-fg)))
-   `(modus-theme-refine-yellow ((,class :background ,yellow-refine-bg 
:foreground ,yellow-refine-fg)))
-   `(modus-theme-refine-blue ((,class :background ,blue-refine-bg :foreground 
,blue-refine-fg)))
-   `(modus-theme-refine-magenta ((,class :background ,magenta-refine-bg 
:foreground ,magenta-refine-fg)))
-   `(modus-theme-refine-cyan ((,class :background ,cyan-refine-bg :foreground 
,cyan-refine-fg)))
-;;;;; "active" combinations, mostly for use on the mode line
-   `(modus-theme-active-red ((,class :background ,red-active :foreground 
,bg-active)))
-   `(modus-theme-active-green ((,class :background ,green-active :foreground 
,bg-active)))
-   `(modus-theme-active-yellow ((,class :background ,yellow-active :foreground 
,bg-active)))
-   `(modus-theme-active-blue ((,class :background ,blue-active :foreground 
,bg-active)))
-   `(modus-theme-active-magenta ((,class :background ,magenta-active 
:foreground ,bg-active)))
-   `(modus-theme-active-cyan ((,class :background ,cyan-active :foreground 
,bg-active)))
-;;;;; nuanced backgrounds
-   ;; useful for adding an accented background that is suitable for all
-   ;; main foreground colours (intended for use in Org source blocks)
-   `(modus-theme-nuanced-red ((,class :background ,red-nuanced-bg
-                                      ,@(and (>= emacs-major-version 27) 
'(:extend t)))))
-   `(modus-theme-nuanced-green ((,class :background ,green-nuanced-bg
-                                        ,@(and (>= emacs-major-version 27) 
'(:extend t)))))
-   `(modus-theme-nuanced-yellow ((,class :background ,yellow-nuanced-bg
-                                         ,@(and (>= emacs-major-version 27) 
'(:extend t)))))
-   `(modus-theme-nuanced-blue ((,class :background ,blue-nuanced-bg
-                                       ,@(and (>= emacs-major-version 27) 
'(:extend t)))))
-   `(modus-theme-nuanced-magenta ((,class :background ,magenta-nuanced-bg
-                                          ,@(and (>= emacs-major-version 27) 
'(:extend t)))))
-   `(modus-theme-nuanced-cyan ((,class :background ,cyan-nuanced-bg
-                                       ,@(and (>= emacs-major-version 27) 
'(:extend t)))))
-;;;;; fringe-specific combinations
-   `(modus-theme-fringe-red ((,class :background ,red-fringe-bg :foreground 
,fg-main)))
-   `(modus-theme-fringe-green ((,class :background ,green-fringe-bg 
:foreground ,fg-main)))
-   `(modus-theme-fringe-yellow ((,class :background ,yellow-fringe-bg 
:foreground ,fg-main)))
-   `(modus-theme-fringe-blue ((,class :background ,blue-fringe-bg :foreground 
,fg-main)))
-   `(modus-theme-fringe-magenta ((,class :background ,magenta-fringe-bg 
:foreground ,fg-main)))
-   `(modus-theme-fringe-cyan ((,class :background ,cyan-fringe-bg :foreground 
,fg-main)))
-;;;;; special base values
-   ;; these are closer to the grayscale than the accents defined above
-   ;; and should only be used when the next closest alternative would be
-   ;; a greyscale value than an accented one
-   `(modus-theme-special-cold ((,class :background ,bg-special-cold 
:foreground ,fg-special-cold)))
-   `(modus-theme-special-mild ((,class :background ,bg-special-mild 
:foreground ,fg-special-mild)))
-   `(modus-theme-special-warm ((,class :background ,bg-special-warm 
:foreground ,fg-special-warm)))
-   `(modus-theme-special-calm ((,class :background ,bg-special-calm 
:foreground ,fg-special-calm)))
-;;;;; diff-specific combinations
-   ;; intended for `diff-mode' or equivalent
-   `(modus-theme-diff-added
-     ((,class ,@(modus-operandi-theme-diff
-                 bg-main green
-                 bg-diff-focus-added fg-diff-focus-added
-                 green-nuanced-bg fg-diff-added))))
-   `(modus-theme-diff-changed
-     ((,class ,@(modus-operandi-theme-diff
-                 bg-main yellow
-                 bg-diff-focus-changed fg-diff-focus-changed
-                 yellow-nuanced-bg fg-diff-changed))))
-   `(modus-theme-diff-removed
-     ((,class ,@(modus-operandi-theme-diff
-                 bg-main red
-                 bg-diff-focus-removed fg-diff-focus-removed
-                 red-nuanced-bg fg-diff-removed))))
-   `(modus-theme-diff-refine-added
-     ((,class ,@(modus-operandi-theme-diff
-                 bg-diff-added fg-diff-added
-                 bg-diff-refine-added fg-diff-refine-added
-                 bg-diff-focus-added fg-diff-focus-added))))
-   `(modus-theme-diff-refine-changed
-     ((,class ,@(modus-operandi-theme-diff
-                 bg-diff-changed fg-diff-changed
-                 bg-diff-refine-changed fg-diff-refine-changed
-                 bg-diff-focus-changed fg-diff-focus-changed))))
-   `(modus-theme-diff-refine-removed
-     ((,class ,@(modus-operandi-theme-diff
-                 bg-diff-removed fg-diff-removed
-                 bg-diff-refine-removed fg-diff-refine-removed
-                 bg-diff-focus-removed fg-diff-focus-removed))))
-   `(modus-theme-diff-focus-added
-     ((,class ,@(modus-operandi-theme-diff
-                 bg-dim green
-                 bg-diff-focus-added fg-diff-focus-added
-                 bg-diff-added fg-diff-added))))
-   `(modus-theme-diff-focus-changed
-     ((,class ,@(modus-operandi-theme-diff
-                 bg-dim yellow
-                 bg-diff-focus-changed fg-diff-focus-changed
-                 bg-diff-changed fg-diff-changed))))
-   `(modus-theme-diff-focus-removed
-     ((,class ,@(modus-operandi-theme-diff
-                 bg-dim red
-                 bg-diff-focus-removed fg-diff-focus-removed
-                 bg-diff-removed fg-diff-removed))))
-   `(modus-theme-diff-heading
-     ((,class ,@(modus-operandi-theme-diff
-                 bg-alt blue-alt
-                 bg-diff-heading fg-diff-heading
-                 blue-nuanced-bg blue))))
-;;;;; mark indicators
-   ;; colour combinations intended for Dired, Ibuffer, or equivalent
-   `(modus-theme-pseudo-header ((,class :inherit bold :foreground ,fg-main)))
-   `(modus-theme-mark-alt ((,class :inherit bold :background ,bg-mark-alt 
:foreground ,fg-mark-alt)))
-   `(modus-theme-mark-del ((,class :inherit bold :background ,bg-mark-del 
:foreground ,fg-mark-del)))
-   `(modus-theme-mark-sel ((,class :inherit bold :background ,bg-mark-sel 
:foreground ,fg-mark-sel)))
-   `(modus-theme-mark-symbol ((,class :inherit bold :foreground ,blue-alt)))
-;;;;; heading levels
-   ;; styles for regular headings used in Org, Markdown, Info, etc.
-   `(modus-theme-heading-1
-     ((,class ,@(modus-operandi-theme-heading
-                 1 fg-main magenta-alt-other magenta-nuanced-bg bg-region)
-              ,@(modus-operandi-theme-scale modus-operandi-theme-scale-4))))
-   `(modus-theme-heading-2
-     ((,class ,@(modus-operandi-theme-heading
-                 2 fg-special-warm magenta-alt red-nuanced-bg bg-region)
-              ,@(modus-operandi-theme-scale modus-operandi-theme-scale-3))))
-   `(modus-theme-heading-3
-     ((,class ,@(modus-operandi-theme-heading
-                 3 fg-special-cold blue blue-nuanced-bg bg-region)
-              ,@(modus-operandi-theme-scale modus-operandi-theme-scale-2))))
-   `(modus-theme-heading-4
-     ((,class ,@(modus-operandi-theme-heading
-                 4 fg-special-mild cyan cyan-nuanced-bg bg-region)
-              ,@(modus-operandi-theme-scale modus-operandi-theme-scale-1))))
-   `(modus-theme-heading-5
-     ((,class ,@(modus-operandi-theme-heading
-                 5 fg-special-calm green-alt-other green-nuanced-bg 
bg-region))))
-   `(modus-theme-heading-6
-     ((,class ,@(modus-operandi-theme-heading
-                 6 yellow-nuanced yellow-alt-other yellow-nuanced-bg 
bg-region))))
-   `(modus-theme-heading-7
-     ((,class ,@(modus-operandi-theme-heading
-                 7 red-nuanced red-alt red-nuanced-bg bg-region))))
-   `(modus-theme-heading-8
-     ((,class ,@(modus-operandi-theme-heading
-                 8 fg-dim magenta bg-alt bg-region))))
-;;;;; other custom faces
-   `(modus-theme-hl-line ((,class :background ,(if 
modus-operandi-theme-intense-hl-line
-                                                   bg-hl-line-intense 
bg-hl-line)
-                                  (and (>= emacs-major-version 27) '(:extend 
t)))))
-;;;; standard faces
-;;;;; absolute essentials
-   `(default ((,class :background ,bg-main :foreground ,fg-main)))
-   `(cursor ((,class :background ,fg-main)))
-   `(fringe ((,class ,@(modus-operandi-theme-fringe bg-inactive bg-active)
-                     :foreground ,fg-main)))
-   `(vertical-border ((,class :foreground ,fg-window-divider-inner)))
-;;;;; basic and/or ungrouped styles
-   ;; Modify the `bold' face to change the weight of all "bold" elements
-   ;; defined by the theme.  You need a typeface that supports a
-   ;; multitude of heavier weights than the regular one and then you
-   ;; must specify the exact name of the one you wish to apply.  Example
-   ;; for your init.el:
-   ;;
-   ;; (set-face-attribute 'bold nil :weight 'semibold)
-   `(bold ((,class :weight bold)))
-   `(comint-highlight-input ((,class :inherit bold)))
-   `(comint-highlight-prompt ((,class ,@(modus-operandi-theme-bold-weight)
-                                      ,@(modus-operandi-theme-prompt
-                                         cyan
-                                         blue-nuanced-bg blue-alt
-                                         blue-refine-bg fg-main))))
-   `(error ((,class :inherit bold :foreground ,red)))
-   `(escape-glyph ((,class :foreground ,fg-escape-char-construct)))
-   `(file-name-shadow ((,class :foreground ,fg-unfocused)))
-   `(header-line ((,class :background ,bg-header :foreground ,fg-header)))
-   `(header-line-highlight ((,class :inherit modus-theme-active-blue)))
-   `(help-argument-name ((,class :foreground ,cyan :slant ,modus-theme-slant)))
-   `(homoglyph ((,class :foreground ,fg-escape-char-construct)))
-   `(ibuffer-locked-buffer ((,class :foreground ,yellow-alt-other)))
-   `(italic ((,class :slant italic)))
-   `(nobreak-hyphen ((,class :foreground ,fg-escape-char-construct)))
-   `(nobreak-space ((,class :foreground ,fg-escape-char-construct :underline 
t)))
-   `(minibuffer-prompt ((,class ,@(modus-operandi-theme-prompt
-                                   cyan-alt-other
-                                   cyan-nuanced-bg cyan
-                                   cyan-refine-bg fg-main))))
-   `(mm-command-output ((,class :foreground ,red-alt-other)))
-   `(mm-uu-extract ((,class :background ,bg-dim :foreground ,fg-special-mild)))
-   `(next-error ((,class :inherit modus-theme-subtle-red)))
-   `(rectangle-preview ((,class :inherit modus-theme-special-mild)))
-   `(region ((,class :background ,bg-region :foreground ,fg-main)))
-   `(secondary-selection ((,class :inherit modus-theme-special-cold)))
-   `(shadow ((,class :foreground ,fg-alt)))
-   `(success ((,class :inherit bold :foreground ,green)))
-   `(trailing-whitespace ((,class :background ,red-intense-bg)))
-   `(warning ((,class :inherit bold :foreground ,yellow)))
-;;;;; buttons, links, widgets
-   `(button ((,class :foreground ,blue-alt-other
-                     ,@(unless modus-operandi-theme-no-link-underline
-                         (list :underline t)))))
-   `(link ((,class :inherit button)))
-   `(link-visited ((,class :inherit link :foreground ,magenta-alt-other)))
-   `(tooltip ((,class :background ,bg-special-cold :foreground ,fg-main)))
-   `(widget-button ((,class :inherit button)))
-   `(widget-button-pressed ((,class :inherit button :foreground ,magenta)))
-   `(widget-documentation ((,class :foreground ,green)))
-   `(widget-field ((,class :background ,bg-alt :foreground ,fg-dim)))
-   `(widget-inactive ((,class :background ,bg-inactive :foreground 
,fg-inactive)))
-   `(widget-single-line-field ((,class :inherit widget-field)))
-;;;;; ag
-   `(ag-hit-face ((,class :foreground ,fg-special-cold)))
-   `(ag-match-face ((,class :inherit modus-theme-special-calm)))
-;;;;; alert
-   `(alert-high-face ((,class :inherit bold :foreground ,red-alt)))
-   `(alert-low-face ((,class :foreground ,fg-special-mild)))
-   `(alert-moderate-face ((,class :inherit bold :foreground ,yellow)))
-   `(alert-trivial-face ((,class :foreground ,fg-special-calm)))
-   `(alert-urgent-face ((,class :inherit bold :foreground ,red-intense)))
-;;;;; all-the-icons
-   `(all-the-icons-blue ((,class :foreground ,blue)))
-   `(all-the-icons-blue-alt ((,class :foreground ,blue-alt)))
-   `(all-the-icons-cyan ((,class :foreground ,cyan)))
-   `(all-the-icons-cyan-alt ((,class :foreground ,cyan-alt)))
-   `(all-the-icons-dblue ((,class :foreground ,blue-alt-other)))
-   `(all-the-icons-dcyan ((,class :foreground ,cyan-alt-other)))
-   `(all-the-icons-dgreen ((,class :foreground ,green-alt-other)))
-   `(all-the-icons-dired-dir-face ((,class :foreground ,blue)))
-   `(all-the-icons-dmaroon ((,class :foreground ,magenta-alt-other)))
-   `(all-the-icons-dorange ((,class :foreground ,red-alt-other)))
-   `(all-the-icons-dpink ((,class :foreground ,magenta)))
-   `(all-the-icons-dpurple ((,class :foreground ,magenta-alt)))
-   `(all-the-icons-dred ((,class :foreground ,red)))
-   `(all-the-icons-dsilver ((,class :foreground ,fg-special-cold)))
-   `(all-the-icons-dyellow ((,class :foreground ,yellow)))
-   `(all-the-icons-green ((,class :foreground ,green)))
-   `(all-the-icons-lblue ((,class :foreground ,blue-refine-fg)))
-   `(all-the-icons-lcyan ((,class :foreground ,cyan-refine-fg)))
-   `(all-the-icons-lgreen ((,class :foreground ,green-refine-fg)))
-   `(all-the-icons-lmaroon ((,class :foreground ,magenta-refine-fg)))
-   `(all-the-icons-lorange ((,class :foreground ,red-refine-fg)))
-   `(all-the-icons-lpink ((,class :foreground ,magenta-refine-fg)))
-   `(all-the-icons-lpurple ((,class :foreground ,magenta-refine-fg)))
-   `(all-the-icons-lred ((,class :foreground ,red-refine-fg)))
-   `(all-the-icons-lsilver ((,class :foreground ,fg-special-cold)))
-   `(all-the-icons-lyellow ((,class :foreground ,yellow-refine-fg)))
-   `(all-the-icons-maroon ((,class :foreground ,magenta)))
-   `(all-the-icons-orange ((,class :foreground ,red-alt)))
-   `(all-the-icons-pink ((,class :foreground ,magenta)))
-   `(all-the-icons-purple ((,class :foreground ,magenta-alt)))
-   `(all-the-icons-purple-alt ((,class :foreground ,magenta-alt-other)))
-   `(all-the-icons-red ((,class :foreground ,red)))
-   `(all-the-icons-red-alt ((,class :foreground ,red-alt)))
-   `(all-the-icons-silver ((,class :foreground ,fg-special-cold)))
-   `(all-the-icons-yellow ((,class :foreground ,yellow)))
-;;;;; annotate
-   `(annotate-annotation ((,class :inherit modus-theme-subtle-blue)))
-   `(annotate-annotation-secondary ((,class :inherit 
modus-theme-subtle-green)))
-   `(annotate-highlight ((,class :background ,blue-nuanced-bg :underline 
,blue-intense)))
-   `(annotate-highlight-secondary ((,class :background ,green-nuanced-bg 
:underline ,green-intense)))
-;;;;; anzu
-   `(anzu-match-1 ((,class :inherit modus-theme-subtle-cyan)))
-   `(anzu-match-2 ((,class :inherit modus-theme-subtle-green)))
-   `(anzu-match-3 ((,class :inherit modus-theme-subtle-yellow)))
-   `(anzu-mode-line ((,class :inherit bold :foreground ,green-active)))
-   `(anzu-mode-line-no-match ((,class :inherit bold :foreground ,red-active)))
-   `(anzu-replace-highlight ((,class :inherit modus-theme-refine-yellow 
:underline t)))
-   `(anzu-replace-to ((,class :inherit (modus-theme-intense-green bold))))
-;;;;; apropos
-   `(apropos-function-button ((,class :inherit button :foreground 
,magenta-alt-other)))
-   `(apropos-keybinding ((,class :inherit bold :foreground ,cyan)))
-   `(apropos-misc-button ((,class :inherit button :foreground 
,cyan-alt-other)))
-   `(apropos-property ((,class ,@(modus-operandi-theme-bold-weight) 
:foreground ,magenta-alt)))
-   `(apropos-symbol ((,class ,@(modus-operandi-theme-bold-weight) :foreground 
,blue-alt-other)))
-   `(apropos-user-option-button ((,class :inherit button :foreground 
,green-alt-other)))
-   `(apropos-variable-button ((,class :inherit button :foreground ,blue)))
-;;;;; apt-sources-list
-   `(apt-sources-list-components ((,class :foreground ,cyan)))
-   `(apt-sources-list-options ((,class :foreground ,yellow)))
-   `(apt-sources-list-suite ((,class :foreground ,green)))
-   `(apt-sources-list-type ((,class :foreground ,magenta)))
-   `(apt-sources-list-uri ((,class :foreground ,blue)))
-;;;;; artbollocks-mode
-   `(artbollocks-face ((,class :foreground ,cyan-nuanced :underline 
,fg-lang-note)))
-   `(artbollocks-lexical-illusions-face ((,class :background ,bg-alt 
:foreground ,red-alt :underline t)))
-   `(artbollocks-passive-voice-face ((,class :foreground ,yellow-nuanced 
:underline ,fg-lang-warning)))
-   `(artbollocks-weasel-words-face ((,class :foreground ,red-nuanced 
:underline ,fg-lang-error)))
-;;;;; auctex and Tex
-   `(font-latex-bold-face ((,class :inherit bold :foreground 
,fg-special-calm)))
-   `(font-latex-doctex-documentation-face ((,class :foreground 
,fg-special-cold :slant ,modus-theme-slant)))
-   `(font-latex-doctex-preprocessor-face ((,class 
,@(modus-operandi-theme-bold-weight) :foreground ,red-alt-other)))
-   `(font-latex-italic-face ((,class :foreground ,fg-special-calm :slant 
italic)))
-   `(font-latex-math-face ((,class :foreground ,cyan-alt-other)))
-   `(font-latex-script-char-face ((,class :foreground ,cyan-alt-other)))
-   `(font-latex-sectioning-0-face ((,class :inherit 
,modus-theme-variable-pitch :foreground ,blue-nuanced)))
-   `(font-latex-sectioning-1-face ((,class :inherit (bold 
,modus-theme-variable-pitch) :foreground ,blue-nuanced)))
-   `(font-latex-sectioning-2-face ((,class :inherit (bold 
,modus-theme-variable-pitch) :foreground ,blue-nuanced)))
-   `(font-latex-sectioning-3-face ((,class :inherit (bold 
,modus-theme-variable-pitch) :foreground ,blue-nuanced)))
-   `(font-latex-sectioning-4-face ((,class :inherit (bold 
,modus-theme-variable-pitch) :foreground ,blue-nuanced)))
-   `(font-latex-sectioning-5-face ((,class :inherit 
,modus-theme-variable-pitch :foreground ,blue-nuanced)))
-   `(font-latex-sedate-face ((,class ,@(modus-operandi-theme-bold-weight) 
:foreground ,magenta-alt-other)))
-   `(font-latex-slide-title-face ((,class :inherit (bold 
,modus-theme-variable-pitch) :foreground ,cyan-nuanced
-                                          ,@(modus-operandi-theme-scale 
modus-operandi-theme-scale-4))))
-   `(font-latex-string-face ((,class :foreground ,blue-alt)))
-   `(font-latex-subscript-face ((,class :height 0.95)))
-   `(font-latex-superscript-face ((,class :height 0.95)))
-   `(font-latex-verbatim-face ((,class :background ,bg-dim :foreground 
,fg-special-mild)))
-   `(font-latex-warning-face ((,class :foreground ,yellow-alt-other)))
-   `(tex-match ((,class :foreground ,blue-alt-other)))
-   `(tex-verbatim ((,class :background ,bg-dim :foreground ,fg-special-mild)))
-   `(texinfo-heading ((,class :foreground ,magenta)))
-   `(TeX-error-description-error ((,class :inherit bold :foreground ,red)))
-   `(TeX-error-description-help ((,class :foreground ,blue)))
-   `(TeX-error-description-tex-said ((,class :foreground ,blue)))
-   `(TeX-error-description-warning ((,class :inherit bold :foreground 
,yellow)))
-;;;;; auto-dim-other-buffers
-   `(auto-dim-other-buffers-face ((,class :background ,bg-alt)))
-;;;;; avy
-   `(avy-background-face ((,class :background ,bg-dim :foreground ,fg-dim)))
-   `(avy-goto-char-timer-face ((,class :inherit (modus-theme-intense-yellow 
bold))))
-   `(avy-lead-face ((,class :inherit (modus-theme-intense-magenta bold))))
-   `(avy-lead-face-0 ((,class :inherit (modus-theme-intense-blue bold))))
-   `(avy-lead-face-1 ((,class :inherit (modus-theme-intense-red bold))))
-   `(avy-lead-face-2 ((,class :inherit (modus-theme-intense-green bold))))
-;;;;; aw (ace-window)
-   `(aw-background-face ((,class :background ,bg-dim :foreground ,fg-dim)))
-   `(aw-key-face ((,class :inherit bold :foreground ,blue-intense)))
-   `(aw-leading-char-face ((,class :inherit bold :height 1.5 :background 
,bg-main :foreground ,red-intense)))
-   `(aw-minibuffer-leading-char-face ((,class :foreground ,magenta-active)))
-   `(aw-mode-line-face ((,class :inherit bold)))
-;;;;; awesome-tray
-   `(awesome-tray-module-awesome-tab-face ((,class :inherit bold :foreground 
,red-alt-other)))
-   `(awesome-tray-module-battery-face ((,class :inherit bold :foreground 
,cyan-alt-other)))
-   `(awesome-tray-module-buffer-name-face ((,class :inherit bold :foreground 
,yellow-alt-other)))
-   `(awesome-tray-module-circe-face ((,class :inherit bold :foreground 
,blue-alt)))
-   `(awesome-tray-module-date-face ((,class :inherit bold :foreground 
,fg-dim)))
-   `(awesome-tray-module-evil-face ((,class :inherit bold :foreground 
,green-alt)))
-   `(awesome-tray-module-git-face ((,class :inherit bold :foreground 
,magenta)))
-   `(awesome-tray-module-last-command-face ((,class :inherit bold :foreground 
,blue-alt-other)))
-   `(awesome-tray-module-location-face ((,class :inherit bold :foreground 
,yellow)))
-   `(awesome-tray-module-mode-name-face ((,class :inherit bold :foreground 
,green)))
-   `(awesome-tray-module-parent-dir-face ((,class :inherit bold :foreground 
,cyan)))
-   `(awesome-tray-module-rvm-face ((,class :inherit bold :foreground 
,magenta-alt-other)))
-;;;;; binder
-   `(binder-sidebar-highlight ((,class :inherit modus-theme-subtle-cyan)))
-   `(binder-sidebar-marked ((,class :inherit modus-theme-mark-sel)))
-   `(binder-sidebar-missing ((,class :inherit modus-theme-subtle-red)))
-   `(binder-sidebar-tags ((,class :foreground ,cyan)))
-;;;;; bm
-   `(bm-face ((,class :inherit modus-theme-subtle-yellow
-                      ,@(and (>= emacs-major-version 27) '(:extend t)))))
-   `(bm-fringe-face ((,class :inherit modus-theme-fringe-yellow)))
-   `(bm-fringe-persistent-face ((,class :inherit modus-theme-fringe-blue)))
-   `(bm-persistent-face ((,class :inherit modus-theme-intense-blue
-                                 ,@(and (>= emacs-major-version 27) '(:extend 
t)))))
-;;;;; bongo
-   `(bongo-album-title ((,class :foreground ,cyan-active)))
-   `(bongo-artist ((,class :foreground ,magenta-active)))
-   `(bongo-currently-playing-track ((,class :inherit bold)))
-   `(bongo-elapsed-track-part ((,class :inherit modus-theme-subtle-magenta 
:underline t)))
-   `(bongo-filled-seek-bar ((,class :background ,blue-subtle-bg :foreground 
,fg-main)))
-   `(bongo-marked-track ((,class :foreground ,fg-mark-alt)))
-   `(bongo-marked-track-line ((,class :background ,bg-mark-alt)))
-   `(bongo-played-track ((,class :foreground ,fg-unfocused :strike-through t)))
-   `(bongo-track-length ((,class :foreground ,blue-alt-other)))
-   `(bongo-track-title ((,class :foreground ,blue-active)))
-   `(bongo-unfilled-seek-bar ((,class :background ,blue-nuanced-bg :foreground 
,fg-main)))
-;;;;; boon
-   `(boon-modeline-cmd ((,class :inherit modus-theme-active-blue)))
-   `(boon-modeline-ins ((,class :inherit modus-theme-active-red)))
-   `(boon-modeline-off ((,class :inherit modus-theme-active-yellow)))
-   `(boon-modeline-spc ((,class :inherit modus-theme-active-green)))
-;;;;; breakpoint (built-in gdb-mi.el)
-   `(breakpoint-disabled ((,class :foreground ,fg-alt)))
-   `(breakpoint-enabled ((,class :inherit bold :foreground ,red)))
-;;;;; buffer-expose
-   `(buffer-expose-ace-char-face ((,class :inherit bold :foreground 
,red-active)))
-   `(buffer-expose-mode-line-face ((,class :foreground ,cyan-active)))
-   `(buffer-expose-selected-face ((,class :inherit modus-theme-special-mild)))
-;;;;; calendar and diary
-   `(calendar-month-header ((,class :inherit bold :foreground ,fg-main)))
-   `(calendar-today ((,class :underline t)))
-   `(calendar-weekday-header ((,class :foreground ,fg-dim)))
-   `(calendar-weekend-header ((,class :foreground ,fg-alt)))
-   `(diary ((,class :foreground ,cyan-alt-other)))
-   `(diary-anniversary ((,class :foreground ,red-alt-other)))
-   `(diary-time ((,class :foreground ,blue-alt)))
-   `(holiday ((,class :foreground ,magenta-alt)))
-;;;;; calfw
-   `(cfw:face-annotation ((,class :foreground ,fg-special-warm)))
-   `(cfw:face-day-title ((,class :foreground ,fg-main)))
-   `(cfw:face-default-content ((,class :foreground ,green-alt)))
-   `(cfw:face-default-day ((,class :inherit (cfw:face-day-title bold))))
-   `(cfw:face-disable ((,class :foreground ,fg-unfocused)))
-   `(cfw:face-grid ((,class :foreground ,fg-window-divider-outer)))
-   `(cfw:face-header ((,class :inherit bold :foreground ,fg-main)))
-   `(cfw:face-holiday ((,class :foreground ,magenta-alt-other)))
-   `(cfw:face-periods ((,class :foreground ,cyan-alt-other)))
-   `(cfw:face-saturday ((,class :inherit bold :foreground ,cyan-alt-other)))
-   `(cfw:face-select ((,class :inherit modus-theme-intense-blue)))
-   `(cfw:face-sunday ((,class :inherit bold :foreground ,cyan-alt-other)))
-   `(cfw:face-title ((,class :inherit ,modus-theme-variable-pitch
-                             :foreground ,fg-special-cold
-                             ,@(modus-operandi-theme-scale 
modus-operandi-theme-scale-5))))
-   `(cfw:face-today ((,class :background ,bg-inactive)))
-   `(cfw:face-today-title ((,class :background ,bg-active)))
-   `(cfw:face-toolbar ((,class :background ,bg-alt :foreground ,bg-alt)))
-   `(cfw:face-toolbar-button-off ((,class :foreground ,fg-alt)))
-   `(cfw:face-toolbar-button-on ((,class :inherit bold :background 
,blue-nuanced-bg
-                                         :foreground ,blue-alt)))
-;;;;; centaur-tabs
-   `(centaur-tabs-active-bar-face ((,class :background ,fg-tab-active)))
-   `(centaur-tabs-close-mouse-face ((,class :inherit bold :foreground 
,red-active :underline t)))
-   `(centaur-tabs-close-selected ((,class :inherit centaur-tabs-selected)))
-   `(centaur-tabs-close-unselected ((,class :inherit centaur-tabs-unselected)))
-   `(centaur-tabs-modified-marker-selected ((,class :inherit 
centaur-tabs-selected)))
-   `(centaur-tabs-modified-marker-unselected ((,class :inherit 
centaur-tabs-unselected)))
-   `(centaur-tabs-default ((,class :background ,bg-main :foreground ,bg-main)))
-   `(centaur-tabs-selected ((,class :inherit bold :background ,bg-tab-active 
:foreground ,fg-main)))
-   `(centaur-tabs-selected-modified ((,class :background ,bg-tab-active 
:foreground ,fg-main :slant italic)))
-   `(centaur-tabs-unselected ((,class :background ,bg-tab-inactive :foreground 
,fg-dim)))
-   `(centaur-tabs-unselected-modified ((,class :background ,bg-tab-inactive 
:foreground ,fg-dim :slant italic)))
-;;;;; change-log and log-view (`vc-print-log' and `vc-print-root-log')
-   `(change-log-acknowledgment ((,class :foreground ,fg-alt)))
-   `(change-log-conditionals ((,class :foreground ,magenta-alt)))
-   `(change-log-date ((,class :foreground ,cyan-alt-other)))
-   `(change-log-email ((,class :foreground ,cyan)))
-   `(change-log-file ((,class :foreground ,blue)))
-   `(change-log-function ((,class :foreground ,green-alt-other)))
-   `(change-log-list ((,class :foreground ,magenta-alt-other)))
-   `(change-log-name ((,class :foreground ,cyan)))
-   `(log-edit-header ((,class :foreground ,fg-special-warm)))
-   `(log-edit-summary ((,class :inherit bold :foreground ,cyan)))
-   `(log-edit-unknown-header ((,class :foreground ,fg-alt)))
-   `(log-view-file ((,class :inherit bold :foreground ,fg-special-cold)))
-   `(log-view-message ((,class :foreground ,fg-alt)))
-;;;;; cider
-   `(cider-debug-code-overlay-face ((,class :background ,bg-alt)))
-   `(cider-debug-prompt-face ((,class :foreground ,magenta-alt :underline t)))
-   `(cider-deprecated-face ((,class :inherit modus-theme-refine-yellow)))
-   `(cider-docview-emphasis-face ((,class :foreground ,fg-special-cold :slant 
italic)))
-   `(cider-docview-literal-face ((,class :foreground ,blue-alt)))
-   `(cider-docview-strong-face ((,class :inherit bold :foreground 
,fg-special-cold)))
-   `(cider-docview-table-border-face ((,class :foreground ,fg-alt)))
-   `(cider-enlightened-face ((,class :box (:line-width -1 :color ,yellow-alt 
:style nil) :background ,bg-dim)))
-   `(cider-enlightened-local-face ((,class :inherit bold :foreground 
,yellow-alt-other)))
-   `(cider-error-highlight-face ((,class :foreground ,red :underline t)))
-   `(cider-fragile-button-face ((,class :box (:line-width 3 :color ,fg-alt 
:style released-button) :foreground ,yellow)))
-   `(cider-fringe-good-face ((,class :foreground ,green-active)))
-   `(cider-instrumented-face ((,class :box (:line-width -1 :color ,red :style 
nil) :background ,bg-dim)))
-   `(cider-reader-conditional-face ((,class :foreground ,fg-special-warm 
:slant italic)))
-   `(cider-repl-input-face ((,class :inherit bold)))
-   `(cider-repl-prompt-face ((,class :foreground ,cyan-alt-other)))
-   `(cider-repl-stderr-face ((,class :inherit bold :foreground ,red)))
-   `(cider-repl-stdout-face ((,class :foreground ,blue)))
-   `(cider-result-overlay-face ((,class :box (:line-width -1 :color ,blue 
:style nil) :background ,bg-dim)))
-   `(cider-stacktrace-error-class-face ((,class :inherit bold :foreground 
,red)))
-   `(cider-stacktrace-error-message-face ((,class :foreground ,red-alt-other 
:slant italic)))
-   `(cider-stacktrace-face ((,class :foreground ,fg-main)))
-   `(cider-stacktrace-filter-active-face ((,class :foreground ,cyan-alt 
:underline t)))
-   `(cider-stacktrace-filter-inactive-face ((,class :foreground ,cyan-alt)))
-   `(cider-stacktrace-fn-face ((,class :inherit bold :foreground ,fg-main)))
-   `(cider-stacktrace-ns-face ((,class :foreground ,fg-alt :slant italic)))
-   `(cider-stacktrace-promoted-button-face ((,class :box (:line-width 3 :color 
,fg-alt :style released-button) :foreground ,red)))
-   `(cider-stacktrace-suppressed-button-face ((,class :box (:line-width 3 
:color ,fg-alt :style pressed-button)
-                                                      :background ,bg-alt 
:foreground ,fg-alt)))
-   `(cider-test-error-face ((,class :inherit modus-theme-subtle-red)))
-   `(cider-test-failure-face ((,class :inherit (modus-theme-intense-red 
bold))))
-   `(cider-test-success-face ((,class :inherit modus-theme-intense-green)))
-   `(cider-traced-face ((,class :box (:line-width -1 :color ,cyan :style nil) 
:background ,bg-dim)))
-   `(cider-warning-highlight-face ((,class :foreground ,yellow :underline t)))
-;;;;; circe (and lui)
-   `(circe-fool-face ((,class :foreground ,fg-alt)))
-   `(circe-highlight-nick-face ((,class :inherit bold :foreground ,blue)))
-   `(circe-prompt-face ((,class :inherit bold :foreground ,cyan-alt-other)))
-   `(circe-server-face ((,class :foreground ,fg-unfocused)))
-   `(lui-button-face ((,class :inherit button :foreground ,blue)))
-   `(lui-highlight-face ((,class :foreground ,magenta-alt)))
-   `(lui-time-stamp-face ((,class :foreground ,blue-nuanced)))
-;;;;; color-rg
-   `(color-rg-font-lock-column-number ((,class :foreground 
,magenta-alt-other)))
-   `(color-rg-font-lock-command ((,class :inherit bold :foreground ,fg-main)))
-   `(color-rg-font-lock-file ((,class :inherit bold :foreground 
,fg-special-cold)))
-   `(color-rg-font-lock-flash ((,class :inherit modus-theme-intense-blue)))
-   `(color-rg-font-lock-function-location ((,class :inherit 
modus-theme-special-calm)))
-   `(color-rg-font-lock-header-line-directory ((,class :foreground 
,blue-active)))
-   `(color-rg-font-lock-header-line-edit-mode ((,class :foreground 
,magenta-active)))
-   `(color-rg-font-lock-header-line-keyword ((,class :foreground 
,green-active)))
-   `(color-rg-font-lock-header-line-text ((,class :foreground ,fg-active)))
-   `(color-rg-font-lock-line-number ((,class :foreground ,fg-special-warm)))
-   `(color-rg-font-lock-mark-changed ((,class :inherit bold :foreground 
,blue)))
-   `(color-rg-font-lock-mark-deleted ((,class :inherit bold :foreground ,red)))
-   `(color-rg-font-lock-match ((,class :inherit modus-theme-special-calm)))
-   `(color-rg-font-lock-position-splitter ((,class :foreground ,fg-alt)))
-;;;;; column-enforce-mode
-   `(column-enforce-face ((,class :inherit modus-theme-refine-yellow)))
-;;;;; company-mode
-   `(company-echo-common ((,class :foreground ,magenta-alt-other)))
-   `(company-preview ((,class :background ,bg-dim :foreground ,fg-dim)))
-   `(company-preview-common ((,class :foreground ,blue-alt)))
-   `(company-preview-search ((,class :inherit modus-theme-special-calm)))
-   `(company-scrollbar-bg ((,class :background ,bg-active)))
-   `(company-scrollbar-fg ((,class :background ,fg-active)))
-   `(company-template-field ((,class :inherit modus-theme-intense-magenta)))
-   `(company-tooltip ((,class :background ,bg-alt :foreground ,fg-alt)))
-   `(company-tooltip-annotation ((,class :foreground ,fg-special-cold :slant 
,modus-theme-slant)))
-   `(company-tooltip-annotation-selection ((,class :inherit bold :foreground 
,fg-main)))
-   `(company-tooltip-common ((,class :inherit bold :foreground ,blue-alt)))
-   `(company-tooltip-common-selection ((,class :foreground ,fg-main)))
-   `(company-tooltip-mouse ((,class :inherit modus-theme-intense-blue)))
-   `(company-tooltip-search ((,class :inherit (modus-theme-refine-cyan bold))))
-   `(company-tooltip-search-selection ((,class :inherit 
(modus-theme-intense-green bold) :underline t)))
-   `(company-tooltip-selection ((,class :inherit (modus-theme-subtle-cyan 
bold))))
-;;;;; company-posframe
-   `(company-posframe-active-backend-name ((,class :inherit bold :background 
,bg-active :foreground ,blue-active)))
-   `(company-posframe-inactive-backend-name ((,class :background ,bg-active 
:foreground ,fg-active)))
-   `(company-posframe-metadata ((,class :background ,bg-inactive :foreground 
,fg-inactive)))
-;;;;; compilation feedback
-   `(compilation-column-number ((,class :foreground ,magenta-alt-other)))
-   `(compilation-error ((,class ,@(modus-operandi-theme-bold-weight) 
:foreground ,red)))
-   `(compilation-info ((,class :foreground ,fg-special-cold)))
-   `(compilation-line-number ((,class :foreground ,fg-special-warm)))
-   `(compilation-mode-line-exit ((,class ,@(modus-operandi-theme-bold-weight) 
:foreground ,blue-active)))
-   `(compilation-mode-line-fail ((,class ,@(modus-operandi-theme-bold-weight) 
:foreground ,red-active)))
-   `(compilation-mode-line-run ((,class ,@(modus-operandi-theme-bold-weight) 
:foreground ,magenta-active)))
-   `(compilation-warning ((,class ,@(modus-operandi-theme-bold-weight) 
:foreground ,yellow)))
-;;;;; completions
-   `(completions-annotations ((,class :foreground ,fg-special-cold :slant 
,modus-theme-slant)))
-   `(completions-common-part ((,class 
,@(modus-operandi-theme-standard-completions
-                                         blue-alt blue-nuanced-bg
-                                         cyan-refine-bg cyan-refine-fg))))
-   `(completions-first-difference ((,class :inherit bold
-                                           
,@(modus-operandi-theme-standard-completions
-                                              magenta-alt blue-nuanced-bg
-                                              magenta-intense-bg fg-main))))
-;;;;; counsel
-   `(counsel-active-mode ((,class :foreground ,magenta-alt-other)))
-   `(counsel-application-name ((,class :foreground ,red-alt-other)))
-   `(counsel-key-binding ((,class :inherit bold :foreground ,blue-alt-other)))
-   `(counsel-outline-1 ((,class :inherit outline-1)))
-   `(counsel-outline-2 ((,class :inherit outline-2)))
-   `(counsel-outline-3 ((,class :inherit outline-3)))
-   `(counsel-outline-4 ((,class :inherit outline-4)))
-   `(counsel-outline-5 ((,class :inherit outline-5)))
-   `(counsel-outline-6 ((,class :inherit outline-6)))
-   `(counsel-outline-7 ((,class :inherit outline-7)))
-   `(counsel-outline-8 ((,class :inherit outline-8)))
-   `(counsel-outline-default ((,class :inherit bold :foreground 
,green-alt-other)))
-   `(counsel-variable-documentation ((,class :foreground ,yellow-alt-other 
:slant ,modus-theme-slant)))
-;;;;; counsel-css
-   `(counsel-css-selector-depth-face-1 ((,class :foreground ,blue)))
-   `(counsel-css-selector-depth-face-2 ((,class :foreground ,cyan)))
-   `(counsel-css-selector-depth-face-3 ((,class :foreground ,green)))
-   `(counsel-css-selector-depth-face-4 ((,class :foreground ,yellow)))
-   `(counsel-css-selector-depth-face-5 ((,class :foreground ,magenta)))
-   `(counsel-css-selector-depth-face-6 ((,class :foreground ,red)))
-;;;;; counsel-notmuch
-   `(counsel-notmuch-count-face ((,class :foreground ,cyan)))
-   `(counsel-notmuch-date-face ((,class :foreground ,blue)))
-   `(counsel-notmuch-people-face ((,class :foreground ,magenta)))
-   `(counsel-notmuch-subject-face ((,class :foreground ,magenta-alt-other)))
-;;;;; counsel-org-capture-string
-   `(counsel-org-capture-string-template-body-face ((,class :foreground 
,fg-special-cold)))
-;;;;; cov
-   `(cov-coverage-not-run-face ((,class :foreground ,red-intense)))
-   `(cov-coverage-run-face ((,class :foreground ,green-intense)))
-   `(cov-heavy-face ((,class :foreground ,magenta-intense)))
-   `(cov-light-face ((,class :foreground ,blue-intense)))
-   `(cov-med-face ((,class :foreground ,yellow-intense)))
-   `(cov-none-face ((,class :foreground ,cyan-intense)))
-;;;;; cperl-mode
-   `(cperl-nonoverridable-face ((,class :foreground ,yellow-alt-other)))
-   `(cperl-array-face ((,class :inherit bold :background ,bg-alt :foreground 
,magenta-alt)))
-   `(cperl-hash-face ((,class :inherit bold :background ,bg-alt :foreground 
,red-alt :slant ,modus-theme-slant)))
-;;;;; csv-mode
-   `(csv-separator-face ((,class :background ,bg-special-cold :foreground 
,fg-main)))
-;;;;; ctrlf
-   `(ctrlf-highlight-active ((,class :inherit (modus-theme-intense-green 
bold))))
-   `(ctrlf-highlight-line ((,class :inherit modus-theme-hl-line)))
-   `(ctrlf-highlight-passive ((,class :inherit modus-theme-refine-cyan)))
-;;;;; custom (M-x customize)
-   `(custom-button ((,class :box (:line-width 2 :color nil :style 
released-button)
-                            :background ,bg-active :foreground ,fg-main)))
-   `(custom-button-mouse ((,class :box (:line-width 2 :color nil :style 
released-button)
-                                  :background ,bg-active :foreground 
,fg-active)))
-   `(custom-button-pressed ((,class :box (:line-width 2 :color nil :style 
pressed-button)
-                                    :background ,bg-active :foreground 
,fg-main)))
-   `(custom-changed ((,class :inherit modus-theme-subtle-cyan)))
-   `(custom-comment ((,class :foreground ,fg-alt)))
-   `(custom-comment-tag ((,class :background ,bg-alt :foreground 
,yellow-alt-other)))
-   `(custom-face-tag ((,class :inherit bold :foreground ,blue-intense)))
-   `(custom-group-tag ((,class :inherit bold :foreground ,green-intense)))
-   `(custom-group-tag-1 ((,class :inherit modus-theme-special-warm)))
-   `(custom-invalid ((,class :inherit (modus-theme-intense-red bold))))
-   `(custom-modified ((,class :inherit modus-theme-subtle-cyan)))
-   `(custom-rogue ((,class :inherit modus-theme-refine-magenta)))
-   `(custom-set ((,class :foreground ,blue-alt)))
-   `(custom-state ((,class :foreground ,cyan-alt-other)))
-   `(custom-themed ((,class :inherit modus-theme-subtle-blue)))
-   `(custom-variable-tag ((,class :inherit bold :foreground ,cyan)))
-;;;;; dap-mode
-   `(dap-mouse-eval-thing-face ((,class :box (:line-width -1 :color 
,blue-active :style nil)
-                                        :background ,bg-active :foreground 
,fg-main)))
-   `(dap-result-overlay-face ((,class :box (:line-width -1 :color ,bg-active 
:style nil)
-                                      :background ,bg-active :foreground 
,fg-main)))
-   `(dap-ui-breakpoint-verified-fringe ((,class :inherit bold :foreground 
,green-active)))
-   `(dap-ui-compile-errline ((,class :inherit bold :foreground ,red-intense)))
-   `(dap-ui-locals-scope-face ((,class :inherit bold :foreground ,magenta 
:underline t)))
-   `(dap-ui-locals-variable-face ((,class :inherit bold :foreground ,cyan)))
-   `(dap-ui-locals-variable-leaf-face ((,class :foreground ,cyan-alt-other 
:slant italic)))
-   `(dap-ui-marker-face ((,class :inherit modus-theme-subtle-blue)))
-   `(dap-ui-sessions-stack-frame-face ((,class :inherit bold :foreground 
,magenta-alt)))
-   `(dap-ui-sessions-terminated-active-face ((,class :inherit bold :foreground 
,fg-alt)))
-   `(dap-ui-sessions-terminated-face ((,class :foreground ,fg-alt)))
-;;;;; dashboard (emacs-dashboard)
-   `(dashboard-banner-logo-title ((,class :inherit bold :foreground 
,fg-special-cold)))
-   `(dashboard-footer ((,class :inherit bold :foreground ,fg-special-mild)))
-   `(dashboard-heading ((,class :inherit bold :foreground ,fg-special-warm)))
-   `(dashboard-navigator ((,class :foreground ,cyan-alt-other)))
-   `(dashboard-text-banner ((,class :foreground ,fg-dim)))
-;;;;; deadgrep
-   `(deadgrep-filename-face ((,class :inherit bold :foreground 
,fg-special-cold)))
-   `(deadgrep-match-face ((,class :inherit modus-theme-special-calm)))
-   `(deadgrep-meta-face ((,class :foreground ,fg-alt)))
-   `(deadgrep-regexp-metachar-face ((,class :inherit bold :foreground 
,yellow-intense)))
-   `(deadgrep-search-term-face ((,class :inherit bold :foreground 
,green-intense)))
-;;;;; debbugs
-   `(debbugs-gnu-archived ((,class :inverse-video t)))
-   `(debbugs-gnu-done ((,class :foreground ,fg-alt)))
-   `(debbugs-gnu-forwarded ((,class :foreground ,fg-special-warm)))
-   `(debbugs-gnu-handled ((,class :foreground ,green)))
-   `(debbugs-gnu-new ((,class :foreground ,red)))
-   `(debbugs-gnu-pending ((,class :foreground ,cyan)))
-   `(debbugs-gnu-stale-1 ((,class :foreground ,yellow-nuanced)))
-   `(debbugs-gnu-stale-2 ((,class :foreground ,yellow)))
-   `(debbugs-gnu-stale-3 ((,class :foreground ,yellow-alt)))
-   `(debbugs-gnu-stale-4 ((,class :foreground ,yellow-alt-other)))
-   `(debbugs-gnu-stale-5 ((,class :foreground ,red-alt)))
-   `(debbugs-gnu-tagged ((,class :foreground ,magenta-alt)))
-;;;;; define-word
-   `(define-word-face-1 ((,class :foreground ,yellow)))
-   `(define-word-face-2 ((,class :foreground ,fg-main)))
-;;;;; deft
-   `(deft-filter-string-error-face ((,class :inherit modus-theme-refine-red)))
-   `(deft-filter-string-face ((,class :foreground ,green-intense)))
-   `(deft-header-face ((,class :inherit bold :foreground ,fg-special-warm)))
-   `(deft-separator-face ((,class :foreground ,fg-alt)))
-   `(deft-summary-face ((,class :foreground ,fg-alt :slant 
,modus-theme-slant)))
-   `(deft-time-face ((,class :foreground ,fg-special-cold)))
-   `(deft-title-face ((,class :inherit bold :foreground ,fg-main)))
-;;;;; dictionary
-   `(dictionary-button-face ((,class :inherit bold :foreground 
,fg-special-cold)))
-   `(dictionary-reference-face ((,class :inherit :foreground ,blue-alt-other)))
-   `(dictionary-word-definition-face ((,class :foreground ,fg-main)))
-   `(dictionary-word-entry-face ((,class :foreground ,fg-special-cold :slant 
,modus-theme-slant)))
-;;;;; diff-hl
-   `(diff-hl-change ((,class :inherit modus-theme-fringe-yellow)))
-   `(diff-hl-delete ((,class :inherit modus-theme-fringe-red)))
-   `(diff-hl-dired-change ((,class :inherit diff-hl-change)))
-   `(diff-hl-dired-delete ((,class :inherit diff-hl-delete)))
-   `(diff-hl-dired-ignored ((,class :inherit dired-ignored)))
-   `(diff-hl-dired-insert ((,class :inherit diff-hl-insert)))
-   `(diff-hl-dired-unknown ((,class :inherit dired-ignored)))
-   `(diff-hl-insert ((,class :inherit modus-theme-fringe-green)))
-   `(diff-hl-reverted-hunk-highlight ((,class :inherit 
(modus-theme-active-magenta bold))))
-;;;;; diff-mode
-   `(diff-added ((,class :inherit modus-theme-diff-added)))
-   `(diff-changed ((,class :inherit modus-theme-diff-changed)))
-   `(diff-context ((,class :foreground ,fg-unfocused)))
-   `(diff-file-header ((,class :inherit bold :foreground ,blue)))
-   `(diff-function ((,class :foreground ,fg-special-cold)))
-   `(diff-header ((,class :foreground ,blue-nuanced)))
-   `(diff-hunk-header ((,class :inherit modus-theme-diff-heading)))
-   `(diff-index ((,class :inherit bold :foreground ,blue-alt)))
-   `(diff-indicator-added ((,class :inherit diff-added)))
-   `(diff-indicator-changed ((,class :inherit diff-changed)))
-   `(diff-indicator-removed ((,class :inherit diff-removed)))
-   `(diff-nonexistent ((,class :inherit (modus-theme-neutral bold))))
-   `(diff-refine-added ((,class :inherit modus-theme-diff-refine-added)))
-   `(diff-refine-changed ((,class :inherit modus-theme-diff-refine-changed)))
-   `(diff-refine-removed ((,class :inherit modus-theme-diff-refine-removed)))
-   `(diff-removed ((,class :inherit modus-theme-diff-removed)))
-;;;;; dim-autoload
-   `(dim-autoload-cookie-line ((,class :foreground ,fg-alt :slant 
,modus-theme-slant)))
-;;;;; dir-treeview
-   `(dir-treeview-archive-face ((,class :foreground ,fg-special-warm)))
-   `(dir-treeview-archive-icon-face ((,class :inherit 
dir-treeview-default-icon-face :foreground ,yellow)))
-   `(dir-treeview-audio-face ((,class :foreground ,magenta)))
-   `(dir-treeview-audio-icon-face ((,class :inherit 
dir-treeview-default-icon-face :foreground ,magenta-alt)))
-   `(dir-treeview-control-face ((,class :foreground ,fg-alt)))
-   `(dir-treeview-control-mouse-face ((,class :inherit highlight)))
-   `(dir-treeview-default-icon-face ((,class :inherit bold :family "Font 
Awesome" :foreground ,fg-alt)))
-   `(dir-treeview-default-filename-face ((,class :foreground ,fg-main)))
-   `(dir-treeview-directory-face ((,class :foreground ,blue)))
-   `(dir-treeview-directory-icon-face ((,class :inherit 
dir-treeview-default-icon-face :foreground ,blue-alt)))
-   `(dir-treeview-executable-face ((,class :foreground ,red-alt)))
-   `(dir-treeview-executable-icon-face ((,class :inherit 
dir-treeview-default-icon-face :foreground ,red-alt-other)))
-   `(dir-treeview-image-face ((,class :foreground ,green-alt-other)))
-   `(dir-treeview-image-icon-face ((,class :inherit 
dir-treeview-default-icon-face :foreground ,green-alt)))
-   `(dir-treeview-indent-face ((,class :foreground ,fg-alt)))
-   `(dir-treeview-label-mouse-face ((,class :inherit highlight)))
-   `(dir-treeview-start-dir-face ((,class :inherit modus-theme-pseudo-header)))
-   `(dir-treeview-symlink-face ((,class :inherit button :foreground ,cyan)))
-   `(dir-treeview-video-face ((,class :foreground ,magenta-alt-other)))
-   `(dir-treeview-video-icon-face ((,class :inherit 
dir-treeview-default-icon-face :foreground ,magenta-alt-other)))
-;;;;; dired
-   `(dired-directory ((,class :foreground ,blue)))
-   `(dired-flagged ((,class :inherit modus-theme-mark-del)))
-   `(dired-header ((,class :inherit modus-theme-pseudo-header)))
-   `(dired-ignored ((,class :foreground ,fg-alt)))
-   `(dired-mark ((,class :inherit modus-theme-mark-symbol)))
-   `(dired-marked ((,class :inherit modus-theme-mark-sel)))
-   `(dired-perm-write ((,class :foreground ,fg-special-warm)))
-   `(dired-symlink ((,class :inherit button :foreground ,cyan-alt)))
-   `(dired-warning ((,class :inherit bold :foreground ,yellow)))
-;;;;; dired-async
-   `(dired-async-failures ((,class ,@(modus-operandi-theme-bold-weight) 
:foreground ,red-active)))
-   `(dired-async-message ((,class ,@(modus-operandi-theme-bold-weight) 
:foreground ,green-active)))
-   `(dired-async-mode-message ((,class ,@(modus-operandi-theme-bold-weight) 
:foreground ,cyan-active)))
-;;;;; dired-git
-   `(dired-git-branch-else ((,class :inherit bold :foreground ,magenta-alt)))
-   `(dired-git-branch-master ((,class :inherit bold :foreground 
,magenta-alt-other)))
-;;;;; dired-git-info
-   `(dgi-commit-message-face ((,class :foreground ,fg-special-mild)))
-;;;;; dired-narrow
-   `(dired-narrow-blink ((,class :inherit (modus-theme-subtle-cyan bold))))
-;;;;; dired-subtree
-   ;; remove background from dired-subtree, else it breaks
-   ;; dired-{flagged,marked} and any other face that sets a background
-   ;; such as hl-line
-   `(dired-subtree-depth-1-face ((,class :background nil)))
-   `(dired-subtree-depth-2-face ((,class :background nil)))
-   `(dired-subtree-depth-3-face ((,class :background nil)))
-   `(dired-subtree-depth-4-face ((,class :background nil)))
-   `(dired-subtree-depth-5-face ((,class :background nil)))
-   `(dired-subtree-depth-6-face ((,class :background nil)))
-;;;;; diredfl
-   `(diredfl-autofile-name ((,class :inherit modus-theme-special-cold)))
-   `(diredfl-compressed-file-name ((,class :foreground ,fg-special-warm)))
-   `(diredfl-compressed-file-suffix ((,class :foreground ,red-alt)))
-   `(diredfl-date-time ((,class :foreground ,cyan-alt-other)))
-   `(diredfl-deletion ((,class :inherit modus-theme-mark-del)))
-   `(diredfl-deletion-file-name ((,class :inherit modus-theme-mark-del)))
-   `(diredfl-dir-heading ((,class :inherit modus-theme-pseudo-header)))
-   `(diredfl-dir-name ((,class :inherit dired-directory)))
-   `(diredfl-dir-priv ((,class :foreground ,blue-alt)))
-   `(diredfl-exec-priv ((,class :foreground ,magenta)))
-   `(diredfl-executable-tag ((,class :foreground ,magenta-alt)))
-   `(diredfl-file-name ((,class :foreground ,fg-main)))
-   `(diredfl-file-suffix ((,class :foreground ,cyan)))
-   `(diredfl-flag-mark ((,class :inherit modus-theme-mark-sel)))
-   `(diredfl-flag-mark-line ((,class :inherit modus-theme-mark-sel)))
-   `(diredfl-ignored-file-name ((,class :foreground ,fg-alt)))
-   `(diredfl-link-priv ((,class :foreground ,blue-alt-other)))
-   `(diredfl-no-priv ((,class :foreground ,fg-alt)))
-   `(diredfl-number ((,class :foreground ,cyan-alt)))
-   `(diredfl-other-priv ((,class :foreground ,yellow)))
-   `(diredfl-rare-priv ((,class :foreground ,red-alt)))
-   `(diredfl-read-priv ((,class :foreground ,fg-main)))
-   `(diredfl-symlink ((,class :inherit dired-symlink)))
-   `(diredfl-tagged-autofile-name ((,class :inherit 
modus-theme-refine-magenta)))
-   `(diredfl-write-priv ((,class :foreground ,cyan)))
-;;;;; disk-usage
-   `(disk-usage-children ((,class :foreground ,yellow)))
-   `(disk-usage-inaccessible ((,class :inherit bold :foreground ,red)))
-   `(disk-usage-percent ((,class :foreground ,green)))
-   `(disk-usage-size ((,class :foreground ,cyan)))
-   `(disk-usage-symlink ((,class :inherit button :foreground ,blue)))
-   `(disk-usage-symlink-directory ((,class :inherit bold :foreground 
,blue-alt)))
-;;;;; doom-modeline
-   `(doom-modeline-bar ((,class :inherit modus-theme-active-blue)))
-   `(doom-modeline-bar-inactive ((,class :background ,fg-inactive :foreground 
,bg-main)))
-   `(doom-modeline-battery-charging ((,class :foreground ,green-active)))
-   `(doom-modeline-battery-critical ((,class :inherit bold :foreground 
,red-active)))
-   `(doom-modeline-battery-error ((,class :inherit bold :box (:line-width -2)
-                                          :foreground ,red-active)))
-   `(doom-modeline-battery-full ((,class :foreground ,blue-active)))
-   `(doom-modeline-battery-normal ((,class :foreground ,fg-active)))
-   `(doom-modeline-battery-warning ((,class :inherit bold :foreground 
,yellow-active)))
-   `(doom-modeline-buffer-file ((,class :inherit bold :foreground ,fg-active)))
-   `(doom-modeline-buffer-major-mode ((,class :inherit bold :foreground 
,cyan-active)))
-   `(doom-modeline-buffer-minor-mode ((,class :foreground ,fg-inactive)))
-   `(doom-modeline-buffer-modified ((,class :inherit bold :foreground 
,magenta-active)))
-   `(doom-modeline-buffer-path ((,class :inherit bold :foreground ,fg-active)))
-   `(doom-modeline-debug ((,class :inherit bold :foreground ,yellow-active)))
-   `(doom-modeline-debug-visual ((,class :inherit bold :foreground 
,red-active)))
-   `(doom-modeline-evil-emacs-state ((,class :inherit bold :foreground 
,magenta-active)))
-   `(doom-modeline-evil-insert-state ((,class :inherit bold :foreground 
,green-active)))
-   `(doom-modeline-evil-motion-state ((,class :inherit bold :foreground 
,fg-inactive)))
-   `(doom-modeline-evil-normal-state ((,class :inherit bold :foreground 
,fg-active)))
-   `(doom-modeline-evil-operator-state ((,class :inherit bold :foreground 
,blue-active)))
-   `(doom-modeline-evil-replace-state ((,class :inherit bold :foreground 
,red-active)))
-   `(doom-modeline-evil-visual-state ((,class :inherit bold :foreground 
,cyan-active)))
-   `(doom-modeline-highlight ((,class :inherit bold :foreground ,blue-active)))
-   `(doom-modeline-host ((,class :slant italic)))
-   `(doom-modeline-info ((,class :foreground ,green-active)))
-   `(doom-modeline-lsp-error ((,class :inherit bold :foreground ,red-active)))
-   `(doom-modeline-lsp-success ((,class :inherit bold :foreground 
,green-active)))
-   `(doom-modeline-lsp-warning ((,class :inherit bold :foreground 
,yellow-active)))
-   `(doom-modeline-panel ((,class :inherit modus-theme-active-blue)))
-   `(doom-modeline-persp-buffer-not-in-persp ((,class :foreground 
,yellow-active :slant italic)))
-   `(doom-modeline-persp-name ((,class :foreground ,fg-active)))
-   `(doom-modeline-project-dir ((,class :inherit bold :foreground 
,blue-active)))
-   `(doom-modeline-project-parent-dir ((,class :foreground ,blue-active)))
-   `(doom-modeline-project-root-dir ((,class :foreground ,fg-active)))
-   `(doom-modeline-unread-number ((,class :foreground ,fg-active :slant 
italic)))
-   `(doom-modeline-urgent ((,class :inherit bold :foreground ,red-active)))
-   `(doom-modeline-warning ((,class :inherit bold :foreground ,yellow-active)))
-;;;;; dynamic-ruler
-   `(dynamic-ruler-negative-face ((,class :inherit 
modus-theme-intense-neutral)))
-   `(dynamic-ruler-positive-face ((,class :inherit 
modus-theme-intense-yellow)))
-;;;;; easy-jekyll
-   `(easy-jekyll-help-face ((,class :background ,bg-dim :foreground 
,cyan-alt-other)))
-;;;;; easy-kill
-   `(easy-kill-origin ((,class :inherit modus-theme-subtle-red)))
-   `(easy-kill-selection ((,class :inherit modus-theme-subtle-yellow)))
-;;;;; ebdb
-   `(ebdb-address-default ((,class :foreground ,fg-main)))
-   `(ebdb-db-char ((,class :foreground ,fg-special-cold)))
-   `(ebdb-defunct ((,class :foreground ,fg-alt)))
-   `(ebdb-field-hidden ((,class :foreground ,magenta)))
-   `(ebdb-field-url ((,class :foreground ,blue)))
-   `(ebdb-label ((,class :foreground ,cyan-alt-other)))
-   `(ebdb-mail-default ((,class :foreground ,fg-main)))
-   `(ebdb-mail-primary ((,class :foreground ,blue-alt)))
-   `(ebdb-marked ((,class :background ,cyan-intense-bg)))
-   `(ebdb-organization-name ((,class :foreground ,fg-special-calm)))
-   `(ebdb-person-name ((,class :foreground ,magenta-alt-other)))
-   `(ebdb-phone-default ((,class :foreground ,fg-special-warm)))
-   `(ebdb-role-defunct ((,class :foreground ,fg-alt)))
-   `(eieio-custom-slot-tag-face ((,class :foreground ,red-alt)))
-;;;;; ediff
-   ;; NOTE: here we break from the pattern of inheriting from the
-   ;; modus-theme-diff-* faces.
-   `(ediff-current-diff-A ((,class ,@(modus-operandi-theme-diff
-                                      bg-dim red
-                                      bg-diff-removed fg-diff-removed
-                                      red-nuanced-bg red-faint))))
-   `(ediff-current-diff-Ancestor ((,class ,@(modus-operandi-theme-diff
-                                             bg-dim fg-special-cold
-                                             bg-special-cold fg-special-cold
-                                             blue-nuanced-bg blue))))
-   `(ediff-current-diff-B ((,class ,@(modus-operandi-theme-diff
-                                      bg-dim green
-                                      bg-diff-added fg-diff-added
-                                      green-nuanced-bg green-faint))))
-   `(ediff-current-diff-C ((,class ,@(modus-operandi-theme-diff
-                                      bg-dim yellow
-                                      bg-diff-changed fg-diff-changed
-                                      yellow-nuanced-bg yellow-faint))))
-   `(ediff-even-diff-A ((,class :background ,bg-diff-neutral-1 :foreground 
,fg-diff-neutral-1)))
-   `(ediff-even-diff-Ancestor ((,class :background ,bg-diff-neutral-2 
:foreground ,fg-diff-neutral-1)))
-   `(ediff-even-diff-B ((,class :background ,bg-diff-neutral-1 :foreground 
,fg-diff-neutral-1)))
-   `(ediff-even-diff-C ((,class :background ,bg-diff-neutral-2 :foreground 
,fg-diff-neutral-2)))
-   `(ediff-fine-diff-A ((,class :background ,bg-diff-focus-removed :foreground 
,fg-diff-focus-removed)))
-   `(ediff-fine-diff-Ancestor ((,class :inherit modus-theme-refine-cyan)))
-   `(ediff-fine-diff-B ((,class :background ,bg-diff-focus-added :foreground 
,fg-diff-focus-added)))
-   `(ediff-fine-diff-C ((,class :background ,bg-diff-focus-changed :foreground 
,fg-diff-focus-changed)))
-   `(ediff-odd-diff-A ((,class :background ,bg-diff-neutral-2 :foreground 
,fg-diff-neutral-2)))
-   `(ediff-odd-diff-Ancestor ((,class :background ,bg-diff-neutral-0 
:foreground ,fg-diff-neutral-0)))
-   `(ediff-odd-diff-B ((,class :background ,bg-diff-neutral-2 :foreground 
,fg-diff-neutral-2)))
-   `(ediff-odd-diff-C ((,class :background ,bg-diff-neutral-1 :foreground 
,fg-diff-neutral-1)))
-;;;;; eglot
-   `(eglot-mode-line ((,class ,@(modus-operandi-theme-bold-weight) :foreground 
,magenta-active)))
-;;;;; el-search
-   `(el-search-highlight-in-prompt-face ((,class :inherit bold :foreground 
,magenta-alt)))
-   `(el-search-match ((,class :inherit modus-theme-intense-green)))
-   `(el-search-other-match ((,class :inherit modus-theme-special-mild)))
-   `(el-search-occur-match ((,class :inherit modus-theme-special-calm)))
-;;;;; eldoc
-   ;; NOTE: see https://github.com/purcell/package-lint/issues/187
-   (list 'eldoc-highlight-function-argument `((,class :inherit bold 
:foreground ,blue-alt-other)))
-;;;;; eldoc-box
-   `(eldoc-box-body ((,class :background ,bg-alt :foreground ,fg-main)))
-   `(eldoc-box-border ((,class :background ,fg-alt)))
-;;;;; elfeed
-   `(elfeed-log-date-face ((,class :foreground ,cyan-alt)))
-   `(elfeed-log-debug-level-face ((,class :foreground ,magenta)))
-   `(elfeed-log-error-level-face ((,class :foreground ,red)))
-   `(elfeed-log-info-level-face ((,class :foreground ,green)))
-   `(elfeed-log-warn-level-face ((,class :foreground ,yellow)))
-   `(elfeed-search-date-face ((,class :foreground ,blue-nuanced)))
-   `(elfeed-search-feed-face ((,class :foreground ,cyan)))
-   `(elfeed-search-filter-face ((,class :inherit bold :foreground 
,magenta-active)))
-   `(elfeed-search-last-update-face ((,class :foreground ,cyan-active)))
-   `(elfeed-search-tag-face ((,class :foreground ,blue-nuanced)))
-   `(elfeed-search-title-face ((,class :foreground ,fg-dim)))
-   `(elfeed-search-unread-count-face ((,class :foreground ,green-active)))
-   `(elfeed-search-unread-title-face ((,class :inherit bold :foreground 
,fg-main)))
-;;;;; elfeed-score
-   `(elfeed-score-date-face ((,class :foreground ,blue)))
-   `(elfeed-score-debug-level-face ((,class :foreground ,magenta-alt-other)))
-   `(elfeed-score-error-level-face ((,class :foreground ,red)))
-   `(elfeed-score-info-level-face ((,class :foreground ,cyan)))
-   `(elfeed-score-warn-level-face ((,class :foreground ,yellow)))
-;;;;; emms
-   `(emms-playlist-track-face ((,class :foreground ,blue)))
-   `(emms-playlist-selected-face ((,class :inherit bold :foreground ,magenta)))
-;;;;; enhanced-ruby-mode
-   `(enh-ruby-heredoc-delimiter-face ((,class :foreground ,blue-alt-other)))
-   `(enh-ruby-op-face ((,class :foreground ,fg-main)))
-   `(enh-ruby-regexp-delimiter-face ((,class :foreground ,green)))
-   `(enh-ruby-regexp-face ((,class :foreground ,magenta)))
-   `(enh-ruby-string-delimiter-face ((,class :foreground ,blue-alt)))
-   `(erm-syn-errline ((,class :foreground ,red :underline t)))
-   `(erm-syn-warnline ((,class :foreground ,yellow :underline t)))
-;;;;; epa
-   `(epa-field-body ((,class :foreground ,fg-main)))
-   `(epa-field-name ((,class :inherit bold :foreground ,fg-dim)))
-   `(epa-mark ((,class :inherit bold :foreground ,magenta)))
-   `(epa-string ((,class :foreground ,blue-alt)))
-   `(epa-validity-disabled ((,class :inherit modus-theme-refine-red)))
-   `(epa-validity-high ((,class :inherit bold :foreground ,green-alt-other)))
-   `(epa-validity-low ((,class :foreground ,fg-alt)))
-   `(epa-validity-medium ((,class :foreground ,green-alt)))
-;;;;; equake
-   `(equake-buffer-face ((,class :background ,bg-main :foreground ,fg-main)))
-   `(equake-shell-type-eshell ((,class :background ,bg-inactive :foreground 
,green-active)))
-   `(equake-shell-type-rash ((,class :background ,bg-inactive :foreground 
,red-active)))
-   `(equake-shell-type-shell ((,class :background ,bg-inactive :foreground 
,cyan-active)))
-   `(equake-shell-type-term ((,class :background ,bg-inactive :foreground 
,yellow-active)))
-   `(equake-shell-type-vterm ((,class :background ,bg-inactive :foreground 
,magenta-active)))
-   `(equake-tab-active ((,class :background ,fg-alt :foreground ,bg-alt)))
-   `(equake-tab-inactive ((,class :foreground ,fg-inactive)))
-;;;;; erc
-   `(erc-action-face ((,class :inherit bold :foreground ,cyan)))
-   `(erc-bold-face ((,class :inherit bold)))
-   `(erc-button ((,class :inherit button)))
-   `(erc-command-indicator-face ((,class :inherit bold :foreground ,cyan-alt)))
-   `(erc-current-nick-face ((,class :foreground ,magenta-alt-other)))
-   `(erc-dangerous-host-face ((,class :inherit modus-theme-intense-red)))
-   `(erc-direct-msg-face ((,class :foreground ,magenta)))
-   `(erc-error-face ((,class :inherit bold :foreground ,red)))
-   `(erc-fool-face ((,class :foreground ,fg-inactive)))
-   `(erc-header-line ((,class :background ,bg-header :foreground ,fg-header)))
-   `(erc-input-face ((,class :foreground ,fg-special-calm)))
-   `(erc-inverse-face ((,class :inherit erc-default-face :inverse-video t)))
-   `(erc-keyword-face ((,class :inherit bold :foreground ,magenta-alt)))
-   `(erc-my-nick-face ((,class :inherit bold :foreground ,magenta)))
-   `(erc-my-nick-prefix-face ((,class :inherit erc-my-nick-face)))
-   `(erc-nick-default-face ((,class :inherit bold :foreground ,blue)))
-   `(erc-nick-msg-face ((,class :inherit bold :foreground ,green)))
-   `(erc-nick-prefix-face ((,class :inherit erc-nick-default-face)))
-   `(erc-notice-face ((,class :foreground ,fg-unfocused)))
-   `(erc-pal-face ((,class :inherit bold :foreground ,red-alt)))
-   `(erc-prompt-face ((,class :inherit bold :foreground ,cyan-alt-other)))
-   `(erc-timestamp-face ((,class :foreground ,blue-nuanced)))
-   `(erc-underline-face ((,class :underline t)))
-   `(bg:erc-color-face0 ((,class :background "white")))
-   `(bg:erc-color-face1 ((,class :background "black")))
-   `(bg:erc-color-face10 ((,class :background ,cyan-subtle-bg)))
-   `(bg:erc-color-face11 ((,class :background ,cyan-intense-bg)))
-   `(bg:erc-color-face12 ((,class :background ,blue-subtle-bg)))
-   `(bg:erc-color-face13 ((,class :background ,magenta-subtle-bg)))
-   `(bg:erc-color-face14 ((,class :background "gray60")))
-   `(bg:erc-color-face15 ((,class :background "gray80")))
-   `(bg:erc-color-face2 ((,class :background ,blue-intense-bg)))
-   `(bg:erc-color-face3 ((,class :background ,green-intense-bg)))
-   `(bg:erc-color-face4 ((,class :background ,red-subtle-bg)))
-   `(bg:erc-color-face5 ((,class :background ,red-intense-bg)))
-   `(bg:erc-color-face6 ((,class :background ,magenta-refine-bg)))
-   `(bg:erc-color-face7 ((,class :background ,yellow-subtle-bg)))
-   `(bg:erc-color-face8 ((,class :background ,yellow-refine-bg)))
-   `(bg:erc-color-face9 ((,class :background ,green-subtle-bg)))
-   `(fg:erc-color-face0 ((,class :foreground "white")))
-   `(fg:erc-color-face1 ((,class :foreground "black")))
-   `(fg:erc-color-face10 ((,class :foreground ,cyan)))
-   `(fg:erc-color-face11 ((,class :foreground ,cyan-alt-other)))
-   `(fg:erc-color-face12 ((,class :foreground ,blue)))
-   `(fg:erc-color-face13 ((,class :foreground ,magenta-alt)))
-   `(fg:erc-color-face14 ((,class :foreground "gray60")))
-   `(fg:erc-color-face15 ((,class :foreground "gray80")))
-   `(fg:erc-color-face2 ((,class :foreground ,blue-alt-other)))
-   `(fg:erc-color-face3 ((,class :foreground ,green)))
-   `(fg:erc-color-face4 ((,class :foreground ,red)))
-   `(fg:erc-color-face5 ((,class :foreground ,red-alt)))
-   `(fg:erc-color-face6 ((,class :foreground ,magenta-alt-other)))
-   `(fg:erc-color-face7 ((,class :foreground ,yellow-alt-other)))
-   `(fg:erc-color-face8 ((,class :foreground ,yellow-alt)))
-   `(fg:erc-color-face9 ((,class :foreground ,green-alt-other)))
-;;;;; eros
-   `(eros-result-overlay-face ((,class :box (:line-width -1 :color ,blue)
-                                       :background ,bg-dim :foreground 
,fg-dim)))
-;;;;; ert
-   `(ert-test-result-expected ((,class :inherit modus-theme-intense-green)))
-   `(ert-test-result-unexpected ((,class :inherit modus-theme-intense-red)))
-;;;;; eshell
-   `(eshell-ls-archive ((,class :inherit bold :foreground ,cyan-alt)))
-   `(eshell-ls-backup ((,class :foreground ,yellow-alt)))
-   `(eshell-ls-clutter ((,class :foreground ,red-alt)))
-   `(eshell-ls-directory ((,class :inherit bold :foreground ,blue-alt)))
-   `(eshell-ls-executable ((,class :foreground ,magenta-alt)))
-   `(eshell-ls-missing ((,class :inherit modus-theme-intense-red)))
-   `(eshell-ls-product ((,class :foreground ,fg-special-warm)))
-   `(eshell-ls-readonly ((,class :foreground ,fg-special-cold)))
-   `(eshell-ls-special ((,class :inherit bold :foreground ,magenta)))
-   `(eshell-ls-symlink ((,class :inherit button :foreground ,cyan)))
-   `(eshell-ls-unreadable ((,class :background ,bg-inactive :foreground 
,fg-inactive)))
-   `(eshell-prompt ((,class ,@(modus-operandi-theme-bold-weight)
-                            ,@(modus-operandi-theme-prompt
-                               green-alt-other
-                               green-nuanced-bg green-alt
-                               green-refine-bg fg-main))))
-;;;;; eshell-fringe-status
-   `(eshell-fringe-status-failure ((,class :foreground ,red)))
-   `(eshell-fringe-status-success ((,class :foreground ,green)))
-;;;;; eshell-git-prompt
-   `(eshell-git-prompt-add-face ((,class :foreground ,fg-alt)))
-   `(eshell-git-prompt-branch-face ((,class :foreground ,fg-alt)))
-   `(eshell-git-prompt-directory-face ((,class :foreground ,cyan)))
-   `(eshell-git-prompt-exit-fail-face ((,class :foreground ,red)))
-   `(eshell-git-prompt-exit-success-face ((,class :foreground ,green)))
-   `(eshell-git-prompt-modified-face ((,class :foreground ,yellow)))
-   `(eshell-git-prompt-powerline-clean-face ((,class :background 
,green-refine-bg)))
-   `(eshell-git-prompt-powerline-dir-face ((,class :background 
,blue-refine-bg)))
-   `(eshell-git-prompt-powerline-not-clean-face ((,class :background 
,magenta-refine-bg)))
-   `(eshell-git-prompt-robyrussell-branch-face ((,class :foreground ,red)))
-   `(eshell-git-prompt-robyrussell-git-dirty-face ((,class :foreground 
,yellow)))
-   `(eshell-git-prompt-robyrussell-git-face ((,class :foreground ,blue)))
-;;;;; eshell-prompt-extras (epe)
-   `(epe-dir-face ((,class ,@(modus-operandi-theme-bold-weight) :foreground 
,blue)))
-   `(epe-git-dir-face ((,class :foreground ,red-alt-other)))
-   `(epe-git-face ((,class :foreground ,cyan-alt)))
-   `(epe-pipeline-delimiter-face ((,class :foreground ,green-alt)))
-   `(epe-pipeline-host-face ((,class :foreground ,blue)))
-   `(epe-pipeline-time-face ((,class :foreground ,fg-special-warm)))
-   `(epe-pipeline-user-face ((,class :foreground ,magenta)))
-   `(epe-remote-face ((,class :foreground ,fg-alt :slant ,modus-theme-slant)))
-   `(epe-status-face ((,class :foreground ,magenta-alt-other)))
-   `(epe-venv-face ((,class :foreground ,fg-alt :slant ,modus-theme-slant)))
-;;;;; eshell-syntax-highlighting
-   `(eshell-syntax-highlighting-alias-face ((,class :foreground ,cyan)))
-   `(eshell-syntax-highlighting-comment-face ((,class :foreground ,fg-alt)))
-   `(eshell-syntax-highlighting-directory-face ((,class :foreground ,blue)))
-   `(eshell-syntax-highlighting-envvar-face ((,class :foreground 
,magenta-alt)))
-   `(eshell-syntax-highlighting-invalid-face ((,class :foreground ,red)))
-   `(eshell-syntax-highlighting-lisp-function-face ((,class :foreground 
,magenta)))
-   `(eshell-syntax-highlighting-shell-command-face ((,class :foreground 
,cyan-alt-other)))
-   `(eshell-syntax-highlighting-string-face ((,class :foreground ,blue-alt)))
-;;;;; evil-mode
-   `(evil-ex-commands ((,class :foreground ,magenta-alt-other)))
-   `(evil-ex-info ((,class :foreground ,cyan-alt-other)))
-   `(evil-ex-lazy-highlight ((,class :inherit modus-theme-refine-cyan)))
-   `(evil-ex-search ((,class :inherit modus-theme-intense-green)))
-   `(evil-ex-substitute-matches ((,class :inherit modus-theme-refine-yellow 
:underline t)))
-   `(evil-ex-substitute-replacement ((,class :inherit 
(modus-theme-intense-green bold))))
-;;;;; evil-goggles
-   `(evil-goggles-change-face ((,class :inherit modus-theme-refine-yellow)))
-   `(evil-goggles-commentary-face ((,class :inherit modus-theme-subtle-neutral 
:slant ,modus-theme-slant)))
-   `(evil-goggles-default-face ((,class :inherit modus-theme-subtle-neutral)))
-   `(evil-goggles-delete-face ((,class :inherit modus-theme-refine-red)))
-   `(evil-goggles-fill-and-move-face ((,class :inherit 
evil-goggles-default-face)))
-   `(evil-goggles-indent-face ((,class :inherit evil-goggles-default-face)))
-   `(evil-goggles-join-face ((,class :inherit modus-theme-subtle-green)))
-   `(evil-goggles-nerd-commenter-face ((,class :inherit 
evil-goggles-commentary-face)))
-   `(evil-goggles-paste-face ((,class :inherit modus-theme-subtle-cyan)))
-   `(evil-goggles-record-macro-face ((,class :inherit 
modus-theme-special-cold)))
-   `(evil-goggles-replace-with-register-face ((,class :inherit 
modus-theme-refine-magenta)))
-   `(evil-goggles-set-marker-face ((,class :inherit 
modus-theme-intense-magenta)))
-   `(evil-goggles-shift-face ((,class :inherit evil-goggles-default-face)))
-   `(evil-goggles-surround-face ((,class :inherit evil-goggles-default-face)))
-   `(evil-goggles-yank-face ((,class :inherit modus-theme-subtle-blue)))
-;;;;; evil-visual-mark-mode
-   `(evil-visual-mark-face ((,class :inherit modus-theme-intense-magenta)))
-;;;;; eww
-   `(eww-invalid-certificate ((,class :foreground ,red-active)))
-   `(eww-valid-certificate ((,class :foreground ,green-active)))
-   `(eww-form-checkbox ((,class :box (:line-width 1 :color ,fg-inactive :style 
released-button) :background ,bg-inactive :foreground ,fg-main)))
-   `(eww-form-file ((,class :box (:line-width 1 :color ,fg-inactive :style 
released-button) :background ,bg-active :foreground ,fg-main)))
-   `(eww-form-select ((,class :inherit eww-form-checkbox)))
-   `(eww-form-submit ((,class :inherit eww-form-file)))
-   `(eww-form-text ((,class :box (:line-width 1 :color ,fg-inactive :style 
none) :background ,bg-active :foreground ,fg-active)))
-   `(eww-form-textarea ((,class :background ,bg-alt :foreground ,fg-main)))
-;;;;; eyebrowse
-   `(eyebrowse-mode-line-active ((,class :inherit bold :foreground 
,blue-active)))
-;;;;; fancy-dabbrev
-   `(fancy-dabbrev-menu-face ((,class :background ,bg-alt :foreground 
,fg-alt)))
-   `(fancy-dabbrev-preview-face ((,class :foreground ,fg-alt :underline t)))
-   `(fancy-dabbrev-selection-face ((,class :inherit (modus-theme-intense-cyan 
bold))))
-;;;;; flycheck
-   `(flycheck-error
-     ((,(append '((supports :underline (:style wave))) class)
-       :underline (:color ,fg-lang-error :style wave))
-      (,class :foreground ,fg-lang-error :underline t)))
-   `(flycheck-error-list-checker-name ((,class :foreground ,magenta-active)))
-   `(flycheck-error-list-column-number ((,class :foreground ,fg-special-cold)))
-   `(flycheck-error-list-error ((,class ,@(modus-operandi-theme-bold-weight) 
:foreground ,red)))
-   `(flycheck-error-list-filename ((,class :foreground ,blue)))
-   `(flycheck-error-list-highlight ((,class :inherit modus-theme-hl-line)))
-   `(flycheck-error-list-id ((,class :foreground ,magenta-alt-other)))
-   `(flycheck-error-list-id-with-explainer ((,class :inherit 
flycheck-error-list-id :box t)))
-   `(flycheck-error-list-info ((,class :foreground ,cyan)))
-   `(flycheck-error-list-line-number ((,class :foreground ,fg-special-warm)))
-   `(flycheck-error-list-warning ((,class :foreground ,yellow)))
-   `(flycheck-fringe-error ((,class :inherit modus-theme-fringe-red)))
-   `(flycheck-fringe-info ((,class :inherit modus-theme-fringe-cyan)))
-   `(flycheck-fringe-warning ((,class :inherit modus-theme-fringe-yellow)))
-   `(flycheck-info
-     ((,(append '((supports :underline (:style wave))) class)
-       :underline (:color ,fg-lang-note :style wave))
-      (,class :foreground ,fg-lang-note :underline t)))
-   `(flycheck-verify-select-checker ((,class :box (:line-width 1 :color nil 
:style released-button))))
-   `(flycheck-warning
-     ((,(append '((supports :underline (:style wave))) class)
-       :underline (:color ,fg-lang-warning :style wave))
-      (,class :foreground ,fg-lang-warning :underline t)))
-;;;;; flycheck-color-mode-line
-   `(flycheck-color-mode-line-error-face ((,class :inherit 
flycheck-fringe-error)))
-   `(flycheck-color-mode-line-info-face ((,class :inherit 
flycheck-fringe-info)))
-   `(flycheck-color-mode-line-running-face ((,class :foreground ,fg-inactive 
:slant italic)))
-   `(flycheck-color-mode-line-info-face ((,class :inherit 
flycheck-fringe-warning)))
-;;;;; flycheck-indicator
-   `(flycheck-indicator-disabled ((,class :foreground ,fg-inactive :slant 
,modus-theme-slant)))
-   `(flycheck-indicator-error ((,class ,@(modus-operandi-theme-bold-weight) 
:foreground ,red-active)))
-   `(flycheck-indicator-info ((,class ,@(modus-operandi-theme-bold-weight) 
:foreground ,blue-active)))
-   `(flycheck-indicator-running ((,class ,@(modus-operandi-theme-bold-weight) 
:foreground ,magenta-active)))
-   `(flycheck-indicator-success ((,class ,@(modus-operandi-theme-bold-weight) 
:foreground ,green-active)))
-   `(flycheck-indicator-warning ((,class ,@(modus-operandi-theme-bold-weight) 
:foreground ,yellow-active)))
-;;;;; flycheck-posframe
-   `(flycheck-posframe-background-face ((,class :background ,bg-alt)))
-   `(flycheck-posframe-border-face ((,class :foreground ,fg-alt)))
-   `(flycheck-posframe-error-face ((,class :inherit bold :foreground ,red)))
-   `(flycheck-posframe-face ((,class :foreground ,fg-main :slant 
,modus-theme-slant)))
-   `(flycheck-posframe-info-face ((,class :inherit bold :foreground ,cyan)))
-   `(flycheck-posframe-warning-face ((,class :inherit bold :foreground 
,yellow)))
-;;;;; flymake
-   `(flymake-error
-     ((,(append '((supports :underline (:style wave))) class)
-       :underline (:color ,fg-lang-error :style wave))
-      (,class :foreground ,fg-lang-error :underline t)))
-   `(flymake-note
-     ((,(append '((supports :underline (:style wave))) class)
-       :underline (:color ,fg-lang-note :style wave))
-      (,class :foreground ,fg-lang-note :underline t)))
-   `(flymake-warning
-     ((,(append '((supports :underline (:style wave))) class)
-       :underline (:color ,fg-lang-warning :style wave))
-      (,class :foreground ,fg-lang-warning :underline t)))
-;;;;; flyspell
-   `(flyspell-duplicate
-     ((,(append '((supports :underline (:style wave))) class)
-       :underline (:color ,fg-lang-warning :style wave))
-      (,class :foreground ,fg-lang-warning :underline t)))
-   `(flyspell-incorrect
-     ((,(append '((supports :underline (:style wave))) class)
-       :underline (:color ,fg-lang-error :style wave))
-      (,class :foreground ,fg-lang-error :underline t)))
-;;;;; flyspell-correct
-   `(flyspell-correct-highlight-face ((,class :inherit 
modus-theme-refine-green)))
-;;;;; flx
-   `(flx-highlight-face ((,class ,@(modus-operandi-theme-extra-completions
-                                    'modus-theme-subtle-magenta
-                                    'modus-theme-intense-magenta
-                                    'modus-theme-nuanced-magenta
-                                    magenta-alt
-                                    'bold))))
-;;;;; freeze-it
-   `(freeze-it-show ((,class :background ,bg-dim :foreground 
,fg-special-warm)))
-;;;;; frog-menu
-   `(frog-menu-action-keybinding-face ((,class :foreground ,blue-alt-other)))
-   `(frog-menu-actions-face ((,class :foreground ,magenta)))
-   `(frog-menu-border ((,class :background ,bg-active)))
-   `(frog-menu-candidates-face ((,class :foreground ,fg-main)))
-   `(frog-menu-posframe-background-face ((,class :background ,bg-dim)))
-   `(frog-menu-prompt-face ((,class :foreground ,cyan)))
-;;;;; focus
-   `(focus-unfocused ((,class :foreground ,fg-unfocused)))
-;;;;; fold-this
-   `(fold-this-overlay ((,class :inherit modus-theme-special-mild)))
-;;;;; font-lock
-   `(font-lock-builtin-face ((,class ,@(modus-operandi-theme-syntax-foreground
-                                        magenta-alt magenta-alt-faint)
-                                     ,@(modus-operandi-theme-bold-weight))))
-   `(font-lock-comment-delimiter-face ((,class :foreground ,fg-alt :slant 
,modus-theme-slant)))
-   `(font-lock-comment-face ((,class :foreground ,fg-alt :slant 
,modus-theme-slant)))
-   `(font-lock-constant-face ((,class ,@(modus-operandi-theme-syntax-foreground
-                                         blue-alt-other 
blue-alt-other-faint))))
-   `(font-lock-doc-face ((,class ,@(modus-operandi-theme-syntax-foreground
-                                    fg-special-cold cyan-alt-other-faint)
-                                 :slant ,modus-theme-slant)))
-   `(font-lock-function-name-face ((,class 
,@(modus-operandi-theme-syntax-foreground
-                                              magenta magenta-faint))))
-   `(font-lock-keyword-face ((,class ,@(modus-operandi-theme-syntax-foreground
-                                        magenta-alt-other 
magenta-alt-other-faint)
-                                     ,@(modus-operandi-theme-bold-weight))))
-   `(font-lock-negation-char-face ((,class 
,@(modus-operandi-theme-syntax-foreground
-                                              yellow yellow-faint)
-                                           
,@(modus-operandi-theme-bold-weight))))
-   `(font-lock-preprocessor-face ((,class 
,@(modus-operandi-theme-syntax-foreground
-                                             red-alt-other 
red-alt-other-faint))))
-   `(font-lock-regexp-grouping-backslash ((,class :inherit bold :foreground 
,fg-escape-char-backslash)))
-   `(font-lock-regexp-grouping-construct ((,class :inherit bold :foreground 
,fg-escape-char-construct)))
-   `(font-lock-string-face ((,class ,@(modus-operandi-theme-syntax-foreground
-                                       blue-alt blue-alt-faint))))
-   `(font-lock-type-face ((,class ,@(modus-operandi-theme-syntax-foreground
-                                     magenta-alt magenta-alt-faint))))
-   `(font-lock-variable-name-face ((,class 
,@(modus-operandi-theme-syntax-foreground
-                                              cyan cyan-faint))))
-   `(font-lock-warning-face ((,class ,@(modus-operandi-theme-syntax-foreground
-                                        yellow-active yellow-alt-faint)
-                                     ,@(modus-operandi-theme-bold-weight))))
-;;;;; forge
-   `(forge-post-author ((,class :inherit bold :foreground ,fg-main)))
-   `(forge-post-date ((,class :foreground ,fg-special-cold)))
-   `(forge-topic-closed ((,class :foreground ,fg-alt)))
-   `(forge-topic-merged ((,class :foreground ,fg-alt)))
-   `(forge-topic-open ((,class :foreground ,fg-special-mild)))
-   `(forge-topic-unmerged ((,class :foreground ,magenta :slant 
,modus-theme-slant)))
-   `(forge-topic-unread ((,class :inherit bold :foreground ,fg-main)))
-;;;;; fountain-mode
-   `(fountain-character ((,class :foreground ,blue-alt-other)))
-   `(fountain-comment ((,class :foreground ,fg-alt :slant ,modus-theme-slant)))
-   `(fountain-dialog ((,class :foreground ,blue-alt)))
-   `(fountain-metadata-key ((,class :foreground ,green-alt-other)))
-   `(fountain-metadata-value ((,class :foreground ,blue)))
-   `(fountain-non-printing ((,class :foreground ,fg-alt)))
-   `(fountain-note ((,class :foreground ,yellow :slant ,modus-theme-slant)))
-   `(fountain-page-break ((,class :inherit bold :foreground ,red-alt)))
-   `(fountain-page-number ((,class :inherit bold :foreground ,red-alt-other)))
-   `(fountain-paren ((,class :foreground ,cyan)))
-   `(fountain-scene-heading ((,class :inherit bold :foreground ,blue-nuanced)))
-   `(fountain-section-heading ((,class :inherit (bold 
,modus-theme-variable-pitch) :foreground ,fg-main
-                                       ,@(modus-operandi-theme-scale 
modus-operandi-theme-scale-4))))
-   `(fountain-section-heading-1 ((,class :inherit (bold 
,modus-theme-variable-pitch) :foreground ,fg-main
-                                         ,@(modus-operandi-theme-scale 
modus-operandi-theme-scale-4))))
-   `(fountain-section-heading-2 ((,class :inherit (bold 
,modus-theme-variable-pitch) :foreground ,fg-special-warm
-                                         ,@(modus-operandi-theme-scale 
modus-operandi-theme-scale-3))))
-   `(fountain-section-heading-3 ((,class :inherit (bold 
,modus-theme-variable-pitch) :foreground ,fg-special-mild
-                                         ,@(modus-operandi-theme-scale 
modus-operandi-theme-scale-2))))
-   `(fountain-section-heading-4 ((,class :inherit (bold 
,modus-theme-variable-pitch) :foreground ,fg-special-calm
-                                         ,@(modus-operandi-theme-scale 
modus-operandi-theme-scale-1))))
-   `(fountain-section-heading-5 ((,class :inherit (bold 
,modus-theme-variable-pitch) :foreground ,fg-special-calm)))
-   `(fountain-synopsis ((,class :foreground ,cyan-alt)))
-   `(fountain-trans ((,class :foreground ,yellow-alt-other)))
-;;;;; geiser
-   `(geiser-font-lock-autodoc-current-arg ((,class 
,@(modus-operandi-theme-syntax-foreground
-                                                      magenta magenta-faint))))
-   `(geiser-font-lock-autodoc-identifier ((,class 
,@(modus-operandi-theme-syntax-foreground
-                                                     blue blue-faint))))
-   `(geiser-font-lock-doc-button ((,class 
,@(modus-operandi-theme-syntax-foreground
-                                             cyan-alt cyan-alt-faint)
-                                          :underline t)))
-   `(geiser-font-lock-doc-link ((,class :inherit link)))
-   `(geiser-font-lock-error-link ((,class 
,@(modus-operandi-theme-syntax-foreground
-                                             red-alt red-alt-faint)
-                                          :underline t)))
-   `(geiser-font-lock-image-button ((,class 
,@(modus-operandi-theme-syntax-foreground
-                                               green-alt green-alt-faint)
-                                            :underline t)))
-   `(geiser-font-lock-repl-input ((,class :inherit bold)))
-   `(geiser-font-lock-repl-output ((,class 
,@(modus-operandi-theme-syntax-foreground
-                                              magenta-alt-other 
magenta-alt-other-faint))))
-   `(geiser-font-lock-repl-prompt ((,class 
,@(modus-operandi-theme-syntax-foreground
-                                              cyan-alt-other 
cyan-alt-other-faint))))
-   `(geiser-font-lock-xref-header ((,class :inherit bold)))
-   `(geiser-font-lock-xref-link ((,class :inherit link)))
-;;;;; git-commit
-   `(git-commit-comment-action ((,class :foreground ,fg-alt :slant 
,modus-theme-slant)))
-   `(git-commit-comment-branch-local ((,class :foreground ,blue-alt :slant 
,modus-theme-slant)))
-   `(git-commit-comment-branch-remote ((,class :foreground ,magenta-alt :slant 
,modus-theme-slant)))
-   `(git-commit-comment-detached ((,class :foreground ,cyan-alt :slant 
,modus-theme-slant)))
-   `(git-commit-comment-file ((,class :foreground ,fg-special-cold :slant 
,modus-theme-slant)))
-   `(git-commit-comment-heading ((,class :inherit bold :foreground ,fg-dim 
:slant ,modus-theme-slant)))
-   `(git-commit-keyword ((,class :foreground ,magenta)))
-   `(git-commit-known-pseudo-header ((,class :foreground ,cyan-alt-other)))
-   `(git-commit-nonempty-second-line ((,class :inherit 
modus-theme-refine-yellow)))
-   `(git-commit-overlong-summary ((,class :inherit modus-theme-refine-yellow)))
-   `(git-commit-pseudo-header ((,class :foreground ,blue)))
-   `(git-commit-summary ((,class :inherit bold :foreground ,cyan)))
-;;;;; git-gutter
-   `(git-gutter:added ((,class :inherit modus-theme-fringe-green)))
-   `(git-gutter:deleted ((,class :inherit modus-theme-fringe-red)))
-   `(git-gutter:modified ((,class :inherit modus-theme-fringe-yellow)))
-   `(git-gutter:separator ((,class :inherit modus-theme-fringe-cyan)))
-   `(git-gutter:unchanged ((,class :inherit modus-theme-fringe-magenta)))
-;;;;; git-gutter-fr
-   `(git-gutter-fr:added ((,class :inherit modus-theme-fringe-green)))
-   `(git-gutter-fr:deleted ((,class :inherit modus-theme-fringe-red)))
-   `(git-gutter-fr:modified ((,class :inherit modus-theme-fringe-yellow)))
-;;;;; git-{gutter,fringe}+
-   `(git-gutter+-added ((,class :inherit modus-theme-fringe-green)))
-   `(git-gutter+-deleted ((,class :inherit modus-theme-fringe-red)))
-   `(git-gutter+-modified ((,class :inherit modus-theme-fringe-yellow)))
-   `(git-gutter+-separator ((,class :inherit modus-theme-fringe-cyan)))
-   `(git-gutter+-unchanged ((,class :inherit modus-theme-fringe-magenta)))
-   `(git-gutter-fr+-added ((,class :inherit modus-theme-fringe-green)))
-   `(git-gutter-fr+-deleted ((,class :inherit modus-theme-fringe-red)))
-   `(git-gutter-fr+-modified ((,class :inherit modus-theme-fringe-yellow)))
-;;;;; git-lens
-   `(git-lens-added ((,class :inherit bold :foreground ,green)))
-   `(git-lens-deleted ((,class :inherit bold :foreground ,red)))
-   `(git-lens-header ((,class :inherit bold :height 1.1 :foreground ,cyan)))
-   `(git-lens-modified ((,class :inherit bold :foreground ,yellow)))
-   `(git-lens-renamed ((,class :inherit bold :foreground ,magenta)))
-;;;;; git-rebase
-   `(git-rebase-comment-hash ((,class :foreground ,fg-special-cold :slant 
,modus-theme-slant)))
-   `(git-rebase-comment-heading ((,class :inherit bold :foreground ,fg-dim 
:slant ,modus-theme-slant)))
-   `(git-rebase-description ((,class :foreground ,fg-main)))
-   `(git-rebase-hash ((,class :foreground ,cyan-alt-other)))
-;;;;; git-timemachine
-   `(git-timemachine-commit ((,class :inherit bold :foreground 
,yellow-active)))
-   `(git-timemachine-minibuffer-author-face ((,class :foreground 
,fg-special-warm)))
-   `(git-timemachine-minibuffer-detail-face ((,class :foreground ,red-alt)))
-;;;;; git-walktree
-   `(git-walktree-commit-face ((,class :foreground ,yellow)))
-   `(git-walktree-symlink-face ((,class :inherit button :foreground ,cyan)))
-   `(git-walktree-tree-face ((,class :foreground ,magenta)))
-;;;;; gnus
-   `(gnus-button ((,class :inherit button)))
-   `(gnus-cite-1 ((,class :foreground ,blue-alt)))
-   `(gnus-cite-10 ((,class :foreground ,magenta-alt-other)))
-   `(gnus-cite-11 ((,class :foreground ,yellow-alt-other)))
-   `(gnus-cite-2 ((,class :foreground ,red-alt)))
-   `(gnus-cite-3 ((,class :foreground ,green-alt)))
-   `(gnus-cite-4 ((,class :foreground ,magenta-alt)))
-   `(gnus-cite-5 ((,class :foreground ,yellow-alt)))
-   `(gnus-cite-6 ((,class :foreground ,cyan-alt)))
-   `(gnus-cite-7 ((,class :foreground ,blue-alt-other)))
-   `(gnus-cite-8 ((,class :foreground ,red-alt-other)))
-   `(gnus-cite-9 ((,class :foreground ,green-alt-other)))
-   `(gnus-cite-attribution ((,class :foreground ,fg-main :slant italic)))
-   `(gnus-emphasis-highlight-words ((,class :inherit 
modus-theme-refine-yellow)))
-   `(gnus-group-mail-1 ((,class :inherit bold :foreground ,magenta-alt)))
-   `(gnus-group-mail-1-empty ((,class :foreground ,magenta-alt)))
-   `(gnus-group-mail-2 ((,class :inherit bold :foreground ,magenta)))
-   `(gnus-group-mail-2-empty ((,class :foreground ,magenta)))
-   `(gnus-group-mail-3 ((,class :inherit bold :foreground ,magenta-alt-other)))
-   `(gnus-group-mail-3-empty ((,class :foreground ,magenta-alt-other)))
-   `(gnus-group-mail-low ((,class :inherit bold :foreground ,magenta-nuanced)))
-   `(gnus-group-mail-low-empty ((,class :foreground ,magenta-nuanced)))
-   `(gnus-group-news-1 ((,class :inherit bold :foreground ,green)))
-   `(gnus-group-news-1-empty ((,class :foreground ,green)))
-   `(gnus-group-news-2 ((,class :inherit bold :foreground ,cyan)))
-   `(gnus-group-news-2-empty ((,class :foreground ,cyan)))
-   `(gnus-group-news-3 ((,class :inherit bold :foreground ,yellow-nuanced)))
-   `(gnus-group-news-3-empty ((,class :foreground ,yellow-nuanced)))
-   `(gnus-group-news-4 ((,class :inherit bold :foreground ,cyan-nuanced)))
-   `(gnus-group-news-4-empty ((,class :foreground ,cyan-nuanced)))
-   `(gnus-group-news-5 ((,class :inherit bold :foreground ,red-nuanced)))
-   `(gnus-group-news-5-empty ((,class :foreground ,red-nuanced)))
-   `(gnus-group-news-6 ((,class :inherit bold :foreground ,fg-alt)))
-   `(gnus-group-news-6-empty ((,class :foreground ,fg-alt)))
-   `(gnus-group-news-low ((,class :inherit bold :foreground ,green-nuanced)))
-   `(gnus-group-news-low-empty ((,class :foreground ,green-nuanced)))
-   `(gnus-header-content ((,class :foreground ,cyan)))
-   `(gnus-header-from ((,class :inherit bold :foreground ,cyan-alt-other 
:underline nil)))
-   `(gnus-header-name ((,class :foreground ,green)))
-   `(gnus-header-newsgroups ((,class :inherit bold :foreground ,blue-alt)))
-   `(gnus-header-subject ((,class :inherit bold :foreground 
,magenta-alt-other)))
-   `(gnus-server-agent ((,class :inherit bold :foreground ,cyan)))
-   `(gnus-server-closed ((,class :inherit bold :foreground ,magenta)))
-   `(gnus-server-cloud ((,class :inherit bold :foreground ,cyan-alt)))
-   `(gnus-server-cloud-host ((,class :inherit modus-theme-refine-cyan)))
-   `(gnus-server-denied ((,class :inherit bold :foreground ,red)))
-   `(gnus-server-offline ((,class :inherit bold :foreground ,yellow)))
-   `(gnus-server-opened ((,class :inherit bold :foreground ,green)))
-   `(gnus-signature ((,class :foreground ,fg-special-cold :slant italic)))
-   `(gnus-splash ((,class :foreground ,fg-alt)))
-   `(gnus-summary-cancelled ((,class :inherit modus-theme-mark-alt)))
-   `(gnus-summary-high-ancient ((,class :inherit bold :foreground ,fg-alt)))
-   `(gnus-summary-high-read ((,class :inherit bold :foreground 
,fg-special-cold)))
-   `(gnus-summary-high-ticked ((,class :inherit bold :foreground 
,red-alt-other)))
-   `(gnus-summary-high-undownloaded ((,class :inherit bold :foreground 
,yellow)))
-   `(gnus-summary-high-unread ((,class :inherit bold :foreground ,fg-main)))
-   `(gnus-summary-low-ancient ((,class :foreground ,fg-alt :slant italic)))
-   `(gnus-summary-low-read ((,class :foreground ,fg-alt :slant italic)))
-   `(gnus-summary-low-ticked ((,class :foreground ,red-refine-fg :slant 
italic)))
-   `(gnus-summary-low-undownloaded ((,class :foreground ,yellow-refine-fg 
:slant italic)))
-   `(gnus-summary-low-unread ((,class :inherit bold :foreground 
,fg-special-cold)))
-   `(gnus-summary-normal-ancient ((,class :foreground ,fg-special-calm)))
-   `(gnus-summary-normal-read ((,class :foreground ,fg-alt)))
-   `(gnus-summary-normal-ticked ((,class :foreground ,red-alt-other)))
-   `(gnus-summary-normal-undownloaded ((,class :foreground ,yellow)))
-   `(gnus-summary-normal-unread ((,class :foreground ,fg-main)))
-   `(gnus-summary-selected ((,class :inherit modus-theme-subtle-blue)))
-;;;;; golden-ratio-scroll-screen
-   `(golden-ratio-scroll-highlight-line-face ((,class :background 
,cyan-subtle-bg :foreground ,fg-main)))
-;;;;; helm
-   `(helm-M-x-key ((,class :inherit bold :foreground ,magenta-alt-other)))
-   `(helm-action ((,class :underline t)))
-   `(helm-bookmark-addressbook ((,class :foreground ,green-alt)))
-   `(helm-bookmark-directory ((,class :inherit bold :foreground ,blue)))
-   `(helm-bookmark-file ((,class :foreground ,fg-main)))
-   `(helm-bookmark-file-not-found ((,class :background ,bg-alt :foreground 
,fg-alt)))
-   `(helm-bookmark-gnus ((,class :foreground ,magenta)))
-   `(helm-bookmark-info ((,class :foreground ,cyan-alt)))
-   `(helm-bookmark-man ((,class :foreground ,yellow-alt)))
-   `(helm-bookmark-w3m ((,class :foreground ,blue-alt)))
-   `(helm-buffer-archive ((,class :inherit bold :foreground ,cyan)))
-   `(helm-buffer-directory ((,class :inherit bold :foreground ,blue)))
-   `(helm-buffer-file ((,class :foreground ,fg-main)))
-   `(helm-buffer-modified ((,class :foreground ,yellow-alt)))
-   `(helm-buffer-not-saved ((,class :foreground ,red-alt)))
-   `(helm-buffer-process ((,class :foreground ,magenta)))
-   `(helm-buffer-saved-out ((,class :inherit bold :background ,bg-alt 
:foreground ,red)))
-   `(helm-buffer-size ((,class :foreground ,fg-alt)))
-   `(helm-candidate-number ((,class :foreground ,cyan-active)))
-   `(helm-candidate-number-suspended ((,class :foreground ,yellow-active)))
-   `(helm-comint-prompts-buffer-name ((,class :foreground ,green-active)))
-   `(helm-comint-prompts-promptidx ((,class :foreground ,cyan-active)))
-   `(helm-delete-async-message ((,class :inherit bold :foreground 
,magenta-active)))
-   `(helm-eob-line ((,class :background ,bg-main :foreground ,fg-main)))
-   `(helm-eshell-prompts-buffer-name ((,class :foreground ,green-active)))
-   `(helm-eshell-prompts-promptidx ((,class :foreground ,cyan-active)))
-   `(helm-etags-file ((,class :foreground ,fg-dim :underline t)))
-   `(helm-ff-backup-file ((,class :foreground ,fg-alt)))
-   `(helm-ff-denied ((,class ,@(modus-operandi-theme-extra-completions
-                                'modus-theme-subtle-red
-                                'modus-theme-intense-red
-                                'modus-theme-nuanced-red
-                                red))))
-   `(helm-ff-directory ((,class :inherit helm-buffer-directory)))
-   `(helm-ff-dirs ((,class :inherit bold :foreground ,blue-alt-other)))
-   `(helm-ff-dotted-directory ((,class :inherit bold :background ,bg-alt 
:foreground ,fg-alt)))
-   `(helm-ff-dotted-symlink-directory ((,class :inherit (button 
helm-ff-dotted-directory))))
-   `(helm-ff-executable ((,class :foreground ,magenta-alt)))
-   `(helm-ff-file ((,class :foreground ,fg-main)))
-   `(helm-ff-file-extension ((,class :foreground ,fg-special-warm)))
-   `(helm-ff-invalid-symlink ((,class :inherit button :foreground ,red)))
-   `(helm-ff-pipe ((,class ,@(modus-operandi-theme-extra-completions
-                              'modus-theme-refine-magenta
-                              'modus-theme-subtle-magenta
-                              'modus-theme-nuanced-magenta
-                              magenta))))
-   `(helm-ff-prefix ((,class ,@(modus-operandi-theme-extra-completions
-                                'modus-theme-refine-yellow
-                                'modus-theme-subtle-yellow
-                                'modus-theme-nuanced-yellow
-                                yellow-alt-other))))
-   `(helm-ff-socket ((,class :foreground ,red-alt-other)))
-   `(helm-ff-suid ((,class ,@(modus-operandi-theme-extra-completions
-                              'modus-theme-subtle-red
-                              'modus-theme-refine-red
-                              'modus-theme-nuanced-yellow
-                              red-alt))))
-   `(helm-ff-symlink ((,class :inherit button :foreground ,cyan)))
-   `(helm-ff-truename ((,class :foreground ,blue-alt-other)))
-   `(helm-grep-cmd-line ((,class :foreground ,yellow-alt-other)))
-   `(helm-grep-file ((,class :inherit bold :foreground ,fg-special-cold)))
-   `(helm-grep-finish ((,class :foreground ,green-active)))
-   `(helm-grep-lineno ((,class :foreground ,fg-special-warm)))
-   `(helm-grep-match ((,class :inherit modus-theme-special-calm)))
-   `(helm-header ((,class :inherit bold :foreground ,fg-special-cold)))
-   `(helm-header-line-left-margin ((,class :inherit bold :foreground 
,yellow-intense)))
-   `(helm-history-deleted ((,class ,@(modus-operandi-theme-extra-completions
-                                      'modus-theme-subtle-red
-                                      'modus-theme-intense-red
-                                      'modus-theme-nuanced-red
-                                      red
-                                      'bold))))
-   `(helm-history-remote ((,class :foreground ,red-alt-other)))
-   `(helm-lisp-completion-info ((,class :foreground ,fg-special-warm)))
-   `(helm-lisp-show-completion ((,class 
,@(modus-operandi-theme-extra-completions
-                                           'modus-theme-subtle-yellow
-                                           'modus-theme-refine-yellow
-                                           'modus-theme-nuanced-yellow
-                                           yellow
-                                           'bold))))
-   `(helm-locate-finish ((,class :foreground ,green-active)))
-   `(helm-match ((,class ,@(modus-operandi-theme-extra-completions
-                            'modus-theme-subtle-cyan
-                            'modus-theme-refine-cyan
-                            'modus-theme-nuanced-cyan
-                            cyan
-                            'bold))))
-   `(helm-match-item ((,class ,@(modus-operandi-theme-extra-completions
-                                 'modus-theme-subtle-neutral
-                                 'modus-theme-subtle-cyan
-                                 'modus-theme-nuanced-cyan
-                                 cyan-alt-other))))
-   `(helm-minibuffer-prompt ((,class :inherit minibuffer-prompt)))
-   `(helm-moccur-buffer ((,class :inherit button :foreground ,cyan-alt-other)))
-   `(helm-mode-prefix ((,class ,@(modus-operandi-theme-extra-completions
-                                  'modus-theme-subtle-magenta
-                                  'modus-theme-intense-magenta
-                                  'modus-theme-nuanced-magenta
-                                  magenta-alt
-                                  'bold))))
-   `(helm-non-file-buffer ((,class :foreground ,fg-alt)))
-   `(helm-prefarg ((,class :foreground ,red-active)))
-   `(helm-resume-need-update ((,class ,@(modus-operandi-theme-extra-completions
-                                         'modus-theme-subtle-magenta
-                                         'modus-theme-refine-magenta
-                                         'modus-theme-nuanced-magenta
-                                         magenta-alt-other))))
-   `(helm-selection ((,class ,@(modus-operandi-theme-extra-completions
-                                'modus-theme-subtle-blue
-                                'modus-theme-refine-blue
-                                'modus-theme-special-cold
-                                nil
-                                'bold))))
-   `(helm-selection-line ((,class :inherit modus-theme-special-cold)))
-   `(helm-separator ((,class :foreground ,fg-special-mild)))
-   `(helm-time-zone-current ((,class :foreground ,green)))
-   `(helm-time-zone-home ((,class :foreground ,magenta)))
-   `(helm-source-header ((,class :inherit bold :foreground ,red-alt
-                                 ,@(modus-operandi-theme-scale 
modus-operandi-theme-scale-4))))
-   `(helm-top-columns ((,class :inherit helm-header)))
-   `(helm-ucs-char ((,class :foreground ,yellow-alt-other)))
-   `(helm-visible-mark ((,class :inherit modus-theme-subtle-cyan)))
-;;;;; helm-ls-git
-   `(helm-ls-git-added-copied-face ((,class :foreground ,green-intense)))
-   `(helm-ls-git-added-modified-face ((,class :foreground ,yellow-intense)))
-   `(helm-ls-git-conflict-face ((,class :inherit bold :foreground 
,red-intense)))
-   `(helm-ls-git-deleted-and-staged-face ((,class :foreground ,red-nuanced)))
-   `(helm-ls-git-deleted-not-staged-face ((,class :foreground ,red)))
-   `(helm-ls-git-modified-and-staged-face ((,class :foreground 
,yellow-nuanced)))
-   `(helm-ls-git-modified-not-staged-face ((,class :foreground ,yellow)))
-   `(helm-ls-git-renamed-modified-face ((,class :foreground ,magenta)))
-   `(helm-ls-git-untracked-face ((,class :foreground ,fg-special-cold)))
-;;;;; helm-switch-shell
-   `(helm-switch-shell-new-shell-face ((,class 
,@(modus-operandi-theme-extra-completions
-                                                  'modus-theme-subtle-magenta
-                                                  'modus-theme-refine-magenta
-                                                  'modus-theme-nuanced-magenta
-                                                  magenta-alt-other
-                                                  'bold))))
-;;;;; helm-xref
-   `(helm-xref-file-name ((,class :inherit bold :foreground ,fg-special-cold)))
-   `(helm-xref-file-name ((,class :foreground ,fg-special-warm)))
-;;;;; helpful
-   `(helpful-heading ((,class :inherit modus-theme-heading-1)))
-;;;;; highlight region or ad-hoc regexp
-   `(hi-black-b ((,class :background ,fg-main :foreground ,bg-main)))
-   `(hi-blue ((,class :background ,bg-alt :foreground ,blue :underline t)))
-   `(hi-blue-b ((,class :inherit modus-theme-intense-blue)))
-   `(hi-green ((,class :background ,bg-alt :foreground ,green :underline t)))
-   `(hi-green-b ((,class :inherit modus-theme-intense-green)))
-   `(hi-pink ((,class :background ,bg-alt :foreground ,magenta :underline t)))
-   `(hi-red-b ((,class :inherit modus-theme-intense-red)))
-   `(hi-yellow ((,class :background ,bg-alt :foreground ,yellow :underline t)))
-   `(highlight ((,class :inherit modus-theme-subtle-blue)))
-   `(highlight-changes ((,class :foreground ,yellow-alt-other)))
-   `(highlight-changes-delete ((,class :foreground ,red-alt-other :underline 
t)))
-   `(hl-line ((,class :inherit modus-theme-hl-line)))
-;;;;; highlight-blocks
-   `(highlight-blocks-depth-1-face ((,class :background ,bg-dim :foreground 
,fg-main)))
-   `(highlight-blocks-depth-2-face ((,class :background ,bg-alt :foreground 
,fg-main)))
-   `(highlight-blocks-depth-3-face ((,class :background ,bg-special-cold 
:foreground ,fg-main)))
-   `(highlight-blocks-depth-4-face ((,class :background ,bg-special-calm 
:foreground ,fg-main)))
-   `(highlight-blocks-depth-5-face ((,class :background ,bg-special-warm 
:foreground ,fg-main)))
-   `(highlight-blocks-depth-6-face ((,class :background ,bg-special-mild 
:foreground ,fg-main)))
-   `(highlight-blocks-depth-7-face ((,class :background ,bg-inactive 
:foreground ,fg-main)))
-   `(highlight-blocks-depth-8-face ((,class :background ,bg-active :foreground 
,fg-main)))
-   `(highlight-blocks-depth-9-face ((,class :background ,cyan-subtle-bg 
:foreground ,fg-main)))
-;;;;; highlight-defined
-   `(highlight-defined-builtin-function-name-face ((,class :foreground 
,magenta)))
-   `(highlight-defined-face-name-face ((,class :foreground ,fg-main)))
-   `(highlight-defined-function-name-face ((,class :foreground ,magenta)))
-   `(highlight-defined-macro-name-face ((,class :foreground ,magenta-alt)))
-   `(highlight-defined-special-form-name-face ((,class :foreground 
,magenta-alt-other)))
-   `(highlight-defined-variable-name-face ((,class :foreground ,cyan)))
-;;;;; highlight-escape-sequences (`hes-mode')
-   `(hes-escape-backslash-face ((,class :inherit bold :foreground 
,fg-escape-char-construct)))
-   `(hes-escape-sequence-face ((,class :inherit bold :foreground 
,fg-escape-char-backslash)))
-;;;;; highlight-indentation
-   `(highlight-indentation-face ((,class :inherit modus-theme-hl-line)))
-   `(highlight-indentation-current-column-face ((,class :background 
,bg-active)))
-;;;;; highlight-numbers
-   `(highlight-numbers-number ((,class :foreground ,blue-alt-other)))
-;;;;; highlight-symbol
-   `(highlight-symbol-face ((,class :inherit modus-theme-special-mild)))
-;;;;; highlight-thing
-   `(highlight-thing ((,class :background ,bg-alt :foreground ,cyan)))
-;;;;; hl-defined
-   `(hdefd-functions ((,class :foreground ,blue)))
-   `(hdefd-undefined ((,class :foreground ,red-alt)))
-   `(hdefd-variables ((,class :foreground ,cyan-alt)))
-;;;;; hl-fill-column
-   `(hl-fill-column-face ((,class :background ,bg-active :foreground 
,fg-active)))
-;;;;; hl-todo
-   `(hl-todo ((,class :inherit bold :foreground ,red-alt-other :slant 
,modus-theme-slant)))
-;;;;; hydra
-   `(hydra-face-amaranth ((,class :inherit bold :foreground ,yellow)))
-   `(hydra-face-blue ((,class :inherit bold :foreground ,blue-alt)))
-   `(hydra-face-pink ((,class :inherit bold :foreground ,magenta-alt)))
-   `(hydra-face-red ((,class :inherit bold :foreground ,red)))
-   `(hydra-face-teal ((,class :inherit bold :foreground ,cyan)))
-;;;;; hyperlist
-   `(hyperlist-condition ((,class :foreground ,green)))
-   `(hyperlist-hashtag ((,class :foreground ,yellow)))
-   `(hyperlist-operator ((,class :foreground ,blue-alt)))
-   `(hyperlist-paren ((,class :foreground ,cyan-alt-other)))
-   `(hyperlist-quote ((,class :foreground ,cyan-alt)))
-   `(hyperlist-ref ((,class :foreground ,magenta-alt-other)))
-   `(hyperlist-stars ((,class :foreground ,fg-alt)))
-   `(hyperlist-tag ((,class :foreground ,red)))
-   `(hyperlist-toplevel ((,class :inherit bold :foreground ,fg-main)))
-;;;;; icomplete
-   `(icomplete-first-match ((,class :inherit bold
-                                    
,@(modus-operandi-theme-standard-completions
-                                       magenta bg-alt
-                                       bg-active fg-main))))
-;;;;; icomplete-vertical
-   `(icomplete-vertical-separator ((,class :foreground ,fg-alt)))
-;;;;; ido-mode
-   `(ido-first-match ((,class :inherit bold
-                              ,@(modus-operandi-theme-standard-completions
-                                 magenta bg-alt
-                                 bg-active fg-main))))
-   `(ido-incomplete-regexp ((,class :inherit error)))
-   `(ido-indicator ((,class :inherit modus-theme-subtle-yellow)))
-   `(ido-only-match ((,class :inherit bold
-                             ,@(modus-operandi-theme-standard-completions
-                                green green-nuanced-bg
-                                green-intense-bg fg-main))))
-   `(ido-subdir ((,class :foreground ,blue)))
-   `(ido-virtual ((,class :foreground ,fg-special-warm)))
-;;;;; iedit
-   `(iedit-occurrence ((,class :inherit modus-theme-refine-blue)))
-   `(iedit-read-only-occurrence ((,class :inherit modus-theme-intense-yellow)))
-;;;;; iflipb
-   `(iflipb-current-buffer-face ((,class :inherit bold :foreground ,cyan-alt)))
-   `(iflipb-other-buffer-face ((,class :foreground ,fg-alt)))
-;;;;; imenu-list
-   `(imenu-list-entry-face-0 ((,class :foreground ,cyan)))
-   `(imenu-list-entry-face-1 ((,class :foreground ,blue)))
-   `(imenu-list-entry-face-2 ((,class :foreground ,cyan-alt-other)))
-   `(imenu-list-entry-face-3 ((,class :foreground ,blue-alt)))
-   `(imenu-list-entry-subalist-face-0 ((,class :inherit bold :foreground 
,magenta-alt-other :underline t)))
-   `(imenu-list-entry-subalist-face-1 ((,class :inherit bold :foreground 
,magenta :underline t)))
-   `(imenu-list-entry-subalist-face-2 ((,class :inherit bold :foreground 
,green-alt-other :underline t)))
-   `(imenu-list-entry-subalist-face-3 ((,class :inherit bold :foreground 
,red-alt-other :underline t)))
-;;;;; indium
-   `(indium-breakpoint-face ((,class :foreground ,red-active)))
-   `(indium-frame-url-face ((,class :inherit button :foreground ,fg-alt)))
-   `(indium-keyword-face ((,class :foreground ,magenta-alt-other)))
-   `(indium-litable-face ((,class :foreground ,fg-special-warm :slant 
,modus-theme-slant)))
-   `(indium-repl-error-face ((,class :inherit bold :foreground ,red)))
-   `(indium-repl-prompt-face ((,class :foreground ,cyan-alt-other)))
-   `(indium-repl-stdout-face ((,class :foreground ,fg-main)))
-;;;;; info
-   `(Info-quoted ((,class ,@(modus-operandi-theme-mixed-fonts)
-                          :foreground ,magenta))) ; the capitalisation is 
canonical
-   `(info-header-node ((,class :inherit bold :foreground ,fg-alt)))
-   `(info-header-xref ((,class :foreground ,blue-active)))
-   `(info-index-match ((,class :inherit match)))
-   `(info-menu-header ((,class :inherit modus-theme-heading-3)))
-   `(info-menu-star ((,class :foreground ,red)))
-   `(info-node ((,class :inherit bold)))
-   `(info-title-1 ((,class :inherit modus-theme-heading-1)))
-   `(info-title-2 ((,class :inherit modus-theme-heading-2)))
-   `(info-title-3 ((,class :inherit modus-theme-heading-3)))
-   `(info-title-4 ((,class :inherit modus-theme-heading-4)))
-;;;;; info-colors
-   `(info-colors-lisp-code-block ((,class :inherit fixed-pitch)))
-   `(info-colors-ref-item-command ((,class :foreground ,magenta)))
-   `(info-colors-ref-item-constant ((,class :foreground ,blue-alt-other)))
-   `(info-colors-ref-item-function ((,class :foreground ,magenta)))
-   `(info-colors-ref-item-macro ((,class ,@(modus-operandi-theme-bold-weight) 
:foreground ,magenta-alt-other)))
-   `(info-colors-ref-item-other ((,class :foreground ,cyan)))
-   `(info-colors-ref-item-special-form ((,class 
,@(modus-operandi-theme-bold-weight) :foreground ,magenta-alt-other)))
-   `(info-colors-ref-item-syntax-class ((,class :foreground ,magenta)))
-   `(info-colors-ref-item-type ((,class :foreground ,magenta-alt)))
-   `(info-colors-ref-item-user-option ((,class :foreground ,cyan)))
-   `(info-colors-ref-item-variable ((,class :foreground ,cyan)))
-;;;;; interaction-log
-   `(ilog-buffer-face ((,class :foreground ,magenta-alt-other)))
-   `(ilog-change-face ((,class :foreground ,magenta-alt)))
-   `(ilog-echo-face ((,class :foreground ,yellow-alt-other)))
-   `(ilog-load-face ((,class :foreground ,green)))
-   `(ilog-message-face ((,class :foreground ,fg-alt)))
-   `(ilog-non-change-face ((,class :foreground ,blue)))
-;;;;; ioccur
-   `(ioccur-cursor ((,class :foreground ,fg-main)))
-   `(ioccur-invalid-regexp ((,class :foreground ,red)))
-   `(ioccur-match-face ((,class :inherit modus-theme-special-calm)))
-   `(ioccur-match-overlay-face ((,class ,@(and (>= emacs-major-version 27) 
'(:extend t))
-                                        :inherit modus-theme-special-cold)))
-   `(ioccur-num-line-face ((,class :foreground ,fg-special-warm)))
-   `(ioccur-overlay-face ((,class ,@(and (>= emacs-major-version 27) '(:extend 
t))
-                                  :inherit modus-theme-refine-blue)))
-   `(ioccur-regexp-face ((,class :inherit (modus-theme-intense-magenta bold))))
-   `(ioccur-title-face ((,class :inherit bold :foreground ,red-alt
-                                ,@(modus-operandi-theme-scale 
modus-operandi-theme-scale-4))))
-;;;;; isearch, occur, and the like
-   `(isearch ((,class :inherit (modus-theme-intense-green bold))))
-   `(isearch-fail ((,class :inherit modus-theme-refine-red)))
-   `(lazy-highlight ((,class :inherit modus-theme-refine-cyan)))
-   `(match ((,class :inherit modus-theme-special-calm)))
-   `(query-replace ((,class :inherit (modus-theme-intense-yellow bold))))
-;;;;; ivy
-   `(ivy-action ((,class :inherit bold :foreground ,red-alt)))
-   `(ivy-completions-annotations ((,class :foreground ,fg-special-cold :slant 
,modus-theme-slant)))
-   `(ivy-confirm-face ((,class :foreground ,cyan)))
-   `(ivy-current-match ((,class ,@(modus-operandi-theme-extra-completions
-                                   'modus-theme-refine-cyan
-                                   'modus-theme-intense-cyan
-                                   'modus-theme-special-warm
-                                   nil
-                                   'bold))))
-   `(ivy-cursor ((,class :background ,fg-main :foreground ,bg-main)))
-   `(ivy-grep-info ((,class :foreground ,cyan-alt)))
-   `(ivy-grep-line-number ((,class :foreground ,fg-special-warm)))
-   `(ivy-highlight-face ((,class :foreground ,magenta)))
-   `(ivy-match-required-face ((,class :inherit error)))
-   `(ivy-minibuffer-match-face-1 ((,class 
,@(modus-operandi-theme-extra-completions
-                                             'modus-theme-subtle-neutral
-                                             'modus-theme-intense-neutral
-                                             'modus-theme-subtle-neutral
-                                             fg-alt))))
-   `(ivy-minibuffer-match-face-2 ((,class 
,@(modus-operandi-theme-extra-completions
-                                             'modus-theme-subtle-green
-                                             'modus-theme-refine-green
-                                             'modus-theme-nuanced-green
-                                             green-alt-other
-                                             'bold))))
-   `(ivy-minibuffer-match-face-3 ((,class 
,@(modus-operandi-theme-extra-completions
-                                             'modus-theme-subtle-cyan
-                                             'modus-theme-refine-cyan
-                                             'modus-theme-nuanced-cyan
-                                             cyan-alt-other
-                                             'bold))))
-   `(ivy-minibuffer-match-face-4 ((,class 
,@(modus-operandi-theme-extra-completions
-                                             'modus-theme-subtle-magenta
-                                             'modus-theme-refine-magenta
-                                             'modus-theme-nuanced-magenta
-                                             magenta-alt-other
-                                             'bold))))
-   `(ivy-minibuffer-match-highlight ((,class 
,@(modus-operandi-theme-extra-completions
-                                                'modus-theme-subtle-blue
-                                                'modus-theme-intense-blue
-                                                'modus-theme-nuanced-blue
-                                                blue-alt-other
-                                                'bold))))
-   `(ivy-modified-buffer ((,class :foreground ,yellow :slant 
,modus-theme-slant)))
-   `(ivy-modified-outside-buffer ((,class :foreground ,yellow-alt :slant 
,modus-theme-slant)))
-   `(ivy-org ((,class :foreground ,cyan-alt-other)))
-   `(ivy-prompt-match ((,class :inherit ivy-current-match)))
-   `(ivy-remote ((,class :foreground ,magenta)))
-   `(ivy-separator ((,class :foreground ,fg-alt)))
-   `(ivy-subdir ((,class :foreground ,blue-alt-other)))
-   `(ivy-virtual ((,class :foreground ,magenta-alt-other)))
-   `(ivy-yanked-word ((,class ,@(modus-operandi-theme-extra-completions
-                                 'modus-theme-subtle-blue
-                                 'modus-theme-refine-blue
-                                 'modus-theme-nuanced-blue
-                                 blue-alt))))
-;;;;; ivy-posframe
-   `(ivy-posframe ((,class :background ,bg-dim :foreground ,fg-main)))
-   `(ivy-posframe-border ((,class :background ,bg-active)))
-   `(ivy-posframe-cursor ((,class :background ,fg-main :foreground ,bg-main)))
-;;;;; jira (org-jira)
-   `(jiralib-comment-face ((,class :background ,bg-alt)))
-   `(jiralib-comment-header-face ((,class :inherit bold)))
-   `(jiralib-issue-info-face ((,class :inherit modus-theme-special-warm)))
-   `(jiralib-issue-info-header-face ((,class :inherit 
(modus-theme-special-warm bold))))
-   `(jiralib-issue-summary-face ((,class :inherit bold)))
-   `(jiralib-link-filter-face ((,class :underline t)))
-   `(jiralib-link-issue-face ((,class :underline t)))
-   `(jiralib-link-project-face ((,class :underline t)))
-;;;;; journalctl-mode
-   `(journalctl-error-face ((,class :inherit bold :foreground ,red)))
-   `(journalctl-finished-face ((,class :inherit bold :foreground ,green)))
-   `(journalctl-host-face ((,class :foreground ,blue)))
-   `(journalctl-process-face ((,class :foreground ,cyan-alt-other)))
-   `(journalctl-starting-face ((,class :foreground ,green)))
-   `(journalctl-timestamp-face ((,class :foreground ,fg-special-cold)))
-   `(journalctl-warning-face ((,class :inherit bold :foreground ,yellow)))
-;;;;; js2-mode
-   `(js2-error ((,class :foreground ,red)))
-   `(js2-external-variable ((,class :foreground ,cyan-alt-other)))
-   `(js2-function-call ((,class :foreground ,magenta)))
-   `(js2-function-param ((,class :foreground ,blue)))
-   `(js2-instance-member ((,class :foreground ,magenta-alt-other)))
-   `(js2-jsdoc-html-tag-delimiter ((,class :foreground ,fg-main)))
-   `(js2-jsdoc-html-tag-name ((,class :foreground ,cyan)))
-   `(js2-jsdoc-tag ((,class :foreground ,fg-special-calm)))
-   `(js2-jsdoc-type ((,class :foreground ,fg-special-cold)))
-   `(js2-jsdoc-value ((,class :foreground ,fg-special-warm)))
-   `(js2-object-property ((,class :foreground ,fg-main)))
-   `(js2-object-property-access ((,class :foreground ,fg-main)))
-   `(js2-private-function-call ((,class :foreground ,green-alt-other)))
-   `(js2-private-member ((,class :foreground ,fg-special-mild)))
-   `(js2-warning ((,class :foreground ,yellow-alt :underline t)))
-;;;;; julia
-   `(julia-macro-face ((,class ,@(modus-operandi-theme-bold-weight) 
:foreground ,magenta)))
-   `(julia-quoted-symbol-face ((,class :foreground ,blue-alt-other)))
-;;;;; jupyter
-   `(jupyter-eval-overlay ((,class :inherit bold :foreground ,blue)))
-   `(jupyter-repl-input-prompt ((,class :foreground ,cyan-alt-other)))
-   `(jupyter-repl-output-prompt ((,class :foreground ,magenta-alt-other)))
-   `(jupyter-repl-traceback ((,class :inherit modus-theme-intense-red)))
-;;;;; kaocha-runner
-   `(kaocha-runner-error-face ((,class :foreground ,red)))
-   `(kaocha-runner-success-face ((,class :foreground ,green)))
-   `(kaocha-runner-warning-face ((,class :foreground ,yellow)))
-;;;;; keycast
-   `(keycast-command ((,class :inherit bold :foreground ,blue-active)))
-   `(keycast-key ((,class ,@(modus-operandi-theme-mode-line-attrs
-                             bg-main blue-active
-                             bg-main blue-active
-                             blue-active blue-intense
-                             'alt-style -3))))
-;;;;; line numbers (display-line-numbers-mode and global variant)
-   `(line-number ((,class :inherit default :background ,bg-dim :foreground 
,fg-alt)))
-   `(line-number-current-line ((,class :inherit default :background ,bg-active 
:foreground ,fg-main)))
-;;;;; lsp-mode
-   `(lsp-face-highlight-read ((,class :inherit modus-theme-subtle-blue 
:underline t)))
-   `(lsp-face-highlight-textual ((,class :inherit modus-theme-subtle-blue)))
-   `(lsp-face-highlight-write ((,class :inherit (modus-theme-refine-blue 
bold))))
-   `(lsp-face-semhl-constant ((,class :foreground ,blue-alt-other)))
-   `(lsp-face-semhl-deprecated
-     ((,(append '((supports :underline (:style wave))) class)
-       :foreground ,yellow :underline (:style wave))
-      (,class :foreground ,yellow :underline t)))
-   `(lsp-face-semhl-enummember ((,class :foreground ,blue-alt-other)))
-   `(lsp-face-semhl-field ((,class :foreground ,cyan-alt)))
-   `(lsp-face-semhl-field-static ((,class :foreground ,cyan-alt :slant 
,modus-theme-slant)))
-   `(lsp-face-semhl-function ((,class :foreground ,magenta)))
-   `(lsp-face-semhl-method ((,class :foreground ,magenta)))
-   `(lsp-face-semhl-namespace ((,class ,@(modus-operandi-theme-bold-weight) 
:foreground ,magenta-alt)))
-   `(lsp-face-semhl-preprocessor ((,class :foreground ,red-alt-other)))
-   `(lsp-face-semhl-static-method ((,class :foreground ,magenta :slant 
,modus-theme-slant)))
-   `(lsp-face-semhl-type-class ((,class :foreground ,magenta-alt)))
-   `(lsp-face-semhl-type-enum ((,class :foreground ,magenta-alt)))
-   `(lsp-face-semhl-type-primitive ((,class :foreground ,magenta-alt :slant 
,modus-theme-slant)))
-   `(lsp-face-semhl-type-template ((,class :foreground ,magenta-alt :slant 
,modus-theme-slant)))
-   `(lsp-face-semhl-type-typedef ((,class :foreground ,magenta-alt :slant 
,modus-theme-slant)))
-   `(lsp-face-semhl-variable ((,class :foreground ,cyan)))
-   `(lsp-face-semhl-variable-local ((,class :foreground ,cyan)))
-   `(lsp-face-semhl-variable-parameter ((,class :foreground ,cyan-alt-other)))
-   `(lsp-lens-face ((,class :height 0.8 :foreground ,fg-alt)))
-   `(lsp-lens-mouse-face ((,class :height 0.8 :foreground ,blue-alt-other 
:underline t)))
-   `(lsp-ui-doc-background ((,class :background ,bg-alt)))
-   `(lsp-ui-doc-header ((,class :background ,bg-header :foreground 
,fg-header)))
-   `(lsp-ui-doc-url ((,class :inherit button :foreground ,blue-alt-other)))
-   `(lsp-ui-peek-filename ((,class :foreground ,fg-special-warm)))
-   `(lsp-ui-peek-footer ((,class :background ,bg-header :foreground 
,fg-header)))
-   `(lsp-ui-peek-header ((,class :background ,bg-header :foreground 
,fg-header)))
-   `(lsp-ui-peek-highlight ((,class :inherit modus-theme-subtle-blue)))
-   `(lsp-ui-peek-line-number ((,class :foreground ,fg-alt)))
-   `(lsp-ui-peek-list ((,class :background ,bg-dim)))
-   `(lsp-ui-peek-peek ((,class :background ,bg-alt)))
-   `(lsp-ui-peek-selection ((,class :inherit modus-theme-subtle-cyan)))
-   `(lsp-ui-sideline-code-action ((,class :foreground ,yellow)))
-   `(lsp-ui-sideline-current-symbol ((,class :inherit bold :height 0.99 :box 
(:line-width -1 :style nil) :foreground ,fg-main)))
-   `(lsp-ui-sideline-symbol ((,class :inherit bold :height 0.99 :box 
(:line-width -1 :style nil) :foreground ,fg-alt)))
-   `(lsp-ui-sideline-symbol-info ((,class :height 0.99 :slant italic)))
-;;;;; magit
-   `(magit-bisect-bad ((,class :foreground ,red-alt-other)))
-   `(magit-bisect-good ((,class :foreground ,green-alt-other)))
-   `(magit-bisect-skip ((,class :foreground ,yellow-alt-other)))
-   `(magit-blame-date ((,class :foreground ,blue)))
-   `(magit-blame-dimmed ((,class :foreground ,fg-alt)))
-   `(magit-blame-hash ((,class :foreground ,fg-special-warm)))
-   `(magit-blame-heading ((,class :background ,bg-alt)))
-   `(magit-blame-highlight ((,class :inherit modus-theme-nuanced-cyan)))
-   `(magit-blame-margin ((,class :inherit magit-blame-highlight)))
-   `(magit-blame-name ((,class :foreground ,magenta-alt-other)))
-   `(magit-blame-summary ((,class :foreground ,cyan-alt-other)))
-   `(magit-branch-current ((,class :foreground ,blue-alt-other :box t)))
-   `(magit-branch-local ((,class :foreground ,blue-alt)))
-   `(magit-branch-remote ((,class :foreground ,magenta-alt)))
-   `(magit-branch-remote-head ((,class :foreground ,magenta-alt-other :box t)))
-   `(magit-branch-upstream ((,class :slant italic)))
-   `(magit-cherry-equivalent ((,class :background ,bg-main :foreground 
,magenta-intense)))
-   `(magit-cherry-unmatched ((,class :background ,bg-main :foreground 
,cyan-intense)))
-   ;; NOTE: here we break from the pattern of inheriting from the
-   ;; modus-theme-diff-* faces, though only for the standard actions,
-   ;; not the highlighted ones.  This is because Magit's interaction
-   ;; model relies on highlighting the current diff hunk.
-   `(magit-diff-added ((,class ,@(modus-operandi-theme-diff
-                                  bg-main green
-                                  bg-diff-added fg-diff-added
-                                  green-nuanced-bg fg-diff-added))))
-   `(magit-diff-added-highlight ((,class :inherit 
modus-theme-diff-focus-added)))
-   `(magit-diff-base ((,class ,@(modus-operandi-theme-diff
-                                 bg-main yellow
-                                 bg-diff-changed fg-diff-changed
-                                 yellow-nuanced-bg fg-diff-changed))))
-   `(magit-diff-base-highlight ((,class :inherit 
modus-theme-diff-focus-changed)))
-   `(magit-diff-context ((,class :foreground ,fg-unfocused)))
-   `(magit-diff-context-highlight ((,class ,@(modus-operandi-theme-diff
-                                              bg-dim fg-dim
-                                              bg-inactive fg-inactive
-                                              bg-dim fg-alt))))
-   `(magit-diff-file-heading ((,class :inherit bold :foreground 
,fg-special-cold)))
-   `(magit-diff-file-heading-highlight ((,class :inherit 
(modus-theme-special-cold bold))))
-   `(magit-diff-file-heading-selection ((,class :inherit 
modus-theme-refine-cyan)))
-   ;; NOTE: here we break from the pattern of inheriting from the
-   ;; modus-theme-diff-* faces.
-   `(magit-diff-hunk-heading ((,class :inherit bold :background ,bg-active
-                                      :foreground ,fg-inactive)))
-   `(magit-diff-hunk-heading-highlight ((,class :inherit bold :background 
,bg-diff-heading
-                                                :foreground ,fg-diff-heading)))
-   `(magit-diff-hunk-heading-selection ((,class :inherit 
modus-theme-refine-blue)))
-   `(magit-diff-hunk-region ((,class :inherit bold)))
-   `(magit-diff-lines-boundary ((,class :background ,fg-main)))
-   `(magit-diff-lines-heading ((,class :inherit modus-theme-refine-magenta)))
-   `(magit-diff-removed ((,class ,@(modus-operandi-theme-diff
-                                    bg-main red
-                                    bg-diff-removed fg-diff-removed
-                                    red-nuanced-bg fg-diff-removed))))
-   `(magit-diff-removed-highlight ((,class :inherit 
modus-theme-diff-focus-removed)))
-   `(magit-diffstat-added ((,class :foreground ,green)))
-   `(magit-diffstat-removed ((,class :foreground ,red)))
-   `(magit-dimmed ((,class :foreground ,fg-unfocused)))
-   `(magit-filename ((,class :foreground ,fg-special-cold)))
-   `(magit-hash ((,class :foreground ,fg-alt)))
-   `(magit-head ((,class :inherit magit-branch-local)))
-   `(magit-header-line ((,class :inherit bold :foreground ,magenta-active)))
-   `(magit-header-line-key ((,class :inherit bold :foreground ,red-active)))
-   `(magit-header-line-log-select ((,class :inherit bold :foreground 
,fg-main)))
-   `(magit-keyword ((,class :foreground ,magenta)))
-   `(magit-keyword-squash ((,class :inherit bold :foreground 
,yellow-alt-other)))
-   `(magit-log-author ((,class :foreground ,cyan)))
-   `(magit-log-date ((,class :foreground ,fg-alt)))
-   `(magit-log-graph ((,class :foreground ,fg-dim)))
-   `(magit-mode-line-process ((,class :inherit bold :foreground ,blue-active)))
-   `(magit-mode-line-process-error ((,class :inherit bold :foreground 
,red-active)))
-   `(magit-process-ng ((,class :inherit error)))
-   `(magit-process-ok ((,class :inherit success)))
-   `(magit-reflog-amend ((,class :background ,bg-main :foreground 
,magenta-intense)))
-   `(magit-reflog-checkout ((,class :background ,bg-main :foreground 
,blue-intense)))
-   `(magit-reflog-cherry-pick ((,class :background ,bg-main :foreground 
,green-intense)))
-   `(magit-reflog-commit ((,class :background ,bg-main :foreground 
,green-intense)))
-   `(magit-reflog-merge ((,class :background ,bg-main :foreground 
,green-intense)))
-   `(magit-reflog-other ((,class :background ,bg-main :foreground 
,cyan-intense)))
-   `(magit-reflog-rebase ((,class :background ,bg-main :foreground 
,magenta-intense)))
-   `(magit-reflog-remote ((,class :background ,bg-main :foreground 
,cyan-intense)))
-   `(magit-reflog-reset ((,class :background ,bg-main :foreground 
,red-intense)))
-   `(magit-refname ((,class :foreground ,fg-alt)))
-   `(magit-refname-pullreq ((,class :foreground ,fg-alt)))
-   `(magit-refname-stash ((,class :foreground ,fg-alt)))
-   `(magit-refname-wip ((,class :foreground ,fg-alt)))
-   `(magit-section ((,class :background ,bg-dim :foreground ,fg-main)))
-   `(magit-section-heading ((,class :inherit bold :foreground ,cyan)))
-   `(magit-section-heading-selection ((,class :inherit 
(modus-theme-refine-cyan bold))))
-   `(magit-section-highlight ((,class :background ,bg-alt)))
-   `(magit-sequence-done ((,class :foreground ,green-alt)))
-   `(magit-sequence-drop ((,class :foreground ,red-alt)))
-   `(magit-sequence-exec ((,class :foreground ,magenta-alt)))
-   `(magit-sequence-head ((,class :foreground ,cyan-alt)))
-   `(magit-sequence-onto ((,class :foreground ,fg-alt)))
-   `(magit-sequence-part ((,class :foreground ,yellow-alt)))
-   `(magit-sequence-pick ((,class :foreground ,blue-alt)))
-   `(magit-sequence-stop ((,class :foreground ,red)))
-   `(magit-signature-bad ((,class :inherit bold :foreground ,red)))
-   `(magit-signature-error ((,class :foreground ,red-alt)))
-   `(magit-signature-expired ((,class :foreground ,yellow)))
-   `(magit-signature-expired-key ((,class :foreground ,yellow)))
-   `(magit-signature-good ((,class :foreground ,green)))
-   `(magit-signature-revoked ((,class :foreground ,magenta)))
-   `(magit-signature-untrusted ((,class :foreground ,cyan)))
-   `(magit-tag ((,class :foreground ,yellow-alt-other)))
-;;;;; magit-imerge
-   `(magit-imerge-overriding-value ((,class :inherit bold :foreground 
,red-alt)))
-;;;;; man
-   `(Man-overstrike ((,class :inherit bold :foreground ,magenta)))
-   `(Man-reverse ((,class :inherit modus-theme-subtle-magenta)))
-   `(Man-underline ((,class :foreground ,cyan :underline t)))
-;;;;; markdown-mode
-   `(markdown-blockquote-face ((,class :foreground ,fg-special-cold :slant 
,modus-theme-slant)))
-   `(markdown-bold-face ((,class :inherit bold)))
-   `(markdown-code-face ((,class ,@(modus-operandi-theme-mixed-fonts))))
-   `(markdown-comment-face ((,class :foreground ,fg-alt :slant 
,modus-theme-slant)))
-   `(markdown-footnote-marker-face ((,class :inherit bold :foreground 
,cyan-alt)))
-   `(markdown-footnote-text-face ((,class :foreground ,fg-main :slant 
,modus-theme-slant)))
-   `(markdown-gfm-checkbox-face ((,class :foreground ,cyan-alt-other)))
-   `(markdown-header-delimiter-face ((,class 
,@(modus-operandi-theme-bold-weight) :foreground ,fg-dim)))
-   `(markdown-header-face ((t nil)))
-   `(markdown-header-face-1 ((,class :inherit modus-theme-heading-1)))
-   `(markdown-header-face-2 ((,class :inherit modus-theme-heading-2)))
-   `(markdown-header-face-3 ((,class :inherit modus-theme-heading-3)))
-   `(markdown-header-face-4 ((,class :inherit modus-theme-heading-4)))
-   `(markdown-header-face-5 ((,class :inherit modus-theme-heading-5)))
-   `(markdown-header-face-6 ((,class :inherit modus-theme-heading-6)))
-   `(markdown-header-rule-face ((,class :inherit bold :foreground 
,fg-special-warm)))
-   `(markdown-hr-face ((,class :inherit bold :foreground ,fg-special-warm)))
-   `(markdown-html-attr-name-face ((,class ,@(modus-operandi-theme-mixed-fonts)
-                                           :foreground ,cyan)))
-   `(markdown-html-attr-value-face ((,class 
,@(modus-operandi-theme-mixed-fonts)
-                                            :foreground ,blue)))
-   `(markdown-html-entity-face ((,class ,@(modus-operandi-theme-mixed-fonts)
-                                        :foreground ,cyan)))
-   `(markdown-html-tag-delimiter-face ((,class 
,@(modus-operandi-theme-mixed-fonts)
-                                               :foreground ,fg-special-mild)))
-   `(markdown-html-tag-name-face ((,class ,@(modus-operandi-theme-mixed-fonts)
-                                          :foreground ,magenta-alt)))
-   `(markdown-inline-code-face ((,class ,@(modus-operandi-theme-mixed-fonts)
-                                        :foreground ,magenta)))
-   `(markdown-italic-face ((,class :foreground ,fg-special-cold :slant 
italic)))
-   `(markdown-language-info-face ((,class ,@(modus-operandi-theme-mixed-fonts)
-                                          :foreground ,fg-special-cold)))
-   `(markdown-language-keyword-face ((,class 
,@(modus-operandi-theme-mixed-fonts)
-                                             :foreground ,green-alt-other)))
-   `(markdown-line-break-face ((,class :inherit modus-theme-refine-cyan 
:underline t)))
-   `(markdown-link-face ((,class :inherit link)))
-   `(markdown-link-title-face ((,class :foreground ,fg-special-cold :slant 
,modus-theme-slant)))
-   `(markdown-list-face ((,class :foreground ,fg-dim)))
-   `(markdown-markup-face ((,class :foreground ,fg-alt)))
-   `(markdown-math-face ((,class :foreground ,magenta-alt-other)))
-   `(markdown-metadata-key-face ((,class :foreground ,cyan-alt-other)))
-   `(markdown-metadata-value-face ((,class :foreground ,blue-alt)))
-   `(markdown-missing-link-face ((,class :inherit bold :foreground ,yellow)))
-   `(markdown-plain-url-face ((,class :inherit markdown-link-face)))
-   `(markdown-pre-face ((,class ,@(and (>= emacs-major-version 27) '(:extend 
t))
-                                ,@(modus-operandi-theme-mixed-fonts)
-                                :background ,bg-dim
-                                :foreground ,fg-special-mild)))
-   `(markdown-reference-face ((,class :inherit markdown-markup-face)))
-   `(markdown-strike-through-face ((,class :strike-through t)))
-   `(markdown-table-face ((,class ,@(modus-operandi-theme-mixed-fonts)
-                                  :foreground ,fg-special-cold)))
-   `(markdown-url-face ((,class :foreground ,blue-alt)))
-;;;;; markup-faces (`adoc-mode')
-   `(markup-anchor-face ((,class :foreground ,fg-inactive)))
-   `(markup-attribute-face ((,class :foreground ,fg-inactive :slant italic)))
-   `(markup-big-face ((,class :height 1.3 :foreground ,blue-nuanced)))
-   `(markup-bold-face ((,class :inherit bold :foreground ,red-nuanced)))
-   `(markup-code-face ((,class :inherit fixed-pitch :foreground ,magenta)))
-   `(markup-command-face ((,class :foreground ,fg-inactive)))
-   `(markup-comment-face ((,class :foreground ,fg-alt :slant 
,modus-theme-slant)))
-   `(markup-complex-replacement-face ((,class :box (:line-width 2 :color nil 
:style released-button)
-                                              :inherit 
modus-theme-refine-magenta)))
-   `(markup-emphasis-face ((,class :foreground ,fg-special-cold :slant 
italic)))
-   `(markup-error-face ((,class :inherit bold :foreground ,red)))
-   `(markup-gen-face ((,class :foreground ,magenta-alt)))
-   `(markup-internal-reference-face ((,class :inherit button :foreground 
,fg-inactive)))
-   `(markup-italic-face ((,class :foreground ,fg-special-cold :slant italic)))
-   `(markup-list-face ((,class :inherit modus-theme-special-calm)))
-   `(markup-meta-face ((,class :foreground ,fg-inactive)))
-   `(markup-meta-hide-face ((,class :foreground ,fg-alt)))
-   `(markup-passthrough-face ((,class :inherit fixed-pitch :foreground ,cyan)))
-   `(markup-preprocessor-face ((,class :foreground ,red-alt-other)))
-   `(markup-replacement-face ((,class :foreground ,yellow-alt-other)))
-   `(markup-secondary-text-face ((,class :height 0.8 :foreground 
,magenta-nuanced)))
-   `(markup-small-face ((,class :height 0.8 :foreground ,fg-main)))
-   `(markup-strong-face ((,class :inherit bold :foreground ,red-nuanced)))
-   `(markup-subscript-face ((,class :height 0.8 :foreground ,fg-special-cold)))
-   `(markup-superscript-face ((,class :height 0.8 :foreground 
,fg-special-cold)))
-   `(markup-table-cell-face ((,class :inherit modus-theme-special-cold)))
-   `(markup-table-face ((,class :inherit modus-theme-subtle-cyan)))
-   `(markup-table-row-face ((,class :inherit modus-theme-subtle-cyan)))
-   `(markup-title-0-face ((,class :height 3.0 :foreground ,blue-nuanced)))
-   `(markup-title-1-face ((,class :height 2.4 :foreground ,blue-nuanced)))
-   `(markup-title-2-face ((,class :height 1.8 :foreground ,blue-nuanced)))
-   `(markup-title-3-face ((,class :height 1.4 :foreground ,blue-nuanced)))
-   `(markup-title-4-face ((,class :height 1.2 :foreground ,blue-nuanced)))
-   `(markup-title-5-face ((,class :height 1.2 :foreground ,blue-nuanced 
:underline t)))
-   `(markup-value-face ((,class :foreground ,fg-inactive)))
-   `(markup-verbatim-face ((,class :inherit modus-theme-special-mild)))
-;;;;; mentor
-   `(mentor-download-message ((,class :foreground ,fg-special-warm)))
-   `(mentor-download-name ((,class :foreground ,fg-special-cold)))
-   `(mentor-download-progress ((,class :foreground ,blue-alt-other)))
-   `(mentor-download-size ((,class :foreground ,magenta-alt-other)))
-   `(mentor-download-speed-down ((,class :foreground ,cyan-alt)))
-   `(mentor-download-speed-up ((,class :foreground ,red-alt)))
-   `(mentor-download-state ((,class :foreground ,yellow-alt)))
-   `(mentor-highlight-face ((,class :inherit modus-theme-subtle-blue)))
-   `(mentor-tracker-name ((,class :foreground ,magenta-alt)))
-;;;;; messages
-   `(message-cited-text-1 ((,class :foreground ,blue-alt)))
-   `(message-cited-text-2 ((,class :foreground ,red-alt)))
-   `(message-cited-text-3 ((,class :foreground ,green-alt)))
-   `(message-cited-text-4 ((,class :foreground ,magenta-alt)))
-   `(message-header-cc ((,class :inherit bold :foreground ,cyan-alt)))
-   `(message-header-name ((,class :foreground ,green-alt-other)))
-   `(message-header-newsgroups ((,class :inherit bold :foreground ,green-alt)))
-   `(message-header-other ((,class :inherit bold :foreground ,cyan-alt-other)))
-   `(message-header-subject ((,class :inherit bold :foreground 
,magenta-alt-other)))
-   `(message-header-to ((,class :inherit bold :foreground ,blue)))
-   `(message-header-xheader ((,class :foreground ,cyan)))
-   `(message-mml ((,class :foreground ,fg-special-warm)))
-   `(message-separator ((,class :inherit modus-theme-intense-neutral)))
-;;;;; minibuffer-line
-   `(minibuffer-line ((,class :foreground ,fg-main)))
-;;;;; minimap
-   `(minimap-active-region-background ((,class :background ,bg-active)))
-   `(minimap-current-line-face ((,class :background ,cyan-intense-bg 
:foreground ,fg-main)))
-;;;;; modeline
-   `(mode-line ((,class ,@(modus-operandi-theme-mode-line-attrs
-                           fg-active bg-active fg-dim bg-active
-                           fg-alt bg-active 'alt-style nil bg-main))))
-   `(mode-line-buffer-id ((,class :inherit bold)))
-   `(mode-line-emphasis ((,class :inherit bold :foreground ,blue-active)))
-   `(mode-line-highlight ((,class :inherit modus-theme-active-blue :box 
(:line-width -1 :style pressed-button))))
-   `(mode-line-inactive ((,class ,@(modus-operandi-theme-mode-line-attrs
-                                    fg-inactive bg-inactive fg-alt bg-dim
-                                    bg-region bg-active))))
-;;;;; mood-line
-   `(mood-line-modified ((,class :foreground ,magenta-active)))
-   `(mood-line-status-error ((,class :inherit bold :foreground ,red-active)))
-   `(mood-line-status-info ((,class :foreground ,cyan-active)))
-   `(mood-line-status-neutral ((,class :foreground ,blue-active)))
-   `(mood-line-status-success ((,class :foreground ,green-active)))
-   `(mood-line-status-warning ((,class :inherit bold :foreground 
,yellow-active)))
-   `(mood-line-unimportant ((,class :foreground ,fg-inactive)))
-;;;;; mpdel
-   `(mpdel-browser-directory-face ((,class :foreground ,blue)))
-   `(mpdel-playlist-current-song-face ((,class :inherit bold :foreground 
,blue-alt-other)))
-;;;;; mu4e
-   `(mu4e-attach-number-face ((,class :inherit bold :foreground ,cyan-alt)))
-   `(mu4e-cited-1-face ((,class :foreground ,blue-alt)))
-   `(mu4e-cited-2-face ((,class :foreground ,red-alt)))
-   `(mu4e-cited-3-face ((,class :foreground ,green-alt)))
-   `(mu4e-cited-4-face ((,class :foreground ,magenta-alt)))
-   `(mu4e-cited-5-face ((,class :foreground ,yellow-alt)))
-   `(mu4e-cited-6-face ((,class :foreground ,cyan-alt)))
-   `(mu4e-cited-7-face ((,class :foreground ,magenta)))
-   `(mu4e-compose-header-face ((,class :inherit mu4e-compose-separator-face)))
-   `(mu4e-compose-separator-face ((,class :inherit 
modus-theme-intense-neutral)))
-   `(mu4e-contact-face ((,class :inherit bold :foreground ,cyan-alt-other)))
-   `(mu4e-context-face ((,class :foreground ,blue-active)))
-   `(mu4e-draft-face ((,class :foreground ,magenta-alt)))
-   `(mu4e-flagged-face ((,class :foreground ,red-alt)))
-   `(mu4e-footer-face ((,class :foreground ,fg-special-cold :slant 
,modus-theme-slant)))
-   `(mu4e-forwarded-face ((,class :foreground ,magenta-alt-other)))
-   `(mu4e-header-face ((,class :foreground ,fg-alt)))
-   `(mu4e-header-highlight-face ((,class :inherit modus-theme-hl-line)))
-   `(mu4e-header-key-face ((,class :foreground ,cyan)))
-   `(mu4e-header-marks-face ((,class :inherit bold :foreground ,magenta-alt)))
-   `(mu4e-header-title-face ((,class :foreground ,fg-special-mild)))
-   `(mu4e-header-value-face ((,class :inherit bold :foreground 
,magenta-alt-other)))
-   `(mu4e-highlight-face ((,class :inherit bold :foreground ,blue-alt-other)))
-   `(mu4e-link-face ((,class :inherit link)))
-   `(mu4e-modeline-face ((,class :foreground ,magenta-active)))
-   `(mu4e-moved-face ((,class :foreground ,yellow :slant ,modus-theme-slant)))
-   `(mu4e-ok-face ((,class :inherit bold :foreground ,green)))
-   `(mu4e-region-code ((,class :inherit modus-theme-special-calm)))
-   `(mu4e-replied-face ((,class :foreground ,blue-faint)))
-   `(mu4e-special-header-value-face ((,class :inherit bold :foreground 
,blue-alt-other)))
-   `(mu4e-system-face ((,class :foreground ,fg-mark-del :slant 
,modus-theme-slant)))
-   `(mu4e-title-face ((,class :foreground ,fg-main)))
-   `(mu4e-trashed-face ((,class :foreground ,red)))
-   `(mu4e-unread-face ((,class :inherit bold :foreground ,fg-main)))
-   `(mu4e-url-number-face ((,class :inherit bold :foreground ,cyan-alt-other)))
-   `(mu4e-view-body-face ((,class :foreground ,fg-main)))
-   `(mu4e-warning-face ((,class :inherit warning)))
-;;;;; mu4e-conversation
-   `(mu4e-conversation-header ((,class :inherit modus-theme-special-cold)))
-   `(mu4e-conversation-sender-1 ((,class :foreground ,fg-special-warm)))
-   `(mu4e-conversation-sender-2 ((,class :foreground ,fg-special-cold)))
-   `(mu4e-conversation-sender-3 ((,class :foreground ,fg-special-mild)))
-   `(mu4e-conversation-sender-4 ((,class :foreground ,fg-alt)))
-   `(mu4e-conversation-sender-5 ((,class :foreground ,yellow-refine-fg)))
-   `(mu4e-conversation-sender-6 ((,class :foreground ,cyan-refine-fg)))
-   `(mu4e-conversation-sender-7 ((,class :foreground ,green-refine-fg)))
-   `(mu4e-conversation-sender-8 ((,class :foreground ,blue-refine-fg)))
-   `(mu4e-conversation-sender-me ((,class :foreground ,fg-main)))
-   `(mu4e-conversation-unread ((,class :inherit bold)))
-;;;;; multiple-cursors
-   `(mc/cursor-bar-face ((,class :height 1 :background ,fg-main)))
-   `(mc/cursor-face ((,class :inverse-video t)))
-   `(mc/region-face ((,class :inherit region)))
-;;;;; neotree
-   `(neo-banner-face ((,class :foreground ,magenta)))
-   `(neo-button-face ((,class :inherit button)))
-   `(neo-dir-link-face ((,class :inherit bold :foreground ,blue)))
-   `(neo-expand-btn-face ((,class :foreground ,cyan)))
-   `(neo-file-link-face ((,class :foreground ,fg-main)))
-   `(neo-header-face ((,class :inherit bold :foreground ,fg-main)))
-   `(neo-root-dir-face ((,class :inherit bold :foreground ,cyan-alt)))
-   `(neo-vc-added-face ((,class :foreground ,green)))
-   `(neo-vc-conflict-face ((,class :inherit bold :foreground ,red)))
-   `(neo-vc-default-face ((,class :foreground ,fg-main)))
-   `(neo-vc-edited-face ((,class :foreground ,yellow)))
-   `(neo-vc-ignored-face ((,class :foreground ,fg-inactive)))
-   `(neo-vc-missing-face ((,class :foreground ,red-alt)))
-   `(neo-vc-needs-merge-face ((,class :foreground ,magenta-alt)))
-   `(neo-vc-needs-update-face ((,class :underline t)))
-   `(neo-vc-removed-face ((,class :strike-through t)))
-   `(neo-vc-unlocked-changes-face ((,class :inherit modus-theme-refine-blue)))
-   `(neo-vc-up-to-date-face ((,class :foreground ,fg-alt)))
-   `(neo-vc-user-face ((,class :foreground ,magenta)))
-;;;;; no-emoji
-   `(no-emoji ((,class :foreground ,cyan)))
-;;;;; notmuch
-   `(notmuch-crypto-decryption ((,class :inherit modus-theme-refine-magenta)))
-   `(notmuch-crypto-part-header ((,class :foreground ,magenta-alt-other)))
-   `(notmuch-crypto-signature-bad ((,class :inherit modus-theme-intense-red)))
-   `(notmuch-crypto-signature-good ((,class :inherit 
modus-theme-refine-green)))
-   `(notmuch-crypto-signature-good-key ((,class :inherit 
modus-theme-refine-yellow)))
-   `(notmuch-crypto-signature-unknown ((,class :inherit 
modus-theme-refine-red)))
-   `(notmuch-hello-logo-background ((,class :background ,bg-main)))
-   `(notmuch-message-summary-face ((,class :inherit modus-theme-nuanced-cyan)))
-   `(notmuch-search-flagged-face ((,class :foreground ,red-alt)))
-   `(notmuch-search-matching-authors ((,class :foreground ,fg-main)))
-   `(notmuch-search-non-matching-authors ((,class :foreground ,fg-alt)))
-   `(notmuch-search-unread-face ((,class :inherit bold)))
-   `(notmuch-tag-added
-     ((,(append '((supports :underline (:style wave))) class)
-       :underline (:color ,green :style wave))
-      (,class :foreground ,green :underline t)))
-   `(notmuch-tag-deleted
-     ((,(append '((supports :underline (:style wave))) class)
-       :underline (:color ,red :style wave))
-      (,class :foreground ,red :underline t)))
-   `(notmuch-tag-face ((,class :inherit bold :foreground ,blue-alt)))
-   `(notmuch-tag-flagged ((,class :foreground ,red-alt)))
-   `(notmuch-tag-unread ((,class :foreground ,magenta-alt)))
-   `(notmuch-tree-match-author-face ((,class :foreground ,fg-special-cold)))
-   `(notmuch-tree-match-face ((,class :foreground ,fg-main)))
-   `(notmuch-tree-match-tag-face ((,class :inherit bold :foreground 
,blue-alt)))
-   `(notmuch-tree-no-match-face ((,class :foreground ,fg-alt)))
-   `(notmuch-wash-cited-text ((,class :foreground ,cyan)))
-   `(notmuch-wash-toggle-button ((,class :background ,bg-alt :foreground 
,fg-alt)))
-;;;;; num3-mode
-   `(num3-face-even ((,class :inherit bold :background ,bg-alt)))
-;;;;; nxml-mode
-   `(nxml-attribute-colon ((,class :foreground ,fg-main)))
-   `(nxml-attribute-local-name ((,class 
,@(modus-operandi-theme-syntax-foreground
-                                           cyan-alt cyan-alt-faint))))
-   `(nxml-attribute-prefix ((,class ,@(modus-operandi-theme-syntax-foreground
-                                       cyan-alt-other cyan-alt-other-faint)
-                                    ,@(modus-operandi-theme-bold-weight))))
-   `(nxml-attribute-value ((,class ,@(modus-operandi-theme-syntax-foreground
-                                      blue blue-faint))))
-   `(nxml-cdata-section-CDATA ((,class 
,@(modus-operandi-theme-syntax-foreground
-                                          red-alt red-alt-faint)
-                                       ,@(modus-operandi-theme-bold-weight))))
-   `(nxml-cdata-section-delimiter ((,class 
,@(modus-operandi-theme-syntax-foreground
-                                              red-alt red-alt-faint))))
-   `(nxml-char-ref-delimiter ((,class ,@(modus-operandi-theme-syntax-foreground
-                                         green-alt-other 
green-alt-other-faint))))
-   `(nxml-char-ref-number ((,class ,@(modus-operandi-theme-syntax-foreground
-                                      green-alt-other green-alt-other-faint)
-                                   ,@(modus-operandi-theme-bold-weight))))
-   `(nxml-delimited-data ((,class :foreground ,fg-special-cold :slant 
,modus-theme-slant)))
-   `(nxml-delimiter ((,class :foreground ,fg-dim)))
-   `(nxml-element-colon ((,class :foreground ,fg-main)))
-   `(nxml-element-local-name ((,class ,@(modus-operandi-theme-syntax-foreground
-                                         magenta magenta-faint))))
-   `(nxml-element-prefix ((,class ,@(modus-operandi-theme-syntax-foreground
-                                     magenta-alt magenta-alt-faint)
-                                  ,@(modus-operandi-theme-bold-weight))))
-   `(nxml-entity-ref-delimiter ((,class 
,@(modus-operandi-theme-syntax-foreground
-                                           green-alt-other 
green-alt-other-faint))))
-   `(nxml-entity-ref-name ((,class ,@(modus-operandi-theme-syntax-foreground
-                                      green-alt-other green-alt-other-faint)
-                                   ,@(modus-operandi-theme-bold-weight))))
-   `(nxml-glyph ((,class :inherit modus-theme-intense-neutral)))
-   `(nxml-hash ((,class ,@(modus-operandi-theme-syntax-foreground
-                           blue-alt blue-alt-faint)
-                        ,@(modus-operandi-theme-bold-weight))))
-   `(nxml-heading ((,class :inherit bold)))
-   `(nxml-name ((,class ,@(modus-operandi-theme-syntax-foreground
-                           magenta-alt magenta-alt-faint)
-                        ,@(modus-operandi-theme-bold-weight))))
-   `(nxml-namespace-attribute-colon ((,class :foreground ,fg-main)))
-   `(nxml-namespace-attribute-prefix ((,class 
,@(modus-operandi-theme-syntax-foreground
-                                                 cyan cyan-faint))))
-   `(nxml-processing-instruction-target ((,class 
,@(modus-operandi-theme-syntax-foreground
-                                                    magenta-alt-other 
magenta-alt-other-faint)
-                                                 
,@(modus-operandi-theme-bold-weight))))
-   `(nxml-prolog-keyword ((,class ,@(modus-operandi-theme-syntax-foreground
-                                     magenta-alt-other magenta-alt-other-faint)
-                                  ,@(modus-operandi-theme-bold-weight))))
-   `(nxml-ref ((,class ,@(modus-operandi-theme-syntax-foreground
-                          green-alt-other green-alt-other-faint)
-                       ,@(modus-operandi-theme-bold-weight))))
-;;;;; objed
-   `(objed-hl ((,class :background ,(if modus-operandi-theme-intense-hl-line
-                                        bg-hl-alt-intense bg-hl-alt))))
-   `(objed-mark ((,class :background ,bg-active)))
-   `(objed-mode-line ((,class :foreground ,cyan-active)))
-;;;;; orderless
-   `(orderless-match-face-0 ((,class :inherit bold
-                                     
,@(modus-operandi-theme-standard-completions
-                                        blue-alt-other blue-nuanced-bg
-                                        blue-refine-bg blue-refine-fg))))
-   `(orderless-match-face-1 ((,class :inherit bold
-                                     
,@(modus-operandi-theme-standard-completions
-                                        magenta-alt magenta-nuanced-bg
-                                        magenta-refine-bg magenta-refine-fg))))
-   `(orderless-match-face-2 ((,class :inherit bold
-                                     
,@(modus-operandi-theme-standard-completions
-                                        green green-nuanced-bg
-                                        green-refine-bg green-refine-fg))))
-   `(orderless-match-face-3 ((,class :inherit bold
-                                     
,@(modus-operandi-theme-standard-completions
-                                        yellow yellow-nuanced-bg
-                                        yellow-refine-bg yellow-refine-fg))))
-;;;;; org
-   `(org-agenda-calendar-event ((,class :foreground ,fg-main)))
-   `(org-agenda-calendar-sexp ((,class :foreground ,cyan-alt)))
-   `(org-agenda-clocking ((,class :inherit modus-theme-special-cold
-                                  ,@(and (>= emacs-major-version 27) '(:extend 
t)))))
-   `(org-agenda-column-dateline ((,class :background ,bg-alt)))
-   `(org-agenda-current-time ((,class :inherit bold :foreground 
,blue-alt-other)))
-   `(org-agenda-date ((,class :foreground ,cyan)))
-   `(org-agenda-date-today ((,class :inherit bold :foreground ,fg-main 
:underline t)))
-   `(org-agenda-date-weekend ((,class :foreground ,cyan-alt-other)))
-   `(org-agenda-diary ((,class :foreground ,fg-main)))
-   `(org-agenda-dimmed-todo-face ((,class :inherit bold :foreground ,fg-alt)))
-   `(org-agenda-done ((,class :foreground ,green-alt)))
-   `(org-agenda-filter-category ((,class :inherit bold :foreground 
,magenta-active)))
-   `(org-agenda-filter-effort ((,class :inherit bold :foreground 
,magenta-active)))
-   `(org-agenda-filter-regexp ((,class :inherit bold :foreground 
,magenta-active)))
-   `(org-agenda-filter-tags ((,class :inherit bold :foreground 
,magenta-active)))
-   `(org-agenda-restriction-lock ((,class :background ,bg-dim :foreground 
,fg-dim)))
-   `(org-agenda-structure ((,class :foreground ,blue-alt)))
-   `(org-archived ((,class :background ,bg-alt :foreground ,fg-alt)))
-   `(org-block ((,class ,@(modus-operandi-theme-mixed-fonts)
-                        ,@(modus-operandi-theme-org-block bg-dim)
-                        :foreground ,fg-main)))
-   `(org-block-begin-line ((,class ,@(modus-operandi-theme-mixed-fonts)
-                                   ,@(modus-operandi-theme-org-block-delim
-                                      bg-dim fg-special-cold
-                                      bg-alt fg-special-mild))))
-   `(org-block-end-line ((,class :inherit org-block-begin-line)))
-   `(org-checkbox ((,class :box (:line-width 1 :color ,bg-active)
-                           :background ,bg-inactive :foreground ,fg-active)))
-   `(org-checkbox-statistics-done ((,class :inherit org-done)))
-   `(org-checkbox-statistics-todo ((,class :inherit org-todo)))
-   `(org-clock-overlay ((,class :inherit modus-theme-special-cold)))
-   `(org-code ((,class ,@(modus-operandi-theme-mixed-fonts) :foreground 
,magenta)))
-   `(org-column ((,class :background ,bg-alt)))
-   `(org-column-title ((,class :inherit bold :underline t :background 
,bg-alt)))
-   `(org-date ((,class :inherit (button fixed-pitch) :foreground 
,cyan-alt-other)))
-   `(org-date-selected ((,class :inherit bold :foreground ,blue-alt 
:inverse-video t)))
-   `(org-document-info ((,class :foreground ,fg-special-cold)))
-   `(org-document-info-keyword ((,class ,@(modus-operandi-theme-mixed-fonts)
-                                        :foreground ,fg-alt)))
-   `(org-document-title ((,class :inherit (bold ,modus-theme-variable-pitch) 
:foreground ,fg-special-cold
-                                 ,@(modus-operandi-theme-scale 
modus-operandi-theme-scale-5))))
-   `(org-done ((,class :box ,bg-region :background ,bg-dim :foreground 
,green)))
-   `(org-drawer ((,class ,@(modus-operandi-theme-mixed-fonts)
-                         :foreground ,cyan)))
-   `(org-ellipsis ((,class :foreground nil))) ; inherits from the heading's 
colour
-   `(org-footnote ((,class :inherit button :foreground ,blue-alt)))
-   `(org-formula ((,class ,@(modus-operandi-theme-mixed-fonts)
-                          :foreground ,red-alt)))
-   `(org-habit-alert-face ((,class :inherit modus-theme-intense-yellow)))
-   `(org-habit-alert-future-face ((,class :inherit modus-theme-refine-yellow)))
-   `(org-habit-clear-face ((,class :inherit modus-theme-intense-magenta)))
-   `(org-habit-clear-future-face ((,class :inherit 
modus-theme-refine-magenta)))
-   `(org-habit-overdue-face ((,class :inherit modus-theme-intense-red)))
-   `(org-habit-overdue-future-face ((,class :inherit modus-theme-refine-red)))
-   `(org-habit-ready-face ((,class :inherit modus-theme-intense-blue)))
-   `(org-habit-ready-future-face ((,class :inherit modus-theme-refine-blue)))
-   `(org-headline-done ((,class :inherit ,modus-theme-variable-pitch 
:foreground ,green-nuanced)))
-   `(org-headline-todo ((,class :inherit ,modus-theme-variable-pitch 
:foreground ,red-nuanced)))
-   `(org-hide ((,class :foreground ,bg-main)))
-   `(org-indent ((,class :inherit (fixed-pitch org-hide))))
-   `(org-latex-and-related ((,class :foreground ,magenta-refine-fg)))
-   `(org-level-1 ((,class :inherit modus-theme-heading-1)))
-   `(org-level-2 ((,class :inherit modus-theme-heading-2)))
-   `(org-level-3 ((,class :inherit modus-theme-heading-3)))
-   `(org-level-4 ((,class :inherit modus-theme-heading-4)))
-   `(org-level-5 ((,class :inherit modus-theme-heading-5)))
-   `(org-level-6 ((,class :inherit modus-theme-heading-6)))
-   `(org-level-7 ((,class :inherit modus-theme-heading-7)))
-   `(org-level-8 ((,class :inherit modus-theme-heading-8)))
-   `(org-link ((,class :inherit link)))
-   `(org-list-dt ((,class :inherit bold)))
-   `(org-macro ((,class :background ,blue-nuanced-bg :foreground 
,magenta-alt-other)))
-   `(org-meta-line ((,class ,@(modus-operandi-theme-mixed-fonts) :foreground 
,fg-alt)))
-   `(org-mode-line-clock ((,class :foreground ,fg-main)))
-   `(org-mode-line-clock-overrun ((,class :inherit modus-theme-active-red)))
-   `(org-priority ((,class :box ,bg-region :background ,bg-dim :foreground 
,magenta)))
-   `(org-property-value ((,class ,@(modus-operandi-theme-mixed-fonts)
-                                 :foreground ,cyan-alt-other)))
-   `(org-quote ((,class ,@(modus-operandi-theme-org-block bg-dim)
-                        :foreground ,fg-special-cold :slant 
,modus-theme-slant)))
-   `(org-scheduled ((,class :foreground ,fg-special-warm)))
-   `(org-scheduled-previously ((,class :foreground ,yellow-alt-other)))
-   `(org-scheduled-today ((,class :foreground ,magenta-alt-other)))
-   `(org-sexp-date ((,class :inherit org-date)))
-   `(org-special-keyword ((,class ,@(modus-operandi-theme-mixed-fonts)
-                                  :foreground ,blue-nuanced)))
-   `(org-table ((,class ,@(modus-operandi-theme-mixed-fonts)
-                        :foreground ,fg-special-cold)))
-   `(org-table-header ((,class :inherit (fixed-pitch 
modus-theme-intense-neutral))))
-   `(org-tag ((,class :foreground ,magenta-nuanced)))
-   `(org-tag-group ((,class :inherit bold :foreground ,cyan-nuanced)))
-   `(org-target ((,class :underline t)))
-   `(org-time-grid ((,class :foreground ,fg-unfocused)))
-   `(org-todo ((,class :box ,bg-region :background ,bg-dim :foreground 
,red-alt)))
-   `(org-upcoming-deadline ((,class :foreground ,red-alt-other)))
-   `(org-upcoming-distant-deadline ((,class :foreground ,red-nuanced)))
-   `(org-verbatim ((,class ,@(modus-operandi-theme-mixed-fonts)
-                           :background ,bg-alt :foreground ,fg-special-calm)))
-   `(org-verse ((,class :inherit org-quote)))
-   `(org-warning ((,class :inherit bold :foreground ,red-alt-other)))
-;;;;; org-journal
-   `(org-journal-calendar-entry-face ((,class :foreground ,yellow-alt-other 
:slant ,modus-theme-slant)))
-   `(org-journal-calendar-scheduled-face ((,class :foreground ,red-alt-other 
:slant ,modus-theme-slant)))
-   `(org-journal-highlight ((,class :foreground ,magenta-alt)))
-;;;;; org-noter
-   `(org-noter-no-notes-exist-face ((,class :inherit bold :foreground 
,red-active)))
-   `(org-noter-notes-exist-face ((,class :inherit bold :foreground 
,green-active)))
-;;;;; org-pomodoro
-   `(org-pomodoro-mode-line ((,class :foreground ,red-active)))
-   `(org-pomodoro-mode-line-break ((,class :foreground ,cyan-active)))
-   `(org-pomodoro-mode-line-overtime ((,class :inherit bold :foreground 
,red-active)))
-;;;;; org-recur
-   `(org-recur ((,class :foreground ,magenta-active)))
-;;;;; org-roam
-   `(org-roam-link ((,class :inherit button :foreground ,green)))
-   `(org-roam-link-current ((,class :inherit button :foreground ,green-alt)))
-   `(org-roam-link-invalid ((,class :inherit button :foreground ,red)))
-   `(org-roam-link-shielded ((,class :inherit button :foreground ,yellow)))
-   `(org-roam-tag ((,class :foreground ,fg-alt :slant italic)))
-;;;;; org-superstar
-   `(org-superstar-item ((,class :foreground ,fg-main)))
-   `(org-superstar-leading ((,class :foreground ,fg-whitespace)))
-;;;;; org-table-sticky-header
-   `(org-table-sticky-header-face ((,class :inherit 
modus-theme-intense-neutral)))
-;;;;; org-treescope
-   `(org-treescope-faces--markerinternal-midday ((,class :inherit 
modus-theme-intense-blue)))
-   `(org-treescope-faces--markerinternal-range ((,class :inherit 
modus-theme-special-mild)))
-;;;;; origami
-   `(origami-fold-header-face ((,class :background ,bg-dim :foreground ,fg-dim 
:box t)))
-   `(origami-fold-replacement-face ((,class :background ,bg-alt :foreground 
,fg-alt)))
-;;;;; outline-mode
-   `(outline-1 ((,class :inherit modus-theme-heading-1)))
-   `(outline-2 ((,class :inherit modus-theme-heading-2)))
-   `(outline-3 ((,class :inherit modus-theme-heading-3)))
-   `(outline-4 ((,class :inherit modus-theme-heading-4)))
-   `(outline-5 ((,class :inherit modus-theme-heading-5)))
-   `(outline-6 ((,class :inherit modus-theme-heading-6)))
-   `(outline-7 ((,class :inherit modus-theme-heading-7)))
-   `(outline-8 ((,class :inherit modus-theme-heading-8)))
-;;;;; outline-minor-faces
-   `(outline-minor-0 ((,class nil)))
-;;;;; package (M-x list-packages)
-   `(package-description ((,class :foreground ,fg-special-cold)))
-   `(package-help-section-name ((,class :inherit bold :foreground 
,magenta-alt-other)))
-   `(package-name ((,class :inherit link)))
-   `(package-status-avail-obso ((,class :inherit bold :foreground ,red)))
-   `(package-status-available ((,class :foreground ,fg-special-mild)))
-   `(package-status-built-in ((,class :foreground ,magenta)))
-   `(package-status-dependency ((,class :foreground ,magenta-alt-other)))
-   `(package-status-disabled ((,class :inherit modus-theme-subtle-red)))
-   `(package-status-external ((,class :foreground ,cyan-alt-other)))
-   `(package-status-held ((,class :foreground ,yellow-alt)))
-   `(package-status-incompat ((,class :inherit bold :foreground ,yellow)))
-   `(package-status-installed ((,class :foreground ,fg-special-warm)))
-   `(package-status-new ((,class :inherit bold :foreground ,green)))
-   `(package-status-unsigned ((,class :inherit bold :foreground ,red-alt)))
-;;;;; page-break-lines
-   `(page-break-lines ((,class :inherit default :foreground 
,fg-window-divider-outer)))
-;;;;; paradox
-   `(paradox-archive-face ((,class :foreground ,fg-special-mild)))
-   `(paradox-comment-face ((,class :foreground ,fg-alt :slant 
,modus-theme-slant)))
-   `(paradox-commit-tag-face ((,class :inherit modus-theme-refine-magenta :box 
t)))
-   `(paradox-description-face ((,class :foreground ,fg-special-cold)))
-   `(paradox-description-face-multiline ((,class :foreground 
,fg-special-cold)))
-   `(paradox-download-face ((,class ,@(modus-operandi-theme-bold-weight) 
:foreground ,blue-alt-other)))
-   `(paradox-highlight-face ((,class ,@(modus-operandi-theme-bold-weight) 
:foreground ,cyan-alt-other)))
-   `(paradox-homepage-button-face ((,class :foreground ,magenta-alt-other 
:underline t)))
-   `(paradox-mode-line-face ((,class :inherit bold :foreground ,cyan-active)))
-   `(paradox-name-face ((,class :foreground ,blue :underline t)))
-   `(paradox-star-face ((,class :foreground ,magenta)))
-   `(paradox-starred-face ((,class :foreground ,magenta-alt)))
-;;;;; paren-face
-   `(parenthesis ((,class :foreground ,fg-unfocused)))
-;;;;; parrot
-   `(parrot-rotate-rotation-highlight-face ((,class :inherit 
modus-theme-refine-magenta)))
-;;;;; pass
-   `(pass-mode-directory-face ((,class :inherit bold :foreground 
,fg-special-cold)))
-   `(pass-mode-entry-face ((,class :background ,bg-main :foreground ,fg-main)))
-   `(pass-mode-header-face ((,class :foreground ,fg-special-warm)))
-;;;;; persp-mode
-   `(persp-face-lighter-buffer-not-in-persp ((,class :inherit 
modus-theme-intense-red)))
-   `(persp-face-lighter-default ((,class :inherit bold :foreground 
,blue-active)))
-   `(persp-face-lighter-nil-persp ((,class :inherit bold :foreground 
,fg-active)))
-;;;;; perspective
-   `(persp-selected-face ((,class :inherit bold :foreground ,blue-active)))
-;;;;; phi-grep
-   `(phi-grep-heading-face  ((,class :inherit bold :foreground ,red-alt
-                                     ,@(modus-operandi-theme-scale 
modus-operandi-theme-scale-4))))
-   `(phi-grep-line-number-face ((,class :foreground ,fg-special-warm)))
-   `(phi-grep-match-face ((,class :inherit modus-theme-special-calm)))
-   `(phi-grep-modified-face ((,class :inherit modus-theme-refine-yellow)))
-   `(phi-grep-overlay-face ((,class :inherit modus-theme-refine-blue)))
-;;;;; phi-search
-   `(phi-replace-preview-face ((,class :inherit modus-theme-intense-magenta)))
-   `(phi-search-failpart-face ((,class :inherit modus-theme-refine-red)))
-   `(phi-search-match-face ((,class :inherit modus-theme-refine-cyan)))
-   `(phi-search-selection-face ((,class :inherit (modus-theme-intense-green 
bold))))
-;;;;; pkgbuild-mode
-   `(pkgbuild-error-face ((,class :underline ,fg-lang-error)))
-;;;;; pomidor
-   `(pomidor-break-face ((,class :foreground ,blue-alt-other)))
-   `(pomidor-overwork-face ((,class :foreground ,red-alt-other)))
-   `(pomidor-skip-face ((,class :foreground ,fg-alt :slant 
,modus-theme-slant)))
-   `(pomidor-work-face ((,class :foreground ,green-alt-other)))
-;;;;; powerline
-   `(powerline-active0 ((,class :background ,bg-main :foreground ,blue-faint 
:inverse-video t)))
-   `(powerline-active1 ((,class :background ,blue-nuanced-bg :foreground 
,blue-nuanced)))
-   `(powerline-active2 ((,class :background ,bg-active :foreground 
,fg-active)))
-   `(powerline-inactive0 ((,class :background ,bg-special-cold :foreground 
,fg-special-cold)))
-   `(powerline-inactive1 ((,class :background ,bg-dim :foreground 
,fg-inactive)))
-   `(powerline-inactive2 ((,class :background ,bg-inactive :foreground 
,fg-inactive)))
-;;;;; powerline-evil
-   `(powerline-evil-base-face ((,class :background ,fg-main :foreground 
,bg-main)))
-   `(powerline-evil-emacs-face ((,class :inherit modus-theme-active-magenta)))
-   `(powerline-evil-insert-face ((,class :inherit modus-theme-active-green)))
-   `(powerline-evil-motion-face ((,class :inherit modus-theme-active-blue)))
-   `(powerline-evil-normal-face ((,class :background ,fg-alt :foreground 
,bg-main)))
-   `(powerline-evil-operator-face ((,class :inherit 
modus-theme-active-yellow)))
-   `(powerline-evil-replace-face ((,class :inherit modus-theme-active-red)))
-   `(powerline-evil-visual-face ((,class :inherit modus-theme-active-cyan)))
-;;;;; proced
-   `(proced-mark ((,class :inherit modus-theme-mark-symbol)))
-   `(proced-marked ((,class :inherit modus-theme-mark-alt)))
-   `(proced-sort-header ((,class :inherit bold :foreground ,fg-special-calm 
:underline t)))
-;;;;; prodigy
-   `(prodigy-green-face ((,class :foreground ,green)))
-   `(prodigy-red-face ((,class :foreground ,red)))
-   `(prodigy-yellow-face ((,class :foreground ,yellow)))
-;;;;; racket-mode
-   `(racket-debug-break-face ((,class :inherit modus-theme-intense-red)))
-   `(racket-debug-locals-face ((,class :box (:line-width -1 :color nil)
-                                       :foreground ,green-alt-other)))
-   `(racket-debug-result-face ((,class :inherit bold :box (:line-width -1 
:color nil)
-                                       :foreground ,green)))
-   `(racket-here-string-face ((,class :foreground ,blue-alt)))
-   `(racket-keyword-argument-face ((,class :foreground ,red-alt)))
-   `(racket-logger-config-face ((,class :foreground ,fg-alt :slant 
,modus-theme-slant)))
-   `(racket-logger-debug-face ((,class :foreground ,blue-alt-other)))
-   `(racket-logger-info-face ((,class :foreground ,fg-lang-note)))
-   `(racket-logger-topic-face ((,class :foreground ,magenta :slant 
,modus-theme-slant)))
-   `(racket-selfeval-face ((,class :foreground ,green-alt)))
-   `(racket-xp-error-face
-     ((,(append '((supports :underline (:style wave))) class)
-       :underline (:color ,fg-lang-error :style wave))
-      (,class :foreground ,fg-lang-error :underline t)))
-;;;;; rainbow-blocks
-   `(rainbow-blocks-depth-1-face ((,class :foreground ,magenta-alt-other)))
-   `(rainbow-blocks-depth-2-face ((,class :foreground ,blue)))
-   `(rainbow-blocks-depth-3-face ((,class :foreground ,magenta-alt)))
-   `(rainbow-blocks-depth-4-face ((,class :foreground ,green)))
-   `(rainbow-blocks-depth-5-face ((,class :foreground ,magenta)))
-   `(rainbow-blocks-depth-6-face ((,class :foreground ,cyan)))
-   `(rainbow-blocks-depth-7-face ((,class :foreground ,yellow)))
-   `(rainbow-blocks-depth-8-face ((,class :foreground ,cyan-alt)))
-   `(rainbow-blocks-depth-9-face ((,class :foreground ,red-alt)))
-   `(rainbow-blocks-unmatched-face ((,class :foreground ,red)))
-;;;;; rainbow-identifiers
-   `(rainbow-identifiers-identifier-1 ((,class :foreground ,green-alt-other)))
-   `(rainbow-identifiers-identifier-2 ((,class :foreground 
,magenta-alt-other)))
-   `(rainbow-identifiers-identifier-3 ((,class :foreground ,cyan-alt-other)))
-   `(rainbow-identifiers-identifier-4 ((,class :foreground ,yellow-alt-other)))
-   `(rainbow-identifiers-identifier-5 ((,class :foreground ,blue-alt-other)))
-   `(rainbow-identifiers-identifier-6 ((,class :foreground ,green-alt)))
-   `(rainbow-identifiers-identifier-7 ((,class :foreground ,magenta-alt)))
-   `(rainbow-identifiers-identifier-8 ((,class :foreground ,cyan-alt)))
-   `(rainbow-identifiers-identifier-9 ((,class :foreground ,yellow-alt)))
-   `(rainbow-identifiers-identifier-10 ((,class :foreground ,green)))
-   `(rainbow-identifiers-identifier-11 ((,class :foreground ,magenta)))
-   `(rainbow-identifiers-identifier-12 ((,class :foreground ,cyan)))
-   `(rainbow-identifiers-identifier-13 ((,class :foreground ,yellow)))
-   `(rainbow-identifiers-identifier-14 ((,class :foreground ,blue-alt)))
-   `(rainbow-identifiers-identifier-15 ((,class :foreground ,red-alt)))
-;;;;; rainbow-delimiters
-   `(rainbow-delimiters-base-face-error ((,class :foreground ,red)))
-   `(rainbow-delimiters-base-face ((,class :foreground ,fg-main)))
-   `(rainbow-delimiters-depth-1-face ((,class :foreground ,green-alt-other)))
-   `(rainbow-delimiters-depth-2-face ((,class :foreground ,magenta-alt-other)))
-   `(rainbow-delimiters-depth-3-face ((,class :foreground ,cyan-alt-other)))
-   `(rainbow-delimiters-depth-4-face ((,class :foreground ,yellow-alt-other)))
-   `(rainbow-delimiters-depth-5-face ((,class :foreground ,blue-alt-other)))
-   `(rainbow-delimiters-depth-6-face ((,class :foreground ,green-alt)))
-   `(rainbow-delimiters-depth-7-face ((,class :foreground ,magenta-alt)))
-   `(rainbow-delimiters-depth-8-face ((,class :foreground ,cyan-alt)))
-   `(rainbow-delimiters-depth-9-face ((,class :foreground ,yellow-alt)))
-   `(rainbow-delimiters-mismatched-face ((,class :inherit bold :foreground 
,red-alt)))
-   `(rainbow-delimiters-unmatched-face ((,class :inherit bold :foreground 
,red)))
-;;;;; rcirc
-   `(rcirc-bright-nick ((,class :inherit bold :foreground ,magenta-alt)))
-   `(rcirc-dim-nick ((,class :foreground ,fg-alt)))
-   `(rcirc-my-nick ((,class :inherit bold :foreground ,magenta)))
-   `(rcirc-nick-in-message ((,class :foreground ,magenta-alt-other)))
-   `(rcirc-nick-in-message-full-line ((,class :inherit bold :foreground 
,fg-special-mild)))
-   `(rcirc-other-nick ((,class :inherit bold :foreground ,fg-special-cold)))
-   `(rcirc-prompt ((,class :inherit bold :foreground ,cyan-alt-other)))
-   `(rcirc-server ((,class :foreground ,fg-unfocused)))
-   `(rcirc-timestamp ((,class :foreground ,blue-nuanced)))
-   `(rcirc-url ((,class :foreground ,blue :underline t)))
-;;;;; regexp-builder (re-builder)
-   `(reb-match-0 ((,class :inherit modus-theme-intense-blue)))
-   `(reb-match-1 ((,class :inherit modus-theme-intense-magenta)))
-   `(reb-match-2 ((,class :inherit modus-theme-intense-green)))
-   `(reb-match-3 ((,class :inherit modus-theme-intense-red)))
-   `(reb-regexp-grouping-backslash ((,class :inherit bold :foreground 
,fg-escape-char-backslash)))
-   `(reb-regexp-grouping-construct ((,class :inherit bold :foreground 
,fg-escape-char-construct)))
-;;;;; rg (rg.el)
-   `(rg-column-number-face ((,class :foreground ,magenta-alt-other)))
-   `(rg-context-face ((,class :foreground ,fg-unfocused)))
-   `(rg-error-face ((,class :inherit bold :foreground ,red)))
-   `(rg-file-tag-face ((,class :foreground ,fg-special-cold)))
-   `(rg-filename-face ((,class :inherit bold :foreground ,fg-special-cold)))
-   `(rg-line-number-face ((,class :foreground ,fg-special-warm)))
-   `(rg-literal-face ((,class :foreground ,blue-alt)))
-   `(rg-match-face ((,class :inherit modus-theme-special-calm)))
-   `(rg-regexp-face ((,class :foreground ,magenta-active)))
-   `(rg-toggle-off-face ((,class :inherit bold :foreground ,fg-inactive)))
-   `(rg-toggle-on-face ((,class :inherit bold :foreground ,cyan-active)))
-   `(rg-warning-face ((,class :inherit bold :foreground ,yellow)))
-;;;;; ripgrep
-   `(ripgrep-context-face ((,class :foreground ,fg-unfocused)))
-   `(ripgrep-error-face ((,class :inherit bold :foreground ,red)))
-   `(ripgrep-hit-face ((,class :foreground ,cyan)))
-   `(ripgrep-match-face ((,class :inherit modus-theme-special-calm)))
-;;;;; rmail
-   `(rmail-header-name ((,class :foreground ,cyan-alt-other)))
-   `(rmail-highlight ((,class :inherit bold :foreground ,magenta-alt)))
-;;;;; ruler-mode
-   `(ruler-mode-column-number ((,class :inherit (ruler-mode-default bold) 
:foreground ,fg-main)))
-   `(ruler-mode-comment-column ((,class :inherit ruler-mode-default 
:foreground ,red-active)))
-   `(ruler-mode-current-column ((,class :inherit ruler-mode-default 
:foreground ,cyan-active :box t)))
-   `(ruler-mode-default ((,class :background ,bg-inactive :foreground 
,fg-inactive)))
-   `(ruler-mode-fill-column ((,class :inherit ruler-mode-default :foreground 
,green-active)))
-   `(ruler-mode-fringes ((,class :inherit ruler-mode-default :foreground 
,blue-active)))
-   `(ruler-mode-goal-column ((,class :inherit ruler-mode-default :foreground 
,magenta-active)))
-   `(ruler-mode-margins ((,class :inherit ruler-mode-default :foreground 
,bg-main)))
-   `(ruler-mode-pad ((,class :background ,bg-active :foreground ,fg-inactive)))
-   `(ruler-mode-tab-stop ((,class :inherit ruler-mode-default :foreground 
,yellow-active)))
-;;;;; sallet
-   `(sallet-buffer-compressed ((,class :foreground ,yellow-nuanced :slant 
italic)))
-   `(sallet-buffer-default-directory ((,class :foreground ,cyan-nuanced)))
-   `(sallet-buffer-directory ((,class :foreground ,blue-nuanced)))
-   `(sallet-buffer-help ((,class :foreground ,fg-special-cold)))
-   `(sallet-buffer-modified ((,class :foreground ,yellow-alt-other :slant 
italic)))
-   `(sallet-buffer-ordinary ((,class :foreground ,fg-main)))
-   `(sallet-buffer-read-only ((,class :foreground ,yellow-alt)))
-   `(sallet-buffer-size ((,class :foreground ,fg-special-calm)))
-   `(sallet-buffer-special ((,class :foreground ,magenta-alt-other)))
-   `(sallet-flx-match ((,class ,@(modus-operandi-theme-extra-completions
-                                  'modus-theme-subtle-cyan
-                                  'modus-theme-refine-cyan
-                                  'modus-theme-nuanced-cyan
-                                  cyan-alt-other))))
-   `(sallet-recentf-buffer-name ((,class :foreground ,blue-nuanced)))
-   `(sallet-recentf-file-path ((,class :foreground ,fg-special-mild)))
-   `(sallet-regexp-match ((,class ,@(modus-operandi-theme-extra-completions
-                                     'modus-theme-subtle-magenta
-                                     'modus-theme-refine-magenta
-                                     'modus-theme-nuanced-magenta
-                                     magenta-alt-other))))
-   `(sallet-source-header ((,class :inherit bold :foreground ,red-alt
-                                   ,@(modus-operandi-theme-scale 
modus-operandi-theme-scale-4))))
-   `(sallet-substring-match ((,class ,@(modus-operandi-theme-extra-completions
-                                        'modus-theme-subtle-blue
-                                        'modus-theme-refine-blue
-                                        'modus-theme-nuanced-blue
-                                        blue-alt-other))))
-;;;;; selectrum
-   `(selectrum-current-candidate
-     ((,class :inherit bold :foreground ,fg-main :underline ,fg-main
-              :background ,@(pcase modus-operandi-theme-completions
-                              ('opinionated (list bg-active))
-                              (_ (list bg-inactive))))))
-   `(selectrum-primary-highlight ((,class :inherit bold
-                                          
,@(modus-operandi-theme-standard-completions
-                                             magenta-alt magenta-nuanced-bg
-                                             magenta-refine-bg 
magenta-refine-fg))))
-   `(selectrum-secondary-highlight ((,class :inherit bold
-                                            
,@(modus-operandi-theme-standard-completions
-                                               cyan-alt-other cyan-nuanced-bg
-                                               cyan-refine-bg 
cyan-refine-fg))))
-;;;;; semantic
-   `(semantic-complete-inline-face ((,class :foreground ,fg-special-warm 
:underline t)))
-   `(semantic-decoration-on-private-members-face ((,class :inherit 
modus-theme-refine-cyan)))
-   `(semantic-decoration-on-protected-members-face ((,class :background 
,bg-dim)))
-   `(semantic-highlight-edits-face ((,class :background ,bg-alt)))
-   `(semantic-highlight-func-current-tag-face ((,class :background ,bg-alt)))
-   `(semantic-idle-symbol-highlight ((,class :inherit 
modus-theme-special-mild)))
-   `(semantic-tag-boundary-face ((,class :overline ,blue-intense)))
-   `(semantic-unmatched-syntax-face ((,class :underline ,fg-lang-error)))
-;;;;; sesman
-   `(sesman-browser-button-face ((,class :foreground ,blue-alt-other 
:underline t)))
-   `(sesman-browser-highligh-face ((,class :inherit modus-theme-subtle-blue)))
-   `(sesman-buffer-face ((,class :foreground ,magenta)))
-   `(sesman-directory-face ((,class :inherit bold :foreground ,blue)))
-   `(sesman-project-face ((,class :inherit bold :foreground 
,magenta-alt-other)))
-;;;;; shell-script-mode
-   `(sh-heredoc ((,class :foreground ,blue-alt)))
-   `(sh-quoted-exec ((,class ,@(modus-operandi-theme-bold-weight) :foreground 
,magenta-alt)))
-;;;;; show-paren-mode
-   `(show-paren-match ((,class ,@(modus-operandi-theme-paren bg-paren-match
-                                                             
bg-paren-match-intense)
-                               :foreground ,fg-main)))
-   `(show-paren-match-expression ((,class :inherit modus-theme-special-calm)))
-   `(show-paren-mismatch ((,class :inherit modus-theme-intense-red)))
-;;;;; side-notes
-   `(side-notes ((,class :background ,bg-dim :foreground ,fg-dim)))
-;;;;; skewer-mode
-   `(skewer-error-face ((,class :foreground ,red :underline t)))
-;;;;; smart-mode-line
-   `(sml/charging ((,class :foreground ,green-active)))
-   `(sml/discharging ((,class :foreground ,red-active)))
-   `(sml/filename ((,class :inherit bold :foreground ,blue-active)))
-   `(sml/folder ((,class :foreground ,fg-active)))
-   `(sml/git ((,class :inherit bold :foreground ,green-active)))
-   `(sml/global ((,class :foreground ,fg-active)))
-   `(sml/line-number ((,class :inherit sml/global)))
-   `(sml/minor-modes ((,class :inherit sml/global)))
-   `(sml/modes ((,class :inherit bold :foreground ,fg-active)))
-   `(sml/modified ((,class :inherit bold :foreground ,magenta-active)))
-   `(sml/mule-info ((,class :inherit sml/global)))
-   `(sml/name-filling ((,class :foreground ,yellow-active)))
-   `(sml/not-modified ((,class :inherit sml/global)))
-   `(sml/numbers-separator ((,class :inherit sml/global)))
-   `(sml/outside-modified ((,class :inherit modus-theme-intense-red)))
-   `(sml/position-percentage ((,class :inherit sml/global)))
-   `(sml/prefix ((,class :foreground ,green-active)))
-   `(sml/process ((,class :inherit sml/prefix)))
-   `(sml/projectile ((,class :inherit sml/git)))
-   `(sml/read-only ((,class :inherit bold :foreground ,cyan-active)))
-   `(sml/remote ((,class :inherit sml/global)))
-   `(sml/sudo ((,class :inherit modus-theme-subtle-red)))
-   `(sml/time ((,class :inherit sml/global)))
-   `(sml/vc ((,class :inherit sml/git)))
-   `(sml/vc-edited ((,class :inherit bold :foreground ,yellow-active)))
-;;;;; smartparens
-   `(sp-pair-overlay-face ((,class :inherit modus-theme-special-warm)))
-   `(sp-show-pair-enclosing ((,class :inherit modus-theme-special-mild)))
-   `(sp-show-pair-match-face ((,class ,@(modus-operandi-theme-paren 
bg-paren-match
-                                                                    
bg-paren-match-intense)
-                                      :foreground ,fg-main)))
-   `(sp-show-pair-mismatch-face ((,class :inherit modus-theme-intense-red)))
-   `(sp-wrap-overlay-closing-pair ((,class :inherit sp-pair-overlay-face)))
-   `(sp-wrap-overlay-face ((,class :inherit sp-pair-overlay-face)))
-   `(sp-wrap-overlay-opening-pair ((,class :inherit sp-pair-overlay-face)))
-   `(sp-wrap-tag-overlay-face ((,class :inherit sp-pair-overlay-face)))
-;;;;; smerge
-   `(smerge-base ((,class :inherit modus-theme-diff-changed)))
-   `(smerge-lower ((,class :inherit modus-theme-diff-added)))
-   `(smerge-markers ((,class :background ,bg-diff-neutral-2 :foreground 
,fg-diff-neutral-2)))
-   `(smerge-refined-added ((,class :inherit modus-theme-diff-refine-added)))
-   `(smerge-refined-changed ((,class)))
-   `(smerge-refined-removed ((,class :inherit 
modus-theme-diff-refine-removed)))
-   `(smerge-upper ((,class :inherit modus-theme-diff-removed)))
-;;;;; spaceline
-   `(spaceline-evil-emacs ((,class :inherit modus-theme-active-magenta)))
-   `(spaceline-evil-insert ((,class :inherit modus-theme-active-green)))
-   `(spaceline-evil-motion ((,class :inherit modus-theme-active-blue)))
-   `(spaceline-evil-normal ((,class :background ,fg-alt :foreground ,bg-alt)))
-   `(spaceline-evil-replace ((,class :inherit modus-theme-active-red)))
-   `(spaceline-evil-visual ((,class :inherit modus-theme-active-cyan)))
-   `(spaceline-flycheck-error ((,class :foreground ,red-active)))
-   `(spaceline-flycheck-info ((,class :foreground ,cyan-active)))
-   `(spaceline-flycheck-warning ((,class :foreground ,yellow-active)))
-   `(spaceline-highlight-face ((,class :inherit modus-theme-fringe-blue)))
-   `(spaceline-modified ((,class :inherit modus-theme-fringe-magenta)))
-   `(spaceline-python-venv ((,class :foreground ,magenta-active)))
-   `(spaceline-read-only ((,class :inherit modus-theme-fringe-red)))
-   `(spaceline-unmodified ((,class :inherit modus-theme-fringe-cyan)))
-;;;;; speedbar
-   `(speedbar-button-face ((,class :inherit link)))
-   `(speedbar-directory-face ((,class :inherit bold :foreground ,blue)))
-   `(speedbar-file-face ((,class :foreground ,fg-main)))
-   `(speedbar-highlight-face ((,class :inherit modus-theme-subtle-blue)))
-   `(speedbar-selected-face ((,class :inherit bold :foreground ,cyan)))
-   `(speedbar-separator-face ((,class :inherit modus-theme-intense-neutral)))
-   `(speedbar-tag-face ((,class :foreground ,yellow-alt-other)))
-;;;;; spell-fu
-   `(spell-fu-incorrect-face
-     ((,(append '((supports :underline (:style wave))) class)
-       :foreground ,fg-lang-error :underline (:style wave))
-      (,class :foreground ,fg-lang-error :underline t)))
-;;;;; stripes
-   `(stripes ((,class :inherit modus-theme-hl-line)))
-;;;;; success
-   `(suggest-heading ((,class :inherit bold :foreground ,yellow-alt-other)))
-;;;;; switch-window
-   `(switch-window-background ((,class :background ,bg-dim)))
-   `(switch-window-label ((,class :height 3.0 :foreground ,blue-intense)))
-;;;;; swiper
-   `(swiper-background-match-face-1 ((,class :inherit 
modus-theme-subtle-neutral)))
-   `(swiper-background-match-face-2 ((,class :inherit 
modus-theme-subtle-cyan)))
-   `(swiper-background-match-face-3 ((,class :inherit 
modus-theme-subtle-magenta)))
-   `(swiper-background-match-face-4 ((,class :inherit 
modus-theme-subtle-green)))
-   `(swiper-line-face ((,class ,@(and (>= emacs-major-version 27) '(:extend t))
-                               :inherit modus-theme-special-cold)))
-   `(swiper-match-face-1 ((,class :inherit swiper-line-face)))
-   `(swiper-match-face-2 ((,class :inherit swiper-line-face)))
-   `(swiper-match-face-3 ((,class :inherit swiper-line-face)))
-   `(swiper-match-face-4 ((,class :inherit swiper-line-face)))
-;;;;; swoop
-   `(swoop-face-header-format-line ((,class :inherit bold :foreground ,red-alt
-                                            ,@(modus-operandi-theme-scale 
modus-operandi-theme-scale-3))))
-   `(swoop-face-line-buffer-name ((,class :inherit bold :foreground ,blue-alt
-                                          ,@(modus-operandi-theme-scale 
modus-operandi-theme-scale-4))))
-   `(swoop-face-line-number ((,class :foreground ,fg-special-warm)))
-   `(swoop-face-target-line ((,class :inherit modus-theme-intense-blue
-                                     ,@(and (>= emacs-major-version 27) 
'(:extend t)))))
-   `(swoop-face-target-words ((,class :inherit modus-theme-refine-cyan)))
-;;;;; sx
-   `(sx-inbox-item-type ((,class :foreground ,magenta-alt-other)))
-   `(sx-inbox-item-type-unread ((,class :inherit (sx-inbox-item-type bold))))
-   `(sx-question-list-answers ((,class :foreground ,green)))
-   `(sx-question-list-answers-accepted ((,class :box t :foreground ,green)))
-   `(sx-question-list-bounty ((,class :inherit bold :background ,bg-alt 
:foreground ,yellow)))
-   `(sx-question-list-date ((,class :foreground ,fg-special-cold)))
-   `(sx-question-list-favorite ((,class :inherit bold :foreground 
,fg-special-warm)))
-   `(sx-question-list-parent ((,class :foreground ,fg-main)))
-   `(sx-question-list-read-question ((,class :foreground ,fg-alt)))
-   `(sx-question-list-score ((,class :foreground ,fg-special-mild)))
-   `(sx-question-list-score-upvoted ((,class :inherit (sx-question-list-score 
bold))))
-   `(sx-question-list-unread-question ((,class :inherit bold :foreground 
,fg-main)))
-   `(sx-question-mode-accepted ((,class :inherit bold :height 1.3 :foreground 
,green)))
-   `(sx-question-mode-closed ((,class :inherit modus-theme-active-yellow :box 
(:line-width 2 :color nil))))
-   `(sx-question-mode-closed-reason ((,class :box (:line-width 2 :color nil) 
:foreground ,fg-main)))
-   `(sx-question-mode-content-face ((,class :background ,bg-dim)))
-   `(sx-question-mode-date ((,class :foreground ,blue)))
-   `(sx-question-mode-header ((,class :inherit bold :foreground ,cyan)))
-   `(sx-question-mode-kbd-tag ((,class :inherit bold :height 0.9 :box 
(:line-width 3 :color ,fg-main :style released-button) :foreground ,fg-main)))
-   `(sx-question-mode-score ((,class :foreground ,fg-dim)))
-   `(sx-question-mode-score-downvoted ((,class :foreground ,yellow)))
-   `(sx-question-mode-score-upvoted ((,class :inherit bold :foreground 
,magenta)))
-   `(sx-question-mode-title ((,class :inherit bold :foreground ,fg-main)))
-   `(sx-question-mode-title-comments ((,class :inherit bold :foreground 
,fg-alt)))
-   `(sx-tag ((,class :foreground ,magenta-alt)))
-   `(sx-user-name ((,class :foreground ,blue-alt)))
-   `(sx-user-reputation ((,class :foreground ,fg-alt)))
-;;;;; symbol-overlay
-   `(symbol-overlay-default-face ((,class :inherit modus-theme-special-warm)))
-   `(symbol-overlay-face-1 ((,class :inherit modus-theme-intense-blue)))
-   `(symbol-overlay-face-2 ((,class :inherit modus-theme-refine-magenta)))
-   `(symbol-overlay-face-3 ((,class :inherit modus-theme-intense-yellow)))
-   `(symbol-overlay-face-4 ((,class :inherit modus-theme-intense-magenta)))
-   `(symbol-overlay-face-5 ((,class :inherit modus-theme-intense-red)))
-   `(symbol-overlay-face-6 ((,class :inherit modus-theme-refine-red)))
-   `(symbol-overlay-face-7 ((,class :inherit modus-theme-intense-cyan)))
-   `(symbol-overlay-face-8 ((,class :inherit modus-theme-refine-cyan)))
-;;;;; syslog-mode
-   `(syslog-debug ((,class :inherit bold :foreground ,cyan-alt-other)))
-   `(syslog-error ((,class :inherit bold :foreground ,red)))
-   `(syslog-file ((,class :inherit bold :foreground ,fg-special-cold)))
-   `(syslog-hide ((,class :background ,bg-main :foreground ,fg-main)))
-   `(syslog-hour ((,class :inherit bold :foreground ,magenta-alt-other)))
-   `(syslog-info ((,class :inherit bold :foreground ,blue-alt-other)))
-   `(syslog-ip ((,class :inherit bold :foreground ,fg-special-mild :underline 
t)))
-   `(syslog-su ((,class :inherit bold :foreground ,red-alt)))
-   `(syslog-warn ((,class :inherit bold :foreground ,yellow)))
-;;;;; table (built-in table.el)
-   `(table-cell ((,class :background ,blue-nuanced-bg)))
-;;;;; telephone-line
-   `(telephone-line-accent-active ((,class :background ,fg-inactive 
:foreground ,bg-inactive)))
-   `(telephone-line-accent-inactive ((,class :background ,bg-active 
:foreground ,fg-active)))
-   `(telephone-line-error ((,class :inherit bold :foreground ,red-active)))
-   `(telephone-line-evil ((,class :foreground ,fg-main)))
-   `(telephone-line-evil-emacs ((,class :inherit telephone-line-evil 
:background ,magenta-intense-bg)))
-   `(telephone-line-evil-insert ((,class :inherit telephone-line-evil 
:background ,green-intense-bg)))
-   `(telephone-line-evil-motion ((,class :inherit telephone-line-evil 
:background ,yellow-intense-bg)))
-   `(telephone-line-evil-normal ((,class :inherit telephone-line-evil 
:background ,bg-alt)))
-   `(telephone-line-evil-operator ((,class :inherit telephone-line-evil 
:background ,yellow-subtle-bg)))
-   `(telephone-line-evil-replace ((,class :inherit telephone-line-evil 
:background ,red-intense-bg)))
-   `(telephone-line-evil-visual ((,class :inherit telephone-line-evil 
:background ,cyan-intense-bg)))
-   `(telephone-line-projectile ((,class :foreground ,cyan-active)))
-   `(telephone-line-unimportant ((,class :foreground ,fg-inactive)))
-   `(telephone-line-warning ((,class :inherit bold :foreground 
,yellow-active)))
-;;;;; term
-   `(term ((,class :background ,bg-main :foreground ,fg-main)))
-   `(term-bold ((,class :inherit bold)))
-   `(term-color-blue ((,class :background ,blue :foreground ,blue)))
-   `(term-color-cyan ((,class :background ,cyan :foreground ,cyan)))
-   `(term-color-green ((,class :background ,green :foreground ,green)))
-   `(term-color-magenta ((,class :background ,magenta :foreground ,magenta)))
-   `(term-color-red ((,class :background ,red :foreground ,red)))
-   `(term-color-yellow ((,class :background ,yellow :foreground ,yellow)))
-   `(term-underline ((,class :underline t)))
-;;;;; tomatinho
-   `(tomatinho-ok-face ((,class :foreground ,blue-intense)))
-   `(tomatinho-pause-face ((,class :foreground ,yellow-intense)))
-   `(tomatinho-reset-face ((,class :foreground ,fg-alt)))
-;;;;; transient
-   `(transient-active-infix ((,class :inherit modus-theme-special-mild)))
-   `(transient-amaranth ((,class :inherit bold :foreground ,yellow)))
-   `(transient-argument ((,class :inherit bold :foreground ,red-alt)))
-   `(transient-blue ((,class :inherit bold :foreground ,blue)))
-   `(transient-disabled-suffix ((,class :inherit modus-theme-intense-red)))
-   `(transient-enabled-suffix ((,class :inherit modus-theme-intense-green)))
-   `(transient-heading ((,class :inherit bold :foreground ,fg-main)))
-   `(transient-inactive-argument ((,class :foreground ,fg-alt)))
-   `(transient-inactive-value ((,class :foreground ,fg-alt)))
-   `(transient-key ((,class :inherit bold :foreground ,blue)))
-   `(transient-mismatched-key ((,class :underline t)))
-   `(transient-nonstandard-key ((,class :underline t)))
-   `(transient-pink ((,class :inherit bold :foreground ,magenta)))
-   `(transient-red ((,class :inherit bold :foreground ,red-intense)))
-   `(transient-teal ((,class :inherit bold :foreground ,cyan-alt-other)))
-   `(transient-unreachable ((,class :foreground ,fg-unfocused)))
-   `(transient-unreachable-key ((,class :foreground ,fg-unfocused)))
-   `(transient-value ((,class :foreground ,magenta-alt)))
-;;;;; trashed
-   `(trashed-deleted ((,class :inherit modus-theme-mark-del)))
-   `(trashed-directory ((,class :foreground ,blue)))
-   `(trashed-mark ((,class :inherit modus-theme-mark-symbol)))
-   `(trashed-marked ((,class :inherit modus-theme-mark-alt)))
-   `(trashed-restored ((,class :inherit modus-theme-mark-sel)))
-   `(trashed-symlink ((,class :inherit button :foreground ,cyan-alt)))
-;;;;; treemacs
-   `(treemacs-directory-collapsed-face ((,class :foreground ,magenta-alt)))
-   `(treemacs-directory-face ((,class :inherit dired-directory)))
-   `(treemacs-file-face ((,class :foreground ,fg-main)))
-   `(treemacs-fringe-indicator-face ((,class :foreground ,fg-main)))
-   `(treemacs-git-added-face ((,class :foreground ,green-intense)))
-   `(treemacs-git-conflict-face ((,class :inherit (modus-theme-intense-red 
bold))))
-   `(treemacs-git-ignored-face ((,class :foreground ,fg-alt)))
-   `(treemacs-git-modified-face ((,class :foreground ,yellow-alt-other)))
-   `(treemacs-git-renamed-face ((,class :foreground ,cyan-alt-other)))
-   `(treemacs-git-unmodified-face ((,class :foreground ,fg-main)))
-   `(treemacs-git-untracked-face ((,class :foreground ,red-alt-other)))
-   `(treemacs-help-column-face ((,class ,@(modus-operandi-theme-bold-weight) 
:foreground ,magenta-alt-other :underline t)))
-   `(treemacs-help-title-face ((,class :foreground ,blue-alt-other)))
-   `(treemacs-on-failure-pulse-face ((,class :inherit 
modus-theme-intense-red)))
-   `(treemacs-on-success-pulse-face ((,class :inherit 
modus-theme-intense-green)))
-   `(treemacs-root-face ((,class :inherit bold :foreground ,blue-alt-other 
:height 1.2 :underline t)))
-   `(treemacs-root-remote-disconnected-face ((,class :inherit 
treemacs-root-remote-face :foreground ,yellow)))
-   `(treemacs-root-remote-face ((,class :inherit treemacs-root-face 
:foreground ,magenta)))
-   `(treemacs-root-remote-unreadable-face ((,class :inherit 
treemacs-root-unreadable-face)))
-   `(treemacs-root-unreadable-face ((,class :inherit treemacs-root-face 
:strike-through t)))
-   `(treemacs-tags-face ((,class :foreground ,blue-alt)))
-   `(treemacs-tags-face ((,class :foreground ,magenta-alt)))
-;;;;; tty-menu
-   `(tty-menu-disabled-face ((,class :background ,bg-alt :foreground ,fg-alt)))
-   `(tty-menu-enabled-face ((,class :inherit bold :background ,bg-alt 
:foreground ,fg-main)))
-   `(tty-menu-selected-face ((,class :inherit modus-theme-intense-blue)))
-;;;;; tuareg
-   `(caml-types-def-face ((,class :inherit modus-theme-subtle-red)))
-   `(caml-types-expr-face ((,class :inherit modus-theme-subtle-green)))
-   `(caml-types-occ-face ((,class :inherit modus-theme-subtle-green)))
-   `(caml-types-scope-face ((,class :inherit modus-theme-subtle-blue)))
-   `(caml-types-typed-face ((,class :inherit modus-theme-subtle-magenta)))
-   `(tuareg-font-double-semicolon-face ((,class 
,@(modus-operandi-theme-syntax-foreground
-                                                   red-alt red-alt-faint))))
-   `(tuareg-font-lock-attribute-face ((,class 
,@(modus-operandi-theme-syntax-foreground
-                                                 magenta magenta-faint))))
-   `(tuareg-font-lock-constructor-face ((,class :foreground ,fg-main)))
-   `(tuareg-font-lock-error-face ((,class :inherit (modus-theme-intense-red 
bold))))
-   `(tuareg-font-lock-extension-node-face ((,class :background ,bg-alt 
:foreground ,magenta)))
-   `(tuareg-font-lock-governing-face ((,class :inherit bold :foreground 
,fg-main)))
-   `(tuareg-font-lock-infix-extension-node-face ((,class 
,@(modus-operandi-theme-syntax-foreground
-                                                            magenta 
magenta-faint))))
-   `(tuareg-font-lock-interactive-directive-face ((,class :foreground 
,fg-special-cold)))
-   `(tuareg-font-lock-interactive-error-face ((,class :inherit bold
-                                                      
,@(modus-operandi-theme-syntax-foreground
-                                                         red red-faint))))
-   `(tuareg-font-lock-interactive-output-face ((,class 
,@(modus-operandi-theme-syntax-foreground
-                                                          blue-alt-other 
blue-alt-other-faint))))
-   `(tuareg-font-lock-label-face ((,class 
,@(modus-operandi-theme-syntax-foreground
-                                             cyan-alt-other 
cyan-alt-other-faint))))
-   `(tuareg-font-lock-line-number-face ((,class :foreground ,fg-special-warm)))
-   `(tuareg-font-lock-module-face ((,class 
,@(modus-operandi-theme-syntax-foreground
-                                              magenta-alt magenta-alt-faint))))
-   `(tuareg-font-lock-multistage-face ((,class :inherit bold :background 
,bg-alt
-                                               
,@(modus-operandi-theme-syntax-foreground
-                                                  blue blue-faint))))
-   `(tuareg-font-lock-operator-face ((,class 
,@(modus-operandi-theme-syntax-foreground
-                                                red-alt red-alt-faint))))
-   `(tuareg-opam-error-face ((,class :inherit bold
-                                     ,@(modus-operandi-theme-syntax-foreground
-                                        red red-faint))))
-   `(tuareg-opam-pkg-variable-name-face ((,class 
,@(modus-operandi-theme-syntax-foreground
-                                                    cyan cyan-faint)
-                                                 :slant ,modus-theme-slant)))
-;;;;; typescript
-   `(typescript-jsdoc-tag ((,class :foreground ,fg-special-mild :slant 
,modus-theme-slant)))
-   `(typescript-jsdoc-type ((,class :foreground ,fg-special-calm :slant 
,modus-theme-slant)))
-   `(typescript-jsdoc-value ((,class :foreground ,fg-special-cold :slant 
,modus-theme-slant)))
-;;;;; undo-tree
-   `(undo-tree-visualizer-active-branch-face ((,class :inherit bold 
:foreground ,fg-main)))
-   `(undo-tree-visualizer-current-face ((,class :foreground ,blue-intense)))
-   `(undo-tree-visualizer-default-face ((,class :foreground ,fg-alt)))
-   `(undo-tree-visualizer-register-face ((,class :foreground 
,magenta-intense)))
-   `(undo-tree-visualizer-unmodified-face ((,class :foreground 
,green-intense)))
-;;;;; vc (vc-hooks.el)
-   `(vc-conflict-state ((,class :foreground ,red-active :slant 
,modus-theme-slant)))
-   `(vc-edited-state ((,class :foreground ,yellow-active)))
-   `(vc-locally-added-state ((,class :foreground ,cyan-active)))
-   `(vc-locked-state ((,class :foreground ,blue-active)))
-   `(vc-missing-state ((,class :foreground ,magenta-active :slant 
,modus-theme-slant)))
-   `(vc-needs-update-state ((,class :foreground ,green-active :slant 
,modus-theme-slant)))
-   `(vc-removed-state ((,class :foreground ,red-active)))
-   `(vc-state-base ((,class :foreground ,fg-active)))
-   `(vc-up-to-date-state ((,class :foreground ,fg-special-cold)))
-;;;;; vdiff
-   `(vdiff-addition-face ((,class :inherit modus-theme-diff-added)))
-   `(vdiff-change-face ((,class :inherit modus-theme-diff-changed)))
-   `(vdiff-closed-fold-face ((,class :background ,bg-diff-neutral-1 
:foreground ,fg-diff-neutral-1)))
-   `(vdiff-refine-added ((,class :inherit modus-theme-diff-refine-added)))
-   `(vdiff-refine-changed ((,class :inherit modus-theme-diff-refine-changed)))
-   `(vdiff-subtraction-face ((,class :inherit modus-theme-diff-removed)))
-   `(vdiff-target-face ((,class :inherit modus-theme-intense-blue)))
-;;;;; vimish-fold
-   `(vimish-fold-fringe ((,class :foreground ,cyan-active)))
-   `(vimish-fold-mouse-face ((,class :inherit modus-theme-intense-blue)))
-   `(vimish-fold-overlay ((,class :background ,bg-alt :foreground 
,fg-special-cold)))
-;;;;; visible-mark
-   `(visible-mark-active ((,class :background ,blue-intense-bg)))
-   `(visible-mark-face1 ((,class :background ,cyan-intense-bg)))
-   `(visible-mark-face2 ((,class :background ,yellow-intense-bg)))
-   `(visible-mark-forward-face1 ((,class :background ,magenta-intense-bg)))
-   `(visible-mark-forward-face2 ((,class :background ,green-intense-bg)))
-;;;;; visual-regexp
-   `(vr/group-0 ((,class :inherit modus-theme-intense-blue)))
-   `(vr/group-1 ((,class :inherit modus-theme-intense-magenta)))
-   `(vr/group-2 ((,class :inherit modus-theme-intense-green)))
-   `(vr/match-0 ((,class :inherit modus-theme-refine-yellow)))
-   `(vr/match-1 ((,class :inherit modus-theme-refine-yellow)))
-   `(vr/match-separator-face ((,class :inherit (modus-theme-intense-neutral 
bold))))
-;;;;; volatile-highlights
-   `(vhl/default-face ((,class ,@(and (>= emacs-major-version 27) '(:extend t))
-                               :background ,bg-alt :foreground ,blue-nuanced)))
-;;;;; vterm
-   `(vterm-color-black ((,class :background "gray35" :foreground "gray35")))
-   `(vterm-color-blue ((,class :background ,blue :foreground ,blue)))
-   `(vterm-color-cyan ((,class :background ,cyan :foreground ,cyan)))
-   `(vterm-color-default ((,class :background ,bg-main :foreground ,fg-main)))
-   `(vterm-color-green ((,class :background ,green :foreground ,green)))
-   `(vterm-color-inverse-video ((,class :background ,bg-main :inverse-video 
t)))
-   `(vterm-color-magenta ((,class :background ,magenta :foreground ,magenta)))
-   `(vterm-color-red ((,class :background ,red :foreground ,red)))
-   `(vterm-color-underline ((,class :foreground ,fg-special-warm :underline 
t)))
-   `(vterm-color-white ((,class :background "gray65" :foreground "gray65")))
-   `(vterm-color-yellow ((,class :background ,yellow :foreground ,yellow)))
-;;;;; wcheck-mode
-   `(wcheck-default-face ((,class :foreground ,red :underline t)))
-;;;;; web-mode
-   `(web-mode-annotation-face ((,class :inherit web-mode-comment-face)))
-   `(web-mode-annotation-html-face ((,class :inherit web-mode-comment-face)))
-   `(web-mode-annotation-tag-face ((,class :inherit web-mode-comment-face 
:underline t)))
-   `(web-mode-block-attr-name-face ((,class 
,@(modus-operandi-theme-syntax-foreground
-                                               blue blue-faint))))
-   `(web-mode-block-attr-value-face ((,class 
,@(modus-operandi-theme-syntax-foreground
-                                                cyan-alt-other 
cyan-alt-other-faint))))
-   `(web-mode-block-comment-face ((,class :inherit web-mode-comment-face)))
-   `(web-mode-block-control-face ((,class 
,@(modus-operandi-theme-syntax-foreground
-                                             magenta-alt magenta-alt-faint)
-                                          
,@(modus-operandi-theme-bold-weight))))
-   `(web-mode-block-delimiter-face ((,class :foreground ,fg-main)))
-   `(web-mode-block-face ((,class :background ,bg-dim)))
-   `(web-mode-block-string-face ((,class :inherit web-mode-string-face)))
-   `(web-mode-bold-face ((,class :inherit bold)))
-   `(web-mode-builtin-face ((,class ,@(modus-operandi-theme-syntax-foreground
-                                       magenta-alt magenta-alt-faint)
-                                    ,@(modus-operandi-theme-bold-weight))))
-   `(web-mode-comment-face ((,class :foreground ,fg-alt :slant 
,modus-theme-slant)))
-   `(web-mode-comment-keyword-face ((,class :inherit bold :background ,bg-dim
-                                            
,@(modus-operandi-theme-syntax-foreground
-                                               yellow yellow-faint))))
-   `(web-mode-constant-face ((,class ,@(modus-operandi-theme-syntax-foreground
-                                        blue-alt-other blue-alt-other-faint))))
-   `(web-mode-css-at-rule-face ((,class 
,@(modus-operandi-theme-syntax-foreground
-                                           blue-alt-other 
blue-alt-other-faint))))
-   `(web-mode-css-color-face ((,class ,@(modus-operandi-theme-syntax-foreground
-                                         magenta-alt magenta-alt-faint)
-                                      ,@(modus-operandi-theme-bold-weight))))
-   `(web-mode-css-comment-face ((,class :inherit web-mode-comment-face)))
-   `(web-mode-css-function-face ((,class 
,@(modus-operandi-theme-syntax-foreground
-                                            magenta-alt magenta-alt-faint)
-                                         
,@(modus-operandi-theme-bold-weight))))
-   `(web-mode-css-priority-face ((,class 
,@(modus-operandi-theme-syntax-foreground
-                                            yellow-alt yellow-alt-faint)
-                                         
,@(modus-operandi-theme-bold-weight))))
-   `(web-mode-css-property-name-face ((,class 
,@(modus-operandi-theme-syntax-foreground
-                                                 cyan cyan-faint))))
-   `(web-mode-css-pseudo-class-face ((,class 
,@(modus-operandi-theme-syntax-foreground
-                                                cyan-alt-other 
cyan-alt-other-faint))))
-   `(web-mode-css-selector-face ((,class 
,@(modus-operandi-theme-syntax-foreground
-                                            magenta-alt-other 
magenta-alt-other-faint)
-                                         
,@(modus-operandi-theme-bold-weight))))
-   `(web-mode-css-string-face ((,class :inherit web-mode-string-face)))
-   `(web-mode-css-variable-face ((,class :foreground ,fg-special-warm)))
-   `(web-mode-current-column-highlight-face ((,class :background ,bg-alt)))
-   `(web-mode-current-element-highlight-face ((,class :inherit 
modus-theme-special-mild)))
-   `(web-mode-doctype-face ((,class :foreground ,fg-special-cold :slant 
,modus-theme-slant)))
-   `(web-mode-error-face ((,class :inherit modus-theme-intense-red)))
-   `(web-mode-filter-face ((,class ,@(modus-operandi-theme-syntax-foreground
-                                      magenta magenta-faint))))
-   `(web-mode-folded-face ((,class :underline t)))
-   `(web-mode-function-call-face ((,class 
,@(modus-operandi-theme-syntax-foreground
-                                             magenta magenta-faint))))
-   `(web-mode-function-name-face ((,class 
,@(modus-operandi-theme-syntax-foreground
-                                             magenta magenta-faint))))
-   `(web-mode-html-attr-custom-face ((,class 
,@(modus-operandi-theme-syntax-foreground
-                                                cyan cyan-faint))))
-   `(web-mode-html-attr-engine-face ((,class :foreground ,fg-main)))
-   `(web-mode-html-attr-equal-face ((,class :foreground ,fg-main)))
-   `(web-mode-html-attr-name-face ((,class 
,@(modus-operandi-theme-syntax-foreground
-                                              cyan cyan-faint))))
-   `(web-mode-html-attr-value-face ((,class 
,@(modus-operandi-theme-syntax-foreground
-                                               blue-alt-other 
blue-alt-other-faint))))
-   `(web-mode-html-entity-face ((,class 
,@(modus-operandi-theme-syntax-foreground
-                                           yellow-alt-other 
yellow-alt-other-faint)
-                                        :slant ,modus-theme-slant)))
-   `(web-mode-html-tag-bracket-face ((,class :foreground ,fg-dim)))
-   `(web-mode-html-tag-custom-face ((,class 
,@(modus-operandi-theme-syntax-foreground
-                                               magenta magenta-faint))))
-   `(web-mode-html-tag-face ((,class ,@(modus-operandi-theme-syntax-foreground
-                                        magenta magenta-faint))))
-   `(web-mode-html-tag-namespaced-face ((,class 
,@(modus-operandi-theme-syntax-foreground
-                                                   magenta-alt 
magenta-alt-faint)
-                                                
,@(modus-operandi-theme-bold-weight))))
-   `(web-mode-html-tag-unclosed-face ((,class 
,@(modus-operandi-theme-syntax-foreground
-                                                 red red-faint)
-                                              :underline t)))
-   `(web-mode-inlay-face ((,class :background ,bg-alt)))
-   `(web-mode-italic-face ((,class :slant italic)))
-   `(web-mode-javascript-comment-face ((,class :inherit 
web-mode-comment-face)))
-   `(web-mode-javascript-string-face ((,class :inherit web-mode-string-face)))
-   `(web-mode-json-comment-face ((,class :inherit web-mode-comment-face)))
-   `(web-mode-json-context-face ((,class 
,@(modus-operandi-theme-syntax-foreground
-                                            magenta-alt magenta-alt-faint))))
-   `(web-mode-json-key-face ((,class :foreground ,blue-nuanced)))
-   `(web-mode-json-string-face ((,class :inherit web-mode-string-face)))
-   `(web-mode-jsx-depth-1-face ((,class :background ,blue-intense-bg 
:foreground ,fg-main)))
-   `(web-mode-jsx-depth-2-face ((,class :background ,blue-subtle-bg 
:foreground ,fg-main)))
-   `(web-mode-jsx-depth-3-face ((,class :background ,bg-special-cold 
:foreground ,fg-special-cold)))
-   `(web-mode-jsx-depth-4-face ((,class :background ,bg-alt :foreground 
,blue-refine-fg)))
-   `(web-mode-jsx-depth-5-face ((,class :background ,bg-alt :foreground 
,blue-nuanced)))
-   `(web-mode-keyword-face ((,class ,@(modus-operandi-theme-syntax-foreground
-                                       magenta-alt-other 
magenta-alt-other-faint)
-                                    ,@(modus-operandi-theme-bold-weight))))
-   `(web-mode-param-name-face ((,class 
,@(modus-operandi-theme-syntax-foreground
-                                          magenta magenta-faint))))
-   `(web-mode-part-comment-face ((,class :inherit web-mode-comment-face)))
-   `(web-mode-part-face ((,class :inherit web-mode-block-face)))
-   `(web-mode-part-string-face ((,class :inherit web-mode-string-face)))
-   `(web-mode-preprocessor-face ((,class 
,@(modus-operandi-theme-syntax-foreground
-                                            red-alt-other 
red-alt-other-faint))))
-   `(web-mode-script-face ((,class :inherit web-mode-part-face)))
-   `(web-mode-sql-keyword-face ((,class :inherit bold
-                                        
,@(modus-operandi-theme-syntax-foreground
-                                           yellow yellow-faint))))
-   `(web-mode-string-face ((,class ,@(modus-operandi-theme-syntax-foreground
-                                      blue-alt blue-alt-faint))))
-   `(web-mode-style-face ((,class :inherit web-mode-part-face)))
-   `(web-mode-symbol-face ((,class ,@(modus-operandi-theme-syntax-foreground
-                                      blue-alt-other blue-alt-other-faint))))
-   `(web-mode-type-face ((,class ,@(modus-operandi-theme-syntax-foreground
-                                    magenta-alt magenta-alt-faint))))
-   `(web-mode-underline-face ((,class :underline t)))
-   `(web-mode-variable-name-face ((,class 
,@(modus-operandi-theme-syntax-foreground
-                                             cyan cyan-faint))))
-   `(web-mode-warning-face ((,class :inherit bold :background ,bg-alt
-                                    ,@(modus-operandi-theme-syntax-foreground
-                                       yellow-alt-other 
yellow-alt-other-faint))))
-   `(web-mode-whitespace-face ((,class :background ,bg-whitespace :foreground 
,fg-whitespace)))
-;;;;; wgrep
-   `(wgrep-delete-face ((,class :inherit modus-theme-refine-yellow)))
-   `(wgrep-done-face ((,class :inherit modus-theme-refine-blue)))
-   `(wgrep-face ((,class :inherit modus-theme-refine-green)))
-   `(wgrep-file-face ((,class :foreground ,fg-special-warm)))
-   `(wgrep-reject-face ((,class :inherit (modus-theme-intense-red bold))))
-;;;;; which-function-mode
-   `(which-func ((,class :foreground ,magenta-active)))
-;;;;; which-key
-   `(which-key-command-description-face ((,class :foreground ,cyan)))
-   `(which-key-group-description-face ((,class :foreground ,magenta-alt)))
-   `(which-key-highlighted-command-face ((,class :foreground ,cyan-alt 
:underline t)))
-   `(which-key-key-face ((,class :inherit bold :foreground ,blue-intense)))
-   `(which-key-local-map-description-face ((,class :foreground ,fg-main)))
-   `(which-key-note-face ((,class :background ,bg-dim :foreground 
,fg-special-mild)))
-   `(which-key-separator-face ((,class :foreground ,fg-alt)))
-   `(which-key-special-key-face ((,class :inherit bold :foreground 
,yellow-intense)))
-;;;;; whitespace-mode
-   `(whitespace-big-indent ((,class :inherit modus-theme-subtle-red)))
-   `(whitespace-empty ((,class :inherit modus-theme-intense-magenta)))
-   `(whitespace-hspace ((,class :background ,bg-whitespace :foreground 
,fg-whitespace)))
-   `(whitespace-indentation ((,class :background ,bg-whitespace :foreground 
,fg-whitespace)))
-   `(whitespace-line ((,class :inherit modus-theme-special-warm)))
-   `(whitespace-newline ((,class :background ,bg-whitespace :foreground 
,fg-whitespace)))
-   `(whitespace-space ((,class :background ,bg-whitespace :foreground 
,fg-whitespace)))
-   `(whitespace-space-after-tab ((,class :inherit modus-theme-subtle-magenta)))
-   `(whitespace-space-before-tab ((,class :inherit modus-theme-subtle-cyan)))
-   `(whitespace-tab ((,class :background ,bg-whitespace :foreground 
,fg-whitespace)))
-   `(whitespace-trailing ((,class :inherit modus-theme-intense-red)))
-;;;;; window-divider-mode
-   `(window-divider ((,class :foreground ,fg-window-divider-inner)))
-   `(window-divider-first-pixel ((,class :foreground 
,fg-window-divider-outer)))
-   `(window-divider-last-pixel ((,class :foreground ,fg-window-divider-outer)))
-;;;;; winum
-   `(winum-face ((,class ,@(modus-operandi-theme-bold-weight) :foreground 
,cyan-active)))
-;;;;; writegood-mode
-   `(writegood-duplicates-face ((,class :background ,bg-alt :foreground 
,red-alt :underline t)))
-   `(writegood-passive-voice-face ((,class :foreground ,yellow-nuanced 
:underline ,fg-lang-warning)))
-   `(writegood-weasels-face ((,class :foreground ,red-nuanced :underline 
,fg-lang-error)))
-;;;;; woman
-   `(woman-addition ((,class :foreground ,magenta-alt-other)))
-   `(woman-bold ((,class :inherit bold :foreground ,magenta)))
-   `(woman-italic ((,class :foreground ,cyan :slant italic)))
-   `(woman-unknown ((,class :foreground ,yellow :slant italic)))
-;;;;; xah-elisp-mode
-   `(xah-elisp-at-symbol ((,class :inherit bold
-                                  ,@(modus-operandi-theme-syntax-foreground
-                                     red-alt red-alt-faint))))
-   `(xah-elisp-cap-variable ((,class ,@(modus-operandi-theme-syntax-foreground
-                                        red-alt-other red-alt-other-faint))))
-   `(xah-elisp-command-face ((,class ,@(modus-operandi-theme-syntax-foreground
-                                        cyan-alt-other cyan-alt-other-faint))))
-   `(xah-elisp-dollar-symbol ((,class ,@(modus-operandi-theme-syntax-foreground
-                                         green green-faint))))
-;;;;; xref
-   `(xref-file-header ((,class :inherit bold :foreground ,fg-special-cold)))
-   `(xref-line-number ((,class :foreground ,fg-alt)))
-   `(xref-match ((,class :inherit match)))
-;;;;; yaml-mode
-   `(yaml-tab-face ((,class :inherit modus-theme-intense-red)))
-;;;;; yasnippet
-   `(yas-field-highlight-face ((,class :background ,bg-alt :foreground 
,fg-main)))
-;;;;; ztree
-   `(ztreep-arrow-face ((,class :foreground ,fg-inactive)))
-   `(ztreep-diff-header-face ((,class :inherit bold :height 1.2 :foreground 
,fg-special-cold)))
-   `(ztreep-diff-header-small-face ((,class :inherit bold :foreground 
,fg-special-mild)))
-   `(ztreep-diff-model-add-face ((,class :foreground ,green)))
-   `(ztreep-diff-model-diff-face ((,class :foreground ,red)))
-   `(ztreep-diff-model-ignored-face ((,class :foreground ,fg-alt 
:strike-through t)))
-   `(ztreep-diff-model-normal-face ((,class :foreground ,fg-alt)))
-   `(ztreep-expand-sign-face ((,class :foreground ,blue)))
-   `(ztreep-header-face ((,class :inherit bold :height 1.2 :foreground 
,fg-special-cold)))
-   `(ztreep-leaf-face ((,class :foreground ,cyan)))
-   `(ztreep-node-count-children-face ((,class :foreground ,fg-special-warm)))
-   `(ztreep-node-face ((,class :foreground ,fg-main))))
-;;;; Emacs 27+
-  (when (>= emacs-major-version 27)
-    (custom-theme-set-faces
-     'modus-operandi
-;;;;; line numbers (`display-line-numbers-mode' and global variant)
-     ;; NOTE that this is specifically for the faces that were
-     ;; introduced in Emacs 27, as the other faces are already
-     ;; supported.
-     `(line-number-major-tick ((,class :inherit (bold default)
-                                       :background ,yellow-nuanced-bg
-                                       :foreground ,yellow-nuanced)))
-     `(line-number-minor-tick ((,class :inherit (bold default)
-                                       :background ,bg-inactive
-                                       :foreground ,fg-inactive)))
-;;;;; tab-bar-mode
-     `(tab-bar ((,class :background ,bg-tab-bar :foreground ,fg-main)))
-     `(tab-bar-tab ((,class :inherit bold :box (:line-width 2 :color 
,bg-tab-active)
-                            :background ,bg-tab-active :foreground ,fg-main)))
-     `(tab-bar-tab-inactive ((,class :box (:line-width 2 :color 
,bg-tab-inactive)
-                                     :background ,bg-tab-inactive :foreground 
,fg-dim)))
-;;;;; tab-line-mode
-     `(tab-line ((,class :height 0.95 :background ,bg-tab-bar :foreground 
,fg-main)))
-     `(tab-line-close-highlight ((,class :foreground ,red)))
-     `(tab-line-highlight ((,class :background ,blue-subtle-bg :foreground 
,fg-dim)))
-     `(tab-line-tab ((,class :inherit bold :box (:line-width 2 :color 
,bg-tab-active)
-                             :background ,bg-tab-active :foreground ,fg-main)))
-     `(tab-line-tab-current ((,class :inherit tab-line-tab)))
-     `(tab-line-tab-inactive ((,class :box (:line-width 2 :color 
,bg-tab-inactive)
-                                      :background ,bg-tab-inactive :foreground 
,fg-dim)))))
-;;;; Emacs 28+
-  (when (>= emacs-major-version 28)
-    (custom-theme-set-faces
-     'modus-operandi
-;;;;; isearch regexp groups
-     `(isearch-group-1 ((,class :inherit modus-theme-intense-blue)))
-     `(isearch-group-2 ((,class :inherit modus-theme-intense-magenta)))))
-;;; variables
-  (custom-theme-set-variables
-   'modus-operandi
-;;;; ansi-colors
-   `(ansi-color-faces-vector [default bold shadow italic underline success 
warning error])
-   `(ansi-color-names-vector [,fg-main ,red ,green ,yellow ,blue ,magenta 
,cyan ,bg-main])
-;;;; awesome-tray
-   `(awesome-tray-mode-line-active-color ,blue)
-   `(awesome-tray-mode-line-inactive-color ,bg-active)
-;;;; flymake fringe indicators
-   `(flymake-error-bitmap '(flymake-double-exclamation-mark 
modus-theme-fringe-red))
-   `(flymake-warning-bitmap '(exclamation-mark modus-theme-fringe-yellow))
-   `(flymake-note-bitmap '(exclamation-mark modus-theme-fringe-cyan))
-;;;; ibuffer
-   `(ibuffer-deletion-face 'modus-theme-mark-del)
-   `(ibuffer-filter-group-name-face 'modus-theme-mark-symbol)
-   `(ibuffer-marked-face 'modus-theme-mark-sel)
-   `(ibuffer-title-face 'modus-theme-pseudo-header)
-;;;; highlight-tail
-   `(highlight-tail-colors
-     '((,green-subtle-bg . 0)
-       (,cyan-subtle-bg . 20)))
-;;;; hl-todo
-   `(hl-todo-keyword-faces
-     '(("HOLD" . ,yellow-alt)
-       ("TODO" . ,magenta)
-       ("NEXT" . ,magenta-alt-other)
-       ("THEM" . ,magenta-alt)
-       ("PROG" . ,cyan)
-       ("OKAY" . ,cyan-alt)
-       ("DONT" . ,green-alt)
-       ("FAIL" . ,red)
-       ("BUG" . ,red)
-       ("DONE" . ,green)
-       ("NOTE" . ,yellow-alt-other)
-       ("KLUDGE" . ,yellow)
-       ("HACK" . ,yellow)
-       ("TEMP" . ,red-nuanced)
-       ("FIXME" . ,red-alt-other)
-       ("XXX+" . ,red-alt)
-       ("REVIEW" . ,cyan-alt-other)
-       ("DEPRECATED" . ,blue-nuanced)))
-;;;; vc-annotate (C-x v g)
-   `(vc-annotate-background nil)
-   `(vc-annotate-background-mode nil)
-   `(vc-annotate-color-map
-     '((20 . ,red)
-       (40 . ,magenta)
-       (60 . ,magenta-alt)
-       (80 . ,red-alt)
-       (100 . ,yellow)
-       (120 . ,yellow-alt)
-       (140 . ,fg-special-warm)
-       (160 . ,fg-special-mild)
-       (180 . ,green)
-       (200 . ,green-alt)
-       (220 . ,cyan-alt-other)
-       (240 . ,cyan-alt)
-       (260 . ,cyan)
-       (280 . ,fg-special-cold)
-       (300 . ,blue)
-       (320 . ,blue-alt)
-       (340 . ,blue-alt-other)
-       (360 . ,magenta-alt-other)))
-   `(vc-annotate-very-old-color nil)
-;;;; xterm-color
-   `(xterm-color-names [,fg-main ,red ,green ,yellow ,blue ,magenta ,cyan 
,bg-alt])
-   `(xterm-color-names-bright [,fg-alt ,red-alt ,green-alt ,yellow-alt 
,blue-alt ,magenta-alt ,cyan-alt ,bg-main]))
-;;; Conditional theme variables
-;;;; org-src-block-faces
-  ;; this is a user option to add a colour-coded background to source
-  ;; blocks for various programming languages
-  (when (eq modus-operandi-theme-org-blocks 'rainbow)
-    (custom-theme-set-variables
-     'modus-operandi
-     `(org-src-block-faces              ; TODO this list should be expanded
-       `(("emacs-lisp" modus-theme-nuanced-magenta)
-         ("elisp" modus-theme-nuanced-magenta)
-         ("clojure" modus-theme-nuanced-magenta)
-         ("clojurescript" modus-theme-nuanced-magenta)
-         ("c" modus-theme-nuanced-blue)
-         ("c++" modus-theme-nuanced-blue)
-         ("sh" modus-theme-nuanced-green)
-         ("shell" modus-theme-nuanced-green)
-         ("html" modus-theme-nuanced-yellow)
-         ("xml" modus-theme-nuanced-yellow)
-         ("css" modus-theme-nuanced-red)
-         ("scss" modus-theme-nuanced-red)
-         ("python" modus-theme-nuanced-green)
-         ("ipython" modus-theme-nuanced-magenta)
-         ("r" modus-theme-nuanced-cyan)
-         ("yaml" modus-theme-nuanced-cyan)
-         ("conf" modus-theme-nuanced-cyan)
-         ("docker" modus-theme-nuanced-cyan)
-         ("json" modus-theme-nuanced-cyan))))))
+(deftheme modus-operandi
+  "Accessible and customizable light theme (WCAG AAA standard).
+Conforms with the highest legibility standard for color contrast
+between background and foreground in any given piece of text,
+which corresponds to a minimum contrast in relative luminance of
+7:1.")
 
-;;; library provides
-;;;###autoload
-(when load-file-name
-  (add-to-list 'custom-theme-load-path
-               (file-name-as-directory (file-name-directory load-file-name))))
+(modus-themes-theme modus-operandi)
 
 (provide-theme 'modus-operandi)
 
-(provide 'modus-operandi-theme)
-
 ;;; modus-operandi-theme.el ends here
diff --git a/etc/themes/modus-themes.el b/etc/themes/modus-themes.el
new file mode 100644
index 0000000..ad20707
--- /dev/null
+++ b/etc/themes/modus-themes.el
@@ -0,0 +1,6456 @@
+;;; modus-themes.el --- Highly accessible themes (WCAG AAA) -*- 
lexical-binding:t -*-
+
+;; Copyright (C) 2019-2021  Free Software Foundation, Inc.
+
+;; Author: Protesilaos Stavrou <info@protesilaos.com>
+;; URL: https://gitlab.com/protesilaos/modus-themes
+;; Version: 1.2.4
+;; Package-Requires: ((emacs "26.1"))
+;; Keywords: faces, theme, accessibility
+
+;; This file is part of GNU Emacs.
+
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or (at
+;; your option) any later version.
+;;
+;; This program is distributed in the hope that it will be useful, but
+;; WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+;; General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with this program.  If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+;;
+;; The Modus themes conform with the highest standard for color-contrast
+;; accessibility between background and foreground values (WCAG AAA).
+;; This file contains all customization options, helper functions,
+;; interactive commands, and face specifications.  Please refer to the
+;; official Info manual for further documentation (distributed with the
+;; themes, or available at: <https://protesilaos.com/modus-themes>).
+;;
+;; The themes share the following customization options, all of which
+;; are disabled by default (nil):
+;;
+;;     modus-themes-slanted-constructs             (boolean)
+;;     modus-themes-bold-constructs                (boolean)
+;;     modus-themes-variable-pitch-headings        (boolean)
+;;     modus-themes-variable-pitch-ui              (boolean)
+;;     modus-themes-no-mixed-fonts                 (boolean)
+;;     modus-themes-headings                       (alist)
+;;     modus-themes-scale-headings                 (boolean)
+;;     modus-themes-fringes                        (choice)
+;;     modus-themes-lang-checkers                  (choice)
+;;     modus-themes-org-blocks                     (choice)
+;;     modus-themes-org-habit                      (choice)
+;;     modus-themes-prompts                        (choice)
+;;     modus-themes-mode-line                      (choice)
+;;     modus-themes-diffs                          (choice)
+;;     modus-themes-syntax                         (choice)
+;;     modus-themes-intense-hl-line                (boolean)
+;;     modus-themes-subtle-line-numbers            (boolean)
+;;     modus-themes-paren-match                    (choice)
+;;     modus-themes-region                         (choice)
+;;     modus-themes-links                          (choice)
+;;     modus-themes-completions                    (choice)
+;;
+;; The default scale for headings is as follows (it can be customized as
+;; well---remember, no scaling takes place by default):
+;;
+;;     modus-themes-scale-1 1.05
+;;     modus-themes-scale-2 1.1
+;;     modus-themes-scale-3 1.15
+;;     modus-themes-scale-4 1.2
+;;     modus-themes-scale-5 1.3
+;;
+;; There also exist two unique customization options for overriding
+;; color palette values.  The specifics are documented in the manual.
+;; The symbols are:
+;;
+;;     modus-themes-operandi-color-overrides       (alist)
+;;     modus-themes-vivendi-color-overrides        (alist)
+;;
+;; Below is the list of explicitly supported packages or face groups
+;; (there are implicitly supported packages as well, which inherit from
+;; font-lock or some basic group).  You are encouraged to report any
+;; missing package or change you would like to see.
+;;
+;;     ace-window
+;;     ag
+;;     alert
+;;     all-the-icons
+;;     annotate
+;;     anzu
+;;     apropos
+;;     apt-sources-list
+;;     artbollocks-mode
+;;     auctex and TeX
+;;     auto-dim-other-buffers
+;;     avy
+;;     awesome-tray
+;;     bbdb
+;;     binder
+;;     bm
+;;     bongo
+;;     boon
+;;     breakpoint (provided by built-in gdb-mi.el)
+;;     buffer-expose
+;;     calendar and diary
+;;     calfw
+;;     centaur-tabs
+;;     cfrs
+;;     change-log and log-view (`vc-print-log' and `vc-print-root-log')
+;;     cider
+;;     circe
+;;     color-rg
+;;     column-enforce-mode
+;;     company-mode
+;;     company-posframe
+;;     compilation-mode
+;;     completions
+;;     consult
+;;     counsel
+;;     counsel-css
+;;     counsel-notmuch
+;;     counsel-org-capture-string
+;;     cov
+;;     cperl-mode
+;;     csv-mode
+;;     ctrlf
+;;     custom (M-x customize)
+;;     dap-mode
+;;     dashboard (emacs-dashboard)
+;;     deadgrep
+;;     debbugs
+;;     define-word
+;;     deft
+;;     dictionary
+;;     diff-hl
+;;     diff-mode
+;;     dim-autoload
+;;     dir-treeview
+;;     dired
+;;     dired-async
+;;     dired-git
+;;     dired-git-info
+;;     dired-narrow
+;;     dired-subtree
+;;     diredc
+;;     diredfl
+;;     diredp (dired+)
+;;     disk-usage
+;;     display-fill-column-indicator-mode
+;;     doom-modeline
+;;     dynamic-ruler
+;;     easy-jekyll
+;;     easy-kill
+;;     ebdb
+;;     ediff
+;;     eglot
+;;     el-search
+;;     eldoc
+;;     eldoc-box
+;;     elfeed
+;;     elfeed-score
+;;     emms
+;;     enhanced-ruby-mode
+;;     epa
+;;     equake
+;;     erc
+;;     eros
+;;     ert
+;;     eshell
+;;     eshell-fringe-status
+;;     eshell-git-prompt
+;;     eshell-prompt-extras (epe)
+;;     eshell-syntax-highlighting
+;;     evil (evil-mode)
+;;     evil-goggles
+;;     evil-snipe
+;;     evil-visual-mark-mode
+;;     eww
+;;     exwm
+;;     eyebrowse
+;;     fancy-dabbrev
+;;     flycheck
+;;     flycheck-color-mode-line
+;;     flycheck-indicator
+;;     flycheck-posframe
+;;     flymake
+;;     flyspell
+;;     flyspell-correct
+;;     flx
+;;     freeze-it
+;;     frog-menu
+;;     focus
+;;     fold-this
+;;     font-lock (generic syntax highlighting)
+;;     forge
+;;     fountain (fountain-mode)
+;;     geiser
+;;     git-commit
+;;     git-gutter (and variants)
+;;     git-lens
+;;     git-rebase
+;;     git-timemachine
+;;     git-walktree
+;;     gnus
+;;     golden-ratio-scroll-screen
+;;     helm
+;;     helm-ls-git
+;;     helm-switch-shell
+;;     helm-xref
+;;     helpful
+;;     highlight-blocks
+;;     highlight-defined
+;;     highlight-escape-sequences (`hes-mode')
+;;     highlight-indentation
+;;     highlight-numbers
+;;     highlight-symbol
+;;     highlight-tail
+;;     highlight-thing
+;;     hl-defined
+;;     hl-fill-column
+;;     hl-line-mode
+;;     hl-todo
+;;     hydra
+;;     hyperlist
+;;     ibuffer
+;;     icomplete
+;;     ido-mode
+;;     iedit
+;;     iflipb
+;;     imenu-list
+;;     indium
+;;     info
+;;     info-colors
+;;     interaction-log
+;;     ioccur
+;;     isearch, occur, etc.
+;;     isl (isearch-light)
+;;     ivy
+;;     ivy-posframe
+;;     jira (org-jira)
+;;     journalctl-mode
+;;     js2-mode
+;;     julia
+;;     jupyter
+;;     kaocha-runner
+;;     keycast
+;;     line numbers (`display-line-numbers-mode' and global variant)
+;;     lsp-mode
+;;     lsp-ui
+;;     macrostep
+;;     magit
+;;     magit-imerge
+;;     make-mode
+;;     man
+;;     marginalia
+;;     markdown-mode
+;;     markup-faces (`adoc-mode')
+;;     mentor
+;;     messages
+;;     minibuffer-line
+;;     minimap
+;;     mmm-mode
+;;     modeline
+;;     mood-line
+;;     mpdel
+;;     mu4e
+;;     mu4e-conversation
+;;     multiple-cursors
+;;     neotree
+;;     no-emoji
+;;     notmuch
+;;     num3-mode
+;;     nxml-mode
+;;     objed
+;;     orderless
+;;     org
+;;     org-journal
+;;     org-noter
+;;     org-pomodoro
+;;     org-recur
+;;     org-roam
+;;     org-superstar
+;;     org-table-sticky-header
+;;     org-tree-slide
+;;     org-treescope
+;;     origami
+;;     outline-mode
+;;     outline-minor-faces
+;;     package (M-x list-packages)
+;;     page-break-lines
+;;     paradox
+;;     paren-face
+;;     parrot
+;;     pass
+;;     pdf-tools
+;;     persp-mode
+;;     perspective
+;;     phi-grep
+;;     phi-search
+;;     pkgbuild-mode
+;;     pomidor
+;;     popup
+;;     powerline
+;;     powerline-evil
+;;     prism (see "Note for prism.el" in the manual)
+;;     proced
+;;     prodigy
+;;     quick-peek
+;;     racket-mode
+;;     rainbow-blocks
+;;     rainbow-identifiers
+;;     rainbow-delimiters
+;;     rcirc
+;;     recursion-indicator
+;;     regexp-builder (also known as `re-builder')
+;;     rg
+;;     ripgrep
+;;     rmail
+;;     ruler-mode
+;;     sallet
+;;     selectrum
+;;     selectrum-prescient
+;;     semantic
+;;     sesman
+;;     shell-script-mode
+;;     shortdoc
+;;     show-paren-mode
+;;     shr
+;;     side-notes
+;;     sieve-mode
+;;     skewer-mode
+;;     smart-mode-line
+;;     smartparens
+;;     smerge
+;;     spaceline
+;;     speedbar
+;;     spell-fu
+;;     spray
+;;     stripes
+;;     suggest
+;;     switch-window
+;;     swiper
+;;     swoop
+;;     sx
+;;     symbol-overlay
+;;     tab-bar-mode
+;;     tab-line-mode
+;;     syslog-mode
+;;     table (built-in table.el)
+;;     telephone-line
+;;     terraform-mode
+;;     term
+;;     tomatinho
+;;     transient (pop-up windows like Magit's)
+;;     trashed
+;;     treemacs
+;;     tty-menu
+;;     tuareg
+;;     typescript
+;;     undo-tree
+;;     vc (built-in mode line status for version control)
+;;     vc-annotate (C-x v g)
+;;     vdiff
+;;     vimish-fold
+;;     visible-mark
+;;     visual-regexp
+;;     volatile-highlights
+;;     vterm
+;;     wcheck-mode
+;;     web-mode
+;;     wgrep
+;;     which-function-mode
+;;     which-key
+;;     whitespace-mode
+;;     window-divider-mode
+;;     winum
+;;     writegood-mode
+;;     woman
+;;     xah-elisp-mode
+;;     xref
+;;     xterm-color (and ansi-colors)
+;;     yaml-mode
+;;     yasnippet
+;;     ztree
+;;
+;; For a complete view of the project, also refer to the following files
+;; (should be distributed in the same repository/directory as the
+;; current item):
+;;
+;; - modus-operandi-theme.el    (Light theme)
+;; - modus-vivendi-theme.el     (Dark theme)
+
+;;; News:
+;;
+;; Users updating from older versions to >= 1.0.0, are advised to read
+;; the anouncement on the emacs-devel mailing list:
+;; <https://lists.gnu.org/archive/html/emacs-devel/2021-03/msg00300.html>.
+;;
+;; The web page of the change log is also available:
+;; <https://protesilaos.com/modus-themes-changelog/>.
+;;
+;; An Info manual should be distributed with the Modus themes.
+;; Evaluate this form to access it directly:
+;;
+;;    (info "(modus-themes) Top")
+
+;;; Code:
+
+
+
+(eval-when-compile (require 'cl-lib))
+
+(defgroup modus-themes ()
+  "Options for `modus-operandi', `modus-vivendi'."
+  :group 'faces
+  :link '(info-link "(modus-themes) Top")
+  :prefix "modus-themes-"
+  :tag "Modus Themes")
+
+;;; Variables for each theme variant
+
+;;;; Modus Operandi
+
+(define-obsolete-variable-alias
+  'modus-operandi-theme-default-colors-alist
+  'modus-themes-colors-operandi
+  "1.0.0")
+
+(define-obsolete-variable-alias
+  'modus-themes-colors-operandi
+  'modus-themes-operandi-colors
+  "1.1.0")
+
+(defconst modus-themes-operandi-colors
+  '(;; base values
+    (bg-main . "#ffffff") (fg-main . "#000000")
+    (bg-dim . "#f8f8f8") (fg-dim . "#282828")
+    (bg-alt . "#f0f0f0") (fg-alt . "#505050")
+    ;; specifically for on/off states and must be combined with
+    ;; themselves, though the backgrounds are also meant to be used with
+    ;; other "active" values, defined further below
+    (bg-active . "#d7d7d7") (fg-active . "#0a0a0a")
+    (bg-inactive . "#efefef") (fg-inactive . "#404148")
+    ;; these special values are intended as alternatives to the base
+    ;; values for cases where we need to avoid confusion between the
+    ;; highlighted constructs; they must either be used as pairs based
+    ;; on their name or each can be combined with {fg,bg}-{main,alt,dim}
+    ;; always in accordance with their role as background or foreground
+    (bg-special-cold . "#dde3f4") (fg-special-cold . "#093060")
+    (bg-special-mild . "#c4ede0") (fg-special-mild . "#184034")
+    (bg-special-warm . "#f0e0d4") (fg-special-warm . "#5d3026")
+    (bg-special-calm . "#f8ddea") (fg-special-calm . "#61284f")
+    ;; foregrounds that can be combined with bg-main, bg-dim, bg-alt
+    (red . "#a60000")
+    (red-alt . "#972500")
+    (red-alt-other . "#a0132f")
+    (red-faint . "#7f1010")
+    (red-alt-faint . "#702f00")
+    (red-alt-other-faint . "#7f002f")
+    (green . "#005e00")
+    (green-alt . "#315b00")
+    (green-alt-other . "#145c33")
+    (green-faint . "#104410")
+    (green-alt-faint . "#30440f")
+    (green-alt-other-faint . "#0f443f")
+    (yellow . "#813e00")
+    (yellow-alt . "#70480f")
+    (yellow-alt-other . "#863927")
+    (yellow-faint . "#5f4400")
+    (yellow-alt-faint . "#5d5000")
+    (yellow-alt-other-faint . "#5e3a20")
+    (blue . "#0031a9")
+    (blue-alt . "#2544bb")
+    (blue-alt-other . "#0000c0")
+    (blue-faint . "#003497")
+    (blue-alt-faint . "#0f3d8c")
+    (blue-alt-other-faint . "#001087")
+    (magenta . "#721045")
+    (magenta-alt . "#8f0075")
+    (magenta-alt-other . "#5317ac")
+    (magenta-faint . "#752f50")
+    (magenta-alt-faint . "#7b206f")
+    (magenta-alt-other-faint . "#55348e")
+    (cyan . "#00538b")
+    (cyan-alt . "#30517f")
+    (cyan-alt-other . "#005a5f")
+    (cyan-faint . "#005077")
+    (cyan-alt-faint . "#354f6f")
+    (cyan-alt-other-faint . "#125458")
+    ;; these foreground values can only be combined with bg-main and are
+    ;; thus not suitable for general purpose highlighting
+    (red-intense . "#b60000")
+    (orange-intense . "#904200")
+    (green-intense . "#006800")
+    (yellow-intense . "#605b00")
+    (blue-intense . "#1f1fce")
+    (magenta-intense . "#a8007f")
+    (purple-intense . "#7f10d0")
+    (cyan-intense . "#005f88")
+    ;; those foregrounds are meant exclusively for bg-active, bg-inactive
+    (red-active . "#8a0000")
+    (green-active . "#004c2e")
+    (yellow-active . "#702d1f")
+    (blue-active . "#0030b4")
+    (magenta-active . "#5c2092")
+    (cyan-active . "#003f8a")
+    ;; the "subtle" values below be combined with fg-dim, while the
+    ;; "intense" should be paired with fg-main
+    (red-subtle-bg . "#f2b0a2")
+    (red-intense-bg . "#ff8892")
+    (green-subtle-bg . "#aecf90")
+    (green-intense-bg . "#5ada88")
+    (yellow-subtle-bg . "#e4c340")
+    (yellow-intense-bg . "#f5df23")
+    (blue-subtle-bg . "#b5d0ff")
+    (blue-intense-bg . "#6aaeff")
+    (magenta-subtle-bg . "#f0d3ff")
+    (magenta-intense-bg . "#d5baff")
+    (cyan-subtle-bg . "#c0efff")
+    (cyan-intense-bg . "#42cbd4")
+    ;; those background values must be combined with fg-main and should
+    ;; only be used for indicators that are placed on the fringes
+    (red-fringe-bg . "#f08290")
+    (green-fringe-bg . "#62c86a")
+    (yellow-fringe-bg . "#dbba3f")
+    (blue-fringe-bg . "#82afff")
+    (magenta-fringe-bg . "#e0a3ff")
+    (cyan-fringe-bg . "#2fcddf")
+    ;; those background values should only be used for graphs or similar
+    ;; applications where colored blocks are expected to be positioned
+    ;; next to each other
+    (red-graph-0-bg . "#ef6f79")
+    (red-graph-1-bg . "#ff9f9f")
+    (green-graph-0-bg . "#49d239")
+    (green-graph-1-bg . "#6dec6d")
+    (yellow-graph-0-bg . "#efec08")
+    (yellow-graph-1-bg . "#dbff4e")
+    (blue-graph-0-bg . "#55a2f0")
+    (blue-graph-1-bg . "#7fcfff")
+    (magenta-graph-0-bg . "#ba86ef")
+    (magenta-graph-1-bg . "#e7afff")
+    (cyan-graph-0-bg . "#30d3f0")
+    (cyan-graph-1-bg . "#6fefff")
+    ;; the following are for cases where both the foreground and the
+    ;; background need to have a similar hue and so must be combined
+    ;; with themselves, even though the foregrounds can be paired with
+    ;; any of the base backgrounds
+    (red-refine-bg . "#ffcccc") (red-refine-fg . "#780000")
+    (green-refine-bg . "#aceaac") (green-refine-fg . "#004c00")
+    (yellow-refine-bg . "#fff29a") (yellow-refine-fg . "#604000")
+    (blue-refine-bg . "#8ac7ff") (blue-refine-fg . "#002288")
+    (magenta-refine-bg . "#ffccff") (magenta-refine-fg . "#770077")
+    (cyan-refine-bg . "#8eecf4") (cyan-refine-fg . "#004850")
+    ;; the "nuanced" backgrounds can be combined with all of the above
+    ;; foregrounds, as well as those included here, while the "nuanced"
+    ;; foregrounds can in turn also be combined with bg-main, bg-dim,
+    ;; bg-alt
+    (red-nuanced-bg . "#fff1f0") (red-nuanced-fg . "#5f0000")
+    (green-nuanced-bg . "#ecf7ed") (green-nuanced-fg . "#004000")
+    (yellow-nuanced-bg . "#fff3da") (yellow-nuanced-fg . "#3f3000")
+    (blue-nuanced-bg . "#f3f3ff") (blue-nuanced-fg . "#201f55")
+    (magenta-nuanced-bg . "#fdf0ff") (magenta-nuanced-fg . "#541f4f")
+    (cyan-nuanced-bg . "#ebf6fa") (cyan-nuanced-fg . "#0f3360")
+    ;; the following are reserved for specific cases
+    ;;
+    ;; bg-hl-line is between bg-dim and bg-alt, so it should
+    ;; work with all accents that cover those two, plus bg-main
+    ;;
+    ;; bg-hl-alt and bg-hl-alt-intense should only be used when no
+    ;; other greyscale or fairly neutral background is available to
+    ;; properly draw attention to a given construct
+    ;;
+    ;; bg-header is between bg-active and bg-inactive, so it
+    ;; can be combined with any of the "active" values, plus the
+    ;; "special" and base foreground colors
+    ;;
+    ;; bg-paren-match, bg-paren-match-intense, bg-region and
+    ;; bg-tab-active must be combined with fg-main, while
+    ;; bg-tab-inactive should be combined with fg-dim, whereas
+    ;; bg-tab-inactive-alt goes together with fg-main
+    ;;
+    ;; bg-tab-bar is only intended for the bar that holds the tabs and
+    ;; can only be combined with fg-main
+    ;;
+    ;; fg-tab-active is meant to be combined with bg-tab-active,
+    ;; though only for styling special elements, such as underlining
+    ;; the current tab
+    ;;
+    ;; fg-escape-char-construct and fg-escape-char-backslash can
+    ;; be combined bg-main, bg-dim, bg-alt
+    ;;
+    ;; fg-lang-error, fg-lang-warning, fg-lang-note can be
+    ;; combined with bg-main, bg-dim, bg-alt
+    ;;
+    ;; fg-mark-sel, fg-mark-del, fg-mark-alt can be combined
+    ;; with bg-main, bg-dim, bg-alt, bg-hl-line
+    ;;
+    ;; fg-unfocused must be combined with bg-main
+    ;;
+    ;; fg-docstring, fg-comment-yellow can be combined with
+    ;; bg-main, bg-dim, bg-alt
+    ;;
+    ;; the window divider colors apply to faces with just an fg value
+    ;;
+    ;; all pairs are combinable with themselves
+    (bg-hl-line . "#f2eff3")
+    (bg-hl-line-intense . "#e0e0e0")
+    (bg-hl-alt . "#fbeee0")
+    (bg-hl-alt-intense . "#e8dfd1")
+    (bg-paren-match . "#e0af82")
+    (bg-paren-match-intense . "#c488ff")
+    (bg-region . "#bcbcbc")
+
+    (bg-tab-bar . "#d5d5d5")
+    (bg-tab-active . "#f6f6f6")
+    (bg-tab-inactive . "#bdbdbd")
+    (bg-tab-inactive-alt . "#999999")
+    (fg-tab-active . "#30169e")
+
+    (fg-escape-char-construct . "#8b1030")
+    (fg-escape-char-backslash . "#654d0f")
+
+    (fg-lang-error . "#9f004f")
+    (fg-lang-warning . "#604f0f")
+    (fg-lang-note . "#4040ae")
+    (fg-lang-underline-error . "#ef4f54")
+    (fg-lang-underline-warning . "#cf9f00")
+    (fg-lang-underline-note . "#3f6fef")
+
+    (fg-window-divider-inner . "#888888")
+    (fg-window-divider-outer . "#585858")
+
+    (fg-unfocused . "#56576d")
+
+    (fg-docstring . "#2a486a")
+    (fg-comment-yellow . "#5f4400")
+
+    (bg-header . "#e5e5e5") (fg-header . "#2a2a2a")
+
+    (bg-whitespace . "#f5efef") (fg-whitespace . "#624956")
+
+    (bg-diff-heading . "#b7cfe0") (fg-diff-heading . "#041645")
+    (bg-diff-added . "#d4fad4") (fg-diff-added . "#004500")
+    (bg-diff-added-deuteran . "#daefff") (fg-diff-added-deuteran . "#002044")
+    (bg-diff-changed . "#fcefcf") (fg-diff-changed . "#524200")
+    (bg-diff-removed . "#ffe8ef") (fg-diff-removed . "#691616")
+
+    (bg-diff-refine-added . "#94cf94") (fg-diff-refine-added . "#002a00")
+    (bg-diff-refine-added-deuteran . "#77c0ef") (fg-diff-refine-added-deuteran 
. "#000035")
+    (bg-diff-refine-changed . "#cccf8f") (fg-diff-refine-changed . "#302010")
+    (bg-diff-refine-removed . "#daa2b0") (fg-diff-refine-removed . "#400000")
+
+    (bg-diff-focus-added . "#bbeabb") (fg-diff-focus-added . "#002c00")
+    (bg-diff-focus-added-deuteran . "#bacfff") (fg-diff-focus-added-deuteran . 
"#001755")
+    (bg-diff-focus-changed . "#ecdfbf") (fg-diff-focus-changed . "#392900")
+    (bg-diff-focus-removed . "#efcbcf") (fg-diff-focus-removed . "#4a0000")
+
+    (bg-diff-neutral-0 . "#979797") (fg-diff-neutral-0 . "#040404")
+    (bg-diff-neutral-1 . "#b0b0b0") (fg-diff-neutral-1 . "#252525")
+    (bg-diff-neutral-2 . "#cccccc") (fg-diff-neutral-2 . "#3a3a3a")
+
+    (bg-mark-sel . "#a0f0cf") (fg-mark-sel . "#005040")
+    (bg-mark-del . "#ffccbb") (fg-mark-del . "#840040")
+    (bg-mark-alt . "#f5d88f") (fg-mark-alt . "#782900"))
+  "The entire palette of `modus-operandi' theme.
+Each element has the form (NAME . HEX) with the former as a
+symbol and the latter as a string.")
+
+;;;; Modus Vivendi
+
+(define-obsolete-variable-alias
+  'modus-vivendi-theme-default-colors-alist
+  'modus-themes-colors-vivendi
+  "1.0.0")
+
+(define-obsolete-variable-alias
+  'modus-themes-colors-vivendi
+  'modus-themes-vivendi-colors
+  "1.1.0")
+
+(defconst modus-themes-vivendi-colors
+  '(;; base values
+    (bg-main . "#000000") (fg-main . "#ffffff")
+    (bg-dim . "#110b11") (fg-dim . "#e0e6f0")
+    (bg-alt . "#181a20") (fg-alt . "#a8a8a8")
+    ;; specifically for on/off states and must be combined with
+    ;; themselves, though the backgrounds are also meant to be used with
+    ;; other "active" values, defined further below
+    (bg-active . "#323232") (fg-active . "#f4f4f4")
+    (bg-inactive . "#1e1e1e") (fg-inactive . "#bfc0c4")
+    ;; these special values are intended as alternatives to the base
+    ;; values for cases where we need to avoid confusion between the
+    ;; highlighted constructs; they must either be used as pairs based
+    ;; on their name or each can be combined with {fg,bg}-{main,alt,dim}
+    ;; always in accordance with their role as background or foreground
+    (bg-special-cold . "#203448") (fg-special-cold . "#c6eaff")
+    (bg-special-mild . "#00322e") (fg-special-mild . "#bfebe0")
+    (bg-special-warm . "#382f27") (fg-special-warm . "#f8dec0")
+    (bg-special-calm . "#392a48") (fg-special-calm . "#fbd6f4")
+    ;; foregrounds that can be combined with bg-main, bg-dim, bg-alt
+    (red . "#ff8059")
+    (red-alt . "#f4923b")
+    (red-alt-other . "#ff9977")
+    (red-faint . "#ffa0a0")
+    (red-alt-faint . "#f5aa80")
+    (red-alt-other-faint . "#ff9fbf")
+    (green . "#44bc44")
+    (green-alt . "#70c900")
+    (green-alt-other . "#00cd68")
+    (green-faint . "#88cf88")
+    (green-alt-faint . "#a8cf88")
+    (green-alt-other-faint . "#88cfaf")
+    (yellow . "#eecc00")
+    (yellow-alt . "#cfdf30")
+    (yellow-alt-other . "#f0ce43")
+    (yellow-faint . "#d2b580")
+    (yellow-alt-faint . "#cabf77")
+    (yellow-alt-other-faint . "#d0ba95")
+    (blue . "#2fafff")
+    (blue-alt . "#79a8ff" )
+    (blue-alt-other . "#00bcff")
+    (blue-faint . "#92baff")
+    (blue-alt-faint . "#a0acf5")
+    (blue-alt-other-faint . "#87c8ff")
+    (magenta . "#feacd0")
+    (magenta-alt . "#f78fe7")
+    (magenta-alt-other . "#b6a0ff")
+    (magenta-faint . "#e0b2d6")
+    (magenta-alt-faint . "#ef9fe4")
+    (magenta-alt-other-faint . "#cfa6ff")
+    (cyan . "#00d3d0")
+    (cyan-alt . "#4ae8fc")
+    (cyan-alt-other . "#6ae4b9")
+    (cyan-faint . "#90c4ed")
+    (cyan-alt-faint . "#a0bfdf")
+    (cyan-alt-other-faint . "#a4d0bb")
+    ;; these foreground values can only be combined with bg-main and are
+    ;; thus not suitable for general purpose highlighting
+    (red-intense . "#fe6060")
+    (orange-intense . "#fba849")
+    (green-intense . "#4fe42f")
+    (yellow-intense . "#f0dd60")
+    (blue-intense . "#4fafff")
+    (magenta-intense . "#ff62d4")
+    (purple-intense . "#9f80ff")
+    (cyan-intense . "#3fdfd0")
+    ;; those foregrounds are meant exclusively for bg-active, bg-inactive
+    (red-active . "#ffa7ba")
+    (green-active . "#70d73f")
+    (yellow-active . "#dbbe5f")
+    (blue-active . "#34cfff")
+    (magenta-active . "#d5b1ff")
+    (cyan-active . "#00d8b4")
+    ;; the "subtle" values below be combined with fg-dim, while the
+    ;; "intense" should be paired with fg-main
+    (red-subtle-bg . "#762422")
+    (red-intense-bg . "#a4202a")
+    (green-subtle-bg . "#2f4a00")
+    (green-intense-bg . "#006800")
+    (yellow-subtle-bg . "#604200")
+    (yellow-intense-bg . "#874900")
+    (blue-subtle-bg . "#10387c")
+    (blue-intense-bg . "#2a40b8")
+    (magenta-subtle-bg . "#49366e")
+    (magenta-intense-bg . "#7042a2")
+    (cyan-subtle-bg . "#00415e")
+    (cyan-intense-bg . "#005f88")
+    ;; those background values must be combined with fg-main and should
+    ;; only be used for indicators that are placed on the fringes
+    (red-fringe-bg . "#8f1f4b")
+    (green-fringe-bg . "#006700")
+    (yellow-fringe-bg . "#6f4f00")
+    (blue-fringe-bg . "#3f33af")
+    (magenta-fringe-bg . "#6f2f89")
+    (cyan-fringe-bg . "#004f8f")
+    ;; those background values should only be used for graphs or similar
+    ;; applications where colored blocks are expected to be positioned
+    ;; next to each other
+    (red-graph-0-bg . "#af0404")
+    (red-graph-1-bg . "#801f2f")
+    (green-graph-0-bg . "#24ba2f")
+    (green-graph-1-bg . "#0f8f07")
+    (yellow-graph-0-bg . "#ffd03e")
+    (yellow-graph-1-bg . "#d7d800")
+    (blue-graph-0-bg . "#406fff")
+    (blue-graph-1-bg . "#2f50c8")
+    (magenta-graph-0-bg . "#af7bee")
+    (magenta-graph-1-bg . "#7f59cf")
+    (cyan-graph-0-bg . "#47dcfa")
+    (cyan-graph-1-bg . "#0bc0df")
+    ;; the following are for cases where both the foreground and the
+    ;; background need to have a similar hue and so must be combined
+    ;; with themselves, even though the foregrounds can be paired with
+    ;; any of the base backgrounds
+    (red-refine-bg . "#77002a") (red-refine-fg . "#ffb9ab")
+    (green-refine-bg . "#00422a") (green-refine-fg . "#9ff0cf")
+    (yellow-refine-bg . "#693200") (yellow-refine-fg . "#e2d980")
+    (blue-refine-bg . "#242679") (blue-refine-fg . "#8ec6ff")
+    (magenta-refine-bg . "#71206a") (magenta-refine-fg . "#ffcaf0")
+    (cyan-refine-bg . "#004065") (cyan-refine-fg . "#8ae4f2")
+    ;; the "nuanced" backgrounds can be combined with all of the above
+    ;; foregrounds, as well as those included here, while the "nuanced"
+    ;; foregrounds can in turn also be combined with bg-main, bg-dim,
+    ;; bg-alt
+    (red-nuanced-bg . "#2c0614") (red-nuanced-fg . "#ffcccc")
+    (green-nuanced-bg . "#001904") (green-nuanced-fg . "#b8e2b8")
+    (yellow-nuanced-bg . "#221000") (yellow-nuanced-fg . "#dfdfb0")
+    (blue-nuanced-bg . "#0f0e39") (blue-nuanced-fg . "#bfd9ff")
+    (magenta-nuanced-bg . "#230631") (magenta-nuanced-fg . "#e5cfef")
+    (cyan-nuanced-bg . "#041529") (cyan-nuanced-fg . "#a8e5e5")
+    ;; the following are reserved for specific cases
+    ;;
+    ;; bg-hl-line is between bg-dim and bg-alt, so it should
+    ;; work with all accents that cover those two, plus bg-main
+    ;;
+    ;; bg-hl-alt and bg-hl-alt-intense should only be used when no
+    ;; other greyscale or fairly neutral background is available to
+    ;; properly draw attention to a given construct
+    ;;
+    ;; bg-header is between bg-active and bg-inactive, so it
+    ;; can be combined with any of the "active" values, plus the
+    ;; "special" and base foreground colors
+    ;;
+    ;; bg-paren-match, bg-paren-match-intense, bg-region and
+    ;; bg-tab-active must be combined with fg-main, while
+    ;; bg-tab-inactive should be combined with fg-dim, whereas
+    ;; bg-tab-inactive-alt goes together with fg-main
+    ;;
+    ;; bg-tab-bar is only intended for the bar that holds the tabs and
+    ;; can only be combined with fg-main
+    ;;
+    ;; fg-tab-active is meant to be combined with bg-tab-active,
+    ;; though only for styling special elements, such as underlining
+    ;; the current tab
+    ;;
+    ;; fg-escape-char-construct and fg-escape-char-backslash can
+    ;; be combined bg-main, bg-dim, bg-alt
+    ;;
+    ;; fg-lang-error, fg-lang-warning, fg-lang-note can be
+    ;; combined with bg-main, bg-dim, bg-alt
+    ;;
+    ;; fg-mark-sel, fg-mark-del, fg-mark-alt can be combined
+    ;; with bg-main, bg-dim, bg-alt, bg-hl-line
+    ;;
+    ;; fg-unfocused must be combined with bg-main
+    ;;
+    ;; fg-docstring, fg-comment-yellow can be combined with
+    ;; bg-main, bg-dim, bg-alt
+    ;;
+    ;; the window divider colors apply to faces with just an fg value
+    ;;
+    ;; all pairs are combinable with themselves
+    (bg-hl-line . "#151823")
+    (bg-hl-line-intense . "#2f2f2f")
+    (bg-hl-alt . "#181732")
+    (bg-hl-alt-intense . "#282e46")
+    (bg-paren-match . "#5f362f")
+    (bg-paren-match-intense . "#7416b5")
+    (bg-region . "#3c3c3c")
+
+    (bg-tab-bar . "#2c2c2c")
+    (bg-tab-active . "#0e0e0e")
+    (bg-tab-inactive . "#3d3d3d")
+    (bg-tab-inactive-alt . "#595959")
+    (fg-tab-active . "#5ac3cf")
+
+    (fg-escape-char-construct . "#e7a59a")
+    (fg-escape-char-backslash . "#abab00")
+
+    (fg-lang-error . "#ef8690")
+    (fg-lang-warning . "#b0aa00")
+    (fg-lang-note . "#9d9def")
+    (fg-lang-underline-error . "#ff4a6f")
+    (fg-lang-underline-warning . "#d0de00")
+    (fg-lang-underline-note . "#5f6fff")
+
+    (fg-window-divider-inner . "#646464")
+    (fg-window-divider-outer . "#969696")
+
+    (fg-unfocused . "#93959b")
+
+    (fg-docstring . "#b0d6f5")
+    (fg-comment-yellow . "#cab98f")
+
+    (bg-header . "#212121") (fg-header . "#dddddd")
+
+    (bg-whitespace . "#101424") (fg-whitespace . "#aa9e9f")
+
+    (bg-diff-heading . "#304466") (fg-diff-heading . "#dae7ff")
+    (bg-diff-added . "#0a280a") (fg-diff-added . "#94ba94")
+    (bg-diff-added-deuteran . "#001a3f") (fg-diff-added-deuteran . "#c4cdf2")
+    (bg-diff-changed . "#2a2000") (fg-diff-changed . "#b0ba9f")
+    (bg-diff-removed . "#40160f") (fg-diff-removed . "#c6adaa")
+
+    (bg-diff-refine-added . "#005a36") (fg-diff-refine-added . "#e0f6e0")
+    (bg-diff-refine-added-deuteran . "#234f8f") (fg-diff-refine-added-deuteran 
. "#dde4ff")
+    (bg-diff-refine-changed . "#585800") (fg-diff-refine-changed . "#ffffcc")
+    (bg-diff-refine-removed . "#852828") (fg-diff-refine-removed . "#ffd9eb")
+
+    (bg-diff-focus-added . "#203d20") (fg-diff-focus-added . "#b4ddb4")
+    (bg-diff-focus-added-deuteran . "#00405f") (fg-diff-focus-added-deuteran . 
"#bfe4ff")
+    (bg-diff-focus-changed . "#4a3a10") (fg-diff-focus-changed . "#d0daaf")
+    (bg-diff-focus-removed . "#5e2526") (fg-diff-focus-removed . "#eebdba")
+
+    (bg-diff-neutral-0 . "#575757") (fg-diff-neutral-0 . "#fcfcfc")
+    (bg-diff-neutral-1 . "#454545") (fg-diff-neutral-1 . "#dddddd")
+    (bg-diff-neutral-2 . "#313131") (fg-diff-neutral-2 . "#bfbfbf")
+
+    (bg-mark-sel . "#002f2f") (fg-mark-sel . "#60cfa2")
+    (bg-mark-del . "#5a0000") (fg-mark-del . "#ff99aa")
+    (bg-mark-alt . "#3f2210") (fg-mark-alt . "#f0aa20"))
+  "The entire palette of `modus-vivendi' theme.
+Each element has the form (NAME . HEX) with the former as a
+symbol and the latter as a string.")
+
+
+
+;;; Custom faces
+
+;; These faces are used internally to ensure consistency between various
+;; groups and to streamline the evaluation of relevant customization
+;; options.
+(defface modus-theme-subtle-red nil
+  "Subtle red background combined with a dimmed foreground.
+This is used for general purpose highlighting, mostly in buffers
+or for completion interfaces.
+
+The actual styling of the face is done by `modus-themes-faces'.")
+
+(defface modus-theme-subtle-green nil
+  "Subtle green background combined with a dimmed foreground.
+This is used for general purpose highlighting, mostly in buffers
+or for completion interfaces.
+
+The actual styling of the face is done by `modus-themes-faces'.")
+
+(defface modus-theme-subtle-yellow nil
+  "Subtle yellow background combined with a dimmed foreground.
+This is used for general purpose highlighting, mostly in buffers
+or for completion interfaces.
+
+The actual styling of the face is done by `modus-themes-faces'.")
+
+(defface modus-theme-subtle-blue nil
+  "Subtle blue background combined with a dimmed foreground.
+This is used for general purpose highlighting, mostly in buffers
+or for completion interfaces.
+
+The actual styling of the face is done by `modus-themes-faces'.")
+
+(defface modus-theme-subtle-magenta nil
+  "Subtle magenta background combined with a dimmed foreground.
+This is used for general purpose highlighting, mostly in buffers
+or for completion interfaces.
+
+The actual styling of the face is done by `modus-themes-faces'.")
+
+(defface modus-theme-subtle-cyan nil
+  "Subtle cyan background combined with a dimmed foreground.
+This is used for general purpose highlighting, mostly in buffers
+or for completion interfaces.
+
+The actual styling of the face is done by `modus-themes-faces'.")
+
+(defface modus-theme-subtle-neutral nil
+  "Subtle gray background combined with a dimmed foreground.
+This is used for general purpose highlighting, mostly in buffers
+or for completion interfaces.
+
+The actual styling of the face is done by `modus-themes-faces'.")
+
+(defface modus-theme-intense-red nil
+  "Intense red background combined with the main foreground.
+This is used for general purpose highlighting, mostly in buffers
+or for completion interfaces.
+
+The actual styling of the face is done by `modus-themes-faces'.")
+
+(defface modus-theme-intense-green nil
+  "Intense green background combined with the main foreground.
+This is used for general purpose highlighting, mostly in buffers
+or for completion interfaces.
+
+The actual styling of the face is done by `modus-themes-faces'.")
+
+(defface modus-theme-intense-yellow nil
+  "Intense yellow background combined with the main foreground.
+This is used for general purpose highlighting, mostly in buffers
+or for completion interfaces.
+
+The actual styling of the face is done by `modus-themes-faces'.")
+
+(defface modus-theme-intense-blue nil
+  "Intense blue background combined with the main foreground.
+This is used for general purpose highlighting, mostly in buffers
+or for completion interfaces.
+
+The actual styling of the face is done by `modus-themes-faces'.")
+
+(defface modus-theme-intense-magenta nil
+  "Intense magenta background combined with the main foreground.
+This is used for general purpose highlighting, mostly in buffers
+or for completion interfaces.
+
+The actual styling of the face is done by `modus-themes-faces'.")
+
+(defface modus-theme-intense-cyan nil
+  "Intense cyan background combined with the main foreground.
+This is used for general purpose highlighting, mostly in buffers
+or for completion interfaces.
+
+The actual styling of the face is done by `modus-themes-faces'.")
+
+(defface modus-theme-intense-neutral nil
+  "Intense gray background combined with the main foreground.
+This is used for general purpose highlighting, mostly in buffers
+or for completion interfaces.
+
+The actual styling of the face is done by `modus-themes-faces'.")
+
+(defface modus-theme-refine-red nil
+  "Combination of accented red background and foreground.
+This is used for general purpose highlighting, mostly in buffers
+or for completion interfaces.
+
+The actual styling of the face is done by `modus-themes-faces'.")
+
+(defface modus-theme-refine-green nil
+  "Combination of accented green background and foreground.
+This is used for general purpose highlighting, mostly in buffers
+or for completion interfaces.
+
+The actual styling of the face is done by `modus-themes-faces'.")
+
+(defface modus-theme-refine-yellow nil
+  "Combination of accented yellow background and foreground.
+This is used for general purpose highlighting, mostly in buffers
+or for completion interfaces.
+
+The actual styling of the face is done by `modus-themes-faces'.")
+
+(defface modus-theme-refine-blue nil
+  "Combination of accented blue background and foreground.
+This is used for general purpose highlighting, mostly in buffers
+or for completion interfaces.
+
+The actual styling of the face is done by `modus-themes-faces'.")
+
+(defface modus-theme-refine-magenta nil
+  "Combination of accented magenta background and foreground.
+This is used for general purpose highlighting, mostly in buffers
+or for completion interfaces.
+
+The actual styling of the face is done by `modus-themes-faces'.")
+
+(defface modus-theme-refine-cyan nil
+  "Combination of accented cyan background and foreground.
+This is used for general purpose highlighting, mostly in buffers
+or for completion interfaces.
+
+The actual styling of the face is done by `modus-themes-faces'.")
+
+(defface modus-theme-active-red nil
+  "A red background meant for use on the modeline or similar.
+This is combined with the modelines primary foreground value.
+
+The actual styling of the face is done by `modus-themes-faces'.")
+
+(defface modus-theme-active-green nil
+  "A green background meant for use on the modeline or similar.
+This is combined with the modelines primary foreground value.
+
+The actual styling of the face is done by `modus-themes-faces'.")
+
+(defface modus-theme-active-yellow nil
+  "A yellow background meant for use on the modeline or similar.
+This is combined with the modelines primary foreground value.
+
+The actual styling of the face is done by `modus-themes-faces'.")
+
+(defface modus-theme-active-blue nil
+  "A blue background meant for use on the modeline or similar.
+This is combined with the modelines primary foreground value.
+
+The actual styling of the face is done by `modus-themes-faces'.")
+
+(defface modus-theme-active-magenta nil
+  "A magenta background meant for use on the modeline or similar.
+This is combined with the modelines primary foreground value.
+
+The actual styling of the face is done by `modus-themes-faces'.")
+
+(defface modus-theme-active-cyan nil
+  "A cyan background meant for use on the modeline or similar.
+This is combined with the modelines primary foreground value.
+
+The actual styling of the face is done by `modus-themes-faces'.")
+
+(defface modus-theme-fringe-red nil
+  "A red background meant for use on the fringe or similar.
+This is combined with the main foreground value.
+
+The actual styling of the face is done by `modus-themes-faces'.")
+
+(defface modus-theme-fringe-green nil
+  "A green background meant for use on the fringe or similar.
+This is combined with the main foreground value.
+
+The actual styling of the face is done by `modus-themes-faces'.")
+
+(defface modus-theme-fringe-yellow nil
+  "A yellow background meant for use on the fringe or similar.
+This is combined with the main foreground value.
+
+The actual styling of the face is done by `modus-themes-faces'.")
+
+(defface modus-theme-fringe-blue nil
+  "A blue background meant for use on the fringe or similar.
+This is combined with the main foreground value.
+
+The actual styling of the face is done by `modus-themes-faces'.")
+
+(defface modus-theme-fringe-magenta nil
+  "A magenta background meant for use on the fringe or similar.
+This is combined with the main foreground value.
+
+The actual styling of the face is done by `modus-themes-faces'.")
+
+(defface modus-theme-fringe-cyan nil
+  "A cyan background meant for use on the fringe or similar.
+This is combined with the main foreground value.
+
+The actual styling of the face is done by `modus-themes-faces'.")
+
+(defface modus-theme-nuanced-red nil
+  "A nuanced red background.
+This does not specify a foreground of its own.  Instead it is meant to
+serve as the backdrop for elements such as Org blocks, headings, and any
+other surface that needs to retain the colors on display.
+
+The actual styling of the face is done by `modus-themes-faces'.")
+
+(defface modus-theme-nuanced-green nil
+  "A nuanced green background.
+This does not specify a foreground of its own.  Instead it is meant to
+serve as the backdrop for elements such as Org blocks, headings, and any
+other surface that needs to retain the colors on display.
+
+The actual styling of the face is done by `modus-themes-faces'.")
+
+(defface modus-theme-nuanced-yellow nil
+  "A nuanced yellow background.
+This does not specify a foreground of its own.  Instead it is meant to
+serve as the backdrop for elements such as Org blocks, headings, and any
+other surface that needs to retain the colors on display.
+
+The actual styling of the face is done by `modus-themes-faces'.")
+
+(defface modus-theme-nuanced-blue nil
+  "A nuanced blue background.
+This does not specify a foreground of its own.  Instead it is meant to
+serve as the backdrop for elements such as Org blocks, headings, and any
+other surface that needs to retain the colors on display.
+
+The actual styling of the face is done by `modus-themes-faces'.")
+
+(defface modus-theme-nuanced-magenta nil
+  "A nuanced magenta background.
+This does not specify a foreground of its own.  Instead it is meant to
+serve as the backdrop for elements such as Org blocks, headings, and any
+other surface that needs to retain the colors on display.
+
+The actual styling of the face is done by `modus-themes-faces'.")
+
+(defface modus-theme-nuanced-cyan nil
+  "A nuanced cyan background.
+This does not specify a foreground of its own.  Instead it is meant to
+serve as the backdrop for elements such as Org blocks, headings, and any
+other surface that needs to retain the colors on display.
+
+The actual styling of the face is done by `modus-themes-faces'.")
+
+(defface modus-theme-special-cold nil
+  "Combines the 'special cold' background and foreground values.
+This is intended for cases when a neutral gray background is not
+suitable and where a combination of more saturated colors would not be
+appropriate.
+
+The actual styling of the face is done by `modus-themes-faces'.")
+
+(defface modus-theme-special-mild nil
+  "Combines the 'special mild' background and foreground values.
+This is intended for cases when a neutral gray background is not
+suitable and where a combination of more saturated colors would not be
+appropriate.
+
+The actual styling of the face is done by `modus-themes-faces'.")
+
+(defface modus-theme-special-warm nil
+  "Combines the 'special warm' background and foreground values.
+This is intended for cases when a neutral gray background is not
+suitable and where a combination of more saturated colors would not be
+appropriate.
+
+The actual styling of the face is done by `modus-themes-faces'.")
+
+(defface modus-theme-special-calm nil
+  "Combines the 'special calm' background and foreground values.
+This is intended for cases when a neutral gray background is not
+suitable and where a combination of more saturated colors would not be
+appropriate.
+
+The actual styling of the face is done by `modus-themes-faces'.")
+
+(defface modus-theme-diff-added nil
+  "Combines green colors for the 'added' state in diffs.
+The applied colors are contingent on the value assigned to
+`modus-themes-diffs'.
+
+The actual styling of the face is done by `modus-themes-faces'.")
+
+(defface modus-theme-diff-changed nil
+  "Combines yellow colors for the 'changed' state in diffs.
+The applied colors are contingent on the value assigned to
+`modus-themes-diffs'.
+
+The actual styling of the face is done by `modus-themes-faces'.")
+
+(defface modus-theme-diff-removed nil
+  "Combines red colors for the 'removed' state in diffs.
+The applied colors are contingent on the value assigned to
+`modus-themes-diffs'.
+
+The actual styling of the face is done by `modus-themes-faces'.")
+
+(defface modus-theme-diff-refine-added nil
+  "Combines green colors for word-wise 'added' state in diffs.
+The applied colors are contingent on the value assigned to
+`modus-themes-diffs'.
+
+The actual styling of the face is done by `modus-themes-faces'.")
+
+(defface modus-theme-diff-refine-changed nil
+  "Combines yellow colors for word-wise 'changed' state in diffs.
+The applied colors are contingent on the value assigned to
+`modus-themes-diffs'.
+
+The actual styling of the face is done by `modus-themes-faces'.")
+
+(defface modus-theme-diff-refine-removed nil
+  "Combines red colors for word-wise 'removed' state in diffs.
+The applied colors are contingent on the value assigned to
+`modus-themes-diffs'.
+
+The actual styling of the face is done by `modus-themes-faces'.")
+
+(defface modus-theme-diff-focus-added nil
+  "Combines green colors for the focused 'added' state in diffs.
+The applied colors are contingent on the value assigned to
+`modus-themes-diffs'.
+
+The actual styling of the face is done by `modus-themes-faces'.")
+
+(defface modus-theme-diff-focus-changed nil
+  "Combines yellow colors for the focused 'changed' state in.
+The applied colors are contingent on the value assigned to
+`modus-themes-diffs'.
+
+The actual styling of the face is done by `modus-themes-faces'.")
+
+(defface modus-theme-diff-focus-removed nil
+  "Combines red colors for the focused 'removed' state in diffs.
+The applied colors are contingent on the value assigned to
+`modus-themes-diffs'.
+
+The actual styling of the face is done by `modus-themes-faces'.")
+
+(defface modus-theme-diff-heading nil
+  "Combines blue colors for the diff hunk heading.
+The applied colors are contingent on the value assigned to
+`modus-themes-diffs'.
+
+The actual styling of the face is done by `modus-themes-faces'.")
+
+(defface modus-theme-pseudo-header nil
+  "Generic style for some elements that function like headings.
+The actual styling of the face is done by `modus-themes-faces'.")
+
+(defface modus-theme-mark-alt nil
+  "Combines yellow colors for marking special lines
+This is intended for use in modes such as Dired, Ibuffer, Proced.
+
+The actual styling of the face is done by `modus-themes-faces'.")
+
+(defface modus-theme-mark-del nil
+  "Combines red colors for marking deletable lines
+This is intended for use in modes such as Dired, Ibuffer, Proced.
+
+The actual styling of the face is done by `modus-themes-faces'.")
+
+(defface modus-theme-mark-sel nil
+  "Combines green colors for marking lines
+This is intended for use in modes such as Dired, Ibuffer, Proced.
+
+The actual styling of the face is done by `modus-themes-faces'.")
+
+(defface modus-theme-mark-symbol nil
+  "Applies a blue color and other styles for mark indicators.
+This is intended for use in modes such as Dired, Ibuffer, Proced.
+
+The actual styling of the face is done by `modus-themes-faces'.")
+
+(defface modus-theme-heading-1 nil
+  "General purpose face for use in headings level 1
+The exact attributes assigned to this face are contingent on the values
+assigned to the `modus-themes-headings' variable.
+
+The actual styling of the face is done by `modus-themes-faces'.")
+
+(defface modus-theme-heading-2 nil
+  "General purpose face for use in headings level 2.
+The exact attributes assigned to this face are contingent on the values
+assigned to the `modus-themes-headings' variable.
+
+The actual styling of the face is done by `modus-themes-faces'.")
+
+(defface modus-theme-heading-3 nil
+  "General purpose face for use in headings level 3.
+The exact attributes assigned to this face are contingent on the values
+assigned to the `modus-themes-headings' variable.
+
+The actual styling of the face is done by `modus-themes-faces'.")
+
+(defface modus-theme-heading-4 nil
+  "General purpose face for use in headings level 4.
+The exact attributes assigned to this face are contingent on the values
+assigned to the `modus-themes-headings' variable.
+
+The actual styling of the face is done by `modus-themes-faces'.")
+
+(defface modus-theme-heading-5 nil
+  "General purpose face for use in headings level 5.
+The exact attributes assigned to this face are contingent on the values
+assigned to the `modus-themes-headings' variable.
+
+The actual styling of the face is done by `modus-themes-faces'.")
+
+(defface modus-theme-heading-6 nil
+  "General purpose face for use in headings level 6.
+The exact attributes assigned to this face are contingent on the values
+assigned to the `modus-themes-headings' variable.
+
+The actual styling of the face is done by `modus-themes-faces'.")
+
+(defface modus-theme-heading-7 nil
+  "General purpose face for use in headings level 7.
+The exact attributes assigned to this face are contingent on the values
+assigned to the `modus-themes-headings' variable.
+
+The actual styling of the face is done by `modus-themes-faces'.")
+
+(defface modus-theme-heading-8 nil
+  "General purpose face for use in headings level 8.
+The exact attributes assigned to this face are contingent on the values
+assigned to the `modus-themes-headings' variable.
+
+The actual styling of the face is done by `modus-themes-faces'.")
+
+(defface modus-theme-hl-line nil
+  "General purpose face for the current line.
+The exact attributes assigned to this face are contingent on the values
+assigned to the `modus-themes-intense-hl-line' variable.
+
+The actual styling of the face is done by `modus-themes-faces'.")
+
+(defface modus-theme-bold nil
+  "Generic face for applying a conditional bold weight.
+This behaves in accordance with `modus-themes-bold-constructs'.
+
+The actual styling of the face is done by `modus-themes-faces'.")
+
+(defface modus-theme-slant nil
+  "Generic face for applying a conditional slant (italics).
+This behaves in accordance with `modus-themes-slanted-constructs'.
+
+The actual styling of the face is done by `modus-themes-faces'.")
+
+(defface modus-theme-variable-pitch nil
+  "Generic face for applying a conditional `variable-pitch'.
+This behaves in accordance with `modus-themes-no-mixed-fonts',
+`modus-themes-variable-pitch-headings' for all heading levels, and
+`modus-themes-variable-pitch-ui'.
+
+The actual styling of the face is done by `modus-themes-faces'.")
+
+(defface modus-theme-graph-red-0 nil
+  "Special subdued red face for use in graphs.
+This is intended to be applied in contexts such as the Org agenda habit
+graph where faithfulness to the semantics of a color value is of
+paramount importance.
+
+The actual styling of the face is done by `modus-themes-faces'.")
+
+(defface modus-theme-graph-red-1 nil
+  "Special prominent red face for use in graphs.
+This is intended to be applied in contexts such as the Org agenda habit
+graph where faithfulness to the semantics of a color value is of
+paramount importance.
+
+The actual styling of the face is done by `modus-themes-faces'.")
+
+(defface modus-theme-graph-green-0 nil
+  "Special subdued green face for use in graphs.
+This is intended to be applied in contexts such as the Org agenda habit
+graph where faithfulness to the semantics of a color value is of
+paramount importance.
+
+The actual styling of the face is done by `modus-themes-faces'.")
+
+(defface modus-theme-graph-green-1 nil
+  "Special prominent green face for use in graphs.
+This is intended to be applied in contexts such as the Org agenda habit
+graph where faithfulness to the semantics of a color value is of
+paramount importance.
+
+The actual styling of the face is done by `modus-themes-faces'.")
+
+(defface modus-theme-graph-yellow-0 nil
+  "Special subdued yellow face for use in graphs.
+This is intended to be applied in contexts such as the Org agenda habit
+graph where faithfulness to the semantics of a color value is of
+paramount importance.
+
+The actual styling of the face is done by `modus-themes-faces'.")
+
+(defface modus-theme-graph-yellow-1 nil
+  "Special prominent yellow face for use in graphs.
+This is intended to be applied in contexts such as the Org agenda habit
+graph where faithfulness to the semantics of a color value is of
+paramount importance.
+
+The actual styling of the face is done by `modus-themes-faces'.")
+
+(defface modus-theme-graph-blue-0 nil
+  "Special subdued blue face for use in graphs.
+This is intended to be applied in contexts such as the Org agenda habit
+graph where faithfulness to the semantics of a color value is of
+paramount importance.
+
+The actual styling of the face is done by `modus-themes-faces'.")
+
+(defface modus-theme-graph-blue-1 nil
+  "Special prominent blue face for use in graphs.
+This is intended to be applied in contexts such as the Org agenda habit
+graph where faithfulness to the semantics of a color value is of
+paramount importance.
+
+The actual styling of the face is done by `modus-themes-faces'.")
+
+(defface modus-theme-graph-magenta-0 nil
+  "Special subdued magenta face for use in graphs.
+This is intended to be applied in contexts such as the Org agenda habit
+graph where faithfulness to the semantics of a color value is of
+paramount importance.
+
+The actual styling of the face is done by `modus-themes-faces'.")
+
+(defface modus-theme-graph-magenta-1 nil
+  "Special prominent magenta face for use in graphs.
+This is intended to be applied in contexts such as the Org agenda habit
+graph where faithfulness to the semantics of a color value is of
+paramount importance.
+
+The actual styling of the face is done by `modus-themes-faces'.")
+
+(defface modus-theme-graph-cyan-0 nil
+  "Special subdued cyan face for use in graphs.
+This is intended to be applied in contexts such as the Org agenda habit
+graph where faithfulness to the semantics of a color value is of
+paramount importance.
+
+The actual styling of the face is done by `modus-themes-faces'.")
+
+(defface modus-theme-graph-cyan-1 nil
+  "Special prominent cyan face for use in graphs.
+This is intended to be applied in contexts such as the Org agenda habit
+graph where faithfulness to the semantics of a color value is of
+paramount importance.
+
+The actual styling of the face is done by `modus-themes-faces'.")
+
+(defface modus-theme-lang-note nil
+  "Generic face for linter or spell checker notes.
+The exact attributes and color combinations are controlled by
+`modus-themes-lang-checkers'.
+
+The actual styling of the face is done by `modus-themes-faces'.")
+
+(defface modus-theme-lang-warning nil
+  "Generic face for linter or spell checker warnings.
+The exact attributes and color combinations are controlled by
+`modus-themes-lang-checkers'.
+
+The actual styling of the face is done by `modus-themes-faces'.")
+
+(defface modus-theme-lang-error nil
+  "Generic face for linter or spell checker errors.
+The exact attributes and color combinations are controlled by
+`modus-themes-lang-checkers'.
+
+The actual styling of the face is done by `modus-themes-faces'.")
+
+
+
+;;; Customization options
+
+;;;; Current customization options (>= 1.0.0)
+
+(defcustom modus-themes-operandi-color-overrides nil
+  "Override colors in the Modus Operandi palette.
+
+For form, see `modus-themes-operandi-colors'."
+  :group 'modus-themes
+  :package-version '(modus-themes . "1.1.0")
+  :version "28.1"
+  :type '(alist :key-type symbol :value-type color)
+  :link '(info-link "(modus-themes) Override colors (DIY)"))
+
+(defcustom modus-themes-vivendi-color-overrides nil
+  "Override colors in the Modus Vivendi palette.
+
+For form, see `modus-themes-vivendi-colors'."
+  :group 'modus-themes
+  :package-version '(modus-themes . "1.1.0")
+  :version "28.1"
+  :type '(alist :key-type symbol :value-type color)
+  :link '(info-link "(modus-themes) Override colors (DIY)"))
+
+;; The byte compiler complains when a defcustom isn't a top level form
+(let* ((names (mapcar (lambda (pair)
+                        (symbol-name (car pair)))
+                      modus-themes-operandi-colors))
+       (colors (mapcar #'intern (sort names #'string<))))
+  (put 'modus-themes-operandi-color-overrides
+       'custom-options (copy-sequence colors))
+  (put 'modus-themes-vivendi-color-overrides
+       'custom-options (copy-sequence colors)))
+
+(defcustom modus-themes-slanted-constructs nil
+  "Use slanted text in more code constructs (italics or oblique)."
+  :group 'modus-themes
+  :package-version '(modus-themes . "1.0.0")
+  :version "28.1"
+  :type 'boolean
+  :link '(info-link "(modus-themes) Slanted constructs"))
+
+(defcustom modus-themes-bold-constructs nil
+  "Use bold text in more code constructs."
+  :group 'modus-themes
+  :package-version '(modus-themes . "1.0.0")
+  :version "28.1"
+  :type 'boolean
+  :link '(info-link "(modus-themes) Bold constructs"))
+
+(defcustom modus-themes-variable-pitch-headings nil
+  "Use proportional fonts (variable-pitch) in headings."
+  :group 'modus-themes
+  :package-version '(modus-themes . "1.0.0")
+  :version "28.1"
+  :type 'boolean
+  :link '(info-link "(modus-themes) Headings' typeface"))
+
+(defcustom modus-themes-variable-pitch-ui nil
+  "Use proportional fonts (variable-pitch) in UI elements.
+This includes the mode line, header line, tab bar, and tab line."
+  :group 'modus-themes
+  :package-version '(modus-themes . "1.1.0")
+  :version "28.1"
+  :type 'boolean
+  :link '(info-link "(modus-themes) UI typeface"))
+
+(defcustom modus-themes-no-mixed-fonts nil
+  "Disable inheritance from `fixed-pitch' in some faces.
+
+This is done by default to allow spacing-sensitive constructs,
+such as Org tables and code blocks, to remain monospaced when
+users opt for something like the command `variable-pitch-mode'.
+The downside with the default is that users need to explicitly
+configure the font family of `fixed-pitch' in order to get a
+consistent experience.  That may be something they do not want to
+do.  Hence this option to disable any kind of technique for
+mixing fonts."
+  :group 'modus-themes
+  :package-version '(modus-themes . "1.0.0")
+  :version "28.1"
+  :type 'boolean
+  :link '(info-link "(modus-themes) No mixed fonts"))
+
+(defcustom modus-themes-headings
+  '((t . nil))
+  "Alist of styles for headings, with optional value per level.
+
+To control faces per level from 1-8, use something like this:
+
+  (setq modus-themes-headings
+        '((1 . highlight)
+          (2 . line)
+          (t . rainbow-line-no-bold)))
+
+To set a uniform value for all heading levels, use this pattern:
+
+  (setq modus-themes-headings
+        '((t . rainbow-line-no-bold)))
+
+The default uses a fairly desaturated foreground value in
+combination with a bold typographic weight.  To specify this
+style for a given level N (assuming you wish to have another
+fallback option), just specify the value t like this:
+
+  (setq modus-themes-headings
+        '((1 . t)
+          (2 . line)
+          (t . rainbow-line-no-bold)))
+
+A description of all possible values:
+
++ `no-bold' retains the default text color while removing the
+  typographic weight.
+
++ `line' is the same as the default plus an overline over the
+  heading.
+
++ `line-no-bold' is the same as `line' without bold weight.
+
++ `rainbow' uses a more colorful foreground in combination with
+  bold weight.
+
++ `rainbow-line' is the same as `rainbow' plus an overline.
+
++ `rainbow-line-no-bold' is the same as `rainbow-line' without
+  the bold weight.
+
++ `highlight' retains the default style of a fairly desaturated
+  foreground combined with a bold weight and add to it a subtle
+  accented background.
+
++ `highlight-no-bold' is the same as `highlight' without a bold
+  weight.
+
++ `rainbow-highlight' is the same as `highlight' but with a more
+  colorful foreground.
+
++ `rainbow-highlight-no-bold' is the same as `rainbow-highlight'
+  without a bold weight.
+
++ `section' retains the default looks and adds to them both an
+  overline and a slightly accented background.  It is, in effect,
+  a combination of the `line' and `highlight' values.
+
++ `section-no-bold' is the same as `section' without a bold
+  weight.
+
++ `rainbow-section' is the same as `section' but with a more
+  colorful foreground.
+
++ `rainbow-section-no-bold' is the same as `rainbow-section'
+  without a bold weight.
+
++ `no-color' does not apply any color to the heading, meaning
+  that it uses the foreground of the `default' face.  It still
+  renders the text with a bold typographic weight.
+
++ `no-color-no-bold' is like `no-color' but without the bold
+  weight."
+  :group 'modus-themes
+  :package-version '(modus-themes . "1.2.0")
+  :version "28.1"
+  :type
+  '(alist
+    :key-type symbol
+    :value-type
+    (choice (const :tag "Fairly desaturated foreground with bold weight 
(default)" t)
+            (const :tag "Like the default without bold weight" no-bold)
+            (const :tag "Like the default plus overline" line)
+            (const :tag "Like `line' without bold weight" line-no-bold)
+            (const :tag "Like the default but with more colorful foreground" 
rainbow)
+            (const :tag "Like `rainbow' plus overline" rainbow-line)
+            (const :tag "Like `rainbow' without bold weight" rainbow-no-bold)
+            (const :tag "Like `rainbow-line' without bold weight" 
rainbow-line-no-bold)
+            (const :tag "Like the default plus subtle background" highlight)
+            (const :tag "Like `highlight' without bold weight" 
highlight-no-bold)
+            (const :tag "Like `highlight' with more colorful foreground" 
rainbow-highlight)
+            (const :tag "Like `rainbow-highlight' without bold weight" 
rainbow-highlight-no-bold)
+            (const :tag "Like `highlight' plus overline" section)
+            (const :tag "Like `section' without bold weight" section-no-bold)
+            (const :tag "Like `section' with more colorful foreground" 
rainbow-section)
+            (const :tag "Like `rainbow-section' without bold weight" 
rainbow-section-no-bold)
+            (const :tag "Do not use any distinct foreground color; just bold 
weight" no-color)
+            (const :tag "Like `no-bold' but without the distinct foreground 
color" no-color-no-bold)))
+  :link '(info-link "(modus-themes) Heading styles"))
+
+(defcustom modus-themes-scale-headings nil
+  "Use font scaling for headings.
+
+For regular headings the scale is controlled by the variables
+`modus-themes-scale-1' (smallest) and its variants all the way up
+to `modus-themes-scale-4' (larger).  While `modus-themes-scale-5'
+is reserved for special headings that must be the largest on the
+scale.
+
+A special heading is, in this context, one that does not fit into
+the syntax for heading levels that apply to the given mode.  For
+example, Org's #+title keyword lies outside the normal eight
+levels of headings.  Whereas, say, Markdown does not have such a
+special heading."
+  :group 'modus-themes
+  :package-version '(modus-themes . "1.2.0")
+  :version "28.1"
+  :type 'boolean
+  :link '(info-link "(modus-themes) Scaled headings"))
+
+(defcustom modus-themes-scale-1 1.05
+  "Font size that is slightly larger than the base value.
+
+This size is used for level 4 headings, such as in Org and
+Markdown files.
+
+The default value is a floating point that is interpreted as a
+multiple of the base font size.  It is recommended to use such a
+value.
+
+However, the variable also accepts an integer, understood as an
+absolute height that is 1/10 of the typeface's point size (e.g. a
+value of 140 is the same as setting the font at 14 point size).
+This will ignore the base font size and, thus, will not scale in
+accordance with it in cases where it changes, such as while using
+`text-scale-adjust'."
+  :group 'modus-themes
+  :package-version '(modus-themes . "1.2.0")
+  :version "28.1"
+  :type 'number
+  :link '(info-link "(modus-themes) Scaled heading sizes"))
+
+(defcustom modus-themes-scale-2 1.1
+  "Font size slightly larger than `modus-themes-scale-1'.
+
+This size is used for level 3 headings, such as in Org and
+Markdown files.
+
+The default value is a floating point that is interpreted as a
+multiple of the base font size.  It is recommended to use such a
+value.
+
+However, the variable also accepts an integer, understood as an
+absolute height that is 1/10 of the typeface's point size (e.g. a
+value of 140 is the same as setting the font at 14 point size).
+This will ignore the base font size and, thus, will not scale in
+accordance with it in cases where it changes, such as while using
+`text-scale-adjust'."
+  :group 'modus-themes
+  :package-version '(modus-themes . "1.2.0")
+  :version "28.1"
+  :type 'number
+  :link '(info-link "(modus-themes) Scaled heading sizes"))
+
+(defcustom modus-themes-scale-3 1.15
+  "Font size slightly larger than `modus-themes-scale-2'.
+
+This size is used for level 2 headings, such as in Org and
+Markdown files.
+
+The default value is a floating point that is interpreted as a
+multiple of the base font size.  It is recommended to use such a
+value.
+
+However, the variable also accepts an integer, understood as an
+absolute height that is 1/10 of the typeface's point size (e.g. a
+value of 140 is the same as setting the font at 14 point size).
+This will ignore the base font size and, thus, will not scale in
+accordance with it in cases where it changes, such as while using
+`text-scale-adjust'."
+  :group 'modus-themes
+  :package-version '(modus-themes . "1.2.0")
+  :version "28.1"
+  :type 'number
+  :link '(info-link "(modus-themes) Scaled heading sizes"))
+
+(defcustom modus-themes-scale-4 1.2
+  "Font size slightly larger than `modus-themes-scale-3'.
+
+This size is used for level 1 headings, such as in Org and
+Markdown files.
+
+The default value is a floating point that is interpreted as a
+multiple of the base font size.  It is recommended to use such a
+value.
+
+However, the variable also accepts an integer, understood as an
+absolute height that is 1/10 of the typeface's point size (e.g. a
+value of 140 is the same as setting the font at 14 point size).
+This will ignore the base font size and, thus, will not scale in
+accordance with it in cases where it changes, such as while using
+`text-scale-adjust'."
+  :group 'modus-themes
+  :package-version '(modus-themes . "1.2.0")
+  :version "28.1"
+  :type 'number
+  :link '(info-link "(modus-themes) Scaled heading sizes"))
+
+(defcustom modus-themes-scale-5 1.3
+  "Font size slightly larger than `modus-themes-scale-4'.
+
+This size is only used for 'special' top level headings, such as
+Org's file title heading, denoted by the #+title key word, and
+the Org agenda structure headers.
+
+The default value is a floating point that is interpreted as a
+multiple of the base font size.  It is recommended to use such a
+value.
+
+However, the variable also accepts an integer, understood as an
+absolute height that is 1/10 of the typeface's point size (e.g. a
+value of 140 is the same as setting the font at 14 point size).
+This will ignore the base font size and, thus, will not scale in
+accordance with it in cases where it changes, such as while using
+`text-scale-adjust'."
+  :group 'modus-themes
+  :package-version '(modus-themes . "1.2.0")
+  :version "28.1"
+  :type 'number
+  :link '(info-link "(modus-themes) Scaled heading sizes"))
+
+(defcustom modus-themes-fringes nil
+  "Define the visibility of fringes.
+
+Nil means the fringes have no background color.  Option `subtle'
+will apply a greyscale value that is visible yet close to the
+main buffer background color.  Option `intense' will use a more
+pronounced greyscale value."
+  :group 'modus-themes
+  :package-version '(modus-themes . "1.0.0")
+  :version "28.1"
+  :type '(choice
+          (const :tag "No visible fringes (default)" nil)
+          (const :tag "Subtle greyscale background" subtle)
+          (const :tag "Intense greyscale background" intense))
+  :link '(info-link "(modus-themes) Fringes"))
+
+(defcustom modus-themes-lang-checkers nil
+  "Control the style of spelling and code checkers/linters.
+
+Nil (the default) applies a color-coded underline to the affected
+text, while it leaves the original foreground in tact.  If the
+display spec of Emacs has support for it, the underline's style
+is that of a wave, otherwise it is a straight line.
+
+Options `subtle-foreground' and `intense-foreground' add a
+color-coded underline while also changing the text's foreground
+accordingly.  The style of the underline is the same as with the
+default option.
+
+Option `straight-underline' is like the default but always
+applies a straight line under the affected text.  Same principle
+for `subtle-foreground-straight-underline' and its counterpart
+`intense-foreground-straight-underline'.
+
+Option `colored-background' uses a straight underline, a
+background, and a foreground.  All are color-coded.  This is the
+most intense combination of face properties."
+  :group 'modus-themes
+  :package-version '(modus-themes . "1.1.0")
+  :version "28.1"
+  :type '(choice
+          (const :tag "Only color-coded wavy underline (default)" nil)
+          (const :tag "Like the default, but with a straight underline" 
straight-underline)
+          (const :tag "Color-coded wavy underline; subtle foreground" 
subtle-foreground)
+          (const :tag "Combines `straight-underline' and `subtle-foreground'" 
subtle-foreground-straight-underline)
+          (const :tag "Color-coded wavy underline; intense foreground" 
intense-foreground)
+          (const :tag "Combines `straight-underline' and `intense-foreground'" 
intense-foreground-straight-underline)
+          (const :tag "Color-coded background, foreground, straight underline" 
colored-background))
+  :link '(info-link "(modus-themes) Language checkers"))
+
+(defcustom modus-themes-org-blocks nil
+  "Use a subtle gray or color-coded background for Org blocks.
+
+Nil means that the block will have no background of its own and
+will use the default that applies to the rest of the buffer.
+
+Option `grayscale' (or `greyscale') will apply a subtle neutral
+gray background to the block's contents.  It also affects the
+begin and end lines of the block: their background will be
+extended to the edge of the window for Emacs version >= 27 where
+the ':extend' keyword is recognized by `set-face-attribute'.
+
+Option `rainbow' will use an accented background for the contents
+of the block.  The exact color will depend on the programming
+language and is controlled by the `org-src-block-faces'
+variable (refer to the theme's source code for the current
+association list)."
+  :group 'modus-themes
+  :package-version '(modus-themes . "1.0.0")
+  :version "28.1"
+  :type '(choice
+          (const :tag "No Org block background (default)" nil)
+          (const :tag "Subtle gray block background" grayscale)
+          (const :tag "Subtle gray block background (alt spelling)" greyscale)
+          (const :tag "Color-coded background per programming language" 
rainbow))
+  :link '(info-link "(modus-themes) Org mode blocks"))
+
+(defcustom modus-themes-org-habit nil
+  "Control the presentation of the `org-habit' graph.
+
+The default is meant to conform with the original aesthetic of
+`org-habit'.  It employs all four color codes that correspond to
+the org-habit states---clear, ready, alert, and overdue---while
+distinguishing between their present and future variants.  This
+results in a total of eight colors in use: red, yellow, green,
+blue, in tinted and shaded versions.  They cover the full set of
+information provided by the `org-habit' consistency graph.
+
+Option `simplified' is like the default except that it removes
+the dichotomy between current and future variants by applying
+uniform color-coded values.  It applies a total of four colors:
+red, yellow, green, blue.  They produce a simplified consistency
+graph that is more legible (or less \"busy\") than the default.
+The intent is to shift focus towards the distinction between the
+four states of a habit task, rather than each state's
+present/future outlook.
+
+Option `traffic-light' further reduces the available colors to
+red, yellow, and green.  As in `simplified', present and future
+variants appear uniformly, but differently from it, the 'clear'
+state is rendered in a green hue, instead of the original blue.
+This is meant to capture the use-case where a habit task being
+\"too early\" is less important than it being \"too late\".  The
+difference between ready and clear states is attenuated by
+painting both of them using shades of green.  This option thus
+highlights the alert and overdue states."
+  :group 'modus-themes
+  :package-version '(modus-themes . "1.1.0")
+  :version "28.1"
+  :type '(choice
+          (const :tag "Respect the original design of org-habit (default)" nil)
+          (const :tag "Like the default, but do not distinguish between 
present and future variants" simplified)
+          (const :tag "Like `simplified', but only use red, yellow, green" 
traffic-light))
+  :link '(info-link "(modus-themes) Org agenda habits"))
+
+(defcustom modus-themes-mode-line nil
+  "Adjust the overall style of the mode line.
+
+Nil is a two-dimensional rectangle with a border around it.  The
+active and the inactive modelines use different shades of
+greyscale values for the background and foreground.
+
+A `3d' value will apply a three-dimensional effect to the active
+modeline.  The inactive modelines remain two-dimensional and are
+toned down a bit, relative to the nil value.
+
+The `moody' option is meant to optimize the modeline for use with
+the library of the same name.  This practically means to remove
+the box effect and rely on underline and overline properties
+instead.  It also tones down the inactive modelines.  Despite its
+intended purpose, this option can also be used without the
+`moody' library.
+
+The `borderless' option uses the same colors as the default (nil
+value), but removes the border effect.  This is done by making
+the box property use the same color as the background,
+effectively blending the two and creating some padding.
+
+The `borderless-3d' and `borderless-moody' approximate the `3d'
+and `moody' options respectively, while removing the borders.
+However, to ensure that the inactive modelines remain visible,
+they apply a slightly more prominent background to them than what
+their counterparts do (same inactive background as with the
+default)."
+  :group 'modus-themes
+  :package-version '(modus-themes . "1.0.0")
+  :version "28.1"
+  :type '(choice
+          (const :tag "Two-dimensional box (default)" nil)
+          (const :tag "Three-dimensional style for the active mode line" 3d)
+          (const :tag "No box effects, which are optimal for use with the 
`moody' library" moody)
+          (const :tag "Like the default, but without border effects" 
borderless)
+          (const :tag "Like `3d', but without noticeable border" borderless-3d)
+          (const :tag "Like `moody', but without noticeable border" 
borderless-moody))
+  :link '(info-link "(modus-themes) Mode line"))
+
+(defcustom modus-themes-diffs nil
+  "Adjust the overall styles of diffs.
+
+Nil means to use fairly intense color combinations for diffs.
+For example, you get a rich green background with a green
+foreground for added lines.  Word-wise or 'refined' diffs follow
+the same pattern but use different shades of those colors to
+remain distinct.
+
+A `desaturated' value follows the same principles as with the nil
+option, while it tones down all relevant colors.
+
+Option `fg-only' will remove all accented backgrounds, except
+from word-wise changes.  It instead uses color-coded foreground
+values to differentiate between added/removed/changed lines.  If
+a background is necessary, such as with `ediff', then a subtle
+greyscale value is used.
+
+Option `bg-only' applies a background but does not override the
+text's foreground.  This makes it suitable for a non-nil value
+passed to `diff-font-lock-syntax' (note: Magit does not support
+syntax highlighting in diffs as of 2020-11-25, version
+20201116.1057).
+
+Option `deuteranopia' accounts for red-green color defficiency by
+replacing all instances of green with colors on the blue side of
+the spectrum.  Other stylistic changes are made in the interest
+of optimizing for such a use-case."
+  :group 'modus-themes
+  :package-version '(modus-themes . "1.2.0")
+  :version "28.1"
+  :type '(choice
+          (const :tag "Intensely colored backgrounds (default)" nil)
+          (const :tag "Slightly accented backgrounds with tinted text" 
desaturated)
+          (const :tag "No backgrounds, except for refined diffs" fg-only)
+          (const :tag "Apply color-coded backgrounds; keep syntax colors in 
tact" bg-only)
+          (const :tag "Optimized for red-green color defficiency" 
deuteranopia))
+  :link '(info-link "(modus-themes) Diffs"))
+
+(defcustom modus-themes-completions nil
+  "Apply special styles to the UI of completion frameworks.
+
+This concerns Icomplete, Ivy, Helm, Selectrum, Ido, as well as
+any other tool meant to enhance their experience.  The effect
+will vary depending on the completion framework.
+
+Nil means to remain faithful to the metaphors that each UI
+establishes.  For example, Icomplete and Ido only use foreground
+colors to style their matches, whereas Ivy or Helm rely on an
+aesthetic that combines colored backgrounds with appropriate text
+color.
+
+Option `moderate' will apply a combination of background and
+foreground that is fairly subtle.  For Icomplete and the like,
+this constitutes a departure from their standard style.  While
+Ivy, Helm, and the others, will use less pronounced colors for
+applicable contexts.
+
+Option `opinionated' will apply color combinations that refashion
+the completion UI.  So Icomplete et al will now use styles that
+resemble the defaults of Ivy and co., while the latter group will
+revert to an even more nuanced aesthetic."
+  :group 'modus-themes
+  :package-version '(modus-themes . "1.0.0")
+  :version "28.1"
+  :type '(choice
+          (const :tag "Respect the framework's established aesthetic 
(default)" nil)
+          (const :tag "Subtle backgrounds for various elements" moderate)
+          (const :tag "Radical alternative to the framework's looks" 
opinionated))
+  :link '(info-link "(modus-themes) Completion UIs"))
+
+(defcustom modus-themes-prompts nil
+  "Use subtle or intense styles for minibuffer and REPL prompts.
+
+Nil means to only use an accented foreground color.
+
+Options `subtle-accented' and `intense-accented' will change both
+the background and the foreground values to use accented color
+combinations that follow the hue of the default styles'
+foreground (e.g. the default minibuffer prompt is cyan text, so
+these combinations will involved a cyan background and an
+appropriate cyan foreground).
+
+Options `subtle-gray' and `intense-gray' are like their
+`subtle-accented' and `intense-accented' counterparts, except
+they use grayscale values instead of accented ones."
+  :group 'modus-themes
+  :package-version '(modus-themes . "1.0.0")
+  :version "28.1"
+  :type '(choice
+          ;; `subtle' is the same as `subtle-accented', while `intense' is
+          ;; equal to `intense-accented' for backward compatibility
+          (const :tag "No prompt background (default)" nil)
+          (const :tag "Subtle accented background for the prompt" 
subtle-accented)
+          (const :tag "Same as `subtle-accented' for compatibility with older 
versions" subtle)
+          (const :tag "Intense accented background and foreground for the 
prompt" intense-accented)
+          (const :tag "Same as `intense-accented' for compatibility with older 
versions" intense)
+          (const :tag "Like `subtle-accented' but grayscale" subtle-gray)
+          (const :tag "Like `intense-accented' but grayscale" intense-gray))
+  :link '(info-link "(modus-themes) Command prompts"))
+
+(defcustom modus-themes-intense-hl-line nil
+  "Use a more prominent background for command `hl-line-mode'."
+  :group 'modus-themes
+  :package-version '(modus-themes . "1.0.0")
+  :version "28.1"
+  :type 'boolean
+  :link '(info-link "(modus-themes) Line highlighting"))
+
+(defcustom modus-themes-subtle-line-numbers nil
+  "Use more subtle style for command `display-line-numbers-mode'."
+  :group 'modus-themes
+  :package-version '(modus-themes . "1.2.0")
+  :version "28.1"
+  :type 'boolean
+  :link '(info-link "(modus-themes) Line numbers"))
+
+(defcustom modus-themes-paren-match nil
+  "Choose the style of matching parentheses or delimiters.
+
+Nil means to use a subtle tinted background color (the default).
+
+Option `intense' applies a saturated background color.
+
+Option `subtle-bold' is the same as the default, but also makes
+use of bold typographic weight (inherits the `bold' face).
+
+Option `intense-bold' is the same as `intense', while it also
+uses a bold weight."
+  :group 'modus-themes
+  :package-version '(modus-themes . "1.0.0")
+  :version "28.1"
+  :type '(choice
+          (const :tag "Sublte tinted background (default)" nil)
+          (const :tag "Like the default, but also use bold typographic weight" 
subtle-bold)
+          (const :tag "Intense saturated background" intense)
+          (const :tag "Like `intense' but with bold weight" intense-bold))
+  :link '(info-link "(modus-themes) Matching parentheses"))
+
+(defcustom modus-themes-syntax nil
+  "Control the overall style of code syntax highlighting.
+
+Nil (the default) means to use colors on the cyan-blue-magenta
+side of the spectrum.  There is little to no use of greens,
+yellows, and reds.
+
+Option `faint' is like the default in terms of the choice of
+palette but applies desaturated color values.
+
+Option `yellow-comments' applies a yellow tint to comments.  The
+rest of the syntax is the same as the default.
+
+Option `green-strings' replaces the blue/cyan/cold color variants
+in strings with greener alternatives.  The rest of the syntax
+remains the same.
+
+Option `yellow-comments-green-strings' combines yellow comments
+with green strings and the rest of the default syntax
+highlighting style.
+
+Option `alt-syntax' expands the color palette and applies new
+color combinations.  Strings are green.  Doc strings are magenta
+tinted.  Comments are gray.
+
+Option `alt-syntax-yellow-comments' combines `alt-syntax' with
+`yellow-comments'.
+
+Option `faint-yellow-comments' combines the `faint' style with
+`yellow-comments'."
+  :group 'modus-themes
+  :package-version '(modus-themes . "1.2.0")
+  :version "28.1"
+  :type '(choice
+          (const :tag "Balanced use of blue, cyan, magenta, purple variants 
(default)" nil)
+          (const :tag "Like the default, but with desaturated color values" 
faint)
+          (const :tag "Apply yellow tint to comments, keep the default style 
for the rest" yellow-comments)
+          (const :tag "Use green for strings, keep the default style for the 
rest" green-strings)
+          (const :tag "Use green for strings, yellow for comments, keep the 
default style for the rest" yellow-comments-green-strings)
+          (const :tag "Refashion syntax highlighting with more colors, gray 
comments" alt-syntax)
+          (const :tag "Like `alt-syntax' but with yellow comments" 
alt-syntax-yellow-comments)
+          (const :tag "Like `faint' but with yellow comments" 
faint-yellow-comments))
+  :link '(info-link "(modus-themes) Syntax styles"))
+
+(defcustom modus-themes-links nil
+  "Set the style of links.
+
+Nil means to use an underline that is the same color as the
+foreground.
+
+Option `faint' applies desaturated colors to the link's text and
+underline.
+
+Option `neutral-underline' applies a subtle grey underline, while
+retaining the link's foreground.
+
+Option `faint-neutral-underline' combines a desaturated text
+color with a subtle grey underline.
+
+Option `no-underline' removes link underlines altogether, while
+retaining their original fairly vivid color.
+
+Option `underline-only' applies an underline while making the
+affected text colorless (it uses the same foreground as the
+theme's default).
+
+Option `neutral-underline-only' makes the text colorless while
+using a subtle underline below it."
+  :group 'modus-themes
+  :package-version '(modus-themes . "1.2.0")
+  :version "28.1"
+  :type '(choice
+          (const :tag "Undeline link using the same color as the text 
(default)" nil)
+          (const :tag "Like the default, but apply less intense colors to 
links" faint)
+          (const :tag "Change the color of link underlines to a neutral grey" 
neutral-underline)
+          (const :tag "Desaturated foreground with neutral grey underline" 
faint-neutral-underline)
+          (const :tag "Remove underline property from links, keeping their 
foreground as-is" no-underline)
+          (const :tag "Apply underline only; use default foreground" 
underline-only)
+          (const :tag "Like `underline-only' but with a subtle underline" 
neutral-underline-only))
+  :link '(info-link "(modus-themes) Link styles"))
+
+(defcustom modus-themes-region nil
+  "Change the overall appearance of the active region.
+
+Nil (the default) means to only use a prominent gray background
+with a neutral foreground.  The foreground overrides all syntax
+highlighting.  The region extends to the edge of the window.
+
+Option `no-extend' preserves the default aesthetic but prevents
+the region from extending to the edge of the window.
+
+Option `bg-only' applies a faint tinted background that is
+distinct from all others used in the theme, while it does not
+override any existing colors.  It extends to the edge of the
+window.
+
+Option `bg-only-no-extend' is a combination of the `bg-only' and
+`no-extend' options."
+  :group 'modus-themes
+  :package-version '(modus-themes . "1.0.0")
+  :version "28.1"
+  :type '(choice
+          (const :tag "Intense background; overrides colors; extends to edge 
of window (default)" nil)
+          (const :tag "As with the default, but does not extend" no-extend)
+          (const :tag "Subtle background; preserves colors; extends to edge of 
window" bg-only)
+          (const :tag "As with the `subtle' option, but does not extend" 
bg-only-no-extend))
+  :link '(info-link "(modus-themes) Active region"))
+
+
+
+;;;; Deprecated customization options (prior to 1.0.0)
+
+;;;;; Modus Operandi obsolete options
+
+(make-obsolete 'modus-operandi-theme-override-colors-alist nil "1.0.0")
+(make-obsolete 'modus-operandi-theme-slanted-constructs 
'modus-themes-slanted-constructs "1.0.0")
+(make-obsolete 'modus-operandi-theme-bold-constructs 
'modus-themes-bold-constructs "1.0.0")
+(make-obsolete 'modus-operandi-theme-proportional-fonts 
'modus-themes-variable-pitch-headings "1.0.0")
+(make-obsolete 'modus-operandi-theme-variable-pitch-headings 
'modus-themes-variable-pitch-headings "1.0.0")
+(make-obsolete 'modus-operandi-theme-no-mixed-fonts 
'modus-themes-no-mixed-fonts "1.0.0")
+(make-obsolete 'modus-operandi-theme-rainbow-headings 'modus-themes-headings 
"1.0.0")
+(make-obsolete 'modus-operandi-theme-section-headings 'modus-themes-headings 
"1.0.0")
+(make-obsolete 'modus-operandi-theme-headings 'modus-themes-headings "1.0.0")
+(make-obsolete 'modus-operandi-theme-scale-headings 
'modus-themes-scale-headings "1.0.0")
+(make-obsolete 'modus-operandi-theme-scale-1 'modus-themes-scale-1 "1.0.0")
+(make-obsolete 'modus-operandi-theme-scale-2 'modus-themes-scale-2 "1.0.0")
+(make-obsolete 'modus-operandi-theme-scale-3 'modus-themes-scale-3 "1.0.0")
+(make-obsolete 'modus-operandi-theme-scale-4 'modus-themes-scale-4 "1.0.0")
+(make-obsolete 'modus-operandi-theme-scale-5 'modus-themes-scale-5 "1.0.0")
+(make-obsolete 'modus-operandi-theme-visible-fringes 'modus-themes-fringes 
"1.0.0")
+(make-obsolete 'modus-operandi-theme-fringes 'modus-themes-fringes "1.0.0")
+(make-obsolete 'modus-operandi-theme-distinct-org-blocks 
'modus-themes-org-blocks "1.0.0")
+(make-obsolete 'modus-operandi-theme-rainbow-org-src-blocks 
'modus-themes-org-blocks "1.0.0")
+(make-obsolete 'modus-operandi-theme-org-blocks 'modus-themes-org-blocks 
"1.0.0")
+(make-obsolete 'modus-operandi-theme-3d-modeline 'modus-themes-mode-line 
"1.0.0")
+(make-obsolete 'modus-operandi-theme-mode-line 'modus-themes-mode-line "1.0.0")
+(make-obsolete 'modus-operandi-theme-subtle-diffs 'modus-themes-diffs "1.0.0")
+(make-obsolete 'modus-operandi-theme-diffs 'modus-themes-diffs "1.0.0")
+(make-obsolete 'modus-operandi-theme-intense-standard-completions 
'modus-themes-completions "1.0.0")
+(make-obsolete 'modus-operandi-theme-completions 'modus-themes-completions 
"1.0.0")
+(make-obsolete 'modus-operandi-theme-prompts 'modus-themes-prompts "1.0.0")
+(make-obsolete 'modus-operandi-theme-intense-hl-line 
'modus-themes-intense-hl-line "1.0.0")
+(make-obsolete 'modus-operandi-theme-intense-paren-match 
'modus-themes-paren-match "1.0.0")
+(make-obsolete 'modus-operandi-theme-faint-syntax 'modus-themes-syntax "1.0.0")
+(make-obsolete 'modus-operandi-theme-comments 'modus-themes-syntax "1.0.0")
+(make-obsolete 'modus-operandi-theme-syntax 'modus-themes-syntax "1.0.0")
+(make-obsolete 'modus-operandi-theme-no-link-underline 'modus-themes-links 
"1.0.0")
+(make-obsolete 'modus-operandi-theme-links 'modus-themes-links "1.0.0")
+
+;;;;; Modus Vivendi obsolete options
+
+(make-obsolete 'modus-vivendi-theme-override-colors-alist nil "1.0.0")
+(make-obsolete 'modus-vivendi-theme-slanted-constructs 
'modus-themes-slanted-constructs "1.0.0")
+(make-obsolete 'modus-vivendi-theme-bold-constructs 
'modus-themes-bold-constructs "1.0.0")
+(make-obsolete 'modus-vivendi-theme-proportional-fonts 
'modus-themes-variable-pitch-headings "1.0.0")
+(make-obsolete 'modus-vivendi-theme-variable-pitch-headings 
'modus-themes-variable-pitch-headings "1.0.0")
+(make-obsolete 'modus-vivendi-theme-no-mixed-fonts 
'modus-themes-no-mixed-fonts "1.0.0")
+(make-obsolete 'modus-vivendi-theme-rainbow-headings 'modus-themes-headings 
"1.0.0")
+(make-obsolete 'modus-vivendi-theme-section-headings 'modus-themes-headings 
"1.0.0")
+(make-obsolete 'modus-vivendi-theme-headings 'modus-themes-headings "1.0.0")
+(make-obsolete 'modus-vivendi-theme-scale-headings 
'modus-themes-scale-headings "1.0.0")
+(make-obsolete 'modus-vivendi-theme-scale-1 'modus-themes-scale-1 "1.0.0")
+(make-obsolete 'modus-vivendi-theme-scale-2 'modus-themes-scale-2 "1.0.0")
+(make-obsolete 'modus-vivendi-theme-scale-3 'modus-themes-scale-3 "1.0.0")
+(make-obsolete 'modus-vivendi-theme-scale-4 'modus-themes-scale-4 "1.0.0")
+(make-obsolete 'modus-vivendi-theme-scale-5 'modus-themes-scale-5 "1.0.0")
+(make-obsolete 'modus-vivendi-theme-visible-fringes 'modus-themes-fringes 
"1.0.0")
+(make-obsolete 'modus-vivendi-theme-fringes 'modus-themes-fringes "1.0.0")
+(make-obsolete 'modus-vivendi-theme-distinct-org-blocks 
'modus-themes-org-blocks "1.0.0")
+(make-obsolete 'modus-vivendi-theme-rainbow-org-src-blocks 
'modus-themes-org-blocks "1.0.0")
+(make-obsolete 'modus-vivendi-theme-org-blocks 'modus-themes-org-blocks 
"1.0.0")
+(make-obsolete 'modus-vivendi-theme-3d-modeline 'modus-themes-mode-line 
"1.0.0")
+(make-obsolete 'modus-vivendi-theme-mode-line 'modus-themes-mode-line "1.0.0")
+(make-obsolete 'modus-vivendi-theme-subtle-diffs 'modus-themes-diffs "1.0.0")
+(make-obsolete 'modus-vivendi-theme-diffs 'modus-themes-diffs "1.0.0")
+(make-obsolete 'modus-vivendi-theme-intense-standard-completions 
'modus-themes-completions "1.0.0")
+(make-obsolete 'modus-vivendi-theme-completions 'modus-themes-completions 
"1.0.0")
+(make-obsolete 'modus-vivendi-theme-prompts 'modus-themes-prompts "1.0.0")
+(make-obsolete 'modus-vivendi-theme-intense-hl-line 
'modus-themes-intense-hl-line "1.0.0")
+(make-obsolete 'modus-vivendi-theme-intense-paren-match 
'modus-themes-paren-match "1.0.0")
+(make-obsolete 'modus-vivendi-theme-faint-syntax 'modus-themes-syntax "1.0.0")
+(make-obsolete 'modus-vivendi-theme-comments 'modus-themes-syntax "1.0.0")
+(make-obsolete 'modus-vivendi-theme-syntax 'modus-themes-syntax "1.0.0")
+(make-obsolete 'modus-vivendi-theme-no-link-underline 'modus-themes-links 
"1.0.0")
+(make-obsolete 'modus-vivendi-theme-links 'modus-themes-links "1.0.0")
+
+
+
+;;; Internal functions
+
+(defun modus-themes--palette (theme)
+  "Return color palette for Modus theme THEME.
+THEME is a symbol, either `modus-operandi' or `modus-vivendi'."
+  (pcase theme
+    ('modus-operandi
+     (append modus-themes-operandi-color-overrides
+             modus-themes-operandi-colors))
+    ('modus-vivendi
+     (append modus-themes-vivendi-color-overrides
+             modus-themes-vivendi-colors))
+    (_theme
+     (error "'%s' is not a Modus theme" theme))))
+
+(defvar modus-themes-faces)
+(defvar modus-themes-custom-variables)
+
+(defmacro modus-themes-theme (name)
+  "Bind NAME's color palette around face specs and variables.
+
+NAME should be the proper name of a Modus theme, either
+`modus-operandi' or `modus-vivendi'.
+
+Face specifications are passed to `custom-theme-set-faces'.
+While variables are handled by `custom-theme-set-variables'.
+Those are stored in `modus-themes-faces' and
+`modus-themes-custom-variables' respectively."
+  (declare (indent 0))
+  (let ((palette-sym (gensym))
+        (colors (mapcar #'car modus-themes-operandi-colors)))
+    `(let* ((class '((class color) (min-colors 89)))
+            (,palette-sym (modus-themes--palette ',name))
+            ,@(mapcar (lambda (color)
+                        (list color `(alist-get ',color ,palette-sym)))
+                      colors))
+       (custom-theme-set-faces ',name ,@modus-themes-faces)
+       (custom-theme-set-variables ',name ,@modus-themes-custom-variables))))
+
+(defun modus-themes--current-theme ()
+  "Return current theme."
+  (car custom-enabled-themes))
+
+;; Helper functions that are meant to ease the implementation of the
+;; above customization options.
+(defun modus-themes--bold-weight ()
+  "Conditional use of a heavier text weight."
+  (when modus-themes-bold-constructs
+    (list :inherit 'bold)))
+
+(defun modus-themes--mixed-fonts ()
+  "Conditional application of `fixed-pitch' inheritance."
+  (unless modus-themes-no-mixed-fonts
+    (list :inherit 'fixed-pitch)))
+
+(defun modus-themes--slant ()
+  "Conditional use of italics for slant attribute."
+  (if modus-themes-slanted-constructs
+      (list 'italic)
+    (list 'normal)))
+
+(defun modus-themes--variable-pitch ()
+  "Conditional use of `variable-pitch' in headings."
+  (when modus-themes-variable-pitch-headings
+    (list :inherit 'variable-pitch)))
+
+(defun modus-themes--variable-pitch-ui ()
+  "Conditional use of `variable-pitch' in UI elements."
+  (when modus-themes-variable-pitch-ui
+    (list :inherit 'variable-pitch)))
+
+(defun modus-themes--fringe (mainbg subtlebg intensebg)
+  "Conditional use of background colors for fringes.
+MAINBG is the default.  SUBTLEBG should be a subtle greyscale
+value.  INTENSEBG must be a more pronounced greyscale color."
+  (pcase modus-themes-fringes
+    ('intense (list :background intensebg))
+    ('subtle (list :background subtlebg))
+    (_ (list :background mainbg))))
+
+(defun modus-themes--line-numbers (mainfg mainbg altfg &optional altbg)
+  "Conditional use of colors for line numbers.
+MAINBG and MAINFG are the default colors.  ALTFG is a color that
+combines with the theme's primary background (white/black)."
+  (if modus-themes-subtle-line-numbers
+      (list :background (or altbg 'unspecified) :foreground altfg)
+    (list :background mainbg :foreground mainfg)))
+
+(defun modus-themes--lang-check (underline subtlefg intensefg bg)
+  "Conditional use of foreground colors for language checkers.
+UNDERLINE is a color-code value for the affected text's underline
+property.  SUBTLEFG and INTENSEFG follow the same color-coding
+pattern and represent a value that is faint or vibrant
+respectively.  BG is a color-coded background."
+  (pcase modus-themes-lang-checkers
+    ('colored-background
+     (list :underline underline :background bg :foreground intensefg))
+    ('intense-foreground
+     (list :underline (list :color underline :style 'wave) :foreground 
intensefg))
+    ('intense-foreground-straight-underline
+     (list :underline underline :foreground intensefg))
+    ('subtle-foreground
+     (list :underline (list :color underline :style 'wave) :foreground 
subtlefg))
+    ('subtle-foreground-straight-underline
+     (list :underline underline :foreground subtlefg))
+    ('straight-underline
+     (list :underline underline))
+    (_ (list :underline (list :color underline :style 'wave)))))
+
+(defun modus-themes--prompt (mainfg subtlebg subtlefg intensebg intensefg)
+  "Conditional use of background colors for prompts.
+MAINFG is the prompt's standard foreground.  SUBTLEBG should be a
+subtle accented background that works with SUBTLEFG.  INTENSEBG
+must be a more pronounced accented color that should be
+combinable with INTENSEFG."
+  (pcase modus-themes-prompts
+    ;; `subtle' is the same as `subtle-accented', while `intense' is
+    ;; equal to `intense-accented' for backward compatibility
+    ('intense-accented (list :background intensebg :foreground intensefg))
+    ('intense (list :background intensebg :foreground intensefg))
+    ('subtle-accented (list :background subtlebg :foreground subtlefg))
+    ('subtle (list :background subtlebg :foreground subtlefg))
+    ('subtle-gray (list :inherit 'modus-theme-subtle-neutral))
+    ('intense-gray (list :inherit 'modus-theme-intense-neutral))
+    (_ (list :background nil :foreground mainfg))))
+
+(defun modus-themes--paren (normalbg intensebg)
+  "Conditional use of intense colors for matching parentheses.
+NORMALBG should be the special palette color 'bg-paren-match' or
+something similar.  INTENSEBG must be easier to discern next to
+other backgrounds, such as the special palette color
+'bg-paren-match-intense'."
+  (pcase modus-themes-paren-match
+    ('subtle-bold (list :inherit 'bold :background normalbg))
+    ('intense-bold (list :inherit 'bold :background intensebg))
+    ('intense (list :background intensebg))
+    (_ (list :background normalbg))))
+
+(defun modus-themes--syntax-foreground (fg faint)
+  "Apply foreground value to code syntax.
+FG is the default.  FAINT is typically the same color in its
+desaturated version."
+  (pcase modus-themes-syntax
+    ('faint (list :foreground faint))
+    ('faint-yellow-comments (list :foreground faint))
+    (_ (list :foreground fg))))
+
+(defun modus-themes--syntax-extra (fg faint alt)
+  "Apply foreground value to code syntax.
+FG is the default.  FAINT is typically the same color in its
+desaturated version.  ALT is another hue."
+  (pcase modus-themes-syntax
+    ('faint (list :foreground faint))
+    ('faint-yellow-comments (list :foreground faint))
+    ('alt-syntax (list :foreground alt))
+    ('alt-syntax-yellow-comments (list :foreground alt))
+    (_ (list :foreground fg))))
+
+(defun modus-themes--syntax-string (fg faint green alt)
+  "Apply foreground value to strings in code syntax.
+FG is the default.  FAINT is typically the same color in its
+desaturated version.  GREEN is a color variant in that side of
+the spectrum.  ALT is another hue."
+  (pcase modus-themes-syntax
+    ('faint (list :foreground faint))
+    ('faint-yellow-comments (list :foreground faint))
+    ('green-strings (list :foreground green))
+    ('yellow-comments-green-strings (list :foreground alt))
+    ('alt-syntax (list :foreground alt))
+    ('alt-syntax-yellow-comments (list :foreground alt))
+    (_ (list :foreground fg))))
+
+(defun modus-themes--syntax-docstring (fg faint green alt)
+  "Apply foreground value to strings in code syntax.
+FG is the default.  FAINT is typically the same color in its
+desaturated version.  GREEN is a color variant in that side of
+the spectrum.  ALT is another hue."
+  (pcase modus-themes-syntax
+    ('faint (list :foreground faint))
+    ('faint-yellow-comments (list :foreground faint))
+    ('green-strings (list :foreground green))
+    ('yellow-comments-green-strings (list :foreground green))
+    ('alt-syntax (list :foreground alt))
+    ('alt-syntax-yellow-comments (list :foreground alt))
+    (_ (list :foreground fg))))
+
+(defun modus-themes--syntax-comment (fg yellow)
+  "Apply foreground value to strings in code syntax.
+FG is the default.  YELLOW is a color variant of that name."
+  (pcase modus-themes-syntax
+    ('yellow-comments (list :foreground yellow))
+    ('yellow-comments-green-strings (list :foreground yellow))
+    ('alt-syntax-yellow-comments (list :foreground yellow))
+    ('faint-yellow-comments (list :foreground yellow))
+    (_ (list :foreground fg))))
+
+(defun modus-themes--heading-p (key)
+  "Query style of KEY in `modus-themes-headings'."
+  (cdr (assoc key modus-themes-headings)))
+
+(defun modus-themes--heading (level fg fg-alt bg border)
+  "Conditional styles for `modus-themes-headings'.
+
+LEVEL is the heading's position in their order.  FG is the
+default text color.  FG-ALT is an accented, more saturated value
+than the default.  BG is a nuanced, typically accented,
+background that can work well with either of the foreground
+values.  BORDER is a color value that combines well with the
+background and alternative foreground."
+  (let* ((key (modus-themes--heading-p `,level))
+         (style (or key (modus-themes--heading-p t)))
+         (var (when modus-themes-variable-pitch-headings
+                'variable-pitch))
+         (varbold (if var
+                      (append (list 'bold) (list var))
+                    'bold)))
+    (pcase style
+      ('no-bold
+       (list :inherit `,var :foreground fg))
+      ('no-color
+       (list :inherit `,varbold))
+      ('no-color-no-bold
+       (list :inherit `,var))
+      ('line
+       (list :inherit `,varbold :foreground fg :overline border))
+      ('line-no-bold
+       (list :inherit `,var :foreground fg :overline border))
+      ('rainbow
+       (list :inherit `,varbold :foreground fg-alt))
+      ('rainbow-no-bold
+       (list :inherit `,var :foreground fg-alt))
+      ('rainbow-line
+       (list :inherit `,varbold :foreground fg-alt :overline border))
+      ('rainbow-line-no-bold
+       (list :inherit `,var :foreground fg-alt :overline border))
+      ('highlight
+       (list :inherit `,varbold :background bg :foreground fg))
+      ('highlight-no-bold
+       (list :inherit `,var :background bg :foreground fg))
+      ('rainbow-highlight
+       (list :inherit `,varbold :background bg :foreground fg-alt))
+      ('rainbow-highlight-no-bold
+       (list :inherit `,var :background bg :foreground fg-alt))
+      ('section
+       (list :inherit `,varbold :background bg :foreground fg :overline border 
:extend t))
+      ('section-no-bold
+       (list :inherit `,var :background bg :foreground fg :overline border 
:extend t))
+      ('rainbow-section
+       (list :inherit `,varbold :background bg :foreground fg-alt :overline 
border :extend t))
+      ('rainbow-section-no-bold
+       (list :inherit `,var :background bg :foreground fg-alt :overline border 
:extend t))
+      (_
+       (list :inherit `,varbold :foreground fg)))))
+
+(defun modus-themes--org-block (bgblk)
+  "Conditionally set the background of Org blocks.
+BGBLK applies to a distinct neutral background.  Else blocks have
+no background of their own (the default), so they look the same
+as the rest of the buffer.
+
+`modus-themes-org-blocks' also accepts a `rainbow' option
+which is applied conditionally to `org-src-block-faces' (see the
+theme's source code)."
+  (if (or (eq modus-themes-org-blocks 'grayscale)
+          (eq modus-themes-org-blocks 'greyscale))
+      (list :background bgblk :extend t)
+    (list :background 'unspecified)))
+
+(defun modus-themes--org-block-delim (bgaccent fgaccent bg fg)
+  "Conditionally set the styles of Org block delimiters.
+BG, FG, BGACCENT, FGACCENT apply a background and foreground
+color respectively.
+
+The former pair is a greyscale combination that should be more
+distinct than the background of the block.  It is applied to the
+default styles or when `modus-themes-org-blocks' is set
+to `greyscale'.
+
+The latter pair should be more subtle than the background of the
+block, as it is used when `modus-themes-org-blocks' is
+set to `rainbow'."
+  (pcase modus-themes-org-blocks
+    ('grayscale (list :background bg :foreground fg :extend t))
+    ('greyscale (list :background bg :foreground fg :extend t))
+    ('rainbow (list :background bgaccent :foreground fgaccent))
+    (_ (list :background bg :foreground fg))))
+
+(defun modus-themes--org-habit (default &optional traffic simple)
+  "Specify background values for `modus-themes-org-habit'.
+If no optional TRAFFIC argument is supplied, the DEFAULT is used
+instead.  Same for SIMPLE."
+  (pcase modus-themes-org-habit
+    ('traffic-light (list :background (or traffic default)))
+    ('simplified (list :background (or simple default)))
+    (_ (list :background default))))
+
+(defun modus-themes--mode-line-attrs
+    (fg bg fg-alt bg-alt border border-3d &optional alt-style border-width 
fg-distant)
+  "Color combinations for `modus-themes-mode-line'.
+
+FG and BG are the default colors.  FG-ALT and BG-ALT are meant to
+accommodate the options for a 3D modeline or a `moody' compliant
+one.  BORDER applies to all permutations of the modeline, except
+the three-dimensional effect, where BORDER-3D is used instead.
+
+Optional ALT-STYLE applies an appropriate style to the mode
+line's box property.
+
+Optional BORDER-WIDTH specifies an integer for the width of the
+rectangle that produces the box effect.
+
+Optional FG-DISTANT should be close to the main background
+values.  It is intended to be used as a distant-foreground
+property."
+  (pcase modus-themes-mode-line
+    ('3d
+     `(:background ,bg-alt :foreground ,fg-alt
+       :box (:line-width ,(or border-width 1)
+             :color ,border-3d
+             :style ,(and alt-style 'released-button))))
+    ('moody
+     `(:background ,bg-alt :foreground ,fg-alt
+       :underline ,border :overline ,border
+       :distant-foreground ,fg-distant))
+    ('borderless
+     `(:foreground ,fg :background ,bg :box ,bg))
+    ('borderless-3d
+     `(:foreground ,fg :background ,bg
+       :box (:line-width ,(or border-width 1)
+             :color ,bg
+             :style ,(and alt-style 'released-button))))
+    ('borderless-moody
+     `(:background ,bg :foreground ,fg
+       :underline ,bg :overline ,bg
+       :distant-foreground ,fg-distant))
+    (_
+     `(:foreground ,fg :background ,bg :box ,border))))
+
+(defun modus-themes--diff
+    (fg-only-bg fg-only-fg mainbg mainfg altbg altfg &optional deuteranbg 
deuteranfg  bg-only-fg)
+  "Color combinations for `modus-themes-diffs'.
+
+FG-ONLY-BG should be similar or the same as the main background.
+FG-ONLY-FG should be a saturated accent value that can be
+combined with the former.
+
+MAINBG must be one of the dedicated backgrounds for diffs while
+MAINFG must be the same for the foreground.
+
+ALTBG needs to be a slightly accented background that is meant to
+be combined with ALTFG.  Both must be less intense than MAINBG
+and MAINFG respectively.
+
+DEUTERANBG and DEUTERANFG must be combinations of colors that account
+for red-green color defficiency (deuteranopia).
+
+Optional BG-ONLY-FG applies ALTFG else leaves the foreground
+unspecified."
+  (pcase modus-themes-diffs
+    ('fg-only (list :background fg-only-bg :foreground fg-only-fg))
+    ('desaturated (list :background altbg :foreground altfg))
+    ('deuteranopia (list :background (or deuteranbg mainbg) :foreground (or 
deuteranfg mainfg)))
+    ('bg-only (list :background altbg :foreground (if bg-only-fg altfg 
'unspecified)))
+    (_ (list :background mainbg :foreground mainfg))))
+
+(defun modus-themes--diff-deuteran (deuteran main)
+  "Determine whether the DEUTERAN or MAIN color should be used.
+This is based on whether `modus-themes-diffs' has the value
+`deuteranopia'."
+  (if (eq modus-themes-diffs 'deuteranopia)
+      (list deuteran)
+    (list main)))
+
+(defun modus-themes--diff-text (fg-only-fg default-fg)
+  "Like `modus-themes--diff', but only for foregrounds.
+FG-ONLY-FG is the foreground that is used when diffs are styled
+using only foreground colors.  DEFAULT-FG covers all other
+cases."
+  (pcase modus-themes-diffs
+    ('fg-only (list :foreground fg-only-fg))
+    ('bg-only (list :foreground 'unspecified))
+    (_ (list :foreground default-fg))))
+
+(defun modus-themes--standard-completions (mainfg subtlebg intensebg intensefg)
+  "Combinations for `modus-themes-completions'.
+
+MAINFG is an accented foreground value.  SUBTLEBG is an accented
+background value that can be combined with MAINFG.  INTENSEBG and
+INTENSEFG are accented colors that are designed to be used in
+tandem.
+
+These are intended for Icomplete, Ido, and related."
+  (pcase modus-themes-completions
+    ('opinionated (list :background intensebg :foreground intensefg))
+    ('moderate (list :background subtlebg :foreground mainfg))
+    (_ (list :foreground mainfg))))
+
+(defun modus-themes--extra-completions (subtleface intenseface altface 
&optional altfg bold)
+  "Combinations for `modus-themes-completions'.
+
+SUBTLEFACE and INTENSEFACE are custom theme faces that combine a
+background and foreground value.  The difference between the two
+is a matter of degree.
+
+ALTFACE is a combination of colors that represents a departure
+from the UI's default aesthetics.  Optional ALTFG is meant to be
+used in tandem with it.
+
+Optional BOLD will apply a heavier weight to the text.
+
+These are intended for Helm, Ivy, etc."
+  (pcase modus-themes-completions
+    ('opinionated (list :inherit (list altface bold)
+                        :foreground (or altfg 'unspecified)))
+    ('moderate (list :inherit (list subtleface bold)))
+    (_ (list :inherit (list intenseface bold)))))
+
+(defun modus-themes--link (fg fgfaint underline)
+  "Conditional application of link styles.
+FG is the link's default color for its text and underline
+property.  FGFAINT is a desaturated color for the text and
+underline.  UNDERLINE is a grey color only for the undeline."
+  (pcase modus-themes-links
+    ('faint (list :foreground fgfaint :underline t))
+    ('neutral-underline (list :foreground fg :underline underline))
+    ('faint-neutral-underline (list :foreground fgfaint :underline underline))
+    ('no-underline (list :foreground fg :underline nil))
+    ('underline-only (list :underline t))
+    ('neutral-underline-only (list :underline underline))
+    (_ (list :foreground fg :underline t))))
+
+(defun modus-themes--link-color (fg fgfaint &optional neutralfg)
+  "Extends `modus-themes--link'.
+FG is the main accented foreground.  FGFAINT is also accented,
+yet desaturated.  Optional NEUTRALFG is a gray value."
+  (pcase modus-themes-links
+    ('faint (list :foreground fgfaint))
+    ('faint-neutral-underline (list :foreground fgfaint))
+    ('underline-only (list :underline t :foreground (or neutralfg 
'unspecified)))
+    ('neutral-underline-only (list :underline 'unspecified :foreground (or 
neutralfg 'unspecified)))
+    (_ (list :foreground fg))))
+
+(defun modus-themes--scale (amount)
+  "Scale heading by AMOUNT.
+AMOUNT is a customization option."
+  (when modus-themes-scale-headings
+    (list :height amount)))
+
+(defun modus-themes--region (bg fg bgsubtle)
+  "Apply `modus-themes-region' styles.
+
+BG and FG are the main values that are used by default.  BGSUBTLE
+is a subtle background value that can be combined with all colors
+used to fontify text and code syntax."
+  (pcase modus-themes-region
+    ('bg-only (list :background bgsubtle))
+    ('bg-only-no-extend (list :background bgsubtle :extend nil))
+    ('no-extend (list :background bg :foreground fg :extend nil))
+    (_ (list :background bg :foreground fg))))
+
+
+
+;;;; Utilities for DIY users
+
+;; This is the WCAG formula: https://www.w3.org/TR/WCAG20-TECHS/G18.html
+(defun modus-themes-wcag-formula (hex)
+  "Get WCAG value of color value HEX.
+The value is defined in hexadecimal RGB notation, such as those in
+`modus-themes-operandi-colors' and `modus-themes-vivendi-colors'."
+  (cl-loop for k in '(0.2126 0.7152 0.0722)
+           for x in (color-name-to-rgb hex)
+           sum (* k (if (<= x 0.03928)
+                        (/ x 12.92)
+                      (expt (/ (+ x 0.055) 1.055) 2.4)))))
+
+;;;###autoload
+(defun modus-themes-contrast (c1 c2)
+  "Measure WCAG contrast ratio between C1 and C2.
+C1 and C2 are color values written in hexadecimal RGB."
+  (let ((ct (/ (+ (modus-themes-wcag-formula c1) 0.05)
+               (+ (modus-themes-wcag-formula c2) 0.05))))
+    (max ct (/ ct))))
+
+(defun modus-themes-current-palette ()
+  "Return current color palette."
+  (modus-themes--palette (modus-themes--current-theme)))
+
+;;;###autoload
+(defun modus-themes-color (color)
+  "Return color value for COLOR from current palette.
+COLOR is a key in `modus-themes-operandi-colors' or
+`modus-themes-vivendi-colors'."
+  (alist-get color (modus-themes-current-palette)))
+
+;;;###autoload
+(defun modus-themes-color-alts (light-color dark-color)
+  "Return color value from current palette.
+When Modus Operandi is enabled, return color value for color
+LIGHT-COLOR.  When Modus Vivendi is enabled, return color value
+for DARK-COLOR.  LIGHT-COLOR and DARK-COLOR are keys in
+`modus-themes-operandi-colors' or `modus-themes-vivendi-colors'."
+  (let* ((theme (modus-themes--current-theme))
+         (color (pcase theme
+                  ('modus-operandi light-color)
+                  ('modus-vivendi dark-color)
+                  (_theme
+                   (error "'%s' is not a Modus theme" theme)))))
+    (alist-get color (modus-themes--palette theme))))
+
+(defmacro modus-themes-with-colors (&rest body)
+  "Evaluate BODY with colors from current palette bound.
+For colors bound, see `modus-themes-operandi-colors' or
+`modus-themes-vivendi-colors'."
+  (declare (indent 0))
+  (let ((palette-sym (gensym))
+        (colors (mapcar #'car modus-themes-operandi-colors)))
+    `(let* ((class '((class color) (min-colors 89)))
+            (,palette-sym (modus-themes-current-palette))
+            ,@(mapcar (lambda (color)
+                        (list color `(alist-get ',color ,palette-sym)))
+                      colors))
+       (ignore class ,@colors)          ; Silence unused variable warnings
+       ,@body)))
+
+
+
+;;;; Commands
+
+;;;###autoload
+(defun modus-themes-load-themes ()
+  "Ensure that the Modus themes are in `custom-enabled-themes'.
+
+This function is intended for use in package declarations such as
+those defined with the help of `use-package'.  The idea is to add
+this function to the `:init' stage of the package's loading, so
+that subsequent calls that assume the presence of a loaded theme,
+like `modus-themes-toggle' or `modus-themes-load-operandi', will
+continue to work as intended even if they are lazy-loaded (such
+as when they are declared in the `:config' phase)."
+  (unless (or (custom-theme-p 'modus-operandi)
+              (custom-theme-p 'modus-vivendi))
+    (load-theme 'modus-operandi t t)
+    (load-theme 'modus-vivendi t t)))
+
+(defvar modus-themes-after-load-theme-hook nil
+  "Hook that runs after the `modus-themes-toggle' routines.")
+
+;; The reason we use `load-theme' instead of `enable-theme' is that the
+;; former does a kind of "reset" on the face specs.  So it plays nicely
+;; with `custom-set-faces', as well as defcustom user customizations,
+;; including the likes of `modus-themes-operandi-color-overrides'.
+;;
+;; Tests show that `enable-theme' does not re-read those variables, so
+;; it might appear to the unsuspecting user that the themes are somehow
+;; broken.
+;;
+;; This "reset", however, comes at the cost of being a bit slower than
+;; `enable-theme'.  User who have a stable setup and seldom update their
+;; variables during a given Emacs session, are better off using
+;; something like this:
+;;
+;; (defun modus-themes-toggle-enabled ()
+;;   "Toggle between `modus-operandi' and `modus-vivendi' themes."
+;;   (interactive)
+;;   (pcase (modus-themes--current-theme)
+;;     ('modus-operandi (progn (enable-theme 'modus-vivendi)
+;;                             (disable-theme 'modus-operandi)))
+;;     ('modus-vivendi (progn (enable-theme 'modus-operandi)
+;;                             (disable-theme 'modus-vivendi)))
+;;     (_ (error "No Modus theme is loaded; evaluate 
`modus-themes-load-themes' first"))))
+
+;;;###autoload
+(defun modus-themes-load-operandi ()
+  "Load `modus-operandi' and disable `modus-vivendi'.
+Also run `modus-themes-after-load-theme-hook'."
+  (disable-theme 'modus-vivendi)
+  (load-theme 'modus-operandi t)
+  (run-hooks 'modus-themes-after-load-theme-hook))
+
+;;;###autoload
+(defun modus-themes-load-vivendi ()
+  "Load `modus-vivendi' and disable `modus-operandi'.
+Also run `modus-themes-after-load-theme-hook'."
+  (disable-theme 'modus-operandi)
+  (load-theme 'modus-vivendi t)
+  (run-hooks 'modus-themes-after-load-theme-hook))
+
+(defun modus-themes--load-prompt ()
+  "Helper for `modus-themes-toggle'."
+  (let ((theme
+         (intern
+          (completing-read "Load Modus theme (will disable all others): "
+                           '(modus-operandi modus-vivendi) nil t))))
+    (mapc #'disable-theme custom-enabled-themes)
+    (pcase theme
+      ('modus-operandi (modus-themes-load-operandi))
+      ('modus-vivendi (modus-themes-load-vivendi)))))
+
+;;;###autoload
+(defun modus-themes-toggle ()
+  "Toggle between `modus-operandi' and `modus-vivendi' themes.
+Also runs `modus-themes-after-load-theme-hook' at its last stage
+by virtue of calling either of `modus-themes-load-operandi' and
+`modus-themes-load-vivendi' functions."
+  (interactive)
+  (modus-themes-load-themes)
+  (pcase (modus-themes--current-theme)
+    ('modus-operandi (modus-themes-load-vivendi))
+    ('modus-vivendi (modus-themes-load-operandi))
+    (_ (modus-themes--load-prompt))))
+
+
+
+;;;; Face specifications
+
+(defconst modus-themes-faces
+  '(
+;;;; custom faces
+    ;; these bespoke faces are inherited by other constructs below
+;;;;; subtle colored backgrounds
+    `(modus-theme-subtle-red ((,class :background ,red-subtle-bg :foreground 
,fg-dim)))
+    `(modus-theme-subtle-green ((,class :background ,green-subtle-bg 
:foreground ,fg-dim)))
+    `(modus-theme-subtle-yellow ((,class :background ,yellow-subtle-bg 
:foreground ,fg-dim)))
+    `(modus-theme-subtle-blue ((,class :background ,blue-subtle-bg :foreground 
,fg-dim)))
+    `(modus-theme-subtle-magenta ((,class :background ,magenta-subtle-bg 
:foreground ,fg-dim)))
+    `(modus-theme-subtle-cyan ((,class :background ,cyan-subtle-bg :foreground 
,fg-dim)))
+    `(modus-theme-subtle-neutral ((,class :background ,bg-inactive :foreground 
,fg-inactive)))
+;;;;; intense colored backgrounds
+    `(modus-theme-intense-red ((,class :background ,red-intense-bg :foreground 
,fg-main)))
+    `(modus-theme-intense-green ((,class :background ,green-intense-bg 
:foreground ,fg-main)))
+    `(modus-theme-intense-yellow ((,class :background ,yellow-intense-bg 
:foreground ,fg-main)))
+    `(modus-theme-intense-blue ((,class :background ,blue-intense-bg 
:foreground ,fg-main)))
+    `(modus-theme-intense-magenta ((,class :background ,magenta-intense-bg 
:foreground ,fg-main)))
+    `(modus-theme-intense-cyan ((,class :background ,cyan-intense-bg 
:foreground ,fg-main)))
+    `(modus-theme-intense-neutral ((,class :background ,bg-active :foreground 
,fg-main)))
+;;;;; refined background and foreground combinations
+    ;; general purpose styles that use an accented foreground against an
+    ;; accented background
+    `(modus-theme-refine-red ((,class :background ,red-refine-bg :foreground 
,red-refine-fg)))
+    `(modus-theme-refine-green ((,class :background ,green-refine-bg 
:foreground ,green-refine-fg)))
+    `(modus-theme-refine-yellow ((,class :background ,yellow-refine-bg 
:foreground ,yellow-refine-fg)))
+    `(modus-theme-refine-blue ((,class :background ,blue-refine-bg :foreground 
,blue-refine-fg)))
+    `(modus-theme-refine-magenta ((,class :background ,magenta-refine-bg 
:foreground ,magenta-refine-fg)))
+    `(modus-theme-refine-cyan ((,class :background ,cyan-refine-bg :foreground 
,cyan-refine-fg)))
+;;;;; "active" combinations, mostly for use on the mode line
+    `(modus-theme-active-red ((,class :background ,red-active :foreground 
,bg-active)))
+    `(modus-theme-active-green ((,class :background ,green-active :foreground 
,bg-active)))
+    `(modus-theme-active-yellow ((,class :background ,yellow-active 
:foreground ,bg-active)))
+    `(modus-theme-active-blue ((,class :background ,blue-active :foreground 
,bg-active)))
+    `(modus-theme-active-magenta ((,class :background ,magenta-active 
:foreground ,bg-active)))
+    `(modus-theme-active-cyan ((,class :background ,cyan-active :foreground 
,bg-active)))
+;;;;; nuanced backgrounds
+    ;; useful for adding an accented background that is suitable for all
+    ;; main foreground colors (intended for use in Org source blocks)
+    `(modus-theme-nuanced-red ((,class :background ,red-nuanced-bg :extend t)))
+    `(modus-theme-nuanced-green ((,class :background ,green-nuanced-bg :extend 
t)))
+    `(modus-theme-nuanced-yellow ((,class :background ,yellow-nuanced-bg 
:extend t)))
+    `(modus-theme-nuanced-blue ((,class :background ,blue-nuanced-bg :extend 
t)))
+    `(modus-theme-nuanced-magenta ((,class :background ,magenta-nuanced-bg 
:extend t)))
+    `(modus-theme-nuanced-cyan ((,class :background ,cyan-nuanced-bg :extend 
t)))
+;;;;; fringe-specific combinations
+    `(modus-theme-fringe-red ((,class :background ,red-fringe-bg :foreground 
,fg-main)))
+    `(modus-theme-fringe-green ((,class :background ,green-fringe-bg 
:foreground ,fg-main)))
+    `(modus-theme-fringe-yellow ((,class :background ,yellow-fringe-bg 
:foreground ,fg-main)))
+    `(modus-theme-fringe-blue ((,class :background ,blue-fringe-bg :foreground 
,fg-main)))
+    `(modus-theme-fringe-magenta ((,class :background ,magenta-fringe-bg 
:foreground ,fg-main)))
+    `(modus-theme-fringe-cyan ((,class :background ,cyan-fringe-bg :foreground 
,fg-main)))
+;;;;; special base values
+    ;; these are closer to the grayscale than the accents defined above
+    ;; and should only be used when the next closest alternative would be
+    ;; a greyscale value than an accented one
+    `(modus-theme-special-cold ((,class :background ,bg-special-cold 
:foreground ,fg-special-cold)))
+    `(modus-theme-special-mild ((,class :background ,bg-special-mild 
:foreground ,fg-special-mild)))
+    `(modus-theme-special-warm ((,class :background ,bg-special-warm 
:foreground ,fg-special-warm)))
+    `(modus-theme-special-calm ((,class :background ,bg-special-calm 
:foreground ,fg-special-calm)))
+;;;;; diff-specific combinations
+    ;; intended for `diff-mode' or equivalent
+    `(modus-theme-diff-added
+      ((,class ,@(modus-themes--diff
+                  bg-main green
+                  bg-diff-focus-added fg-diff-focus-added
+                  green-nuanced-bg fg-diff-added
+                  bg-diff-focus-added-deuteran fg-diff-focus-added-deuteran))))
+    `(modus-theme-diff-changed
+      ((,class ,@(modus-themes--diff
+                  bg-main yellow
+                  bg-diff-focus-changed fg-diff-focus-changed
+                  yellow-nuanced-bg fg-diff-changed))))
+    `(modus-theme-diff-removed
+      ((,class ,@(modus-themes--diff
+                  bg-main red
+                  bg-diff-focus-removed fg-diff-focus-removed
+                  red-nuanced-bg fg-diff-removed))))
+    `(modus-theme-diff-refine-added
+      ((,class ,@(modus-themes--diff
+                  bg-diff-added fg-diff-added
+                  bg-diff-refine-added fg-diff-refine-added
+                  bg-diff-focus-added fg-diff-focus-added
+                  bg-diff-refine-added-deuteran 
fg-diff-refine-added-deuteran))))
+    `(modus-theme-diff-refine-changed
+      ((,class ,@(modus-themes--diff
+                  bg-diff-changed fg-diff-changed
+                  bg-diff-refine-changed fg-diff-refine-changed
+                  bg-diff-focus-changed fg-diff-focus-changed))))
+    `(modus-theme-diff-refine-removed
+      ((,class ,@(modus-themes--diff
+                  bg-diff-removed fg-diff-removed
+                  bg-diff-refine-removed fg-diff-refine-removed
+                  bg-diff-focus-removed fg-diff-focus-removed))))
+    `(modus-theme-diff-focus-added
+      ((,class ,@(modus-themes--diff
+                  bg-dim green
+                  bg-diff-focus-added fg-diff-focus-added
+                  bg-diff-added fg-diff-added
+                  bg-diff-focus-added-deuteran fg-diff-focus-added-deuteran))))
+    `(modus-theme-diff-focus-changed
+      ((,class ,@(modus-themes--diff
+                  bg-dim yellow
+                  bg-diff-focus-changed fg-diff-focus-changed
+                  bg-diff-changed fg-diff-changed))))
+    `(modus-theme-diff-focus-removed
+      ((,class ,@(modus-themes--diff
+                  bg-dim red
+                  bg-diff-focus-removed fg-diff-focus-removed
+                  bg-diff-removed fg-diff-removed))))
+    `(modus-theme-diff-heading
+      ((,class ,@(modus-themes--diff
+                  bg-main blue
+                  bg-diff-heading fg-diff-heading
+                  cyan-nuanced-bg cyan-nuanced-fg
+                  bg-header fg-main
+                  t))))
+;;;;; mark indicators
+    ;; color combinations intended for Dired, Ibuffer, or equivalent
+    `(modus-theme-pseudo-header ((,class :inherit bold :foreground ,fg-main)))
+    `(modus-theme-mark-alt ((,class :inherit bold :background ,bg-mark-alt 
:foreground ,fg-mark-alt)))
+    `(modus-theme-mark-del ((,class :inherit bold :background ,bg-mark-del 
:foreground ,fg-mark-del)))
+    `(modus-theme-mark-sel ((,class :inherit bold :background ,bg-mark-sel 
:foreground ,fg-mark-sel)))
+    `(modus-theme-mark-symbol ((,class :inherit bold :foreground ,blue-alt)))
+;;;;; heading levels
+    ;; styles for regular headings used in Org, Markdown, Info, etc.
+    `(modus-theme-heading-1
+      ((,class ,@(modus-themes--heading
+                  1 fg-main magenta-alt-other magenta-nuanced-bg bg-region)
+               ,@(modus-themes--scale modus-themes-scale-4))))
+    `(modus-theme-heading-2
+      ((,class ,@(modus-themes--heading
+                  2 fg-special-warm magenta-alt red-nuanced-bg bg-region)
+               ,@(modus-themes--scale modus-themes-scale-3))))
+    `(modus-theme-heading-3
+      ((,class ,@(modus-themes--heading
+                  3 fg-special-cold blue blue-nuanced-bg bg-region)
+               ,@(modus-themes--scale modus-themes-scale-2))))
+    `(modus-theme-heading-4
+      ((,class ,@(modus-themes--heading
+                  4 fg-special-mild cyan cyan-nuanced-bg bg-region)
+               ,@(modus-themes--scale modus-themes-scale-1))))
+    `(modus-theme-heading-5
+      ((,class ,@(modus-themes--heading
+                  5 fg-special-calm green-alt-other green-nuanced-bg 
bg-region))))
+    `(modus-theme-heading-6
+      ((,class ,@(modus-themes--heading
+                  6 yellow-nuanced-fg yellow-alt-other yellow-nuanced-bg 
bg-region))))
+    `(modus-theme-heading-7
+      ((,class ,@(modus-themes--heading
+                  7 red-nuanced-fg red-alt red-nuanced-bg bg-region))))
+    `(modus-theme-heading-8
+      ((,class ,@(modus-themes--heading
+                  8 fg-dim magenta bg-alt bg-region))))
+;;;;; graph-specific faces
+    `(modus-theme-graph-red-0 ((,class :background ,red-graph-0-bg)))
+    `(modus-theme-graph-red-1 ((,class :background ,red-graph-1-bg)))
+    `(modus-theme-graph-green-0 ((,class :background ,green-graph-0-bg)))
+    `(modus-theme-graph-green-1 ((,class :background ,green-graph-1-bg)))
+    `(modus-theme-graph-yellow-0 ((,class :background ,yellow-graph-0-bg)))
+    `(modus-theme-graph-yellow-1 ((,class :background ,yellow-graph-1-bg)))
+    `(modus-theme-graph-blue-0 ((,class :background ,blue-graph-0-bg)))
+    `(modus-theme-graph-blue-1 ((,class :background ,blue-graph-1-bg)))
+    `(modus-theme-graph-magenta-0 ((,class :background ,magenta-graph-0-bg)))
+    `(modus-theme-graph-magenta-1 ((,class :background ,magenta-graph-1-bg)))
+    `(modus-theme-graph-cyan-0 ((,class :background ,cyan-graph-0-bg)))
+    `(modus-theme-graph-cyan-1 ((,class :background ,cyan-graph-1-bg)))
+;;;;; language checkers
+    `(modus-theme-lang-error ((,class ,@(modus-themes--lang-check 
fg-lang-underline-error fg-lang-error red red-nuanced-bg))))
+    `(modus-theme-lang-note ((,class ,@(modus-themes--lang-check 
fg-lang-underline-note fg-lang-note blue-alt blue-nuanced-bg))))
+    `(modus-theme-lang-warning ((,class ,@(modus-themes--lang-check 
fg-lang-underline-warning fg-lang-warning yellow yellow-nuanced-bg))))
+;;;;; other custom faces
+    `(modus-theme-bold ((,class ,@(modus-themes--bold-weight))))
+    `(modus-theme-hl-line ((,class :background ,(if 
modus-themes-intense-hl-line
+                                                    bg-hl-line-intense 
bg-hl-line)
+                                   :extend t)))
+    `(modus-theme-slant ((,class :inherit italic :slant 
,@(modus-themes--slant))))
+    `(modus-theme-variable-pitch ((,class ,@(modus-themes--variable-pitch))))
+;;;; standard faces
+;;;;; absolute essentials
+    `(default ((,class :background ,bg-main :foreground ,fg-main)))
+    `(cursor ((,class :background ,fg-main)))
+    `(fringe ((,class ,@(modus-themes--fringe bg-main bg-inactive bg-active)
+                      :foreground ,fg-main)))
+    `(vertical-border ((,class :foreground ,fg-window-divider-inner)))
+;;;;; basic and/or ungrouped styles
+    `(bold ((,class :weight bold)))
+    `(bold-italic ((,class :inherit (bold italic))))
+    `(buffer-menu-buffer ((,class :inherit bold)))
+    `(comint-highlight-input ((,class :inherit bold)))
+    `(comint-highlight-prompt ((,class :inherit modus-theme-bold
+                                       ,@(modus-themes--prompt
+                                          cyan
+                                          blue-nuanced-bg blue-alt
+                                          blue-refine-bg fg-main))))
+    `(error ((,class :inherit bold :foreground ,red)))
+    `(escape-glyph ((,class :foreground ,fg-escape-char-construct)))
+    `(file-name-shadow ((,class :foreground ,fg-unfocused)))
+    `(header-line ((,class ,@(modus-themes--variable-pitch-ui)
+                           :background ,bg-header :foreground ,fg-header)))
+    `(header-line-highlight ((,class :inherit modus-theme-active-blue)))
+    `(help-argument-name ((,class :inherit modus-theme-slant :foreground 
,cyan)))
+    `(homoglyph ((,class :foreground ,red-alt-faint)))
+    `(ibuffer-locked-buffer ((,class :foreground ,yellow-alt-other-faint)))
+    `(italic ((,class :slant italic)))
+    `(nobreak-hyphen ((,class :foreground ,fg-escape-char-construct)))
+    `(nobreak-space ((,class :foreground ,fg-escape-char-construct :underline 
t)))
+    `(minibuffer-prompt ((,class ,@(modus-themes--prompt
+                                    cyan-alt-other
+                                    cyan-nuanced-bg cyan
+                                    cyan-refine-bg fg-main))))
+    `(mm-command-output ((,class :foreground ,red-alt-other)))
+    `(mm-uu-extract ((,class :background ,bg-dim :foreground 
,fg-special-mild)))
+    `(next-error ((,class :inherit modus-theme-subtle-red)))
+    `(rectangle-preview ((,class :inherit modus-theme-special-mild)))
+    `(region ((,class ,@(modus-themes--region bg-region fg-main 
bg-hl-alt-intense))))
+    `(secondary-selection ((,class :inherit modus-theme-special-cold)))
+    `(shadow ((,class :foreground ,fg-alt)))
+    `(success ((,class :inherit bold :foreground ,green)))
+    `(trailing-whitespace ((,class :background ,red-intense-bg)))
+    `(warning ((,class :inherit bold :foreground ,yellow)))
+;;;;; buttons, links, widgets
+    `(button ((,class ,@(modus-themes--link
+                         blue-alt-other blue-alt-other-faint bg-region))))
+    `(link ((,class :inherit button)))
+    `(link-visited ((,class :inherit button
+                            ,@(modus-themes--link-color
+                               magenta-alt-other magenta-alt-other-faint 
fg-alt))))
+    `(tooltip ((,class :background ,bg-special-cold :foreground ,fg-main)))
+    `(widget-button ((,class :inherit button)))
+    `(widget-button-pressed ((,class :inherit button
+                                     ,@(modus-themes--link-color
+                                        magenta magenta-faint))))
+    `(widget-documentation ((,class :foreground ,green)))
+    `(widget-field ((,class :background ,bg-alt :foreground ,fg-dim)))
+    `(widget-inactive ((,class :background ,bg-inactive :foreground 
,fg-inactive)))
+    `(widget-single-line-field ((,class :inherit widget-field)))
+;;;;; ag
+    `(ag-hit-face ((,class :foreground ,fg-special-cold)))
+    `(ag-match-face ((,class :inherit modus-theme-special-calm)))
+;;;;; alert
+    `(alert-high-face ((,class :inherit bold :foreground ,red-alt)))
+    `(alert-low-face ((,class :foreground ,fg-special-mild)))
+    `(alert-moderate-face ((,class :inherit bold :foreground ,yellow)))
+    `(alert-trivial-face ((,class :foreground ,fg-special-calm)))
+    `(alert-urgent-face ((,class :inherit bold :foreground ,red-intense)))
+;;;;; all-the-icons
+    `(all-the-icons-blue ((,class :foreground ,blue)))
+    `(all-the-icons-blue-alt ((,class :foreground ,blue-alt)))
+    `(all-the-icons-cyan ((,class :foreground ,cyan)))
+    `(all-the-icons-cyan-alt ((,class :foreground ,cyan-alt)))
+    `(all-the-icons-dblue ((,class :foreground ,blue-alt-other)))
+    `(all-the-icons-dcyan ((,class :foreground ,cyan-alt-other)))
+    `(all-the-icons-dgreen ((,class :foreground ,green-alt-other)))
+    `(all-the-icons-dired-dir-face ((,class :foreground ,blue)))
+    `(all-the-icons-dmaroon ((,class :foreground ,magenta-alt-other)))
+    `(all-the-icons-dorange ((,class :foreground ,red-alt-other)))
+    `(all-the-icons-dpink ((,class :foreground ,magenta)))
+    `(all-the-icons-dpurple ((,class :foreground ,magenta-alt)))
+    `(all-the-icons-dred ((,class :foreground ,red)))
+    `(all-the-icons-dsilver ((,class :foreground ,fg-special-cold)))
+    `(all-the-icons-dyellow ((,class :foreground ,yellow)))
+    `(all-the-icons-green ((,class :foreground ,green)))
+    `(all-the-icons-lblue ((,class :foreground ,blue-refine-fg)))
+    `(all-the-icons-lcyan ((,class :foreground ,cyan-refine-fg)))
+    `(all-the-icons-lgreen ((,class :foreground ,green-refine-fg)))
+    `(all-the-icons-lmaroon ((,class :foreground ,magenta-refine-fg)))
+    `(all-the-icons-lorange ((,class :foreground ,red-refine-fg)))
+    `(all-the-icons-lpink ((,class :foreground ,magenta-refine-fg)))
+    `(all-the-icons-lpurple ((,class :foreground ,magenta-refine-fg)))
+    `(all-the-icons-lred ((,class :foreground ,red-refine-fg)))
+    `(all-the-icons-lsilver ((,class :foreground ,fg-special-cold)))
+    `(all-the-icons-lyellow ((,class :foreground ,yellow-refine-fg)))
+    `(all-the-icons-maroon ((,class :foreground ,magenta)))
+    `(all-the-icons-orange ((,class :foreground ,red-alt)))
+    `(all-the-icons-pink ((,class :foreground ,magenta)))
+    `(all-the-icons-purple ((,class :foreground ,magenta-alt)))
+    `(all-the-icons-purple-alt ((,class :foreground ,magenta-alt-other)))
+    `(all-the-icons-red ((,class :foreground ,red)))
+    `(all-the-icons-red-alt ((,class :foreground ,red-alt)))
+    `(all-the-icons-silver ((,class :foreground ,fg-special-cold)))
+    `(all-the-icons-yellow ((,class :foreground ,yellow)))
+;;;;; annotate
+    `(annotate-annotation ((,class :inherit modus-theme-subtle-blue)))
+    `(annotate-annotation-secondary ((,class :inherit 
modus-theme-subtle-green)))
+    `(annotate-highlight ((,class :background ,blue-nuanced-bg :underline 
,blue-intense)))
+    `(annotate-highlight-secondary ((,class :background ,green-nuanced-bg 
:underline ,green-intense)))
+;;;;; anzu
+    `(anzu-match-1 ((,class :inherit modus-theme-subtle-cyan)))
+    `(anzu-match-2 ((,class :inherit modus-theme-subtle-green)))
+    `(anzu-match-3 ((,class :inherit modus-theme-subtle-yellow)))
+    `(anzu-mode-line ((,class :inherit bold :foreground ,green-active)))
+    `(anzu-mode-line-no-match ((,class :inherit bold :foreground ,red-active)))
+    `(anzu-replace-highlight ((,class :inherit modus-theme-refine-yellow 
:underline t)))
+    `(anzu-replace-to ((,class :inherit (modus-theme-intense-green bold))))
+;;;;; apropos
+    `(apropos-function-button ((,class :inherit button
+                                       ,@(modus-themes--link-color
+                                          magenta-alt-other 
magenta-alt-other-faint))))
+    `(apropos-keybinding ((,class :inherit bold :foreground ,cyan)))
+    `(apropos-misc-button ((,class :inherit button
+                                   ,@(modus-themes--link-color
+                                      cyan-alt-other cyan-alt-other-faint))))
+    `(apropos-property ((,class :inherit modus-theme-bold :foreground 
,magenta-alt)))
+    `(apropos-symbol ((,class :inherit modus-theme-bold :foreground 
,blue-alt-other)))
+    `(apropos-user-option-button ((,class :inherit button
+                                          ,@(modus-themes--link-color
+                                             green-alt-other 
green-alt-other-faint))))
+    `(apropos-variable-button ((,class :inherit button
+                                       ,@(modus-themes--link-color
+                                          blue blue-faint))))
+;;;;; apt-sources-list
+    `(apt-sources-list-components ((,class :foreground ,cyan)))
+    `(apt-sources-list-options ((,class :foreground ,yellow)))
+    `(apt-sources-list-suite ((,class :foreground ,green)))
+    `(apt-sources-list-type ((,class :foreground ,magenta)))
+    `(apt-sources-list-uri ((,class :foreground ,blue)))
+;;;;; artbollocks-mode
+    `(artbollocks-face ((,class :inherit modus-theme-lang-note)))
+    `(artbollocks-lexical-illusions-face ((,class :background ,bg-alt 
:foreground ,red-alt :underline t)))
+    `(artbollocks-passive-voice-face ((,class :inherit 
modus-theme-lang-warning)))
+    `(artbollocks-weasel-words-face ((,class :inherit modus-theme-lang-error)))
+;;;;; auctex and Tex
+    `(font-latex-bold-face ((,class :inherit bold :foreground 
,fg-special-calm)))
+    `(font-latex-doctex-documentation-face ((,class :inherit modus-theme-slant 
:foreground ,fg-special-cold)))
+    `(font-latex-doctex-preprocessor-face ((,class :inherit modus-theme-bold 
:foreground ,red-alt-other)))
+    `(font-latex-italic-face ((,class :inherit italic :foreground 
,fg-special-calm)))
+    `(font-latex-math-face ((,class :foreground ,cyan-alt-other)))
+    `(font-latex-script-char-face ((,class :foreground ,cyan-alt-other)))
+    `(font-latex-sectioning-0-face ((,class :inherit 
modus-theme-variable-pitch :foreground ,blue-nuanced-fg)))
+    `(font-latex-sectioning-1-face ((,class :inherit (bold 
modus-theme-variable-pitch) :foreground ,blue-nuanced-fg)))
+    `(font-latex-sectioning-2-face ((,class :inherit (bold 
modus-theme-variable-pitch) :foreground ,blue-nuanced-fg)))
+    `(font-latex-sectioning-3-face ((,class :inherit (bold 
modus-theme-variable-pitch) :foreground ,blue-nuanced-fg)))
+    `(font-latex-sectioning-4-face ((,class :inherit (bold 
modus-theme-variable-pitch) :foreground ,blue-nuanced-fg)))
+    `(font-latex-sectioning-5-face ((,class :inherit 
modus-theme-variable-pitch :foreground ,blue-nuanced-fg)))
+    `(font-latex-sedate-face ((,class :inherit modus-theme-bold :foreground 
,magenta-alt-other)))
+    `(font-latex-slide-title-face ((,class :inherit (bold 
modus-theme-variable-pitch) :foreground ,cyan-nuanced-fg
+                                           ,@(modus-themes--scale 
modus-themes-scale-4))))
+    `(font-latex-string-face ((,class :inherit font-lock-string-face)))
+    `(font-latex-subscript-face ((,class :height 0.95)))
+    `(font-latex-superscript-face ((,class :height 0.95)))
+    `(font-latex-verbatim-face ((,class :background ,bg-dim :foreground 
,fg-special-mild)))
+    `(font-latex-warning-face ((,class :inherit font-lock-warning-face)))
+    `(tex-match ((,class :foreground ,blue-alt-other)))
+    `(tex-verbatim ((,class :background ,bg-dim :foreground ,fg-special-mild)))
+    `(texinfo-heading ((,class :foreground ,magenta)))
+    `(TeX-error-description-error ((,class :inherit error)))
+    `(TeX-error-description-help ((,class :foreground ,blue)))
+    `(TeX-error-description-tex-said ((,class :foreground ,blue)))
+    `(TeX-error-description-warning ((,class :inherit warning)))
+;;;;; auto-dim-other-buffers
+    `(auto-dim-other-buffers-face ((,class :background ,bg-alt)))
+;;;;; avy
+    `(avy-background-face ((,class :background ,bg-dim :foreground ,fg-dim)))
+    `(avy-goto-char-timer-face ((,class :inherit (modus-theme-intense-yellow 
bold))))
+    `(avy-lead-face ((,class :inherit (modus-theme-intense-magenta bold))))
+    `(avy-lead-face-0 ((,class :inherit (modus-theme-intense-blue bold))))
+    `(avy-lead-face-1 ((,class :inherit (modus-theme-intense-red bold))))
+    `(avy-lead-face-2 ((,class :inherit (modus-theme-intense-green bold))))
+;;;;; aw (ace-window)
+    `(aw-background-face ((,class :background ,bg-dim :foreground ,fg-dim)))
+    `(aw-key-face ((,class :inherit bold :foreground ,blue-intense)))
+    `(aw-leading-char-face ((,class :inherit bold :height 1.5 :slant normal 
:background ,bg-main :foreground ,red-intense)))
+    `(aw-minibuffer-leading-char-face ((,class :foreground ,magenta-active)))
+    `(aw-mode-line-face ((,class :inherit bold)))
+;;;;; awesome-tray
+    `(awesome-tray-module-awesome-tab-face ((,class :inherit bold :foreground 
,red-alt-other)))
+    `(awesome-tray-module-battery-face ((,class :inherit bold :foreground 
,cyan-alt-other)))
+    `(awesome-tray-module-buffer-name-face ((,class :inherit bold :foreground 
,yellow-alt-other)))
+    `(awesome-tray-module-circe-face ((,class :inherit bold :foreground 
,blue-alt)))
+    `(awesome-tray-module-date-face ((,class :inherit bold :foreground 
,fg-dim)))
+    `(awesome-tray-module-evil-face ((,class :inherit bold :foreground 
,green-alt)))
+    `(awesome-tray-module-git-face ((,class :inherit bold :foreground 
,magenta)))
+    `(awesome-tray-module-last-command-face ((,class :inherit bold :foreground 
,blue-alt-other)))
+    `(awesome-tray-module-location-face ((,class :inherit bold :foreground 
,yellow)))
+    `(awesome-tray-module-mode-name-face ((,class :inherit bold :foreground 
,green)))
+    `(awesome-tray-module-parent-dir-face ((,class :inherit bold :foreground 
,cyan)))
+    `(awesome-tray-module-rvm-face ((,class :inherit bold :foreground 
,magenta-alt-other)))
+;;;;; bbdb
+    `(bbdb-name ((,class :foreground ,magenta-alt-other)))
+    `(bbdb-organization ((,class :foreground ,red-alt-other)))
+    `(bbdb-field-name ((,class :foreground ,cyan-alt-other)))
+;;;;; binder
+    `(binder-sidebar-highlight ((,class :inherit modus-theme-subtle-cyan)))
+    `(binder-sidebar-marked ((,class :inherit modus-theme-mark-sel)))
+    `(binder-sidebar-missing ((,class :inherit modus-theme-subtle-red)))
+    `(binder-sidebar-tags ((,class :foreground ,cyan)))
+;;;;; bm
+    `(bm-face ((,class :inherit modus-theme-subtle-yellow :extend t)))
+    `(bm-fringe-face ((,class :inherit modus-theme-fringe-yellow)))
+    `(bm-fringe-persistent-face ((,class :inherit modus-theme-fringe-blue)))
+    `(bm-persistent-face ((,class :inherit modus-theme-intense-blue :extend 
t)))
+;;;;; bongo
+    `(bongo-album-title ((,class :foreground ,yellow-active)))
+    `(bongo-artist ((,class :foreground ,magenta-active)))
+    `(bongo-currently-playing-track ((,class :inherit bold)))
+    `(bongo-elapsed-track-part ((,class :inherit modus-theme-subtle-magenta 
:underline t)))
+    `(bongo-filled-seek-bar ((,class :background ,blue-intense-bg :foreground 
,fg-main)))
+    `(bongo-marked-track ((,class :foreground ,fg-mark-alt)))
+    `(bongo-marked-track-line ((,class :background ,bg-mark-alt)))
+    `(bongo-played-track ((,class :foreground ,fg-unfocused :strike-through 
t)))
+    `(bongo-track-length ((,class :foreground ,fg-active)))
+    `(bongo-track-title ((,class :foreground ,cyan-active)))
+    `(bongo-unfilled-seek-bar ((,class :background ,bg-special-cold 
:foreground ,fg-main)))
+;;;;; boon
+    `(boon-modeline-cmd ((,class :inherit modus-theme-active-blue)))
+    `(boon-modeline-ins ((,class :inherit modus-theme-active-red)))
+    `(boon-modeline-off ((,class :inherit modus-theme-active-yellow)))
+    `(boon-modeline-spc ((,class :inherit modus-theme-active-green)))
+;;;;; breakpoint (built-in gdb-mi.el)
+    `(breakpoint-disabled ((,class :inherit shadow)))
+    `(breakpoint-enabled ((,class :inherit bold :foreground ,red)))
+;;;;; buffer-expose
+    `(buffer-expose-ace-char-face ((,class :inherit bold :foreground 
,red-active)))
+    `(buffer-expose-mode-line-face ((,class :foreground ,cyan-active)))
+    `(buffer-expose-selected-face ((,class :inherit modus-theme-special-mild)))
+;;;;; calendar and diary
+    `(calendar-month-header ((,class :inherit modus-theme-pseudo-header)))
+    `(calendar-today ((,class :inherit bold :underline t)))
+    `(calendar-weekday-header ((,class :inherit shadow)))
+    `(calendar-weekend-header ((,class :inherit shadow)))
+    `(diary ((,class :background ,green-nuanced-bg :foreground 
,green-alt-other)))
+    `(diary-anniversary ((,class :foreground ,red-alt-other)))
+    `(diary-time ((,class :foreground ,blue-alt)))
+    `(holiday ((,class :background ,magenta-nuanced-bg :foreground 
,magenta-alt)))
+;;;;; calfw
+    `(cfw:face-annotation ((,class :foreground ,fg-special-warm)))
+    `(cfw:face-day-title ((,class :foreground ,fg-main)))
+    `(cfw:face-default-content ((,class :foreground ,green-alt)))
+    `(cfw:face-default-day ((,class :inherit (cfw:face-day-title bold))))
+    `(cfw:face-disable ((,class :foreground ,fg-unfocused)))
+    `(cfw:face-grid ((,class :foreground ,fg-window-divider-outer)))
+    `(cfw:face-header ((,class :inherit bold :foreground ,fg-main)))
+    `(cfw:face-holiday ((,class :foreground ,magenta-alt-other)))
+    `(cfw:face-periods ((,class :foreground ,cyan-alt-other)))
+    `(cfw:face-saturday ((,class :inherit bold :foreground ,cyan-alt-other)))
+    `(cfw:face-select ((,class :inherit modus-theme-intense-blue)))
+    `(cfw:face-sunday ((,class :inherit bold :foreground ,cyan-alt-other)))
+    `(cfw:face-title ((,class :inherit modus-theme-variable-pitch
+                              :foreground ,fg-special-cold
+                              ,@(modus-themes--scale modus-themes-scale-5))))
+    `(cfw:face-today ((,class :background ,bg-inactive)))
+    `(cfw:face-today-title ((,class :background ,bg-active)))
+    `(cfw:face-toolbar ((,class :background ,bg-alt :foreground ,bg-alt)))
+    `(cfw:face-toolbar-button-off ((,class :inherit shadow)))
+    `(cfw:face-toolbar-button-on ((,class :inherit bold :background 
,blue-nuanced-bg
+                                          :foreground ,blue-alt)))
+;;;;; centaur-tabs
+    `(centaur-tabs-active-bar-face ((,class :background ,fg-tab-active)))
+    `(centaur-tabs-close-mouse-face ((,class :inherit bold :foreground 
,red-active :underline t)))
+    `(centaur-tabs-close-selected ((,class :inherit centaur-tabs-selected)))
+    `(centaur-tabs-close-unselected ((,class :inherit 
centaur-tabs-unselected)))
+    `(centaur-tabs-modified-marker-selected ((,class :inherit 
centaur-tabs-selected)))
+    `(centaur-tabs-modified-marker-unselected ((,class :inherit 
centaur-tabs-unselected)))
+    `(centaur-tabs-default ((,class :background ,bg-main :foreground 
,bg-main)))
+    `(centaur-tabs-selected ((,class :inherit bold :background ,bg-tab-active 
:foreground ,fg-main)))
+    `(centaur-tabs-selected-modified ((,class :inherit italic :background 
,bg-tab-active :foreground ,fg-main)))
+    `(centaur-tabs-unselected ((,class :background ,bg-tab-inactive 
:foreground ,fg-dim)))
+    `(centaur-tabs-unselected-modified ((,class :inherit italic :background 
,bg-tab-inactive :foreground ,fg-dim)))
+;;;;; cfrs
+    `(cfrs-border-color ((,class :background ,fg-window-divider-inner)))
+;;;;; change-log and log-view (`vc-print-log' and `vc-print-root-log')
+    `(change-log-acknowledgment ((,class :foreground ,fg-alt)))
+    `(change-log-conditionals ((,class :foreground ,yellow)))
+    `(change-log-date ((,class :foreground ,cyan)))
+    `(change-log-email ((,class :foreground ,cyan-alt-other)))
+    `(change-log-file ((,class :inherit bold :foreground ,fg-special-cold)))
+    `(change-log-function ((,class :foreground ,green-alt-other)))
+    `(change-log-list ((,class :foreground ,magenta-alt)))
+    `(change-log-name ((,class :foreground ,magenta-alt-other)))
+    `(log-edit-header ((,class :foreground ,fg-special-warm)))
+    `(log-edit-summary ((,class :inherit bold :foreground ,blue)))
+    `(log-edit-unknown-header ((,class :inherit shadow)))
+    `(log-view-commit-body ((,class :foreground ,blue-nuanced-fg)))
+    `(log-view-file ((,class :inherit bold :foreground ,fg-special-cold)))
+    `(log-view-message ((,class :background ,bg-alt :foreground ,fg-alt)))
+;;;;; cider
+    `(cider-debug-code-overlay-face ((,class :background ,bg-alt)))
+    `(cider-debug-prompt-face ((,class :foreground ,magenta-alt :underline t)))
+    `(cider-deprecated-face ((,class :inherit modus-theme-refine-yellow)))
+    `(cider-docview-emphasis-face ((,class :inherit italic :foreground 
,fg-special-cold)))
+    `(cider-docview-literal-face ((,class :foreground ,blue-alt)))
+    `(cider-docview-strong-face ((,class :inherit bold :foreground 
,fg-special-cold)))
+    `(cider-docview-table-border-face ((,class :inherit shadow)))
+    `(cider-enlightened-face ((,class :box (:line-width -1 :color ,yellow-alt 
:style nil) :background ,bg-dim)))
+    `(cider-enlightened-local-face ((,class :inherit bold :foreground 
,yellow-alt-other)))
+    `(cider-error-highlight-face ((,class :foreground ,red :underline t)))
+    `(cider-fragile-button-face ((,class :box (:line-width 3 :color ,fg-alt 
:style released-button) :foreground ,yellow)))
+    `(cider-fringe-good-face ((,class :foreground ,green-active)))
+    `(cider-instrumented-face ((,class :box (:line-width -1 :color ,red :style 
nil) :background ,bg-dim)))
+    `(cider-reader-conditional-face ((,class :inherit italic :foreground 
,fg-special-warm)))
+    `(cider-repl-input-face ((,class :inherit bold)))
+    `(cider-repl-prompt-face ((,class :foreground ,cyan-alt-other)))
+    `(cider-repl-stderr-face ((,class :inherit bold :foreground ,red)))
+    `(cider-repl-stdout-face ((,class :foreground ,blue)))
+    `(cider-result-overlay-face ((,class :box (:line-width -1 :color ,blue 
:style nil) :background ,bg-dim)))
+    `(cider-stacktrace-error-class-face ((,class :inherit bold :foreground 
,red)))
+    `(cider-stacktrace-error-message-face ((,class :inherit italic :foreground 
,red-alt-other)))
+    `(cider-stacktrace-face ((,class :foreground ,fg-main)))
+    `(cider-stacktrace-filter-active-face ((,class :foreground ,cyan-alt 
:underline t)))
+    `(cider-stacktrace-filter-inactive-face ((,class :foreground ,cyan-alt)))
+    `(cider-stacktrace-fn-face ((,class :inherit bold :foreground ,fg-main)))
+    `(cider-stacktrace-ns-face ((,class :inherit italic :foreground ,fg-alt)))
+    `(cider-stacktrace-promoted-button-face ((,class :box (:line-width 3 
:color ,fg-alt :style released-button) :foreground ,red)))
+    `(cider-stacktrace-suppressed-button-face ((,class :box (:line-width 3 
:color ,fg-alt :style pressed-button)
+                                                       :background ,bg-alt 
:foreground ,fg-alt)))
+    `(cider-test-error-face ((,class :inherit modus-theme-subtle-red)))
+    `(cider-test-failure-face ((,class :inherit (modus-theme-intense-red 
bold))))
+    `(cider-test-success-face ((,class :inherit modus-theme-intense-green)))
+    `(cider-traced-face ((,class :box (:line-width -1 :color ,cyan :style nil) 
:background ,bg-dim)))
+    `(cider-warning-highlight-face ((,class :foreground ,yellow :underline t)))
+;;;;; circe (and lui)
+    `(circe-fool-face ((,class :inherit shadow)))
+    `(circe-highlight-nick-face ((,class :inherit bold :foreground ,blue)))
+    `(circe-prompt-face ((,class :inherit bold :foreground ,cyan-alt-other)))
+    `(circe-server-face ((,class :foreground ,fg-unfocused)))
+    `(lui-button-face ((,class :inherit button)))
+    `(lui-highlight-face ((,class :foreground ,magenta-alt)))
+    `(lui-time-stamp-face ((,class :foreground ,blue-nuanced-fg)))
+;;;;; color-rg
+    `(color-rg-font-lock-column-number ((,class :foreground 
,magenta-alt-other)))
+    `(color-rg-font-lock-command ((,class :inherit bold :foreground ,fg-main)))
+    `(color-rg-font-lock-file ((,class :inherit bold :foreground 
,fg-special-cold)))
+    `(color-rg-font-lock-flash ((,class :inherit modus-theme-intense-blue)))
+    `(color-rg-font-lock-function-location ((,class :inherit 
modus-theme-special-calm)))
+    `(color-rg-font-lock-header-line-directory ((,class :foreground 
,blue-active)))
+    `(color-rg-font-lock-header-line-edit-mode ((,class :foreground 
,magenta-active)))
+    `(color-rg-font-lock-header-line-keyword ((,class :foreground 
,green-active)))
+    `(color-rg-font-lock-header-line-text ((,class :foreground ,fg-active)))
+    `(color-rg-font-lock-line-number ((,class :foreground ,fg-special-warm)))
+    `(color-rg-font-lock-mark-changed ((,class :inherit bold :foreground 
,blue)))
+    `(color-rg-font-lock-mark-deleted ((,class :inherit bold :foreground 
,red)))
+    `(color-rg-font-lock-match ((,class :inherit modus-theme-special-calm)))
+    `(color-rg-font-lock-position-splitter ((,class :inherit shadow)))
+;;;;; column-enforce-mode
+    `(column-enforce-face ((,class :inherit modus-theme-refine-yellow)))
+;;;;; company-mode
+    `(company-echo-common ((,class :foreground ,magenta-alt-other)))
+    `(company-preview ((,class :background ,bg-dim :foreground ,fg-dim)))
+    `(company-preview-common ((,class :foreground ,blue-alt)))
+    `(company-preview-search ((,class :inherit modus-theme-special-calm)))
+    `(company-scrollbar-bg ((,class :background ,bg-active)))
+    `(company-scrollbar-fg ((,class :background ,fg-active)))
+    `(company-template-field ((,class :inherit modus-theme-intense-magenta)))
+    `(company-tooltip ((,class :background ,bg-alt :foreground ,fg-alt)))
+    `(company-tooltip-annotation ((,class :inherit modus-theme-slant 
:foreground ,fg-special-cold)))
+    `(company-tooltip-annotation-selection ((,class :inherit bold :foreground 
,fg-main)))
+    `(company-tooltip-common ((,class :inherit bold :foreground ,blue-alt)))
+    `(company-tooltip-common-selection ((,class :foreground ,fg-main)))
+    `(company-tooltip-mouse ((,class :inherit modus-theme-intense-blue)))
+    `(company-tooltip-search ((,class :inherit (modus-theme-refine-cyan 
bold))))
+    `(company-tooltip-search-selection ((,class :inherit 
(modus-theme-intense-green bold) :underline t)))
+    `(company-tooltip-selection ((,class :inherit (modus-theme-subtle-cyan 
bold))))
+;;;;; company-posframe
+    `(company-posframe-active-backend-name ((,class :inherit bold :background 
,bg-active :foreground ,blue-active)))
+    `(company-posframe-inactive-backend-name ((,class :background ,bg-active 
:foreground ,fg-active)))
+    `(company-posframe-metadata ((,class :background ,bg-inactive :foreground 
,fg-inactive)))
+;;;;; compilation feedback
+    `(compilation-column-number ((,class :foreground ,magenta-alt-other)))
+    `(compilation-error ((,class :inherit modus-theme-bold :foreground ,red)))
+    `(compilation-info ((,class :inherit modus-theme-bold :foreground 
,fg-special-cold)))
+    `(compilation-line-number ((,class :foreground ,fg-special-warm)))
+    `(compilation-mode-line-exit ((,class :inherit modus-theme-bold 
:foreground ,blue-active)))
+    `(compilation-mode-line-fail ((,class :inherit modus-theme-bold 
:foreground ,red-active)))
+    `(compilation-mode-line-run ((,class :inherit modus-theme-bold :foreground 
,magenta-active)))
+    `(compilation-warning ((,class :inherit modus-theme-bold :foreground 
,yellow)))
+;;;;; completions
+    `(completions-annotations ((,class :inherit modus-theme-slant :foreground 
,cyan-faint)))
+    `(completions-common-part ((,class ,@(modus-themes--standard-completions
+                                          blue-alt blue-nuanced-bg
+                                          cyan-refine-bg cyan-refine-fg))))
+    `(completions-first-difference ((,class :inherit bold
+                                            
,@(modus-themes--standard-completions
+                                               magenta-alt blue-nuanced-bg
+                                               magenta-intense-bg fg-main))))
+;;;;; consult
+    `(consult-async-running ((,class :inherit bold :foreground ,blue)))
+    `(consult-async-split ((,class :foreground ,magenta-alt)))
+    `(consult-bookmark ((,class :foreground ,blue)))
+    `(consult-file ((,class :foreground ,fg-special-cold)))
+    `(consult-imenu-prefix ((,class :inherit shadow)))
+    `(consult-key ((,class :inherit modus-themes-bold :foreground 
,magenta-alt-other)))
+    `(consult-line-number ((,class :foreground ,fg-special-warm)))
+    `(consult-line-number-prefix ((,class :foreground ,fg-unfocused)))
+    `(consult-narrow-indicator ((,class :foreground ,magenta-alt)))
+    `(consult-preview-cursor ((,class :inherit modus-theme-intense-blue)))
+    `(consult-preview-error ((,class :inherit modus-theme-intense-red)))
+    `(consult-preview-line ((,class :background ,bg-hl-alt-intense)))
+;;;;; counsel
+    `(counsel-active-mode ((,class :foreground ,magenta-alt-other)))
+    `(counsel-application-name ((,class :foreground ,red-alt-other)))
+    `(counsel-key-binding ((,class :inherit bold :foreground ,blue-alt-other)))
+    `(counsel-outline-1 ((,class :inherit org-level-1)))
+    `(counsel-outline-2 ((,class :inherit org-level-2)))
+    `(counsel-outline-3 ((,class :inherit org-level-3)))
+    `(counsel-outline-4 ((,class :inherit org-level-4)))
+    `(counsel-outline-5 ((,class :inherit org-level-5)))
+    `(counsel-outline-6 ((,class :inherit org-level-6)))
+    `(counsel-outline-7 ((,class :inherit org-level-7)))
+    `(counsel-outline-8 ((,class :inherit org-level-8)))
+    `(counsel-outline-default ((,class :foreground ,fg-main)))
+    `(counsel-variable-documentation ((,class :inherit modus-theme-slant 
:foreground ,yellow-alt-other)))
+;;;;; counsel-css
+    `(counsel-css-selector-depth-face-1 ((,class :foreground ,blue)))
+    `(counsel-css-selector-depth-face-2 ((,class :foreground ,cyan)))
+    `(counsel-css-selector-depth-face-3 ((,class :foreground ,green)))
+    `(counsel-css-selector-depth-face-4 ((,class :foreground ,yellow)))
+    `(counsel-css-selector-depth-face-5 ((,class :foreground ,magenta)))
+    `(counsel-css-selector-depth-face-6 ((,class :foreground ,red)))
+;;;;; counsel-notmuch
+    `(counsel-notmuch-count-face ((,class :foreground ,cyan)))
+    `(counsel-notmuch-date-face ((,class :foreground ,blue)))
+    `(counsel-notmuch-people-face ((,class :foreground ,magenta)))
+    `(counsel-notmuch-subject-face ((,class :foreground ,magenta-alt-other)))
+;;;;; counsel-org-capture-string
+    `(counsel-org-capture-string-template-body-face ((,class :foreground 
,fg-special-cold)))
+;;;;; cov
+    `(cov-coverage-not-run-face ((,class :foreground ,red-intense)))
+    `(cov-coverage-run-face ((,class :foreground ,green-intense)))
+    `(cov-heavy-face ((,class :foreground ,magenta-intense)))
+    `(cov-light-face ((,class :foreground ,blue-intense)))
+    `(cov-med-face ((,class :foreground ,yellow-intense)))
+    `(cov-none-face ((,class :foreground ,cyan-intense)))
+;;;;; cperl-mode
+    `(cperl-nonoverridable-face ((,class :foreground unspecified)))
+    `(cperl-array-face ((,class :inherit font-lock-keyword-face)))
+    `(cperl-hash-face ((,class :inherit font-lock-variable-name-face)))
+;;;;; csv-mode
+    `(csv-separator-face ((,class :background ,bg-special-cold :foreground 
,fg-main)))
+;;;;; ctrlf
+    `(ctrlf-highlight-active ((,class :inherit (modus-theme-intense-green 
bold))))
+    `(ctrlf-highlight-line ((,class :inherit modus-theme-hl-line)))
+    `(ctrlf-highlight-passive ((,class :inherit modus-theme-refine-cyan)))
+;;;;; custom (M-x customize)
+    `(custom-button ((,class :box (:line-width 2 :color nil :style 
released-button)
+                             :background ,bg-active :foreground ,fg-main)))
+    `(custom-button-mouse ((,class :box (:line-width 2 :color nil :style 
released-button)
+                                   :background ,bg-active :foreground 
,fg-active)))
+    `(custom-button-pressed ((,class :box (:line-width 2 :color nil :style 
pressed-button)
+                                     :background ,bg-active :foreground 
,fg-main)))
+    `(custom-changed ((,class :inherit modus-theme-subtle-cyan)))
+    `(custom-comment ((,class :inherit shadow)))
+    `(custom-comment-tag ((,class :background ,bg-alt :foreground 
,yellow-alt-other)))
+    `(custom-face-tag ((,class :inherit bold :foreground ,blue-intense)))
+    `(custom-group-tag ((,class :inherit bold :foreground ,green-intense)))
+    `(custom-group-tag-1 ((,class :inherit modus-theme-special-warm)))
+    `(custom-invalid ((,class :inherit (modus-theme-intense-red bold))))
+    `(custom-modified ((,class :inherit modus-theme-subtle-cyan)))
+    `(custom-rogue ((,class :inherit modus-theme-refine-magenta)))
+    `(custom-set ((,class :foreground ,blue-alt)))
+    `(custom-state ((,class :foreground ,cyan-alt-other)))
+    `(custom-themed ((,class :inherit modus-theme-subtle-blue)))
+    `(custom-variable-tag ((,class :inherit bold :foreground ,cyan)))
+;;;;; dap-mode
+    `(dap-mouse-eval-thing-face ((,class :box (:line-width -1 :color 
,blue-active :style nil)
+                                         :background ,bg-active :foreground 
,fg-main)))
+    `(dap-result-overlay-face ((,class :box (:line-width -1 :color ,bg-active 
:style nil)
+                                       :background ,bg-active :foreground 
,fg-main)))
+    `(dap-ui-breakpoint-verified-fringe ((,class :inherit bold :foreground 
,green-active)))
+    `(dap-ui-compile-errline ((,class :inherit bold :foreground ,red-intense)))
+    `(dap-ui-locals-scope-face ((,class :inherit bold :foreground ,magenta 
:underline t)))
+    `(dap-ui-locals-variable-face ((,class :inherit bold :foreground ,cyan)))
+    `(dap-ui-locals-variable-leaf-face ((,class :inherit italic :foreground 
,cyan-alt-other)))
+    `(dap-ui-marker-face ((,class :inherit modus-theme-subtle-blue)))
+    `(dap-ui-sessions-stack-frame-face ((,class :inherit bold :foreground 
,magenta-alt)))
+    `(dap-ui-sessions-terminated-active-face ((,class :inherit bold 
:foreground ,fg-alt)))
+    `(dap-ui-sessions-terminated-face ((,class :inherit shadow)))
+;;;;; dashboard (emacs-dashboard)
+    `(dashboard-banner-logo-title ((,class :inherit bold :foreground 
,fg-special-cold)))
+    `(dashboard-footer ((,class :inherit bold :foreground ,fg-special-mild)))
+    `(dashboard-heading ((,class :inherit bold :foreground ,fg-special-warm)))
+    `(dashboard-navigator ((,class :foreground ,cyan-alt-other)))
+    `(dashboard-text-banner ((,class :foreground ,fg-dim)))
+;;;;; deadgrep
+    `(deadgrep-filename-face ((,class :inherit bold :foreground 
,fg-special-cold)))
+    `(deadgrep-match-face ((,class :inherit modus-theme-special-calm)))
+    `(deadgrep-meta-face ((,class :inherit shadow)))
+    `(deadgrep-regexp-metachar-face ((,class :inherit bold :foreground 
,yellow-intense)))
+    `(deadgrep-search-term-face ((,class :inherit bold :foreground 
,green-intense)))
+;;;;; debbugs
+    `(debbugs-gnu-archived ((,class :inverse-video t)))
+    `(debbugs-gnu-done ((,class :inherit shadow)))
+    `(debbugs-gnu-forwarded ((,class :foreground ,fg-special-warm)))
+    `(debbugs-gnu-handled ((,class :foreground ,green)))
+    `(debbugs-gnu-new ((,class :foreground ,red)))
+    `(debbugs-gnu-pending ((,class :foreground ,cyan)))
+    `(debbugs-gnu-stale-1 ((,class :foreground ,yellow-nuanced-fg)))
+    `(debbugs-gnu-stale-2 ((,class :foreground ,yellow)))
+    `(debbugs-gnu-stale-3 ((,class :foreground ,yellow-alt)))
+    `(debbugs-gnu-stale-4 ((,class :foreground ,yellow-alt-other)))
+    `(debbugs-gnu-stale-5 ((,class :foreground ,red-alt)))
+    `(debbugs-gnu-tagged ((,class :foreground ,magenta-alt)))
+;;;;; define-word
+    `(define-word-face-1 ((,class :foreground ,yellow)))
+    `(define-word-face-2 ((,class :foreground ,fg-main)))
+;;;;; deft
+    `(deft-filter-string-error-face ((,class :inherit modus-theme-refine-red)))
+    `(deft-filter-string-face ((,class :foreground ,green-intense)))
+    `(deft-header-face ((,class :inherit bold :foreground ,fg-special-warm)))
+    `(deft-separator-face ((,class :inherit shadow)))
+    `(deft-summary-face ((,class :inherit modus-theme-slant :foreground 
,fg-alt)))
+    `(deft-time-face ((,class :foreground ,fg-special-cold)))
+    `(deft-title-face ((,class :inherit bold :foreground ,fg-main)))
+;;;;; dictionary
+    `(dictionary-button-face ((,class :inherit bold :foreground 
,fg-special-cold)))
+    `(dictionary-reference-face ((,class :inherit button)))
+    `(dictionary-word-definition-face (()))
+    `(dictionary-word-entry-face ((,class :inherit font-lock-comment-face)))
+;;;;; diff-hl
+    `(diff-hl-change ((,class :inherit modus-theme-fringe-yellow)))
+    `(diff-hl-delete ((,class :inherit modus-theme-fringe-red)))
+    `(diff-hl-dired-change ((,class :inherit diff-hl-change)))
+    `(diff-hl-dired-delete ((,class :inherit diff-hl-delete)))
+    `(diff-hl-dired-ignored ((,class :inherit dired-ignored)))
+    `(diff-hl-dired-insert ((,class :inherit diff-hl-insert)))
+    `(diff-hl-dired-unknown ((,class :inherit dired-ignored)))
+    `(diff-hl-insert ((,class :inherit modus-theme-fringe-green)))
+    `(diff-hl-reverted-hunk-highlight ((,class :inherit 
(modus-theme-active-magenta bold))))
+;;;;; diff-mode
+    `(diff-added ((,class :inherit modus-theme-diff-added)))
+    `(diff-changed ((,class :inherit modus-theme-diff-changed :extend t)))
+    `(diff-context ((,class ,@(modus-themes--diff-text fg-main fg-unfocused))))
+    `(diff-error ((,class :inherit modus-theme-intense-red)))
+    `(diff-file-header ((,class :inherit (bold diff-header))))
+    `(diff-function ((,class :inherit modus-theme-diff-heading)))
+    `(diff-header ((,class ,@(modus-themes--diff-text cyan-faint fg-main))))
+    `(diff-hunk-header ((,class :inherit (bold modus-theme-diff-heading))))
+    `(diff-index ((,class :inherit bold :foreground ,blue-alt)))
+    `(diff-indicator-added ((,class :inherit (diff-added bold)
+                                    :foreground ,@(modus-themes--diff-deuteran 
blue green))))
+    `(diff-indicator-changed ((,class :inherit (diff-changed bold) :foreground 
,yellow)))
+    `(diff-indicator-removed ((,class :inherit (diff-removed bold) :foreground 
,red)))
+    `(diff-nonexistent ((,class :inherit (modus-theme-neutral bold))))
+    `(diff-refine-added ((,class :inherit modus-theme-diff-refine-added)))
+    `(diff-refine-changed ((,class :inherit modus-theme-diff-refine-changed)))
+    `(diff-refine-removed ((,class :inherit modus-theme-diff-refine-removed)))
+    `(diff-removed ((,class :inherit modus-theme-diff-removed)))
+;;;;; dim-autoload
+    `(dim-autoload-cookie-line ((,class :inherit font-lock-comment-face)))
+;;;;; dir-treeview
+    `(dir-treeview-archive-face ((,class :foreground ,fg-special-warm)))
+    `(dir-treeview-archive-icon-face ((,class :inherit 
dir-treeview-default-icon-face :foreground ,yellow)))
+    `(dir-treeview-audio-face ((,class :foreground ,magenta)))
+    `(dir-treeview-audio-icon-face ((,class :inherit 
dir-treeview-default-icon-face :foreground ,magenta-alt)))
+    `(dir-treeview-control-face ((,class :inherit shadow)))
+    `(dir-treeview-control-mouse-face ((,class :inherit highlight)))
+    `(dir-treeview-default-icon-face ((,class :inherit bold :family "Font 
Awesome" :foreground ,fg-alt)))
+    `(dir-treeview-default-filename-face ((,class :foreground ,fg-main)))
+    `(dir-treeview-directory-face ((,class :foreground ,blue)))
+    `(dir-treeview-directory-icon-face ((,class :inherit 
dir-treeview-default-icon-face :foreground ,blue-alt)))
+    `(dir-treeview-executable-face ((,class :foreground ,red-alt)))
+    `(dir-treeview-executable-icon-face ((,class :inherit 
dir-treeview-default-icon-face :foreground ,red-alt-other)))
+    `(dir-treeview-image-face ((,class :foreground ,green-alt-other)))
+    `(dir-treeview-image-icon-face ((,class :inherit 
dir-treeview-default-icon-face :foreground ,green-alt)))
+    `(dir-treeview-indent-face ((,class :inherit shadow)))
+    `(dir-treeview-label-mouse-face ((,class :inherit highlight)))
+    `(dir-treeview-start-dir-face ((,class :inherit 
modus-theme-pseudo-header)))
+    `(dir-treeview-symlink-face ((,class :inherit button
+                                         ,@(modus-themes--link-color
+                                            cyan cyan-faint))))
+    `(dir-treeview-video-face ((,class :foreground ,magenta-alt-other)))
+    `(dir-treeview-video-icon-face ((,class :inherit 
dir-treeview-default-icon-face :foreground ,magenta-alt-other)))
+;;;;; dired
+    `(dired-broken-symlink ((,class :inherit button :foreground ,red)))
+    `(dired-directory ((,class :foreground ,blue)))
+    `(dired-flagged ((,class :inherit modus-theme-mark-del)))
+    `(dired-header ((,class :inherit modus-theme-pseudo-header)))
+    `(dired-ignored ((,class :inherit shadow)))
+    `(dired-mark ((,class :inherit modus-theme-mark-symbol)))
+    `(dired-marked ((,class :inherit modus-theme-mark-sel)))
+    `(dired-perm-write ((,class :foreground ,fg-special-warm)))
+    `(dired-symlink ((,class :inherit button
+                             ,@(modus-themes--link-color
+                                cyan-alt cyan-alt-faint))))
+    `(dired-warning ((,class :inherit bold :foreground ,yellow)))
+;;;;; dired-async
+    `(dired-async-failures ((,class :inherit modus-theme-bold :foreground 
,red-active)))
+    `(dired-async-message ((,class :inherit modus-theme-bold :foreground 
,green-active)))
+    `(dired-async-mode-message ((,class :inherit modus-theme-bold :foreground 
,cyan-active)))
+;;;;; dired-git
+    `(dired-git-branch-else ((,class :inherit bold :foreground ,magenta-alt)))
+    `(dired-git-branch-master ((,class :inherit bold :foreground 
,magenta-alt-other)))
+;;;;; dired-git-info
+    `(dgi-commit-message-face ((,class :foreground ,fg-special-mild)))
+;;;;; dired-narrow
+    `(dired-narrow-blink ((,class :inherit (modus-theme-subtle-cyan bold))))
+;;;;; dired-subtree
+    ;; remove backgrounds from dired-subtree faces, else they break
+    ;; dired-{flagged,marked} and any other face that sets a background
+    ;; such as hl-line.  Also, denoting depth by varying shades of gray
+    ;; is not good for accessibility.
+    `(dired-subtree-depth-1-face (()))
+    `(dired-subtree-depth-2-face (()))
+    `(dired-subtree-depth-3-face (()))
+    `(dired-subtree-depth-4-face (()))
+    `(dired-subtree-depth-5-face (()))
+    `(dired-subtree-depth-6-face (()))
+;;;;; diredc
+    `(diredc-face-chmod-font-lock-dir ((,class :foreground ,blue-alt)))
+    `(diredc-face-chmod-font-lock-exec ((,class :foreground ,magenta)))
+    `(diredc-face-chmod-font-lock-read ((,class :foreground ,fg-main)))
+    `(diredc-face-chmod-font-lock-write ((,class :foreground ,cyan)))
+;;;;; diredfl
+    `(diredfl-autofile-name ((,class :inherit modus-theme-special-cold)))
+    `(diredfl-compressed-file-name ((,class :foreground ,fg-special-warm)))
+    `(diredfl-compressed-file-suffix ((,class :foreground ,red-alt)))
+    `(diredfl-date-time ((,class :foreground ,cyan-alt-other)))
+    `(diredfl-deletion ((,class :inherit modus-theme-mark-del)))
+    `(diredfl-deletion-file-name ((,class :inherit modus-theme-mark-del)))
+    `(diredfl-dir-heading ((,class :inherit modus-theme-pseudo-header)))
+    `(diredfl-dir-name ((,class :inherit dired-directory)))
+    `(diredfl-dir-priv ((,class :foreground ,blue-alt)))
+    `(diredfl-exec-priv ((,class :foreground ,magenta)))
+    `(diredfl-executable-tag ((,class :foreground ,magenta-alt)))
+    `(diredfl-file-name ((,class :foreground ,fg-main)))
+    `(diredfl-file-suffix ((,class :foreground ,cyan)))
+    `(diredfl-flag-mark ((,class :inherit modus-theme-mark-sel)))
+    `(diredfl-flag-mark-line ((,class :inherit modus-theme-mark-sel)))
+    `(diredfl-ignored-file-name ((,class :inherit shadow)))
+    `(diredfl-link-priv ((,class :foreground ,blue-alt-other)))
+    `(diredfl-no-priv ((,class :inherit shadow)))
+    `(diredfl-number ((,class :foreground ,cyan-alt)))
+    `(diredfl-other-priv ((,class :foreground ,yellow)))
+    `(diredfl-rare-priv ((,class :foreground ,red-alt)))
+    `(diredfl-read-priv ((,class :foreground ,fg-main)))
+    `(diredfl-symlink ((,class :inherit dired-symlink)))
+    `(diredfl-tagged-autofile-name ((,class :inherit 
modus-theme-refine-magenta)))
+    `(diredfl-write-priv ((,class :foreground ,cyan)))
+;;;;; dired+
+    `(diredp-autofile-name ((,class :inherit modus-theme-special-cold)))
+    `(diredp-compressed-file-name ((,class :foreground ,fg-special-warm)))
+    `(diredp-compressed-file-suffix ((,class :foreground ,red-alt)))
+    `(diredp-date-time ((,class :foreground ,cyan-alt-other)))
+    `(diredp-deletion ((,class :inherit modus-theme-mark-del)))
+    `(diredp-deletion-file-name ((,class :inherit modus-theme-mark-del)))
+    `(diredp-dir-heading ((,class :inherit modus-theme-pseudo-header)))
+    `(diredp-dir-name ((,class :inherit dired-directory)))
+    `(diredp-dir-priv ((,class :foreground ,blue-alt)))
+    `(diredp-exec-priv ((,class :foreground ,magenta)))
+    `(diredp-executable-tag ((,class :foreground ,magenta-alt)))
+    `(diredp-file-name ((,class :foreground ,fg-main)))
+    `(diredp-file-suffix ((,class :foreground ,cyan)))
+    `(diredp-flag-mark ((,class :inherit modus-theme-mark-sel)))
+    `(diredp-flag-mark-line ((,class :inherit modus-theme-mark-sel)))
+    `(diredp-ignored-file-name ((,class :inherit shadow)))
+    `(diredp-link-priv ((,class :foreground ,blue-alt-other)))
+    `(diredp-mode-line-flagged ((,class :foreground ,red-active)))
+    `(diredp-mode-line-marked ((,class :foreground ,green-active)))
+    `(diredp-no-priv ((,class :inherit shadow)))
+    `(diredp-number ((,class :foreground ,cyan-alt)))
+    `(diredp-omit-file-name ((,class :inherit shadow :strike-through t)))
+    `(diredp-other-priv ((,class :foreground ,yellow)))
+    `(diredp-rare-priv ((,class :foreground ,red-alt)))
+    `(diredp-read-priv ((,class :foreground ,fg-main)))
+    `(diredp-symlink ((,class :inherit dired-symlink)))
+    `(diredp-tagged-autofile-name ((,class :inherit 
modus-theme-refine-magenta)))
+    `(diredp-write-priv ((,class :foreground ,cyan)))
+;;;;; disk-usage
+    `(disk-usage-children ((,class :foreground ,yellow)))
+    `(disk-usage-inaccessible ((,class :inherit bold :foreground ,red)))
+    `(disk-usage-percent ((,class :foreground ,green)))
+    `(disk-usage-size ((,class :foreground ,cyan)))
+    `(disk-usage-symlink ((,class :inherit button)))
+    `(disk-usage-symlink-directory ((,class :inherit bold :foreground 
,blue-alt)))
+;;;;; display-fill-column-indicator-mode
+    `(fill-column-indicator ((,class :foreground ,bg-active)))
+;;;;; doom-modeline
+    `(doom-modeline-bar ((,class :inherit modus-theme-active-blue)))
+    `(doom-modeline-bar-inactive ((,class :background ,fg-inactive :foreground 
,bg-main)))
+    `(doom-modeline-battery-charging ((,class :foreground ,green-active)))
+    `(doom-modeline-battery-critical ((,class :inherit bold :foreground 
,red-active)))
+    `(doom-modeline-battery-error ((,class :inherit bold :box (:line-width -2)
+                                           :foreground ,red-active)))
+    `(doom-modeline-battery-full ((,class :foreground ,blue-active)))
+    `(doom-modeline-battery-normal ((,class :foreground ,fg-active)))
+    `(doom-modeline-battery-warning ((,class :inherit bold :foreground 
,yellow-active)))
+    `(doom-modeline-buffer-file ((,class :inherit bold :foreground 
,fg-active)))
+    `(doom-modeline-buffer-major-mode ((,class :inherit bold :foreground 
,cyan-active)))
+    `(doom-modeline-buffer-minor-mode ((,class :foreground ,fg-inactive)))
+    `(doom-modeline-buffer-modified ((,class :inherit bold :foreground 
,magenta-active)))
+    `(doom-modeline-buffer-path ((,class :inherit bold :foreground 
,fg-active)))
+    `(doom-modeline-debug ((,class :inherit bold :foreground ,yellow-active)))
+    `(doom-modeline-debug-visual ((,class :inherit bold :foreground 
,red-active)))
+    `(doom-modeline-evil-emacs-state ((,class :inherit bold :foreground 
,magenta-active)))
+    `(doom-modeline-evil-insert-state ((,class :inherit bold :foreground 
,green-active)))
+    `(doom-modeline-evil-motion-state ((,class :inherit bold :foreground 
,fg-inactive)))
+    `(doom-modeline-evil-normal-state ((,class :inherit bold :foreground 
,fg-active)))
+    `(doom-modeline-evil-operator-state ((,class :inherit bold :foreground 
,blue-active)))
+    `(doom-modeline-evil-replace-state ((,class :inherit bold :foreground 
,red-active)))
+    `(doom-modeline-evil-visual-state ((,class :inherit bold :foreground 
,cyan-active)))
+    `(doom-modeline-highlight ((,class :inherit bold :foreground 
,blue-active)))
+    `(doom-modeline-host ((,class :inherit italic)))
+    `(doom-modeline-info ((,class :foreground ,green-active)))
+    `(doom-modeline-lsp-error ((,class :inherit bold :foreground ,red-active)))
+    `(doom-modeline-lsp-success ((,class :inherit bold :foreground 
,green-active)))
+    `(doom-modeline-lsp-warning ((,class :inherit bold :foreground 
,yellow-active)))
+    `(doom-modeline-panel ((,class :inherit modus-theme-active-blue)))
+    `(doom-modeline-persp-buffer-not-in-persp ((,class :inherit italic 
:foreground ,yellow-active)))
+    `(doom-modeline-persp-name ((,class :foreground ,fg-active)))
+    `(doom-modeline-project-dir ((,class :inherit bold :foreground 
,blue-active)))
+    `(doom-modeline-project-parent-dir ((,class :foreground ,blue-active)))
+    `(doom-modeline-project-root-dir ((,class :foreground ,fg-active)))
+    `(doom-modeline-unread-number ((,class :inherit italic :foreground 
,fg-active)))
+    `(doom-modeline-urgent ((,class :inherit bold :foreground ,red-active)))
+    `(doom-modeline-warning ((,class :inherit bold :foreground 
,yellow-active)))
+;;;;; dynamic-ruler
+    `(dynamic-ruler-negative-face ((,class :inherit 
modus-theme-intense-neutral)))
+    `(dynamic-ruler-positive-face ((,class :inherit 
modus-theme-intense-yellow)))
+;;;;; easy-jekyll
+    `(easy-jekyll-help-face ((,class :background ,bg-dim :foreground 
,cyan-alt-other)))
+;;;;; easy-kill
+    `(easy-kill-origin ((,class :inherit modus-theme-subtle-red)))
+    `(easy-kill-selection ((,class :inherit modus-theme-subtle-yellow)))
+;;;;; ebdb
+    `(ebdb-address-default ((,class :foreground ,fg-special-calm)))
+    `(ebdb-defunct ((,class :inherit shadow)))
+    `(ebdb-field-hidden ((,class :foreground ,magenta)))
+    `(ebdb-label ((,class :foreground ,cyan-alt-other)))
+    `(ebdb-mail-default ((,class :foreground ,fg-main)))
+    `(ebdb-mail-primary ((,class :foreground ,magenta-alt)))
+    `(ebdb-marked ((,class :background ,cyan-intense-bg)))
+    `(ebdb-organization-name ((,class :foreground ,red-alt-other)))
+    `(ebdb-person-name ((,class :foreground ,magenta-alt-other)))
+    `(ebdb-phone-default ((,class :foreground ,cyan)))
+    `(eieio-custom-slot-tag-face ((,class :foreground ,red-alt)))
+;;;;; ediff
+    ;; NOTE: here we break from the pattern of inheriting from the
+    ;; modus-theme-diff-* faces.
+    `(ediff-current-diff-A ((,class ,@(modus-themes--diff
+                                       bg-dim red
+                                       bg-diff-removed fg-diff-removed
+                                       red-nuanced-bg red-faint))))
+    `(ediff-current-diff-Ancestor ((,class ,@(modus-themes--diff
+                                              bg-dim fg-special-cold
+                                              bg-special-cold fg-special-cold
+                                              blue-nuanced-bg blue))))
+    `(ediff-current-diff-B ((,class ,@(modus-themes--diff
+                                       bg-dim green
+                                       bg-diff-added fg-diff-added
+                                       green-nuanced-bg green-faint
+                                       bg-diff-added-deuteran 
fg-diff-added-deuteran))))
+    `(ediff-current-diff-C ((,class ,@(modus-themes--diff
+                                       bg-dim yellow
+                                       bg-diff-changed fg-diff-changed
+                                       yellow-nuanced-bg yellow-faint))))
+    `(ediff-even-diff-A ((,class :background ,bg-diff-neutral-1 :foreground 
,fg-diff-neutral-1)))
+    `(ediff-even-diff-Ancestor ((,class :background ,bg-diff-neutral-2 
:foreground ,fg-diff-neutral-1)))
+    `(ediff-even-diff-B ((,class :background ,bg-diff-neutral-1 :foreground 
,fg-diff-neutral-1)))
+    `(ediff-even-diff-C ((,class :background ,bg-diff-neutral-2 :foreground 
,fg-diff-neutral-2)))
+    `(ediff-fine-diff-A ((,class :background ,bg-diff-focus-removed 
:foreground ,fg-diff-focus-removed)))
+    `(ediff-fine-diff-Ancestor ((,class :inherit modus-theme-refine-cyan)))
+    `(ediff-fine-diff-B
+      ((,class :background ,@(modus-themes--diff-deuteran 
bg-diff-focus-added-deuteran bg-diff-focus-added)
+               :foreground ,@(modus-themes--diff-deuteran 
fg-diff-focus-added-deuteran fg-diff-focus-added))))
+    `(ediff-fine-diff-C ((,class :background ,bg-diff-focus-changed 
:foreground ,fg-diff-focus-changed)))
+    `(ediff-odd-diff-A ((,class :background ,bg-diff-neutral-2 :foreground 
,fg-diff-neutral-2)))
+    `(ediff-odd-diff-Ancestor ((,class :background ,bg-diff-neutral-0 
:foreground ,fg-diff-neutral-0)))
+    `(ediff-odd-diff-B ((,class :background ,bg-diff-neutral-2 :foreground 
,fg-diff-neutral-2)))
+    `(ediff-odd-diff-C ((,class :background ,bg-diff-neutral-1 :foreground 
,fg-diff-neutral-1)))
+;;;;; eglot
+    `(eglot-mode-line ((,class :inherit modus-theme-bold :foreground 
,magenta-active)))
+;;;;; el-search
+    `(el-search-highlight-in-prompt-face ((,class :inherit bold :foreground 
,magenta-alt)))
+    `(el-search-match ((,class :inherit modus-theme-intense-green)))
+    `(el-search-other-match ((,class :inherit modus-theme-special-mild)))
+    `(el-search-occur-match ((,class :inherit modus-theme-special-calm)))
+;;;;; eldoc
+    ;; NOTE: see https://github.com/purcell/package-lint/issues/187
+    (list 'eldoc-highlight-function-argument `((,class :inherit bold 
:foreground ,blue-alt-other)))
+;;;;; eldoc-box
+    `(eldoc-box-body ((,class :background ,bg-alt :foreground ,fg-main)))
+    `(eldoc-box-border ((,class :background ,fg-alt)))
+;;;;; elfeed
+    `(elfeed-log-date-face ((,class :inherit elfeed-search-date-face)))
+    `(elfeed-log-debug-level-face ((,class :inherit 
elfeed-search-filter-face)))
+    `(elfeed-log-error-level-face ((,class :inherit error)))
+    `(elfeed-log-info-level-face ((,class :inherit success)))
+    `(elfeed-log-warn-level-face ((,class :inherit warning)))
+    `(elfeed-search-date-face ((,class :foreground ,cyan)))
+    `(elfeed-search-feed-face ((,class :foreground ,blue-faint)))
+    `(elfeed-search-filter-face ((,class :inherit bold :foreground 
,magenta-active)))
+    `(elfeed-search-last-update-face ((,class :foreground ,cyan-active)))
+    `(elfeed-search-tag-face ((,class :foreground ,cyan-alt-other)))
+    `(elfeed-search-title-face ((,class :foreground ,fg-dim)))
+    `(elfeed-search-unread-count-face ((,class :foreground ,green-active)))
+    `(elfeed-search-unread-title-face ((,class :inherit bold :foreground 
,fg-main)))
+;;;;; elfeed-score
+    `(elfeed-score-date-face ((,class :foreground ,blue)))
+    `(elfeed-score-debug-level-face ((,class :foreground ,magenta-alt-other)))
+    `(elfeed-score-error-level-face ((,class :foreground ,red)))
+    `(elfeed-score-info-level-face ((,class :foreground ,cyan)))
+    `(elfeed-score-warn-level-face ((,class :foreground ,yellow)))
+;;;;; emms
+    `(emms-playlist-track-face ((,class :foreground ,blue)))
+    `(emms-playlist-selected-face ((,class :inherit bold :foreground 
,magenta)))
+;;;;; enhanced-ruby-mode
+    `(enh-ruby-heredoc-delimiter-face ((,class :foreground ,blue-alt-other)))
+    `(enh-ruby-op-face ((,class :foreground ,fg-main)))
+    `(enh-ruby-regexp-delimiter-face ((,class :foreground ,green)))
+    `(enh-ruby-regexp-face ((,class :foreground ,magenta)))
+    `(enh-ruby-string-delimiter-face ((,class :foreground ,blue-alt)))
+    `(erm-syn-errline ((,class :foreground ,red :underline t)))
+    `(erm-syn-warnline ((,class :foreground ,yellow :underline t)))
+;;;;; epa
+    `(epa-field-body ((,class :foreground ,fg-main)))
+    `(epa-field-name ((,class :inherit bold :foreground ,fg-dim)))
+    `(epa-mark ((,class :inherit bold :foreground ,magenta)))
+    `(epa-string ((,class :foreground ,blue-alt)))
+    `(epa-validity-disabled ((,class :foreground ,red)))
+    `(epa-validity-high ((,class :inherit bold :foreground ,cyan)))
+    `(epa-validity-low ((,class :inherit shadow)))
+    `(epa-validity-medium ((,class :foreground ,green-alt)))
+;;;;; equake
+    `(equake-buffer-face ((,class :background ,bg-main :foreground ,fg-main)))
+    `(equake-shell-type-eshell ((,class :background ,bg-inactive :foreground 
,green-active)))
+    `(equake-shell-type-rash ((,class :background ,bg-inactive :foreground 
,red-active)))
+    `(equake-shell-type-shell ((,class :background ,bg-inactive :foreground 
,cyan-active)))
+    `(equake-shell-type-term ((,class :background ,bg-inactive :foreground 
,yellow-active)))
+    `(equake-shell-type-vterm ((,class :background ,bg-inactive :foreground 
,magenta-active)))
+    `(equake-tab-active ((,class :background ,fg-alt :foreground ,bg-alt)))
+    `(equake-tab-inactive ((,class :foreground ,fg-inactive)))
+;;;;; erc
+    `(erc-action-face ((,class :inherit bold :foreground ,cyan)))
+    `(erc-bold-face ((,class :inherit bold)))
+    `(erc-button ((,class :inherit button)))
+    `(erc-command-indicator-face ((,class :inherit bold :foreground 
,cyan-alt)))
+    `(erc-current-nick-face ((,class :foreground ,magenta-alt-other)))
+    `(erc-dangerous-host-face ((,class :inherit modus-theme-intense-red)))
+    `(erc-direct-msg-face ((,class :foreground ,magenta)))
+    `(erc-error-face ((,class :inherit bold :foreground ,red)))
+    `(erc-fool-face ((,class :foreground ,fg-inactive)))
+    `(erc-header-line ((,class :background ,bg-header :foreground ,fg-header)))
+    `(erc-input-face ((,class :foreground ,fg-special-calm)))
+    `(erc-inverse-face ((,class :inherit erc-default-face :inverse-video t)))
+    `(erc-keyword-face ((,class :inherit bold :foreground ,magenta-alt)))
+    `(erc-my-nick-face ((,class :inherit bold :foreground ,magenta)))
+    `(erc-my-nick-prefix-face ((,class :inherit erc-my-nick-face)))
+    `(erc-nick-default-face ((,class :inherit bold :foreground ,blue)))
+    `(erc-nick-msg-face ((,class :inherit bold :foreground ,green)))
+    `(erc-nick-prefix-face ((,class :inherit erc-nick-default-face)))
+    `(erc-notice-face ((,class :foreground ,fg-unfocused)))
+    `(erc-pal-face ((,class :inherit bold :foreground ,red-alt)))
+    `(erc-prompt-face ((,class :inherit bold :foreground ,cyan-alt-other)))
+    `(erc-timestamp-face ((,class :foreground ,blue-nuanced-fg)))
+    `(erc-underline-face ((,class :underline t)))
+    `(bg:erc-color-face0 ((,class :background "white")))
+    `(bg:erc-color-face1 ((,class :background "black")))
+    `(bg:erc-color-face10 ((,class :background ,cyan-subtle-bg)))
+    `(bg:erc-color-face11 ((,class :background ,cyan-intense-bg)))
+    `(bg:erc-color-face12 ((,class :background ,blue-subtle-bg)))
+    `(bg:erc-color-face13 ((,class :background ,magenta-subtle-bg)))
+    `(bg:erc-color-face14 ((,class :background "gray60")))
+    `(bg:erc-color-face15 ((,class :background "gray80")))
+    `(bg:erc-color-face2 ((,class :background ,blue-intense-bg)))
+    `(bg:erc-color-face3 ((,class :background ,green-intense-bg)))
+    `(bg:erc-color-face4 ((,class :background ,red-subtle-bg)))
+    `(bg:erc-color-face5 ((,class :background ,red-intense-bg)))
+    `(bg:erc-color-face6 ((,class :background ,magenta-refine-bg)))
+    `(bg:erc-color-face7 ((,class :background ,yellow-subtle-bg)))
+    `(bg:erc-color-face8 ((,class :background ,yellow-refine-bg)))
+    `(bg:erc-color-face9 ((,class :background ,green-subtle-bg)))
+    `(fg:erc-color-face0 ((,class :foreground "white")))
+    `(fg:erc-color-face1 ((,class :foreground "black")))
+    `(fg:erc-color-face10 ((,class :foreground ,cyan)))
+    `(fg:erc-color-face11 ((,class :foreground ,cyan-alt-other)))
+    `(fg:erc-color-face12 ((,class :foreground ,blue)))
+    `(fg:erc-color-face13 ((,class :foreground ,magenta-alt)))
+    `(fg:erc-color-face14 ((,class :foreground "gray60")))
+    `(fg:erc-color-face15 ((,class :foreground "gray80")))
+    `(fg:erc-color-face2 ((,class :foreground ,blue-alt-other)))
+    `(fg:erc-color-face3 ((,class :foreground ,green)))
+    `(fg:erc-color-face4 ((,class :foreground ,red)))
+    `(fg:erc-color-face5 ((,class :foreground ,red-alt)))
+    `(fg:erc-color-face6 ((,class :foreground ,magenta-alt-other)))
+    `(fg:erc-color-face7 ((,class :foreground ,yellow-alt-other)))
+    `(fg:erc-color-face8 ((,class :foreground ,yellow-alt)))
+    `(fg:erc-color-face9 ((,class :foreground ,green-alt-other)))
+;;;;; eros
+    `(eros-result-overlay-face ((,class :box (:line-width -1 :color ,blue)
+                                        :background ,bg-dim :foreground 
,fg-dim)))
+;;;;; ert
+    `(ert-test-result-expected ((,class :inherit modus-theme-intense-green)))
+    `(ert-test-result-unexpected ((,class :inherit modus-theme-intense-red)))
+;;;;; eshell
+    `(eshell-ls-archive ((,class :inherit bold :foreground ,cyan-alt)))
+    `(eshell-ls-backup ((,class :foreground ,yellow-alt)))
+    `(eshell-ls-clutter ((,class :foreground ,red-alt)))
+    `(eshell-ls-directory ((,class :inherit bold :foreground ,blue-alt)))
+    `(eshell-ls-executable ((,class :foreground ,magenta-alt)))
+    `(eshell-ls-missing ((,class :inherit modus-theme-intense-red)))
+    `(eshell-ls-product ((,class :foreground ,fg-special-warm)))
+    `(eshell-ls-readonly ((,class :foreground ,fg-special-cold)))
+    `(eshell-ls-special ((,class :inherit bold :foreground ,magenta)))
+    `(eshell-ls-symlink ((,class :inherit button
+                                 ,@(modus-themes--link-color
+                                    cyan cyan-faint))))
+    `(eshell-ls-unreadable ((,class :background ,bg-inactive :foreground 
,fg-inactive)))
+    `(eshell-prompt ((,class :inherit modus-theme-bold
+                             ,@(modus-themes--prompt
+                                green-alt-other
+                                green-nuanced-bg green-alt
+                                green-refine-bg fg-main))))
+;;;;; eshell-fringe-status
+    `(eshell-fringe-status-failure ((,class :foreground ,red)))
+    `(eshell-fringe-status-success ((,class :foreground ,green)))
+;;;;; eshell-git-prompt
+    `(eshell-git-prompt-add-face ((,class :inherit shadow)))
+    `(eshell-git-prompt-branch-face ((,class :inherit shadow)))
+    `(eshell-git-prompt-directory-face ((,class :foreground ,cyan)))
+    `(eshell-git-prompt-exit-fail-face ((,class :foreground ,red)))
+    `(eshell-git-prompt-exit-success-face ((,class :foreground ,green)))
+    `(eshell-git-prompt-modified-face ((,class :foreground ,yellow)))
+    `(eshell-git-prompt-powerline-clean-face ((,class :background 
,green-refine-bg)))
+    `(eshell-git-prompt-powerline-dir-face ((,class :background 
,blue-refine-bg)))
+    `(eshell-git-prompt-powerline-not-clean-face ((,class :background 
,magenta-refine-bg)))
+    `(eshell-git-prompt-robyrussell-branch-face ((,class :foreground ,red)))
+    `(eshell-git-prompt-robyrussell-git-dirty-face ((,class :foreground 
,yellow)))
+    `(eshell-git-prompt-robyrussell-git-face ((,class :foreground ,blue)))
+;;;;; eshell-prompt-extras (epe)
+    `(epe-dir-face ((,class :inherit modus-theme-bold :foreground ,blue)))
+    `(epe-git-dir-face ((,class :foreground ,red-alt-other)))
+    `(epe-git-face ((,class :foreground ,cyan-alt)))
+    `(epe-pipeline-delimiter-face ((,class :foreground ,green-alt)))
+    `(epe-pipeline-host-face ((,class :foreground ,blue)))
+    `(epe-pipeline-time-face ((,class :foreground ,fg-special-warm)))
+    `(epe-pipeline-user-face ((,class :foreground ,magenta)))
+    `(epe-remote-face ((,class :inherit modus-theme-slant :foreground 
,fg-alt)))
+    `(epe-status-face ((,class :foreground ,magenta-alt-other)))
+    `(epe-venv-face ((,class :inherit modus-theme-slant :foreground ,fg-alt)))
+;;;;; eshell-syntax-highlighting
+    `(eshell-syntax-highlighting-alias-face ((,class :foreground ,cyan)))
+    `(eshell-syntax-highlighting-comment-face ((,class :inherit shadow)))
+    `(eshell-syntax-highlighting-directory-face ((,class :foreground ,blue)))
+    `(eshell-syntax-highlighting-envvar-face ((,class :foreground 
,magenta-alt)))
+    `(eshell-syntax-highlighting-invalid-face ((,class :foreground ,red)))
+    `(eshell-syntax-highlighting-lisp-function-face ((,class :foreground 
,magenta)))
+    `(eshell-syntax-highlighting-shell-command-face ((,class :foreground 
,cyan-alt-other)))
+    `(eshell-syntax-highlighting-string-face ((,class :foreground ,blue-alt)))
+;;;;; evil-mode
+    `(evil-ex-commands ((,class :foreground ,magenta-alt-other)))
+    `(evil-ex-info ((,class :foreground ,cyan-alt-other)))
+    `(evil-ex-lazy-highlight ((,class :inherit modus-theme-refine-cyan)))
+    `(evil-ex-search ((,class :inherit modus-theme-intense-green)))
+    `(evil-ex-substitute-matches ((,class :inherit modus-theme-refine-yellow 
:underline t)))
+    `(evil-ex-substitute-replacement ((,class :inherit 
(modus-theme-intense-green bold))))
+;;;;; evil-goggles
+    `(evil-goggles-change-face ((,class :inherit modus-theme-refine-yellow)))
+    `(evil-goggles-commentary-face ((,class :inherit 
(modus-theme-subtle-neutral modus-theme-slant))))
+    `(evil-goggles-default-face ((,class :inherit modus-theme-subtle-neutral)))
+    `(evil-goggles-delete-face ((,class :inherit modus-theme-refine-red)))
+    `(evil-goggles-fill-and-move-face ((,class :inherit 
evil-goggles-default-face)))
+    `(evil-goggles-indent-face ((,class :inherit evil-goggles-default-face)))
+    `(evil-goggles-join-face ((,class :inherit modus-theme-subtle-green)))
+    `(evil-goggles-nerd-commenter-face ((,class :inherit 
evil-goggles-commentary-face)))
+    `(evil-goggles-paste-face ((,class :inherit modus-theme-subtle-cyan)))
+    `(evil-goggles-record-macro-face ((,class :inherit 
modus-theme-special-cold)))
+    `(evil-goggles-replace-with-register-face ((,class :inherit 
modus-theme-refine-magenta)))
+    `(evil-goggles-set-marker-face ((,class :inherit 
modus-theme-intense-magenta)))
+    `(evil-goggles-shift-face ((,class :inherit evil-goggles-default-face)))
+    `(evil-goggles-surround-face ((,class :inherit evil-goggles-default-face)))
+    `(evil-goggles-yank-face ((,class :inherit modus-theme-subtle-blue)))
+;;;;; evil-snipe
+    `(evil-snipe-first-match-face ((,class :inherit (bold 
modus-theme-intense-blue))))
+    `(evil-snipe-matches-face ((,class :inherit modus-theme-refine-magenta)))
+;;;;; evil-visual-mark-mode
+    `(evil-visual-mark-face ((,class :inherit modus-theme-intense-magenta)))
+;;;;; eww
+    `(eww-invalid-certificate ((,class :foreground ,red-active)))
+    `(eww-valid-certificate ((,class :foreground ,green-active)))
+    `(eww-form-checkbox ((,class :box (:line-width 1 :color ,fg-inactive 
:style released-button) :background ,bg-inactive :foreground ,fg-main)))
+    `(eww-form-file ((,class :box (:line-width 1 :color ,fg-inactive :style 
released-button) :background ,bg-active :foreground ,fg-main)))
+    `(eww-form-select ((,class :inherit eww-form-checkbox)))
+    `(eww-form-submit ((,class :inherit eww-form-file)))
+    `(eww-form-text ((,class :box (:line-width 1 :color ,fg-inactive :style 
none) :background ,bg-active :foreground ,fg-active)))
+    `(eww-form-textarea ((,class :background ,bg-alt :foreground ,fg-main)))
+;;;;; eyebrowse
+    `(eyebrowse-mode-line-active ((,class :inherit bold :foreground 
,blue-active)))
+;;;;; fancy-dabbrev
+    `(fancy-dabbrev-menu-face ((,class :background ,bg-alt :foreground 
,fg-alt)))
+    `(fancy-dabbrev-preview-face ((,class :inherit shadow :underline t)))
+    `(fancy-dabbrev-selection-face ((,class :inherit (modus-theme-intense-cyan 
bold))))
+;;;;; flycheck
+    `(flycheck-error ((,class :inherit modus-theme-lang-error)))
+    `(flycheck-error-list-checker-name ((,class :foreground ,magenta-active)))
+    `(flycheck-error-list-column-number ((,class :foreground 
,fg-special-cold)))
+    `(flycheck-error-list-error ((,class :inherit modus-theme-bold :foreground 
,red)))
+    `(flycheck-error-list-filename ((,class :foreground ,blue)))
+    `(flycheck-error-list-highlight ((,class :inherit modus-theme-hl-line)))
+    `(flycheck-error-list-id ((,class :foreground ,magenta-alt-other)))
+    `(flycheck-error-list-id-with-explainer ((,class :inherit 
flycheck-error-list-id :box t)))
+    `(flycheck-error-list-info ((,class :foreground ,cyan)))
+    `(flycheck-error-list-line-number ((,class :foreground ,fg-special-warm)))
+    `(flycheck-error-list-warning ((,class :foreground ,yellow)))
+    `(flycheck-fringe-error ((,class :inherit modus-theme-fringe-red)))
+    `(flycheck-fringe-info ((,class :inherit modus-theme-fringe-cyan)))
+    `(flycheck-fringe-warning ((,class :inherit modus-theme-fringe-yellow)))
+    `(flycheck-info ((,class :inherit modus-theme-lang-note)))
+    `(flycheck-verify-select-checker ((,class :box (:line-width 1 :color nil 
:style released-button))))
+    `(flycheck-warning ((,class :inherit modus-theme-lang-warning)))
+;;;;; flycheck-color-mode-line
+    `(flycheck-color-mode-line-error-face ((,class :inherit 
flycheck-fringe-error)))
+    `(flycheck-color-mode-line-info-face ((,class :inherit 
flycheck-fringe-info)))
+    `(flycheck-color-mode-line-running-face ((,class :inherit italic 
:foreground ,fg-inactive)))
+    `(flycheck-color-mode-line-info-face ((,class :inherit 
flycheck-fringe-warning)))
+;;;;; flycheck-indicator
+    `(flycheck-indicator-disabled ((,class :inherit modus-theme-slant 
:foreground ,fg-inactive)))
+    `(flycheck-indicator-error ((,class :inherit modus-theme-bold :foreground 
,red-active)))
+    `(flycheck-indicator-info ((,class :inherit modus-theme-bold :foreground 
,blue-active)))
+    `(flycheck-indicator-running ((,class :inherit modus-theme-bold 
:foreground ,magenta-active)))
+    `(flycheck-indicator-success ((,class :inherit modus-theme-bold 
:foreground ,green-active)))
+    `(flycheck-indicator-warning ((,class :inherit modus-theme-bold 
:foreground ,yellow-active)))
+;;;;; flycheck-posframe
+    `(flycheck-posframe-background-face ((,class :background ,bg-alt)))
+    `(flycheck-posframe-border-face ((,class :inherit shadow)))
+    `(flycheck-posframe-error-face ((,class :inherit bold :foreground ,red)))
+    `(flycheck-posframe-face ((,class :inherit modus-theme-slant :foreground 
,fg-main)))
+    `(flycheck-posframe-info-face ((,class :inherit bold :foreground ,cyan)))
+    `(flycheck-posframe-warning-face ((,class :inherit bold :foreground 
,yellow)))
+;;;;; flymake
+    `(flymake-error ((,class :inherit modus-theme-lang-error)))
+    `(flymake-note ((,class :inherit modus-theme-lang-note)))
+    `(flymake-warning ((,class :inherit modus-theme-lang-warning)))
+;;;;; flyspell
+    `(flyspell-duplicate ((,class :inherit modus-theme-lang-warning)))
+    `(flyspell-incorrect ((,class :inherit modus-theme-lang-error)))
+;;;;; flyspell-correct
+    `(flyspell-correct-highlight-face ((,class :inherit 
modus-theme-refine-green)))
+;;;;; flx
+    `(flx-highlight-face ((,class ,@(modus-themes--extra-completions
+                                     'modus-theme-subtle-magenta
+                                     'modus-theme-intense-magenta
+                                     'modus-theme-nuanced-magenta
+                                     magenta-alt
+                                     'bold))))
+;;;;; freeze-it
+    `(freeze-it-show ((,class :background ,bg-dim :foreground 
,fg-special-warm)))
+;;;;; frog-menu
+    `(frog-menu-action-keybinding-face ((,class :foreground ,blue-alt-other)))
+    `(frog-menu-actions-face ((,class :foreground ,magenta)))
+    `(frog-menu-border ((,class :background ,bg-active)))
+    `(frog-menu-candidates-face ((,class :foreground ,fg-main)))
+    `(frog-menu-posframe-background-face ((,class :background ,bg-dim)))
+    `(frog-menu-prompt-face ((,class :foreground ,cyan)))
+;;;;; focus
+    `(focus-unfocused ((,class :foreground ,fg-unfocused)))
+;;;;; fold-this
+    `(fold-this-overlay ((,class :inherit modus-theme-special-mild)))
+;;;;; font-lock
+    `(font-lock-builtin-face ((,class :inherit modus-theme-bold
+                                      ,@(modus-themes--syntax-extra
+                                         magenta-alt magenta-alt-faint 
blue-alt))))
+    `(font-lock-comment-delimiter-face ((,class :inherit 
font-lock-comment-face)))
+    `(font-lock-comment-face ((,class :inherit modus-theme-slant
+                                      ,@(modus-themes--syntax-comment
+                                         fg-alt fg-comment-yellow))))
+    `(font-lock-constant-face ((,class ,@(modus-themes--syntax-extra
+                                          blue-alt-other blue-alt-other-faint 
magenta-alt-other))))
+    `(font-lock-doc-face ((,class :inherit modus-theme-slant
+                                  ,@(modus-themes--syntax-docstring
+                                     fg-docstring green-alt-other-faint
+                                     green-alt-other-faint 
magenta-nuanced-fg))))
+    `(font-lock-function-name-face ((,class ,@(modus-themes--syntax-extra
+                                               magenta magenta-faint 
magenta-alt))))
+    `(font-lock-keyword-face ((,class :inherit modus-theme-bold
+                                      ,@(modus-themes--syntax-extra
+                                         magenta-alt-other 
magenta-alt-other-faint cyan-alt-other))))
+    `(font-lock-negation-char-face ((,class :inherit modus-theme-bold
+                                            ,@(modus-themes--syntax-foreground
+                                               yellow yellow-faint))))
+    `(font-lock-preprocessor-face ((,class ,@(modus-themes--syntax-foreground
+                                              red-alt-other 
red-alt-other-faint))))
+    `(font-lock-regexp-grouping-backslash ((,class :inherit bold
+                                                   
,@(modus-themes--syntax-string
+                                                      fg-escape-char-backslash 
yellow-alt-faint
+                                                      magenta-alt-other 
blue-alt))))
+    `(font-lock-regexp-grouping-construct ((,class :inherit bold
+                                                   
,@(modus-themes--syntax-string
+                                                      fg-escape-char-construct 
red-alt-other-faint
+                                                      red magenta-alt))))
+    `(font-lock-string-face ((,class ,@(modus-themes--syntax-string
+                                        blue-alt blue-alt-faint green 
green-alt))))
+    `(font-lock-type-face ((,class :inherit modus-theme-bold
+                                   ,@(modus-themes--syntax-extra
+                                      cyan-alt-other cyan-alt-faint 
cyan-alt))))
+    `(font-lock-variable-name-face ((,class ,@(modus-themes--syntax-extra
+                                               cyan cyan-faint 
blue-alt-faint))))
+    `(font-lock-warning-face ((,class :inherit modus-theme-bold
+                                      ,@(modus-themes--syntax-foreground
+                                         yellow-active yellow-alt-faint))))
+;;;;; forge
+    `(forge-post-author ((,class :inherit bold :foreground ,fg-main)))
+    `(forge-post-date ((,class :foreground ,fg-special-cold)))
+    `(forge-topic-closed ((,class :inherit shadow)))
+    `(forge-topic-merged ((,class :inherit shadow)))
+    `(forge-topic-open ((,class :foreground ,fg-special-mild)))
+    `(forge-topic-unmerged ((,class :inherit modus-theme-slant :foreground 
,magenta)))
+    `(forge-topic-unread ((,class :inherit bold :foreground ,fg-main)))
+;;;;; fountain-mode
+    `(fountain-character ((,class :foreground ,blue-alt-other)))
+    `(fountain-comment ((,class :inherit modus-theme-slant :foreground 
,fg-alt)))
+    `(fountain-dialog ((,class :foreground ,blue-alt)))
+    `(fountain-metadata-key ((,class :foreground ,green-alt-other)))
+    `(fountain-metadata-value ((,class :foreground ,blue)))
+    `(fountain-non-printing ((,class :inherit shadow)))
+    `(fountain-note ((,class :inherit modus-theme-slant :foreground ,yellow)))
+    `(fountain-page-break ((,class :inherit bold :foreground ,red-alt)))
+    `(fountain-page-number ((,class :inherit bold :foreground ,red-alt-other)))
+    `(fountain-paren ((,class :foreground ,cyan)))
+    `(fountain-scene-heading ((,class :inherit bold :foreground 
,blue-nuanced-fg)))
+    `(fountain-section-heading ((,class :inherit modus-theme-heading-1)))
+    `(fountain-section-heading-1 ((,class :inherit modus-theme-heading-1)))
+    `(fountain-section-heading-2 ((,class :inherit modus-theme-heading-2)))
+    `(fountain-section-heading-3 ((,class :inherit modus-theme-heading-3)))
+    `(fountain-section-heading-4 ((,class :inherit modus-theme-heading-4)))
+    `(fountain-section-heading-5 ((,class :inherit modus-theme-heading-5)))
+    `(fountain-synopsis ((,class :foreground ,cyan-alt)))
+    `(fountain-trans ((,class :foreground ,yellow-alt-other)))
+;;;;; geiser
+    `(geiser-font-lock-autodoc-current-arg ((,class :inherit 
font-lock-function-name-face)))
+    `(geiser-font-lock-autodoc-identifier ((,class :inherit 
font-lock-constant-face)))
+    `(geiser-font-lock-doc-button ((,class :inherit button :foreground 
,fg-docstring)))
+    `(geiser-font-lock-doc-link ((,class :inherit button)))
+    `(geiser-font-lock-error-link ((,class :inherit button :foreground ,red)))
+    `(geiser-font-lock-image-button ((,class :inherit button :foreground 
,green-alt)))
+    `(geiser-font-lock-repl-input ((,class :inherit bold)))
+    `(geiser-font-lock-repl-output ((,class :inherit font-lock-keyword-face)))
+    `(geiser-font-lock-repl-prompt ((,class :inherit minibuffer-prompt)))
+    `(geiser-font-lock-xref-header ((,class :inherit bold)))
+    `(geiser-font-lock-xref-link ((,class :inherit button)))
+;;;;; git-commit
+    `(git-commit-comment-action ((,class :inherit font-lock-comment-face)))
+    `(git-commit-comment-branch-local ((,class :inherit modus-theme-slant 
:foreground ,blue-alt)))
+    `(git-commit-comment-branch-remote ((,class :inherit modus-theme-slant 
:foreground ,magenta-alt)))
+    `(git-commit-comment-detached ((,class :inherit modus-theme-slant 
:foreground ,cyan-alt)))
+    `(git-commit-comment-file ((,class :inherit modus-theme-slant
+                                       ,@(modus-themes--syntax-comment
+                                          fg-special-cold red-nuanced-fg))))
+    `(git-commit-comment-heading ((,class :inherit (bold modus-theme-slant)
+                                          ,@(modus-themes--syntax-comment
+                                             fg-dim fg-special-warm))))
+    `(git-commit-keyword ((,class :foreground ,magenta)))
+    `(git-commit-known-pseudo-header ((,class :foreground ,cyan-alt-other)))
+    `(git-commit-nonempty-second-line ((,class :inherit 
modus-theme-refine-yellow)))
+    `(git-commit-overlong-summary ((,class :inherit 
modus-theme-refine-yellow)))
+    `(git-commit-pseudo-header ((,class :foreground ,blue)))
+    `(git-commit-summary ((,class :inherit bold :foreground ,cyan)))
+;;;;; git-gutter
+    `(git-gutter:added ((,class :inherit modus-theme-fringe-green)))
+    `(git-gutter:deleted ((,class :inherit modus-theme-fringe-red)))
+    `(git-gutter:modified ((,class :inherit modus-theme-fringe-yellow)))
+    `(git-gutter:separator ((,class :inherit modus-theme-fringe-cyan)))
+    `(git-gutter:unchanged ((,class :inherit modus-theme-fringe-magenta)))
+;;;;; git-gutter-fr
+    `(git-gutter-fr:added ((,class :inherit modus-theme-fringe-green)))
+    `(git-gutter-fr:deleted ((,class :inherit modus-theme-fringe-red)))
+    `(git-gutter-fr:modified ((,class :inherit modus-theme-fringe-yellow)))
+;;;;; git-{gutter,fringe}+
+    `(git-gutter+-added ((,class :inherit modus-theme-fringe-green)))
+    `(git-gutter+-deleted ((,class :inherit modus-theme-fringe-red)))
+    `(git-gutter+-modified ((,class :inherit modus-theme-fringe-yellow)))
+    `(git-gutter+-separator ((,class :inherit modus-theme-fringe-cyan)))
+    `(git-gutter+-unchanged ((,class :inherit modus-theme-fringe-magenta)))
+    `(git-gutter-fr+-added ((,class :inherit modus-theme-fringe-green)))
+    `(git-gutter-fr+-deleted ((,class :inherit modus-theme-fringe-red)))
+    `(git-gutter-fr+-modified ((,class :inherit modus-theme-fringe-yellow)))
+;;;;; git-lens
+    `(git-lens-added ((,class :inherit bold :foreground ,green)))
+    `(git-lens-deleted ((,class :inherit bold :foreground ,red)))
+    `(git-lens-header ((,class :inherit bold :height 1.1 :foreground ,cyan)))
+    `(git-lens-modified ((,class :inherit bold :foreground ,yellow)))
+    `(git-lens-renamed ((,class :inherit bold :foreground ,magenta)))
+;;;;; git-rebase
+    `(git-rebase-comment-hash ((,class :inherit modus-theme-slant
+                                       ,@(modus-themes--syntax-comment
+                                          fg-special-cold red-nuanced-fg))))
+    `(git-rebase-comment-heading  ((,class :inherit (bold modus-theme-slant)
+                                           ,@(modus-themes--syntax-comment
+                                              fg-dim fg-special-warm))))
+    `(git-rebase-description ((,class :foreground ,fg-main)))
+    `(git-rebase-hash ((,class :foreground ,cyan-alt-other)))
+;;;;; git-timemachine
+    `(git-timemachine-commit ((,class :inherit bold :foreground 
,yellow-active)))
+    `(git-timemachine-minibuffer-author-face ((,class :foreground 
,fg-special-warm)))
+    `(git-timemachine-minibuffer-detail-face ((,class :foreground ,red-alt)))
+;;;;; git-walktree
+    `(git-walktree-commit-face ((,class :foreground ,yellow)))
+    `(git-walktree-symlink-face ((,class :inherit button)))
+    `(git-walktree-tree-face ((,class :foreground ,magenta)))
+;;;;; gnus
+    `(gnus-button ((,class :inherit button)))
+    `(gnus-cite-1 ((,class :foreground ,blue-faint)))
+    `(gnus-cite-10 ((,class :foreground ,yellow-alt-other)))
+    `(gnus-cite-11 ((,class :foreground ,magenta-alt)))
+    `(gnus-cite-2 ((,class :foreground ,green-alt-other)))
+    `(gnus-cite-3 ((,class :foreground ,red-alt-other)))
+    `(gnus-cite-4 ((,class :foreground ,cyan)))
+    `(gnus-cite-5 ((,class :foreground ,yellow-alt)))
+    `(gnus-cite-6 ((,class :foreground ,magenta)))
+    `(gnus-cite-7 ((,class :foreground ,green-alt)))
+    `(gnus-cite-8 ((,class :foreground ,magenta-alt-other)))
+    `(gnus-cite-9 ((,class :foreground ,cyan-alt)))
+    `(gnus-cite-attribution ((,class :inherit italic :foreground ,fg-main)))
+    `(gnus-emphasis-bold ((,class :inherit bold)))
+    `(gnus-emphasis-bold-italic ((,class :inherit bold-italic)))
+    `(gnus-emphasis-highlight-words ((,class :inherit 
modus-theme-refine-yellow)))
+    `(gnus-emphasis-italic ((,class :inherit italic)))
+    `(gnus-emphasis-underline-bold ((,class :inherit gnus-emphasis-bold 
:underline t)))
+    `(gnus-emphasis-underline-bold-italic ((,class :inherit 
gnus-emphasis-bold-italic :underline t)))
+    `(gnus-emphasis-underline-italic ((,class :inherit gnus-emphasis-italic 
:underline t)))
+    `(gnus-group-mail-1 ((,class :inherit bold :foreground ,magenta-alt)))
+    `(gnus-group-mail-1-empty ((,class :foreground ,magenta-alt)))
+    `(gnus-group-mail-2 ((,class :inherit bold :foreground ,magenta)))
+    `(gnus-group-mail-2-empty ((,class :foreground ,magenta)))
+    `(gnus-group-mail-3 ((,class :inherit bold :foreground 
,magenta-alt-other)))
+    `(gnus-group-mail-3-empty ((,class :foreground ,magenta-alt-other)))
+    `(gnus-group-mail-low ((,class :inherit bold :foreground 
,magenta-nuanced-fg)))
+    `(gnus-group-mail-low-empty ((,class :foreground ,magenta-nuanced-fg)))
+    `(gnus-group-news-1 ((,class :inherit bold :foreground ,green)))
+    `(gnus-group-news-1-empty ((,class :foreground ,green)))
+    `(gnus-group-news-2 ((,class :inherit bold :foreground ,cyan)))
+    `(gnus-group-news-2-empty ((,class :foreground ,cyan)))
+    `(gnus-group-news-3 ((,class :inherit bold :foreground 
,yellow-nuanced-fg)))
+    `(gnus-group-news-3-empty ((,class :foreground ,yellow-nuanced-fg)))
+    `(gnus-group-news-4 ((,class :inherit bold :foreground ,cyan-nuanced-fg)))
+    `(gnus-group-news-4-empty ((,class :foreground ,cyan-nuanced-fg)))
+    `(gnus-group-news-5 ((,class :inherit bold :foreground ,red-nuanced-fg)))
+    `(gnus-group-news-5-empty ((,class :foreground ,red-nuanced-fg)))
+    `(gnus-group-news-6 ((,class :inherit bold :foreground ,fg-alt)))
+    `(gnus-group-news-6-empty ((,class :inherit shadow)))
+    `(gnus-group-news-low ((,class :inherit bold :foreground 
,green-nuanced-fg)))
+    `(gnus-group-news-low-empty ((,class :foreground ,green-nuanced-fg)))
+    `(gnus-header-content ((,class :inherit message-header-other)))
+    `(gnus-header-from ((,class :inherit message-header-to :underline nil)))
+    `(gnus-header-name ((,class :inherit message-header-name)))
+    `(gnus-header-newsgroups ((,class :inherit message-header-newsgroups)))
+    `(gnus-header-subject ((,class :inherit message-header-subject)))
+    `(gnus-server-agent ((,class :inherit bold :foreground ,cyan)))
+    `(gnus-server-closed ((,class :inherit bold :foreground ,magenta)))
+    `(gnus-server-cloud ((,class :inherit bold :foreground ,cyan-alt)))
+    `(gnus-server-cloud-host ((,class :inherit modus-theme-refine-cyan)))
+    `(gnus-server-denied ((,class :inherit bold :foreground ,red)))
+    `(gnus-server-offline ((,class :inherit bold :foreground ,yellow)))
+    `(gnus-server-opened ((,class :inherit bold :foreground ,green)))
+    `(gnus-signature ((,class :inherit italic :foreground ,fg-special-cold)))
+    `(gnus-splash ((,class :inherit shadow)))
+    `(gnus-summary-cancelled ((,class :inherit modus-theme-mark-alt)))
+    `(gnus-summary-high-ancient ((,class :inherit bold :foreground ,fg-alt)))
+    `(gnus-summary-high-read ((,class :inherit bold :foreground 
,fg-special-cold)))
+    `(gnus-summary-high-ticked ((,class :inherit bold :foreground 
,red-alt-other)))
+    `(gnus-summary-high-undownloaded ((,class :inherit bold :foreground 
,yellow)))
+    `(gnus-summary-high-unread ((,class :inherit bold :foreground ,fg-main)))
+    `(gnus-summary-low-ancient ((,class :inherit italic :foreground ,fg-alt)))
+    `(gnus-summary-low-read ((,class :inherit italic :foreground ,fg-alt)))
+    `(gnus-summary-low-ticked ((,class :inherit italic :foreground 
,red-refine-fg)))
+    `(gnus-summary-low-undownloaded ((,class :inherit italic :foreground 
,yellow-refine-fg)))
+    `(gnus-summary-low-unread ((,class :inherit bold :foreground 
,fg-special-cold)))
+    `(gnus-summary-normal-ancient ((,class :foreground ,fg-special-calm)))
+    `(gnus-summary-normal-read ((,class :inherit shadow)))
+    `(gnus-summary-normal-ticked ((,class :foreground ,red-alt-other)))
+    `(gnus-summary-normal-undownloaded ((,class :foreground ,yellow)))
+    `(gnus-summary-normal-unread ((,class :foreground ,fg-main)))
+    `(gnus-summary-selected ((,class :inherit modus-theme-subtle-blue)))
+;;;;; golden-ratio-scroll-screen
+    `(golden-ratio-scroll-highlight-line-face ((,class :background 
,cyan-subtle-bg :foreground ,fg-main)))
+;;;;; helm
+    `(helm-M-x-key ((,class :inherit bold :foreground ,magenta-alt-other)))
+    `(helm-action ((,class :underline t)))
+    `(helm-bookmark-addressbook ((,class :foreground ,green-alt)))
+    `(helm-bookmark-directory ((,class :inherit bold :foreground ,blue)))
+    `(helm-bookmark-file ((,class :foreground ,fg-main)))
+    `(helm-bookmark-file-not-found ((,class :background ,bg-alt :foreground 
,fg-alt)))
+    `(helm-bookmark-gnus ((,class :foreground ,magenta)))
+    `(helm-bookmark-info ((,class :foreground ,cyan-alt)))
+    `(helm-bookmark-man ((,class :foreground ,yellow-alt)))
+    `(helm-bookmark-w3m ((,class :foreground ,blue-alt)))
+    `(helm-buffer-archive ((,class :inherit bold :foreground ,cyan)))
+    `(helm-buffer-directory ((,class :inherit bold :foreground ,blue)))
+    `(helm-buffer-file ((,class :foreground ,fg-main)))
+    `(helm-buffer-modified ((,class :foreground ,yellow-alt)))
+    `(helm-buffer-not-saved ((,class :foreground ,red-alt)))
+    `(helm-buffer-process ((,class :foreground ,magenta)))
+    `(helm-buffer-saved-out ((,class :inherit bold :background ,bg-alt 
:foreground ,red)))
+    `(helm-buffer-size ((,class :inherit shadow)))
+    `(helm-candidate-number ((,class :foreground ,cyan-active)))
+    `(helm-candidate-number-suspended ((,class :foreground ,yellow-active)))
+    `(helm-comint-prompts-buffer-name ((,class :foreground ,green-active)))
+    `(helm-comint-prompts-promptidx ((,class :foreground ,cyan-active)))
+    `(helm-delete-async-message ((,class :inherit bold :foreground 
,magenta-active)))
+    `(helm-eob-line ((,class :background ,bg-main :foreground ,fg-main)))
+    `(helm-eshell-prompts-buffer-name ((,class :foreground ,green-active)))
+    `(helm-eshell-prompts-promptidx ((,class :foreground ,cyan-active)))
+    `(helm-etags-file ((,class :foreground ,fg-dim :underline t)))
+    `(helm-ff-backup-file ((,class :inherit shadow)))
+    `(helm-ff-denied ((,class ,@(modus-themes--extra-completions
+                                 'modus-theme-subtle-red
+                                 'modus-theme-intense-red
+                                 'modus-theme-nuanced-red
+                                 red))))
+    `(helm-ff-directory ((,class :inherit helm-buffer-directory)))
+    `(helm-ff-dirs ((,class :inherit bold :foreground ,blue-alt-other)))
+    `(helm-ff-dotted-directory ((,class :inherit bold :background ,bg-alt 
:foreground ,fg-alt)))
+    `(helm-ff-dotted-symlink-directory ((,class :inherit (button 
helm-ff-dotted-directory))))
+    `(helm-ff-executable ((,class :foreground ,magenta-alt)))
+    `(helm-ff-file ((,class :foreground ,fg-main)))
+    `(helm-ff-file-extension ((,class :foreground ,fg-special-warm)))
+    `(helm-ff-invalid-symlink ((,class :inherit button
+                                       ,@(modus-themes--link-color
+                                          red red-faint))))
+    `(helm-ff-pipe ((,class ,@(modus-themes--extra-completions
+                               'modus-theme-refine-magenta
+                               'modus-theme-subtle-magenta
+                               'modus-theme-nuanced-magenta
+                               magenta))))
+    `(helm-ff-prefix ((,class ,@(modus-themes--extra-completions
+                                 'modus-theme-refine-yellow
+                                 'modus-theme-subtle-yellow
+                                 'modus-theme-nuanced-yellow
+                                 yellow-alt-other))))
+    `(helm-ff-socket ((,class :foreground ,red-alt-other)))
+    `(helm-ff-suid ((,class ,@(modus-themes--extra-completions
+                               'modus-theme-subtle-red
+                               'modus-theme-refine-red
+                               'modus-theme-nuanced-yellow
+                               red-alt))))
+    `(helm-ff-symlink ((,class :inherit button
+                               ,@(modus-themes--link-color
+                                  cyan cyan-faint))))
+    `(helm-ff-truename ((,class :foreground ,blue-alt-other)))
+    `(helm-fd-finish ((,class :foreground ,green-active)))
+    `(helm-grep-cmd-line ((,class :foreground ,yellow-alt-other)))
+    `(helm-grep-file ((,class :inherit bold :foreground ,fg-special-cold)))
+    `(helm-grep-finish ((,class :foreground ,green-active)))
+    `(helm-grep-lineno ((,class :foreground ,fg-special-warm)))
+    `(helm-grep-match ((,class :inherit modus-theme-special-calm)))
+    `(helm-header ((,class :inherit bold :foreground ,fg-special-cold)))
+    `(helm-header-line-left-margin ((,class :inherit bold :foreground 
,yellow-intense)))
+    `(helm-history-deleted ((,class ,@(modus-themes--extra-completions
+                                       'modus-theme-subtle-red
+                                       'modus-theme-intense-red
+                                       'modus-theme-nuanced-red
+                                       red
+                                       'bold))))
+    `(helm-history-remote ((,class :foreground ,red-alt-other)))
+    `(helm-lisp-completion-info ((,class :foreground ,fg-special-warm)))
+    `(helm-lisp-show-completion ((,class ,@(modus-themes--extra-completions
+                                            'modus-theme-subtle-yellow
+                                            'modus-theme-refine-yellow
+                                            'modus-theme-nuanced-yellow
+                                            yellow
+                                            'bold))))
+    `(helm-locate-finish ((,class :foreground ,green-active)))
+    `(helm-match ((,class ,@(modus-themes--extra-completions
+                             'modus-theme-subtle-cyan
+                             'modus-theme-refine-cyan
+                             'modus-theme-nuanced-cyan
+                             cyan
+                             'bold))))
+    `(helm-match-item ((,class ,@(modus-themes--extra-completions
+                                  'modus-theme-subtle-neutral
+                                  'modus-theme-subtle-cyan
+                                  'modus-theme-nuanced-cyan
+                                  cyan-alt-other))))
+    `(helm-minibuffer-prompt ((,class :inherit minibuffer-prompt)))
+    `(helm-moccur-buffer ((,class :inherit button
+                                  ,@(modus-themes--link-color
+                                     cyan-alt-other cyan-alt-other-faint))))
+    `(helm-mode-prefix ((,class ,@(modus-themes--extra-completions
+                                   'modus-theme-subtle-magenta
+                                   'modus-theme-intense-magenta
+                                   'modus-theme-nuanced-magenta
+                                   magenta-alt
+                                   'bold))))
+    `(helm-non-file-buffer ((,class :inherit shadow)))
+    `(helm-prefarg ((,class :foreground ,red-active)))
+    `(helm-resume-need-update ((,class ,@(modus-themes--extra-completions
+                                          'modus-theme-subtle-magenta
+                                          'modus-theme-refine-magenta
+                                          'modus-theme-nuanced-magenta
+                                          magenta-alt-other))))
+    `(helm-selection ((,class ,@(modus-themes--extra-completions
+                                 'modus-theme-subtle-blue
+                                 'modus-theme-refine-blue
+                                 'modus-theme-special-cold
+                                 nil
+                                 'bold))))
+    `(helm-selection-line ((,class :inherit modus-theme-special-cold)))
+    `(helm-separator ((,class :foreground ,fg-special-mild)))
+    `(helm-time-zone-current ((,class :foreground ,green)))
+    `(helm-time-zone-home ((,class :foreground ,magenta)))
+    `(helm-source-header ((,class :inherit bold :foreground ,red-alt
+                                  ,@(modus-themes--scale 
modus-themes-scale-4))))
+    `(helm-top-columns ((,class :inherit helm-header)))
+    `(helm-ucs-char ((,class :foreground ,yellow-alt-other)))
+    `(helm-visible-mark ((,class :inherit modus-theme-subtle-cyan)))
+;;;;; helm-ls-git
+    `(helm-ls-git-added-copied-face ((,class :foreground ,green-intense)))
+    `(helm-ls-git-added-modified-face ((,class :foreground ,yellow-intense)))
+    `(helm-ls-git-conflict-face ((,class :inherit bold :foreground 
,red-intense)))
+    `(helm-ls-git-deleted-and-staged-face ((,class :foreground 
,red-nuanced-fg)))
+    `(helm-ls-git-deleted-not-staged-face ((,class :foreground ,red)))
+    `(helm-ls-git-modified-and-staged-face ((,class :foreground 
,yellow-nuanced-fg)))
+    `(helm-ls-git-modified-not-staged-face ((,class :foreground ,yellow)))
+    `(helm-ls-git-renamed-modified-face ((,class :foreground ,magenta)))
+    `(helm-ls-git-untracked-face ((,class :foreground ,fg-special-cold)))
+;;;;; helm-switch-shell
+    `(helm-switch-shell-new-shell-face ((,class 
,@(modus-themes--extra-completions
+                                                   'modus-theme-subtle-magenta
+                                                   'modus-theme-refine-magenta
+                                                   'modus-theme-nuanced-magenta
+                                                   magenta-alt-other
+                                                   'bold))))
+;;;;; helm-xref
+    `(helm-xref-file-name ((,class :inherit bold :foreground 
,fg-special-cold)))
+    `(helm-xref-file-name ((,class :foreground ,fg-special-warm)))
+;;;;; helpful
+    `(helpful-heading ((,class :inherit modus-theme-heading-1)))
+;;;;; highlight region or ad-hoc regexp
+    `(hi-aquamarine ((,class :background ,cyan-subtle-bg :foreground 
,fg-main)))
+    `(hi-black-b ((,class :inherit bold :background ,fg-main :foreground 
,bg-main)))
+    `(hi-black-hb ((,class :inherit bold :background ,fg-alt :foreground 
,bg-main)))
+    `(hi-blue ((,class :background ,blue-subtle-bg :foreground ,fg-main)))
+    `(hi-blue-b ((,class :inherit (bold hi-blue))))
+    `(hi-green ((,class :background ,green-subtle-bg :foreground ,fg-main)))
+    `(hi-green-b ((,class :inherit (bold hi-green))))
+    `(hi-pink ((,class :background ,magenta-subtle-bg :foreground ,fg-main)))
+    `(hi-pink-b ((,class :inherit (bold hi-pink))))
+    `(hi-red-b ((,class :inherit bold :background ,red-intense-bg :foreground 
,fg-main)))
+    `(hi-salmon ((,class :background ,red-subtle-bg :foreground ,fg-main)))
+    `(hi-yellow ((,class :background ,yellow-subtle-bg :foreground ,fg-main)))
+    `(highlight ((,class :inherit modus-theme-subtle-blue)))
+    `(highlight-changes ((,class :foreground ,yellow-alt-other)))
+    `(highlight-changes-delete ((,class :foreground ,red-alt-other :underline 
t)))
+    `(hl-line ((,class :inherit modus-theme-hl-line)))
+;;;;; highlight-blocks
+    `(highlight-blocks-depth-1-face ((,class :background ,bg-dim :foreground 
,fg-main)))
+    `(highlight-blocks-depth-2-face ((,class :background ,bg-alt :foreground 
,fg-main)))
+    `(highlight-blocks-depth-3-face ((,class :background ,bg-special-cold 
:foreground ,fg-main)))
+    `(highlight-blocks-depth-4-face ((,class :background ,bg-special-calm 
:foreground ,fg-main)))
+    `(highlight-blocks-depth-5-face ((,class :background ,bg-special-warm 
:foreground ,fg-main)))
+    `(highlight-blocks-depth-6-face ((,class :background ,bg-special-mild 
:foreground ,fg-main)))
+    `(highlight-blocks-depth-7-face ((,class :background ,bg-inactive 
:foreground ,fg-main)))
+    `(highlight-blocks-depth-8-face ((,class :background ,bg-active 
:foreground ,fg-main)))
+    `(highlight-blocks-depth-9-face ((,class :background ,cyan-subtle-bg 
:foreground ,fg-main)))
+;;;;; highlight-defined
+    `(highlight-defined-builtin-function-name-face ((,class :foreground 
,magenta)))
+    `(highlight-defined-face-name-face ((,class :foreground ,fg-main)))
+    `(highlight-defined-function-name-face ((,class :foreground ,magenta)))
+    `(highlight-defined-macro-name-face ((,class :foreground ,magenta-alt)))
+    `(highlight-defined-special-form-name-face ((,class :foreground 
,magenta-alt-other)))
+    `(highlight-defined-variable-name-face ((,class :foreground ,cyan)))
+;;;;; highlight-escape-sequences (`hes-mode')
+    `(hes-escape-backslash-face ((,class :inherit bold :foreground 
,fg-escape-char-construct)))
+    `(hes-escape-sequence-face ((,class :inherit bold :foreground 
,fg-escape-char-backslash)))
+;;;;; highlight-indentation
+    `(highlight-indentation-face ((,class :inherit modus-theme-hl-line)))
+    `(highlight-indentation-current-column-face ((,class :background 
,bg-active)))
+;;;;; highlight-numbers
+    `(highlight-numbers-number ((,class :foreground ,blue-alt-other)))
+;;;;; highlight-symbol
+    `(highlight-symbol-face ((,class :inherit modus-theme-special-mild)))
+;;;;; highlight-thing
+    `(highlight-thing ((,class :background ,bg-alt :foreground ,cyan)))
+;;;;; hl-defined
+    `(hdefd-functions ((,class :foreground ,blue)))
+    `(hdefd-undefined ((,class :foreground ,red-alt)))
+    `(hdefd-variables ((,class :foreground ,cyan-alt)))
+;;;;; hl-fill-column
+    `(hl-fill-column-face ((,class :background ,bg-active :foreground 
,fg-active)))
+;;;;; hl-todo
+    `(hl-todo ((,class :inherit (bold modus-theme-slant) :foreground 
,red-alt-other)))
+;;;;; hydra
+    `(hydra-face-amaranth ((,class :inherit bold :foreground ,yellow)))
+    `(hydra-face-blue ((,class :inherit bold :foreground ,blue-alt)))
+    `(hydra-face-pink ((,class :inherit bold :foreground ,magenta-alt)))
+    `(hydra-face-red ((,class :inherit bold :foreground ,red)))
+    `(hydra-face-teal ((,class :inherit bold :foreground ,cyan)))
+;;;;; hyperlist
+    `(hyperlist-condition ((,class :foreground ,green)))
+    `(hyperlist-hashtag ((,class :foreground ,yellow)))
+    `(hyperlist-operator ((,class :foreground ,blue-alt)))
+    `(hyperlist-paren ((,class :foreground ,cyan-alt-other)))
+    `(hyperlist-quote ((,class :foreground ,cyan-alt)))
+    `(hyperlist-ref ((,class :foreground ,magenta-alt-other)))
+    `(hyperlist-stars ((,class :inherit shadow)))
+    `(hyperlist-tag ((,class :foreground ,red)))
+    `(hyperlist-toplevel ((,class :inherit bold :foreground ,fg-main)))
+;;;;; icomplete
+    `(icomplete-first-match ((,class :inherit bold
+                                     ,@(modus-themes--standard-completions
+                                        magenta bg-alt
+                                        bg-active fg-main))))
+;;;;; icomplete-vertical
+    `(icomplete-vertical-separator ((,class :inherit shadow)))
+;;;;; ido-mode
+    `(ido-first-match ((,class :inherit bold
+                               ,@(modus-themes--standard-completions
+                                  magenta bg-alt
+                                  bg-active fg-main))))
+    `(ido-incomplete-regexp ((,class :inherit error)))
+    `(ido-indicator ((,class :inherit modus-theme-subtle-yellow)))
+    `(ido-only-match ((,class :inherit bold
+                              ,@(modus-themes--standard-completions
+                                 green green-nuanced-bg
+                                 green-intense-bg fg-main))))
+    `(ido-subdir ((,class :foreground ,blue)))
+    `(ido-virtual ((,class :foreground ,fg-special-warm)))
+;;;;; iedit
+    `(iedit-occurrence ((,class :inherit modus-theme-refine-blue)))
+    `(iedit-read-only-occurrence ((,class :inherit 
modus-theme-intense-yellow)))
+;;;;; iflipb
+    `(iflipb-current-buffer-face ((,class :inherit bold :foreground 
,cyan-alt)))
+    `(iflipb-other-buffer-face ((,class :inherit shadow)))
+;;;;; imenu-list
+    `(imenu-list-entry-face-0 ((,class :foreground ,cyan)))
+    `(imenu-list-entry-face-1 ((,class :foreground ,blue)))
+    `(imenu-list-entry-face-2 ((,class :foreground ,cyan-alt-other)))
+    `(imenu-list-entry-face-3 ((,class :foreground ,blue-alt)))
+    `(imenu-list-entry-subalist-face-0 ((,class :inherit bold :foreground 
,magenta-alt-other :underline t)))
+    `(imenu-list-entry-subalist-face-1 ((,class :inherit bold :foreground 
,magenta :underline t)))
+    `(imenu-list-entry-subalist-face-2 ((,class :inherit bold :foreground 
,green-alt-other :underline t)))
+    `(imenu-list-entry-subalist-face-3 ((,class :inherit bold :foreground 
,red-alt-other :underline t)))
+;;;;; indium
+    `(indium-breakpoint-face ((,class :foreground ,red-active)))
+    `(indium-frame-url-face ((,class :inherit button :foreground ,fg-alt)))
+    `(indium-keyword-face ((,class :foreground ,magenta-alt-other)))
+    `(indium-litable-face ((,class :inherit modus-theme-slant :foreground 
,fg-special-warm)))
+    `(indium-repl-error-face ((,class :inherit bold :foreground ,red)))
+    `(indium-repl-prompt-face ((,class :foreground ,cyan-alt-other)))
+    `(indium-repl-stdout-face ((,class :foreground ,fg-main)))
+;;;;; info
+    `(Info-quoted ((,class ,@(modus-themes--mixed-fonts) ; the capitalization 
is canonical
+                           :background ,bg-alt :foreground ,fg-special-calm)))
+    `(info-header-node ((,class :inherit bold :foreground ,fg-alt)))
+    `(info-header-xref ((,class :foreground ,blue-active)))
+    `(info-index-match ((,class :inherit match)))
+    `(info-menu-header ((,class :inherit modus-theme-heading-3)))
+    `(info-menu-star ((,class :foreground ,red)))
+    `(info-node ((,class :inherit bold)))
+    `(info-title-1 ((,class :inherit modus-theme-heading-1)))
+    `(info-title-2 ((,class :inherit modus-theme-heading-2)))
+    `(info-title-3 ((,class :inherit modus-theme-heading-3)))
+    `(info-title-4 ((,class :inherit modus-theme-heading-4)))
+;;;;; info-colors
+    `(info-colors-lisp-code-block ((,class :inherit fixed-pitch)))
+    `(info-colors-ref-item-command ((,class :foreground ,magenta)))
+    `(info-colors-ref-item-constant ((,class :inherit 
font-lock-constant-face)))
+    `(info-colors-ref-item-function ((,class :inherit 
font-lock-function-name-face)))
+    `(info-colors-ref-item-macro ((,class :inherit font-lock-keyword-face)))
+    `(info-colors-ref-item-other ((,class :inherit font-lock-doc-face)))
+    `(info-colors-ref-item-special-form ((,class :inherit 
font-lock-keyword-face)))
+    `(info-colors-ref-item-syntax-class ((,class :inherit 
font-lock-builtin-face)))
+    `(info-colors-ref-item-type ((,class :inherit font-lock-type-face)))
+    `(info-colors-ref-item-user-option ((,class :inherit 
font-lock-variable-name-face)))
+    `(info-colors-ref-item-variable ((,class :inherit 
font-lock-variable-name-face)))
+;;;;; interaction-log
+    `(ilog-buffer-face ((,class :foreground ,magenta-alt-other)))
+    `(ilog-change-face ((,class :foreground ,magenta-alt)))
+    `(ilog-echo-face ((,class :foreground ,yellow-alt-other)))
+    `(ilog-load-face ((,class :foreground ,green)))
+    `(ilog-message-face ((,class :inherit shadow)))
+    `(ilog-non-change-face ((,class :foreground ,blue)))
+;;;;; ioccur
+    `(ioccur-cursor ((,class :foreground ,fg-main)))
+    `(ioccur-invalid-regexp ((,class :foreground ,red)))
+    `(ioccur-match-face ((,class :inherit modus-theme-special-calm)))
+    `(ioccur-match-overlay-face ((,class :inherit modus-theme-special-cold 
:extend t)))
+    `(ioccur-num-line-face ((,class :foreground ,fg-special-warm)))
+    `(ioccur-overlay-face ((,class :inherit modus-theme-refine-blue :extend 
t)))
+    `(ioccur-regexp-face ((,class :inherit (modus-theme-intense-magenta 
bold))))
+    `(ioccur-title-face ((,class :inherit bold :foreground ,red-alt
+                                 ,@(modus-themes--scale 
modus-themes-scale-4))))
+;;;;; isearch, occur, and the like
+    `(isearch ((,class :inherit (modus-theme-intense-green bold))))
+    `(isearch-fail ((,class :inherit modus-theme-refine-red)))
+    `(isearch-group-1 ((,class :inherit modus-theme-intense-blue)))
+    `(isearch-group-2 ((,class :inherit modus-theme-intense-magenta)))
+    `(lazy-highlight ((,class :inherit modus-theme-refine-cyan)))
+    `(match ((,class :inherit modus-theme-special-calm)))
+    `(query-replace ((,class :inherit (modus-theme-intense-yellow bold))))
+;;;;; isl (isearch-light)
+    `(isl-line ((,class :inherit modus-theme-subtle-green)))
+    `(isl-match ((,class :inherit modus-theme-refine-cyan)))
+    `(isl-number ((,class :inherit modus-theme-bold :foreground 
,green-active)))
+    `(isl-on ((,class :inherit (bold modus-theme-intense-green))))
+    `(isl-string ((,class :inherit modus-theme-bold :foreground ,cyan-active)))
+;;;;; ivy
+    `(ivy-action ((,class :inherit bold :foreground ,red-alt)))
+    `(ivy-completions-annotations ((,class :inherit completions-annotations)))
+    `(ivy-confirm-face ((,class :foreground ,cyan)))
+    `(ivy-current-match ((,class ,@(modus-themes--extra-completions
+                                    'modus-theme-refine-cyan
+                                    'modus-theme-intense-cyan
+                                    'modus-theme-special-cold
+                                    nil
+                                    'bold))))
+    `(ivy-cursor ((,class :background ,fg-main :foreground ,bg-main)))
+    `(ivy-grep-info ((,class :foreground ,cyan-alt)))
+    `(ivy-grep-line-number ((,class :foreground ,fg-special-warm)))
+    `(ivy-highlight-face ((,class :foreground ,magenta)))
+    `(ivy-match-required-face ((,class :inherit error)))
+    `(ivy-minibuffer-match-face-1 ((,class ,@(modus-themes--extra-completions
+                                              'modus-theme-subtle-neutral
+                                              'modus-theme-intense-neutral
+                                              'modus-theme-nuanced-cyan
+                                              fg-alt))))
+    `(ivy-minibuffer-match-face-2 ((,class ,@(modus-themes--extra-completions
+                                              'modus-theme-subtle-green
+                                              'modus-theme-refine-green
+                                              'modus-theme-nuanced-green
+                                              green-alt-other
+                                              'bold))))
+    `(ivy-minibuffer-match-face-3 ((,class ,@(modus-themes--extra-completions
+                                              'modus-theme-subtle-blue
+                                              'modus-theme-refine-blue
+                                              'modus-theme-nuanced-blue
+                                              blue-alt-other
+                                              'bold))))
+    `(ivy-minibuffer-match-face-4 ((,class ,@(modus-themes--extra-completions
+                                              'modus-theme-subtle-magenta
+                                              'modus-theme-refine-magenta
+                                              'modus-theme-nuanced-magenta
+                                              magenta-alt-other
+                                              'bold))))
+    `(ivy-minibuffer-match-highlight ((,class 
,@(modus-themes--extra-completions
+                                                 'modus-theme-subtle-cyan
+                                                 'modus-theme-intense-cyan
+                                                 'modus-theme-nuanced-cyan
+                                                 cyan-alt-other
+                                                 'bold))))
+    `(ivy-modified-buffer ((,class :inherit modus-theme-slant :foreground 
,yellow)))
+    `(ivy-modified-outside-buffer ((,class :inherit modus-theme-slant 
:foreground ,yellow-alt)))
+    `(ivy-org ((,class :foreground ,cyan-alt-other)))
+    `(ivy-prompt-match ((,class :inherit ivy-current-match)))
+    `(ivy-remote ((,class :foreground ,magenta)))
+    `(ivy-separator ((,class :inherit shadow)))
+    `(ivy-subdir ((,class :foreground ,blue-alt-other)))
+    `(ivy-virtual ((,class :foreground ,magenta-alt-other)))
+    `(ivy-yanked-word ((,class ,@(modus-themes--extra-completions
+                                  'modus-theme-subtle-blue
+                                  'modus-theme-refine-blue
+                                  'modus-theme-nuanced-blue
+                                  blue-alt))))
+;;;;; ivy-posframe
+    `(ivy-posframe ((,class :background ,bg-dim :foreground ,fg-main)))
+    `(ivy-posframe-border ((,class :background ,fg-window-divider-inner)))
+    `(ivy-posframe-cursor ((,class :background ,fg-main :foreground ,bg-main)))
+;;;;; jira (org-jira)
+    `(jiralib-comment-face ((,class :background ,bg-alt)))
+    `(jiralib-comment-header-face ((,class :inherit bold)))
+    `(jiralib-issue-info-face ((,class :inherit modus-theme-special-warm)))
+    `(jiralib-issue-info-header-face ((,class :inherit 
(modus-theme-special-warm bold))))
+    `(jiralib-issue-summary-face ((,class :inherit bold)))
+    `(jiralib-link-filter-face ((,class :underline t)))
+    `(jiralib-link-issue-face ((,class :underline t)))
+    `(jiralib-link-project-face ((,class :underline t)))
+;;;;; journalctl-mode
+    `(journalctl-error-face ((,class :inherit bold :foreground ,red)))
+    `(journalctl-finished-face ((,class :inherit bold :foreground ,green)))
+    `(journalctl-host-face ((,class :foreground ,blue)))
+    `(journalctl-process-face ((,class :foreground ,cyan-alt-other)))
+    `(journalctl-starting-face ((,class :foreground ,green)))
+    `(journalctl-timestamp-face ((,class :foreground ,fg-special-cold)))
+    `(journalctl-warning-face ((,class :inherit bold :foreground ,yellow)))
+;;;;; js2-mode
+    `(js2-error ((,class :foreground ,red)))
+    `(js2-external-variable ((,class :foreground ,cyan-alt-other)))
+    `(js2-function-call ((,class :foreground ,magenta)))
+    `(js2-function-param ((,class :foreground ,blue)))
+    `(js2-instance-member ((,class :foreground ,magenta-alt-other)))
+    `(js2-jsdoc-html-tag-delimiter ((,class :foreground ,fg-main)))
+    `(js2-jsdoc-html-tag-name ((,class :foreground ,cyan)))
+    `(js2-jsdoc-tag ((,class :foreground ,fg-special-calm)))
+    `(js2-jsdoc-type ((,class :foreground ,fg-special-cold)))
+    `(js2-jsdoc-value ((,class :foreground ,fg-special-warm)))
+    `(js2-object-property ((,class :foreground ,fg-main)))
+    `(js2-object-property-access ((,class :foreground ,fg-main)))
+    `(js2-private-function-call ((,class :foreground ,green-alt-other)))
+    `(js2-private-member ((,class :foreground ,fg-special-mild)))
+    `(js2-warning ((,class :foreground ,yellow-alt :underline t)))
+;;;;; julia
+    `(julia-macro-face ((,class :inherit modus-theme-bold :foreground 
,magenta)))
+    `(julia-quoted-symbol-face ((,class :foreground ,blue-alt-other)))
+;;;;; jupyter
+    `(jupyter-eval-overlay ((,class :inherit bold :foreground ,blue)))
+    `(jupyter-repl-input-prompt ((,class :foreground ,cyan-alt-other)))
+    `(jupyter-repl-output-prompt ((,class :foreground ,magenta-alt-other)))
+    `(jupyter-repl-traceback ((,class :inherit modus-theme-intense-red)))
+;;;;; kaocha-runner
+    `(kaocha-runner-error-face ((,class :foreground ,red)))
+    `(kaocha-runner-success-face ((,class :foreground ,green)))
+    `(kaocha-runner-warning-face ((,class :foreground ,yellow)))
+;;;;; keycast
+    `(keycast-command ((,class :inherit bold :foreground ,blue-active)))
+    `(keycast-key ((,class ,@(modus-themes--mode-line-attrs
+                              bg-main blue-active
+                              bg-main blue-active
+                              blue-active blue-intense
+                              'alt-style -3))))
+;;;;; line numbers (display-line-numbers-mode and global variant)
+    `(line-number
+      ((,class :inherit default
+               ,@(modus-themes--line-numbers
+                  fg-alt bg-dim
+                  fg-unfocused))))
+    `(line-number-current-line
+      ((,class :inherit (bold default)
+               ,@(modus-themes--line-numbers
+                  fg-main bg-active
+                  blue-alt-other))))
+    `(line-number-major-tick
+      ((,class :inherit (bold default)
+               ,@(modus-themes--line-numbers
+                  yellow-nuanced-fg yellow-nuanced-bg
+                  red-alt))))
+    `(line-number-minor-tick
+      ((,class :inherit (bold default)
+               ,@(modus-themes--line-numbers
+                  fg-alt bg-inactive
+                  fg-inactive))))
+;;;;; lsp-mode
+    `(lsp-face-highlight-read ((,class :inherit modus-theme-subtle-blue 
:underline t)))
+    `(lsp-face-highlight-textual ((,class :inherit modus-theme-subtle-blue)))
+    `(lsp-face-highlight-write ((,class :inherit (modus-theme-refine-blue 
bold))))
+    `(lsp-face-semhl-constant ((,class :foreground ,blue-alt-other)))
+    `(lsp-face-semhl-deprecated
+      ((,(append '((supports :underline (:style wave))) class)
+        :foreground ,yellow :underline (:style wave))
+       (,class :foreground ,yellow :underline t)))
+    `(lsp-face-semhl-enummember ((,class :foreground ,blue-alt-other)))
+    `(lsp-face-semhl-field ((,class :foreground ,cyan-alt)))
+    `(lsp-face-semhl-field-static ((,class :inherit modus-theme-slant 
:foreground ,cyan-alt)))
+    `(lsp-face-semhl-function ((,class :foreground ,magenta)))
+    `(lsp-face-semhl-method ((,class :foreground ,magenta)))
+    `(lsp-face-semhl-namespace ((,class :inherit modus-theme-bold :foreground 
,magenta-alt)))
+    `(lsp-face-semhl-preprocessor ((,class :foreground ,red-alt-other)))
+    `(lsp-face-semhl-static-method ((,class :inherit modus-theme-slant 
:foreground ,magenta)))
+    `(lsp-face-semhl-type-class ((,class :foreground ,magenta-alt)))
+    `(lsp-face-semhl-type-enum ((,class :foreground ,magenta-alt)))
+    `(lsp-face-semhl-type-primitive ((,class :inherit modus-theme-slant 
:foreground ,magenta-alt)))
+    `(lsp-face-semhl-type-template ((,class :inherit modus-theme-slant 
:foreground ,magenta-alt)))
+    `(lsp-face-semhl-type-typedef ((,class :inherit modus-theme-slant 
:foreground ,magenta-alt)))
+    `(lsp-face-semhl-variable ((,class :foreground ,cyan)))
+    `(lsp-face-semhl-variable-local ((,class :foreground ,cyan)))
+    `(lsp-face-semhl-variable-parameter ((,class :foreground ,cyan-alt-other)))
+    `(lsp-lens-face ((,class :height 0.8 :foreground ,fg-alt)))
+    `(lsp-lens-mouse-face ((,class :height 0.8 :foreground ,blue-alt-other 
:underline t)))
+    `(lsp-ui-doc-background ((,class :background ,bg-alt)))
+    `(lsp-ui-doc-header ((,class :background ,bg-header :foreground 
,fg-header)))
+    `(lsp-ui-doc-url ((,class :inherit button)))
+    `(lsp-ui-peek-filename ((,class :foreground ,fg-special-warm)))
+    `(lsp-ui-peek-footer ((,class :background ,bg-header :foreground 
,fg-header)))
+    `(lsp-ui-peek-header ((,class :background ,bg-header :foreground 
,fg-header)))
+    `(lsp-ui-peek-highlight ((,class :inherit modus-theme-subtle-blue)))
+    `(lsp-ui-peek-line-number ((,class :inherit shadow)))
+    `(lsp-ui-peek-list ((,class :background ,bg-dim)))
+    `(lsp-ui-peek-peek ((,class :background ,bg-alt)))
+    `(lsp-ui-peek-selection ((,class :inherit modus-theme-subtle-cyan)))
+    `(lsp-ui-sideline-code-action ((,class :foreground ,yellow)))
+    `(lsp-ui-sideline-current-symbol ((,class :inherit bold :height 0.99 :box 
(:line-width -1 :style nil) :foreground ,fg-main)))
+    `(lsp-ui-sideline-symbol ((,class :inherit bold :height 0.99 :box 
(:line-width -1 :style nil) :foreground ,fg-alt)))
+    `(lsp-ui-sideline-symbol-info ((,class :inherit italic :height 0.99)))
+;;;;; macrostep
+    `(macrostep-compiler-macro-face ((,class :inherit italic)))
+    `(macrostep-expansion-highlight-face ((,class :background 
,blue-nuanced-bg)))
+    `(macrostep-gensym-1 ((,class :inherit bold :foreground ,blue :box t)))
+    `(macrostep-gensym-2 ((,class :inherit bold :foreground ,green :box t)))
+    `(macrostep-gensym-3 ((,class :inherit bold :foreground ,yellow :box t)))
+    `(macrostep-gensym-4 ((,class :inherit bold :foreground ,red :box t)))
+    `(macrostep-gensym-5 ((,class :inherit bold :foreground ,magenta :box t)))
+    `(macrostep-macro-face ((,class :inherit button :foreground ,green-alt)))
+;;;;; magit
+    `(magit-bisect-bad ((,class :foreground ,red-alt-other)))
+    `(magit-bisect-good ((,class :foreground ,green-alt-other)))
+    `(magit-bisect-skip ((,class :foreground ,yellow-alt-other)))
+    `(magit-blame-date ((,class :foreground ,blue)))
+    `(magit-blame-dimmed ((,class :inherit shadow)))
+    `(magit-blame-hash ((,class :foreground ,fg-special-warm)))
+    `(magit-blame-heading ((,class :background ,bg-alt)))
+    `(magit-blame-highlight ((,class :inherit modus-theme-nuanced-cyan)))
+    `(magit-blame-margin ((,class :inherit magit-blame-highlight)))
+    `(magit-blame-name ((,class :foreground ,magenta-alt-other)))
+    `(magit-blame-summary ((,class :foreground ,cyan-alt-other)))
+    `(magit-branch-current ((,class :foreground ,blue-alt-other :box t)))
+    `(magit-branch-local ((,class :foreground ,blue-alt)))
+    `(magit-branch-remote ((,class :foreground ,magenta-alt)))
+    `(magit-branch-remote-head ((,class :foreground ,magenta-alt-other :box 
t)))
+    `(magit-branch-upstream ((,class :inherit italic)))
+    `(magit-cherry-equivalent ((,class :background ,bg-main :foreground 
,magenta-intense)))
+    `(magit-cherry-unmatched ((,class :background ,bg-main :foreground 
,cyan-intense)))
+    ;; NOTE: here we break from the pattern of inheriting from the
+    ;; modus-theme-diff-* faces, though only for the standard actions,
+    ;; not the highlighted ones.  This is because Magit's interaction
+    ;; model relies on highlighting the current diff hunk.
+    `(magit-diff-added ((,class ,@(modus-themes--diff
+                                   bg-main green
+                                   bg-diff-added fg-diff-added
+                                   green-nuanced-bg fg-diff-added
+                                   bg-diff-added-deuteran 
fg-diff-added-deuteran))))
+    `(magit-diff-added-highlight ((,class :inherit 
modus-theme-diff-focus-added)))
+    `(magit-diff-base ((,class ,@(modus-themes--diff
+                                  bg-main yellow
+                                  bg-diff-changed fg-diff-changed
+                                  yellow-nuanced-bg fg-diff-changed))))
+    `(magit-diff-base-highlight ((,class :inherit 
modus-theme-diff-focus-changed)))
+    `(magit-diff-context ((,class :foreground ,fg-unfocused)))
+    `(magit-diff-context-highlight ((,class ,@(modus-themes--diff
+                                               bg-dim fg-dim
+                                               bg-inactive fg-inactive
+                                               bg-dim fg-alt))))
+    `(magit-diff-file-heading ((,class :inherit bold :foreground 
,fg-special-cold)))
+    `(magit-diff-file-heading-highlight ((,class :inherit 
(modus-theme-special-cold bold))))
+    `(magit-diff-file-heading-selection ((,class :inherit 
modus-theme-refine-cyan)))
+    ;; NOTE: here we break from the pattern of inheriting from the
+    ;; modus-theme-diff-* faces.
+    `(magit-diff-hunk-heading ((,class :inherit bold :background ,bg-active
+                                       :foreground ,fg-inactive)))
+    `(magit-diff-hunk-heading-highlight
+      ((,class :inherit bold
+               :background ,@(modus-themes--diff-deuteran bg-region 
bg-diff-heading)
+               :foreground ,@(modus-themes--diff-deuteran fg-main 
fg-diff-heading))))
+    `(magit-diff-hunk-heading-selection ((,class :inherit 
modus-theme-refine-blue)))
+    `(magit-diff-hunk-region ((,class :inherit bold)))
+    `(magit-diff-lines-boundary ((,class :background ,fg-main)))
+    `(magit-diff-lines-heading ((,class :inherit modus-theme-refine-magenta)))
+    `(magit-diff-removed ((,class ,@(modus-themes--diff
+                                     bg-main red
+                                     bg-diff-removed fg-diff-removed
+                                     red-nuanced-bg fg-diff-removed))))
+    `(magit-diff-removed-highlight ((,class :inherit 
modus-theme-diff-focus-removed)))
+    `(magit-diffstat-added ((,class :foreground ,@(modus-themes--diff-deuteran 
blue green))))
+    `(magit-diffstat-removed ((,class :foreground ,red)))
+    `(magit-dimmed ((,class :foreground ,fg-unfocused)))
+    `(magit-filename ((,class :foreground ,fg-special-cold)))
+    `(magit-hash ((,class :inherit shadow)))
+    `(magit-head ((,class :inherit magit-branch-local)))
+    `(magit-header-line ((,class :inherit bold :foreground ,magenta-active)))
+    `(magit-header-line-key ((,class :inherit bold :foreground ,blue-active)))
+    `(magit-header-line-log-select ((,class :inherit bold :foreground 
,fg-main)))
+    `(magit-keyword ((,class :foreground ,magenta)))
+    `(magit-keyword-squash ((,class :inherit bold :foreground 
,yellow-alt-other)))
+    `(magit-log-author ((,class :foreground ,cyan)))
+    `(magit-log-date ((,class :inherit shadow)))
+    `(magit-log-graph ((,class :foreground ,fg-dim)))
+    `(magit-mode-line-process ((,class :inherit bold :foreground 
,blue-active)))
+    `(magit-mode-line-process-error ((,class :inherit bold :foreground 
,red-active)))
+    `(magit-process-ng ((,class :inherit error)))
+    `(magit-process-ok ((,class :inherit success)))
+    `(magit-reflog-amend ((,class :background ,bg-main :foreground 
,magenta-intense)))
+    `(magit-reflog-checkout ((,class :background ,bg-main :foreground 
,blue-intense)))
+    `(magit-reflog-cherry-pick ((,class :background ,bg-main :foreground 
,green-intense)))
+    `(magit-reflog-commit ((,class :background ,bg-main :foreground 
,green-intense)))
+    `(magit-reflog-merge ((,class :background ,bg-main :foreground 
,green-intense)))
+    `(magit-reflog-other ((,class :background ,bg-main :foreground 
,cyan-intense)))
+    `(magit-reflog-rebase ((,class :background ,bg-main :foreground 
,magenta-intense)))
+    `(magit-reflog-remote ((,class :background ,bg-main :foreground 
,cyan-intense)))
+    `(magit-reflog-reset ((,class :background ,bg-main :foreground 
,red-intense)))
+    `(magit-refname ((,class :inherit shadow)))
+    `(magit-refname-pullreq ((,class :inherit shadow)))
+    `(magit-refname-stash ((,class :inherit shadow)))
+    `(magit-refname-wip ((,class :inherit shadow)))
+    `(magit-section ((,class :background ,bg-dim :foreground ,fg-main)))
+    `(magit-section-heading ((,class :inherit bold :foreground ,cyan)))
+    `(magit-section-heading-selection ((,class :inherit 
(modus-theme-refine-cyan bold))))
+    `(magit-section-highlight ((,class :background ,bg-alt)))
+    `(magit-sequence-done ((,class :foreground ,green-alt)))
+    `(magit-sequence-drop ((,class :foreground ,red-alt)))
+    `(magit-sequence-exec ((,class :foreground ,magenta-alt)))
+    `(magit-sequence-head ((,class :foreground ,cyan-alt)))
+    `(magit-sequence-onto ((,class :inherit shadow)))
+    `(magit-sequence-part ((,class :foreground ,yellow-alt)))
+    `(magit-sequence-pick ((,class :foreground ,blue-alt)))
+    `(magit-sequence-stop ((,class :foreground ,red)))
+    `(magit-signature-bad ((,class :inherit bold :foreground ,red)))
+    `(magit-signature-error ((,class :foreground ,red-alt)))
+    `(magit-signature-expired ((,class :foreground ,yellow)))
+    `(magit-signature-expired-key ((,class :foreground ,yellow)))
+    `(magit-signature-good ((,class :foreground ,green)))
+    `(magit-signature-revoked ((,class :foreground ,magenta)))
+    `(magit-signature-untrusted ((,class :foreground ,cyan)))
+    `(magit-tag ((,class :foreground ,yellow-alt-other)))
+;;;;; magit-imerge
+    `(magit-imerge-overriding-value ((,class :inherit bold :foreground 
,red-alt)))
+;;;;; make-mode (makefiles)
+    `(makefile-makepp-perl ((,class :background ,cyan-nuanced-bg)))
+    `(makefile-space ((,class :background ,magenta-nuanced-bg)))
+;;;;; man
+    `(Man-overstrike ((,class :inherit bold :foreground ,magenta)))
+    `(Man-reverse ((,class :inherit modus-theme-subtle-magenta)))
+    `(Man-underline ((,class :foreground ,cyan :underline t)))
+;;;;; marginalia
+    `(marginalia-archive ((,class :foreground ,green-nuanced-fg)))
+    `(marginalia-date ((,class :foreground ,blue-nuanced-fg)))
+    `(marginalia-char ((,class :foreground ,red-active)))
+    `(marginalia-documentation ((,class :foreground ,fg-special-cold :inherit 
modus-theme-slant)))
+    `(marginalia-file-modes ((,class :inherit shadow)))
+    `(marginalia-file-name ((,class :foreground ,fg-special-mild)))
+    `(marginalia-file-owner ((,class :foreground ,red-nuanced-fg)))
+    `(marginalia-key ((,class :foreground ,magenta-active)))
+    `(marginalia-mode ((,class :foreground ,cyan-active)))
+    `(marginalia-modified ((,class :foreground ,yellow-active)))
+    `(marginalia-number ((,class :foreground ,blue-active)))
+    `(marginalia-size ((,class :foreground ,green-active)))
+    `(marginalia-type ((,class :foreground ,fg-special-warm)))
+    `(marginalia-variable ((,class :foreground ,yellow-nuanced-fg)))
+    `(marginalia-version ((,class :foreground ,cyan-active)))
+;;;;; markdown-mode
+    `(markdown-blockquote-face ((,class :inherit modus-theme-slant :foreground 
,fg-special-cold)))
+    `(markdown-bold-face ((,class :inherit bold)))
+    `(markdown-code-face ((,class ,@(modus-themes--mixed-fonts) :background 
,bg-dim :extend t)))
+    `(markdown-comment-face ((,class :inherit font-lock-comment-face)))
+    `(markdown-footnote-marker-face ((,class :inherit bold :foreground 
,cyan-alt)))
+    `(markdown-footnote-text-face ((,class :inherit modus-theme-slant 
:foreground ,fg-main)))
+    `(markdown-gfm-checkbox-face ((,class :foreground ,cyan-alt-other)))
+    `(markdown-header-delimiter-face ((,class :inherit modus-theme-bold 
:foreground ,fg-dim)))
+    `(markdown-header-face ((t nil)))
+    `(markdown-header-face-1 ((,class :inherit modus-theme-heading-1)))
+    `(markdown-header-face-2 ((,class :inherit modus-theme-heading-2)))
+    `(markdown-header-face-3 ((,class :inherit modus-theme-heading-3)))
+    `(markdown-header-face-4 ((,class :inherit modus-theme-heading-4)))
+    `(markdown-header-face-5 ((,class :inherit modus-theme-heading-5)))
+    `(markdown-header-face-6 ((,class :inherit modus-theme-heading-6)))
+    `(markdown-header-rule-face ((,class :inherit bold :foreground 
,fg-special-warm)))
+    `(markdown-hr-face ((,class :inherit bold :foreground ,fg-special-warm)))
+    `(markdown-html-attr-name-face ((,class ,@(modus-themes--mixed-fonts)
+                                            :foreground ,cyan)))
+    `(markdown-html-attr-value-face ((,class ,@(modus-themes--mixed-fonts)
+                                             :foreground ,blue)))
+    `(markdown-html-entity-face ((,class ,@(modus-themes--mixed-fonts)
+                                         :foreground ,cyan)))
+    `(markdown-html-tag-delimiter-face ((,class ,@(modus-themes--mixed-fonts)
+                                                :foreground ,fg-special-mild)))
+    `(markdown-html-tag-name-face ((,class ,@(modus-themes--mixed-fonts)
+                                           :foreground ,magenta-alt)))
+    `(markdown-inline-code-face ((,class ,@(modus-themes--mixed-fonts)
+                                         :background ,bg-alt :foreground 
,fg-special-calm)))
+    `(markdown-italic-face ((,class :inherit italic :foreground 
,fg-special-cold)))
+    `(markdown-language-info-face ((,class ,@(modus-themes--mixed-fonts)
+                                           :foreground ,fg-special-cold)))
+    `(markdown-language-keyword-face ((,class ,@(modus-themes--mixed-fonts)
+                                              :background ,bg-alt
+                                              :foreground ,fg-alt)))
+    `(markdown-line-break-face ((,class :inherit modus-theme-refine-cyan 
:underline t)))
+    `(markdown-link-face ((,class :inherit button)))
+    `(markdown-link-title-face ((,class :inherit modus-theme-slant :foreground 
,fg-special-cold)))
+    `(markdown-list-face ((,class :foreground ,fg-dim)))
+    `(markdown-markup-face ((,class :inherit shadow)))
+    `(markdown-math-face ((,class :foreground ,magenta-alt-other)))
+    `(markdown-metadata-key-face ((,class :foreground ,cyan-alt-other)))
+    `(markdown-metadata-value-face ((,class :foreground ,blue-alt)))
+    `(markdown-missing-link-face ((,class :inherit bold :foreground ,yellow)))
+    `(markdown-plain-url-face ((,class :inherit markdown-link-face)))
+    `(markdown-pre-face ((,class :inherit markdown-code-face :foreground 
,fg-special-mild)))
+    `(markdown-reference-face ((,class :inherit markdown-markup-face)))
+    `(markdown-strike-through-face ((,class :strike-through t)))
+    `(markdown-table-face ((,class ,@(modus-themes--mixed-fonts)
+                                   :foreground ,fg-special-cold)))
+    `(markdown-url-face ((,class :foreground ,blue-alt)))
+;;;;; markup-faces (`adoc-mode')
+    `(markup-anchor-face ((,class :foreground ,fg-inactive)))
+    `(markup-attribute-face ((,class :inherit italic :foreground 
,fg-inactive)))
+    `(markup-big-face ((,class :height 1.3 :foreground ,blue-nuanced-fg)))
+    `(markup-bold-face ((,class :inherit bold :foreground ,red-nuanced-fg)))
+    `(markup-code-face ((,class :inherit fixed-pitch :foreground ,magenta)))
+    `(markup-command-face ((,class :foreground ,fg-inactive)))
+    `(markup-comment-face ((,class :inherit font-lock-comment-face)))
+    `(markup-complex-replacement-face ((,class :box (:line-width 2 :color nil 
:style released-button)
+                                               :inherit 
modus-theme-refine-magenta)))
+    `(markup-emphasis-face ((,class :inherit italic :foreground 
,fg-special-cold)))
+    `(markup-error-face ((,class :inherit bold :foreground ,red)))
+    `(markup-gen-face ((,class :foreground ,magenta-alt)))
+    `(markup-internal-reference-face ((,class :inherit button :foreground 
,fg-alt)))
+    `(markup-italic-face ((,class :inherit italic :foreground 
,fg-special-cold)))
+    `(markup-list-face ((,class :inherit modus-theme-special-calm)))
+    `(markup-meta-face ((,class :foreground ,fg-inactive)))
+    `(markup-meta-hide-face ((,class :inherit shadow)))
+    `(markup-passthrough-face ((,class :inherit fixed-pitch :foreground 
,cyan)))
+    `(markup-preprocessor-face ((,class :foreground ,red-alt-other)))
+    `(markup-replacement-face ((,class :foreground ,yellow-alt-other)))
+    `(markup-secondary-text-face ((,class :height 0.8 :foreground 
,magenta-nuanced-fg)))
+    `(markup-small-face ((,class :height 0.8 :foreground ,fg-main)))
+    `(markup-strong-face ((,class :inherit bold :foreground ,red-nuanced-fg)))
+    `(markup-subscript-face ((,class :height 0.8 :foreground 
,fg-special-cold)))
+    `(markup-superscript-face ((,class :height 0.8 :foreground 
,fg-special-cold)))
+    `(markup-table-cell-face ((,class :inherit modus-theme-special-cold)))
+    `(markup-table-face ((,class :inherit modus-theme-subtle-cyan)))
+    `(markup-table-row-face ((,class :inherit modus-theme-subtle-cyan)))
+    `(markup-title-0-face ((,class :height 3.0 :foreground ,blue-nuanced-fg)))
+    `(markup-title-1-face ((,class :height 2.4 :foreground ,blue-nuanced-fg)))
+    `(markup-title-2-face ((,class :height 1.8 :foreground ,blue-nuanced-fg)))
+    `(markup-title-3-face ((,class :height 1.4 :foreground ,blue-nuanced-fg)))
+    `(markup-title-4-face ((,class :height 1.2 :foreground ,blue-nuanced-fg)))
+    `(markup-title-5-face ((,class :height 1.2 :foreground ,blue-nuanced-fg 
:underline t)))
+    `(markup-value-face ((,class :foreground ,fg-inactive)))
+    `(markup-verbatim-face ((,class :inherit modus-theme-special-mild)))
+;;;;; mentor
+    `(mentor-download-message ((,class :foreground ,fg-special-warm)))
+    `(mentor-download-name ((,class :foreground ,fg-special-cold)))
+    `(mentor-download-progress ((,class :foreground ,blue-alt-other)))
+    `(mentor-download-size ((,class :foreground ,magenta-alt-other)))
+    `(mentor-download-speed-down ((,class :foreground ,cyan-alt)))
+    `(mentor-download-speed-up ((,class :foreground ,red-alt)))
+    `(mentor-download-state ((,class :foreground ,yellow-alt)))
+    `(mentor-highlight-face ((,class :inherit modus-theme-subtle-blue)))
+    `(mentor-tracker-name ((,class :foreground ,magenta-alt)))
+;;;;; messages
+    `(message-cited-text-1 ((,class :foreground ,blue-faint)))
+    `(message-cited-text-2 ((,class :foreground ,green-alt-other)))
+    `(message-cited-text-3 ((,class :foreground ,red-alt-other)))
+    `(message-cited-text-4 ((,class :foreground ,cyan)))
+    `(message-header-cc ((,class :foreground ,blue-alt-other)))
+    `(message-header-name ((,class :inherit bold :foreground ,cyan)))
+    `(message-header-newsgroups ((,class :inherit message-header-other)))
+    `(message-header-other ((,class :foreground ,fg-special-calm)))
+    `(message-header-subject ((,class :inherit bold :foreground ,magenta-alt)))
+    `(message-header-to ((,class :inherit bold :foreground 
,magenta-alt-other)))
+    `(message-header-xheader ((,class :foreground ,blue-alt)))
+    `(message-mml ((,class :foreground ,yellow)))
+    `(message-separator ((,class :inherit modus-theme-intense-neutral)))
+;;;;; minibuffer-line
+    `(minibuffer-line ((,class :foreground ,fg-main)))
+;;;;; minimap
+    `(minimap-active-region-background ((,class :background ,bg-active)))
+    `(minimap-current-line-face ((,class :background ,cyan-intense-bg 
:foreground ,fg-main)))
+;;;;; mmm-mode
+    `(mmm-cleanup-submode-face ((,class :background ,yellow-nuanced-bg)))
+    `(mmm-code-submode-face ((,class :background ,bg-alt)))
+    `(mmm-comment-submode-face ((,class :background ,blue-nuanced-bg)))
+    `(mmm-declaration-submode-face ((,class :background ,cyan-nuanced-bg)))
+    `(mmm-default-submode-face ((,class :background ,bg-dim)))
+    `(mmm-init-submode-face ((,class :background ,magenta-nuanced-bg)))
+    `(mmm-output-submode-face ((,class :background ,red-nuanced-bg)))
+    `(mmm-special-submode-face ((,class :background ,green-nuanced-bg)))
+;;;;; modeline
+    `(mode-line ((,class ,@(modus-themes--variable-pitch-ui)
+                         ,@(modus-themes--mode-line-attrs
+                            fg-active bg-active fg-dim bg-active
+                            fg-alt bg-active 'alt-style nil bg-main))))
+    `(mode-line-buffer-id ((,class :inherit bold)))
+    `(mode-line-emphasis ((,class :inherit bold :foreground ,blue-active)))
+    `(mode-line-highlight ((,class :inherit modus-theme-active-blue :box 
(:line-width -1 :style pressed-button))))
+    `(mode-line-inactive ((,class ,@(modus-themes--variable-pitch-ui)
+                                  ,@(modus-themes--mode-line-attrs
+                                     fg-inactive bg-inactive fg-alt bg-dim
+                                     bg-region bg-active))))
+;;;;; mood-line
+    `(mood-line-modified ((,class :foreground ,magenta-active)))
+    `(mood-line-status-error ((,class :inherit bold :foreground ,red-active)))
+    `(mood-line-status-info ((,class :foreground ,cyan-active)))
+    `(mood-line-status-neutral ((,class :foreground ,blue-active)))
+    `(mood-line-status-success ((,class :foreground ,green-active)))
+    `(mood-line-status-warning ((,class :inherit bold :foreground 
,yellow-active)))
+    `(mood-line-unimportant ((,class :foreground ,fg-inactive)))
+;;;;; mpdel
+    `(mpdel-browser-directory-face ((,class :foreground ,blue)))
+    `(mpdel-playlist-current-song-face ((,class :inherit bold :foreground 
,blue-alt-other)))
+;;;;; mu4e
+    `(mu4e-attach-number-face ((,class :inherit bold :foreground ,fg-dim)))
+    `(mu4e-cited-1-face ((,class :foreground ,blue-faint)))
+    `(mu4e-cited-2-face ((,class :foreground ,green-alt-other)))
+    `(mu4e-cited-3-face ((,class :foreground ,red-alt-other)))
+    `(mu4e-cited-4-face ((,class :foreground ,cyan)))
+    `(mu4e-cited-5-face ((,class :foreground ,yellow-alt)))
+    `(mu4e-cited-6-face ((,class :foreground ,magenta)))
+    `(mu4e-cited-7-face ((,class :foreground ,green-alt)))
+    `(mu4e-compose-header-face ((,class :inherit mu4e-compose-separator-face)))
+    `(mu4e-compose-separator-face ((,class :inherit 
modus-theme-intense-neutral)))
+    `(mu4e-contact-face ((,class :inherit message-header-to)))
+    `(mu4e-context-face ((,class :foreground ,blue-active)))
+    `(mu4e-draft-face ((,class :foreground ,magenta-alt)))
+    `(mu4e-flagged-face ((,class :foreground ,red-alt)))
+    `(mu4e-footer-face ((,class :inherit modus-theme-slant :foreground 
,fg-special-cold)))
+    `(mu4e-forwarded-face ((,class :foreground ,magenta-alt-other)))
+    `(mu4e-header-face ((,class :inherit shadow)))
+    `(mu4e-header-highlight-face ((,class :inherit modus-theme-hl-line)))
+    `(mu4e-header-key-face ((,class :inherit message-header-name)))
+    `(mu4e-header-marks-face ((,class :inherit 
mu4e-special-header-value-face)))
+    `(mu4e-header-title-face ((,class :foreground ,fg-special-mild)))
+    `(mu4e-header-value-face ((,class :inherit message-header-other)))
+    `(mu4e-highlight-face ((,class :inherit bold :foreground ,blue-alt-other)))
+    `(mu4e-link-face ((,class :inherit button)))
+    `(mu4e-modeline-face ((,class :foreground ,magenta-active)))
+    `(mu4e-moved-face ((,class :inherit modus-theme-slant :foreground 
,yellow)))
+    `(mu4e-ok-face ((,class :inherit bold :foreground ,green)))
+    `(mu4e-region-code ((,class :inherit modus-theme-special-calm)))
+    `(mu4e-replied-face ((,class :foreground ,blue)))
+    `(mu4e-special-header-value-face ((,class :inherit 
message-header-subject)))
+    `(mu4e-system-face ((,class :inherit modus-theme-slant :foreground 
,fg-mark-del)))
+    `(mu4e-title-face ((,class :foreground ,fg-main)))
+    `(mu4e-trashed-face ((,class :foreground ,red)))
+    `(mu4e-unread-face ((,class :inherit bold)))
+    `(mu4e-url-number-face ((,class :foreground ,fg-alt)))
+    `(mu4e-view-body-face ((,class :foreground ,fg-main)))
+    `(mu4e-warning-face ((,class :inherit warning)))
+;;;;; mu4e-conversation
+    `(mu4e-conversation-header ((,class :inherit modus-theme-special-cold)))
+    `(mu4e-conversation-sender-1 ((,class :foreground ,fg-special-warm)))
+    `(mu4e-conversation-sender-2 ((,class :foreground ,fg-special-cold)))
+    `(mu4e-conversation-sender-3 ((,class :foreground ,fg-special-mild)))
+    `(mu4e-conversation-sender-4 ((,class :inherit shadow)))
+    `(mu4e-conversation-sender-5 ((,class :foreground ,yellow-refine-fg)))
+    `(mu4e-conversation-sender-6 ((,class :foreground ,cyan-refine-fg)))
+    `(mu4e-conversation-sender-7 ((,class :foreground ,green-refine-fg)))
+    `(mu4e-conversation-sender-8 ((,class :foreground ,blue-refine-fg)))
+    `(mu4e-conversation-sender-me ((,class :foreground ,fg-main)))
+    `(mu4e-conversation-unread ((,class :inherit bold)))
+;;;;; multiple-cursors
+    `(mc/cursor-bar-face ((,class :height 1 :background ,fg-main)))
+    `(mc/cursor-face ((,class :inverse-video t)))
+    `(mc/region-face ((,class :inherit region)))
+;;;;; neotree
+    `(neo-banner-face ((,class :foreground ,magenta)))
+    `(neo-button-face ((,class :inherit button)))
+    `(neo-dir-link-face ((,class :inherit bold :foreground ,blue)))
+    `(neo-expand-btn-face ((,class :foreground ,cyan)))
+    `(neo-file-link-face ((,class :foreground ,fg-main)))
+    `(neo-header-face ((,class :inherit bold :foreground ,fg-main)))
+    `(neo-root-dir-face ((,class :inherit bold :foreground ,cyan-alt)))
+    `(neo-vc-added-face ((,class :foreground ,green)))
+    `(neo-vc-conflict-face ((,class :inherit bold :foreground ,red)))
+    `(neo-vc-default-face ((,class :foreground ,fg-main)))
+    `(neo-vc-edited-face ((,class :foreground ,yellow)))
+    `(neo-vc-ignored-face ((,class :foreground ,fg-inactive)))
+    `(neo-vc-missing-face ((,class :foreground ,red-alt)))
+    `(neo-vc-needs-merge-face ((,class :foreground ,magenta-alt)))
+    `(neo-vc-needs-update-face ((,class :underline t)))
+    `(neo-vc-removed-face ((,class :strike-through t)))
+    `(neo-vc-unlocked-changes-face ((,class :inherit modus-theme-refine-blue)))
+    `(neo-vc-up-to-date-face ((,class :inherit shadow)))
+    `(neo-vc-user-face ((,class :foreground ,magenta)))
+;;;;; no-emoji
+    `(no-emoji ((,class :foreground ,cyan)))
+;;;;; notmuch
+    `(notmuch-crypto-decryption ((,class :inherit modus-theme-refine-magenta)))
+    `(notmuch-crypto-part-header ((,class :foreground ,magenta-alt-other)))
+    `(notmuch-crypto-signature-bad ((,class :inherit modus-theme-intense-red)))
+    `(notmuch-crypto-signature-good ((,class :inherit 
modus-theme-refine-green)))
+    `(notmuch-crypto-signature-good-key ((,class :inherit 
modus-theme-refine-yellow)))
+    `(notmuch-crypto-signature-unknown ((,class :inherit 
modus-theme-refine-red)))
+    `(notmuch-hello-logo-background ((,class :background "gray50")))
+    `(notmuch-message-summary-face ((,class :inherit 
modus-theme-nuanced-cyan)))
+    `(notmuch-search-count ((,class :inherit shadow)))
+    `(notmuch-search-date ((,class :foreground ,cyan)))
+    `(notmuch-search-flagged-face ((,class :foreground ,red-alt)))
+    `(notmuch-search-matching-authors ((,class :foreground ,fg-main)))
+    `(notmuch-search-non-matching-authors ((,class :inherit shadow)))
+    `(notmuch-search-subject ((,class :foreground ,fg-dim)))
+    `(notmuch-search-unread-face ((,class :inherit bold)))
+    `(notmuch-tag-added
+      ((,(append '((supports :underline (:style wave))) class)
+        :underline (:color ,green :style wave))
+       (,class :foreground ,green :underline t)))
+    `(notmuch-tag-deleted
+      ((,(append '((supports :underline (:style wave))) class)
+        :underline (:color ,red :style wave))
+       (,class :foreground ,red :underline t)))
+    `(notmuch-tag-face ((,class :inherit bold :foreground ,blue-alt)))
+    `(notmuch-tag-flagged ((,class :foreground ,red-alt)))
+    `(notmuch-tag-unread ((,class :foreground ,magenta-alt)))
+    `(notmuch-tree-match-author-face ((,class :foreground ,fg-special-cold)))
+    `(notmuch-tree-match-date-face ((,class :inherit notmuch-search-date)))
+    `(notmuch-tree-match-face ((,class :foreground ,fg-main)))
+    `(notmuch-tree-match-tag-face ((,class :inherit bold :foreground 
,blue-alt)))
+    `(notmuch-tree-no-match-face ((,class :inherit shadow)))
+    `(notmuch-tree-no-match-date-face ((,class :inherit shadow)))
+    `(notmuch-wash-cited-text ((,class :foreground ,cyan)))
+    `(notmuch-wash-toggle-button ((,class :background ,bg-alt :foreground 
,fg-alt)))
+;;;;; num3-mode
+    `(num3-face-even ((,class :inherit bold :background ,bg-alt)))
+;;;;; nxml-mode
+    `(nxml-attribute-colon ((,class :foreground ,fg-main)))
+    `(nxml-attribute-local-name ((,class :inherit 
font-lock-variable-name-face)))
+    `(nxml-attribute-prefix ((,class  :inherit font-lock-type-face)))
+    `(nxml-attribute-value ((,class :inherit font-lock-constant-face)))
+    `(nxml-cdata-section-CDATA ((,class :inherit error)))
+    `(nxml-cdata-section-delimiter ((,class :inherit error)))
+    `(nxml-char-ref-delimiter ((,class :foreground ,fg-special-mild)))
+    `(nxml-char-ref-number ((,class :inherit modus-theme-bold :foreground 
,fg-special-mild)))
+    `(nxml-delimited-data ((,class :inherit modus-theme-slant :foreground 
,fg-special-cold)))
+    `(nxml-delimiter ((,class :foreground ,fg-dim)))
+    `(nxml-element-colon ((,class :foreground ,fg-main)))
+    `(nxml-element-local-name ((,class :inherit font-lock-function-name-face)))
+    `(nxml-element-prefix ((,class :inherit font-lock-builtin-face)))
+    `(nxml-entity-ref-delimiter ((,class :foreground ,fg-special-mild)))
+    `(nxml-entity-ref-name ((,class :inherit modus-theme-bold :foreground 
,fg-special-mild)))
+    `(nxml-glyph ((,class :inherit modus-theme-intense-neutral)))
+    `(nxml-hash ((,class :inherit (bold font-lock-string-face))))
+    `(nxml-heading ((,class :inherit bold)))
+    `(nxml-name ((,class :inherit font-lock-builtin-face)))
+    `(nxml-namespace-attribute-colon ((,class :foreground ,fg-main)))
+    `(nxml-namespace-attribute-prefix ((,class :inherit 
font-lock-variable-name-face)))
+    `(nxml-processing-instruction-target ((,class :inherit 
font-lock-keyword-face)))
+    `(nxml-prolog-keyword ((,class :inherit font-lock-keyword-face)))
+    `(nxml-ref ((,class :inherit modus-theme-bold :foreground 
,fg-special-mild)))
+    `(rng-error ((,class :inherit error)))
+;;;;; objed
+    `(objed-hl ((,class :background ,(if modus-themes-intense-hl-line
+                                         bg-hl-alt-intense bg-hl-alt))))
+    `(objed-mark ((,class :background ,bg-active)))
+    `(objed-mode-line ((,class :foreground ,cyan-active)))
+;;;;; orderless
+    `(orderless-match-face-0 ((,class :inherit bold
+                                      ,@(modus-themes--standard-completions
+                                         blue-alt-other blue-nuanced-bg
+                                         blue-refine-bg blue-refine-fg))))
+    `(orderless-match-face-1 ((,class :inherit bold
+                                      ,@(modus-themes--standard-completions
+                                         magenta-alt magenta-nuanced-bg
+                                         magenta-refine-bg 
magenta-refine-fg))))
+    `(orderless-match-face-2 ((,class :inherit bold
+                                      ,@(modus-themes--standard-completions
+                                         green green-nuanced-bg
+                                         green-refine-bg green-refine-fg))))
+    `(orderless-match-face-3 ((,class :inherit bold
+                                      ,@(modus-themes--standard-completions
+                                         yellow yellow-nuanced-bg
+                                         yellow-refine-bg yellow-refine-fg))))
+;;;;; org
+    `(org-agenda-calendar-event ((,class :foreground ,fg-main)))
+    `(org-agenda-calendar-sexp ((,class :foreground ,cyan-alt)))
+    `(org-agenda-clocking ((,class :inherit modus-theme-special-cold :extend 
t)))
+    `(org-agenda-column-dateline ((,class :background ,bg-alt)))
+    `(org-agenda-current-time ((,class :inherit bold :foreground 
,blue-alt-other)))
+    `(org-agenda-date ((,class :foreground ,cyan)))
+    `(org-agenda-date-today ((,class :inherit bold :foreground ,fg-main 
:underline t)))
+    `(org-agenda-date-weekend ((,class :foreground ,cyan-alt-other)))
+    `(org-agenda-diary ((,class :foreground ,fg-main)))
+    `(org-agenda-dimmed-todo-face ((,class :inherit bold :foreground ,fg-alt)))
+    `(org-agenda-done ((,class :foreground ,green-alt)))
+    `(org-agenda-filter-category ((,class :inherit bold :foreground 
,magenta-active)))
+    `(org-agenda-filter-effort ((,class :inherit bold :foreground 
,magenta-active)))
+    `(org-agenda-filter-regexp ((,class :inherit bold :foreground 
,magenta-active)))
+    `(org-agenda-filter-tags ((,class :inherit bold :foreground 
,magenta-active)))
+    `(org-agenda-restriction-lock ((,class :background ,bg-dim :foreground 
,fg-dim)))
+    `(org-agenda-structure ((,class ,@(modus-themes--scale 
modus-themes-scale-5)
+                                    :foreground ,blue-alt)))
+    `(org-archived ((,class :background ,bg-alt :foreground ,fg-alt)))
+    `(org-block ((,class ,@(modus-themes--mixed-fonts)
+                         ,@(modus-themes--org-block bg-dim)
+                         :foreground ,fg-main)))
+    `(org-block-begin-line ((,class ,@(modus-themes--mixed-fonts)
+                                    ,@(modus-themes--org-block-delim
+                                       bg-dim fg-special-cold
+                                       bg-alt fg-special-mild))))
+    `(org-block-end-line ((,class :inherit org-block-begin-line)))
+    `(org-checkbox ((,class :box (:line-width 1 :color ,bg-active)
+                            :background ,bg-inactive :foreground ,fg-active)))
+    `(org-checkbox-statistics-done ((,class :inherit org-done)))
+    `(org-checkbox-statistics-todo ((,class :inherit org-todo)))
+    `(org-clock-overlay ((,class :inherit modus-theme-special-cold)))
+    `(org-code ((,class ,@(modus-themes--mixed-fonts)
+                        :background ,red-nuanced-bg :foreground ,magenta)))
+    `(org-column ((,class :background ,bg-alt)))
+    `(org-column-title ((,class :inherit bold :underline t :background 
,bg-alt)))
+    `(org-date ((,class :inherit ,(if modus-themes-no-mixed-fonts
+                                      'button
+                                    '(button fixed-pitch))
+                        ,@(modus-themes--link-color
+                           cyan cyan-faint))))
+    `(org-date-selected ((,class :inherit bold :foreground ,blue-alt 
:inverse-video t)))
+    `(org-dispatcher-highlight ((,class :inherit (bold modus-theme-mark-alt))))
+    `(org-document-info ((,class :foreground ,fg-special-cold)))
+    `(org-document-info-keyword ((,class ,@(modus-themes--mixed-fonts)
+                                         :foreground ,fg-alt)))
+    `(org-document-title ((,class :inherit (bold modus-theme-variable-pitch) 
:foreground ,fg-special-cold
+                                  ,@(modus-themes--scale 
modus-themes-scale-5))))
+    `(org-done ((,class :foreground ,green)))
+    `(org-drawer ((,class ,@(modus-themes--mixed-fonts)
+                          :foreground ,fg-alt)))
+    `(org-ellipsis (())) ; inherits from the heading's color
+    `(org-footnote ((,class :inherit button
+                            ,@(modus-themes--link-color
+                               blue-alt blue-alt-faint))))
+    `(org-formula ((,class ,@(modus-themes--mixed-fonts)
+                           :foreground ,red-alt)))
+    `(org-habit-alert-face ((,class ,@(modus-themes--org-habit
+                                       yellow-graph-0-bg
+                                       yellow-graph-0-bg
+                                       yellow-graph-1-bg))))
+    `(org-habit-alert-future-face ((,class ,@(modus-themes--org-habit
+                                              yellow-graph-1-bg
+                                              yellow-graph-0-bg
+                                              yellow-graph-1-bg))))
+    `(org-habit-clear-face ((,class ,@(modus-themes--org-habit
+                                       blue-graph-0-bg
+                                       green-graph-1-bg
+                                       blue-graph-1-bg))))
+    `(org-habit-clear-future-face ((,class ,@(modus-themes--org-habit
+                                              blue-graph-1-bg
+                                              green-graph-1-bg
+                                              blue-graph-1-bg))))
+    `(org-habit-overdue-face ((,class ,@(modus-themes--org-habit
+                                         red-graph-0-bg
+                                         red-graph-0-bg
+                                         red-graph-1-bg))))
+    `(org-habit-overdue-future-face ((,class ,@(modus-themes--org-habit
+                                                red-graph-1-bg
+                                                red-graph-0-bg
+                                                red-graph-1-bg))))
+    `(org-habit-ready-face ((,class ,@(modus-themes--org-habit
+                                       green-graph-0-bg
+                                       green-graph-0-bg
+                                       green-graph-1-bg))))
+    `(org-habit-ready-future-face ((,class ,@(modus-themes--org-habit
+                                              green-graph-1-bg
+                                              green-graph-0-bg
+                                              green-graph-1-bg))))
+    `(org-headline-done ((,class :inherit modus-theme-variable-pitch 
:foreground ,green-nuanced-fg)))
+    `(org-headline-todo ((,class :inherit modus-theme-variable-pitch 
:foreground ,red-nuanced-fg)))
+    `(org-hide ((,class :foreground ,bg-main)))
+    `(org-indent ((,class :inherit (fixed-pitch org-hide))))
+    `(org-latex-and-related ((,class :foreground ,magenta-refine-fg)))
+    `(org-level-1 ((,class :inherit modus-theme-heading-1)))
+    `(org-level-2 ((,class :inherit modus-theme-heading-2)))
+    `(org-level-3 ((,class :inherit modus-theme-heading-3)))
+    `(org-level-4 ((,class :inherit modus-theme-heading-4)))
+    `(org-level-5 ((,class :inherit modus-theme-heading-5)))
+    `(org-level-6 ((,class :inherit modus-theme-heading-6)))
+    `(org-level-7 ((,class :inherit modus-theme-heading-7)))
+    `(org-level-8 ((,class :inherit modus-theme-heading-8)))
+    `(org-link ((,class :inherit button)))
+    `(org-list-dt ((,class :inherit bold)))
+    `(org-macro ((,class ,@(modus-themes--mixed-fonts)
+                         :background ,blue-nuanced-bg :foreground 
,magenta-alt-other)))
+    `(org-meta-line ((,class ,@(modus-themes--mixed-fonts) :foreground 
,fg-alt)))
+    `(org-mode-line-clock ((,class :foreground ,fg-main)))
+    `(org-mode-line-clock-overrun ((,class :inherit modus-theme-active-red)))
+    `(org-priority ((,class :foreground ,magenta)))
+    `(org-property-value ((,class ,@(modus-themes--mixed-fonts)
+                                  :foreground ,fg-special-cold)))
+    `(org-quote ((,class :inherit modus-theme-slant
+                         ,@(modus-themes--org-block bg-dim)
+                         :foreground ,fg-special-cold)))
+    `(org-scheduled ((,class :foreground ,magenta-alt)))
+    `(org-scheduled-previously ((,class :foreground ,yellow-alt-other)))
+    `(org-scheduled-today ((,class :foreground ,magenta-alt-other)))
+    `(org-sexp-date ((,class :inherit org-date)))
+    `(org-special-keyword ((,class ,@(modus-themes--mixed-fonts)
+                                   :foreground ,fg-alt)))
+    `(org-table ((,class ,@(modus-themes--mixed-fonts)
+                         :foreground ,fg-special-cold)))
+    `(org-table-header ((,class :inherit (fixed-pitch 
modus-theme-intense-neutral))))
+    `(org-tag ((,class :foreground ,magenta-nuanced-fg)))
+    `(org-tag-group ((,class :inherit bold :foreground ,cyan-nuanced-fg)))
+    `(org-target ((,class :underline t)))
+    `(org-time-grid ((,class :foreground ,fg-unfocused)))
+    `(org-todo ((,class :foreground ,red)))
+    `(org-upcoming-deadline ((,class :foreground ,red-alt-other)))
+    `(org-upcoming-distant-deadline ((,class :foreground ,red-nuanced-fg)))
+    `(org-verbatim ((,class ,@(modus-themes--mixed-fonts)
+                            :background ,bg-alt :foreground ,fg-special-calm)))
+    `(org-verse ((,class :inherit org-quote)))
+    `(org-warning ((,class :inherit bold :foreground ,red-alt-other)))
+;;;;; org-journal
+    `(org-journal-calendar-entry-face ((,class :inherit modus-theme-slant 
:foreground ,yellow-alt-other)))
+    `(org-journal-calendar-scheduled-face ((,class :inherit modus-theme-slant 
:foreground ,red-alt-other)))
+    `(org-journal-highlight ((,class :foreground ,magenta-alt)))
+;;;;; org-noter
+    `(org-noter-no-notes-exist-face ((,class :inherit bold :foreground 
,red-active)))
+    `(org-noter-notes-exist-face ((,class :inherit bold :foreground 
,green-active)))
+;;;;; org-pomodoro
+    `(org-pomodoro-mode-line ((,class :foreground ,red-active)))
+    `(org-pomodoro-mode-line-break ((,class :foreground ,cyan-active)))
+    `(org-pomodoro-mode-line-overtime ((,class :inherit bold :foreground 
,red-active)))
+;;;;; org-recur
+    `(org-recur ((,class :foreground ,magenta-active)))
+;;;;; org-roam
+    `(org-roam-link ((,class :inherit button
+                             ,@(modus-themes--link-color
+                                green green-faint))))
+    `(org-roam-link-current ((,class :inherit button
+                                     ,@(modus-themes--link-color
+                                        green-alt green-alt-faint))))
+    `(org-roam-link-invalid ((,class :inherit button
+                                     ,@(modus-themes--link-color
+                                        red red-faint))))
+    `(org-roam-link-shielded ((,class :inherit button
+                                      ,@(modus-themes--link-color
+                                         yellow yellow-faint))))
+    `(org-roam-tag ((,class :inherit italic :foreground ,fg-alt)))
+;;;;; org-superstar
+    `(org-superstar-item ((,class :foreground ,fg-main)))
+    `(org-superstar-leading ((,class :foreground ,fg-whitespace)))
+;;;;; org-table-sticky-header
+    `(org-table-sticky-header-face ((,class :inherit 
modus-theme-intense-neutral)))
+;;;;; org-tree-slide
+    `(org-tree-slide-header-overlay-face
+      ((,class :inherit (bold modus-theme-variable-pitch) :background ,bg-main
+               :foreground ,fg-special-cold :overline nil
+               ,@(modus-themes--scale modus-themes-scale-5))))
+;;;;; org-treescope
+    `(org-treescope-faces--markerinternal-midday ((,class :inherit 
modus-theme-intense-blue)))
+    `(org-treescope-faces--markerinternal-range ((,class :inherit 
modus-theme-special-mild)))
+;;;;; origami
+    `(origami-fold-header-face ((,class :background ,bg-dim :foreground 
,fg-dim :box t)))
+    `(origami-fold-replacement-face ((,class :background ,bg-alt :foreground 
,fg-alt)))
+;;;;; outline-mode
+    `(outline-1 ((,class :inherit modus-theme-heading-1)))
+    `(outline-2 ((,class :inherit modus-theme-heading-2)))
+    `(outline-3 ((,class :inherit modus-theme-heading-3)))
+    `(outline-4 ((,class :inherit modus-theme-heading-4)))
+    `(outline-5 ((,class :inherit modus-theme-heading-5)))
+    `(outline-6 ((,class :inherit modus-theme-heading-6)))
+    `(outline-7 ((,class :inherit modus-theme-heading-7)))
+    `(outline-8 ((,class :inherit modus-theme-heading-8)))
+;;;;; outline-minor-faces
+    `(outline-minor-0 ((,class :background ,bg-alt)))
+;;;;; package (M-x list-packages)
+    `(package-description ((,class :foreground ,fg-special-cold)))
+    `(package-help-section-name ((,class :inherit bold :foreground 
,magenta-alt-other)))
+    `(package-name ((,class :inherit button)))
+    `(package-status-avail-obso ((,class :inherit bold :foreground ,red)))
+    `(package-status-available ((,class :foreground ,fg-special-mild)))
+    `(package-status-built-in ((,class :foreground ,magenta)))
+    `(package-status-dependency ((,class :foreground ,magenta-alt-other)))
+    `(package-status-disabled ((,class :inherit modus-theme-subtle-red)))
+    `(package-status-external ((,class :foreground ,cyan-alt-other)))
+    `(package-status-held ((,class :foreground ,yellow-alt)))
+    `(package-status-incompat ((,class :inherit bold :foreground ,yellow)))
+    `(package-status-installed ((,class :foreground ,fg-special-warm)))
+    `(package-status-new ((,class :inherit bold :foreground ,green)))
+    `(package-status-unsigned ((,class :inherit bold :foreground ,red-alt)))
+;;;;; page-break-lines
+    `(page-break-lines ((,class :inherit default :foreground 
,fg-window-divider-outer)))
+;;;;; paradox
+    `(paradox-archive-face ((,class :foreground ,fg-special-mild)))
+    `(paradox-comment-face ((,class :inherit font-lock-comment-face)))
+    `(paradox-commit-tag-face ((,class :inherit modus-theme-refine-magenta 
:box t)))
+    `(paradox-description-face ((,class :foreground ,fg-special-cold)))
+    `(paradox-description-face-multiline ((,class :foreground 
,fg-special-cold)))
+    `(paradox-download-face ((,class :inherit modus-theme-bold :foreground 
,blue-alt-other)))
+    `(paradox-highlight-face ((,class :inherit modus-theme-bold :foreground 
,cyan-alt-other)))
+    `(paradox-homepage-button-face ((,class :foreground ,magenta-alt-other 
:underline t)))
+    `(paradox-mode-line-face ((,class :inherit bold :foreground ,cyan-active)))
+    `(paradox-name-face ((,class :foreground ,blue :underline t)))
+    `(paradox-star-face ((,class :foreground ,magenta)))
+    `(paradox-starred-face ((,class :foreground ,magenta-alt)))
+;;;;; paren-face
+    `(parenthesis ((,class :foreground ,fg-unfocused)))
+;;;;; parrot
+    `(parrot-rotate-rotation-highlight-face ((,class :inherit 
modus-theme-refine-magenta)))
+;;;;; pass
+    `(pass-mode-directory-face ((,class :inherit bold :foreground 
,fg-special-cold)))
+    `(pass-mode-entry-face ((,class :background ,bg-main :foreground 
,fg-main)))
+    `(pass-mode-header-face ((,class :foreground ,fg-special-warm)))
+;;;;; pdf-tools
+    `(pdf-links-read-link ((,class :background ,fg-main :foreground 
,magenta-intense-bg :inherit bold))) ; Foreground is background and vice versa
+    `(pdf-occur-document-face ((,class :inherit shadow)))
+    `(pdf-occur-page-face ((,class :inherit shadow)))
+;;;;; persp-mode
+    `(persp-face-lighter-buffer-not-in-persp ((,class :inherit 
modus-theme-intense-red)))
+    `(persp-face-lighter-default ((,class :inherit bold :foreground 
,blue-active)))
+    `(persp-face-lighter-nil-persp ((,class :inherit bold :foreground 
,fg-active)))
+;;;;; perspective
+    `(persp-selected-face ((,class :inherit bold :foreground ,blue-active)))
+;;;;; phi-grep
+    `(phi-grep-heading-face  ((,class :inherit bold :foreground ,red-alt
+                                      ,@(modus-themes--scale 
modus-themes-scale-4))))
+    `(phi-grep-line-number-face ((,class :foreground ,fg-special-warm)))
+    `(phi-grep-match-face ((,class :inherit modus-theme-special-calm)))
+    `(phi-grep-modified-face ((,class :inherit modus-theme-refine-yellow)))
+    `(phi-grep-overlay-face ((,class :inherit modus-theme-refine-blue)))
+;;;;; phi-search
+    `(phi-replace-preview-face ((,class :inherit modus-theme-intense-magenta)))
+    `(phi-search-failpart-face ((,class :inherit modus-theme-refine-red)))
+    `(phi-search-match-face ((,class :inherit modus-theme-refine-cyan)))
+    `(phi-search-selection-face ((,class :inherit (modus-theme-intense-green 
bold))))
+;;;;; pkgbuild-mode
+    `(pkgbuild-error-face ((,class :inherit modus-theme-lang-error)))
+;;;;; pomidor
+    `(pomidor-break-face ((,class :foreground ,blue-alt-other)))
+    `(pomidor-overwork-face ((,class :foreground ,red-alt-other)))
+    `(pomidor-skip-face ((,class :inherit modus-theme-slant :foreground 
,fg-alt)))
+    `(pomidor-work-face ((,class :foreground ,green-alt-other)))
+;;;;; popup
+    `(popup-face ((,class :background ,bg-alt :foreground ,fg-main)))
+    `(popup-isearch-match ((,class :inherit (modus-theme-refine-cyan bold))))
+    `(popup-menu-mouse-face ((,class :inherit modus-theme-intense-blue)))
+    `(popup-menu-selection-face ((,class :inherit (modus-theme-subtle-cyan 
bold))))
+    `(popup-scroll-bar-background-face ((,class :background ,bg-active)))
+    `(popup-scroll-bar-foreground-face ((,class :foreground ,fg-active)))
+    `(popup-summary-face ((,class :background ,bg-active :foreground 
,fg-inactive)))
+    `(popup-tip-face ((,class :inherit modus-theme-refine-yellow)))
+;;;;; powerline
+    `(powerline-active0 ((,class :background ,bg-main :foreground ,blue-faint 
:inverse-video t)))
+    `(powerline-active1 ((,class :background ,blue-nuanced-bg :foreground 
,blue-nuanced-fg)))
+    `(powerline-active2 ((,class :background ,bg-active :foreground 
,fg-active)))
+    `(powerline-inactive0 ((,class :background ,bg-special-cold :foreground 
,fg-special-cold)))
+    `(powerline-inactive1 ((,class :background ,bg-dim :foreground 
,fg-inactive)))
+    `(powerline-inactive2 ((,class :background ,bg-inactive :foreground 
,fg-inactive)))
+;;;;; powerline-evil
+    `(powerline-evil-base-face ((,class :background ,fg-main :foreground 
,bg-main)))
+    `(powerline-evil-emacs-face ((,class :inherit modus-theme-active-magenta)))
+    `(powerline-evil-insert-face ((,class :inherit modus-theme-active-green)))
+    `(powerline-evil-motion-face ((,class :inherit modus-theme-active-blue)))
+    `(powerline-evil-normal-face ((,class :background ,fg-alt :foreground 
,bg-main)))
+    `(powerline-evil-operator-face ((,class :inherit 
modus-theme-active-yellow)))
+    `(powerline-evil-replace-face ((,class :inherit modus-theme-active-red)))
+    `(powerline-evil-visual-face ((,class :inherit modus-theme-active-cyan)))
+;;;;; proced
+    `(proced-mark ((,class :inherit modus-theme-mark-symbol)))
+    `(proced-marked ((,class :inherit modus-theme-mark-alt)))
+    `(proced-sort-header ((,class :inherit bold :foreground ,fg-special-calm 
:underline t)))
+;;;;; prodigy
+    `(prodigy-green-face ((,class :foreground ,green)))
+    `(prodigy-red-face ((,class :foreground ,red)))
+    `(prodigy-yellow-face ((,class :foreground ,yellow)))
+;;;;; quick-peek
+    `(quick-peek-background-face ((,class :background ,bg-alt)))
+    `(quick-peek-border-face ((,class :background ,fg-window-divider-inner 
:height 1)))
+    `(quick-peek-padding-face ((,class :background ,bg-alt :height 0.15)))
+;;;;; racket-mode
+    `(racket-debug-break-face ((,class :inherit modus-theme-intense-red)))
+    `(racket-debug-locals-face ((,class :box (:line-width -1 :color nil)
+                                        :foreground ,green-alt-other)))
+    `(racket-debug-result-face ((,class :inherit bold :box (:line-width -1 
:color nil)
+                                        :foreground ,green)))
+    `(racket-here-string-face ((,class :foreground ,blue-alt)))
+    `(racket-keyword-argument-face ((,class :foreground ,red-alt)))
+    `(racket-logger-config-face ((,class :inherit modus-theme-slant 
:foreground ,fg-alt)))
+    `(racket-logger-debug-face ((,class :foreground ,blue-alt-other)))
+    `(racket-logger-info-face ((,class :foreground ,fg-lang-note)))
+    `(racket-logger-topic-face ((,class :inherit modus-theme-slant :foreground 
,magenta)))
+    `(racket-selfeval-face ((,class :foreground ,green-alt)))
+    `(racket-xp-error-face ((,class :inherit modus-theme-lang-error)))
+;;;;; rainbow-blocks
+    `(rainbow-blocks-depth-1-face ((,class :foreground ,magenta-alt-other)))
+    `(rainbow-blocks-depth-2-face ((,class :foreground ,blue)))
+    `(rainbow-blocks-depth-3-face ((,class :foreground ,magenta-alt)))
+    `(rainbow-blocks-depth-4-face ((,class :foreground ,green)))
+    `(rainbow-blocks-depth-5-face ((,class :foreground ,magenta)))
+    `(rainbow-blocks-depth-6-face ((,class :foreground ,cyan)))
+    `(rainbow-blocks-depth-7-face ((,class :foreground ,yellow)))
+    `(rainbow-blocks-depth-8-face ((,class :foreground ,cyan-alt)))
+    `(rainbow-blocks-depth-9-face ((,class :foreground ,red-alt)))
+    `(rainbow-blocks-unmatched-face ((,class :foreground ,red)))
+;;;;; rainbow-identifiers
+    `(rainbow-identifiers-identifier-1 ((,class :foreground ,green-alt-other)))
+    `(rainbow-identifiers-identifier-2 ((,class :foreground 
,magenta-alt-other)))
+    `(rainbow-identifiers-identifier-3 ((,class :foreground ,cyan-alt-other)))
+    `(rainbow-identifiers-identifier-4 ((,class :foreground 
,yellow-alt-other)))
+    `(rainbow-identifiers-identifier-5 ((,class :foreground ,blue-alt-other)))
+    `(rainbow-identifiers-identifier-6 ((,class :foreground ,green-alt)))
+    `(rainbow-identifiers-identifier-7 ((,class :foreground ,magenta-alt)))
+    `(rainbow-identifiers-identifier-8 ((,class :foreground ,cyan-alt)))
+    `(rainbow-identifiers-identifier-9 ((,class :foreground ,yellow-alt)))
+    `(rainbow-identifiers-identifier-10 ((,class :foreground ,green)))
+    `(rainbow-identifiers-identifier-11 ((,class :foreground ,magenta)))
+    `(rainbow-identifiers-identifier-12 ((,class :foreground ,cyan)))
+    `(rainbow-identifiers-identifier-13 ((,class :foreground ,yellow)))
+    `(rainbow-identifiers-identifier-14 ((,class :foreground ,blue-alt)))
+    `(rainbow-identifiers-identifier-15 ((,class :foreground ,red-alt)))
+;;;;; rainbow-delimiters
+    `(rainbow-delimiters-base-error-face ((,class :background ,red-subtle-bg 
:foreground ,fg-main)))
+    `(rainbow-delimiters-base-face ((,class :foreground ,fg-main)))
+    `(rainbow-delimiters-depth-1-face ((,class :foreground ,fg-main)))
+    `(rainbow-delimiters-depth-2-face ((,class :foreground ,magenta-intense)))
+    `(rainbow-delimiters-depth-3-face ((,class :foreground ,cyan-intense)))
+    `(rainbow-delimiters-depth-4-face ((,class :foreground ,orange-intense)))
+    `(rainbow-delimiters-depth-5-face ((,class :foreground ,purple-intense)))
+    `(rainbow-delimiters-depth-6-face ((,class :foreground ,green-intense)))
+    `(rainbow-delimiters-depth-7-face ((,class :foreground ,red-intense)))
+    `(rainbow-delimiters-depth-8-face ((,class :foreground ,blue-intense)))
+    `(rainbow-delimiters-depth-9-face ((,class :foreground ,yellow-intense)))
+    `(rainbow-delimiters-mismatched-face ((,class :inherit (bold 
modus-theme-refine-yellow))))
+    `(rainbow-delimiters-unmatched-face ((,class :inherit (bold 
modus-theme-refine-red))))
+;;;;; rcirc
+    `(rcirc-bright-nick ((,class :inherit bold :foreground ,magenta-alt)))
+    `(rcirc-dim-nick ((,class :inherit shadow)))
+    `(rcirc-my-nick ((,class :inherit bold :foreground ,magenta)))
+    `(rcirc-nick-in-message ((,class :foreground ,magenta-alt-other)))
+    `(rcirc-nick-in-message-full-line ((,class :inherit bold :foreground 
,fg-special-mild)))
+    `(rcirc-other-nick ((,class :inherit bold :foreground ,fg-special-cold)))
+    `(rcirc-prompt ((,class :inherit bold :foreground ,cyan-alt-other)))
+    `(rcirc-server ((,class :foreground ,fg-unfocused)))
+    `(rcirc-timestamp ((,class :foreground ,blue-nuanced-fg)))
+    `(rcirc-url ((,class :foreground ,blue :underline t)))
+;;;;; recursion-indicator
+    `(recursion-indicator-general ((,class :foreground ,blue-active)))
+    `(recursion-indicator-minibuffer ((,class :foreground ,red-active)))
+;;;;; regexp-builder (re-builder)
+    `(reb-match-0 ((,class :inherit modus-theme-refine-cyan)))
+    `(reb-match-1 ((,class :inherit modus-theme-subtle-magenta)))
+    `(reb-match-2 ((,class :inherit modus-theme-subtle-green)))
+    `(reb-match-3 ((,class :inherit modus-theme-refine-yellow)))
+    `(reb-regexp-grouping-backslash ((,class :inherit 
font-lock-regexp-grouping-backslash)))
+    `(reb-regexp-grouping-construct ((,class :inherit 
font-lock-regexp-grouping-construct)))
+;;;;; rg (rg.el)
+    `(rg-column-number-face ((,class :foreground ,magenta-alt-other)))
+    `(rg-context-face ((,class :foreground ,fg-unfocused)))
+    `(rg-error-face ((,class :inherit bold :foreground ,red)))
+    `(rg-file-tag-face ((,class :foreground ,fg-special-cold)))
+    `(rg-filename-face ((,class :inherit bold :foreground ,fg-special-cold)))
+    `(rg-line-number-face ((,class :foreground ,fg-special-warm)))
+    `(rg-literal-face ((,class :foreground ,blue-alt)))
+    `(rg-match-face ((,class :inherit modus-theme-special-calm)))
+    `(rg-regexp-face ((,class :foreground ,magenta-active)))
+    `(rg-toggle-off-face ((,class :inherit bold :foreground ,fg-inactive)))
+    `(rg-toggle-on-face ((,class :inherit bold :foreground ,cyan-active)))
+    `(rg-warning-face ((,class :inherit bold :foreground ,yellow)))
+;;;;; ripgrep
+    `(ripgrep-context-face ((,class :foreground ,fg-unfocused)))
+    `(ripgrep-error-face ((,class :inherit bold :foreground ,red)))
+    `(ripgrep-hit-face ((,class :foreground ,cyan)))
+    `(ripgrep-match-face ((,class :inherit modus-theme-special-calm)))
+;;;;; rmail
+    `(rmail-header-name ((,class :foreground ,cyan-alt-other)))
+    `(rmail-highlight ((,class :inherit bold :foreground ,magenta-alt)))
+;;;;; ruler-mode
+    `(ruler-mode-column-number ((,class :inherit ruler-mode-default 
:foreground ,fg-main)))
+    `(ruler-mode-comment-column ((,class :inherit ruler-mode-default 
:foreground ,red)))
+    `(ruler-mode-current-column ((,class :inherit ruler-mode-default 
:background ,blue-subtle-bg :foreground ,fg-main)))
+    `(ruler-mode-default ((,class :inherit default :background ,bg-alt 
:foreground ,fg-unfocused)))
+    `(ruler-mode-fill-column ((,class :inherit ruler-mode-default :foreground 
,green)))
+    `(ruler-mode-fringes ((,class :inherit ruler-mode-default :foreground 
,cyan)))
+    `(ruler-mode-goal-column ((,class :inherit ruler-mode-default :foreground 
,blue)))
+    `(ruler-mode-margins ((,class :inherit ruler-mode-default :foreground 
,bg-main)))
+    `(ruler-mode-pad ((,class :inherit ruler-mode-default :background 
,bg-active :foreground ,fg-inactive)))
+    `(ruler-mode-tab-stop ((,class :inherit ruler-mode-default :foreground 
,fg-special-warm)))
+;;;;; sallet
+    `(sallet-buffer-compressed ((,class :inherit italic :foreground 
,yellow-nuanced-fg)))
+    `(sallet-buffer-default-directory ((,class :foreground ,cyan-nuanced-fg)))
+    `(sallet-buffer-directory ((,class :foreground ,blue-nuanced-fg)))
+    `(sallet-buffer-help ((,class :foreground ,fg-special-cold)))
+    `(sallet-buffer-modified ((,class :inherit italic :foreground 
,yellow-alt-other)))
+    `(sallet-buffer-ordinary ((,class :foreground ,fg-main)))
+    `(sallet-buffer-read-only ((,class :foreground ,yellow-alt)))
+    `(sallet-buffer-size ((,class :foreground ,fg-special-calm)))
+    `(sallet-buffer-special ((,class :foreground ,magenta-alt-other)))
+    `(sallet-flx-match ((,class ,@(modus-themes--extra-completions
+                                   'modus-theme-subtle-cyan
+                                   'modus-theme-refine-cyan
+                                   'modus-theme-nuanced-cyan
+                                   cyan-alt-other))))
+    `(sallet-recentf-buffer-name ((,class :foreground ,blue-nuanced-fg)))
+    `(sallet-recentf-file-path ((,class :foreground ,fg-special-mild)))
+    `(sallet-regexp-match ((,class ,@(modus-themes--extra-completions
+                                      'modus-theme-subtle-magenta
+                                      'modus-theme-refine-magenta
+                                      'modus-theme-nuanced-magenta
+                                      magenta-alt-other))))
+    `(sallet-source-header ((,class :inherit bold :foreground ,red-alt
+                                    ,@(modus-themes--scale 
modus-themes-scale-4))))
+    `(sallet-substring-match ((,class ,@(modus-themes--extra-completions
+                                         'modus-theme-subtle-blue
+                                         'modus-theme-refine-blue
+                                         'modus-theme-nuanced-blue
+                                         blue-alt-other))))
+;;;;; selectrum
+;; NOTE 2021-02-22: The `selectrum-primary-highlight' and
+;; `selectrum-secondary-highlight' are deprecated upstream in favour of
+;; their selectrum-prescient counterparts.  We shall remove those faces
+;; from the themes once we are certain that they are no longer relevant.
+    `(selectrum-current-candidate
+      ((,class :inherit bold :foreground ,fg-main
+               :background ,@(pcase modus-themes-completions
+                               ('opinionated (list bg-active))
+                               (_ (list bg-inactive))))))
+    `(selectrum-primary-highlight
+      ((,class :inherit bold
+               ,@(modus-themes--standard-completions
+                  magenta-alt magenta-nuanced-bg
+                  magenta-refine-bg magenta-refine-fg))))
+    `(selectrum-secondary-highlight
+      ((,class :inherit bold
+               ,@(modus-themes--standard-completions
+                  cyan-alt-other cyan-nuanced-bg
+                  cyan-refine-bg cyan-refine-fg))))
+;;;;; selectrum-prescient
+    `(selectrum-prescient-primary-highlight
+      ((,class :inherit bold
+               ,@(modus-themes--standard-completions
+                  magenta-alt magenta-nuanced-bg
+                  magenta-refine-bg magenta-refine-fg))))
+    `(selectrum-prescient-secondary-highlight
+      ((,class :inherit bold
+               ,@(modus-themes--standard-completions
+                  cyan-alt-other cyan-nuanced-bg
+                  cyan-refine-bg cyan-refine-fg))))
+;;;;; semantic
+    `(semantic-complete-inline-face ((,class :foreground ,fg-special-warm 
:underline t)))
+    `(semantic-decoration-on-fileless-includes ((,class :inherit 
modus-theme-refine-green)))
+    `(semantic-decoration-on-private-members-face ((,class :inherit 
modus-theme-refine-cyan)))
+    `(semantic-decoration-on-protected-members-face ((,class :background 
,bg-dim)))
+    `(semantic-decoration-on-unknown-includes ((,class :inherit 
modus-theme-refine-red)))
+    `(semantic-decoration-on-unparsed-includes ((,class :inherit 
modus-theme-refine-yellow)))
+    `(semantic-highlight-edits-face ((,class :background ,bg-alt)))
+    `(semantic-highlight-func-current-tag-face ((,class :background ,bg-alt)))
+    `(semantic-idle-symbol-highlight ((,class :inherit 
modus-theme-special-mild)))
+    `(semantic-tag-boundary-face ((,class :overline ,blue-intense)))
+    `(semantic-unmatched-syntax-face ((,class :underline ,fg-lang-error)))
+;;;;; sesman
+    `(sesman-browser-button-face ((,class :foreground ,blue-alt-other 
:underline t)))
+    `(sesman-browser-highligh-face ((,class :inherit modus-theme-subtle-blue)))
+    `(sesman-buffer-face ((,class :foreground ,magenta)))
+    `(sesman-directory-face ((,class :inherit bold :foreground ,blue)))
+    `(sesman-project-face ((,class :inherit bold :foreground 
,magenta-alt-other)))
+;;;;; shell-script-mode
+    `(sh-heredoc ((,class :foreground ,blue-alt)))
+    `(sh-quoted-exec ((,class :inherit modus-theme-bold :foreground 
,magenta-alt)))
+;;;;; shortdoc
+    `(shortdoc-heading ((,class :inherit modus-theme-pseudo-header)))
+    `(shortdoc-section (())) ; remove the default's variable-pitch style
+;;;;; show-paren-mode
+    `(show-paren-match ((,class ,@(modus-themes--paren bg-paren-match
+                                                       bg-paren-match-intense)
+                                :foreground ,fg-main)))
+    `(show-paren-match-expression ((,class :inherit modus-theme-special-calm)))
+    `(show-paren-mismatch ((,class :inherit modus-theme-intense-red)))
+;;;;; shr
+    `(shr-abbreviation
+      ((,(append '((supports :underline (:style wave))) class)
+        :foreground ,fg-docstring :underline (:color ,fg-alt :style wave))
+       (,class :foreground ,fg-docstring :underline t)))
+    `(shr-selected-link ((,class :inherit modus-theme-subtle-cyan)))
+;;;;; side-notes
+    `(side-notes ((,class :background ,bg-dim :foreground ,fg-dim)))
+;;;;; sieve-mode
+    `(sieve-action-commands ((,class :inherit font-lock-builtin-face)))
+    `(sieve-control-commands ((,class :inherit font-lock-keyword-face)))
+    `(sieve-tagged-arguments ((,class :inherit font-lock-type-face)))
+    `(sieve-test-commands ((,class :inherit font-lock-function-name-face)))
+;;;;; skewer-mode
+    `(skewer-error-face ((,class :foreground ,red :underline t)))
+;;;;; smart-mode-line
+    `(sml/charging ((,class :foreground ,green-active)))
+    `(sml/discharging ((,class :foreground ,red-active)))
+    `(sml/filename ((,class :inherit bold :foreground ,blue-active)))
+    `(sml/folder ((,class :foreground ,fg-active)))
+    `(sml/git ((,class :inherit bold :foreground ,green-active)))
+    `(sml/global ((,class :foreground ,fg-active)))
+    `(sml/line-number ((,class :inherit sml/global)))
+    `(sml/minor-modes ((,class :inherit sml/global)))
+    `(sml/modes ((,class :inherit bold :foreground ,fg-active)))
+    `(sml/modified ((,class :inherit bold :foreground ,magenta-active)))
+    `(sml/mule-info ((,class :inherit sml/global)))
+    `(sml/name-filling ((,class :foreground ,yellow-active)))
+    `(sml/not-modified ((,class :inherit sml/global)))
+    `(sml/numbers-separator ((,class :inherit sml/global)))
+    `(sml/outside-modified ((,class :inherit modus-theme-intense-red)))
+    `(sml/position-percentage ((,class :inherit sml/global)))
+    `(sml/prefix ((,class :foreground ,green-active)))
+    `(sml/process ((,class :inherit sml/prefix)))
+    `(sml/projectile ((,class :inherit sml/git)))
+    `(sml/read-only ((,class :inherit bold :foreground ,cyan-active)))
+    `(sml/remote ((,class :inherit sml/global)))
+    `(sml/sudo ((,class :inherit modus-theme-subtle-red)))
+    `(sml/time ((,class :inherit sml/global)))
+    `(sml/vc ((,class :inherit sml/git)))
+    `(sml/vc-edited ((,class :inherit bold :foreground ,yellow-active)))
+;;;;; smartparens
+    `(sp-pair-overlay-face ((,class :inherit modus-theme-special-warm)))
+    `(sp-show-pair-enclosing ((,class :inherit modus-theme-special-mild)))
+    `(sp-show-pair-match-face ((,class ,@(modus-themes--paren bg-paren-match
+                                                              
bg-paren-match-intense)
+                                       :foreground ,fg-main)))
+    `(sp-show-pair-mismatch-face ((,class :inherit modus-theme-intense-red)))
+    `(sp-wrap-overlay-closing-pair ((,class :inherit sp-pair-overlay-face)))
+    `(sp-wrap-overlay-face ((,class :inherit sp-pair-overlay-face)))
+    `(sp-wrap-overlay-opening-pair ((,class :inherit sp-pair-overlay-face)))
+    `(sp-wrap-tag-overlay-face ((,class :inherit sp-pair-overlay-face)))
+;;;;; smerge
+    `(smerge-base ((,class :inherit modus-theme-diff-changed)))
+    `(smerge-lower ((,class :inherit modus-theme-diff-added)))
+    `(smerge-markers ((,class :background ,bg-diff-neutral-2 :foreground 
,fg-diff-neutral-2)))
+    `(smerge-refined-added ((,class :inherit modus-theme-diff-refine-added)))
+    `(smerge-refined-changed (()))
+    `(smerge-refined-removed ((,class :inherit 
modus-theme-diff-refine-removed)))
+    `(smerge-upper ((,class :inherit modus-theme-diff-removed)))
+;;;;; solaire
+    `(solaire-default-face ((,class :inherit default :background ,bg-alt 
:foreground ,fg-dim)))
+    `(solaire-line-number-face ((,class :inherit solaire-default-face 
:foreground ,fg-unfocused)))
+    `(solaire-hl-line-face ((,class :background ,bg-active)))
+    `(solaire-org-hide-face ((,class :background ,bg-alt :foreground ,bg-alt)))
+;;;;; spaceline
+    `(spaceline-evil-emacs ((,class :inherit modus-theme-active-magenta)))
+    `(spaceline-evil-insert ((,class :inherit modus-theme-active-green)))
+    `(spaceline-evil-motion ((,class :inherit modus-theme-active-blue)))
+    `(spaceline-evil-normal ((,class :background ,fg-alt :foreground ,bg-alt)))
+    `(spaceline-evil-replace ((,class :inherit modus-theme-active-red)))
+    `(spaceline-evil-visual ((,class :inherit modus-theme-active-cyan)))
+    `(spaceline-flycheck-error ((,class :foreground ,red-active)))
+    `(spaceline-flycheck-info ((,class :foreground ,cyan-active)))
+    `(spaceline-flycheck-warning ((,class :foreground ,yellow-active)))
+    `(spaceline-highlight-face ((,class :inherit modus-theme-fringe-blue)))
+    `(spaceline-modified ((,class :inherit modus-theme-fringe-magenta)))
+    `(spaceline-python-venv ((,class :foreground ,magenta-active)))
+    `(spaceline-read-only ((,class :inherit modus-theme-fringe-red)))
+    `(spaceline-unmodified ((,class :inherit modus-theme-fringe-cyan)))
+;;;;; speedbar
+    `(speedbar-button-face ((,class :inherit button)))
+    `(speedbar-directory-face ((,class :inherit bold :foreground ,blue)))
+    `(speedbar-file-face ((,class :foreground ,fg-main)))
+    `(speedbar-highlight-face ((,class :inherit modus-theme-subtle-blue)))
+    `(speedbar-selected-face ((,class :inherit bold :foreground ,cyan)))
+    `(speedbar-separator-face ((,class :inherit modus-theme-intense-neutral)))
+    `(speedbar-tag-face ((,class :foreground ,yellow-alt-other)))
+;;;;; spell-fu
+    `(spell-fu-incorrect-face ((,class :inherit modus-theme-lang-error)))
+;;;;; spray
+    `(spray-accent-face ((,class :foreground ,red-intense)))
+    `(spray-base-face ((,class :inherit default :foreground ,fg-special-cold)))
+;;;;; stripes
+    `(stripes ((,class :inherit modus-theme-hl-line)))
+;;;;; success
+    `(suggest-heading ((,class :inherit bold :foreground ,yellow-alt-other)))
+;;;;; switch-window
+    `(switch-window-background ((,class :background ,bg-dim)))
+    `(switch-window-label ((,class :height 3.0 :foreground ,blue-intense)))
+;;;;; swiper
+    `(swiper-background-match-face-1 ((,class :inherit 
modus-theme-subtle-neutral)))
+    `(swiper-background-match-face-2 ((,class :inherit 
modus-theme-refine-cyan)))
+    `(swiper-background-match-face-3 ((,class :inherit 
modus-theme-refine-magenta)))
+    `(swiper-background-match-face-4 ((,class :inherit 
modus-theme-refine-yellow)))
+    `(swiper-line-face ((,class :inherit modus-theme-special-cold)))
+    `(swiper-match-face-1 ((,class :inherit (bold 
modus-theme-intense-neutral))))
+    `(swiper-match-face-2 ((,class :inherit (bold modus-theme-intense-green))))
+    `(swiper-match-face-3 ((,class :inherit (bold modus-theme-intense-blue))))
+    `(swiper-match-face-4 ((,class :inherit (bold modus-theme-intense-red))))
+;;;;; swoop
+    `(swoop-face-header-format-line ((,class :inherit bold :foreground ,red-alt
+                                             ,@(modus-themes--scale 
modus-themes-scale-3))))
+    `(swoop-face-line-buffer-name ((,class :inherit bold :foreground ,blue-alt
+                                           ,@(modus-themes--scale 
modus-themes-scale-4))))
+    `(swoop-face-line-number ((,class :foreground ,fg-special-warm)))
+    `(swoop-face-target-line ((,class :inherit modus-theme-intense-blue 
:extend t)))
+    `(swoop-face-target-words ((,class :inherit modus-theme-refine-cyan)))
+;;;;; sx
+    `(sx-inbox-item-type ((,class :foreground ,magenta-alt-other)))
+    `(sx-inbox-item-type-unread ((,class :inherit (sx-inbox-item-type bold))))
+    `(sx-question-list-answers ((,class :foreground ,green)))
+    `(sx-question-list-answers-accepted ((,class :box t :foreground ,green)))
+    `(sx-question-list-bounty ((,class :inherit bold :background ,bg-alt 
:foreground ,yellow)))
+    `(sx-question-list-date ((,class :foreground ,fg-special-cold)))
+    `(sx-question-list-favorite ((,class :inherit bold :foreground 
,fg-special-warm)))
+    `(sx-question-list-parent ((,class :foreground ,fg-main)))
+    `(sx-question-list-read-question ((,class :inherit shadow)))
+    `(sx-question-list-score ((,class :foreground ,fg-special-mild)))
+    `(sx-question-list-score-upvoted ((,class :inherit (sx-question-list-score 
bold))))
+    `(sx-question-list-unread-question ((,class :inherit bold :foreground 
,fg-main)))
+    `(sx-question-mode-accepted ((,class :inherit bold :height 1.3 :foreground 
,green)))
+    `(sx-question-mode-closed ((,class :inherit modus-theme-active-yellow :box 
(:line-width 2 :color nil))))
+    `(sx-question-mode-closed-reason ((,class :box (:line-width 2 :color nil) 
:foreground ,fg-main)))
+    `(sx-question-mode-content-face ((,class :background ,bg-dim)))
+    `(sx-question-mode-date ((,class :foreground ,blue)))
+    `(sx-question-mode-header ((,class :inherit bold :foreground ,cyan)))
+    `(sx-question-mode-kbd-tag ((,class :inherit bold :height 0.9 :box 
(:line-width 3 :color ,fg-main :style released-button) :foreground ,fg-main)))
+    `(sx-question-mode-score ((,class :foreground ,fg-dim)))
+    `(sx-question-mode-score-downvoted ((,class :foreground ,yellow)))
+    `(sx-question-mode-score-upvoted ((,class :inherit bold :foreground 
,magenta)))
+    `(sx-question-mode-title ((,class :inherit bold :foreground ,fg-main)))
+    `(sx-question-mode-title-comments ((,class :inherit bold :foreground 
,fg-alt)))
+    `(sx-tag ((,class :foreground ,magenta-alt)))
+    `(sx-user-name ((,class :foreground ,blue-alt)))
+    `(sx-user-reputation ((,class :inherit shadow)))
+;;;;; symbol-overlay
+    `(symbol-overlay-default-face ((,class :inherit modus-theme-special-warm)))
+    `(symbol-overlay-face-1 ((,class :inherit modus-theme-intense-blue)))
+    `(symbol-overlay-face-2 ((,class :inherit modus-theme-refine-magenta)))
+    `(symbol-overlay-face-3 ((,class :inherit modus-theme-intense-yellow)))
+    `(symbol-overlay-face-4 ((,class :inherit modus-theme-intense-magenta)))
+    `(symbol-overlay-face-5 ((,class :inherit modus-theme-intense-red)))
+    `(symbol-overlay-face-6 ((,class :inherit modus-theme-refine-red)))
+    `(symbol-overlay-face-7 ((,class :inherit modus-theme-intense-cyan)))
+    `(symbol-overlay-face-8 ((,class :inherit modus-theme-refine-cyan)))
+;;;;; syslog-mode
+    `(syslog-debug ((,class :inherit bold :foreground ,cyan-alt-other)))
+    `(syslog-error ((,class :inherit bold :foreground ,red)))
+    `(syslog-file ((,class :inherit bold :foreground ,fg-special-cold)))
+    `(syslog-hide ((,class :background ,bg-main :foreground ,fg-main)))
+    `(syslog-hour ((,class :inherit bold :foreground ,magenta-alt-other)))
+    `(syslog-info ((,class :inherit bold :foreground ,blue-alt-other)))
+    `(syslog-ip ((,class :inherit bold :foreground ,fg-special-mild :underline 
t)))
+    `(syslog-su ((,class :inherit bold :foreground ,red-alt)))
+    `(syslog-warn ((,class :inherit bold :foreground ,yellow)))
+;;;;; tab-bar-mode
+    `(tab-bar ((,class ,@(modus-themes--variable-pitch-ui)
+                       :background ,bg-tab-bar :foreground ,fg-main)))
+    `(tab-bar-tab ((,class :inherit bold :box (:line-width 2 :color 
,bg-tab-active)
+                           :background ,bg-tab-active :foreground ,fg-main)))
+    `(tab-bar-tab-inactive ((,class :box (:line-width 2 :color 
,bg-tab-inactive)
+                                    :background ,bg-tab-inactive :foreground 
,fg-dim)))
+;;;;; tab-line-mode
+    `(tab-line ((,class ,@(modus-themes--variable-pitch-ui)
+                        :height 0.95 :background ,bg-tab-bar :foreground 
,fg-main)))
+    `(tab-line-close-highlight ((,class :foreground ,red)))
+    `(tab-line-highlight ((,class :background ,blue-subtle-bg :foreground 
,fg-dim)))
+    `(tab-line-tab ((,class :inherit bold :box (:line-width 2 :color 
,bg-tab-active)
+                            :background ,bg-tab-active :foreground ,fg-main)))
+    `(tab-line-tab-current ((,class :inherit tab-line-tab)))
+    `(tab-line-tab-inactive ((,class :box (:line-width 2 :color 
,bg-tab-inactive)
+                                     :background ,bg-tab-inactive :foreground 
,fg-dim)))
+    `(tab-line-tab-inactive-alternate ((,class :box (:line-width 2 :color 
,bg-tab-inactive-alt)
+                                               :background 
,bg-tab-inactive-alt :foreground ,fg-main)))
+;;;;; table (built-in table.el)
+    `(table-cell ((,class :background ,blue-nuanced-bg)))
+;;;;; telephone-line
+    `(telephone-line-accent-active ((,class :background ,fg-inactive 
:foreground ,bg-inactive)))
+    `(telephone-line-accent-inactive ((,class :background ,bg-active 
:foreground ,fg-active)))
+    `(telephone-line-error ((,class :inherit bold :foreground ,red-active)))
+    `(telephone-line-evil ((,class :foreground ,fg-main)))
+    `(telephone-line-evil-emacs ((,class :inherit telephone-line-evil 
:background ,magenta-intense-bg)))
+    `(telephone-line-evil-insert ((,class :inherit telephone-line-evil 
:background ,green-intense-bg)))
+    `(telephone-line-evil-motion ((,class :inherit telephone-line-evil 
:background ,yellow-intense-bg)))
+    `(telephone-line-evil-normal ((,class :inherit telephone-line-evil 
:background ,bg-alt)))
+    `(telephone-line-evil-operator ((,class :inherit telephone-line-evil 
:background ,yellow-subtle-bg)))
+    `(telephone-line-evil-replace ((,class :inherit telephone-line-evil 
:background ,red-intense-bg)))
+    `(telephone-line-evil-visual ((,class :inherit telephone-line-evil 
:background ,cyan-intense-bg)))
+    `(telephone-line-projectile ((,class :foreground ,cyan-active)))
+    `(telephone-line-unimportant ((,class :foreground ,fg-inactive)))
+    `(telephone-line-warning ((,class :inherit bold :foreground 
,yellow-active)))
+;;;;; terraform-mode
+    `(terraform--resource-name-face ((,class ,@(modus-themes--syntax-string
+                                                magenta-alt-other 
magenta-alt-other-faint
+                                                red-alt red-alt))))
+    `(terraform--resource-type-face ((,class ,@(modus-themes--syntax-string
+                                                green green-faint
+                                                blue-alt magenta-alt))))
+;;;;; term
+    `(term ((,class :background ,bg-main :foreground ,fg-main)))
+    `(term-bold ((,class :inherit bold)))
+    `(term-color-black ((,class :background "gray35" :foreground "gray35")))
+    `(term-color-blue ((,class :background ,blue :foreground ,blue)))
+    `(term-color-cyan ((,class :background ,cyan :foreground ,cyan)))
+    `(term-color-green ((,class :background ,green :foreground ,green)))
+    `(term-color-magenta ((,class :background ,magenta :foreground ,magenta)))
+    `(term-color-red ((,class :background ,red :foreground ,red)))
+    `(term-color-white ((,class :background "gray65" :foreground "gray65")))
+    `(term-color-yellow ((,class :background ,yellow :foreground ,yellow)))
+    `(term-underline ((,class :underline t)))
+;;;;; tomatinho
+    `(tomatinho-ok-face ((,class :foreground ,blue-intense)))
+    `(tomatinho-pause-face ((,class :foreground ,yellow-intense)))
+    `(tomatinho-reset-face ((,class :inherit shadow)))
+;;;;; transient
+    `(transient-active-infix ((,class :inherit modus-theme-special-mild)))
+    `(transient-amaranth ((,class :inherit bold :foreground ,yellow)))
+    `(transient-argument ((,class :inherit bold :foreground ,red-alt)))
+    `(transient-blue ((,class :inherit bold :foreground ,blue)))
+    `(transient-disabled-suffix ((,class :inherit modus-theme-intense-red)))
+    `(transient-enabled-suffix ((,class :inherit modus-theme-intense-green)))
+    `(transient-heading ((,class :inherit bold :foreground ,fg-main)))
+    `(transient-inactive-argument ((,class :inherit shadow)))
+    `(transient-inactive-value ((,class :inherit shadow)))
+    `(transient-key ((,class :inherit bold :foreground ,blue)))
+    `(transient-mismatched-key ((,class :underline t)))
+    `(transient-nonstandard-key ((,class :underline t)))
+    `(transient-pink ((,class :inherit bold :foreground ,magenta)))
+    `(transient-red ((,class :inherit bold :foreground ,red-intense)))
+    `(transient-teal ((,class :inherit bold :foreground ,cyan-alt-other)))
+    `(transient-unreachable ((,class :foreground ,fg-unfocused)))
+    `(transient-unreachable-key ((,class :foreground ,fg-unfocused)))
+    `(transient-value ((,class :inherit bold :foreground ,magenta-alt-other)))
+;;;;; trashed
+    `(trashed-deleted ((,class :inherit modus-theme-mark-del)))
+    `(trashed-directory ((,class :foreground ,blue)))
+    `(trashed-mark ((,class :inherit modus-theme-mark-symbol)))
+    `(trashed-marked ((,class :inherit modus-theme-mark-alt)))
+    `(trashed-restored ((,class :inherit modus-theme-mark-sel)))
+    `(trashed-symlink ((,class :inherit button
+                               ,@(modus-themes--link-color
+                                  cyan-alt cyan-alt-faint))))
+;;;;; treemacs
+    `(treemacs-directory-collapsed-face ((,class :foreground ,magenta-alt)))
+    `(treemacs-directory-face ((,class :inherit dired-directory)))
+    `(treemacs-file-face ((,class :foreground ,fg-main)))
+    `(treemacs-fringe-indicator-face ((,class :foreground ,fg-main)))
+    `(treemacs-git-added-face ((,class :foreground ,green-intense)))
+    `(treemacs-git-conflict-face ((,class :inherit (modus-theme-intense-red 
bold))))
+    `(treemacs-git-ignored-face ((,class :inherit shadow)))
+    `(treemacs-git-modified-face ((,class :foreground ,yellow-alt-other)))
+    `(treemacs-git-renamed-face ((,class :foreground ,cyan-alt-other)))
+    `(treemacs-git-unmodified-face ((,class :foreground ,fg-main)))
+    `(treemacs-git-untracked-face ((,class :foreground ,red-alt-other)))
+    `(treemacs-help-column-face ((,class :inherit modus-theme-bold :foreground 
,magenta-alt-other :underline t)))
+    `(treemacs-help-title-face ((,class :foreground ,blue-alt-other)))
+    `(treemacs-on-failure-pulse-face ((,class :inherit 
modus-theme-intense-red)))
+    `(treemacs-on-success-pulse-face ((,class :inherit 
modus-theme-intense-green)))
+    `(treemacs-root-face ((,class :inherit bold :foreground ,blue-alt-other 
:height 1.2 :underline t)))
+    `(treemacs-root-remote-disconnected-face ((,class :inherit 
treemacs-root-remote-face :foreground ,yellow)))
+    `(treemacs-root-remote-face ((,class :inherit treemacs-root-face 
:foreground ,magenta)))
+    `(treemacs-root-remote-unreadable-face ((,class :inherit 
treemacs-root-unreadable-face)))
+    `(treemacs-root-unreadable-face ((,class :inherit treemacs-root-face 
:strike-through t)))
+    `(treemacs-tags-face ((,class :foreground ,blue-alt)))
+    `(treemacs-tags-face ((,class :foreground ,magenta-alt)))
+;;;;; tty-menu
+    `(tty-menu-disabled-face ((,class :background ,bg-alt :foreground 
,fg-alt)))
+    `(tty-menu-enabled-face ((,class :inherit bold :background ,bg-alt 
:foreground ,fg-main)))
+    `(tty-menu-selected-face ((,class :inherit modus-theme-intense-blue)))
+;;;;; tuareg
+    `(caml-types-def-face ((,class :inherit modus-theme-subtle-red)))
+    `(caml-types-expr-face ((,class :inherit modus-theme-subtle-green)))
+    `(caml-types-occ-face ((,class :inherit modus-theme-subtle-green)))
+    `(caml-types-scope-face ((,class :inherit modus-theme-subtle-blue)))
+    `(caml-types-typed-face ((,class :inherit modus-theme-subtle-magenta)))
+    `(tuareg-font-double-semicolon-face ((,class :inherit 
font-lock-preprocessor-face)))
+    `(tuareg-font-lock-attribute-face ((,class :inherit 
font-lock-function-name-face)))
+    `(tuareg-font-lock-constructor-face ((,class :foreground ,fg-main)))
+    `(tuareg-font-lock-error-face ((,class :inherit (modus-theme-intense-red 
bold))))
+    `(tuareg-font-lock-extension-node-face ((,class :background ,bg-alt 
:foreground ,magenta)))
+    `(tuareg-font-lock-governing-face ((,class :inherit bold :foreground 
,fg-main)))
+    `(tuareg-font-lock-infix-extension-node-face ((,class :inherit 
font-lock-function-name-face)))
+    `(tuareg-font-lock-interactive-directive-face ((,class :foreground 
,fg-special-cold)))
+    `(tuareg-font-lock-interactive-error-face ((,class :inherit error)))
+    `(tuareg-font-lock-interactive-output-face ((,class :inherit 
font-lock-constant-face)))
+    `(tuareg-font-lock-label-face ((,class :inherit font-lock-type-face)))
+    `(tuareg-font-lock-line-number-face ((,class :foreground 
,fg-special-warm)))
+    `(tuareg-font-lock-module-face ((,class :inherit font-lock-builtin-face)))
+    `(tuareg-font-lock-multistage-face ((,class :inherit bold :background 
,bg-alt :foreground ,blue)))
+    `(tuareg-font-lock-operator-face ((,class :inherit 
font-lock-preprocessor-face)))
+    `(tuareg-opam-error-face ((,class :inherit error)))
+    `(tuareg-opam-pkg-variable-name-face ((,class :inherit 
font-lock-variable-name-face)))
+;;;;; typescript
+    `(typescript-jsdoc-tag ((,class :inherit modus-theme-slant :foreground 
,fg-special-mild)))
+    `(typescript-jsdoc-type ((,class :inherit modus-theme-slant :foreground 
,fg-special-calm)))
+    `(typescript-jsdoc-value ((,class :inherit modus-theme-slant :foreground 
,fg-special-cold)))
+;;;;; undo-tree
+    `(undo-tree-visualizer-active-branch-face ((,class :inherit bold 
:foreground ,fg-main)))
+    `(undo-tree-visualizer-current-face ((,class :foreground ,blue-intense)))
+    `(undo-tree-visualizer-default-face ((,class :inherit shadow)))
+    `(undo-tree-visualizer-register-face ((,class :foreground 
,magenta-intense)))
+    `(undo-tree-visualizer-unmodified-face ((,class :foreground 
,green-intense)))
+;;;;; vc (vc-dir.el, vc-hooks.el)
+    `(vc-dir-directory ((,class :foreground ,blue)))
+    `(vc-dir-file ((,class :foreground ,fg-main)))
+    `(vc-dir-header ((,class :foreground ,cyan-alt-other)))
+    `(vc-dir-header-value ((,class :foreground ,magenta-alt-other)))
+    `(vc-dir-mark-indicator ((,class :foreground ,blue-alt-other)))
+    `(vc-dir-status-edited ((,class :foreground ,yellow)))
+    `(vc-dir-status-ignored ((,class :foreground ,fg-unfocused)))
+    `(vc-dir-status-up-to-date ((,class :foreground ,cyan)))
+    `(vc-dir-status-warning ((,class :foreground ,red)))
+    `(vc-conflict-state ((,class :inherit modus-theme-slant :foreground 
,red-active)))
+    `(vc-edited-state ((,class :foreground ,yellow-active)))
+    `(vc-locally-added-state ((,class :foreground ,cyan-active)))
+    `(vc-locked-state ((,class :foreground ,blue-active)))
+    `(vc-missing-state ((,class :inherit modus-theme-slant :foreground 
,magenta-active)))
+    `(vc-needs-update-state ((,class :inherit modus-theme-slant :foreground 
,green-active)))
+    `(vc-removed-state ((,class :foreground ,red-active)))
+    `(vc-state-base ((,class :foreground ,fg-active)))
+    `(vc-up-to-date-state ((,class :foreground ,fg-special-cold)))
+;;;;; vdiff
+    `(vdiff-addition-face ((,class :inherit modus-theme-diff-added)))
+    `(vdiff-change-face ((,class :inherit modus-theme-diff-changed)))
+    `(vdiff-closed-fold-face ((,class :background ,bg-diff-neutral-1 
:foreground ,fg-diff-neutral-1)))
+    `(vdiff-refine-added ((,class :inherit modus-theme-diff-refine-added)))
+    `(vdiff-refine-changed ((,class :inherit modus-theme-diff-refine-changed)))
+    `(vdiff-subtraction-face ((,class :inherit modus-theme-diff-removed)))
+    `(vdiff-target-face ((,class :inherit modus-theme-intense-blue)))
+;;;;; vimish-fold
+    `(vimish-fold-fringe ((,class :foreground ,cyan-active)))
+    `(vimish-fold-mouse-face ((,class :inherit modus-theme-intense-blue)))
+    `(vimish-fold-overlay ((,class :background ,bg-alt :foreground 
,fg-special-cold)))
+;;;;; visible-mark
+    `(visible-mark-active ((,class :background ,blue-intense-bg)))
+    `(visible-mark-face1 ((,class :background ,cyan-intense-bg)))
+    `(visible-mark-face2 ((,class :background ,yellow-intense-bg)))
+    `(visible-mark-forward-face1 ((,class :background ,magenta-intense-bg)))
+    `(visible-mark-forward-face2 ((,class :background ,green-intense-bg)))
+;;;;; visual-regexp
+    `(vr/group-0 ((,class :inherit modus-theme-intense-blue)))
+    `(vr/group-1 ((,class :inherit modus-theme-intense-magenta)))
+    `(vr/group-2 ((,class :inherit modus-theme-intense-green)))
+    `(vr/match-0 ((,class :inherit modus-theme-refine-yellow)))
+    `(vr/match-1 ((,class :inherit modus-theme-refine-yellow)))
+    `(vr/match-separator-face ((,class :inherit (modus-theme-intense-neutral 
bold))))
+;;;;; volatile-highlights
+    `(vhl/default-face ((,class :background ,bg-alt :foreground 
,blue-nuanced-fg :extend t)))
+;;;;; vterm
+    `(vterm-color-black ((,class :background "gray35" :foreground "gray35")))
+    `(vterm-color-blue ((,class :background ,blue :foreground ,blue)))
+    `(vterm-color-cyan ((,class :background ,cyan :foreground ,cyan)))
+    `(vterm-color-default ((,class :background ,bg-main :foreground ,fg-main)))
+    `(vterm-color-green ((,class :background ,green :foreground ,green)))
+    `(vterm-color-inverse-video ((,class :background ,bg-main :inverse-video 
t)))
+    `(vterm-color-magenta ((,class :background ,magenta :foreground ,magenta)))
+    `(vterm-color-red ((,class :background ,red :foreground ,red)))
+    `(vterm-color-underline ((,class :foreground ,fg-special-warm :underline 
t)))
+    `(vterm-color-white ((,class :background "gray65" :foreground "gray65")))
+    `(vterm-color-yellow ((,class :background ,yellow :foreground ,yellow)))
+;;;;; wcheck-mode
+    `(wcheck-default-face ((,class :foreground ,red :underline t)))
+;;;;; web-mode
+    `(web-mode-annotation-face ((,class :inherit web-mode-comment-face)))
+    `(web-mode-annotation-html-face ((,class :inherit web-mode-comment-face)))
+    `(web-mode-annotation-tag-face ((,class :inherit web-mode-comment-face 
:underline t)))
+    `(web-mode-block-attr-name-face ((,class :inherit 
font-lock-constant-face)))
+    `(web-mode-block-attr-value-face ((,class :inherit font-lock-type-face)))
+    `(web-mode-block-comment-face ((,class :inherit web-mode-comment-face)))
+    `(web-mode-block-control-face ((,class :inherit font-lock-builtin-face)))
+    `(web-mode-block-delimiter-face ((,class :foreground ,fg-main)))
+    `(web-mode-block-face ((,class :background ,bg-dim)))
+    `(web-mode-block-string-face ((,class :inherit web-mode-string-face)))
+    `(web-mode-bold-face ((,class :inherit bold)))
+    `(web-mode-builtin-face ((,class :inherit font-lock-builtin-face)))
+    `(web-mode-comment-face ((,class :inherit font-lock-comment-face)))
+    `(web-mode-comment-keyword-face ((,class :inherit font-lock-warning-face)))
+    `(web-mode-constant-face ((,class :inherit font-lock-constant-face)))
+    `(web-mode-css-at-rule-face ((,class :inherit font-lock-constant-face)))
+    `(web-mode-css-color-face ((,class :inherit font-lock-builtin-face)))
+    `(web-mode-css-comment-face ((,class :inherit web-mode-comment-face)))
+    `(web-mode-css-function-face ((,class :inherit font-lock-builtin-face)))
+    `(web-mode-css-priority-face ((,class :inherit font-lock-warning-face)))
+    `(web-mode-css-property-name-face ((,class :inherit 
font-lock-keyword-face)))
+    `(web-mode-css-pseudo-class-face ((,class :inherit font-lock-doc-face)))
+    `(web-mode-css-selector-face ((,class :inherit font-lock-keyword-face)))
+    `(web-mode-css-string-face ((,class :inherit web-mode-string-face)))
+    `(web-mode-css-variable-face ((,class :foreground ,fg-special-warm)))
+    `(web-mode-current-column-highlight-face ((,class :background ,bg-alt)))
+    `(web-mode-current-element-highlight-face ((,class :inherit 
modus-theme-special-mild)))
+    `(web-mode-doctype-face ((,class :inherit modus-theme-slant :foreground 
,fg-special-cold)))
+    `(web-mode-error-face ((,class :inherit modus-theme-intense-red)))
+    `(web-mode-filter-face ((,class :inherit font-lock-function-name-face)))
+    `(web-mode-folded-face ((,class :underline t)))
+    `(web-mode-function-call-face ((,class :inherit 
font-lock-function-name-face)))
+    `(web-mode-function-name-face ((,class :inherit 
font-lock-function-name-face)))
+    `(web-mode-html-attr-custom-face ((,class :inherit 
font-lock-variable-name-face)))
+    `(web-mode-html-attr-engine-face ((,class :foreground ,fg-main)))
+    `(web-mode-html-attr-equal-face ((,class :foreground ,fg-main)))
+    `(web-mode-html-attr-name-face ((,class :inherit 
font-lock-variable-name-face)))
+    `(web-mode-html-attr-value-face ((,class :inherit 
font-lock-constant-face)))
+    `(web-mode-html-entity-face ((,class :inherit 
font-lock-negation-char-face)))
+    `(web-mode-html-tag-bracket-face ((,class :foreground ,fg-dim)))
+    `(web-mode-html-tag-custom-face ((,class :inherit 
font-lock-function-name-face)))
+    `(web-mode-html-tag-face ((,class :inherit font-lock-function-name-face)))
+    `(web-mode-html-tag-namespaced-face ((,class :inherit 
font-lock-builtin-face)))
+    `(web-mode-html-tag-unclosed-face ((,class :inherit error :underline t)))
+    `(web-mode-inlay-face ((,class :background ,bg-alt)))
+    `(web-mode-italic-face ((,class :inherit italic)))
+    `(web-mode-javascript-comment-face ((,class :inherit 
web-mode-comment-face)))
+    `(web-mode-javascript-string-face ((,class :inherit web-mode-string-face)))
+    `(web-mode-json-comment-face ((,class :inherit web-mode-comment-face)))
+    `(web-mode-json-context-face ((,class :inherit font-lock-builtin-face)))
+    `(web-mode-json-key-face ((,class :foreground ,blue-nuanced-fg)))
+    `(web-mode-json-string-face ((,class :inherit web-mode-string-face)))
+    `(web-mode-jsx-depth-1-face ((,class :background ,blue-intense-bg 
:foreground ,fg-main)))
+    `(web-mode-jsx-depth-2-face ((,class :background ,blue-subtle-bg 
:foreground ,fg-main)))
+    `(web-mode-jsx-depth-3-face ((,class :background ,bg-special-cold 
:foreground ,fg-special-cold)))
+    `(web-mode-jsx-depth-4-face ((,class :background ,bg-alt :foreground 
,blue-refine-fg)))
+    `(web-mode-jsx-depth-5-face ((,class :background ,bg-alt :foreground 
,blue-nuanced-fg)))
+    `(web-mode-keyword-face ((,class :inherit :inherit 
font-lock-keyword-face)))
+    `(web-mode-param-name-face ((,class :inherit 
font-lock-function-name-face)))
+    `(web-mode-part-comment-face ((,class :inherit web-mode-comment-face)))
+    `(web-mode-part-face ((,class :inherit web-mode-block-face)))
+    `(web-mode-part-string-face ((,class :inherit web-mode-string-face)))
+    `(web-mode-preprocessor-face ((,class :inherit 
font-lock-preprocessor-face)))
+    `(web-mode-script-face ((,class :inherit web-mode-part-face)))
+    `(web-mode-sql-keyword-face ((,class :inherit 
font-lock-negation-char-face)))
+    `(web-mode-string-face ((,class :inherit font-lock-string-face)))
+    `(web-mode-style-face ((,class :inherit web-mode-part-face)))
+    `(web-mode-symbol-face ((,class :inherit font-lock-constant-face)))
+    `(web-mode-type-face ((,class :inherit font-lock-builtin-face)))
+    `(web-mode-underline-face ((,class :underline t)))
+    `(web-mode-variable-name-face ((,class :inherit 
font-lock-variable-name-face)))
+    `(web-mode-warning-face ((,class :inherit font-lock-warning-face)))
+    `(web-mode-whitespace-face ((,class :background ,bg-whitespace :foreground 
,fg-whitespace)))
+;;;;; wgrep
+    `(wgrep-delete-face ((,class :inherit modus-theme-refine-yellow)))
+    `(wgrep-done-face ((,class :inherit modus-theme-refine-blue)))
+    `(wgrep-face ((,class :inherit modus-theme-refine-green)))
+    `(wgrep-file-face ((,class :foreground ,fg-special-warm)))
+    `(wgrep-reject-face ((,class :inherit (modus-theme-intense-red bold))))
+;;;;; which-function-mode
+    `(which-func ((,class :foreground ,magenta-active)))
+;;;;; which-key
+    `(which-key-command-description-face ((,class :foreground ,fg-main)))
+    `(which-key-group-description-face ((,class :foreground ,magenta-alt)))
+    `(which-key-highlighted-command-face ((,class :foreground ,yellow 
:underline t)))
+    `(which-key-key-face ((,class :inherit bold :foreground ,blue-intense)))
+    `(which-key-local-map-description-face ((,class :foreground ,fg-main)))
+    `(which-key-note-face ((,class :foreground ,fg-special-warm)))
+    `(which-key-separator-face ((,class :inherit shadow)))
+    `(which-key-special-key-face ((,class :inherit bold :foreground 
,orange-intense)))
+;;;;; whitespace-mode
+    `(whitespace-big-indent ((,class :inherit modus-theme-subtle-red)))
+    `(whitespace-empty ((,class :inherit modus-theme-intense-magenta)))
+    `(whitespace-hspace ((,class :background ,bg-whitespace :foreground 
,fg-whitespace)))
+    `(whitespace-indentation ((,class :background ,bg-whitespace :foreground 
,fg-whitespace)))
+    `(whitespace-line ((,class :background ,bg-alt)))
+    `(whitespace-newline ((,class :background ,bg-whitespace :foreground 
,fg-whitespace)))
+    `(whitespace-space ((,class :background ,bg-whitespace :foreground 
,fg-whitespace)))
+    `(whitespace-space-after-tab ((,class :inherit 
modus-theme-subtle-magenta)))
+    `(whitespace-space-before-tab ((,class :inherit modus-theme-subtle-cyan)))
+    `(whitespace-tab ((,class :background ,bg-whitespace :foreground 
,fg-whitespace)))
+    `(whitespace-trailing ((,class :inherit modus-theme-intense-red)))
+;;;;; window-divider-mode
+    `(window-divider ((,class :foreground ,fg-window-divider-inner)))
+    `(window-divider-first-pixel ((,class :foreground 
,fg-window-divider-outer)))
+    `(window-divider-last-pixel ((,class :foreground 
,fg-window-divider-outer)))
+;;;;; winum
+    `(winum-face ((,class :inherit modus-theme-bold :foreground ,cyan-active)))
+;;;;; writegood-mode
+    `(writegood-duplicates-face ((,class :background ,bg-alt :foreground 
,red-alt :underline t)))
+    `(writegood-passive-voice-face ((,class :inherit 
modus-theme-lang-warning)))
+    `(writegood-weasels-face ((,class :inherit modus-theme-lang-error)))
+;;;;; woman
+    `(woman-addition ((,class :foreground ,magenta-alt-other)))
+    `(woman-bold ((,class :inherit bold :foreground ,magenta)))
+    `(woman-italic ((,class :inherit italic :foreground ,cyan)))
+    `(woman-unknown ((,class :inherit italic :foreground ,yellow)))
+;;;;; xah-elisp-mode
+    `(xah-elisp-at-symbol ((,class :inherit font-lock-warning-face)))
+    `(xah-elisp-cap-variable ((,class :inherit font-lock-preprocessor-face)))
+    `(xah-elisp-command-face ((,class :inherit font-lock-type-face)))
+    `(xah-elisp-dollar-symbol ((,class :inherit font-lock-variable-name-face)))
+;;;;; xref
+    `(xref-file-header ((,class :inherit bold :foreground ,fg-special-cold)))
+    `(xref-line-number ((,class :inherit shadow)))
+    `(xref-match ((,class :inherit match)))
+;;;;; yaml-mode
+    `(yaml-tab-face ((,class :inherit modus-theme-intense-red)))
+;;;;; yasnippet
+    `(yas-field-highlight-face ((,class :background ,bg-hl-alt-intense)))
+;;;;; ztree
+    `(ztreep-arrow-face ((,class :foreground ,fg-inactive)))
+    `(ztreep-diff-header-face ((,class :inherit bold :height 1.2 :foreground 
,fg-special-cold)))
+    `(ztreep-diff-header-small-face ((,class :inherit bold :foreground 
,fg-special-mild)))
+    `(ztreep-diff-model-add-face ((,class :foreground ,green)))
+    `(ztreep-diff-model-diff-face ((,class :foreground ,red)))
+    `(ztreep-diff-model-ignored-face ((,class :inherit shadow :strike-through 
t)))
+    `(ztreep-diff-model-normal-face ((,class :inherit shadow)))
+    `(ztreep-expand-sign-face ((,class :foreground ,blue)))
+    `(ztreep-header-face ((,class :inherit bold :height 1.2 :foreground 
,fg-special-cold)))
+    `(ztreep-leaf-face ((,class :foreground ,cyan)))
+    `(ztreep-node-count-children-face ((,class :foreground ,fg-special-warm)))
+    `(ztreep-node-face ((,class :foreground ,fg-main))))
+  "Face specs for use with `modus-themes-theme'.")
+
+(defconst modus-themes-custom-variables
+  '(
+;;;; ansi-colors
+    `(ansi-color-faces-vector [default bold shadow italic underline success 
warning error])
+    `(ansi-color-names-vector ["gray35" ,red ,green ,yellow ,blue ,magenta 
,cyan "gray65"])
+;;;; awesome-tray
+    `(awesome-tray-mode-line-active-color ,blue)
+    `(awesome-tray-mode-line-inactive-color ,bg-active)
+;;;; exwm
+    `(exwm-floating-border-color ,fg-window-divider-inner)
+;;;; flymake fringe indicators
+    `(flymake-error-bitmap '(flymake-double-exclamation-mark 
modus-theme-fringe-red))
+    `(flymake-warning-bitmap '(exclamation-mark modus-theme-fringe-yellow))
+    `(flymake-note-bitmap '(exclamation-mark modus-theme-fringe-cyan))
+;;;; ibuffer
+    `(ibuffer-deletion-face 'modus-theme-mark-del)
+    `(ibuffer-filter-group-name-face 'modus-theme-mark-symbol)
+    `(ibuffer-marked-face 'modus-theme-mark-sel)
+    `(ibuffer-title-face 'modus-theme-pseudo-header)
+;;;; highlight-tail
+    `(highlight-tail-colors
+      '((,green-subtle-bg . 0)
+        (,cyan-subtle-bg . 20)))
+;;;; hl-todo
+    `(hl-todo-keyword-faces
+      '(("HOLD" . ,yellow-alt)
+        ("TODO" . ,magenta)
+        ("NEXT" . ,magenta-alt-other)
+        ("THEM" . ,magenta-alt)
+        ("PROG" . ,cyan)
+        ("OKAY" . ,cyan-alt)
+        ("DONT" . ,green-alt)
+        ("FAIL" . ,red)
+        ("BUG" . ,red)
+        ("DONE" . ,green)
+        ("NOTE" . ,yellow-alt-other)
+        ("KLUDGE" . ,yellow)
+        ("HACK" . ,yellow)
+        ("TEMP" . ,red-nuanced-fg)
+        ("FIXME" . ,red-alt-other)
+        ("XXX+" . ,red-alt)
+        ("REVIEW" . ,cyan-alt-other)
+        ("DEPRECATED" . ,blue-nuanced-fg)))
+;;;; pdf-tools
+    `(pdf-view-midnight-colors
+      '(,fg-main . ,bg-dim))
+;;;; vc-annotate (C-x v g)
+    `(vc-annotate-background nil)
+    `(vc-annotate-background-mode nil)
+    `(vc-annotate-color-map
+      '((20 . ,red)
+        (40 . ,magenta)
+        (60 . ,magenta-alt)
+        (80 . ,red-alt)
+        (100 . ,yellow)
+        (120 . ,yellow-alt)
+        (140 . ,fg-special-warm)
+        (160 . ,fg-special-mild)
+        (180 . ,green)
+        (200 . ,green-alt)
+        (220 . ,cyan-alt-other)
+        (240 . ,cyan-alt)
+        (260 . ,cyan)
+        (280 . ,fg-special-cold)
+        (300 . ,blue)
+        (320 . ,blue-alt)
+        (340 . ,blue-alt-other)
+        (360 . ,magenta-alt-other)))
+    `(vc-annotate-very-old-color nil)
+;;;; xterm-color
+    `(xterm-color-names ["black" ,red ,green ,yellow ,blue ,magenta ,cyan 
"gray65"])
+    `(xterm-color-names-bright ["gray35" ,red-alt ,green-alt ,yellow-alt 
,blue-alt ,magenta-alt ,cyan-alt "white"])
+    (if (eq modus-themes-org-blocks 'rainbow)
+        `(org-src-block-faces              ; TODO this list should be expanded
+          `(("emacs-lisp" modus-theme-nuanced-magenta)
+            ("elisp" modus-theme-nuanced-magenta)
+            ("clojure" modus-theme-nuanced-magenta)
+            ("clojurescript" modus-theme-nuanced-magenta)
+            ("c" modus-theme-nuanced-blue)
+            ("c++" modus-theme-nuanced-blue)
+            ("sh" modus-theme-nuanced-green)
+            ("shell" modus-theme-nuanced-green)
+            ("html" modus-theme-nuanced-yellow)
+            ("xml" modus-theme-nuanced-yellow)
+            ("css" modus-theme-nuanced-red)
+            ("scss" modus-theme-nuanced-red)
+            ("python" modus-theme-nuanced-green)
+            ("ipython" modus-theme-nuanced-magenta)
+            ("r" modus-theme-nuanced-cyan)
+            ("yaml" modus-theme-nuanced-cyan)
+            ("conf" modus-theme-nuanced-cyan)
+            ("docker" modus-theme-nuanced-cyan)))
+      `(org-src-block-faces '())))
+  "Custom variables for `modus-themes-theme'.")
+
+;;;###autoload
+(when load-file-name
+  (let ((dir (file-name-directory load-file-name)))
+    (unless (equal dir (expand-file-name "themes/" data-directory))
+      (add-to-list 'custom-theme-load-path dir))))
+
+(provide 'modus-themes)
+;;; modus-themes.el ends here
diff --git a/etc/themes/modus-vivendi-theme.el 
b/etc/themes/modus-vivendi-theme.el
index 73f07d6..814f10d 100644
--- a/etc/themes/modus-vivendi-theme.el
+++ b/etc/themes/modus-vivendi-theme.el
@@ -1,4666 +1,69 @@
 ;;; modus-vivendi-theme.el --- Accessible dark theme (WCAG AAA) -*- 
lexical-binding:t -*-
 
-;; Copyright (C) 2019-2021 Free Software Foundation, Inc.
+;; Copyright (C) 2019-2021  Free Software Foundation, Inc.
 
 ;; Author: Protesilaos Stavrou <info@protesilaos.com>
 ;; URL: https://gitlab.com/protesilaos/modus-themes
-;; Version: 0.13.0
+;; Version: 1.2.3
 ;; Package-Requires: ((emacs "26.1"))
 ;; Keywords: faces, theme, accessibility
 
 ;; This file is part of GNU Emacs.
 
-;; GNU Emacs is free software: you can redistribute it and/or modify
+;; This program is free software; you can redistribute it and/or modify
 ;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation, either version 3 of the License, or
-;; (at your option) any later version.
-
-;; 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.
-
+;; the Free Software Foundation, either version 3 of the License, or (at
+;; your option) any later version.
+;;
+;; This program is distributed in the hope that it will be useful, but
+;; WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+;; General Public License for more details.
+;;
 ;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs.  If not, see <https://www.gnu.org/licenses/>.
+;; along with this program.  If not, see <https://www.gnu.org/licenses/>.
 
 ;;; Commentary:
 ;;
-;; This theme is designed for colour-contrast accessibility.
-;;
-;; 1. Provide a consistent minimum contrast ratio between background and
-;; foreground values of 7:1 or higher.  This meets the highest such
-;; accessibility criterion per the guidelines of the Worldwide Web
-;; Consortium's Working Group on Accessibility (WCAG AAA standard).
+;; Modus Vivendi is the dark variant of the Modus themes (Modus Operandi
+;; is the light one).  The themes are designed for color-contrast
+;; accessibility.  More specifically:
 ;;
-;; 2. Offer as close to full face coverage as possible.  The list is
-;; already quite long (see further below), with more additions to follow
-;; as part of the ongoing development process.
+;;     1. Provide a consistent minimum contrast ratio between background
+;;     and foreground values of 7:1 or higher.  This meets the highest
+;;     such accessibility criterion per the guidelines of the Worldwide
+;;     Web Consortium's Working Group on Accessibility (WCAG AAA
+;;     standard).
 ;;
-;; The theme provides the following customisation options, all of which
-;; are disabled by default:
+;;     2. Offer as close to full face coverage as possible.  The list is
+;;     already quite long, with more additions to follow as part of the
+;;     ongoing development process.
 ;;
-;;     modus-vivendi-theme-slanted-constructs             (boolean)
-;;     modus-vivendi-theme-bold-constructs                (boolean)
-;;     modus-vivendi-theme-variable-pitch-headings        (boolean)
-;;     modus-vivendi-theme-no-mixed-fonts                 (boolean)
-;;     modus-vivendi-theme-headings                       (alist)
-;;     modus-vivendi-theme-scale-headings                 (boolean)
-;;     modus-vivendi-theme-fringes                        (choice)
-;;     modus-vivendi-theme-org-blocks                     (choice)
-;;     modus-vivendi-theme-prompts                        (choice)
-;;     modus-vivendi-theme-mode-line                      (choice)
-;;     modus-vivendi-theme-diffs                          (choice)
-;;     modus-vivendi-theme-faint-syntax                   (boolean)
-;;     modus-vivendi-theme-intense-hl-line                (boolean)
-;;     modus-vivendi-theme-intense-paren-match            (boolean)
-;;     modus-vivendi-theme-no-link-underline              (boolean)
-;;     modus-vivendi-theme-completions                    (choice)
-;;     modus-vivendi-theme-override-colors-alist          (alist)
+;; For a complete view of the project, also refer to the following files
+;; (should be distributed in the same repository/directory as the
+;; current item):
 ;;
-;; The default scale is as follows (it can be customised as well):
-;;
-;;     modus-vivendi-theme-scale-1 1.05
-;;     modus-vivendi-theme-scale-2 1.1
-;;     modus-vivendi-theme-scale-3 1.15
-;;     modus-vivendi-theme-scale-4 1.2
-;;     modus-vivendi-theme-scale-5 1.3
-;;
-;; What follows is the list of explicitly supported packages or face
-;; groups (there are implicitly supported packages as well, which
-;; inherit from font-lock or some basic group).  You are encouraged to
-;; notify me of any missing package or change you would like to see.
-;;
-;;     ace-window
-;;     ag
-;;     alert
-;;     all-the-icons
-;;     annotate
-;;     anzu
-;;     apropos
-;;     apt-sources-list
-;;     artbollocks-mode
-;;     auctex and TeX
-;;     auto-dim-other-buffers
-;;     avy
-;;     awesome-tray
-;;     binder
-;;     bm
-;;     bongo
-;;     boon
-;;     breakpoint (provided by built-in gdb-mi.el)
-;;     buffer-expose
-;;     calendar and diary
-;;     calfw
-;;     centaur-tabs
-;;     change-log and log-view (`vc-print-log' and `vc-print-root-log')
-;;     cider
-;;     circe
-;;     color-rg
-;;     column-enforce-mode
-;;     company-mode
-;;     company-posframe
-;;     compilation-mode
-;;     completions
-;;     counsel
-;;     counsel-css
-;;     counsel-notmuch
-;;     counsel-org-capture-string
-;;     cov
-;;     cperl-mode
-;;     csv-mode
-;;     ctrlf
-;;     custom (M-x customize)
-;;     dap-mode
-;;     dashboard (emacs-dashboard)
-;;     deadgrep
-;;     debbugs
-;;     define-word
-;;     deft
-;;     dictionary
-;;     diff-hl
-;;     diff-mode
-;;     dim-autoload
-;;     dir-treeview
-;;     dired
-;;     dired-async
-;;     dired-git
-;;     dired-git-info
-;;     dired-narrow
-;;     dired-subtree
-;;     diredfl
-;;     disk-usage
-;;     doom-modeline
-;;     dynamic-ruler
-;;     easy-jekyll
-;;     easy-kill
-;;     ebdb
-;;     ediff
-;;     eglot
-;;     el-search
-;;     eldoc
-;;     eldoc-box
-;;     elfeed
-;;     elfeed-score
-;;     emms
-;;     enhanced-ruby-mode
-;;     epa
-;;     equake
-;;     erc
-;;     eros
-;;     ert
-;;     eshell
-;;     eshell-fringe-status
-;;     eshell-git-prompt
-;;     eshell-prompt-extras (epe)
-;;     eshell-syntax-highlighting
-;;     evil (evil-mode)
-;;     evil-goggles
-;;     evil-visual-mark-mode
-;;     eww
-;;     eyebrowse
-;;     fancy-dabbrev
-;;     flycheck
-;;     flycheck-color-mode-line
-;;     flycheck-indicator
-;;     flycheck-posframe
-;;     flymake
-;;     flyspell
-;;     flyspell-correct
-;;     flx
-;;     freeze-it
-;;     frog-menu
-;;     focus
-;;     fold-this
-;;     font-lock (generic syntax highlighting)
-;;     forge
-;;     fountain (fountain-mode)
-;;     geiser
-;;     git-commit
-;;     git-gutter (and variants)
-;;     git-lens
-;;     git-rebase
-;;     git-timemachine
-;;     git-walktree
-;;     gnus
-;;     golden-ratio-scroll-screen
-;;     helm
-;;     helm-ls-git
-;;     helm-switch-shell
-;;     helm-xref
-;;     helpful
-;;     highlight-blocks
-;;     highlight-defined
-;;     highlight-escape-sequences (`hes-mode')
-;;     highlight-indentation
-;;     highlight-numbers
-;;     highlight-symbol
-;;     highlight-tail
-;;     highlight-thing
-;;     hl-defined
-;;     hl-fill-column
-;;     hl-line-mode
-;;     hl-todo
-;;     hydra
-;;     hyperlist
-;;     ibuffer
-;;     icomplete
-;;     ido-mode
-;;     iedit
-;;     iflipb
-;;     imenu-list
-;;     indium
-;;     info
-;;     info-colors
-;;     interaction-log
-;;     ioccur
-;;     isearch, occur, etc.
-;;     ivy
-;;     ivy-posframe
-;;     jira (org-jira)
-;;     journalctl-mode
-;;     js2-mode
-;;     julia
-;;     jupyter
-;;     kaocha-runner
-;;     keycast
-;;     line numbers (`display-line-numbers-mode' and global variant)
-;;     lsp-mode
-;;     lsp-ui
-;;     magit
-;;     magit-imerge
-;;     man
-;;     markdown-mode
-;;     markup-faces (`adoc-mode')
-;;     mentor
-;;     messages
-;;     minibuffer-line
-;;     minimap
-;;     modeline
-;;     mood-line
-;;     mpdel
-;;     mu4e
-;;     mu4e-conversation
-;;     multiple-cursors
-;;     neotree
-;;     no-emoji
-;;     notmuch
-;;     num3-mode
-;;     nxml-mode
-;;     objed
-;;     orderless
-;;     org
-;;     org-journal
-;;     org-noter
-;;     org-pomodoro
-;;     org-recur
-;;     org-roam
-;;     org-superstar
-;;     org-table-sticky-header
-;;     org-treescope
-;;     origami
-;;     outline-mode
-;;     outline-minor-faces
-;;     package (M-x list-packages)
-;;     page-break-lines
-;;     paradox
-;;     paren-face
-;;     parrot
-;;     pass
-;;     persp-mode
-;;     perspective
-;;     phi-grep
-;;     phi-search
-;;     pkgbuild-mode
-;;     pomidor
-;;     powerline
-;;     powerline-evil
-;;     proced
-;;     prodigy
-;;     racket-mode
-;;     rainbow-blocks
-;;     rainbow-identifiers
-;;     rainbow-delimiters
-;;     rcirc
-;;     regexp-builder (also known as `re-builder')
-;;     rg
-;;     ripgrep
-;;     rmail
-;;     ruler-mode
-;;     sallet
-;;     selectrum
-;;     semantic
-;;     sesman
-;;     shell-script-mode
-;;     show-paren-mode
-;;     side-notes
-;;     skewer-mode
-;;     smart-mode-line
-;;     smartparens
-;;     smerge
-;;     spaceline
-;;     speedbar
-;;     spell-fu
-;;     stripes
-;;     suggest
-;;     switch-window
-;;     swiper
-;;     swoop
-;;     sx
-;;     symbol-overlay
-;;     tab-bar-mode
-;;     tab-line-mode
-;;     syslog-mode
-;;     table (built-in table.el)
-;;     telephone-line
-;;     term
-;;     tomatinho
-;;     transient (pop-up windows like Magit's)
-;;     trashed
-;;     treemacs
-;;     tty-menu
-;;     tuareg
-;;     typescript
-;;     undo-tree
-;;     vc (built-in mode line status for version control)
-;;     vc-annotate (C-x v g)
-;;     vdiff
-;;     vimish-fold
-;;     visible-mark
-;;     visual-regexp
-;;     volatile-highlights
-;;     vterm
-;;     wcheck-mode
-;;     web-mode
-;;     wgrep
-;;     which-function-mode
-;;     which-key
-;;     whitespace-mode
-;;     window-divider-mode
-;;     winum
-;;     writegood-mode
-;;     woman
-;;     xah-elisp-mode
-;;     xref
-;;     xterm-color (and ansi-colors)
-;;     yaml-mode
-;;     yasnippet
-;;     ztree
+;; - modus-themes.el            (Main code shared between the themes)
+;; - modus-operandi-theme.el    (Light theme)
 
 ;;; Code:
 
 
 
-(deftheme modus-vivendi
-  "Dark theme that conforms with the highest accessibility
-  standard for colour contrast between background and
-  foreground elements (WCAG AAA).")
-
-;;; Custom faces
-
-;; These faces will be inherited by actual constructs.  They are meant
-;; for those cases where a face needs to distinguish its output from
-;; the rest of the text, such as `isearch' and `occur'…  We define
-;; these separately in order to combine each colour with its
-;; appropriate foreground value.  This is to ensure a consistent
-;; contrast ratio of >= 7:1.
-(defgroup modus-theme ()
-  "Theme that ensures WCAG AAA accessibility (contrast ratio
-between foreground and background is >= 7:1)."
-  :group 'faces
-  :prefix "modus-theme-"
-  :link '(url-link :tag "GitLab" "https://gitlab.com/protesilaos/modus-themes";)
-  :tag "Modus Vivendi")
-
-(defface modus-theme-subtle-red nil nil)
-(defface modus-theme-subtle-green nil nil)
-(defface modus-theme-subtle-yellow nil nil)
-(defface modus-theme-subtle-blue nil nil)
-(defface modus-theme-subtle-magenta nil nil)
-(defface modus-theme-subtle-cyan nil nil)
-(defface modus-theme-subtle-neutral nil nil)
-(defface modus-theme-intense-red nil nil)
-(defface modus-theme-intense-green nil nil)
-(defface modus-theme-intense-yellow nil nil)
-(defface modus-theme-intense-blue nil nil)
-(defface modus-theme-intense-magenta nil nil)
-(defface modus-theme-intense-cyan nil nil)
-(defface modus-theme-intense-neutral nil nil)
-(defface modus-theme-refine-red nil nil)
-(defface modus-theme-refine-green nil nil)
-(defface modus-theme-refine-yellow nil nil)
-(defface modus-theme-refine-blue nil nil)
-(defface modus-theme-refine-magenta nil nil)
-(defface modus-theme-refine-cyan nil nil)
-(defface modus-theme-active-red nil nil)
-(defface modus-theme-active-green nil nil)
-(defface modus-theme-active-yellow nil nil)
-(defface modus-theme-active-blue nil nil)
-(defface modus-theme-active-magenta nil nil)
-(defface modus-theme-active-cyan nil nil)
-(defface modus-theme-fringe-red nil nil)
-(defface modus-theme-fringe-green nil nil)
-(defface modus-theme-fringe-yellow nil nil)
-(defface modus-theme-fringe-blue nil nil)
-(defface modus-theme-fringe-magenta nil nil)
-(defface modus-theme-fringe-cyan nil nil)
-(defface modus-theme-nuanced-red nil nil)
-(defface modus-theme-nuanced-green nil nil)
-(defface modus-theme-nuanced-yellow nil nil)
-(defface modus-theme-nuanced-blue nil nil)
-(defface modus-theme-nuanced-magenta nil nil)
-(defface modus-theme-nuanced-cyan nil nil)
-(defface modus-theme-special-cold nil nil)
-(defface modus-theme-special-mild nil nil)
-(defface modus-theme-special-warm nil nil)
-(defface modus-theme-special-calm nil nil)
-(defface modus-theme-diff-added nil nil)
-(defface modus-theme-diff-changed nil nil)
-(defface modus-theme-diff-removed nil nil)
-(defface modus-theme-diff-refine-added nil nil)
-(defface modus-theme-diff-refine-changed nil nil)
-(defface modus-theme-diff-refine-removed nil nil)
-(defface modus-theme-diff-focus-added nil nil)
-(defface modus-theme-diff-focus-changed nil nil)
-(defface modus-theme-diff-focus-removed nil nil)
-(defface modus-theme-diff-heading nil nil)
-(defface modus-theme-pseudo-header nil nil)
-(defface modus-theme-mark-alt nil nil)
-(defface modus-theme-mark-del nil nil)
-(defface modus-theme-mark-sel nil nil)
-(defface modus-theme-mark-symbol nil nil)
-(defface modus-theme-heading-1 nil nil)
-(defface modus-theme-heading-2 nil nil)
-(defface modus-theme-heading-3 nil nil)
-(defface modus-theme-heading-4 nil nil)
-(defface modus-theme-heading-5 nil nil)
-(defface modus-theme-heading-6 nil nil)
-(defface modus-theme-heading-7 nil nil)
-(defface modus-theme-heading-8 nil nil)
-(defface modus-theme-hl-line nil nil)
-
-;;; Customisation options
-
-;; User-facing customisation options.  They are all deactivated by
-;; default (users must opt in).
-(defcustom modus-vivendi-theme-slanted-constructs nil
-  "Use slanted text in more code constructs (italics or oblique)."
-  :type 'boolean)
-
-(defcustom modus-vivendi-theme-bold-constructs nil
-  "Use bold text in more code constructs."
-  :type 'boolean)
-
-(define-obsolete-variable-alias 'modus-vivendi-theme-proportional-fonts
-  'modus-vivendi-theme-variable-pitch-headings "`modus-vivendi-theme' 0.11.0")
-
-(defcustom modus-vivendi-theme-proportional-fonts nil
-  "Use proportional fonts (variable-pitch) in headings."
-  :type 'boolean)
-
-(defcustom modus-vivendi-theme-variable-pitch-headings nil
-  "Use proportional fonts (variable-pitch) in headings."
-  :type 'boolean)
-
-(defcustom modus-vivendi-theme-no-mixed-fonts nil
-  "Disable inheritance from `fixed-pitch' in some faces.
-
-This is done by default to allow spacing-sensitive constructs,
-such as Org tables and code blocks, to remain monospaced when
-users opt for something like the command `variable-pitch-mode'.
-The downside with the default is that users need to explicitly
-configure the font family of `fixed-pitch' in order to get a
-consistent experience.  That may be something they do not want to
-do.  Hence this option to disable any kind of technique for
-mixing fonts."
-  :type 'boolean)
-
-(make-obsolete 'modus-vivendi-theme-rainbow-headings
-               'modus-vivendi-theme-headings
-               "`modus-vivendi-theme' 0.13.0")
-
-(defcustom modus-vivendi-theme-rainbow-headings nil
-  "Use more saturated colours for headings."
-  :type 'boolean)
-
-(make-obsolete 'modus-vivendi-theme-section-headings
-               'modus-vivendi-theme-headings
-               "`modus-vivendi-theme' 0.13.0")
-
-(defcustom modus-vivendi-theme-section-headings nil
-  "Use a background and an overline in headings."
-  :type 'boolean)
-
-(defcustom modus-vivendi-theme-headings
-  '((t . nil))
-  "Alist of styles for headings, with optional value per level.
-
-To control faces per level from 1-8, use something like this:
-
-  (setq modus-vivendi-theme-headings
-        '((1 . highlight)
-          (2 . line)
-          (t . rainbow-line-no-bold)))
-
-To set a uniform value for all heading levels, use this pattern:
-
-  (setq modus-vivendi-theme-headings
-        '((t . rainbow-line-no-bold)))
-
-The default uses a fairly desaturated foreground value in
-combination with a bold typographic weight.  To specify this
-style for a given level N (assuming you wish to have another
-fallback option), just specify the value t like this:
-
-  (setq modus-vivendi-theme-headings
-        '((1 . t)
-          (2 . line)
-          (t . rainbow-line-no-bold)))
-
-A description of all possible values:
-
-+ `no-bold' retains the default text colour while removing
-  the typographic weight.
-
-+ `line' is the same as the default plus an overline over the
-  heading.
-
-+ `line-no-bold' is the same as `line' without bold weight.
-
-+ `rainbow' uses a more colourful foreground in combination
-  with bold weight.
-
-+ `rainbow-line' is the same as `rainbow' plus an overline.
-
-+ `rainbow-line-no-bold' is the same as `rainbow-line' without
-  the bold weight.
-
-+ `highlight' retains the default style of a fairly desaturated
-  foreground combined with a bold weight and add to it a subtle
-  accented background.
-
-+ `highlight-no-bold' is the same as `highlight' without a bold
-  weight.
-
-+ `rainbow-highlight' is the same as `highlight' but with a more
-  colourful foreground.
-
-+ `rainbow-highlight-no-bold' is the same as `rainbow-highlight'
-  without a bold weight.
-
-+ `section' retains the default looks and adds to them both an
-  overline and a slightly accented background.  It is, in effect,
-  a combination of the `line' and `highlight' values.
-
-+ `section-no-bold' is the same as `section' without a bold
-  weight.
-
-+ `rainbow-section' is the same as `section' but with a more
-  colourful foreground.
-
-+ `rainbow-section-no-bold' is the same as `rainbow-section'
-  without a bold weight."
-  :type
-  '(alist
-    :key-type symbol
-    :value-type
-    (choice (const :tag "Fairly desaturated foreground with bold weight 
(default)" t)
-            (const :tag "Like the default without bold weight" no-bold)
-            (const :tag "Like the default plus overline" line)
-            (const :tag "Like `line' without bold weight" line-no-bold)
-            (const :tag "Like the default but with more colourful foreground" 
rainbow)
-            (const :tag "Like `rainbow' plus overline" rainbow-line)
-            (const :tag "Like `rainbow' without bold weight" rainbow-no-bold)
-            (const :tag "Like `rainbow-line' without bold weight" 
rainbow-line-no-bold)
-            (const :tag "Like the default plus subtle background" highlight)
-            (const :tag "Like `highlight' without bold weight" 
highlight-no-bold)
-            (const :tag "Like `highlight' with more colourful foreground" 
rainbow-highlight)
-            (const :tag "Like `rainbow-highlight' without bold weight" 
rainbow-highlight-no-bold)
-            (const :tag "Like `highlight' plus overline" section)
-            (const :tag "Like `section' without bold weight" section-no-bold)
-            (const :tag "Like `section' with more colourful foreground" 
rainbow-section)
-            (const :tag "Like `rainbow-section' without bold weight" 
rainbow-section-no-bold))))
-
-(defcustom modus-vivendi-theme-scale-headings nil
-  "Use font scaling for headings."
-  :type 'boolean)
-
-(defcustom modus-vivendi-theme-scale-1 1.05
-  "Font size that is slightly larger than the base value.
-The default is a floating point that is interpreted as a multiple
-of the base font size.  However, the variable also accepts an
-integer, understood as an absolute height (e.g. a value of 140 is
-the same as setting the font at 14 point size).
-
-For more on the matter, read the documentation of
-`set-face-attribute', specifically the ':height' section."
-  :type 'number)
-
-(defcustom modus-vivendi-theme-scale-2 1.1
-  "Font size slightly larger than `modus-vivendi-theme-scale-1'.
-The default is a floating point that is interpreted as a multiple
-of the base font size.  However, the variable also accepts an
-integer, understood as an absolute height (e.g. a value of 140 is
-the same as setting the font at 14 point size).
-
-For more on the matter, read the documentation of
-`set-face-attribute', specifically the ':height' section."
-  :type 'number)
-
-(defcustom modus-vivendi-theme-scale-3 1.15
-  "Font size slightly larger than `modus-vivendi-theme-scale-2'.
-The default is a floating point that is interpreted as a multiple
-of the base font size.  However, the variable also accepts an
-integer, understood as an absolute height (e.g. a value of 140 is
-the same as setting the font at 14 point size).
-
-For more on the matter, read the documentation of
-`set-face-attribute', specifically the ':height' section."
-  :type 'number)
-
-(defcustom modus-vivendi-theme-scale-4 1.2
-  "Font size slightly larger than `modus-vivendi-theme-scale-3'.
-The default is a floating point that is interpreted as a multiple
-of the base font size.  However, the variable also accepts an
-integer, understood as an absolute height (e.g. a value of 140 is
-the same as setting the font at 14 point size).
-
-For more on the matter, read the documentation of
-`set-face-attribute', specifically the ':height' section."
-  :type 'number)
-
-(defcustom modus-vivendi-theme-scale-5 1.3
-  "Font size slightly larger than `modus-vivendi-theme-scale-4'.
-The default is a floating point that is interpreted as a multiple
-of the base font size.  However, the variable also accepts an
-integer, understood as an absolute height (e.g. a value of 140 is
-the same as setting the font at 14 point size).
-
-For more on the matter, read the documentation of
-`set-face-attribute', specifically the ':height' section."
-  :type 'number)
-
-(make-obsolete 'modus-vivendi-theme-visible-fringes
-               'modus-vivendi-theme-fringes
-               "`modus-vivendi-theme' 0.12.0")
-
-(defcustom modus-vivendi-theme-visible-fringes nil
-  "Use a visible style for fringes."
-  :type 'boolean)
-
-(defcustom modus-vivendi-theme-fringes nil
-  "Define the visibility of fringes.
-
-Nil means the fringes have no background colour.  Option `subtle'
-will apply a greyscale value that is visible yet close to the
-main buffer background colour.  Option `intense' will use a more
-pronounced greyscale value."
-  :type '(choice
-          (const :tag "No visible fringes (default)" nil)
-          (const :tag "Subtle greyscale background" subtle)
-          (const :tag "Intense greyscale background" intense)))
-
-(make-obsolete 'modus-vivendi-theme-distinct-org-blocks
-               'modus-vivendi-theme-org-blocks
-               "`modus-vivendi-theme' 0.11.0")
-
-(defcustom modus-vivendi-theme-distinct-org-blocks nil
-  "Use a distinct neutral background for `org-mode' blocks."
-  :type 'boolean)
-
-(make-obsolete 'modus-vivendi-theme-rainbow-org-src-blocks
-               'modus-vivendi-theme-org-blocks
-               "`modus-vivendi-theme' 0.11.0")
-
-(defcustom modus-vivendi-theme-rainbow-org-src-blocks nil
-  "Use colour-coded backgrounds for `org-mode' source blocks.
-The colour in use depends on the language (send feedback to
-include more languages)."
-  :type 'boolean)
-
-(defcustom modus-vivendi-theme-org-blocks nil
-  "Use a subtle grey or colour-coded background for Org blocks.
-
-Nil means that the block will have no background of its own and
-will use the default that applies to the rest of the buffer.
-
-Option `greyscale' will apply a subtle neutral grey background to
-the block's contents.  It also affects the begin and end lines of
-the block: their background will be extended to the edge of the
-window for Emacs version >= 27 where the ':extend' keyword is
-recognised by `set-face-attribute'.
-
-Option `rainbow' will use an accented background for the contents
-of the block.  The exact colour will depend on the programming
-language and is controlled by the `org-src-block-faces'
-variable (refer to the theme's source code for the current
-association list)."
-  :type '(choice
-          (const :tag "No Org block background (default)" nil)
-          (const :tag "Subtle grey block background" greyscale)
-          (const :tag "Colour-coded background per programming language" 
rainbow)))
-
-(make-obsolete 'modus-vivendi-theme-3d-modeline
-               'modus-vivendi-theme-mode-line
-               "`modus-vivendi-theme' 0.13.0")
-
-(defcustom modus-vivendi-theme-3d-modeline nil
-  "Use a three-dimensional style for the active mode line."
-  :type 'boolean)
-
-(defcustom modus-vivendi-theme-mode-line nil
-  "Adjust the overall style of the mode line.
-
-Nil is a two-dimensional rectangle with a border around it.  The
-active and the inactive modelines use different shades of
-greyscale values for the background and foreground.
-
-A `3d' value will apply a three-dimensional effect to the active
-modeline.  The inactive modelines remain two-dimensional and are
-toned down a bit, relative to the nil value.
-
-The `moody' option is meant to optimise the modeline for use with
-the library of the same name.  This practically means to remove
-the box effect and rely on underline and overline properties
-instead.  It also tones down the inactive modelines.  Despite its
-intended purpose, this option can also be used without the
-`moody' library."
-  :type '(choice
-          (const :tag "Two-dimensional box (default)" nil)
-          (const :tag "Three-dimensional style for the active mode line" 3d)
-          (const :tag "No box effects, which are optimal for use with the 
`moody' library" moody)))
-
-(make-obsolete 'modus-vivendi-theme-subtle-diffs
-               'modus-vivendi-theme-diffs
-               "`modus-vivendi-theme' 0.13.0")
-
-(defcustom modus-vivendi-theme-subtle-diffs nil
-  "Use fewer/dim backgrounds in `diff-mode', `ediff',`magit'."
-  :type 'boolean)
-
-(defcustom modus-vivendi-theme-diffs nil
-  "Adjust the overall styles of diffs.
-
-Nil means to use fairly intense colour combinations for diffs.
-For example, you get a rich green background with a green
-foreground for added lines.  Word-wise or 'refined' diffs follow
-the same pattern but use different shades of those colours to
-remain distinct.
-
-A `desaturated' value follows the same principles as with the nil
-option, while it tones down all relevant colours.
-
-Option `fg-only' will remove all accented backgrounds, except
-from word-wise changes.  It instead uses colour-coded foreground
-values to differentiate between added/removed/changed lines.  If
-a background is necessary, such as with `ediff', then a subtle
-greyscale value is used."
-  :type '(choice
-          (const :tag "Intensely coloured backgrounds (default)" nil)
-          (const :tag "Slightly accented backgrounds with tinted text" 
desaturated)
-          (const :tag "No backgrounds, except for refined diffs" fg-only)))
-
-(make-obsolete 'modus-vivendi-theme-intense-standard-completions
-               'modus-vivendi-theme-completions
-               "`modus-vivendi-theme' 0.12.0")
-
-(defcustom modus-vivendi-theme-intense-standard-completions nil
-  "Use prominent backgrounds for Icomplete, Ido, or similar."
-  :type 'boolean)
-
-(defcustom modus-vivendi-theme-completions nil
-  "Apply special styles to the UI of completion frameworks.
-
-This concerns Icomplete, Ivy, Helm, Selectrum, Ido, as well as
-any other tool meant to enhance their experience.  The effect
-will vary depending on the completion framework.
-
-Nil means to remain faithful to the metaphors that each UI
-establishes.  For example, Icomplete and Ido only use foreground
-colours to style their matches, whereas Ivy or Helm rely on an
-aesthetic that combines coloured backgrounds with appropriate
-text colour.
-
-Option `moderate' will apply a combination of background and
-foreground that is fairly subtle.  For Icomplete and the like,
-this constitutes a departure from their standard style.  While
-Ivy, Helm, and the others, will use less pronounced colours for
-applicable contexts.
-
-Option `opinionated' will apply colour combinations that
-refashion the completion UI.  So Icomplete et al will now use
-styles that resemble the defaults of Ivy and co., while the
-latter group will revert to an even more nuanced aesthetic."
-  :type '(choice
-          (const :tag "Respect the framework's established aesthetic 
(default)" nil)
-          (const :tag "Subtle backgrounds for various elements" moderate)
-          (const :tag "Radical alternative to the framework's looks" 
opinionated)))
-
-(defcustom modus-vivendi-theme-prompts nil
-  "Use subtle or intense styles for minibuffer and REPL prompts.
-
-Nil means to only use an accented foreground colour.
-
-Options `subtle' and `intense' will change both the background
-and the foreground values.  The latter has a more pronounced
-effect than the former."
-  :type '(choice
-          (const :tag "No prompt background (default)" nil)
-          (const :tag "Subtle accented background for the prompt" subtle)
-          (const :tag "Intense background and foreground for the prompt" 
intense)))
-
-(defcustom modus-vivendi-theme-intense-hl-line nil
-  "Use more prominent background for command `hl-line-mode'."
-  :type 'boolean)
-
-(defcustom modus-vivendi-theme-intense-paren-match nil
-  "Use more prominent colour for parenthesis matching."
-  :type 'boolean)
-
-(defcustom modus-vivendi-theme-faint-syntax nil
-  "Use less saturated colours for code syntax highlighting."
-  :type 'boolean)
-
-(defcustom modus-vivendi-theme-no-link-underline nil
-  "Do not underline links."
-  :type 'boolean)
-
-;;; Internal functions
-
-;; Helper functions that are meant to ease the implementation of the
-;; above customisation options.
-(defun modus-vivendi-theme-bold-weight ()
-  "Conditional use of a heavier text weight."
-  (when modus-vivendi-theme-bold-constructs
-    (list :inherit 'bold)))
-
-(defun modus-vivendi-theme-mixed-fonts ()
-  "Conditional application of `fixed-pitch' inheritance."
-  (unless modus-vivendi-theme-no-mixed-fonts
-    (list :inherit 'fixed-pitch)))
-
-(defun modus-vivendi-theme-fringe (subtlebg intensebg)
-  "Conditional use of background colours for fringes.
-SUBTLEBG should be a subtle greyscale value.  INTENSEBG must be a
-more pronounced greyscale colour."
-  (pcase modus-vivendi-theme-fringes
-    ('intense (list :background intensebg))
-    ('subtle (list :background subtlebg))
-    (_ (list :background nil))))
-
-(defun modus-vivendi-theme-prompt (mainfg subtlebg subtlefg intensebg 
intensefg)
-  "Conditional use of background colours for prompts.
-MAINFG is the prompt's standard foreground.  SUBTLEBG should be a
-subtle accented background that works with SUBTLEFG.  INTENSEBG
-must be a more pronounced accented colour that should be
-combinable with INTENSEFG."
-  (pcase modus-vivendi-theme-prompts
-    ('intense (list :background intensebg :foreground intensefg))
-    ('subtle (list :background subtlebg :foreground subtlefg))
-    (_ (list :background nil :foreground mainfg))))
-
-(defun modus-vivendi-theme-paren (normalbg intensebg)
-  "Conditional use of intense colours for matching parentheses.
-NORMALBG should the special palette colour 'bg-paren-match' or
-something similar.  INTENSEBG must be easier to discern next to
-other backgrounds, such as the special palette colour
-'bg-paren-match-intense'."
-  (if modus-vivendi-theme-intense-paren-match
-      (list :background intensebg)
-    (list :background normalbg)))
-
-(defun modus-vivendi-theme-syntax-foreground (normal faint)
-  "Apply foreground value to code syntax.
-NORMAL is the more saturated colour, which should be the default.
-FAINT is the less saturated colour."
-  (if modus-vivendi-theme-faint-syntax
-      (list :foreground faint)
-    (list :foreground normal)))
-
-(defun modus-vivendi-theme-heading-p (key)
-  "Query style of KEY in `modus-vivendi-theme-headings'."
-  (cdr (assoc key modus-vivendi-theme-headings)))
-
-(defun modus-vivendi-theme-heading (level fg fg-alt bg border)
-  "Conditional styles for `modus-vivendi-theme-headings'.
-
-LEVEL is the heading's position in their order.  FG is the
-default text colour.  FG-ALT is an accented, more saturated value
-than the default.  BG is a nuanced, typically accented,
-background that can work well with either of the foreground
-values.  BORDER is a colour value that combines well with the
-background and alternative foreground."
-  (let* ((key (modus-vivendi-theme-heading-p `,level))
-         (style (or key (modus-vivendi-theme-heading-p t)))
-         (var (if modus-vivendi-theme-variable-pitch-headings
-                  'variable-pitch
-                'default)))
-    (pcase style
-      ('no-bold
-       (list :inherit `,var :foreground fg))
-      ('line
-       (list :inherit `(bold ,var) :foreground fg :overline border))
-      ('line-no-bold
-       (list :inherit `,var :foreground fg :overline border))
-      ('rainbow
-       (list :inherit `(bold ,var) :foreground fg-alt))
-      ('rainbow-no-bold
-       (list :inherit `,var :foreground fg-alt))
-      ('rainbow-line
-       (list :inherit `(bold ,var) :foreground fg-alt :overline border))
-      ('rainbow-line-no-bold
-       (list :inherit `,var :foreground fg-alt :overline border))
-      ('highlight
-       (list :inherit `(bold ,var) :background bg :foreground fg))
-      ('highlight-no-bold
-       (list :inherit `,var :background bg :foreground fg))
-      ('rainbow-highlight
-       (list :inherit `(bold ,var) :background bg :foreground fg-alt))
-      ('rainbow-highlight-no-bold
-       (list :inherit `,var :background bg :foreground fg-alt))
-      ('section
-       (append
-        (and (>= emacs-major-version 27) '(:extend t))
-        (list :inherit `(bold ,var) :background bg :foreground fg :overline 
border)))
-      ('section-no-bold
-       (append
-        (and (>= emacs-major-version 27) '(:extend t))
-        (list :inherit `,var :background bg :foreground fg :overline border)))
-      ('rainbow-section
-       (append
-        (and (>= emacs-major-version 27) '(:extend t))
-        (list :inherit `(bold ,var) :background bg :foreground fg-alt 
:overline border)))
-      ('rainbow-section-no-bold
-       (append
-        (and (>= emacs-major-version 27) '(:extend t))
-        (list :inherit `,var :background bg :foreground fg-alt :overline 
border)))
-      (_
-       (list :inherit `(bold ,var) :foreground fg)))))
-
-(defun modus-vivendi-theme-org-block (bgblk)
-  "Conditionally set the background of Org blocks.
-BGBLK applies to a distinct neutral background.  Else blocks have
-no background of their own (the default), so they look the same
-as the rest of the buffer.
-
-`modus-vivendi-theme-org-blocks' also accepts a `rainbow' option
-which is applied conditionally to `org-src-block-faces' (see the
-theme's source code)."
-  (if (eq modus-vivendi-theme-org-blocks 'greyscale)
-      (append
-       (and (>= emacs-major-version 27) '(:extend t))
-       (list :background bgblk))
-    (list :background nil)))
-
-(defun modus-vivendi-theme-org-block-delim (bgaccent fgaccent bg fg)
-  "Conditionally set the styles of Org block delimiters.
-BG, FG, BGACCENT, FGACCENT apply a background and foreground
-colour respectively.
-
-The former pair is a greyscale combination that should be more
-distinct than the background of the block.  It is applied to the
-default styles or when `modus-vivendi-theme-org-blocks' is set
-to `greyscale'.
-
-The latter pair should be more subtle than the background of the
-block, as it is used when `modus-vivendi-theme-org-blocks' is
-set to `rainbow'."
-  (pcase modus-vivendi-theme-org-blocks
-    ('greyscale (append (and (>= emacs-major-version 27) '(:extend t))
-                        (list :background bg :foreground fg)))
-    ('rainbow (list :background bgaccent :foreground fgaccent))
-    (_ (list :background bg :foreground fg))))
-
-(defun modus-vivendi-theme-mode-line-attrs
-    (fg bg fg-alt bg-alt border border-3d &optional alt-style border-width 
fg-distant)
-  "Colour combinations for `modus-vivendi-theme-mode-line'.
-
-FG and BG are the default colours.  FG-ALT and BG-ALT are meant
-to accommodate the options for a 3D modeline or a `moody'
-compliant one.  BORDER applies to all permutations of the
-modeline, except the three-dimensional effect, where BORDER-3D is
-used instead.
-
-Optional ALT-STYLE applies an appropriate style to the mode
-line's box property.
-
-Optional BORDER-WIDTH specifies an integer for the width of the
-rectangle that produces the box effect.
-
-Optional FG-DISTANT should be close to the main background
-values.  It is intended to be used as a distant-foreground
-property."
-  (pcase modus-vivendi-theme-mode-line
-    ('3d
-     `(:background ,bg-alt :foreground ,fg-alt
-                   :box (:line-width ,(or border-width 1)
-                                     :color ,border-3d
-                                     :style ,(and alt-style 
'released-button))))
-    ('moody
-     `(:background ,bg-alt :foreground ,fg-alt :underline ,border :overline 
,border
-                   :distant-foreground ,fg-distant))
-    (_
-     `(:foreground ,fg :background ,bg :box ,border))))
-
-(defun modus-vivendi-theme-diff (fg-only-bg fg-only-fg mainbg mainfg altbg 
altfg)
-  "Colour combinations for `modus-vivendi-theme-diffs'.
-
-FG-ONLY-BG should be similar or the same as the main background.
-FG-ONLY-FG should be a saturated accent value that can be
-combined with the former.
-
-MAINBG must be one of the dedicated backgrounds for diffs while
-MAINFG must be the same for the foreground.
-
-ALTBG needs to be a slightly accented background that is meant to
-be combined with ALTFG.  Both must be less intense than MAINBG
-and MAINFG respectively."
-  (pcase modus-vivendi-theme-diffs
-    ('fg-only (list :background fg-only-bg :foreground fg-only-fg))
-    ('desaturated (list :background altbg :foreground altfg))
-    (_ (list :background mainbg :foreground mainfg))))
-
-(defun modus-vivendi-theme-standard-completions (mainfg subtlebg intensebg 
intensefg)
-  "Combinations for `modus-vivendi-theme-completions'.
-
-MAINFG is an accented foreground value.  SUBTLEBG is an accented
-background value that can be combined with MAINFG.  INTENSEBG and
-INTENSEFG are accented colours that are designed to be used in
-tandem.
-
-These are intended for Icomplete, Ido, and related."
-  (pcase modus-vivendi-theme-completions
-    ('opinionated (list :background intensebg :foreground intensefg))
-    ('moderate (list :background subtlebg :foreground mainfg))
-    (_ (list :foreground mainfg))))
-
-(defun modus-vivendi-theme-extra-completions (subtleface intenseface altface 
&optional altfg bold)
-  "Combinations for `modus-vivendi-theme-completions'.
-
-SUBTLEFACE and INTENSEFACE are custom theme faces that combine a
-background and foreground value.  The difference between the two
-is a matter of degree.
-
-ALTFACE is a combination of colours that represents a departure
-from the UI's default aesthetics.  Optional ALTFG is meant to be
-used in tandem with it.
-
-Optional BOLD will apply a heavier weight to the text.
-
-These are intended for Helm, Ivy, etc."
-  (pcase modus-vivendi-theme-completions
-    ('opinionated (list :inherit (list altface bold)
-                        :foreground (or altfg 'unspecified)))
-    ('moderate (list :inherit (list subtleface bold)))
-    (_ (list :inherit (list intenseface bold)))))
-
-(defun modus-vivendi-theme-scale (amount)
-  "Scale heading by AMOUNT.
-
-AMOUNT is a customisation option."
-  (when modus-vivendi-theme-scale-headings
-    (list :height amount)))
-
-;;; Colour palette
-
-;; Define colour palette.  Each colour must have a >= 7:1 contrast
-;; ratio relative to the foreground/background colour it is rendered
-;; against.
-;;
-;; The design of the colour palette as a macro that maps it to faces is
-;; adapted from zenbern-theme.el, last seen at commit 7dd7968:
-;; https://github.com/bbatsov/zenburn-emacs
 (eval-and-compile
-  (defconst modus-vivendi-theme-default-colors-alist
-    '(;; base values
-      ("bg-main" . "#000000") ("fg-main" . "#ffffff")
-      ("bg-alt" . "#181a20") ("fg-alt" . "#a8a8a8")
-      ("bg-dim" . "#110b11") ("fg-dim" . "#e0e6f0")
-      ;; specifically for on/off states (e.g. `mode-line')
-      ;;
-      ;; must be combined with themselves
-      ("bg-active" . "#323232") ("fg-active" . "#f4f4f4")
-      ("bg-inactive" . "#1e1e1e") ("fg-inactive" . "#bfc0c4")
-      ;; special base values, used only for cases where the above
-      ;; fg-* or bg-* cannot or should not be used (to avoid confusion)
-      ;; must be combined with: {fg,bg}-{main,alt,dim}
-      ("bg-special-cold" . "#203448") ("fg-special-cold" . "#c6eaff")
-      ("bg-special-mild" . "#00322e") ("fg-special-mild" . "#bfebe0")
-      ("bg-special-warm" . "#382f27") ("fg-special-warm" . "#f8dec0")
-      ("bg-special-calm" . "#392a48") ("fg-special-calm" . "#fbd6f4")
-      ;; styles for the main constructs
-      ;;
-      ;; must be combined with: `bg-main', `bg-alt', `bg-dim'
-      ("red" . "#ff8059") ("green" . "#44bc44")
-      ("yellow" . "#eecc00") ("blue" . "#2fafff")
-      ("magenta" . "#feacd0") ("cyan" . "#00d3d0")
-      ;; styles for common, but still specialised constructs
-      ;;
-      ;; must be combined with: `bg-main', `bg-alt', `bg-dim'
-      ("red-alt" . "#f4923b") ("green-alt" . "#80d200")
-      ("yellow-alt" . "#cfdf30") ("blue-alt" . "#79a8ff")
-      ("magenta-alt" . "#f78fe7") ("cyan-alt" . "#4ae8fc")
-      ;; same purpose as above, just slight differences
-      ;;
-      ;; must be combined with: `bg-main', `bg-alt', `bg-dim'
-      ("red-alt-other" . "#ff9977") ("green-alt-other" . "#00cd68")
-      ("yellow-alt-other" . "#f0ce43") ("blue-alt-other" . "#00bcff")
-      ("magenta-alt-other" . "#b6a0ff") ("cyan-alt-other" . "#6ae4b9")
-      ;; styles for desaturated foreground text, intended for use with
-      ;; the `modus-vivendi-theme-faint-syntax' option
-      ;;
-      ;; must be combined with: `bg-main', `bg-alt', `bg-dim'
-      ("red-faint" . "#ffa0a0") ("green-faint" . "#88cf88")
-      ("yellow-faint" . "#d2b580") ("blue-faint" . "#92baff")
-      ("magenta-faint" . "#e0b2d6") ("cyan-faint" . "#a0bfdf")
-
-      ("red-alt-faint" . "#f5aa80") ("green-alt-faint" . "#a8cf88")
-      ("yellow-alt-faint" . "#cabf77") ("blue-alt-faint" . "#a4b0ff")
-      ("magenta-alt-faint" . "#ef9fe4") ("cyan-alt-faint" . "#90c4ed")
-
-      ("red-alt-other-faint" . "#ff9fbf") ("green-alt-other-faint" . "#88cfaf")
-      ("yellow-alt-other-faint" . "#d0ba95") ("blue-alt-other-faint" . 
"#8fc5ff")
-      ("magenta-alt-other-faint" . "#d0b4ff") ("cyan-alt-other-faint" . 
"#a4d0bb")
-      ;; styles for elements that should be very subtle, yet accented
-      ;;
-      ;; must be combined with: `bg-main', `bg-alt', `bg-dim' or any of
-      ;; the "nuanced" backgrounds
-      ("red-nuanced" . "#ffcccc") ("green-nuanced" . "#b8e2b8")
-      ("yellow-nuanced" . "#dfdfb0") ("blue-nuanced" . "#bfd9ff")
-      ("magenta-nuanced" . "#e5cfef") ("cyan-nuanced" . "#a8e5e5")
-      ;; styles for slightly accented background
-      ;;
-      ;; must be combined with any of the above foreground values
-      ("red-nuanced-bg" . "#2c0614") ("green-nuanced-bg" . "#001904")
-      ("yellow-nuanced-bg" . "#221000") ("blue-nuanced-bg" . "#0f0e39")
-      ("magenta-nuanced-bg" . "#230631") ("cyan-nuanced-bg" . "#041529")
-      ;; styles for elements that should draw attention to themselves
-      ;;
-      ;; must be combined with: `bg-main'
-      ("red-intense" . "#fb6859") ("green-intense" . "#00fc50")
-      ("yellow-intense" . "#ffdd00") ("blue-intense" . "#00a2ff")
-      ("magenta-intense" . "#ff8bd4") ("cyan-intense" . "#30ffc0")
-      ;; styles for background elements that should be visible yet
-      ;; subtle
-      ;;
-      ;; must be combined with: `fg-dim'
-      ("red-subtle-bg" . "#762422") ("green-subtle-bg" . "#2f4a00")
-      ("yellow-subtle-bg" . "#604200") ("blue-subtle-bg" . "#10387c")
-      ("magenta-subtle-bg" . "#49366e") ("cyan-subtle-bg" . "#00415e")
-      ;; styles for background elements that should be visible and
-      ;; distinguishable
-      ;;
-      ;; must be combined with: `fg-main'
-      ("red-intense-bg" . "#a4202a") ("green-intense-bg" . "#006800")
-      ("yellow-intense-bg" . "#874900") ("blue-intense-bg" . "#2a40b8")
-      ("magenta-intense-bg" . "#7042a2") ("cyan-intense-bg" . "#005f88")
-      ;; styles for refined contexts where both the foreground and the
-      ;; background need to have the same/similar hue
-      ;;
-      ;; must be combined with themselves OR the foregrounds can be
-      ;; combined with any of the base backgrounds
-      ("red-refine-bg" . "#77002a") ("red-refine-fg" . "#ffb9ab")
-      ("green-refine-bg" . "#00422a") ("green-refine-fg" . "#9ff0cf")
-      ("yellow-refine-bg" . "#693200") ("yellow-refine-fg" . "#e2d980")
-      ("blue-refine-bg" . "#242679") ("blue-refine-fg" . "#8ec6ff")
-      ("magenta-refine-bg" . "#71206a") ("magenta-refine-fg" . "#ffcaf0")
-      ("cyan-refine-bg" . "#004065") ("cyan-refine-fg" . "#8ae4f2")
-      ;; styles that are meant exclusively for the mode line
-      ;;
-      ;; must be combined with: `bg-active', `bg-inactive'
-      ("red-active" . "#ffa7ba") ("green-active" . "#70d73f")
-      ("yellow-active" . "#dbbe5f") ("blue-active" . "#34cfff")
-      ("magenta-active" . "#d5b1ff") ("cyan-active" . "#00d8b4")
-      ;; styles that are meant exclusively for the fringes
-      ;;
-      ;; must be combined with `fg-main'
-      ("red-fringe-bg" . "#8f1f4b") ("green-fringe-bg" . "#006700")
-      ("yellow-fringe-bg" . "#6f4f00") ("blue-fringe-bg" . "#3f33af")
-      ("magenta-fringe-bg" . "#6f2f89") ("cyan-fringe-bg" . "#004f8f")
-      ;; styles reserved for specific faces
-      ;;
-      ;; `bg-hl-line' is between `bg-dim' and `bg-alt', so it should
-      ;; work with all accents that cover those two, plus `bg-main'
-      ;;
-      ;; `bg-hl-alt' and `bg-hl-alt-intense' should only be used when no
-      ;; other greyscale or fairly neutral background is available to
-      ;; properly draw attention to a given construct
-      ;;
-      ;; `bg-header' is between `bg-active' and `bg-inactive', so it
-      ;; can be combined with any of the "active" values, plus the
-      ;; "special" and base foreground colours
-      ;;
-      ;; `bg-paren-match', `bg-paren-match-intense', `bg-region' and
-      ;; `bg-tab-active' must be combined with `fg-main', while
-      ;; `bg-tab-inactive' should be combined with `fg-dim'
-      ;;
-      ;; `bg-tab-bar' is only intended for the bar that holds the tabs and
-      ;; can only be combined with `fg-main'
-      ;;
-      ;; `fg-tab-active' is meant to be combined with `bg-tab-active',
-      ;; though only for styling special elements, such as underlining
-      ;; the current tab
-      ;;
-      ;; `fg-escape-char-construct' and `fg-escape-char-backslash' can
-      ;; be combined `bg-main', `bg-dim', `bg-alt'
-      ;;
-      ;; `fg-lang-error', `fg-lang-warning', `fg-lang-note' can be
-      ;; combined with `bg-main', `bg-dim', `bg-alt'
-      ;;
-      ;; `fg-mark-sel', `fg-mark-del', `fg-mark-alt' can be combined
-      ;; with `bg-main', `bg-dim', `bg-alt', `bg-hl-line'
-      ;;
-      ;; `fg-unfocused' must be combined with `fg-main'
-      ;;
-      ;; the window divider colours apply to faces with just an fg value
-      ;;
-      ;; all pairs are combinable with themselves
-      ("bg-hl-line" . "#151823")
-      ("bg-hl-line-intense" . "#2f2f2f")
-      ("bg-hl-alt" . "#181732")
-      ("bg-hl-alt-intense" . "#282e46")
-      ("bg-paren-match" . "#5f362f")
-      ("bg-paren-match-intense" . "#7416b5")
-      ("bg-region" . "#3c3c3c")
-
-      ("bg-tab-bar" . "#2c2c2c")
-      ("bg-tab-active" . "#0e0e0e")
-      ("bg-tab-inactive" . "#3d3d3d")
-      ("fg-tab-active" . "#5ac3cf")
+  (unless (and (fboundp 'require-theme)
+               (require-theme 'modus-themes t))
+    (require 'modus-themes)))
 
-      ("fg-escape-char-construct" . "#e7a59a")
-      ("fg-escape-char-backslash" . "#abab00")
-
-      ("fg-lang-error" . "#ef8690")
-      ("fg-lang-warning" . "#b0aa00")
-      ("fg-lang-note" . "#9d9def")
-
-      ("fg-window-divider-inner" . "#646464")
-      ("fg-window-divider-outer" . "#969696")
-
-      ("fg-unfocused" . "#93959b")
-
-      ("bg-header" . "#212121") ("fg-header" . "#dddddd")
-
-      ("bg-whitespace" . "#170016") ("fg-whitespace" . "#a4959f")
-
-      ("bg-diff-heading" . "#304466") ("fg-diff-heading" . "#dadffe")
-      ("bg-diff-added" . "#0a280a") ("fg-diff-added" . "#94ba94")
-      ("bg-diff-changed" . "#2a2000") ("fg-diff-changed" . "#b0ba9f")
-      ("bg-diff-removed" . "#40160f") ("fg-diff-removed" . "#c6adaa")
-
-      ("bg-diff-refine-added" . "#005a36") ("fg-diff-refine-added" . "#e0f6e0")
-      ("bg-diff-refine-changed" . "#585800") ("fg-diff-refine-changed" . 
"#ffffcc")
-      ("bg-diff-refine-removed" . "#852828") ("fg-diff-refine-removed" . 
"#ffd9eb")
-
-      ("bg-diff-focus-added" . "#203d20") ("fg-diff-focus-added" . "#b4ddb4")
-      ("bg-diff-focus-changed" . "#4a3a10") ("fg-diff-focus-changed" . 
"#d0daaf")
-      ("bg-diff-focus-removed" . "#5e2526") ("fg-diff-focus-removed" . 
"#eebdba")
-
-      ("bg-diff-neutral-0" . "#575757") ("fg-diff-neutral-0" . "#fcfcfc")
-      ("bg-diff-neutral-1" . "#454545") ("fg-diff-neutral-1" . "#dddddd")
-      ("bg-diff-neutral-2" . "#313131") ("fg-diff-neutral-2" . "#bfbfbf")
-
-      ("bg-mark-sel" . "#002f2f") ("fg-mark-sel" . "#60cfa2")
-      ("bg-mark-del" . "#5a0000") ("fg-mark-del" . "#ff99aa")
-      ("bg-mark-alt" . "#3f2210") ("fg-mark-alt" . "#f0aa20"))
-    "The entire palette of `modus-vivendi-theme'.
-Each element has the form (NAME . HEX).")
-
-  (defcustom modus-vivendi-theme-override-colors-alist '()
-    "Association list of palette colour overrides.
-Values can be mapped to variables, using the same syntax as the
-one present in `modus-vivendi-theme-default-colors-alist'.
-
-This is only meant for do-it-yourself usage, with the
-understanding that the user is responsible for the resulting
-contrast ratio between new and existing colours."
-    :type '(alist
-            :key-type (string :tag "Name")
-            :value-type (string :tag " Hex")))
-
-  (defmacro modus-vivendi-theme-with-color-variables (&rest body)
-    "`let' bind all colours around BODY.
-Also bind `class' to ((class color) (min-colors 89))."
-    (declare (indent 0))
-    `(let ((class '((class color) (min-colors 89)))
-           ,@(mapcar (lambda (cons)
-                       (list (intern (car cons)) (cdr cons)))
-                     (append modus-vivendi-theme-default-colors-alist
-                             modus-vivendi-theme-override-colors-alist))
-           ;; simple conditional styles that evaluate user-facing
-           ;; customisation options
-           (modus-theme-slant
-            (if modus-vivendi-theme-slanted-constructs 'italic 'normal))
-           (modus-theme-variable-pitch
-            (if modus-vivendi-theme-variable-pitch-headings 'variable-pitch 
'default)))
-       ,@body)))
-
-
-
-;;; Faces
-
-(modus-vivendi-theme-with-color-variables
-  (custom-theme-set-faces
-   'modus-vivendi
-;;;; custom faces
-   ;; these bespoke faces are inherited by other constructs below
-;;;;; subtle coloured backgrounds
-   `(modus-theme-subtle-red ((,class :background ,red-subtle-bg :foreground 
,fg-dim)))
-   `(modus-theme-subtle-green ((,class :background ,green-subtle-bg 
:foreground ,fg-dim)))
-   `(modus-theme-subtle-yellow ((,class :background ,yellow-subtle-bg 
:foreground ,fg-dim)))
-   `(modus-theme-subtle-blue ((,class :background ,blue-subtle-bg :foreground 
,fg-dim)))
-   `(modus-theme-subtle-magenta ((,class :background ,magenta-subtle-bg 
:foreground ,fg-dim)))
-   `(modus-theme-subtle-cyan ((,class :background ,cyan-subtle-bg :foreground 
,fg-dim)))
-   `(modus-theme-subtle-neutral ((,class :background ,bg-inactive :foreground 
,fg-inactive)))
-;;;;; intense coloured backgrounds
-   `(modus-theme-intense-red ((,class :background ,red-intense-bg :foreground 
,fg-main)))
-   `(modus-theme-intense-green ((,class :background ,green-intense-bg 
:foreground ,fg-main)))
-   `(modus-theme-intense-yellow ((,class :background ,yellow-intense-bg 
:foreground ,fg-main)))
-   `(modus-theme-intense-blue ((,class :background ,blue-intense-bg 
:foreground ,fg-main)))
-   `(modus-theme-intense-magenta ((,class :background ,magenta-intense-bg 
:foreground ,fg-main)))
-   `(modus-theme-intense-cyan ((,class :background ,cyan-intense-bg 
:foreground ,fg-main)))
-   `(modus-theme-intense-neutral ((,class :background ,bg-active :foreground 
,fg-main)))
-;;;;; refined background and foreground combinations
-   ;; general purpose styles that use an accented foreground against an
-   ;; accented background
-   `(modus-theme-refine-red ((,class :background ,red-refine-bg :foreground 
,red-refine-fg)))
-   `(modus-theme-refine-green ((,class :background ,green-refine-bg 
:foreground ,green-refine-fg)))
-   `(modus-theme-refine-yellow ((,class :background ,yellow-refine-bg 
:foreground ,yellow-refine-fg)))
-   `(modus-theme-refine-blue ((,class :background ,blue-refine-bg :foreground 
,blue-refine-fg)))
-   `(modus-theme-refine-magenta ((,class :background ,magenta-refine-bg 
:foreground ,magenta-refine-fg)))
-   `(modus-theme-refine-cyan ((,class :background ,cyan-refine-bg :foreground 
,cyan-refine-fg)))
-;;;;; "active" combinations, mostly for use on the mode line
-   `(modus-theme-active-red ((,class :background ,red-active :foreground 
,bg-active)))
-   `(modus-theme-active-green ((,class :background ,green-active :foreground 
,bg-active)))
-   `(modus-theme-active-yellow ((,class :background ,yellow-active :foreground 
,bg-active)))
-   `(modus-theme-active-blue ((,class :background ,blue-active :foreground 
,bg-active)))
-   `(modus-theme-active-magenta ((,class :background ,magenta-active 
:foreground ,bg-active)))
-   `(modus-theme-active-cyan ((,class :background ,cyan-active :foreground 
,bg-active)))
-;;;;; nuanced backgrounds
-   ;; useful for adding an accented background that is suitable for all
-   ;; main foreground colours (intended for use in Org source blocks)
-   `(modus-theme-nuanced-red ((,class :background ,red-nuanced-bg
-                                      ,@(and (>= emacs-major-version 27) 
'(:extend t)))))
-   `(modus-theme-nuanced-green ((,class :background ,green-nuanced-bg
-                                        ,@(and (>= emacs-major-version 27) 
'(:extend t)))))
-   `(modus-theme-nuanced-yellow ((,class :background ,yellow-nuanced-bg
-                                         ,@(and (>= emacs-major-version 27) 
'(:extend t)))))
-   `(modus-theme-nuanced-blue ((,class :background ,blue-nuanced-bg
-                                       ,@(and (>= emacs-major-version 27) 
'(:extend t)))))
-   `(modus-theme-nuanced-magenta ((,class :background ,magenta-nuanced-bg
-                                          ,@(and (>= emacs-major-version 27) 
'(:extend t)))))
-   `(modus-theme-nuanced-cyan ((,class :background ,cyan-nuanced-bg
-                                       ,@(and (>= emacs-major-version 27) 
'(:extend t)))))
-;;;;; fringe-specific combinations
-   `(modus-theme-fringe-red ((,class :background ,red-fringe-bg :foreground 
,fg-main)))
-   `(modus-theme-fringe-green ((,class :background ,green-fringe-bg 
:foreground ,fg-main)))
-   `(modus-theme-fringe-yellow ((,class :background ,yellow-fringe-bg 
:foreground ,fg-main)))
-   `(modus-theme-fringe-blue ((,class :background ,blue-fringe-bg :foreground 
,fg-main)))
-   `(modus-theme-fringe-magenta ((,class :background ,magenta-fringe-bg 
:foreground ,fg-main)))
-   `(modus-theme-fringe-cyan ((,class :background ,cyan-fringe-bg :foreground 
,fg-main)))
-;;;;; special base values
-   ;; these are closer to the grayscale than the accents defined above
-   ;; and should only be used when the next closest alternative would be
-   ;; a greyscale value than an accented one
-   `(modus-theme-special-cold ((,class :background ,bg-special-cold 
:foreground ,fg-special-cold)))
-   `(modus-theme-special-mild ((,class :background ,bg-special-mild 
:foreground ,fg-special-mild)))
-   `(modus-theme-special-warm ((,class :background ,bg-special-warm 
:foreground ,fg-special-warm)))
-   `(modus-theme-special-calm ((,class :background ,bg-special-calm 
:foreground ,fg-special-calm)))
-;;;;; diff-specific combinations
-   ;; intended for `diff-mode' or equivalent
-   `(modus-theme-diff-added
-     ((,class ,@(modus-vivendi-theme-diff
-                 bg-main green
-                 bg-diff-focus-added fg-diff-focus-added
-                 green-nuanced-bg fg-diff-added))))
-   `(modus-theme-diff-changed
-     ((,class ,@(modus-vivendi-theme-diff
-                 bg-main yellow
-                 bg-diff-focus-changed fg-diff-focus-changed
-                 yellow-nuanced-bg fg-diff-changed))))
-   `(modus-theme-diff-removed
-     ((,class ,@(modus-vivendi-theme-diff
-                 bg-main red
-                 bg-diff-focus-removed fg-diff-focus-removed
-                 red-nuanced-bg fg-diff-removed))))
-   `(modus-theme-diff-refine-added
-     ((,class ,@(modus-vivendi-theme-diff
-                 bg-diff-added fg-diff-added
-                 bg-diff-refine-added fg-diff-refine-added
-                 bg-diff-focus-added fg-diff-focus-added))))
-   `(modus-theme-diff-refine-changed
-     ((,class ,@(modus-vivendi-theme-diff
-                 bg-diff-changed fg-diff-changed
-                 bg-diff-refine-changed fg-diff-refine-changed
-                 bg-diff-focus-changed fg-diff-focus-changed))))
-   `(modus-theme-diff-refine-removed
-     ((,class ,@(modus-vivendi-theme-diff
-                 bg-diff-removed fg-diff-removed
-                 bg-diff-refine-removed fg-diff-refine-removed
-                 bg-diff-focus-removed fg-diff-focus-removed))))
-   `(modus-theme-diff-focus-added
-     ((,class ,@(modus-vivendi-theme-diff
-                 bg-dim green
-                 bg-diff-focus-added fg-diff-focus-added
-                 bg-diff-added fg-diff-added))))
-   `(modus-theme-diff-focus-changed
-     ((,class ,@(modus-vivendi-theme-diff
-                 bg-dim yellow
-                 bg-diff-focus-changed fg-diff-focus-changed
-                 bg-diff-changed fg-diff-changed))))
-   `(modus-theme-diff-focus-removed
-     ((,class ,@(modus-vivendi-theme-diff
-                 bg-dim red
-                 bg-diff-focus-removed fg-diff-focus-removed
-                 bg-diff-removed fg-diff-removed))))
-   `(modus-theme-diff-heading
-     ((,class ,@(modus-vivendi-theme-diff
-                 bg-alt blue-alt
-                 bg-diff-heading fg-diff-heading
-                 blue-nuanced-bg blue))))
-;;;;; mark indicators
-   ;; colour combinations intended for Dired, Ibuffer, or equivalent
-   `(modus-theme-pseudo-header ((,class :inherit bold :foreground ,fg-main)))
-   `(modus-theme-mark-alt ((,class :inherit bold :background ,bg-mark-alt 
:foreground ,fg-mark-alt)))
-   `(modus-theme-mark-del ((,class :inherit bold :background ,bg-mark-del 
:foreground ,fg-mark-del)))
-   `(modus-theme-mark-sel ((,class :inherit bold :background ,bg-mark-sel 
:foreground ,fg-mark-sel)))
-   `(modus-theme-mark-symbol ((,class :inherit bold :foreground ,blue-alt)))
-;;;;; heading levels
-   ;; styles for regular headings used in Org, Markdown, Info, etc.
-   `(modus-theme-heading-1
-     ((,class ,@(modus-vivendi-theme-heading
-                 1 fg-main magenta-alt-other magenta-nuanced-bg bg-region)
-              ,@(modus-vivendi-theme-scale modus-vivendi-theme-scale-4))))
-   `(modus-theme-heading-2
-     ((,class ,@(modus-vivendi-theme-heading
-                 2 fg-special-warm magenta-alt red-nuanced-bg bg-region)
-              ,@(modus-vivendi-theme-scale modus-vivendi-theme-scale-3))))
-   `(modus-theme-heading-3
-     ((,class ,@(modus-vivendi-theme-heading
-                 3 fg-special-cold blue blue-nuanced-bg bg-region)
-              ,@(modus-vivendi-theme-scale modus-vivendi-theme-scale-2))))
-   `(modus-theme-heading-4
-     ((,class ,@(modus-vivendi-theme-heading
-                 4 fg-special-mild cyan cyan-nuanced-bg bg-region)
-              ,@(modus-vivendi-theme-scale modus-vivendi-theme-scale-1))))
-   `(modus-theme-heading-5
-     ((,class ,@(modus-vivendi-theme-heading
-                 5 fg-special-calm green-alt-other green-nuanced-bg 
bg-region))))
-   `(modus-theme-heading-6
-     ((,class ,@(modus-vivendi-theme-heading
-                 6 yellow-nuanced yellow-alt-other yellow-nuanced-bg 
bg-region))))
-   `(modus-theme-heading-7
-     ((,class ,@(modus-vivendi-theme-heading
-                 7 red-nuanced red-alt red-nuanced-bg bg-region))))
-   `(modus-theme-heading-8
-     ((,class ,@(modus-vivendi-theme-heading
-                 8 fg-dim magenta bg-alt bg-region))))
-;;;;; other custom faces
-   `(modus-theme-hl-line ((,class :background ,(if 
modus-vivendi-theme-intense-hl-line
-                                                   bg-hl-line-intense 
bg-hl-line)
-                                  (and (>= emacs-major-version 27) '(:extend 
t)))))
-;;;; standard faces
-;;;;; absolute essentials
-   `(default ((,class :background ,bg-main :foreground ,fg-main)))
-   `(cursor ((,class :background ,fg-main)))
-   `(fringe ((,class ,@(modus-vivendi-theme-fringe bg-inactive bg-active)
-                     :foreground ,fg-main)))
-   `(vertical-border ((,class :foreground ,fg-window-divider-inner)))
-;;;;; basic and/or ungrouped styles
-   ;; Modify the `bold' face to change the weight of all "bold" elements
-   ;; defined by the theme.  You need a typeface that supports a
-   ;; multitude of heavier weights than the regular one and then you
-   ;; must specify the exact name of the one you wish to apply.  Example
-   ;; for your init.el:
-   ;;
-   ;; (set-face-attribute 'bold nil :weight 'semibold)
-   `(bold ((,class :weight bold)))
-   `(comint-highlight-input ((,class :inherit bold)))
-   `(comint-highlight-prompt ((,class ,@(modus-vivendi-theme-bold-weight)
-                                      ,@(modus-vivendi-theme-prompt
-                                         cyan
-                                         blue-nuanced-bg blue-alt
-                                         blue-refine-bg fg-main))))
-   `(error ((,class :inherit bold :foreground ,red)))
-   `(escape-glyph ((,class :foreground ,fg-escape-char-construct)))
-   `(file-name-shadow ((,class :foreground ,fg-unfocused)))
-   `(header-line ((,class :background ,bg-header :foreground ,fg-header)))
-   `(header-line-highlight ((,class :inherit modus-theme-active-blue)))
-   `(help-argument-name ((,class :foreground ,cyan :slant ,modus-theme-slant)))
-   `(homoglyph ((,class :foreground ,fg-escape-char-construct)))
-   `(ibuffer-locked-buffer ((,class :foreground ,yellow-alt-other)))
-   `(italic ((,class :slant italic)))
-   `(nobreak-hyphen ((,class :foreground ,fg-escape-char-construct)))
-   `(nobreak-space ((,class :foreground ,fg-escape-char-construct :underline 
t)))
-   `(minibuffer-prompt ((,class ,@(modus-vivendi-theme-prompt
-                                   cyan-alt-other
-                                   cyan-nuanced-bg cyan
-                                   cyan-refine-bg fg-main))))
-   `(mm-command-output ((,class :foreground ,red-alt-other)))
-   `(mm-uu-extract ((,class :background ,bg-dim :foreground ,fg-special-mild)))
-   `(next-error ((,class :inherit modus-theme-subtle-red)))
-   `(rectangle-preview ((,class :inherit modus-theme-special-mild)))
-   `(region ((,class :background ,bg-region :foreground ,fg-main)))
-   `(secondary-selection ((,class :inherit modus-theme-special-cold)))
-   `(shadow ((,class :foreground ,fg-alt)))
-   `(success ((,class :inherit bold :foreground ,green)))
-   `(trailing-whitespace ((,class :background ,red-intense-bg)))
-   `(warning ((,class :inherit bold :foreground ,yellow)))
-;;;;; buttons, links, widgets
-   `(button ((,class :foreground ,blue-alt-other
-                     ,@(unless modus-vivendi-theme-no-link-underline
-                         (list :underline t)))))
-   `(link ((,class :inherit button)))
-   `(link-visited ((,class :inherit link :foreground ,magenta-alt-other)))
-   `(tooltip ((,class :background ,bg-special-cold :foreground ,fg-main)))
-   `(widget-button ((,class :inherit button)))
-   `(widget-button-pressed ((,class :inherit button :foreground ,magenta)))
-   `(widget-documentation ((,class :foreground ,green)))
-   `(widget-field ((,class :background ,bg-alt :foreground ,fg-dim)))
-   `(widget-inactive ((,class :background ,bg-inactive :foreground 
,fg-inactive)))
-   `(widget-single-line-field ((,class :inherit widget-field)))
-;;;;; ag
-   `(ag-hit-face ((,class :foreground ,fg-special-cold)))
-   `(ag-match-face ((,class :inherit modus-theme-special-calm)))
-;;;;; alert
-   `(alert-high-face ((,class :inherit bold :foreground ,red-alt)))
-   `(alert-low-face ((,class :foreground ,fg-special-mild)))
-   `(alert-moderate-face ((,class :inherit bold :foreground ,yellow)))
-   `(alert-trivial-face ((,class :foreground ,fg-special-calm)))
-   `(alert-urgent-face ((,class :inherit bold :foreground ,red-intense)))
-;;;;; all-the-icons
-   `(all-the-icons-blue ((,class :foreground ,blue)))
-   `(all-the-icons-blue-alt ((,class :foreground ,blue-alt)))
-   `(all-the-icons-cyan ((,class :foreground ,cyan)))
-   `(all-the-icons-cyan-alt ((,class :foreground ,cyan-alt)))
-   `(all-the-icons-dblue ((,class :foreground ,blue-alt-other)))
-   `(all-the-icons-dcyan ((,class :foreground ,cyan-alt-other)))
-   `(all-the-icons-dgreen ((,class :foreground ,green-alt-other)))
-   `(all-the-icons-dired-dir-face ((,class :foreground ,blue)))
-   `(all-the-icons-dmaroon ((,class :foreground ,magenta-alt-other)))
-   `(all-the-icons-dorange ((,class :foreground ,red-alt-other)))
-   `(all-the-icons-dpink ((,class :foreground ,magenta)))
-   `(all-the-icons-dpurple ((,class :foreground ,magenta-alt)))
-   `(all-the-icons-dred ((,class :foreground ,red)))
-   `(all-the-icons-dsilver ((,class :foreground ,fg-special-cold)))
-   `(all-the-icons-dyellow ((,class :foreground ,yellow)))
-   `(all-the-icons-green ((,class :foreground ,green)))
-   `(all-the-icons-lblue ((,class :foreground ,blue-refine-fg)))
-   `(all-the-icons-lcyan ((,class :foreground ,cyan-refine-fg)))
-   `(all-the-icons-lgreen ((,class :foreground ,green-refine-fg)))
-   `(all-the-icons-lmaroon ((,class :foreground ,magenta-refine-fg)))
-   `(all-the-icons-lorange ((,class :foreground ,red-refine-fg)))
-   `(all-the-icons-lpink ((,class :foreground ,magenta-refine-fg)))
-   `(all-the-icons-lpurple ((,class :foreground ,magenta-refine-fg)))
-   `(all-the-icons-lred ((,class :foreground ,red-refine-fg)))
-   `(all-the-icons-lsilver ((,class :foreground ,fg-special-cold)))
-   `(all-the-icons-lyellow ((,class :foreground ,yellow-refine-fg)))
-   `(all-the-icons-maroon ((,class :foreground ,magenta)))
-   `(all-the-icons-orange ((,class :foreground ,red-alt)))
-   `(all-the-icons-pink ((,class :foreground ,magenta)))
-   `(all-the-icons-purple ((,class :foreground ,magenta-alt)))
-   `(all-the-icons-purple-alt ((,class :foreground ,magenta-alt-other)))
-   `(all-the-icons-red ((,class :foreground ,red)))
-   `(all-the-icons-red-alt ((,class :foreground ,red-alt)))
-   `(all-the-icons-silver ((,class :foreground ,fg-special-cold)))
-   `(all-the-icons-yellow ((,class :foreground ,yellow)))
-;;;;; annotate
-   `(annotate-annotation ((,class :inherit modus-theme-subtle-blue)))
-   `(annotate-annotation-secondary ((,class :inherit 
modus-theme-subtle-green)))
-   `(annotate-highlight ((,class :background ,blue-nuanced-bg :underline 
,blue-intense)))
-   `(annotate-highlight-secondary ((,class :background ,green-nuanced-bg 
:underline ,green-intense)))
-;;;;; anzu
-   `(anzu-match-1 ((,class :inherit modus-theme-subtle-cyan)))
-   `(anzu-match-2 ((,class :inherit modus-theme-subtle-green)))
-   `(anzu-match-3 ((,class :inherit modus-theme-subtle-yellow)))
-   `(anzu-mode-line ((,class :inherit bold :foreground ,green-active)))
-   `(anzu-mode-line-no-match ((,class :inherit bold :foreground ,red-active)))
-   `(anzu-replace-highlight ((,class :inherit modus-theme-refine-yellow 
:underline t)))
-   `(anzu-replace-to ((,class :inherit (modus-theme-intense-green bold))))
-;;;;; apropos
-   `(apropos-function-button ((,class :inherit button :foreground 
,magenta-alt-other)))
-   `(apropos-keybinding ((,class :inherit bold :foreground ,cyan)))
-   `(apropos-misc-button ((,class :inherit button :foreground 
,cyan-alt-other)))
-   `(apropos-property ((,class ,@(modus-vivendi-theme-bold-weight) :foreground 
,magenta-alt)))
-   `(apropos-symbol ((,class ,@(modus-vivendi-theme-bold-weight) :foreground 
,blue-alt-other)))
-   `(apropos-user-option-button ((,class :inherit button :foreground 
,green-alt-other)))
-   `(apropos-variable-button ((,class :inherit button :foreground ,blue)))
-;;;;; apt-sources-list
-   `(apt-sources-list-components ((,class :foreground ,cyan)))
-   `(apt-sources-list-options ((,class :foreground ,yellow)))
-   `(apt-sources-list-suite ((,class :foreground ,green)))
-   `(apt-sources-list-type ((,class :foreground ,magenta)))
-   `(apt-sources-list-uri ((,class :foreground ,blue)))
-;;;;; artbollocks-mode
-   `(artbollocks-face ((,class :foreground ,cyan-nuanced :underline 
,fg-lang-note)))
-   `(artbollocks-lexical-illusions-face ((,class :background ,bg-alt 
:foreground ,red-alt :underline t)))
-   `(artbollocks-passive-voice-face ((,class :foreground ,yellow-nuanced 
:underline ,fg-lang-warning)))
-   `(artbollocks-weasel-words-face ((,class :foreground ,red-nuanced 
:underline ,fg-lang-error)))
-;;;;; auctex and Tex
-   `(font-latex-bold-face ((,class :inherit bold :foreground 
,fg-special-calm)))
-   `(font-latex-doctex-documentation-face ((,class :foreground 
,fg-special-cold :slant ,modus-theme-slant)))
-   `(font-latex-doctex-preprocessor-face ((,class 
,@(modus-vivendi-theme-bold-weight) :foreground ,red-alt-other)))
-   `(font-latex-italic-face ((,class :foreground ,fg-special-calm :slant 
italic)))
-   `(font-latex-math-face ((,class :foreground ,cyan-alt-other)))
-   `(font-latex-script-char-face ((,class :foreground ,cyan-alt-other)))
-   `(font-latex-sectioning-0-face ((,class :inherit 
,modus-theme-variable-pitch :foreground ,blue-nuanced)))
-   `(font-latex-sectioning-1-face ((,class :inherit (bold 
,modus-theme-variable-pitch) :foreground ,blue-nuanced)))
-   `(font-latex-sectioning-2-face ((,class :inherit (bold 
,modus-theme-variable-pitch) :foreground ,blue-nuanced)))
-   `(font-latex-sectioning-3-face ((,class :inherit (bold 
,modus-theme-variable-pitch) :foreground ,blue-nuanced)))
-   `(font-latex-sectioning-4-face ((,class :inherit (bold 
,modus-theme-variable-pitch) :foreground ,blue-nuanced)))
-   `(font-latex-sectioning-5-face ((,class :inherit 
,modus-theme-variable-pitch :foreground ,blue-nuanced)))
-   `(font-latex-sedate-face ((,class ,@(modus-vivendi-theme-bold-weight) 
:foreground ,magenta-alt-other)))
-   `(font-latex-slide-title-face ((,class :inherit (bold 
,modus-theme-variable-pitch) :foreground ,cyan-nuanced
-                                          ,@(modus-vivendi-theme-scale 
modus-vivendi-theme-scale-4))))
-   `(font-latex-string-face ((,class :foreground ,blue-alt)))
-   `(font-latex-subscript-face ((,class :height 0.95)))
-   `(font-latex-superscript-face ((,class :height 0.95)))
-   `(font-latex-verbatim-face ((,class :background ,bg-dim :foreground 
,fg-special-mild)))
-   `(font-latex-warning-face ((,class :foreground ,yellow-alt-other)))
-   `(tex-match ((,class :foreground ,blue-alt-other)))
-   `(tex-verbatim ((,class :background ,bg-dim :foreground ,fg-special-mild)))
-   `(texinfo-heading ((,class :foreground ,magenta)))
-   `(TeX-error-description-error ((,class :inherit bold :foreground ,red)))
-   `(TeX-error-description-help ((,class :foreground ,blue)))
-   `(TeX-error-description-tex-said ((,class :foreground ,blue)))
-   `(TeX-error-description-warning ((,class :inherit bold :foreground 
,yellow)))
-;;;;; auto-dim-other-buffers
-   `(auto-dim-other-buffers-face ((,class :background ,bg-alt)))
-;;;;; avy
-   `(avy-background-face ((,class :background ,bg-dim :foreground ,fg-dim)))
-   `(avy-goto-char-timer-face ((,class :inherit (modus-theme-intense-yellow 
bold))))
-   `(avy-lead-face ((,class :inherit (modus-theme-intense-magenta bold))))
-   `(avy-lead-face-0 ((,class :inherit (modus-theme-intense-blue bold))))
-   `(avy-lead-face-1 ((,class :inherit (modus-theme-intense-red bold))))
-   `(avy-lead-face-2 ((,class :inherit (modus-theme-intense-green bold))))
-;;;;; aw (ace-window)
-   `(aw-background-face ((,class :background ,bg-dim :foreground ,fg-dim)))
-   `(aw-key-face ((,class :inherit bold :foreground ,blue-intense)))
-   `(aw-leading-char-face ((,class :inherit bold :height 1.5 :background 
,bg-main :foreground ,red-intense)))
-   `(aw-minibuffer-leading-char-face ((,class :foreground ,magenta-active)))
-   `(aw-mode-line-face ((,class :inherit bold)))
-;;;;; awesome-tray
-   `(awesome-tray-module-awesome-tab-face ((,class :inherit bold :foreground 
,red-alt-other)))
-   `(awesome-tray-module-battery-face ((,class :inherit bold :foreground 
,cyan-alt-other)))
-   `(awesome-tray-module-buffer-name-face ((,class :inherit bold :foreground 
,yellow-alt-other)))
-   `(awesome-tray-module-circe-face ((,class :inherit bold :foreground 
,blue-alt)))
-   `(awesome-tray-module-date-face ((,class :inherit bold :foreground 
,fg-dim)))
-   `(awesome-tray-module-evil-face ((,class :inherit bold :foreground 
,green-alt)))
-   `(awesome-tray-module-git-face ((,class :inherit bold :foreground 
,magenta)))
-   `(awesome-tray-module-last-command-face ((,class :inherit bold :foreground 
,blue-alt-other)))
-   `(awesome-tray-module-location-face ((,class :inherit bold :foreground 
,yellow)))
-   `(awesome-tray-module-mode-name-face ((,class :inherit bold :foreground 
,green)))
-   `(awesome-tray-module-parent-dir-face ((,class :inherit bold :foreground 
,cyan)))
-   `(awesome-tray-module-rvm-face ((,class :inherit bold :foreground 
,magenta-alt-other)))
-;;;;; binder
-   `(binder-sidebar-highlight ((,class :inherit modus-theme-subtle-cyan)))
-   `(binder-sidebar-marked ((,class :inherit modus-theme-mark-sel)))
-   `(binder-sidebar-missing ((,class :inherit modus-theme-subtle-red)))
-   `(binder-sidebar-tags ((,class :foreground ,cyan)))
-;;;;; bm
-   `(bm-face ((,class :inherit modus-theme-subtle-yellow
-                      ,@(and (>= emacs-major-version 27) '(:extend t)))))
-   `(bm-fringe-face ((,class :inherit modus-theme-fringe-yellow)))
-   `(bm-fringe-persistent-face ((,class :inherit modus-theme-fringe-blue)))
-   `(bm-persistent-face ((,class :inherit modus-theme-intense-blue
-                                 ,@(and (>= emacs-major-version 27) '(:extend 
t)))))
-;;;;; bongo
-   `(bongo-album-title ((,class :foreground ,cyan-active)))
-   `(bongo-artist ((,class :foreground ,magenta-active)))
-   `(bongo-currently-playing-track ((,class :inherit bold)))
-   `(bongo-elapsed-track-part ((,class :inherit modus-theme-subtle-magenta 
:underline t)))
-   `(bongo-filled-seek-bar ((,class :background ,blue-subtle-bg :foreground 
,fg-main)))
-   `(bongo-marked-track ((,class :foreground ,fg-mark-alt)))
-   `(bongo-marked-track-line ((,class :background ,bg-mark-alt)))
-   `(bongo-played-track ((,class :foreground ,fg-unfocused :strike-through t)))
-   `(bongo-track-length ((,class :foreground ,blue-alt-other)))
-   `(bongo-track-title ((,class :foreground ,blue-active)))
-   `(bongo-unfilled-seek-bar ((,class :background ,blue-nuanced-bg :foreground 
,fg-main)))
-;;;;; boon
-   `(boon-modeline-cmd ((,class :inherit modus-theme-active-blue)))
-   `(boon-modeline-ins ((,class :inherit modus-theme-active-red)))
-   `(boon-modeline-off ((,class :inherit modus-theme-active-yellow)))
-   `(boon-modeline-spc ((,class :inherit modus-theme-active-green)))
-;;;;; breakpoint (built-in gdb-mi.el)
-   `(breakpoint-disabled ((,class :foreground ,fg-alt)))
-   `(breakpoint-enabled ((,class :inherit bold :foreground ,red)))
-;;;;; buffer-expose
-   `(buffer-expose-ace-char-face ((,class :inherit bold :foreground 
,red-active)))
-   `(buffer-expose-mode-line-face ((,class :foreground ,cyan-active)))
-   `(buffer-expose-selected-face ((,class :inherit modus-theme-special-mild)))
-;;;;; calendar and diary
-   `(calendar-month-header ((,class :inherit bold :foreground ,fg-main)))
-   `(calendar-today ((,class :underline t)))
-   `(calendar-weekday-header ((,class :foreground ,fg-dim)))
-   `(calendar-weekend-header ((,class :foreground ,fg-alt)))
-   `(diary ((,class :foreground ,cyan-alt-other)))
-   `(diary-anniversary ((,class :foreground ,red-alt-other)))
-   `(diary-time ((,class :foreground ,blue-alt)))
-   `(holiday ((,class :foreground ,magenta-alt)))
-;;;;; calfw
-   `(cfw:face-annotation ((,class :foreground ,fg-special-warm)))
-   `(cfw:face-day-title ((,class :foreground ,fg-main)))
-   `(cfw:face-default-content ((,class :foreground ,green-alt)))
-   `(cfw:face-default-day ((,class :inherit (cfw:face-day-title bold))))
-   `(cfw:face-disable ((,class :foreground ,fg-unfocused)))
-   `(cfw:face-grid ((,class :foreground ,fg-window-divider-outer)))
-   `(cfw:face-header ((,class :inherit bold :foreground ,fg-main)))
-   `(cfw:face-holiday ((,class :foreground ,magenta-alt-other)))
-   `(cfw:face-periods ((,class :foreground ,cyan-alt-other)))
-   `(cfw:face-saturday ((,class :inherit bold :foreground ,cyan-alt-other)))
-   `(cfw:face-select ((,class :inherit modus-theme-intense-blue)))
-   `(cfw:face-sunday ((,class :inherit bold :foreground ,cyan-alt-other)))
-   `(cfw:face-title ((,class :inherit ,modus-theme-variable-pitch
-                             :foreground ,fg-special-cold
-                             ,@(modus-vivendi-theme-scale 
modus-vivendi-theme-scale-5))))
-   `(cfw:face-today ((,class :background ,bg-inactive)))
-   `(cfw:face-today-title ((,class :background ,bg-active)))
-   `(cfw:face-toolbar ((,class :background ,bg-alt :foreground ,bg-alt)))
-   `(cfw:face-toolbar-button-off ((,class :foreground ,fg-alt)))
-   `(cfw:face-toolbar-button-on ((,class :inherit bold :background 
,blue-nuanced-bg
-                                         :foreground ,blue-alt)))
-;;;;; centaur-tabs
-   `(centaur-tabs-active-bar-face ((,class :background ,fg-tab-active)))
-   `(centaur-tabs-close-mouse-face ((,class :inherit bold :foreground 
,red-active :underline t)))
-   `(centaur-tabs-close-selected ((,class :inherit centaur-tabs-selected)))
-   `(centaur-tabs-close-unselected ((,class :inherit centaur-tabs-unselected)))
-   `(centaur-tabs-modified-marker-selected ((,class :inherit 
centaur-tabs-selected)))
-   `(centaur-tabs-modified-marker-unselected ((,class :inherit 
centaur-tabs-unselected)))
-   `(centaur-tabs-default ((,class :background ,bg-main :foreground ,bg-main)))
-   `(centaur-tabs-selected ((,class :inherit bold :background ,bg-tab-active 
:foreground ,fg-main)))
-   `(centaur-tabs-selected-modified ((,class :background ,bg-tab-active 
:foreground ,fg-main :slant italic)))
-   `(centaur-tabs-unselected ((,class :background ,bg-tab-inactive :foreground 
,fg-dim)))
-   `(centaur-tabs-unselected-modified ((,class :background ,bg-tab-inactive 
:foreground ,fg-dim :slant italic)))
-;;;;; change-log and log-view (`vc-print-log' and `vc-print-root-log')
-   `(change-log-acknowledgment ((,class :foreground ,fg-alt)))
-   `(change-log-conditionals ((,class :foreground ,magenta-alt)))
-   `(change-log-date ((,class :foreground ,cyan-alt-other)))
-   `(change-log-email ((,class :foreground ,cyan)))
-   `(change-log-file ((,class :foreground ,blue)))
-   `(change-log-function ((,class :foreground ,green-alt-other)))
-   `(change-log-list ((,class :foreground ,magenta-alt-other)))
-   `(change-log-name ((,class :foreground ,cyan)))
-   `(log-edit-header ((,class :foreground ,fg-special-warm)))
-   `(log-edit-summary ((,class :inherit bold :foreground ,cyan)))
-   `(log-edit-unknown-header ((,class :foreground ,fg-alt)))
-   `(log-view-file ((,class :inherit bold :foreground ,fg-special-cold)))
-   `(log-view-message ((,class :foreground ,fg-alt)))
-;;;;; cider
-   `(cider-debug-code-overlay-face ((,class :background ,bg-alt)))
-   `(cider-debug-prompt-face ((,class :foreground ,magenta-alt :underline t)))
-   `(cider-deprecated-face ((,class :inherit modus-theme-refine-yellow)))
-   `(cider-docview-emphasis-face ((,class :foreground ,fg-special-cold :slant 
italic)))
-   `(cider-docview-literal-face ((,class :foreground ,blue-alt)))
-   `(cider-docview-strong-face ((,class :inherit bold :foreground 
,fg-special-cold)))
-   `(cider-docview-table-border-face ((,class :foreground ,fg-alt)))
-   `(cider-enlightened-face ((,class :box (:line-width -1 :color ,yellow-alt 
:style nil) :background ,bg-dim)))
-   `(cider-enlightened-local-face ((,class :inherit bold :foreground 
,yellow-alt-other)))
-   `(cider-error-highlight-face ((,class :foreground ,red :underline t)))
-   `(cider-fragile-button-face ((,class :box (:line-width 3 :color ,fg-alt 
:style released-button) :foreground ,yellow)))
-   `(cider-fringe-good-face ((,class :foreground ,green-active)))
-   `(cider-instrumented-face ((,class :box (:line-width -1 :color ,red :style 
nil) :background ,bg-dim)))
-   `(cider-reader-conditional-face ((,class :foreground ,fg-special-warm 
:slant italic)))
-   `(cider-repl-input-face ((,class :inherit bold)))
-   `(cider-repl-prompt-face ((,class :foreground ,cyan-alt-other)))
-   `(cider-repl-stderr-face ((,class :inherit bold :foreground ,red)))
-   `(cider-repl-stdout-face ((,class :foreground ,blue)))
-   `(cider-result-overlay-face ((,class :box (:line-width -1 :color ,blue 
:style nil) :background ,bg-dim)))
-   `(cider-stacktrace-error-class-face ((,class :inherit bold :foreground 
,red)))
-   `(cider-stacktrace-error-message-face ((,class :foreground ,red-alt-other 
:slant italic)))
-   `(cider-stacktrace-face ((,class :foreground ,fg-main)))
-   `(cider-stacktrace-filter-active-face ((,class :foreground ,cyan-alt 
:underline t)))
-   `(cider-stacktrace-filter-inactive-face ((,class :foreground ,cyan-alt)))
-   `(cider-stacktrace-fn-face ((,class :inherit bold :foreground ,fg-main)))
-   `(cider-stacktrace-ns-face ((,class :foreground ,fg-alt :slant italic)))
-   `(cider-stacktrace-promoted-button-face ((,class :box (:line-width 3 :color 
,fg-alt :style released-button) :foreground ,red)))
-   `(cider-stacktrace-suppressed-button-face ((,class :box (:line-width 3 
:color ,fg-alt :style pressed-button)
-                                                      :background ,bg-alt 
:foreground ,fg-alt)))
-   `(cider-test-error-face ((,class :inherit modus-theme-subtle-red)))
-   `(cider-test-failure-face ((,class :inherit (modus-theme-intense-red 
bold))))
-   `(cider-test-success-face ((,class :inherit modus-theme-intense-green)))
-   `(cider-traced-face ((,class :box (:line-width -1 :color ,cyan :style nil) 
:background ,bg-dim)))
-   `(cider-warning-highlight-face ((,class :foreground ,yellow :underline t)))
-;;;;; circe (and lui)
-   `(circe-fool-face ((,class :foreground ,fg-alt)))
-   `(circe-highlight-nick-face ((,class :inherit bold :foreground ,blue)))
-   `(circe-prompt-face ((,class :inherit bold :foreground ,cyan-alt-other)))
-   `(circe-server-face ((,class :foreground ,fg-unfocused)))
-   `(lui-button-face ((,class :inherit button :foreground ,blue)))
-   `(lui-highlight-face ((,class :foreground ,magenta-alt)))
-   `(lui-time-stamp-face ((,class :foreground ,blue-nuanced)))
-;;;;; color-rg
-   `(color-rg-font-lock-column-number ((,class :foreground 
,magenta-alt-other)))
-   `(color-rg-font-lock-command ((,class :inherit bold :foreground ,fg-main)))
-   `(color-rg-font-lock-file ((,class :inherit bold :foreground 
,fg-special-cold)))
-   `(color-rg-font-lock-flash ((,class :inherit modus-theme-intense-blue)))
-   `(color-rg-font-lock-function-location ((,class :inherit 
modus-theme-special-calm)))
-   `(color-rg-font-lock-header-line-directory ((,class :foreground 
,blue-active)))
-   `(color-rg-font-lock-header-line-edit-mode ((,class :foreground 
,magenta-active)))
-   `(color-rg-font-lock-header-line-keyword ((,class :foreground 
,green-active)))
-   `(color-rg-font-lock-header-line-text ((,class :foreground ,fg-active)))
-   `(color-rg-font-lock-line-number ((,class :foreground ,fg-special-warm)))
-   `(color-rg-font-lock-mark-changed ((,class :inherit bold :foreground 
,blue)))
-   `(color-rg-font-lock-mark-deleted ((,class :inherit bold :foreground ,red)))
-   `(color-rg-font-lock-match ((,class :inherit modus-theme-special-calm)))
-   `(color-rg-font-lock-position-splitter ((,class :foreground ,fg-alt)))
-;;;;; column-enforce-mode
-   `(column-enforce-face ((,class :inherit modus-theme-refine-yellow)))
-;;;;; company-mode
-   `(company-echo-common ((,class :foreground ,magenta-alt-other)))
-   `(company-preview ((,class :background ,bg-dim :foreground ,fg-dim)))
-   `(company-preview-common ((,class :foreground ,blue-alt)))
-   `(company-preview-search ((,class :inherit modus-theme-special-calm)))
-   `(company-scrollbar-bg ((,class :background ,bg-active)))
-   `(company-scrollbar-fg ((,class :background ,fg-active)))
-   `(company-template-field ((,class :inherit modus-theme-intense-magenta)))
-   `(company-tooltip ((,class :background ,bg-alt :foreground ,fg-alt)))
-   `(company-tooltip-annotation ((,class :foreground ,fg-special-cold :slant 
,modus-theme-slant)))
-   `(company-tooltip-annotation-selection ((,class :inherit bold :foreground 
,fg-main)))
-   `(company-tooltip-common ((,class :inherit bold :foreground ,blue-alt)))
-   `(company-tooltip-common-selection ((,class :foreground ,fg-main)))
-   `(company-tooltip-mouse ((,class :inherit modus-theme-intense-blue)))
-   `(company-tooltip-search ((,class :inherit (modus-theme-refine-cyan bold))))
-   `(company-tooltip-search-selection ((,class :inherit 
(modus-theme-intense-green bold) :underline t)))
-   `(company-tooltip-selection ((,class :inherit (modus-theme-subtle-cyan 
bold))))
-;;;;; company-posframe
-   `(company-posframe-active-backend-name ((,class :inherit bold :background 
,bg-active :foreground ,blue-active)))
-   `(company-posframe-inactive-backend-name ((,class :background ,bg-active 
:foreground ,fg-active)))
-   `(company-posframe-metadata ((,class :background ,bg-inactive :foreground 
,fg-inactive)))
-;;;;; compilation feedback
-   `(compilation-column-number ((,class :foreground ,magenta-alt-other)))
-   `(compilation-error ((,class ,@(modus-vivendi-theme-bold-weight) 
:foreground ,red)))
-   `(compilation-info ((,class :foreground ,fg-special-cold)))
-   `(compilation-line-number ((,class :foreground ,fg-special-warm)))
-   `(compilation-mode-line-exit ((,class ,@(modus-vivendi-theme-bold-weight) 
:foreground ,blue-active)))
-   `(compilation-mode-line-fail ((,class ,@(modus-vivendi-theme-bold-weight) 
:foreground ,red-active)))
-   `(compilation-mode-line-run ((,class ,@(modus-vivendi-theme-bold-weight) 
:foreground ,magenta-active)))
-   `(compilation-warning ((,class ,@(modus-vivendi-theme-bold-weight) 
:foreground ,yellow)))
-;;;;; completions
-   `(completions-annotations ((,class :foreground ,fg-special-cold :slant 
,modus-theme-slant)))
-   `(completions-common-part ((,class 
,@(modus-vivendi-theme-standard-completions
-                                         blue-alt blue-nuanced-bg
-                                         cyan-refine-bg cyan-refine-fg))))
-   `(completions-first-difference ((,class :inherit bold
-                                           
,@(modus-vivendi-theme-standard-completions
-                                              magenta-alt blue-nuanced-bg
-                                              magenta-intense-bg fg-main))))
-;;;;; counsel
-   `(counsel-active-mode ((,class :foreground ,magenta-alt-other)))
-   `(counsel-application-name ((,class :foreground ,red-alt-other)))
-   `(counsel-key-binding ((,class :inherit bold :foreground ,blue-alt-other)))
-   `(counsel-outline-1 ((,class :inherit outline-1)))
-   `(counsel-outline-2 ((,class :inherit outline-2)))
-   `(counsel-outline-3 ((,class :inherit outline-3)))
-   `(counsel-outline-4 ((,class :inherit outline-4)))
-   `(counsel-outline-5 ((,class :inherit outline-5)))
-   `(counsel-outline-6 ((,class :inherit outline-6)))
-   `(counsel-outline-7 ((,class :inherit outline-7)))
-   `(counsel-outline-8 ((,class :inherit outline-8)))
-   `(counsel-outline-default ((,class :inherit bold :foreground 
,green-alt-other)))
-   `(counsel-variable-documentation ((,class :foreground ,yellow-alt-other 
:slant ,modus-theme-slant)))
-;;;;; counsel-css
-   `(counsel-css-selector-depth-face-1 ((,class :foreground ,blue)))
-   `(counsel-css-selector-depth-face-2 ((,class :foreground ,cyan)))
-   `(counsel-css-selector-depth-face-3 ((,class :foreground ,green)))
-   `(counsel-css-selector-depth-face-4 ((,class :foreground ,yellow)))
-   `(counsel-css-selector-depth-face-5 ((,class :foreground ,magenta)))
-   `(counsel-css-selector-depth-face-6 ((,class :foreground ,red)))
-;;;;; counsel-notmuch
-   `(counsel-notmuch-count-face ((,class :foreground ,cyan)))
-   `(counsel-notmuch-date-face ((,class :foreground ,blue)))
-   `(counsel-notmuch-people-face ((,class :foreground ,magenta)))
-   `(counsel-notmuch-subject-face ((,class :foreground ,magenta-alt-other)))
-;;;;; counsel-org-capture-string
-   `(counsel-org-capture-string-template-body-face ((,class :foreground 
,fg-special-cold)))
-;;;;; cov
-   `(cov-coverage-not-run-face ((,class :foreground ,red-intense)))
-   `(cov-coverage-run-face ((,class :foreground ,green-intense)))
-   `(cov-heavy-face ((,class :foreground ,magenta-intense)))
-   `(cov-light-face ((,class :foreground ,blue-intense)))
-   `(cov-med-face ((,class :foreground ,yellow-intense)))
-   `(cov-none-face ((,class :foreground ,cyan-intense)))
-;;;;; cperl-mode
-   `(cperl-nonoverridable-face ((,class :foreground ,yellow-alt-other)))
-   `(cperl-array-face ((,class :inherit bold :background ,bg-alt :foreground 
,magenta-alt)))
-   `(cperl-hash-face ((,class :inherit bold :background ,bg-alt :foreground 
,red-alt :slant ,modus-theme-slant)))
-;;;;; csv-mode
-   `(csv-separator-face ((,class :background ,bg-special-cold :foreground 
,fg-main)))
-;;;;; ctrlf
-   `(ctrlf-highlight-active ((,class :inherit (modus-theme-intense-green 
bold))))
-   `(ctrlf-highlight-line ((,class :inherit modus-theme-hl-line)))
-   `(ctrlf-highlight-passive ((,class :inherit modus-theme-refine-cyan)))
-;;;;; custom (M-x customize)
-   `(custom-button ((,class :box (:line-width 2 :color nil :style 
released-button)
-                            :background ,bg-active :foreground ,fg-main)))
-   `(custom-button-mouse ((,class :box (:line-width 2 :color nil :style 
released-button)
-                                  :background ,bg-active :foreground 
,fg-active)))
-   `(custom-button-pressed ((,class :box (:line-width 2 :color nil :style 
pressed-button)
-                                    :background ,bg-active :foreground 
,fg-main)))
-   `(custom-changed ((,class :inherit modus-theme-subtle-cyan)))
-   `(custom-comment ((,class :foreground ,fg-alt)))
-   `(custom-comment-tag ((,class :background ,bg-alt :foreground 
,yellow-alt-other)))
-   `(custom-face-tag ((,class :inherit bold :foreground ,blue-intense)))
-   `(custom-group-tag ((,class :inherit bold :foreground ,green-intense)))
-   `(custom-group-tag-1 ((,class :inherit modus-theme-special-warm)))
-   `(custom-invalid ((,class :inherit (modus-theme-intense-red bold))))
-   `(custom-modified ((,class :inherit modus-theme-subtle-cyan)))
-   `(custom-rogue ((,class :inherit modus-theme-refine-magenta)))
-   `(custom-set ((,class :foreground ,blue-alt)))
-   `(custom-state ((,class :foreground ,cyan-alt-other)))
-   `(custom-themed ((,class :inherit modus-theme-subtle-blue)))
-   `(custom-variable-tag ((,class :inherit bold :foreground ,cyan)))
-;;;;; dap-mode
-   `(dap-mouse-eval-thing-face ((,class :box (:line-width -1 :color 
,blue-active :style nil)
-                                        :background ,bg-active :foreground 
,fg-main)))
-   `(dap-result-overlay-face ((,class :box (:line-width -1 :color ,bg-active 
:style nil)
-                                      :background ,bg-active :foreground 
,fg-main)))
-   `(dap-ui-breakpoint-verified-fringe ((,class :inherit bold :foreground 
,green-active)))
-   `(dap-ui-compile-errline ((,class :inherit bold :foreground ,red-intense)))
-   `(dap-ui-locals-scope-face ((,class :inherit bold :foreground ,magenta 
:underline t)))
-   `(dap-ui-locals-variable-face ((,class :inherit bold :foreground ,cyan)))
-   `(dap-ui-locals-variable-leaf-face ((,class :foreground ,cyan-alt-other 
:slant italic)))
-   `(dap-ui-marker-face ((,class :inherit modus-theme-subtle-blue)))
-   `(dap-ui-sessions-stack-frame-face ((,class :inherit bold :foreground 
,magenta-alt)))
-   `(dap-ui-sessions-terminated-active-face ((,class :inherit bold :foreground 
,fg-alt)))
-   `(dap-ui-sessions-terminated-face ((,class :foreground ,fg-alt)))
-;;;;; dashboard (emacs-dashboard)
-   `(dashboard-banner-logo-title ((,class :inherit bold :foreground 
,fg-special-cold)))
-   `(dashboard-footer ((,class :inherit bold :foreground ,fg-special-mild)))
-   `(dashboard-heading ((,class :inherit bold :foreground ,fg-special-warm)))
-   `(dashboard-navigator ((,class :foreground ,cyan-alt-other)))
-   `(dashboard-text-banner ((,class :foreground ,fg-dim)))
-;;;;; deadgrep
-   `(deadgrep-filename-face ((,class :inherit bold :foreground 
,fg-special-cold)))
-   `(deadgrep-match-face ((,class :inherit modus-theme-special-calm)))
-   `(deadgrep-meta-face ((,class :foreground ,fg-alt)))
-   `(deadgrep-regexp-metachar-face ((,class :inherit bold :foreground 
,yellow-intense)))
-   `(deadgrep-search-term-face ((,class :inherit bold :foreground 
,green-intense)))
-;;;;; debbugs
-   `(debbugs-gnu-archived ((,class :inverse-video t)))
-   `(debbugs-gnu-done ((,class :foreground ,fg-alt)))
-   `(debbugs-gnu-forwarded ((,class :foreground ,fg-special-warm)))
-   `(debbugs-gnu-handled ((,class :foreground ,green)))
-   `(debbugs-gnu-new ((,class :foreground ,red)))
-   `(debbugs-gnu-pending ((,class :foreground ,cyan)))
-   `(debbugs-gnu-stale-1 ((,class :foreground ,yellow-nuanced)))
-   `(debbugs-gnu-stale-2 ((,class :foreground ,yellow)))
-   `(debbugs-gnu-stale-3 ((,class :foreground ,yellow-alt)))
-   `(debbugs-gnu-stale-4 ((,class :foreground ,yellow-alt-other)))
-   `(debbugs-gnu-stale-5 ((,class :foreground ,red-alt)))
-   `(debbugs-gnu-tagged ((,class :foreground ,magenta-alt)))
-;;;;; define-word
-   `(define-word-face-1 ((,class :foreground ,yellow)))
-   `(define-word-face-2 ((,class :foreground ,fg-main)))
-;;;;; deft
-   `(deft-filter-string-error-face ((,class :inherit modus-theme-refine-red)))
-   `(deft-filter-string-face ((,class :foreground ,green-intense)))
-   `(deft-header-face ((,class :inherit bold :foreground ,fg-special-warm)))
-   `(deft-separator-face ((,class :foreground ,fg-alt)))
-   `(deft-summary-face ((,class :foreground ,fg-alt :slant 
,modus-theme-slant)))
-   `(deft-time-face ((,class :foreground ,fg-special-cold)))
-   `(deft-title-face ((,class :inherit bold :foreground ,fg-main)))
-;;;;; dictionary
-   `(dictionary-button-face ((,class :inherit bold :foreground 
,fg-special-cold)))
-   `(dictionary-reference-face ((,class :inherit button :foreground 
,blue-alt-other)))
-   `(dictionary-word-definition-face ((,class :foreground ,fg-main)))
-   `(dictionary-word-entry-face ((,class :foreground ,fg-special-cold :slant 
,modus-theme-slant)))
-;;;;; diff-hl
-   `(diff-hl-change ((,class :inherit modus-theme-fringe-yellow)))
-   `(diff-hl-delete ((,class :inherit modus-theme-fringe-red)))
-   `(diff-hl-dired-change ((,class :inherit diff-hl-change)))
-   `(diff-hl-dired-delete ((,class :inherit diff-hl-delete)))
-   `(diff-hl-dired-ignored ((,class :inherit dired-ignored)))
-   `(diff-hl-dired-insert ((,class :inherit diff-hl-insert)))
-   `(diff-hl-dired-unknown ((,class :inherit dired-ignored)))
-   `(diff-hl-insert ((,class :inherit modus-theme-fringe-green)))
-   `(diff-hl-reverted-hunk-highlight ((,class :inherit 
(modus-theme-active-magenta bold))))
-;;;;; diff-mode
-   `(diff-added ((,class :inherit modus-theme-diff-added)))
-   `(diff-changed ((,class :inherit modus-theme-diff-changed)))
-   `(diff-context ((,class :foreground ,fg-unfocused)))
-   `(diff-file-header ((,class :inherit bold :foreground ,blue)))
-   `(diff-function ((,class :foreground ,fg-special-cold)))
-   `(diff-header ((,class :foreground ,blue-nuanced)))
-   `(diff-hunk-header ((,class :inherit modus-theme-diff-heading)))
-   `(diff-index ((,class :inherit bold :foreground ,blue-alt)))
-   `(diff-indicator-added ((,class :inherit diff-added)))
-   `(diff-indicator-changed ((,class :inherit diff-changed)))
-   `(diff-indicator-removed ((,class :inherit diff-removed)))
-   `(diff-nonexistent ((,class :inherit (modus-theme-neutral bold))))
-   `(diff-refine-added ((,class :inherit modus-theme-diff-refine-added)))
-   `(diff-refine-changed ((,class :inherit modus-theme-diff-refine-changed)))
-   `(diff-refine-removed ((,class :inherit modus-theme-diff-refine-removed)))
-   `(diff-removed ((,class :inherit modus-theme-diff-removed)))
-;;;;; dim-autoload
-   `(dim-autoload-cookie-line ((,class :foreground ,fg-alt :slant 
,modus-theme-slant)))
-;;;;; dir-treeview
-   `(dir-treeview-archive-face ((,class :foreground ,fg-special-warm)))
-   `(dir-treeview-archive-icon-face ((,class :inherit 
dir-treeview-default-icon-face :foreground ,yellow)))
-   `(dir-treeview-audio-face ((,class :foreground ,magenta)))
-   `(dir-treeview-audio-icon-face ((,class :inherit 
dir-treeview-default-icon-face :foreground ,magenta-alt)))
-   `(dir-treeview-control-face ((,class :foreground ,fg-alt)))
-   `(dir-treeview-control-mouse-face ((,class :inherit highlight)))
-   `(dir-treeview-default-icon-face ((,class :inherit bold :family "Font 
Awesome" :foreground ,fg-alt)))
-   `(dir-treeview-default-filename-face ((,class :foreground ,fg-main)))
-   `(dir-treeview-directory-face ((,class :foreground ,blue)))
-   `(dir-treeview-directory-icon-face ((,class :inherit 
dir-treeview-default-icon-face :foreground ,blue-alt)))
-   `(dir-treeview-executable-face ((,class :foreground ,red-alt)))
-   `(dir-treeview-executable-icon-face ((,class :inherit 
dir-treeview-default-icon-face :foreground ,red-alt-other)))
-   `(dir-treeview-image-face ((,class :foreground ,green-alt-other)))
-   `(dir-treeview-image-icon-face ((,class :inherit 
dir-treeview-default-icon-face :foreground ,green-alt)))
-   `(dir-treeview-indent-face ((,class :foreground ,fg-alt)))
-   `(dir-treeview-label-mouse-face ((,class :inherit highlight)))
-   `(dir-treeview-start-dir-face ((,class :inherit modus-theme-pseudo-header)))
-   `(dir-treeview-symlink-face ((,class :inherit button :foreground ,cyan)))
-   `(dir-treeview-video-face ((,class :foreground ,magenta-alt-other)))
-   `(dir-treeview-video-icon-face ((,class :inherit 
dir-treeview-default-icon-face :foreground ,magenta-alt-other)))
-;;;;; dired
-   `(dired-directory ((,class :foreground ,blue)))
-   `(dired-flagged ((,class :inherit modus-theme-mark-del)))
-   `(dired-header ((,class :inherit modus-theme-pseudo-header)))
-   `(dired-ignored ((,class :foreground ,fg-alt)))
-   `(dired-mark ((,class :inherit modus-theme-mark-symbol)))
-   `(dired-marked ((,class :inherit modus-theme-mark-sel)))
-   `(dired-perm-write ((,class :foreground ,fg-special-warm)))
-   `(dired-symlink ((,class :inherit button :foreground ,cyan-alt)))
-   `(dired-warning ((,class :inherit bold :foreground ,yellow)))
-;;;;; dired-async
-   `(dired-async-failures ((,class ,@(modus-vivendi-theme-bold-weight) 
:foreground ,red-active)))
-   `(dired-async-message ((,class ,@(modus-vivendi-theme-bold-weight) 
:foreground ,green-active)))
-   `(dired-async-mode-message ((,class ,@(modus-vivendi-theme-bold-weight) 
:foreground ,cyan-active)))
-;;;;; dired-git
-   `(dired-git-branch-else ((,class :inherit bold :foreground ,magenta-alt)))
-   `(dired-git-branch-master ((,class :inherit bold :foreground 
,magenta-alt-other)))
-;;;;; dired-git-info
-   `(dgi-commit-message-face ((,class :foreground ,fg-special-mild)))
-;;;;; dired-narrow
-   `(dired-narrow-blink ((,class :inherit (modus-theme-subtle-cyan bold))))
-;;;;; dired-subtree
-   ;; remove background from dired-subtree, else it breaks
-   ;; dired-{flagged,marked} and any other face that sets a background
-   ;; such as hl-line
-   `(dired-subtree-depth-1-face ((,class :background nil)))
-   `(dired-subtree-depth-2-face ((,class :background nil)))
-   `(dired-subtree-depth-3-face ((,class :background nil)))
-   `(dired-subtree-depth-4-face ((,class :background nil)))
-   `(dired-subtree-depth-5-face ((,class :background nil)))
-   `(dired-subtree-depth-6-face ((,class :background nil)))
-;;;;; diredfl
-   `(diredfl-autofile-name ((,class :inherit modus-theme-special-cold)))
-   `(diredfl-compressed-file-name ((,class :foreground ,fg-special-warm)))
-   `(diredfl-compressed-file-suffix ((,class :foreground ,red-alt)))
-   `(diredfl-date-time ((,class :foreground ,cyan-alt-other)))
-   `(diredfl-deletion ((,class :inherit modus-theme-mark-del)))
-   `(diredfl-deletion-file-name ((,class :inherit modus-theme-mark-del)))
-   `(diredfl-dir-heading ((,class :inherit modus-theme-pseudo-header)))
-   `(diredfl-dir-name ((,class :inherit dired-directory)))
-   `(diredfl-dir-priv ((,class :foreground ,blue-alt)))
-   `(diredfl-exec-priv ((,class :foreground ,magenta)))
-   `(diredfl-executable-tag ((,class :foreground ,magenta-alt)))
-   `(diredfl-file-name ((,class :foreground ,fg-main)))
-   `(diredfl-file-suffix ((,class :foreground ,cyan)))
-   `(diredfl-flag-mark ((,class :inherit modus-theme-mark-sel)))
-   `(diredfl-flag-mark-line ((,class :inherit modus-theme-mark-sel)))
-   `(diredfl-ignored-file-name ((,class :foreground ,fg-alt)))
-   `(diredfl-link-priv ((,class :foreground ,blue-alt-other)))
-   `(diredfl-no-priv ((,class :foreground ,fg-alt)))
-   `(diredfl-number ((,class :foreground ,cyan-alt)))
-   `(diredfl-other-priv ((,class :foreground ,yellow)))
-   `(diredfl-rare-priv ((,class :foreground ,red-alt)))
-   `(diredfl-read-priv ((,class :foreground ,fg-main)))
-   `(diredfl-symlink ((,class :inherit dired-symlink)))
-   `(diredfl-tagged-autofile-name ((,class :inherit 
modus-theme-refine-magenta)))
-   `(diredfl-write-priv ((,class :foreground ,cyan)))
-;;;;; disk-usage
-   `(disk-usage-children ((,class :foreground ,yellow)))
-   `(disk-usage-inaccessible ((,class :inherit bold :foreground ,red)))
-   `(disk-usage-percent ((,class :foreground ,green)))
-   `(disk-usage-size ((,class :foreground ,cyan)))
-   `(disk-usage-symlink ((,class :inherit button :foreground ,blue)))
-   `(disk-usage-symlink-directory ((,class :inherit bold :foreground 
,blue-alt)))
-;;;;; doom-modeline
-   `(doom-modeline-bar ((,class :inherit modus-theme-active-blue)))
-   `(doom-modeline-bar-inactive ((,class :background ,fg-inactive :foreground 
,bg-main)))
-   `(doom-modeline-battery-charging ((,class :foreground ,green-active)))
-   `(doom-modeline-battery-critical ((,class :inherit bold :foreground 
,red-active)))
-   `(doom-modeline-battery-error ((,class :inherit bold :box (:line-width -2)
-                                          :foreground ,red-active)))
-   `(doom-modeline-battery-full ((,class :foreground ,blue-active)))
-   `(doom-modeline-battery-normal ((,class :foreground ,fg-active)))
-   `(doom-modeline-battery-warning ((,class :inherit bold :foreground 
,yellow-active)))
-   `(doom-modeline-buffer-file ((,class :inherit bold :foreground ,fg-active)))
-   `(doom-modeline-buffer-major-mode ((,class :inherit bold :foreground 
,cyan-active)))
-   `(doom-modeline-buffer-minor-mode ((,class :foreground ,fg-inactive)))
-   `(doom-modeline-buffer-modified ((,class :inherit bold :foreground 
,magenta-active)))
-   `(doom-modeline-buffer-path ((,class :inherit bold :foreground ,fg-active)))
-   `(doom-modeline-debug ((,class :inherit bold :foreground ,yellow-active)))
-   `(doom-modeline-debug-visual ((,class :inherit bold :foreground 
,red-active)))
-   `(doom-modeline-evil-emacs-state ((,class :inherit bold :foreground 
,magenta-active)))
-   `(doom-modeline-evil-insert-state ((,class :inherit bold :foreground 
,green-active)))
-   `(doom-modeline-evil-motion-state ((,class :inherit bold :foreground 
,fg-inactive)))
-   `(doom-modeline-evil-normal-state ((,class :inherit bold :foreground 
,fg-active)))
-   `(doom-modeline-evil-operator-state ((,class :inherit bold :foreground 
,blue-active)))
-   `(doom-modeline-evil-replace-state ((,class :inherit bold :foreground 
,red-active)))
-   `(doom-modeline-evil-visual-state ((,class :inherit bold :foreground 
,cyan-active)))
-   `(doom-modeline-highlight ((,class :inherit bold :foreground ,blue-active)))
-   `(doom-modeline-host ((,class :slant italic)))
-   `(doom-modeline-info ((,class :foreground ,green-active)))
-   `(doom-modeline-lsp-error ((,class :inherit bold :foreground ,red-active)))
-   `(doom-modeline-lsp-success ((,class :inherit bold :foreground 
,green-active)))
-   `(doom-modeline-lsp-warning ((,class :inherit bold :foreground 
,yellow-active)))
-   `(doom-modeline-panel ((,class :inherit modus-theme-active-blue)))
-   `(doom-modeline-persp-buffer-not-in-persp ((,class :foreground 
,yellow-active :slant italic)))
-   `(doom-modeline-persp-name ((,class :foreground ,fg-active)))
-   `(doom-modeline-project-dir ((,class :inherit bold :foreground 
,blue-active)))
-   `(doom-modeline-project-parent-dir ((,class :foreground ,blue-active)))
-   `(doom-modeline-project-root-dir ((,class :foreground ,fg-active)))
-   `(doom-modeline-unread-number ((,class :foreground ,fg-active :slant 
italic)))
-   `(doom-modeline-urgent ((,class :inherit bold :foreground ,red-active)))
-   `(doom-modeline-warning ((,class :inherit bold :foreground ,yellow-active)))
-;;;;; dynamic-ruler
-   `(dynamic-ruler-negative-face ((,class :inherit 
modus-theme-intense-neutral)))
-   `(dynamic-ruler-positive-face ((,class :inherit 
modus-theme-intense-yellow)))
-;;;;; easy-jekyll
-   `(easy-jekyll-help-face ((,class :background ,bg-dim :foreground 
,cyan-alt-other)))
-;;;;; easy-kill
-   `(easy-kill-origin ((,class :inherit modus-theme-subtle-red)))
-   `(easy-kill-selection ((,class :inherit modus-theme-subtle-yellow)))
-;;;;; ebdb
-   `(ebdb-address-default ((,class :foreground ,fg-main)))
-   `(ebdb-db-char ((,class :foreground ,fg-special-cold)))
-   `(ebdb-defunct ((,class :foreground ,fg-alt)))
-   `(ebdb-field-hidden ((,class :foreground ,magenta)))
-   `(ebdb-field-url ((,class :foreground ,blue)))
-   `(ebdb-label ((,class :foreground ,cyan-alt-other)))
-   `(ebdb-mail-default ((,class :foreground ,fg-main)))
-   `(ebdb-mail-primary ((,class :foreground ,blue-alt)))
-   `(ebdb-marked ((,class :background ,cyan-intense-bg)))
-   `(ebdb-organization-name ((,class :foreground ,fg-special-calm)))
-   `(ebdb-person-name ((,class :foreground ,magenta-alt-other)))
-   `(ebdb-phone-default ((,class :foreground ,fg-special-warm)))
-   `(ebdb-role-defunct ((,class :foreground ,fg-alt)))
-   `(eieio-custom-slot-tag-face ((,class :foreground ,red-alt)))
-;;;;; ediff
-   ;; NOTE: here we break from the pattern of inheriting from the
-   ;; modus-theme-diff-* faces.
-   `(ediff-current-diff-A ((,class ,@(modus-vivendi-theme-diff
-                                      bg-dim red
-                                      bg-diff-removed fg-diff-removed
-                                      red-nuanced-bg red-faint))))
-   `(ediff-current-diff-Ancestor ((,class ,@(modus-vivendi-theme-diff
-                                             bg-dim fg-special-cold
-                                             bg-special-cold fg-special-cold
-                                             blue-nuanced-bg blue))))
-   `(ediff-current-diff-B ((,class ,@(modus-vivendi-theme-diff
-                                      bg-dim green
-                                      bg-diff-added fg-diff-added
-                                      green-nuanced-bg green-faint))))
-   `(ediff-current-diff-C ((,class ,@(modus-vivendi-theme-diff
-                                      bg-dim yellow
-                                      bg-diff-changed fg-diff-changed
-                                      yellow-nuanced-bg yellow-faint))))
-   `(ediff-even-diff-A ((,class :background ,bg-diff-neutral-1 :foreground 
,fg-diff-neutral-1)))
-   `(ediff-even-diff-Ancestor ((,class :background ,bg-diff-neutral-2 
:foreground ,fg-diff-neutral-1)))
-   `(ediff-even-diff-B ((,class :background ,bg-diff-neutral-1 :foreground 
,fg-diff-neutral-1)))
-   `(ediff-even-diff-C ((,class :background ,bg-diff-neutral-2 :foreground 
,fg-diff-neutral-2)))
-   `(ediff-fine-diff-A ((,class :background ,bg-diff-focus-removed :foreground 
,fg-diff-focus-removed)))
-   `(ediff-fine-diff-Ancestor ((,class :inherit modus-theme-refine-cyan)))
-   `(ediff-fine-diff-B ((,class :background ,bg-diff-focus-added :foreground 
,fg-diff-focus-added)))
-   `(ediff-fine-diff-C ((,class :background ,bg-diff-focus-changed :foreground 
,fg-diff-focus-changed)))
-   `(ediff-odd-diff-A ((,class :background ,bg-diff-neutral-2 :foreground 
,fg-diff-neutral-2)))
-   `(ediff-odd-diff-Ancestor ((,class :background ,bg-diff-neutral-0 
:foreground ,fg-diff-neutral-0)))
-   `(ediff-odd-diff-B ((,class :background ,bg-diff-neutral-2 :foreground 
,fg-diff-neutral-2)))
-   `(ediff-odd-diff-C ((,class :background ,bg-diff-neutral-1 :foreground 
,fg-diff-neutral-1)))
-;;;;; eglot
-   `(eglot-mode-line ((,class ,@(modus-vivendi-theme-bold-weight) :foreground 
,magenta-active)))
-;;;;; el-search
-   `(el-search-highlight-in-prompt-face ((,class :inherit bold :foreground 
,magenta-alt)))
-   `(el-search-match ((,class :inherit modus-theme-intense-green)))
-   `(el-search-other-match ((,class :inherit modus-theme-special-mild)))
-   `(el-search-occur-match ((,class :inherit modus-theme-special-calm)))
-;;;;; eldoc
-   ;; NOTE: see https://github.com/purcell/package-lint/issues/187
-   (list 'eldoc-highlight-function-argument `((,class :inherit bold 
:foreground ,blue-alt-other)))
-;;;;; eldoc-box
-   `(eldoc-box-body ((,class :background ,bg-alt :foreground ,fg-main)))
-   `(eldoc-box-border ((,class :background ,fg-alt)))
-;;;;; elfeed
-   `(elfeed-log-date-face ((,class :foreground ,cyan-alt)))
-   `(elfeed-log-debug-level-face ((,class :foreground ,magenta)))
-   `(elfeed-log-error-level-face ((,class :foreground ,red)))
-   `(elfeed-log-info-level-face ((,class :foreground ,green)))
-   `(elfeed-log-warn-level-face ((,class :foreground ,yellow)))
-   `(elfeed-search-date-face ((,class :foreground ,blue-nuanced)))
-   `(elfeed-search-feed-face ((,class :foreground ,cyan)))
-   `(elfeed-search-filter-face ((,class :inherit bold :foreground 
,magenta-active)))
-   `(elfeed-search-last-update-face ((,class :foreground ,cyan-active)))
-   `(elfeed-search-tag-face ((,class :foreground ,blue-nuanced)))
-   `(elfeed-search-title-face ((,class :foreground ,fg-dim)))
-   `(elfeed-search-unread-count-face ((,class :foreground ,green-active)))
-   `(elfeed-search-unread-title-face ((,class :inherit bold :foreground 
,fg-main)))
-;;;;; elfeed-score
-   `(elfeed-score-date-face ((,class :foreground ,blue)))
-   `(elfeed-score-debug-level-face ((,class :foreground ,magenta-alt-other)))
-   `(elfeed-score-error-level-face ((,class :foreground ,red)))
-   `(elfeed-score-info-level-face ((,class :foreground ,cyan)))
-   `(elfeed-score-warn-level-face ((,class :foreground ,yellow)))
-;;;;; emms
-   `(emms-playlist-track-face ((,class :foreground ,blue)))
-   `(emms-playlist-selected-face ((,class :inherit bold :foreground ,magenta)))
-;;;;; enhanced-ruby-mode
-   `(enh-ruby-heredoc-delimiter-face ((,class :foreground ,blue-alt-other)))
-   `(enh-ruby-op-face ((,class :foreground ,fg-main)))
-   `(enh-ruby-regexp-delimiter-face ((,class :foreground ,green)))
-   `(enh-ruby-regexp-face ((,class :foreground ,magenta)))
-   `(enh-ruby-string-delimiter-face ((,class :foreground ,blue-alt)))
-   `(erm-syn-errline ((,class :foreground ,red :underline t)))
-   `(erm-syn-warnline ((,class :foreground ,yellow :underline t)))
-;;;;; epa
-   `(epa-field-body ((,class :foreground ,fg-main)))
-   `(epa-field-name ((,class :inherit bold :foreground ,fg-dim)))
-   `(epa-mark ((,class :inherit bold :foreground ,magenta)))
-   `(epa-string ((,class :foreground ,blue-alt)))
-   `(epa-validity-disabled ((,class :inherit modus-theme-refine-red)))
-   `(epa-validity-high ((,class :inherit bold :foreground ,green-alt-other)))
-   `(epa-validity-low ((,class :foreground ,fg-alt)))
-   `(epa-validity-medium ((,class :foreground ,green-alt)))
-;;;;; equake
-   `(equake-buffer-face ((,class :background ,bg-main :foreground ,fg-main)))
-   `(equake-shell-type-eshell ((,class :background ,bg-inactive :foreground 
,green-active)))
-   `(equake-shell-type-rash ((,class :background ,bg-inactive :foreground 
,red-active)))
-   `(equake-shell-type-shell ((,class :background ,bg-inactive :foreground 
,cyan-active)))
-   `(equake-shell-type-term ((,class :background ,bg-inactive :foreground 
,yellow-active)))
-   `(equake-shell-type-vterm ((,class :background ,bg-inactive :foreground 
,magenta-active)))
-   `(equake-tab-active ((,class :background ,fg-alt :foreground ,bg-alt)))
-   `(equake-tab-inactive ((,class :foreground ,fg-inactive)))
-;;;;; erc
-   `(erc-action-face ((,class :inherit bold :foreground ,cyan)))
-   `(erc-bold-face ((,class :inherit bold)))
-   `(erc-button ((,class :inherit button)))
-   `(erc-command-indicator-face ((,class :inherit bold :foreground ,cyan-alt)))
-   `(erc-current-nick-face ((,class :foreground ,magenta-alt-other)))
-   `(erc-dangerous-host-face ((,class :inherit modus-theme-intense-red)))
-   `(erc-direct-msg-face ((,class :foreground ,magenta)))
-   `(erc-error-face ((,class :inherit bold :foreground ,red)))
-   `(erc-fool-face ((,class :foreground ,fg-inactive)))
-   `(erc-header-line ((,class :background ,bg-header :foreground ,fg-header)))
-   `(erc-input-face ((,class :foreground ,fg-special-calm)))
-   `(erc-inverse-face ((,class :inherit erc-default-face :inverse-video t)))
-   `(erc-keyword-face ((,class :inherit bold :foreground ,magenta-alt)))
-   `(erc-my-nick-face ((,class :inherit bold :foreground ,magenta)))
-   `(erc-my-nick-prefix-face ((,class :inherit erc-my-nick-face)))
-   `(erc-nick-default-face ((,class :inherit bold :foreground ,blue)))
-   `(erc-nick-msg-face ((,class :inherit bold :foreground ,green)))
-   `(erc-nick-prefix-face ((,class :inherit erc-nick-default-face)))
-   `(erc-notice-face ((,class :foreground ,fg-unfocused)))
-   `(erc-pal-face ((,class :inherit bold :foreground ,red-alt)))
-   `(erc-prompt-face ((,class :inherit bold :foreground ,cyan-alt-other)))
-   `(erc-timestamp-face ((,class :foreground ,blue-nuanced)))
-   `(erc-underline-face ((,class :underline t)))
-   `(bg:erc-color-face0 ((,class :background "white")))
-   `(bg:erc-color-face1 ((,class :background "black")))
-   `(bg:erc-color-face10 ((,class :background ,cyan-subtle-bg)))
-   `(bg:erc-color-face11 ((,class :background ,cyan-intense-bg)))
-   `(bg:erc-color-face12 ((,class :background ,blue-subtle-bg)))
-   `(bg:erc-color-face13 ((,class :background ,magenta-subtle-bg)))
-   `(bg:erc-color-face14 ((,class :background "gray60")))
-   `(bg:erc-color-face15 ((,class :background "gray80")))
-   `(bg:erc-color-face2 ((,class :background ,blue-intense-bg)))
-   `(bg:erc-color-face3 ((,class :background ,green-intense-bg)))
-   `(bg:erc-color-face4 ((,class :background ,red-subtle-bg)))
-   `(bg:erc-color-face5 ((,class :background ,red-intense-bg)))
-   `(bg:erc-color-face6 ((,class :background ,magenta-refine-bg)))
-   `(bg:erc-color-face7 ((,class :background ,yellow-subtle-bg)))
-   `(bg:erc-color-face8 ((,class :background ,yellow-refine-bg)))
-   `(bg:erc-color-face9 ((,class :background ,green-subtle-bg)))
-   `(fg:erc-color-face0 ((,class :foreground "white")))
-   `(fg:erc-color-face1 ((,class :foreground "black")))
-   `(fg:erc-color-face10 ((,class :foreground ,cyan)))
-   `(fg:erc-color-face11 ((,class :foreground ,cyan-alt-other)))
-   `(fg:erc-color-face12 ((,class :foreground ,blue)))
-   `(fg:erc-color-face13 ((,class :foreground ,magenta-alt)))
-   `(fg:erc-color-face14 ((,class :foreground "gray60")))
-   `(fg:erc-color-face15 ((,class :foreground "gray80")))
-   `(fg:erc-color-face2 ((,class :foreground ,blue-alt-other)))
-   `(fg:erc-color-face3 ((,class :foreground ,green)))
-   `(fg:erc-color-face4 ((,class :foreground ,red)))
-   `(fg:erc-color-face5 ((,class :foreground ,red-alt)))
-   `(fg:erc-color-face6 ((,class :foreground ,magenta-alt-other)))
-   `(fg:erc-color-face7 ((,class :foreground ,yellow-alt-other)))
-   `(fg:erc-color-face8 ((,class :foreground ,yellow-alt)))
-   `(fg:erc-color-face9 ((,class :foreground ,green-alt-other)))
-;;;;; eros
-   `(eros-result-overlay-face ((,class :box (:line-width -1 :color ,blue)
-                                       :background ,bg-dim :foreground 
,fg-dim)))
-;;;;; ert
-   `(ert-test-result-expected ((,class :inherit modus-theme-intense-green)))
-   `(ert-test-result-unexpected ((,class :inherit modus-theme-intense-red)))
-;;;;; eshell
-   `(eshell-ls-archive ((,class :inherit bold :foreground ,cyan-alt)))
-   `(eshell-ls-backup ((,class :foreground ,yellow-alt)))
-   `(eshell-ls-clutter ((,class :foreground ,red-alt)))
-   `(eshell-ls-directory ((,class :inherit bold :foreground ,blue-alt)))
-   `(eshell-ls-executable ((,class :foreground ,magenta-alt)))
-   `(eshell-ls-missing ((,class :inherit modus-theme-intense-red)))
-   `(eshell-ls-product ((,class :foreground ,fg-special-warm)))
-   `(eshell-ls-readonly ((,class :foreground ,fg-special-cold)))
-   `(eshell-ls-special ((,class :inherit bold :foreground ,magenta)))
-   `(eshell-ls-symlink ((,class :inherit button :foreground ,cyan)))
-   `(eshell-ls-unreadable ((,class :background ,bg-inactive :foreground 
,fg-inactive)))
-   `(eshell-prompt ((,class ,@(modus-vivendi-theme-bold-weight)
-                            ,@(modus-vivendi-theme-prompt
-                               green-alt-other
-                               green-nuanced-bg green-alt
-                               green-refine-bg fg-main))))
-;;;;; eshell-fringe-status
-   `(eshell-fringe-status-failure ((,class :foreground ,red)))
-   `(eshell-fringe-status-success ((,class :foreground ,green)))
-;;;;; eshell-git-prompt
-   `(eshell-git-prompt-add-face ((,class :foreground ,fg-alt)))
-   `(eshell-git-prompt-branch-face ((,class :foreground ,fg-alt)))
-   `(eshell-git-prompt-directory-face ((,class :foreground ,cyan)))
-   `(eshell-git-prompt-exit-fail-face ((,class :foreground ,red)))
-   `(eshell-git-prompt-exit-success-face ((,class :foreground ,green)))
-   `(eshell-git-prompt-modified-face ((,class :foreground ,yellow)))
-   `(eshell-git-prompt-powerline-clean-face ((,class :background 
,green-refine-bg)))
-   `(eshell-git-prompt-powerline-dir-face ((,class :background 
,blue-refine-bg)))
-   `(eshell-git-prompt-powerline-not-clean-face ((,class :background 
,magenta-refine-bg)))
-   `(eshell-git-prompt-robyrussell-branch-face ((,class :foreground ,red)))
-   `(eshell-git-prompt-robyrussell-git-dirty-face ((,class :foreground 
,yellow)))
-   `(eshell-git-prompt-robyrussell-git-face ((,class :foreground ,blue)))
-;;;;; eshell-prompt-extras (epe)
-   `(epe-dir-face ((,class ,@(modus-vivendi-theme-bold-weight) :foreground 
,blue)))
-   `(epe-git-dir-face ((,class :foreground ,red-alt-other)))
-   `(epe-git-face ((,class :foreground ,cyan-alt)))
-   `(epe-pipeline-delimiter-face ((,class :foreground ,green-alt)))
-   `(epe-pipeline-host-face ((,class :foreground ,blue)))
-   `(epe-pipeline-time-face ((,class :foreground ,fg-special-warm)))
-   `(epe-pipeline-user-face ((,class :foreground ,magenta)))
-   `(epe-remote-face ((,class :foreground ,fg-alt :slant ,modus-theme-slant)))
-   `(epe-status-face ((,class :foreground ,magenta-alt-other)))
-   `(epe-venv-face ((,class :foreground ,fg-alt :slant ,modus-theme-slant)))
-;;;;; eshell-syntax-highlighting
-   `(eshell-syntax-highlighting-alias-face ((,class :foreground ,cyan)))
-   `(eshell-syntax-highlighting-comment-face ((,class :foreground ,fg-alt)))
-   `(eshell-syntax-highlighting-directory-face ((,class :foreground ,blue)))
-   `(eshell-syntax-highlighting-envvar-face ((,class :foreground 
,magenta-alt)))
-   `(eshell-syntax-highlighting-invalid-face ((,class :foreground ,red)))
-   `(eshell-syntax-highlighting-lisp-function-face ((,class :foreground 
,magenta)))
-   `(eshell-syntax-highlighting-shell-command-face ((,class :foreground 
,cyan-alt-other)))
-   `(eshell-syntax-highlighting-string-face ((,class :foreground ,blue-alt)))
-;;;;; evil-mode
-   `(evil-ex-commands ((,class :foreground ,magenta-alt-other)))
-   `(evil-ex-info ((,class :foreground ,cyan-alt-other)))
-   `(evil-ex-lazy-highlight ((,class :inherit modus-theme-refine-cyan)))
-   `(evil-ex-search ((,class :inherit modus-theme-intense-green)))
-   `(evil-ex-substitute-matches ((,class :inherit modus-theme-refine-yellow 
:underline t)))
-   `(evil-ex-substitute-replacement ((,class :inherit 
(modus-theme-intense-green bold))))
-;;;;; evil-goggles
-   `(evil-goggles-change-face ((,class :inherit modus-theme-refine-yellow)))
-   `(evil-goggles-commentary-face ((,class :inherit modus-theme-subtle-neutral 
:slant ,modus-theme-slant)))
-   `(evil-goggles-default-face ((,class :inherit modus-theme-subtle-neutral)))
-   `(evil-goggles-delete-face ((,class :inherit modus-theme-refine-red)))
-   `(evil-goggles-fill-and-move-face ((,class :inherit 
evil-goggles-default-face)))
-   `(evil-goggles-indent-face ((,class :inherit evil-goggles-default-face)))
-   `(evil-goggles-join-face ((,class :inherit modus-theme-subtle-green)))
-   `(evil-goggles-nerd-commenter-face ((,class :inherit 
evil-goggles-commentary-face)))
-   `(evil-goggles-paste-face ((,class :inherit modus-theme-subtle-cyan)))
-   `(evil-goggles-record-macro-face ((,class :inherit 
modus-theme-special-cold)))
-   `(evil-goggles-replace-with-register-face ((,class :inherit 
modus-theme-refine-magenta)))
-   `(evil-goggles-set-marker-face ((,class :inherit 
modus-theme-intense-magenta)))
-   `(evil-goggles-shift-face ((,class :inherit evil-goggles-default-face)))
-   `(evil-goggles-surround-face ((,class :inherit evil-goggles-default-face)))
-   `(evil-goggles-yank-face ((,class :inherit modus-theme-subtle-blue)))
-;;;;; evil-visual-mark-mode
-   `(evil-visual-mark-face ((,class :inherit modus-theme-intense-magenta)))
-;;;;; eww
-   `(eww-invalid-certificate ((,class :foreground ,red-active)))
-   `(eww-valid-certificate ((,class :foreground ,green-active)))
-   `(eww-form-checkbox ((,class :box (:line-width 1 :color ,fg-inactive :style 
released-button) :background ,bg-inactive :foreground ,fg-main)))
-   `(eww-form-file ((,class :box (:line-width 1 :color ,fg-inactive :style 
released-button) :background ,bg-active :foreground ,fg-main)))
-   `(eww-form-select ((,class :inherit eww-form-checkbox)))
-   `(eww-form-submit ((,class :inherit eww-form-file)))
-   `(eww-form-text ((,class :box (:line-width 1 :color ,fg-inactive :style 
none) :background ,bg-active :foreground ,fg-active)))
-   `(eww-form-textarea ((,class :background ,bg-alt :foreground ,fg-main)))
-;;;;; eyebrowse
-   `(eyebrowse-mode-line-active ((,class :inherit bold :foreground 
,blue-active)))
-;;;;; fancy-dabbrev
-   `(fancy-dabbrev-menu-face ((,class :background ,bg-alt :foreground 
,fg-alt)))
-   `(fancy-dabbrev-preview-face ((,class :foreground ,fg-alt :underline t)))
-   `(fancy-dabbrev-selection-face ((,class :inherit (modus-theme-intense-cyan 
bold))))
-;;;;; flycheck
-   `(flycheck-error
-     ((,(append '((supports :underline (:style wave))) class)
-       :underline (:color ,fg-lang-error :style wave))
-      (,class :foreground ,fg-lang-error :underline t)))
-   `(flycheck-error-list-checker-name ((,class :foreground ,magenta-active)))
-   `(flycheck-error-list-column-number ((,class :foreground ,fg-special-cold)))
-   `(flycheck-error-list-error ((,class ,@(modus-vivendi-theme-bold-weight) 
:foreground ,red)))
-   `(flycheck-error-list-filename ((,class :foreground ,blue)))
-   `(flycheck-error-list-highlight ((,class :inherit modus-theme-hl-line)))
-   `(flycheck-error-list-id ((,class :foreground ,magenta-alt-other)))
-   `(flycheck-error-list-id-with-explainer ((,class :inherit 
flycheck-error-list-id :box t)))
-   `(flycheck-error-list-info ((,class :foreground ,cyan)))
-   `(flycheck-error-list-line-number ((,class :foreground ,fg-special-warm)))
-   `(flycheck-error-list-warning ((,class :foreground ,yellow)))
-   `(flycheck-fringe-error ((,class :inherit modus-theme-fringe-red)))
-   `(flycheck-fringe-info ((,class :inherit modus-theme-fringe-cyan)))
-   `(flycheck-fringe-warning ((,class :inherit modus-theme-fringe-yellow)))
-   `(flycheck-info
-     ((,(append '((supports :underline (:style wave))) class)
-       :underline (:color ,fg-lang-note :style wave))
-      (,class :foreground ,fg-lang-note :underline t)))
-   `(flycheck-verify-select-checker ((,class :box (:line-width 1 :color nil 
:style released-button))))
-   `(flycheck-warning
-     ((,(append '((supports :underline (:style wave))) class)
-       :underline (:color ,fg-lang-warning :style wave))
-      (,class :foreground ,fg-lang-warning :underline t)))
-;;;;; flycheck-color-mode-line
-   `(flycheck-color-mode-line-error-face ((,class :inherit 
flycheck-fringe-error)))
-   `(flycheck-color-mode-line-info-face ((,class :inherit 
flycheck-fringe-info)))
-   `(flycheck-color-mode-line-running-face ((,class :foreground ,fg-inactive 
:slant italic)))
-   `(flycheck-color-mode-line-info-face ((,class :inherit 
flycheck-fringe-warning)))
-;;;;; flycheck-indicator
-   `(flycheck-indicator-disabled ((,class :foreground ,fg-inactive :slant 
,modus-theme-slant)))
-   `(flycheck-indicator-error ((,class ,@(modus-vivendi-theme-bold-weight) 
:foreground ,red-active)))
-   `(flycheck-indicator-info ((,class ,@(modus-vivendi-theme-bold-weight) 
:foreground ,blue-active)))
-   `(flycheck-indicator-running ((,class ,@(modus-vivendi-theme-bold-weight) 
:foreground ,magenta-active)))
-   `(flycheck-indicator-success ((,class ,@(modus-vivendi-theme-bold-weight) 
:foreground ,green-active)))
-   `(flycheck-indicator-warning ((,class ,@(modus-vivendi-theme-bold-weight) 
:foreground ,yellow-active)))
-;;;;; flycheck-posframe
-   `(flycheck-posframe-background-face ((,class :background ,bg-alt)))
-   `(flycheck-posframe-border-face ((,class :foreground ,fg-alt)))
-   `(flycheck-posframe-error-face ((,class :inherit bold :foreground ,red)))
-   `(flycheck-posframe-face ((,class :foreground ,fg-main :slant 
,modus-theme-slant)))
-   `(flycheck-posframe-info-face ((,class :inherit bold :foreground ,cyan)))
-   `(flycheck-posframe-warning-face ((,class :inherit bold :foreground 
,yellow)))
-;;;;; flymake
-   `(flymake-error
-     ((,(append '((supports :underline (:style wave))) class)
-       :underline (:color ,fg-lang-error :style wave))
-      (,class :foreground ,fg-lang-error :underline t)))
-   `(flymake-note
-     ((,(append '((supports :underline (:style wave))) class)
-       :underline (:color ,fg-lang-note :style wave))
-      (,class :foreground ,fg-lang-note :underline t)))
-   `(flymake-warning
-     ((,(append '((supports :underline (:style wave))) class)
-       :underline (:color ,fg-lang-warning :style wave))
-      (,class :foreground ,fg-lang-warning :underline t)))
-;;;;; flyspell
-   `(flyspell-duplicate
-     ((,(append '((supports :underline (:style wave))) class)
-       :underline (:color ,fg-lang-warning :style wave))
-      (,class :foreground ,fg-lang-warning :underline t)))
-   `(flyspell-incorrect
-     ((,(append '((supports :underline (:style wave))) class)
-       :underline (:color ,fg-lang-error :style wave))
-      (,class :foreground ,fg-lang-error :underline t)))
-;;;;; flyspell-correct
-   `(flyspell-correct-highlight-face ((,class :inherit 
modus-theme-refine-green)))
-;;;;; flx
-   `(flx-highlight-face ((,class ,@(modus-vivendi-theme-extra-completions
-                                    'modus-theme-subtle-magenta
-                                    'modus-theme-intense-magenta
-                                    'modus-theme-nuanced-magenta
-                                    magenta-alt
-                                    'bold))))
-;;;;; freeze-it
-   `(freeze-it-show ((,class :background ,bg-dim :foreground 
,fg-special-warm)))
-;;;;; frog-menu
-   `(frog-menu-action-keybinding-face ((,class :foreground ,blue-alt-other)))
-   `(frog-menu-actions-face ((,class :foreground ,magenta)))
-   `(frog-menu-border ((,class :background ,bg-active)))
-   `(frog-menu-candidates-face ((,class :foreground ,fg-main)))
-   `(frog-menu-posframe-background-face ((,class :background ,bg-dim)))
-   `(frog-menu-prompt-face ((,class :foreground ,cyan)))
-;;;;; focus
-   `(focus-unfocused ((,class :foreground ,fg-unfocused)))
-;;;;; fold-this
-   `(fold-this-overlay ((,class :inherit modus-theme-special-mild)))
-;;;;; font-lock
-   `(font-lock-builtin-face ((,class ,@(modus-vivendi-theme-syntax-foreground
-                                        magenta-alt magenta-alt-faint)
-                                     ,@(modus-vivendi-theme-bold-weight))))
-   `(font-lock-comment-delimiter-face ((,class :foreground ,fg-alt :slant 
,modus-theme-slant)))
-   `(font-lock-comment-face ((,class :foreground ,fg-alt :slant 
,modus-theme-slant)))
-   `(font-lock-constant-face ((,class ,@(modus-vivendi-theme-syntax-foreground
-                                         blue-alt-other 
blue-alt-other-faint))))
-   `(font-lock-doc-face ((,class ,@(modus-vivendi-theme-syntax-foreground
-                                    fg-special-cold cyan-alt-other-faint)
-                                 :slant ,modus-theme-slant)))
-   `(font-lock-function-name-face ((,class 
,@(modus-vivendi-theme-syntax-foreground
-                                              magenta magenta-faint))))
-   `(font-lock-keyword-face ((,class ,@(modus-vivendi-theme-syntax-foreground
-                                        magenta-alt-other 
magenta-alt-other-faint)
-                                     ,@(modus-vivendi-theme-bold-weight))))
-   `(font-lock-negation-char-face ((,class 
,@(modus-vivendi-theme-syntax-foreground
-                                              yellow yellow-faint)
-                                           
,@(modus-vivendi-theme-bold-weight))))
-   `(font-lock-preprocessor-face ((,class 
,@(modus-vivendi-theme-syntax-foreground
-                                             red-alt-other 
red-alt-other-faint))))
-   `(font-lock-regexp-grouping-backslash ((,class :inherit bold :foreground 
,fg-escape-char-backslash)))
-   `(font-lock-regexp-grouping-construct ((,class :inherit bold :foreground 
,fg-escape-char-construct)))
-   `(font-lock-string-face ((,class ,@(modus-vivendi-theme-syntax-foreground
-                                       blue-alt blue-alt-faint))))
-   `(font-lock-type-face ((,class ,@(modus-vivendi-theme-syntax-foreground
-                                     magenta-alt magenta-alt-faint))))
-   `(font-lock-variable-name-face ((,class 
,@(modus-vivendi-theme-syntax-foreground
-                                              cyan cyan-faint))))
-   `(font-lock-warning-face ((,class ,@(modus-vivendi-theme-syntax-foreground
-                                        yellow-active yellow-alt-faint)
-                                     ,@(modus-vivendi-theme-bold-weight))))
-;;;;; forge
-   `(forge-post-author ((,class :inherit bold :foreground ,fg-main)))
-   `(forge-post-date ((,class :foreground ,fg-special-cold)))
-   `(forge-topic-closed ((,class :foreground ,fg-alt)))
-   `(forge-topic-merged ((,class :foreground ,fg-alt)))
-   `(forge-topic-open ((,class :foreground ,fg-special-mild)))
-   `(forge-topic-unmerged ((,class :foreground ,magenta :slant 
,modus-theme-slant)))
-   `(forge-topic-unread ((,class :inherit bold :foreground ,fg-main)))
-;;;;; fountain-mode
-   `(fountain-character ((,class :foreground ,blue-alt-other)))
-   `(fountain-comment ((,class :foreground ,fg-alt :slant ,modus-theme-slant)))
-   `(fountain-dialog ((,class :foreground ,blue-alt)))
-   `(fountain-metadata-key ((,class :foreground ,green-alt-other)))
-   `(fountain-metadata-value ((,class :foreground ,blue)))
-   `(fountain-non-printing ((,class :foreground ,fg-alt)))
-   `(fountain-note ((,class :foreground ,yellow :slant ,modus-theme-slant)))
-   `(fountain-page-break ((,class :inherit bold :foreground ,red-alt)))
-   `(fountain-page-number ((,class :inherit bold :foreground ,red-alt-other)))
-   `(fountain-paren ((,class :foreground ,cyan)))
-   `(fountain-scene-heading ((,class :inherit bold :foreground ,blue-nuanced)))
-   `(fountain-section-heading ((,class :inherit (bold 
,modus-theme-variable-pitch) :foreground ,fg-main
-                                       ,@(modus-vivendi-theme-scale 
modus-vivendi-theme-scale-4))))
-   `(fountain-section-heading-1 ((,class :inherit (bold 
,modus-theme-variable-pitch) :foreground ,fg-main
-                                         ,@(modus-vivendi-theme-scale 
modus-vivendi-theme-scale-4))))
-   `(fountain-section-heading-2 ((,class :inherit (bold 
,modus-theme-variable-pitch) :foreground ,fg-special-warm
-                                         ,@(modus-vivendi-theme-scale 
modus-vivendi-theme-scale-3))))
-   `(fountain-section-heading-3 ((,class :inherit (bold 
,modus-theme-variable-pitch) :foreground ,fg-special-mild
-                                         ,@(modus-vivendi-theme-scale 
modus-vivendi-theme-scale-2))))
-   `(fountain-section-heading-4 ((,class :inherit (bold 
,modus-theme-variable-pitch) :foreground ,fg-special-calm
-                                         ,@(modus-vivendi-theme-scale 
modus-vivendi-theme-scale-1))))
-   `(fountain-section-heading-5 ((,class :inherit (bold 
,modus-theme-variable-pitch) :foreground ,fg-special-calm)))
-   `(fountain-synopsis ((,class :foreground ,cyan-alt)))
-   `(fountain-trans ((,class :foreground ,yellow-alt-other)))
-;;;;; geiser
-   `(geiser-font-lock-autodoc-current-arg ((,class 
,@(modus-vivendi-theme-syntax-foreground
-                                                      magenta magenta-faint))))
-   `(geiser-font-lock-autodoc-identifier ((,class 
,@(modus-vivendi-theme-syntax-foreground
-                                                     blue blue-faint))))
-   `(geiser-font-lock-doc-button ((,class 
,@(modus-vivendi-theme-syntax-foreground
-                                             cyan-alt cyan-alt-faint)
-                                          :underline t)))
-   `(geiser-font-lock-doc-link ((,class :inherit link)))
-   `(geiser-font-lock-error-link ((,class 
,@(modus-vivendi-theme-syntax-foreground
-                                             red-alt red-alt-faint)
-                                          :underline t)))
-   `(geiser-font-lock-image-button ((,class 
,@(modus-vivendi-theme-syntax-foreground
-                                               green-alt green-alt-faint)
-                                            :underline t)))
-   `(geiser-font-lock-repl-input ((,class :inherit bold)))
-   `(geiser-font-lock-repl-output ((,class 
,@(modus-vivendi-theme-syntax-foreground
-                                              magenta-alt-other 
magenta-alt-other-faint))))
-   `(geiser-font-lock-repl-prompt ((,class 
,@(modus-vivendi-theme-syntax-foreground
-                                              cyan-alt-other 
cyan-alt-other-faint))))
-   `(geiser-font-lock-xref-header ((,class :inherit bold)))
-   `(geiser-font-lock-xref-link ((,class :inherit link)))
-;;;;; git-commit
-   `(git-commit-comment-action ((,class :foreground ,fg-alt :slant 
,modus-theme-slant)))
-   `(git-commit-comment-branch-local ((,class :foreground ,blue-alt :slant 
,modus-theme-slant)))
-   `(git-commit-comment-branch-remote ((,class :foreground ,magenta-alt :slant 
,modus-theme-slant)))
-   `(git-commit-comment-detached ((,class :foreground ,cyan-alt :slant 
,modus-theme-slant)))
-   `(git-commit-comment-file ((,class :foreground ,fg-special-cold :slant 
,modus-theme-slant)))
-   `(git-commit-comment-heading ((,class :inherit bold :foreground ,fg-dim 
:slant ,modus-theme-slant)))
-   `(git-commit-keyword ((,class :foreground ,magenta)))
-   `(git-commit-known-pseudo-header ((,class :foreground ,cyan-alt-other)))
-   `(git-commit-nonempty-second-line ((,class :inherit 
modus-theme-refine-yellow)))
-   `(git-commit-overlong-summary ((,class :inherit modus-theme-refine-yellow)))
-   `(git-commit-pseudo-header ((,class :foreground ,blue)))
-   `(git-commit-summary ((,class :inherit bold :foreground ,cyan)))
-;;;;; git-gutter
-   `(git-gutter:added ((,class :inherit modus-theme-fringe-green)))
-   `(git-gutter:deleted ((,class :inherit modus-theme-fringe-red)))
-   `(git-gutter:modified ((,class :inherit modus-theme-fringe-yellow)))
-   `(git-gutter:separator ((,class :inherit modus-theme-fringe-cyan)))
-   `(git-gutter:unchanged ((,class :inherit modus-theme-fringe-magenta)))
-;;;;; git-gutter-fr
-   `(git-gutter-fr:added ((,class :inherit modus-theme-fringe-green)))
-   `(git-gutter-fr:deleted ((,class :inherit modus-theme-fringe-red)))
-   `(git-gutter-fr:modified ((,class :inherit modus-theme-fringe-yellow)))
-;;;;; git-{gutter,fringe}+
-   `(git-gutter+-added ((,class :inherit modus-theme-fringe-green)))
-   `(git-gutter+-deleted ((,class :inherit modus-theme-fringe-red)))
-   `(git-gutter+-modified ((,class :inherit modus-theme-fringe-yellow)))
-   `(git-gutter+-separator ((,class :inherit modus-theme-fringe-cyan)))
-   `(git-gutter+-unchanged ((,class :inherit modus-theme-fringe-magenta)))
-   `(git-gutter-fr+-added ((,class :inherit modus-theme-fringe-green)))
-   `(git-gutter-fr+-deleted ((,class :inherit modus-theme-fringe-red)))
-   `(git-gutter-fr+-modified ((,class :inherit modus-theme-fringe-yellow)))
-;;;;; git-lens
-   `(git-lens-added ((,class :inherit bold :foreground ,green)))
-   `(git-lens-deleted ((,class :inherit bold :foreground ,red)))
-   `(git-lens-header ((,class :inherit bold :height 1.1 :foreground ,cyan)))
-   `(git-lens-modified ((,class :inherit bold :foreground ,yellow)))
-   `(git-lens-renamed ((,class :inherit bold :foreground ,magenta)))
-;;;;; git-rebase
-   `(git-rebase-comment-hash ((,class :foreground ,fg-special-cold :slant 
,modus-theme-slant)))
-   `(git-rebase-comment-heading ((,class :inherit bold :foreground ,fg-dim 
:slant ,modus-theme-slant)))
-   `(git-rebase-description ((,class :foreground ,fg-main)))
-   `(git-rebase-hash ((,class :foreground ,cyan-alt-other)))
-;;;;; git-timemachine
-   `(git-timemachine-commit ((,class :inherit bold :foreground 
,yellow-active)))
-   `(git-timemachine-minibuffer-author-face ((,class :foreground 
,fg-special-warm)))
-   `(git-timemachine-minibuffer-detail-face ((,class :foreground ,red-alt)))
-;;;;; git-walktree
-   `(git-walktree-commit-face ((,class :foreground ,yellow)))
-   `(git-walktree-symlink-face ((,class :inherit button :foreground ,cyan)))
-   `(git-walktree-tree-face ((,class :foreground ,magenta)))
-;;;;; gnus
-   `(gnus-button ((,class :inherit button)))
-   `(gnus-cite-1 ((,class :foreground ,blue-alt)))
-   `(gnus-cite-10 ((,class :foreground ,magenta-alt-other)))
-   `(gnus-cite-11 ((,class :foreground ,yellow-alt-other)))
-   `(gnus-cite-2 ((,class :foreground ,red-alt)))
-   `(gnus-cite-3 ((,class :foreground ,green-alt)))
-   `(gnus-cite-4 ((,class :foreground ,magenta-alt)))
-   `(gnus-cite-5 ((,class :foreground ,yellow-alt)))
-   `(gnus-cite-6 ((,class :foreground ,cyan-alt)))
-   `(gnus-cite-7 ((,class :foreground ,blue-alt-other)))
-   `(gnus-cite-8 ((,class :foreground ,red-alt-other)))
-   `(gnus-cite-9 ((,class :foreground ,green-alt-other)))
-   `(gnus-cite-attribution ((,class :foreground ,fg-main :slant italic)))
-   `(gnus-emphasis-highlight-words ((,class :inherit 
modus-theme-refine-yellow)))
-   `(gnus-group-mail-1 ((,class :inherit bold :foreground ,magenta-alt)))
-   `(gnus-group-mail-1-empty ((,class :foreground ,magenta-alt)))
-   `(gnus-group-mail-2 ((,class :inherit bold :foreground ,magenta)))
-   `(gnus-group-mail-2-empty ((,class :foreground ,magenta)))
-   `(gnus-group-mail-3 ((,class :inherit bold :foreground ,magenta-alt-other)))
-   `(gnus-group-mail-3-empty ((,class :foreground ,magenta-alt-other)))
-   `(gnus-group-mail-low ((,class :inherit bold :foreground ,magenta-nuanced)))
-   `(gnus-group-mail-low-empty ((,class :foreground ,magenta-nuanced)))
-   `(gnus-group-news-1 ((,class :inherit bold :foreground ,green)))
-   `(gnus-group-news-1-empty ((,class :foreground ,green)))
-   `(gnus-group-news-2 ((,class :inherit bold :foreground ,cyan)))
-   `(gnus-group-news-2-empty ((,class :foreground ,cyan)))
-   `(gnus-group-news-3 ((,class :inherit bold :foreground ,yellow-nuanced)))
-   `(gnus-group-news-3-empty ((,class :foreground ,yellow-nuanced)))
-   `(gnus-group-news-4 ((,class :inherit bold :foreground ,cyan-nuanced)))
-   `(gnus-group-news-4-empty ((,class :foreground ,cyan-nuanced)))
-   `(gnus-group-news-5 ((,class :inherit bold :foreground ,red-nuanced)))
-   `(gnus-group-news-5-empty ((,class :foreground ,red-nuanced)))
-   `(gnus-group-news-6 ((,class :inherit bold :foreground ,fg-alt)))
-   `(gnus-group-news-6-empty ((,class :foreground ,fg-alt)))
-   `(gnus-group-news-low ((,class :inherit bold :foreground ,green-nuanced)))
-   `(gnus-group-news-low-empty ((,class :foreground ,green-nuanced)))
-   `(gnus-header-content ((,class :foreground ,cyan)))
-   `(gnus-header-from ((,class :inherit bold :foreground ,cyan-alt-other 
:underline nil)))
-   `(gnus-header-name ((,class :foreground ,green)))
-   `(gnus-header-newsgroups ((,class :inherit bold :foreground ,blue-alt)))
-   `(gnus-header-subject ((,class :inherit bold :foreground 
,magenta-alt-other)))
-   `(gnus-server-agent ((,class :inherit bold :foreground ,cyan)))
-   `(gnus-server-closed ((,class :inherit bold :foreground ,magenta)))
-   `(gnus-server-cloud ((,class :inherit bold :foreground ,cyan-alt)))
-   `(gnus-server-cloud-host ((,class :inherit modus-theme-refine-cyan)))
-   `(gnus-server-denied ((,class :inherit bold :foreground ,red)))
-   `(gnus-server-offline ((,class :inherit bold :foreground ,yellow)))
-   `(gnus-server-opened ((,class :inherit bold :foreground ,green)))
-   `(gnus-signature ((,class :foreground ,fg-special-cold :slant italic)))
-   `(gnus-splash ((,class :foreground ,fg-alt)))
-   `(gnus-summary-cancelled ((,class :inherit modus-theme-mark-alt)))
-   `(gnus-summary-high-ancient ((,class :inherit bold :foreground ,fg-alt)))
-   `(gnus-summary-high-read ((,class :inherit bold :foreground 
,fg-special-cold)))
-   `(gnus-summary-high-ticked ((,class :inherit bold :foreground 
,red-alt-other)))
-   `(gnus-summary-high-undownloaded ((,class :inherit bold :foreground 
,yellow)))
-   `(gnus-summary-high-unread ((,class :inherit bold :foreground ,fg-main)))
-   `(gnus-summary-low-ancient ((,class :foreground ,fg-alt :slant italic)))
-   `(gnus-summary-low-read ((,class :foreground ,fg-alt :slant italic)))
-   `(gnus-summary-low-ticked ((,class :foreground ,red-refine-fg :slant 
italic)))
-   `(gnus-summary-low-undownloaded ((,class :foreground ,yellow-refine-fg 
:slant italic)))
-   `(gnus-summary-low-unread ((,class :inherit bold :foreground 
,fg-special-cold)))
-   `(gnus-summary-normal-ancient ((,class :foreground ,fg-special-calm)))
-   `(gnus-summary-normal-read ((,class :foreground ,fg-alt)))
-   `(gnus-summary-normal-ticked ((,class :foreground ,red-alt-other)))
-   `(gnus-summary-normal-undownloaded ((,class :foreground ,yellow)))
-   `(gnus-summary-normal-unread ((,class :foreground ,fg-main)))
-   `(gnus-summary-selected ((,class :inherit modus-theme-subtle-blue)))
-;;;;; golden-ratio-scroll-screen
-   `(golden-ratio-scroll-highlight-line-face ((,class :background 
,cyan-subtle-bg :foreground ,fg-main)))
-;;;;; helm
-   `(helm-M-x-key ((,class :inherit bold :foreground ,magenta-alt-other)))
-   `(helm-action ((,class :underline t)))
-   `(helm-bookmark-addressbook ((,class :foreground ,green-alt)))
-   `(helm-bookmark-directory ((,class :inherit bold :foreground ,blue)))
-   `(helm-bookmark-file ((,class :foreground ,fg-main)))
-   `(helm-bookmark-file-not-found ((,class :background ,bg-alt :foreground 
,fg-alt)))
-   `(helm-bookmark-gnus ((,class :foreground ,magenta)))
-   `(helm-bookmark-info ((,class :foreground ,cyan-alt)))
-   `(helm-bookmark-man ((,class :foreground ,yellow-alt)))
-   `(helm-bookmark-w3m ((,class :foreground ,blue-alt)))
-   `(helm-buffer-archive ((,class :inherit bold :foreground ,cyan)))
-   `(helm-buffer-directory ((,class :inherit bold :foreground ,blue)))
-   `(helm-buffer-file ((,class :foreground ,fg-main)))
-   `(helm-buffer-modified ((,class :foreground ,yellow-alt)))
-   `(helm-buffer-not-saved ((,class :foreground ,red-alt)))
-   `(helm-buffer-process ((,class :foreground ,magenta)))
-   `(helm-buffer-saved-out ((,class :inherit bold :background ,bg-alt 
:foreground ,red)))
-   `(helm-buffer-size ((,class :foreground ,fg-alt)))
-   `(helm-candidate-number ((,class :foreground ,cyan-active)))
-   `(helm-candidate-number-suspended ((,class :foreground ,yellow-active)))
-   `(helm-comint-prompts-buffer-name ((,class :foreground ,green-active)))
-   `(helm-comint-prompts-promptidx ((,class :foreground ,cyan-active)))
-   `(helm-delete-async-message ((,class :inherit bold :foreground 
,magenta-active)))
-   `(helm-eob-line ((,class :background ,bg-main :foreground ,fg-main)))
-   `(helm-eshell-prompts-buffer-name ((,class :foreground ,green-active)))
-   `(helm-eshell-prompts-promptidx ((,class :foreground ,cyan-active)))
-   `(helm-etags-file ((,class :foreground ,fg-dim :underline t)))
-   `(helm-ff-backup-file ((,class :foreground ,fg-alt)))
-   `(helm-ff-denied ((,class ,@(modus-vivendi-theme-extra-completions
-                                'modus-theme-subtle-red
-                                'modus-theme-intense-red
-                                'modus-theme-nuanced-red
-                                red))))
-   `(helm-ff-directory ((,class :inherit helm-buffer-directory)))
-   `(helm-ff-dirs ((,class :inherit bold :foreground ,blue-alt-other)))
-   `(helm-ff-dotted-directory ((,class :inherit bold :background ,bg-alt 
:foreground ,fg-alt)))
-   `(helm-ff-dotted-symlink-directory ((,class :inherit (button 
helm-ff-dotted-directory))))
-   `(helm-ff-executable ((,class :foreground ,magenta-alt)))
-   `(helm-ff-file ((,class :foreground ,fg-main)))
-   `(helm-ff-file-extension ((,class :foreground ,fg-special-warm)))
-   `(helm-ff-invalid-symlink ((,class :inherit button :foreground ,red)))
-   `(helm-ff-pipe ((,class ,@(modus-vivendi-theme-extra-completions
-                              'modus-theme-refine-magenta
-                              'modus-theme-subtle-magenta
-                              'modus-theme-nuanced-magenta
-                              magenta))))
-   `(helm-ff-prefix ((,class ,@(modus-vivendi-theme-extra-completions
-                                'modus-theme-refine-yellow
-                                'modus-theme-subtle-yellow
-                                'modus-theme-nuanced-yellow
-                                yellow-alt-other))))
-   `(helm-ff-socket ((,class :foreground ,red-alt-other)))
-   `(helm-ff-suid ((,class ,@(modus-vivendi-theme-extra-completions
-                              'modus-theme-subtle-red
-                              'modus-theme-refine-red
-                              'modus-theme-nuanced-yellow
-                              red-alt))))
-   `(helm-ff-symlink ((,class :inherit button :foreground ,cyan)))
-   `(helm-ff-truename ((,class :foreground ,blue-alt-other)))
-   `(helm-grep-cmd-line ((,class :foreground ,yellow-alt-other)))
-   `(helm-grep-file ((,class :inherit bold :foreground ,fg-special-cold)))
-   `(helm-grep-finish ((,class :foreground ,green-active)))
-   `(helm-grep-lineno ((,class :foreground ,fg-special-warm)))
-   `(helm-grep-match ((,class :inherit modus-theme-special-calm)))
-   `(helm-header ((,class :inherit bold :foreground ,fg-special-cold)))
-   `(helm-header-line-left-margin ((,class :inherit bold :foreground 
,yellow-intense)))
-   `(helm-history-deleted ((,class ,@(modus-vivendi-theme-extra-completions
-                                      'modus-theme-subtle-red
-                                      'modus-theme-intense-red
-                                      'modus-theme-nuanced-red
-                                      red
-                                      'bold))))
-   `(helm-history-remote ((,class :foreground ,red-alt-other)))
-   `(helm-lisp-completion-info ((,class :foreground ,fg-special-warm)))
-   `(helm-lisp-show-completion ((,class 
,@(modus-vivendi-theme-extra-completions
-                                           'modus-theme-subtle-yellow
-                                           'modus-theme-refine-yellow
-                                           'modus-theme-nuanced-yellow
-                                           yellow
-                                           'bold))))
-   `(helm-locate-finish ((,class :foreground ,green-active)))
-   `(helm-match ((,class ,@(modus-vivendi-theme-extra-completions
-                            'modus-theme-subtle-cyan
-                            'modus-theme-refine-cyan
-                            'modus-theme-nuanced-cyan
-                            cyan
-                            'bold))))
-   `(helm-match-item ((,class ,@(modus-vivendi-theme-extra-completions
-                                 'modus-theme-subtle-neutral
-                                 'modus-theme-subtle-cyan
-                                 'modus-theme-nuanced-cyan
-                                 cyan-alt-other))))
-   `(helm-minibuffer-prompt ((,class :inherit minibuffer-prompt)))
-   `(helm-moccur-buffer ((,class :inherit button :foreground ,cyan-alt-other)))
-   `(helm-mode-prefix ((,class ,@(modus-vivendi-theme-extra-completions
-                                  'modus-theme-subtle-magenta
-                                  'modus-theme-intense-magenta
-                                  'modus-theme-nuanced-magenta
-                                  magenta-alt
-                                  'bold))))
-   `(helm-non-file-buffer ((,class :foreground ,fg-alt)))
-   `(helm-prefarg ((,class :foreground ,red-active)))
-   `(helm-resume-need-update ((,class ,@(modus-vivendi-theme-extra-completions
-                                         'modus-theme-subtle-magenta
-                                         'modus-theme-refine-magenta
-                                         'modus-theme-nuanced-magenta
-                                         magenta-alt-other))))
-   `(helm-selection ((,class ,@(modus-vivendi-theme-extra-completions
-                                'modus-theme-subtle-blue
-                                'modus-theme-refine-blue
-                                'modus-theme-special-cold
-                                nil
-                                'bold))))
-   `(helm-selection-line ((,class :inherit modus-theme-special-cold)))
-   `(helm-separator ((,class :foreground ,fg-special-mild)))
-   `(helm-time-zone-current ((,class :foreground ,green)))
-   `(helm-time-zone-home ((,class :foreground ,magenta)))
-   `(helm-source-header ((,class :inherit bold :foreground ,red-alt
-                                 ,@(modus-vivendi-theme-scale 
modus-vivendi-theme-scale-4))))
-   `(helm-top-columns ((,class :inherit helm-header)))
-   `(helm-ucs-char ((,class :foreground ,yellow-alt-other)))
-   `(helm-visible-mark ((,class :inherit modus-theme-subtle-cyan)))
-;;;;; helm-ls-git
-   `(helm-ls-git-added-copied-face ((,class :foreground ,green-intense)))
-   `(helm-ls-git-added-modified-face ((,class :foreground ,yellow-intense)))
-   `(helm-ls-git-conflict-face ((,class :inherit bold :foreground 
,red-intense)))
-   `(helm-ls-git-deleted-and-staged-face ((,class :foreground ,red-nuanced)))
-   `(helm-ls-git-deleted-not-staged-face ((,class :foreground ,red)))
-   `(helm-ls-git-modified-and-staged-face ((,class :foreground 
,yellow-nuanced)))
-   `(helm-ls-git-modified-not-staged-face ((,class :foreground ,yellow)))
-   `(helm-ls-git-renamed-modified-face ((,class :foreground ,magenta)))
-   `(helm-ls-git-untracked-face ((,class :foreground ,fg-special-cold)))
-;;;;; helm-switch-shell
-   `(helm-switch-shell-new-shell-face ((,class 
,@(modus-vivendi-theme-extra-completions
-                                                  'modus-theme-subtle-magenta
-                                                  'modus-theme-refine-magenta
-                                                  'modus-theme-nuanced-magenta
-                                                  magenta-alt-other
-                                                  'bold))))
-;;;;; helm-xref
-   `(helm-xref-file-name ((,class :inherit bold :foreground ,fg-special-cold)))
-   `(helm-xref-file-name ((,class :foreground ,fg-special-warm)))
-;;;;; helpful
-   `(helpful-heading ((,class :inherit modus-theme-heading-1)))
-;;;;; highlight region or ad-hoc regexp
-   `(hi-black-b ((,class :background ,fg-main :foreground ,bg-main)))
-   `(hi-blue ((,class :background ,bg-alt :foreground ,blue :underline t)))
-   `(hi-blue-b ((,class :inherit modus-theme-intense-blue)))
-   `(hi-green ((,class :background ,bg-alt :foreground ,green :underline t)))
-   `(hi-green-b ((,class :inherit modus-theme-intense-green)))
-   `(hi-pink ((,class :background ,bg-alt :foreground ,magenta :underline t)))
-   `(hi-red-b ((,class :inherit modus-theme-intense-red)))
-   `(hi-yellow ((,class :background ,bg-alt :foreground ,yellow :underline t)))
-   `(highlight ((,class :inherit modus-theme-subtle-blue)))
-   `(highlight-changes ((,class :foreground ,yellow-alt-other)))
-   `(highlight-changes-delete ((,class :foreground ,red-alt-other :underline 
t)))
-   `(hl-line ((,class :inherit modus-theme-hl-line)))
-;;;;; highlight-blocks
-   `(highlight-blocks-depth-1-face ((,class :background ,bg-dim :foreground 
,fg-main)))
-   `(highlight-blocks-depth-2-face ((,class :background ,bg-alt :foreground 
,fg-main)))
-   `(highlight-blocks-depth-3-face ((,class :background ,bg-special-cold 
:foreground ,fg-main)))
-   `(highlight-blocks-depth-4-face ((,class :background ,bg-special-calm 
:foreground ,fg-main)))
-   `(highlight-blocks-depth-5-face ((,class :background ,bg-special-warm 
:foreground ,fg-main)))
-   `(highlight-blocks-depth-6-face ((,class :background ,bg-special-mild 
:foreground ,fg-main)))
-   `(highlight-blocks-depth-7-face ((,class :background ,bg-inactive 
:foreground ,fg-main)))
-   `(highlight-blocks-depth-8-face ((,class :background ,bg-active :foreground 
,fg-main)))
-   `(highlight-blocks-depth-9-face ((,class :background ,cyan-subtle-bg 
:foreground ,fg-main)))
-;;;;; highlight-defined
-   `(highlight-defined-builtin-function-name-face ((,class :foreground 
,magenta)))
-   `(highlight-defined-face-name-face ((,class :foreground ,fg-main)))
-   `(highlight-defined-function-name-face ((,class :foreground ,magenta)))
-   `(highlight-defined-macro-name-face ((,class :foreground ,magenta-alt)))
-   `(highlight-defined-special-form-name-face ((,class :foreground 
,magenta-alt-other)))
-   `(highlight-defined-variable-name-face ((,class :foreground ,cyan)))
-;;;;; highlight-escape-sequences (`hes-mode')
-   `(hes-escape-backslash-face ((,class :inherit bold :foreground 
,fg-escape-char-construct)))
-   `(hes-escape-sequence-face ((,class :inherit bold :foreground 
,fg-escape-char-backslash)))
-;;;;; highlight-indentation
-   `(highlight-indentation-face ((,class :inherit modus-theme-hl-line)))
-   `(highlight-indentation-current-column-face ((,class :background 
,bg-active)))
-;;;;; highlight-numbers
-   `(highlight-numbers-number ((,class :foreground ,blue-alt-other)))
-;;;;; highlight-symbol
-   `(highlight-symbol-face ((,class :inherit modus-theme-special-mild)))
-;;;;; highlight-thing
-   `(highlight-thing ((,class :background ,bg-alt :foreground ,cyan)))
-;;;;; hl-defined
-   `(hdefd-functions ((,class :foreground ,blue)))
-   `(hdefd-undefined ((,class :foreground ,red-alt)))
-   `(hdefd-variables ((,class :foreground ,cyan-alt)))
-;;;;; hl-fill-column
-   `(hl-fill-column-face ((,class :background ,bg-active :foreground 
,fg-active)))
-;;;;; hl-todo
-   `(hl-todo ((,class :inherit bold :foreground ,red-alt-other :slant 
,modus-theme-slant)))
-;;;;; hydra
-   `(hydra-face-amaranth ((,class :inherit bold :foreground ,yellow)))
-   `(hydra-face-blue ((,class :inherit bold :foreground ,blue-alt)))
-   `(hydra-face-pink ((,class :inherit bold :foreground ,magenta-alt)))
-   `(hydra-face-red ((,class :inherit bold :foreground ,red)))
-   `(hydra-face-teal ((,class :inherit bold :foreground ,cyan)))
-;;;;; hyperlist
-   `(hyperlist-condition ((,class :foreground ,green)))
-   `(hyperlist-hashtag ((,class :foreground ,yellow)))
-   `(hyperlist-operator ((,class :foreground ,blue-alt)))
-   `(hyperlist-paren ((,class :foreground ,cyan-alt-other)))
-   `(hyperlist-quote ((,class :foreground ,cyan-alt)))
-   `(hyperlist-ref ((,class :foreground ,magenta-alt-other)))
-   `(hyperlist-stars ((,class :foreground ,fg-alt)))
-   `(hyperlist-tag ((,class :foreground ,red)))
-   `(hyperlist-toplevel ((,class :inherit bold :foreground ,fg-main)))
-;;;;; icomplete
-   `(icomplete-first-match ((,class :inherit bold
-                                    ,@(modus-vivendi-theme-standard-completions
-                                       magenta bg-alt
-                                       bg-active fg-main))))
-;;;;; icomplete-vertical
-   `(icomplete-vertical-separator ((,class :foreground ,fg-alt)))
-;;;;; ido-mode
-   `(ido-first-match ((,class :inherit bold
-                              ,@(modus-vivendi-theme-standard-completions
-                                 magenta bg-alt
-                                 bg-active fg-main))))
-   `(ido-incomplete-regexp ((,class :inherit error)))
-   `(ido-indicator ((,class :inherit modus-theme-subtle-yellow)))
-   `(ido-only-match ((,class :inherit bold
-                             ,@(modus-vivendi-theme-standard-completions
-                                green green-nuanced-bg
-                                green-intense-bg fg-main))))
-   `(ido-subdir ((,class :foreground ,blue)))
-   `(ido-virtual ((,class :foreground ,fg-special-warm)))
-;;;;; iedit
-   `(iedit-occurrence ((,class :inherit modus-theme-refine-blue)))
-   `(iedit-read-only-occurrence ((,class :inherit modus-theme-intense-yellow)))
-;;;;; iflipb
-   `(iflipb-current-buffer-face ((,class :inherit bold :foreground ,cyan-alt)))
-   `(iflipb-other-buffer-face ((,class :foreground ,fg-alt)))
-;;;;; imenu-list
-   `(imenu-list-entry-face-0 ((,class :foreground ,cyan)))
-   `(imenu-list-entry-face-1 ((,class :foreground ,blue)))
-   `(imenu-list-entry-face-2 ((,class :foreground ,cyan-alt-other)))
-   `(imenu-list-entry-face-3 ((,class :foreground ,blue-alt)))
-   `(imenu-list-entry-subalist-face-0 ((,class :inherit bold :foreground 
,magenta-alt-other :underline t)))
-   `(imenu-list-entry-subalist-face-1 ((,class :inherit bold :foreground 
,magenta :underline t)))
-   `(imenu-list-entry-subalist-face-2 ((,class :inherit bold :foreground 
,green-alt-other :underline t)))
-   `(imenu-list-entry-subalist-face-3 ((,class :inherit bold :foreground 
,red-alt-other :underline t)))
-;;;;; indium
-   `(indium-breakpoint-face ((,class :foreground ,red-active)))
-   `(indium-frame-url-face ((,class :inherit button :foreground ,fg-alt)))
-   `(indium-keyword-face ((,class :foreground ,magenta-alt-other)))
-   `(indium-litable-face ((,class :foreground ,fg-special-warm :slant 
,modus-theme-slant)))
-   `(indium-repl-error-face ((,class :inherit bold :foreground ,red)))
-   `(indium-repl-prompt-face ((,class :foreground ,cyan-alt-other)))
-   `(indium-repl-stdout-face ((,class :foreground ,fg-main)))
-;;;;; info
-   `(Info-quoted ((,class ,@(modus-vivendi-theme-mixed-fonts)
-                          :foreground ,magenta))) ; the capitalisation is 
canonical
-   `(info-header-node ((,class :inherit bold :foreground ,fg-alt)))
-   `(info-header-xref ((,class :foreground ,blue-active)))
-   `(info-index-match ((,class :inherit match)))
-   `(info-menu-header ((,class :inherit modus-theme-heading-3)))
-   `(info-menu-star ((,class :foreground ,red)))
-   `(info-node ((,class :inherit bold)))
-   `(info-title-1 ((,class :inherit modus-theme-heading-1)))
-   `(info-title-2 ((,class :inherit modus-theme-heading-2)))
-   `(info-title-3 ((,class :inherit modus-theme-heading-3)))
-   `(info-title-4 ((,class :inherit modus-theme-heading-4)))
-;;;;; info-colors
-   `(info-colors-lisp-code-block ((,class :inherit fixed-pitch)))
-   `(info-colors-ref-item-command ((,class :foreground ,magenta)))
-   `(info-colors-ref-item-constant ((,class :foreground ,blue-alt-other)))
-   `(info-colors-ref-item-function ((,class :foreground ,magenta)))
-   `(info-colors-ref-item-macro ((,class ,@(modus-vivendi-theme-bold-weight) 
:foreground ,magenta-alt-other)))
-   `(info-colors-ref-item-other ((,class :foreground ,cyan)))
-   `(info-colors-ref-item-special-form ((,class 
,@(modus-vivendi-theme-bold-weight) :foreground ,magenta-alt-other)))
-   `(info-colors-ref-item-syntax-class ((,class :foreground ,magenta)))
-   `(info-colors-ref-item-type ((,class :foreground ,magenta-alt)))
-   `(info-colors-ref-item-user-option ((,class :foreground ,cyan)))
-   `(info-colors-ref-item-variable ((,class :foreground ,cyan)))
-;;;;; interaction-log
-   `(ilog-buffer-face ((,class :foreground ,magenta-alt-other)))
-   `(ilog-change-face ((,class :foreground ,magenta-alt)))
-   `(ilog-echo-face ((,class :foreground ,yellow-alt-other)))
-   `(ilog-load-face ((,class :foreground ,green)))
-   `(ilog-message-face ((,class :foreground ,fg-alt)))
-   `(ilog-non-change-face ((,class :foreground ,blue)))
-;;;;; ioccur
-   `(ioccur-cursor ((,class :foreground ,fg-main)))
-   `(ioccur-invalid-regexp ((,class :foreground ,red)))
-   `(ioccur-match-face ((,class :inherit modus-theme-special-calm)))
-   `(ioccur-match-overlay-face ((,class ,@(and (>= emacs-major-version 27) 
'(:extend t))
-                                        :inherit modus-theme-special-cold)))
-   `(ioccur-num-line-face ((,class :foreground ,fg-special-warm)))
-   `(ioccur-overlay-face ((,class ,@(and (>= emacs-major-version 27) '(:extend 
t))
-                                  :inherit modus-theme-refine-blue)))
-   `(ioccur-regexp-face ((,class :inherit (modus-theme-intense-magenta bold))))
-   `(ioccur-title-face ((,class :inherit bold :foreground ,red-alt
-                                ,@(modus-vivendi-theme-scale 
modus-vivendi-theme-scale-4))))
-;;;;; isearch, occur, and the like
-   `(isearch ((,class :inherit (modus-theme-intense-green bold))))
-   `(isearch-fail ((,class :inherit modus-theme-refine-red)))
-   `(lazy-highlight ((,class :inherit modus-theme-refine-cyan)))
-   `(match ((,class :inherit modus-theme-special-calm)))
-   `(query-replace ((,class :inherit (modus-theme-intense-yellow bold))))
-;;;;; ivy
-   `(ivy-action ((,class :inherit bold :foreground ,red-alt)))
-   `(ivy-completions-annotations ((,class :foreground ,fg-special-cold :slant 
,modus-theme-slant)))
-   `(ivy-confirm-face ((,class :foreground ,cyan)))
-   `(ivy-current-match ((,class ,@(modus-vivendi-theme-extra-completions
-                                   'modus-theme-refine-cyan
-                                   'modus-theme-intense-cyan
-                                   'modus-theme-special-warm
-                                   nil
-                                   'bold))))
-   `(ivy-cursor ((,class :background ,fg-main :foreground ,bg-main)))
-   `(ivy-grep-info ((,class :foreground ,cyan-alt)))
-   `(ivy-grep-line-number ((,class :foreground ,fg-special-warm)))
-   `(ivy-highlight-face ((,class :foreground ,magenta)))
-   `(ivy-match-required-face ((,class :inherit error)))
-   `(ivy-minibuffer-match-face-1 ((,class 
,@(modus-vivendi-theme-extra-completions
-                                             'modus-theme-subtle-neutral
-                                             'modus-theme-intense-neutral
-                                             'modus-theme-subtle-neutral
-                                             fg-alt))))
-   `(ivy-minibuffer-match-face-2 ((,class 
,@(modus-vivendi-theme-extra-completions
-                                             'modus-theme-subtle-green
-                                             'modus-theme-refine-green
-                                             'modus-theme-nuanced-green
-                                             green-alt-other
-                                             'bold))))
-   `(ivy-minibuffer-match-face-3 ((,class 
,@(modus-vivendi-theme-extra-completions
-                                             'modus-theme-subtle-cyan
-                                             'modus-theme-refine-cyan
-                                             'modus-theme-nuanced-cyan
-                                             cyan-alt-other
-                                             'bold))))
-   `(ivy-minibuffer-match-face-4 ((,class 
,@(modus-vivendi-theme-extra-completions
-                                             'modus-theme-subtle-magenta
-                                             'modus-theme-refine-magenta
-                                             'modus-theme-nuanced-magenta
-                                             magenta-alt-other
-                                             'bold))))
-   `(ivy-minibuffer-match-highlight ((,class 
,@(modus-vivendi-theme-extra-completions
-                                                'modus-theme-subtle-blue
-                                                'modus-theme-intense-blue
-                                                'modus-theme-nuanced-blue
-                                                blue-alt-other
-                                                'bold))))
-   `(ivy-modified-buffer ((,class :foreground ,yellow :slant 
,modus-theme-slant)))
-   `(ivy-modified-outside-buffer ((,class :foreground ,yellow-alt :slant 
,modus-theme-slant)))
-   `(ivy-org ((,class :foreground ,cyan-alt-other)))
-   `(ivy-prompt-match ((,class :inherit ivy-current-match)))
-   `(ivy-remote ((,class :foreground ,magenta)))
-   `(ivy-separator ((,class :foreground ,fg-alt)))
-   `(ivy-subdir ((,class :foreground ,blue-alt-other)))
-   `(ivy-virtual ((,class :foreground ,magenta-alt-other)))
-   `(ivy-yanked-word ((,class ,@(modus-vivendi-theme-extra-completions
-                                 'modus-theme-subtle-blue
-                                 'modus-theme-refine-blue
-                                 'modus-theme-nuanced-blue
-                                 blue-alt))))
-;;;;; ivy-posframe
-   `(ivy-posframe ((,class :background ,bg-dim :foreground ,fg-main)))
-   `(ivy-posframe-border ((,class :background ,bg-active)))
-   `(ivy-posframe-cursor ((,class :background ,fg-main :foreground ,bg-main)))
-;;;;; jira (org-jira)
-   `(jiralib-comment-face ((,class :background ,bg-alt)))
-   `(jiralib-comment-header-face ((,class :inherit bold)))
-   `(jiralib-issue-info-face ((,class :inherit modus-theme-special-warm)))
-   `(jiralib-issue-info-header-face ((,class :inherit 
(modus-theme-special-warm bold))))
-   `(jiralib-issue-summary-face ((,class :inherit bold)))
-   `(jiralib-link-filter-face ((,class :underline t)))
-   `(jiralib-link-issue-face ((,class :underline t)))
-   `(jiralib-link-project-face ((,class :underline t)))
-;;;;; journalctl-mode
-   `(journalctl-error-face ((,class :inherit bold :foreground ,red)))
-   `(journalctl-finished-face ((,class :inherit bold :foreground ,green)))
-   `(journalctl-host-face ((,class :foreground ,blue)))
-   `(journalctl-process-face ((,class :foreground ,cyan-alt-other)))
-   `(journalctl-starting-face ((,class :foreground ,green)))
-   `(journalctl-timestamp-face ((,class :foreground ,fg-special-cold)))
-   `(journalctl-warning-face ((,class :inherit bold :foreground ,yellow)))
-;;;;; js2-mode
-   `(js2-error ((,class :foreground ,red)))
-   `(js2-external-variable ((,class :foreground ,cyan-alt-other)))
-   `(js2-function-call ((,class :foreground ,magenta)))
-   `(js2-function-param ((,class :foreground ,blue)))
-   `(js2-instance-member ((,class :foreground ,magenta-alt-other)))
-   `(js2-jsdoc-html-tag-delimiter ((,class :foreground ,fg-main)))
-   `(js2-jsdoc-html-tag-name ((,class :foreground ,cyan)))
-   `(js2-jsdoc-tag ((,class :foreground ,fg-special-calm)))
-   `(js2-jsdoc-type ((,class :foreground ,fg-special-cold)))
-   `(js2-jsdoc-value ((,class :foreground ,fg-special-warm)))
-   `(js2-object-property ((,class :foreground ,fg-main)))
-   `(js2-object-property-access ((,class :foreground ,fg-main)))
-   `(js2-private-function-call ((,class :foreground ,green-alt-other)))
-   `(js2-private-member ((,class :foreground ,fg-special-mild)))
-   `(js2-warning ((,class :foreground ,yellow-alt :underline t)))
-;;;;; julia
-   `(julia-macro-face ((,class ,@(modus-vivendi-theme-bold-weight) :foreground 
,magenta)))
-   `(julia-quoted-symbol-face ((,class :foreground ,blue-alt-other)))
-;;;;; jupyter
-   `(jupyter-eval-overlay ((,class :inherit bold :foreground ,blue)))
-   `(jupyter-repl-input-prompt ((,class :foreground ,cyan-alt-other)))
-   `(jupyter-repl-output-prompt ((,class :foreground ,magenta-alt-other)))
-   `(jupyter-repl-traceback ((,class :inherit modus-theme-intense-red)))
-;;;;; kaocha-runner
-   `(kaocha-runner-error-face ((,class :foreground ,red)))
-   `(kaocha-runner-success-face ((,class :foreground ,green)))
-   `(kaocha-runner-warning-face ((,class :foreground ,yellow)))
-;;;;; keycast
-   `(keycast-command ((,class :inherit bold :foreground ,blue-active)))
-   `(keycast-key ((,class ,@(modus-vivendi-theme-mode-line-attrs
-                             bg-main blue-active
-                             bg-main blue-active
-                             blue-active blue-intense
-                             'alt-style -3))))
-;;;;; line numbers (display-line-numbers-mode and global variant)
-   `(line-number ((,class :inherit default :background ,bg-dim :foreground 
,fg-alt)))
-   `(line-number-current-line ((,class :inherit default :background ,bg-active 
:foreground ,fg-main)))
-;;;;; lsp-mode
-   `(lsp-face-highlight-read ((,class :inherit modus-theme-subtle-blue 
:underline t)))
-   `(lsp-face-highlight-textual ((,class :inherit modus-theme-subtle-blue)))
-   `(lsp-face-highlight-write ((,class :inherit (modus-theme-refine-blue 
bold))))
-   `(lsp-face-semhl-constant ((,class :foreground ,blue-alt-other)))
-   `(lsp-face-semhl-deprecated
-     ((,(append '((supports :underline (:style wave))) class)
-       :foreground ,yellow :underline (:style wave))
-      (,class :foreground ,yellow :underline t)))
-   `(lsp-face-semhl-enummember ((,class :foreground ,blue-alt-other)))
-   `(lsp-face-semhl-field ((,class :foreground ,cyan-alt)))
-   `(lsp-face-semhl-field-static ((,class :foreground ,cyan-alt :slant 
,modus-theme-slant)))
-   `(lsp-face-semhl-function ((,class :foreground ,magenta)))
-   `(lsp-face-semhl-method ((,class :foreground ,magenta)))
-   `(lsp-face-semhl-namespace ((,class ,@(modus-vivendi-theme-bold-weight) 
:foreground ,magenta-alt)))
-   `(lsp-face-semhl-preprocessor ((,class :foreground ,red-alt-other)))
-   `(lsp-face-semhl-static-method ((,class :foreground ,magenta :slant 
,modus-theme-slant)))
-   `(lsp-face-semhl-type-class ((,class :foreground ,magenta-alt)))
-   `(lsp-face-semhl-type-enum ((,class :foreground ,magenta-alt)))
-   `(lsp-face-semhl-type-primitive ((,class :foreground ,magenta-alt :slant 
,modus-theme-slant)))
-   `(lsp-face-semhl-type-template ((,class :foreground ,magenta-alt :slant 
,modus-theme-slant)))
-   `(lsp-face-semhl-type-typedef ((,class :foreground ,magenta-alt :slant 
,modus-theme-slant)))
-   `(lsp-face-semhl-variable ((,class :foreground ,cyan)))
-   `(lsp-face-semhl-variable-local ((,class :foreground ,cyan)))
-   `(lsp-face-semhl-variable-parameter ((,class :foreground ,cyan-alt-other)))
-   `(lsp-lens-face ((,class :height 0.8 :foreground ,fg-alt)))
-   `(lsp-lens-mouse-face ((,class :height 0.8 :foreground ,blue-alt-other 
:underline t)))
-   `(lsp-ui-doc-background ((,class :background ,bg-alt)))
-   `(lsp-ui-doc-header ((,class :background ,bg-header :foreground 
,fg-header)))
-   `(lsp-ui-doc-url ((,class :inherit button :foreground ,blue-alt-other)))
-   `(lsp-ui-peek-filename ((,class :foreground ,fg-special-warm)))
-   `(lsp-ui-peek-footer ((,class :background ,bg-header :foreground 
,fg-header)))
-   `(lsp-ui-peek-header ((,class :background ,bg-header :foreground 
,fg-header)))
-   `(lsp-ui-peek-highlight ((,class :inherit modus-theme-subtle-blue)))
-   `(lsp-ui-peek-line-number ((,class :foreground ,fg-alt)))
-   `(lsp-ui-peek-list ((,class :background ,bg-dim)))
-   `(lsp-ui-peek-peek ((,class :background ,bg-alt)))
-   `(lsp-ui-peek-selection ((,class :inherit modus-theme-subtle-cyan)))
-   `(lsp-ui-sideline-code-action ((,class :foreground ,yellow)))
-   `(lsp-ui-sideline-current-symbol ((,class :inherit bold :height 0.99 :box 
(:line-width -1 :style nil) :foreground ,fg-main)))
-   `(lsp-ui-sideline-symbol ((,class :inherit bold :height 0.99 :box 
(:line-width -1 :style nil) :foreground ,fg-alt)))
-   `(lsp-ui-sideline-symbol-info ((,class :height 0.99 :slant italic)))
-;;;;; magit
-   `(magit-bisect-bad ((,class :foreground ,red-alt-other)))
-   `(magit-bisect-good ((,class :foreground ,green-alt-other)))
-   `(magit-bisect-skip ((,class :foreground ,yellow-alt-other)))
-   `(magit-blame-date ((,class :foreground ,blue)))
-   `(magit-blame-dimmed ((,class :foreground ,fg-alt)))
-   `(magit-blame-hash ((,class :foreground ,fg-special-warm)))
-   `(magit-blame-heading ((,class :background ,bg-alt)))
-   `(magit-blame-highlight ((,class :inherit modus-theme-nuanced-cyan)))
-   `(magit-blame-margin ((,class :inherit magit-blame-highlight)))
-   `(magit-blame-name ((,class :foreground ,magenta-alt-other)))
-   `(magit-blame-summary ((,class :foreground ,cyan-alt-other)))
-   `(magit-branch-current ((,class :foreground ,blue-alt-other :box t)))
-   `(magit-branch-local ((,class :foreground ,blue-alt)))
-   `(magit-branch-remote ((,class :foreground ,magenta-alt)))
-   `(magit-branch-remote-head ((,class :foreground ,magenta-alt-other :box t)))
-   `(magit-branch-upstream ((,class :slant italic)))
-   `(magit-cherry-equivalent ((,class :background ,bg-main :foreground 
,magenta-intense)))
-   `(magit-cherry-unmatched ((,class :background ,bg-main :foreground 
,cyan-intense)))
-   ;; NOTE: here we break from the pattern of inheriting from the
-   ;; modus-theme-diff-* faces, though only for the standard actions,
-   ;; not the highlighted ones.  This is because Magit's interaction
-   ;; model relies on highlighting the current diff hunk.
-   `(magit-diff-added ((,class ,@(modus-vivendi-theme-diff
-                                  bg-main green
-                                  bg-diff-added fg-diff-added
-                                  green-nuanced-bg fg-diff-added))))
-   `(magit-diff-added-highlight ((,class :inherit 
modus-theme-diff-focus-added)))
-   `(magit-diff-base ((,class ,@(modus-vivendi-theme-diff
-                                 bg-main yellow
-                                 bg-diff-changed fg-diff-changed
-                                 yellow-nuanced-bg fg-diff-changed))))
-   `(magit-diff-base-highlight ((,class :inherit 
modus-theme-diff-focus-changed)))
-   `(magit-diff-context ((,class :foreground ,fg-unfocused)))
-   `(magit-diff-context-highlight ((,class ,@(modus-vivendi-theme-diff
-                                              bg-dim fg-dim
-                                              bg-inactive fg-inactive
-                                              bg-dim fg-alt))))
-   `(magit-diff-file-heading ((,class :inherit bold :foreground 
,fg-special-cold)))
-   `(magit-diff-file-heading-highlight ((,class :inherit 
(modus-theme-special-cold bold))))
-   `(magit-diff-file-heading-selection ((,class :inherit 
modus-theme-refine-cyan)))
-   ;; NOTE: here we break from the pattern of inheriting from the
-   ;; modus-theme-diff-* faces.
-   `(magit-diff-hunk-heading ((,class :inherit bold :background ,bg-active
-                                      :foreground ,fg-inactive)))
-   `(magit-diff-hunk-heading-highlight ((,class :inherit bold :background 
,bg-diff-heading
-                                                :foreground ,fg-diff-heading)))
-   `(magit-diff-hunk-heading-selection ((,class :inherit 
modus-theme-refine-blue)))
-   `(magit-diff-hunk-region ((,class :inherit bold)))
-   `(magit-diff-lines-boundary ((,class :background ,fg-main)))
-   `(magit-diff-lines-heading ((,class :inherit modus-theme-refine-magenta)))
-   `(magit-diff-removed ((,class ,@(modus-vivendi-theme-diff
-                                    bg-main red
-                                    bg-diff-removed fg-diff-removed
-                                    red-nuanced-bg fg-diff-removed))))
-   `(magit-diff-removed-highlight ((,class :inherit 
modus-theme-diff-focus-removed)))
-   `(magit-diffstat-added ((,class :foreground ,green)))
-   `(magit-diffstat-removed ((,class :foreground ,red)))
-   `(magit-dimmed ((,class :foreground ,fg-unfocused)))
-   `(magit-filename ((,class :foreground ,fg-special-cold)))
-   `(magit-hash ((,class :foreground ,fg-alt)))
-   `(magit-head ((,class :inherit magit-branch-local)))
-   `(magit-header-line ((,class :inherit bold :foreground ,magenta-active)))
-   `(magit-header-line-key ((,class :inherit bold :foreground ,red-active)))
-   `(magit-header-line-log-select ((,class :inherit bold :foreground 
,fg-main)))
-   `(magit-keyword ((,class :foreground ,magenta)))
-   `(magit-keyword-squash ((,class :inherit bold :foreground 
,yellow-alt-other)))
-   `(magit-log-author ((,class :foreground ,cyan)))
-   `(magit-log-date ((,class :foreground ,fg-alt)))
-   `(magit-log-graph ((,class :foreground ,fg-dim)))
-   `(magit-mode-line-process ((,class :inherit bold :foreground ,blue-active)))
-   `(magit-mode-line-process-error ((,class :inherit bold :foreground 
,red-active)))
-   `(magit-process-ng ((,class :inherit error)))
-   `(magit-process-ok ((,class :inherit success)))
-   `(magit-reflog-amend ((,class :background ,bg-main :foreground 
,magenta-intense)))
-   `(magit-reflog-checkout ((,class :background ,bg-main :foreground 
,blue-intense)))
-   `(magit-reflog-cherry-pick ((,class :background ,bg-main :foreground 
,green-intense)))
-   `(magit-reflog-commit ((,class :background ,bg-main :foreground 
,green-intense)))
-   `(magit-reflog-merge ((,class :background ,bg-main :foreground 
,green-intense)))
-   `(magit-reflog-other ((,class :background ,bg-main :foreground 
,cyan-intense)))
-   `(magit-reflog-rebase ((,class :background ,bg-main :foreground 
,magenta-intense)))
-   `(magit-reflog-remote ((,class :background ,bg-main :foreground 
,cyan-intense)))
-   `(magit-reflog-reset ((,class :background ,bg-main :foreground 
,red-intense)))
-   `(magit-refname ((,class :foreground ,fg-alt)))
-   `(magit-refname-pullreq ((,class :foreground ,fg-alt)))
-   `(magit-refname-stash ((,class :foreground ,fg-alt)))
-   `(magit-refname-wip ((,class :foreground ,fg-alt)))
-   `(magit-section ((,class :background ,bg-dim :foreground ,fg-main)))
-   `(magit-section-heading ((,class :inherit bold :foreground ,cyan)))
-   `(magit-section-heading-selection ((,class :inherit 
(modus-theme-refine-cyan bold))))
-   `(magit-section-highlight ((,class :background ,bg-alt)))
-   `(magit-sequence-done ((,class :foreground ,green-alt)))
-   `(magit-sequence-drop ((,class :foreground ,red-alt)))
-   `(magit-sequence-exec ((,class :foreground ,magenta-alt)))
-   `(magit-sequence-head ((,class :foreground ,cyan-alt)))
-   `(magit-sequence-onto ((,class :foreground ,fg-alt)))
-   `(magit-sequence-part ((,class :foreground ,yellow-alt)))
-   `(magit-sequence-pick ((,class :foreground ,blue-alt)))
-   `(magit-sequence-stop ((,class :foreground ,red)))
-   `(magit-signature-bad ((,class :inherit bold :foreground ,red)))
-   `(magit-signature-error ((,class :foreground ,red-alt)))
-   `(magit-signature-expired ((,class :foreground ,yellow)))
-   `(magit-signature-expired-key ((,class :foreground ,yellow)))
-   `(magit-signature-good ((,class :foreground ,green)))
-   `(magit-signature-revoked ((,class :foreground ,magenta)))
-   `(magit-signature-untrusted ((,class :foreground ,cyan)))
-   `(magit-tag ((,class :foreground ,yellow-alt-other)))
-;;;;; magit-imerge
-   `(magit-imerge-overriding-value ((,class :inherit bold :foreground 
,red-alt)))
-;;;;; man
-   `(Man-overstrike ((,class :inherit bold :foreground ,magenta)))
-   `(Man-reverse ((,class :inherit modus-theme-subtle-magenta)))
-   `(Man-underline ((,class :foreground ,cyan :underline t)))
-;;;;; markdown-mode
-   `(markdown-blockquote-face ((,class :foreground ,fg-special-cold :slant 
,modus-theme-slant)))
-   `(markdown-bold-face ((,class :inherit bold)))
-   `(markdown-code-face ((,class ,@(modus-vivendi-theme-mixed-fonts))))
-   `(markdown-comment-face ((,class :foreground ,fg-alt :slant 
,modus-theme-slant)))
-   `(markdown-footnote-marker-face ((,class :inherit bold :foreground 
,cyan-alt)))
-   `(markdown-footnote-text-face ((,class :foreground ,fg-main :slant 
,modus-theme-slant)))
-   `(markdown-gfm-checkbox-face ((,class :foreground ,cyan-alt-other)))
-   `(markdown-header-delimiter-face ((,class 
,@(modus-vivendi-theme-bold-weight) :foreground ,fg-dim)))
-   `(markdown-header-face ((t nil)))
-   `(markdown-header-face-1 ((,class :inherit modus-theme-heading-1)))
-   `(markdown-header-face-2 ((,class :inherit modus-theme-heading-2)))
-   `(markdown-header-face-3 ((,class :inherit modus-theme-heading-3)))
-   `(markdown-header-face-4 ((,class :inherit modus-theme-heading-4)))
-   `(markdown-header-face-5 ((,class :inherit modus-theme-heading-5)))
-   `(markdown-header-face-6 ((,class :inherit modus-theme-heading-6)))
-   `(markdown-header-rule-face ((,class :inherit bold :foreground 
,fg-special-warm)))
-   `(markdown-hr-face ((,class :inherit bold :foreground ,fg-special-warm)))
-   `(markdown-html-attr-name-face ((,class ,@(modus-vivendi-theme-mixed-fonts)
-                                           :foreground ,cyan)))
-   `(markdown-html-attr-value-face ((,class ,@(modus-vivendi-theme-mixed-fonts)
-                                            :foreground ,blue)))
-   `(markdown-html-entity-face ((,class ,@(modus-vivendi-theme-mixed-fonts)
-                                        :foreground ,cyan)))
-   `(markdown-html-tag-delimiter-face ((,class 
,@(modus-vivendi-theme-mixed-fonts)
-                                               :foreground ,fg-special-mild)))
-   `(markdown-html-tag-name-face ((,class ,@(modus-vivendi-theme-mixed-fonts)
-                                          :foreground ,magenta-alt)))
-   `(markdown-inline-code-face ((,class ,@(modus-vivendi-theme-mixed-fonts)
-                                        :foreground ,magenta)))
-   `(markdown-italic-face ((,class :foreground ,fg-special-cold :slant 
italic)))
-   `(markdown-language-info-face ((,class ,@(modus-vivendi-theme-mixed-fonts)
-                                          :foreground ,fg-special-cold)))
-   `(markdown-language-keyword-face ((,class 
,@(modus-vivendi-theme-mixed-fonts)
-                                             :foreground ,green-alt-other)))
-   `(markdown-line-break-face ((,class :inherit modus-theme-refine-cyan 
:underline t)))
-   `(markdown-link-face ((,class :inherit link)))
-   `(markdown-link-title-face ((,class :foreground ,fg-special-cold :slant 
,modus-theme-slant)))
-   `(markdown-list-face ((,class :foreground ,fg-dim)))
-   `(markdown-markup-face ((,class :foreground ,fg-alt)))
-   `(markdown-math-face ((,class :foreground ,magenta-alt-other)))
-   `(markdown-metadata-key-face ((,class :foreground ,cyan-alt-other)))
-   `(markdown-metadata-value-face ((,class :foreground ,blue-alt)))
-   `(markdown-missing-link-face ((,class :inherit bold :foreground ,yellow)))
-   `(markdown-plain-url-face ((,class :inherit markdown-link-face)))
-   `(markdown-pre-face ((,class ,@(and (>= emacs-major-version 27) '(:extend 
t))
-                                ,@(modus-vivendi-theme-mixed-fonts)
-                                :background ,bg-dim
-                                :foreground ,fg-special-mild)))
-   `(markdown-reference-face ((,class :inherit markdown-markup-face)))
-   `(markdown-strike-through-face ((,class :strike-through t)))
-   `(markdown-table-face ((,class ,@(modus-vivendi-theme-mixed-fonts)
-                                  :foreground ,fg-special-cold)))
-   `(markdown-url-face ((,class :foreground ,blue-alt)))
-;;;;; markup-faces (`adoc-mode')
-   `(markup-anchor-face ((,class :foreground ,fg-inactive)))
-   `(markup-attribute-face ((,class :foreground ,fg-inactive :slant italic)))
-   `(markup-big-face ((,class :height 1.3 :foreground ,blue-nuanced)))
-   `(markup-bold-face ((,class :inherit bold :foreground ,red-nuanced)))
-   `(markup-code-face ((,class :inherit fixed-pitch :foreground ,magenta)))
-   `(markup-command-face ((,class :foreground ,fg-inactive)))
-   `(markup-comment-face ((,class :foreground ,fg-alt :slant 
,modus-theme-slant)))
-   `(markup-complex-replacement-face ((,class :box (:line-width 2 :color nil 
:style released-button)
-                                              :inherit 
modus-theme-refine-magenta)))
-   `(markup-emphasis-face ((,class :foreground ,fg-special-cold :slant 
italic)))
-   `(markup-error-face ((,class :inherit bold :foreground ,red)))
-   `(markup-gen-face ((,class :foreground ,magenta-alt)))
-   `(markup-internal-reference-face ((,class :inherit button :foreground 
,fg-inactive)))
-   `(markup-italic-face ((,class :foreground ,fg-special-cold :slant italic)))
-   `(markup-list-face ((,class :inherit modus-theme-special-calm)))
-   `(markup-meta-face ((,class :foreground ,fg-inactive)))
-   `(markup-meta-hide-face ((,class :foreground ,fg-alt)))
-   `(markup-passthrough-face ((,class :inherit fixed-pitch :foreground ,cyan)))
-   `(markup-preprocessor-face ((,class :foreground ,red-alt-other)))
-   `(markup-replacement-face ((,class :foreground ,yellow-alt-other)))
-   `(markup-secondary-text-face ((,class :height 0.8 :foreground 
,magenta-nuanced)))
-   `(markup-small-face ((,class :height 0.8 :foreground ,fg-main)))
-   `(markup-strong-face ((,class :inherit bold :foreground ,red-nuanced)))
-   `(markup-subscript-face ((,class :height 0.8 :foreground ,fg-special-cold)))
-   `(markup-superscript-face ((,class :height 0.8 :foreground 
,fg-special-cold)))
-   `(markup-table-cell-face ((,class :inherit modus-theme-special-cold)))
-   `(markup-table-face ((,class :inherit modus-theme-subtle-cyan)))
-   `(markup-table-row-face ((,class :inherit modus-theme-subtle-cyan)))
-   `(markup-title-0-face ((,class :height 3.0 :foreground ,blue-nuanced)))
-   `(markup-title-1-face ((,class :height 2.4 :foreground ,blue-nuanced)))
-   `(markup-title-2-face ((,class :height 1.8 :foreground ,blue-nuanced)))
-   `(markup-title-3-face ((,class :height 1.4 :foreground ,blue-nuanced)))
-   `(markup-title-4-face ((,class :height 1.2 :foreground ,blue-nuanced)))
-   `(markup-title-5-face ((,class :height 1.2 :foreground ,blue-nuanced 
:underline t)))
-   `(markup-value-face ((,class :foreground ,fg-inactive)))
-   `(markup-verbatim-face ((,class :inherit modus-theme-special-mild)))
-;;;;; mentor
-   `(mentor-download-message ((,class :foreground ,fg-special-warm)))
-   `(mentor-download-name ((,class :foreground ,fg-special-cold)))
-   `(mentor-download-progress ((,class :foreground ,blue-alt-other)))
-   `(mentor-download-size ((,class :foreground ,magenta-alt-other)))
-   `(mentor-download-speed-down ((,class :foreground ,cyan-alt)))
-   `(mentor-download-speed-up ((,class :foreground ,red-alt)))
-   `(mentor-download-state ((,class :foreground ,yellow-alt)))
-   `(mentor-highlight-face ((,class :inherit modus-theme-subtle-blue)))
-   `(mentor-tracker-name ((,class :foreground ,magenta-alt)))
-;;;;; messages
-   `(message-cited-text-1 ((,class :foreground ,blue-alt)))
-   `(message-cited-text-2 ((,class :foreground ,red-alt)))
-   `(message-cited-text-3 ((,class :foreground ,green-alt)))
-   `(message-cited-text-4 ((,class :foreground ,magenta-alt)))
-   `(message-header-cc ((,class :inherit bold :foreground ,cyan-alt)))
-   `(message-header-name ((,class :foreground ,green-alt-other)))
-   `(message-header-newsgroups ((,class :inherit bold :foreground ,green-alt)))
-   `(message-header-other ((,class :inherit bold :foreground ,cyan-alt-other)))
-   `(message-header-subject ((,class :inherit bold :foreground 
,magenta-alt-other)))
-   `(message-header-to ((,class :inherit bold :foreground ,blue)))
-   `(message-header-xheader ((,class :foreground ,cyan)))
-   `(message-mml ((,class :foreground ,fg-special-warm)))
-   `(message-separator ((,class :inherit modus-theme-intense-neutral)))
-;;;;; minibuffer-line
-   `(minibuffer-line ((,class :foreground ,fg-main)))
-;;;;; minimap
-   `(minimap-active-region-background ((,class :background ,bg-active)))
-   `(minimap-current-line-face ((,class :background ,cyan-intense-bg 
:foreground ,fg-main)))
-;;;;; modeline
-   `(mode-line ((,class ,@(modus-vivendi-theme-mode-line-attrs
-                           fg-active bg-active fg-dim bg-active
-                           fg-alt bg-active 'alt-style nil bg-main))))
-   `(mode-line-buffer-id ((,class :inherit bold)))
-   `(mode-line-emphasis ((,class :inherit bold :foreground ,blue-active)))
-   `(mode-line-highlight ((,class :inherit modus-theme-active-blue :box 
(:line-width -1 :style pressed-button))))
-   `(mode-line-inactive ((,class ,@(modus-vivendi-theme-mode-line-attrs
-                                    fg-inactive bg-inactive fg-alt bg-dim
-                                    bg-region bg-active))))
-;;;;; mood-line
-   `(mood-line-modified ((,class :foreground ,magenta-active)))
-   `(mood-line-status-error ((,class :inherit bold :foreground ,red-active)))
-   `(mood-line-status-info ((,class :foreground ,cyan-active)))
-   `(mood-line-status-neutral ((,class :foreground ,blue-active)))
-   `(mood-line-status-success ((,class :foreground ,green-active)))
-   `(mood-line-status-warning ((,class :inherit bold :foreground 
,yellow-active)))
-   `(mood-line-unimportant ((,class :foreground ,fg-inactive)))
-;;;;; mpdel
-   `(mpdel-browser-directory-face ((,class :foreground ,blue)))
-   `(mpdel-playlist-current-song-face ((,class :inherit bold :foreground 
,blue-alt-other)))
-;;;;; mu4e
-   `(mu4e-attach-number-face ((,class :inherit bold :foreground ,cyan-alt)))
-   `(mu4e-cited-1-face ((,class :foreground ,blue-alt)))
-   `(mu4e-cited-2-face ((,class :foreground ,red-alt)))
-   `(mu4e-cited-3-face ((,class :foreground ,green-alt)))
-   `(mu4e-cited-4-face ((,class :foreground ,magenta-alt)))
-   `(mu4e-cited-5-face ((,class :foreground ,yellow-alt)))
-   `(mu4e-cited-6-face ((,class :foreground ,cyan-alt)))
-   `(mu4e-cited-7-face ((,class :foreground ,magenta)))
-   `(mu4e-compose-header-face ((,class :inherit mu4e-compose-separator-face)))
-   `(mu4e-compose-separator-face ((,class :inherit 
modus-theme-intense-neutral)))
-   `(mu4e-contact-face ((,class :inherit bold :foreground ,cyan-alt-other)))
-   `(mu4e-context-face ((,class :foreground ,blue-active)))
-   `(mu4e-draft-face ((,class :foreground ,magenta-alt)))
-   `(mu4e-flagged-face ((,class :foreground ,red-alt)))
-   `(mu4e-footer-face ((,class :foreground ,fg-special-cold :slant 
,modus-theme-slant)))
-   `(mu4e-forwarded-face ((,class :foreground ,magenta-alt-other)))
-   `(mu4e-header-face ((,class :foreground ,fg-alt)))
-   `(mu4e-header-highlight-face ((,class :inherit modus-theme-hl-line)))
-   `(mu4e-header-key-face ((,class :foreground ,cyan)))
-   `(mu4e-header-marks-face ((,class :inherit bold :foreground ,magenta-alt)))
-   `(mu4e-header-title-face ((,class :foreground ,fg-special-mild)))
-   `(mu4e-header-value-face ((,class :inherit bold :foreground 
,magenta-alt-other)))
-   `(mu4e-highlight-face ((,class :inherit bold :foreground ,blue-alt-other)))
-   `(mu4e-link-face ((,class :inherit link)))
-   `(mu4e-modeline-face ((,class :foreground ,magenta-active)))
-   `(mu4e-moved-face ((,class :foreground ,yellow :slant ,modus-theme-slant)))
-   `(mu4e-ok-face ((,class :inherit bold :foreground ,green)))
-   `(mu4e-region-code ((,class :inherit modus-theme-special-calm)))
-   `(mu4e-replied-face ((,class :foreground ,blue-faint)))
-   `(mu4e-special-header-value-face ((,class :inherit bold :foreground 
,blue-alt-other)))
-   `(mu4e-system-face ((,class :foreground ,fg-mark-del :slant 
,modus-theme-slant)))
-   `(mu4e-title-face ((,class :foreground ,fg-main)))
-   `(mu4e-trashed-face ((,class :foreground ,red)))
-   `(mu4e-unread-face ((,class :inherit bold :foreground ,fg-main)))
-   `(mu4e-url-number-face ((,class :inherit bold :foreground ,cyan-alt-other)))
-   `(mu4e-view-body-face ((,class :foreground ,fg-main)))
-   `(mu4e-warning-face ((,class :inherit warning)))
-;;;;; mu4e-conversation
-   `(mu4e-conversation-header ((,class :inherit modus-theme-special-cold)))
-   `(mu4e-conversation-sender-1 ((,class :foreground ,fg-special-warm)))
-   `(mu4e-conversation-sender-2 ((,class :foreground ,fg-special-cold)))
-   `(mu4e-conversation-sender-3 ((,class :foreground ,fg-special-mild)))
-   `(mu4e-conversation-sender-4 ((,class :foreground ,fg-alt)))
-   `(mu4e-conversation-sender-5 ((,class :foreground ,yellow-refine-fg)))
-   `(mu4e-conversation-sender-6 ((,class :foreground ,cyan-refine-fg)))
-   `(mu4e-conversation-sender-7 ((,class :foreground ,green-refine-fg)))
-   `(mu4e-conversation-sender-8 ((,class :foreground ,blue-refine-fg)))
-   `(mu4e-conversation-sender-me ((,class :foreground ,fg-main)))
-   `(mu4e-conversation-unread ((,class :inherit bold)))
-;;;;; multiple-cursors
-   `(mc/cursor-bar-face ((,class :height 1 :background ,fg-main)))
-   `(mc/cursor-face ((,class :inverse-video t)))
-   `(mc/region-face ((,class :inherit region)))
-;;;;; neotree
-   `(neo-banner-face ((,class :foreground ,magenta)))
-   `(neo-button-face ((,class :inherit button)))
-   `(neo-dir-link-face ((,class :inherit bold :foreground ,blue)))
-   `(neo-expand-btn-face ((,class :foreground ,cyan)))
-   `(neo-file-link-face ((,class :foreground ,fg-main)))
-   `(neo-header-face ((,class :inherit bold :foreground ,fg-main)))
-   `(neo-root-dir-face ((,class :inherit bold :foreground ,cyan-alt)))
-   `(neo-vc-added-face ((,class :foreground ,green)))
-   `(neo-vc-conflict-face ((,class :inherit bold :foreground ,red)))
-   `(neo-vc-default-face ((,class :foreground ,fg-main)))
-   `(neo-vc-edited-face ((,class :foreground ,yellow)))
-   `(neo-vc-ignored-face ((,class :foreground ,fg-inactive)))
-   `(neo-vc-missing-face ((,class :foreground ,red-alt)))
-   `(neo-vc-needs-merge-face ((,class :foreground ,magenta-alt)))
-   `(neo-vc-needs-update-face ((,class :underline t)))
-   `(neo-vc-removed-face ((,class :strike-through t)))
-   `(neo-vc-unlocked-changes-face ((,class :inherit modus-theme-refine-blue)))
-   `(neo-vc-up-to-date-face ((,class :foreground ,fg-alt)))
-   `(neo-vc-user-face ((,class :foreground ,magenta)))
-;;;;; no-emoji
-   `(no-emoji ((,class :foreground ,cyan)))
-;;;;; notmuch
-   `(notmuch-crypto-decryption ((,class :inherit modus-theme-refine-magenta)))
-   `(notmuch-crypto-part-header ((,class :foreground ,magenta-alt-other)))
-   `(notmuch-crypto-signature-bad ((,class :inherit modus-theme-intense-red)))
-   `(notmuch-crypto-signature-good ((,class :inherit 
modus-theme-refine-green)))
-   `(notmuch-crypto-signature-good-key ((,class :inherit 
modus-theme-refine-yellow)))
-   `(notmuch-crypto-signature-unknown ((,class :inherit 
modus-theme-refine-red)))
-   `(notmuch-hello-logo-background ((,class :background ,bg-main)))
-   `(notmuch-message-summary-face ((,class :inherit modus-theme-nuanced-cyan)))
-   `(notmuch-search-flagged-face ((,class :foreground ,red-alt)))
-   `(notmuch-search-matching-authors ((,class :foreground ,fg-main)))
-   `(notmuch-search-non-matching-authors ((,class :foreground ,fg-alt)))
-   `(notmuch-search-unread-face ((,class :inherit bold)))
-   `(notmuch-tag-added
-     ((,(append '((supports :underline (:style wave))) class)
-       :underline (:color ,green :style wave))
-      (,class :foreground ,green :underline t)))
-   `(notmuch-tag-deleted
-     ((,(append '((supports :underline (:style wave))) class)
-       :underline (:color ,red :style wave))
-      (,class :foreground ,red :underline t)))
-   `(notmuch-tag-face ((,class :inherit bold :foreground ,blue-alt)))
-   `(notmuch-tag-flagged ((,class :foreground ,red-alt)))
-   `(notmuch-tag-unread ((,class :foreground ,magenta-alt)))
-   `(notmuch-tree-match-author-face ((,class :foreground ,fg-special-cold)))
-   `(notmuch-tree-match-face ((,class :foreground ,fg-main)))
-   `(notmuch-tree-match-tag-face ((,class :inherit bold :foreground 
,blue-alt)))
-   `(notmuch-tree-no-match-face ((,class :foreground ,fg-alt)))
-   `(notmuch-wash-cited-text ((,class :foreground ,cyan)))
-   `(notmuch-wash-toggle-button ((,class :background ,bg-alt :foreground 
,fg-alt)))
-;;;;; num3-mode
-   `(num3-face-even ((,class :inherit bold :background ,bg-alt)))
-;;;;; nxml-mode
-   `(nxml-attribute-colon ((,class :foreground ,fg-main)))
-   `(nxml-attribute-local-name ((,class 
,@(modus-vivendi-theme-syntax-foreground
-                                           cyan-alt cyan-alt-faint))))
-   `(nxml-attribute-prefix ((,class ,@(modus-vivendi-theme-syntax-foreground
-                                       cyan-alt-other cyan-alt-other-faint)
-                                    ,@(modus-vivendi-theme-bold-weight))))
-   `(nxml-attribute-value ((,class ,@(modus-vivendi-theme-syntax-foreground
-                                      blue blue-faint))))
-   `(nxml-cdata-section-CDATA ((,class ,@(modus-vivendi-theme-syntax-foreground
-                                          red-alt red-alt-faint)
-                                       ,@(modus-vivendi-theme-bold-weight))))
-   `(nxml-cdata-section-delimiter ((,class 
,@(modus-vivendi-theme-syntax-foreground
-                                              red-alt red-alt-faint))))
-   `(nxml-char-ref-delimiter ((,class ,@(modus-vivendi-theme-syntax-foreground
-                                         green-alt-other 
green-alt-other-faint))))
-   `(nxml-char-ref-number ((,class ,@(modus-vivendi-theme-syntax-foreground
-                                      green-alt-other green-alt-other-faint)
-                                   ,@(modus-vivendi-theme-bold-weight))))
-   `(nxml-delimited-data ((,class :foreground ,fg-special-cold :slant 
,modus-theme-slant)))
-   `(nxml-delimiter ((,class :foreground ,fg-dim)))
-   `(nxml-element-colon ((,class :foreground ,fg-main)))
-   `(nxml-element-local-name ((,class ,@(modus-vivendi-theme-syntax-foreground
-                                         magenta magenta-faint))))
-   `(nxml-element-prefix ((,class ,@(modus-vivendi-theme-syntax-foreground
-                                     magenta-alt magenta-alt-faint)
-                                  ,@(modus-vivendi-theme-bold-weight))))
-   `(nxml-entity-ref-delimiter ((,class 
,@(modus-vivendi-theme-syntax-foreground
-                                           green-alt-other 
green-alt-other-faint))))
-   `(nxml-entity-ref-name ((,class ,@(modus-vivendi-theme-syntax-foreground
-                                      green-alt-other green-alt-other-faint)
-                                   ,@(modus-vivendi-theme-bold-weight))))
-   `(nxml-glyph ((,class :inherit modus-theme-intense-neutral)))
-   `(nxml-hash ((,class ,@(modus-vivendi-theme-syntax-foreground
-                           blue-alt blue-alt-faint)
-                        ,@(modus-vivendi-theme-bold-weight))))
-   `(nxml-heading ((,class :inherit bold)))
-   `(nxml-name ((,class ,@(modus-vivendi-theme-syntax-foreground
-                           magenta-alt magenta-alt-faint)
-                        ,@(modus-vivendi-theme-bold-weight))))
-   `(nxml-namespace-attribute-colon ((,class :foreground ,fg-main)))
-   `(nxml-namespace-attribute-prefix ((,class 
,@(modus-vivendi-theme-syntax-foreground
-                                                 cyan cyan-faint))))
-   `(nxml-processing-instruction-target ((,class 
,@(modus-vivendi-theme-syntax-foreground
-                                                    magenta-alt-other 
magenta-alt-other-faint)
-                                                 
,@(modus-vivendi-theme-bold-weight))))
-   `(nxml-prolog-keyword ((,class ,@(modus-vivendi-theme-syntax-foreground
-                                     magenta-alt-other magenta-alt-other-faint)
-                                  ,@(modus-vivendi-theme-bold-weight))))
-   `(nxml-ref ((,class ,@(modus-vivendi-theme-syntax-foreground
-                          green-alt-other green-alt-other-faint)
-                       ,@(modus-vivendi-theme-bold-weight))))
-;;;;; objed
-   `(objed-hl ((,class :background ,(if modus-vivendi-theme-intense-hl-line
-                                        bg-hl-alt-intense bg-hl-alt))))
-   `(objed-mark ((,class :background ,bg-active)))
-   `(objed-mode-line ((,class :foreground ,cyan-active)))
-;;;;; orderless
-   `(orderless-match-face-0 ((,class :inherit bold
-                                     
,@(modus-vivendi-theme-standard-completions
-                                        blue-alt-other blue-nuanced-bg
-                                        blue-refine-bg blue-refine-fg))))
-   `(orderless-match-face-1 ((,class :inherit bold
-                                     
,@(modus-vivendi-theme-standard-completions
-                                        magenta-alt magenta-nuanced-bg
-                                        magenta-refine-bg magenta-refine-fg))))
-   `(orderless-match-face-2 ((,class :inherit bold
-                                     
,@(modus-vivendi-theme-standard-completions
-                                        green green-nuanced-bg
-                                        green-refine-bg green-refine-fg))))
-   `(orderless-match-face-3 ((,class :inherit bold
-                                     
,@(modus-vivendi-theme-standard-completions
-                                        yellow yellow-nuanced-bg
-                                        yellow-refine-bg yellow-refine-fg))))
-;;;;; org
-   `(org-agenda-calendar-event ((,class :foreground ,fg-main)))
-   `(org-agenda-calendar-sexp ((,class :foreground ,cyan-alt)))
-   `(org-agenda-clocking ((,class :inherit modus-theme-special-cold
-                                  ,@(and (>= emacs-major-version 27) '(:extend 
t)))))
-   `(org-agenda-column-dateline ((,class :background ,bg-alt)))
-   `(org-agenda-current-time ((,class :inherit bold :foreground 
,blue-alt-other)))
-   `(org-agenda-date ((,class :foreground ,cyan)))
-   `(org-agenda-date-today ((,class :inherit bold :foreground ,fg-main 
:underline t)))
-   `(org-agenda-date-weekend ((,class :foreground ,cyan-alt-other)))
-   `(org-agenda-diary ((,class :foreground ,fg-main)))
-   `(org-agenda-dimmed-todo-face ((,class :inherit bold :foreground ,fg-alt)))
-   `(org-agenda-done ((,class :foreground ,green-alt)))
-   `(org-agenda-filter-category ((,class :inherit bold :foreground 
,magenta-active)))
-   `(org-agenda-filter-effort ((,class :inherit bold :foreground 
,magenta-active)))
-   `(org-agenda-filter-regexp ((,class :inherit bold :foreground 
,magenta-active)))
-   `(org-agenda-filter-tags ((,class :inherit bold :foreground 
,magenta-active)))
-   `(org-agenda-restriction-lock ((,class :background ,bg-dim :foreground 
,fg-dim)))
-   `(org-agenda-structure ((,class :foreground ,blue-alt)))
-   `(org-archived ((,class :background ,bg-alt :foreground ,fg-alt)))
-   `(org-block ((,class ,@(modus-vivendi-theme-mixed-fonts)
-                        ,@(modus-vivendi-theme-org-block bg-dim)
-                        :foreground ,fg-main)))
-   `(org-block-begin-line ((,class ,@(modus-vivendi-theme-mixed-fonts)
-                                   ,@(modus-vivendi-theme-org-block-delim
-                                      bg-dim fg-special-cold
-                                      bg-alt fg-special-mild))))
-   `(org-block-end-line ((,class :inherit org-block-begin-line)))
-   `(org-checkbox ((,class :box (:line-width 1 :color ,bg-active)
-                           :background ,bg-inactive :foreground ,fg-active)))
-   `(org-checkbox-statistics-done ((,class :inherit org-done)))
-   `(org-checkbox-statistics-todo ((,class :inherit org-todo)))
-   `(org-clock-overlay ((,class :inherit modus-theme-special-cold)))
-   `(org-code ((,class ,@(modus-vivendi-theme-mixed-fonts) :foreground 
,magenta)))
-   `(org-column ((,class :background ,bg-alt)))
-   `(org-column-title ((,class :inherit bold :underline t :background 
,bg-alt)))
-   `(org-date ((,class :inherit (button fixed-pitch) :foreground 
,cyan-alt-other)))
-   `(org-date-selected ((,class :inherit bold :foreground ,blue-alt 
:inverse-video t)))
-   `(org-document-info ((,class :foreground ,fg-special-cold)))
-   `(org-document-info-keyword ((,class ,@(modus-vivendi-theme-mixed-fonts)
-                                        :foreground ,fg-alt)))
-   `(org-document-title ((,class :inherit (bold ,modus-theme-variable-pitch) 
:foreground ,fg-special-cold
-                                 ,@(modus-vivendi-theme-scale 
modus-vivendi-theme-scale-5))))
-   `(org-done ((,class :box ,bg-region :background ,bg-dim :foreground 
,green)))
-   `(org-drawer ((,class ,@(modus-vivendi-theme-mixed-fonts)
-                         :foreground ,cyan)))
-   `(org-ellipsis ((,class :foreground nil))) ; inherits from the heading's 
colour
-   `(org-footnote ((,class :inherit button :foreground ,blue-alt)))
-   `(org-formula ((,class ,@(modus-vivendi-theme-mixed-fonts)
-                          :foreground ,red-alt)))
-   `(org-habit-alert-face ((,class :inherit modus-theme-intense-yellow)))
-   `(org-habit-alert-future-face ((,class :inherit modus-theme-refine-yellow)))
-   `(org-habit-clear-face ((,class :inherit modus-theme-intense-magenta)))
-   `(org-habit-clear-future-face ((,class :inherit 
modus-theme-refine-magenta)))
-   `(org-habit-overdue-face ((,class :inherit modus-theme-intense-red)))
-   `(org-habit-overdue-future-face ((,class :inherit modus-theme-refine-red)))
-   `(org-habit-ready-face ((,class :inherit modus-theme-intense-blue)))
-   `(org-habit-ready-future-face ((,class :inherit modus-theme-refine-blue)))
-   `(org-headline-done ((,class :inherit ,modus-theme-variable-pitch 
:foreground ,green-nuanced)))
-   `(org-headline-todo ((,class :inherit ,modus-theme-variable-pitch 
:foreground ,red-nuanced)))
-   `(org-hide ((,class :foreground ,bg-main)))
-   `(org-indent ((,class :inherit (fixed-pitch org-hide))))
-   `(org-latex-and-related ((,class :foreground ,magenta-refine-fg)))
-   `(org-level-1 ((,class :inherit modus-theme-heading-1)))
-   `(org-level-2 ((,class :inherit modus-theme-heading-2)))
-   `(org-level-3 ((,class :inherit modus-theme-heading-3)))
-   `(org-level-4 ((,class :inherit modus-theme-heading-4)))
-   `(org-level-5 ((,class :inherit modus-theme-heading-5)))
-   `(org-level-6 ((,class :inherit modus-theme-heading-6)))
-   `(org-level-7 ((,class :inherit modus-theme-heading-7)))
-   `(org-level-8 ((,class :inherit modus-theme-heading-8)))
-   `(org-link ((,class :inherit link)))
-   `(org-list-dt ((,class :inherit bold)))
-   `(org-macro ((,class :background ,blue-nuanced-bg :foreground 
,magenta-alt-other)))
-   `(org-meta-line ((,class ,@(modus-vivendi-theme-mixed-fonts) :foreground 
,fg-alt)))
-   `(org-mode-line-clock ((,class :foreground ,fg-main)))
-   `(org-mode-line-clock-overrun ((,class :inherit modus-theme-active-red)))
-   `(org-priority ((,class :box ,bg-region :background ,bg-dim :foreground 
,magenta)))
-   `(org-property-value ((,class ,@(modus-vivendi-theme-mixed-fonts)
-                                 :foreground ,cyan-alt-other)))
-   `(org-quote ((,class ,@(modus-vivendi-theme-org-block bg-dim)
-                        :foreground ,fg-special-cold :slant 
,modus-theme-slant)))
-   `(org-scheduled ((,class :foreground ,fg-special-warm)))
-   `(org-scheduled-previously ((,class :foreground ,yellow-alt-other)))
-   `(org-scheduled-today ((,class :foreground ,magenta-alt-other)))
-   `(org-sexp-date ((,class :inherit org-date)))
-   `(org-special-keyword ((,class ,@(modus-vivendi-theme-mixed-fonts)
-                                  :foreground ,blue-nuanced)))
-   `(org-table ((,class ,@(modus-vivendi-theme-mixed-fonts)
-                        :foreground ,fg-special-cold)))
-   `(org-table-header ((,class :inherit (fixed-pitch 
modus-theme-intense-neutral))))
-   `(org-tag ((,class :foreground ,magenta-nuanced)))
-   `(org-tag-group ((,class :inherit bold :foreground ,cyan-nuanced)))
-   `(org-target ((,class :underline t)))
-   `(org-time-grid ((,class :foreground ,fg-unfocused)))
-   `(org-todo ((,class :box ,bg-region :background ,bg-dim :foreground 
,red-alt)))
-   `(org-upcoming-deadline ((,class :foreground ,red-alt-other)))
-   `(org-upcoming-distant-deadline ((,class :foreground ,red-nuanced)))
-   `(org-verbatim ((,class ,@(modus-vivendi-theme-mixed-fonts)
-                           :background ,bg-alt :foreground ,fg-special-calm)))
-   `(org-verse ((,class :inherit org-quote)))
-   `(org-warning ((,class :inherit bold :foreground ,red-alt-other)))
-;;;;; org-journal
-   `(org-journal-calendar-entry-face ((,class :foreground ,yellow-alt-other 
:slant ,modus-theme-slant)))
-   `(org-journal-calendar-scheduled-face ((,class :foreground ,red-alt-other 
:slant ,modus-theme-slant)))
-   `(org-journal-highlight ((,class :foreground ,magenta-alt)))
-;;;;; org-noter
-   `(org-noter-no-notes-exist-face ((,class :inherit bold :foreground 
,red-active)))
-   `(org-noter-notes-exist-face ((,class :inherit bold :foreground 
,green-active)))
-;;;;; org-pomodoro
-   `(org-pomodoro-mode-line ((,class :foreground ,red-active)))
-   `(org-pomodoro-mode-line-break ((,class :foreground ,cyan-active)))
-   `(org-pomodoro-mode-line-overtime ((,class :inherit bold :foreground 
,red-active)))
-;;;;; org-recur
-   `(org-recur ((,class :foreground ,magenta-active)))
-;;;;; org-roam
-   `(org-roam-link ((,class :inherit button :foreground ,green)))
-   `(org-roam-link-current ((,class :inherit button :foreground ,green-alt)))
-   `(org-roam-link-invalid ((,class :inherit button :foreground ,red)))
-   `(org-roam-link-shielded ((,class :inherit button :foreground ,yellow)))
-   `(org-roam-tag ((,class :foreground ,fg-alt :slant italic)))
-;;;;; org-superstar
-   `(org-superstar-item ((,class :foreground ,fg-main)))
-   `(org-superstar-leading ((,class :foreground ,fg-whitespace)))
-;;;;; org-table-sticky-header
-   `(org-table-sticky-header-face ((,class :inherit 
modus-theme-intense-neutral)))
-;;;;; org-treescope
-   `(org-treescope-faces--markerinternal-midday ((,class :inherit 
modus-theme-intense-blue)))
-   `(org-treescope-faces--markerinternal-range ((,class :inherit 
modus-theme-special-mild)))
-;;;;; origami
-   `(origami-fold-header-face ((,class :background ,bg-dim :foreground ,fg-dim 
:box t)))
-   `(origami-fold-replacement-face ((,class :background ,bg-alt :foreground 
,fg-alt)))
-;;;;; outline-mode
-   `(outline-1 ((,class :inherit modus-theme-heading-1)))
-   `(outline-2 ((,class :inherit modus-theme-heading-2)))
-   `(outline-3 ((,class :inherit modus-theme-heading-3)))
-   `(outline-4 ((,class :inherit modus-theme-heading-4)))
-   `(outline-5 ((,class :inherit modus-theme-heading-5)))
-   `(outline-6 ((,class :inherit modus-theme-heading-6)))
-   `(outline-7 ((,class :inherit modus-theme-heading-7)))
-   `(outline-8 ((,class :inherit modus-theme-heading-8)))
-;;;;; outline-minor-faces
-   `(outline-minor-0 ((,class nil)))
-;;;;; package (M-x list-packages)
-   `(package-description ((,class :foreground ,fg-special-cold)))
-   `(package-help-section-name ((,class :inherit bold :foreground 
,magenta-alt-other)))
-   `(package-name ((,class :inherit link)))
-   `(package-status-avail-obso ((,class :inherit bold :foreground ,red)))
-   `(package-status-available ((,class :foreground ,fg-special-mild)))
-   `(package-status-built-in ((,class :foreground ,magenta)))
-   `(package-status-dependency ((,class :foreground ,magenta-alt-other)))
-   `(package-status-disabled ((,class :inherit modus-theme-subtle-red)))
-   `(package-status-external ((,class :foreground ,cyan-alt-other)))
-   `(package-status-held ((,class :foreground ,yellow-alt)))
-   `(package-status-incompat ((,class :inherit bold :foreground ,yellow)))
-   `(package-status-installed ((,class :foreground ,fg-special-warm)))
-   `(package-status-new ((,class :inherit bold :foreground ,green)))
-   `(package-status-unsigned ((,class :inherit bold :foreground ,red-alt)))
-;;;;; page-break-lines
-   `(page-break-lines ((,class :inherit default :foreground 
,fg-window-divider-outer)))
-;;;;; paradox
-   `(paradox-archive-face ((,class :foreground ,fg-special-mild)))
-   `(paradox-comment-face ((,class :foreground ,fg-alt :slant 
,modus-theme-slant)))
-   `(paradox-commit-tag-face ((,class :inherit modus-theme-refine-magenta :box 
t)))
-   `(paradox-description-face ((,class :foreground ,fg-special-cold)))
-   `(paradox-description-face-multiline ((,class :foreground 
,fg-special-cold)))
-   `(paradox-download-face ((,class ,@(modus-vivendi-theme-bold-weight) 
:foreground ,blue-alt-other)))
-   `(paradox-highlight-face ((,class ,@(modus-vivendi-theme-bold-weight) 
:foreground ,cyan-alt-other)))
-   `(paradox-homepage-button-face ((,class :foreground ,magenta-alt-other 
:underline t)))
-   `(paradox-mode-line-face ((,class :inherit bold :foreground ,cyan-active)))
-   `(paradox-name-face ((,class :foreground ,blue :underline t)))
-   `(paradox-star-face ((,class :foreground ,magenta)))
-   `(paradox-starred-face ((,class :foreground ,magenta-alt)))
-;;;;; paren-face
-   `(parenthesis ((,class :foreground ,fg-unfocused)))
-;;;;; parrot
-   `(parrot-rotate-rotation-highlight-face ((,class :inherit 
modus-theme-refine-magenta)))
-;;;;; pass
-   `(pass-mode-directory-face ((,class :inherit bold :foreground 
,fg-special-cold)))
-   `(pass-mode-entry-face ((,class :background ,bg-main :foreground ,fg-main)))
-   `(pass-mode-header-face ((,class :foreground ,fg-special-warm)))
-;;;;; persp-mode
-   `(persp-face-lighter-buffer-not-in-persp ((,class :inherit 
modus-theme-intense-red)))
-   `(persp-face-lighter-default ((,class :inherit bold :foreground 
,blue-active)))
-   `(persp-face-lighter-nil-persp ((,class :inherit bold :foreground 
,fg-active)))
-;;;;; perspective
-   `(persp-selected-face ((,class :inherit bold :foreground ,blue-active)))
-;;;;; phi-grep
-   `(phi-grep-heading-face  ((,class :inherit bold :foreground ,red-alt
-                                     ,@(modus-vivendi-theme-scale 
modus-vivendi-theme-scale-4))))
-   `(phi-grep-line-number-face ((,class :foreground ,fg-special-warm)))
-   `(phi-grep-match-face ((,class :inherit modus-theme-special-calm)))
-   `(phi-grep-modified-face ((,class :inherit modus-theme-refine-yellow)))
-   `(phi-grep-overlay-face ((,class :inherit modus-theme-refine-blue)))
-;;;;; phi-search
-   `(phi-replace-preview-face ((,class :inherit modus-theme-intense-magenta)))
-   `(phi-search-failpart-face ((,class :inherit modus-theme-refine-red)))
-   `(phi-search-match-face ((,class :inherit modus-theme-refine-cyan)))
-   `(phi-search-selection-face ((,class :inherit (modus-theme-intense-green 
bold))))
-;;;;; pkgbuild-mode
-   `(pkgbuild-error-face ((,class :underline ,fg-lang-error)))
-;;;;; pomidor
-   `(pomidor-break-face ((,class :foreground ,blue-alt-other)))
-   `(pomidor-overwork-face ((,class :foreground ,red-alt-other)))
-   `(pomidor-skip-face ((,class :foreground ,fg-alt :slant 
,modus-theme-slant)))
-   `(pomidor-work-face ((,class :foreground ,green-alt-other)))
-;;;;; powerline
-   `(powerline-active0 ((,class :background ,bg-main :foreground ,blue-faint 
:inverse-video t)))
-   `(powerline-active1 ((,class :background ,blue-nuanced-bg :foreground 
,blue-nuanced)))
-   `(powerline-active2 ((,class :background ,bg-active :foreground 
,fg-active)))
-   `(powerline-inactive0 ((,class :background ,bg-special-cold :foreground 
,fg-special-cold)))
-   `(powerline-inactive1 ((,class :background ,bg-dim :foreground 
,fg-inactive)))
-   `(powerline-inactive2 ((,class :background ,bg-inactive :foreground 
,fg-inactive)))
-;;;;; powerline-evil
-   `(powerline-evil-base-face ((,class :background ,fg-main :foreground 
,bg-main)))
-   `(powerline-evil-emacs-face ((,class :inherit modus-theme-active-magenta)))
-   `(powerline-evil-insert-face ((,class :inherit modus-theme-active-green)))
-   `(powerline-evil-motion-face ((,class :inherit modus-theme-active-blue)))
-   `(powerline-evil-normal-face ((,class :background ,fg-alt :foreground 
,bg-main)))
-   `(powerline-evil-operator-face ((,class :inherit 
modus-theme-active-yellow)))
-   `(powerline-evil-replace-face ((,class :inherit modus-theme-active-red)))
-   `(powerline-evil-visual-face ((,class :inherit modus-theme-active-cyan)))
-;;;;; proced
-   `(proced-mark ((,class :inherit modus-theme-mark-symbol)))
-   `(proced-marked ((,class :inherit modus-theme-mark-alt)))
-   `(proced-sort-header ((,class :inherit bold :foreground ,fg-special-calm 
:underline t)))
-;;;;; prodigy
-   `(prodigy-green-face ((,class :foreground ,green)))
-   `(prodigy-red-face ((,class :foreground ,red)))
-   `(prodigy-yellow-face ((,class :foreground ,yellow)))
-;;;;; racket-mode
-   `(racket-debug-break-face ((,class :inherit modus-theme-intense-red)))
-   `(racket-debug-locals-face ((,class :box (:line-width -1 :color nil)
-                                       :foreground ,green-alt-other)))
-   `(racket-debug-result-face ((,class :inherit bold :box (:line-width -1 
:color nil)
-                                       :foreground ,green)))
-   `(racket-here-string-face ((,class :foreground ,blue-alt)))
-   `(racket-keyword-argument-face ((,class :foreground ,red-alt)))
-   `(racket-logger-config-face ((,class :foreground ,fg-alt :slant 
,modus-theme-slant)))
-   `(racket-logger-debug-face ((,class :foreground ,blue-alt-other)))
-   `(racket-logger-info-face ((,class :foreground ,fg-lang-note)))
-   `(racket-logger-topic-face ((,class :foreground ,magenta :slant 
,modus-theme-slant)))
-   `(racket-selfeval-face ((,class :foreground ,green-alt)))
-   `(racket-xp-error-face
-     ((,(append '((supports :underline (:style wave))) class)
-       :underline (:color ,fg-lang-error :style wave))
-      (,class :foreground ,fg-lang-error :underline t)))
-;;;;; rainbow-blocks
-   `(rainbow-blocks-depth-1-face ((,class :foreground ,magenta-alt-other)))
-   `(rainbow-blocks-depth-2-face ((,class :foreground ,blue)))
-   `(rainbow-blocks-depth-3-face ((,class :foreground ,magenta-alt)))
-   `(rainbow-blocks-depth-4-face ((,class :foreground ,green)))
-   `(rainbow-blocks-depth-5-face ((,class :foreground ,magenta)))
-   `(rainbow-blocks-depth-6-face ((,class :foreground ,cyan)))
-   `(rainbow-blocks-depth-7-face ((,class :foreground ,yellow)))
-   `(rainbow-blocks-depth-8-face ((,class :foreground ,cyan-alt)))
-   `(rainbow-blocks-depth-9-face ((,class :foreground ,red-alt)))
-   `(rainbow-blocks-unmatched-face ((,class :foreground ,red)))
-;;;;; rainbow-identifiers
-   `(rainbow-identifiers-identifier-1 ((,class :foreground ,green-alt-other)))
-   `(rainbow-identifiers-identifier-2 ((,class :foreground 
,magenta-alt-other)))
-   `(rainbow-identifiers-identifier-3 ((,class :foreground ,cyan-alt-other)))
-   `(rainbow-identifiers-identifier-4 ((,class :foreground ,yellow-alt-other)))
-   `(rainbow-identifiers-identifier-5 ((,class :foreground ,blue-alt-other)))
-   `(rainbow-identifiers-identifier-6 ((,class :foreground ,green-alt)))
-   `(rainbow-identifiers-identifier-7 ((,class :foreground ,magenta-alt)))
-   `(rainbow-identifiers-identifier-8 ((,class :foreground ,cyan-alt)))
-   `(rainbow-identifiers-identifier-9 ((,class :foreground ,yellow-alt)))
-   `(rainbow-identifiers-identifier-10 ((,class :foreground ,green)))
-   `(rainbow-identifiers-identifier-11 ((,class :foreground ,magenta)))
-   `(rainbow-identifiers-identifier-12 ((,class :foreground ,cyan)))
-   `(rainbow-identifiers-identifier-13 ((,class :foreground ,yellow)))
-   `(rainbow-identifiers-identifier-14 ((,class :foreground ,blue-alt)))
-   `(rainbow-identifiers-identifier-15 ((,class :foreground ,red-alt)))
-;;;;; rainbow-delimiters
-   `(rainbow-delimiters-base-face-error ((,class :foreground ,red)))
-   `(rainbow-delimiters-base-face ((,class :foreground ,fg-main)))
-   `(rainbow-delimiters-depth-1-face ((,class :foreground ,green-alt-other)))
-   `(rainbow-delimiters-depth-2-face ((,class :foreground ,magenta-alt-other)))
-   `(rainbow-delimiters-depth-3-face ((,class :foreground ,cyan-alt-other)))
-   `(rainbow-delimiters-depth-4-face ((,class :foreground ,yellow-alt-other)))
-   `(rainbow-delimiters-depth-5-face ((,class :foreground ,blue-alt-other)))
-   `(rainbow-delimiters-depth-6-face ((,class :foreground ,green-alt)))
-   `(rainbow-delimiters-depth-7-face ((,class :foreground ,magenta-alt)))
-   `(rainbow-delimiters-depth-8-face ((,class :foreground ,cyan-alt)))
-   `(rainbow-delimiters-depth-9-face ((,class :foreground ,yellow-alt)))
-   `(rainbow-delimiters-mismatched-face ((,class :inherit bold :foreground 
,red-alt)))
-   `(rainbow-delimiters-unmatched-face ((,class :inherit bold :foreground 
,red)))
-;;;;; rcirc
-   `(rcirc-bright-nick ((,class :inherit bold :foreground ,magenta-alt)))
-   `(rcirc-dim-nick ((,class :foreground ,fg-alt)))
-   `(rcirc-my-nick ((,class :inherit bold :foreground ,magenta)))
-   `(rcirc-nick-in-message ((,class :foreground ,magenta-alt-other)))
-   `(rcirc-nick-in-message-full-line ((,class :inherit bold :foreground 
,fg-special-mild)))
-   `(rcirc-other-nick ((,class :inherit bold :foreground ,fg-special-cold)))
-   `(rcirc-prompt ((,class :inherit bold :foreground ,cyan-alt-other)))
-   `(rcirc-server ((,class :foreground ,fg-unfocused)))
-   `(rcirc-timestamp ((,class :foreground ,blue-nuanced)))
-   `(rcirc-url ((,class :foreground ,blue :underline t)))
-;;;;; regexp-builder (re-builder)
-   `(reb-match-0 ((,class :inherit modus-theme-intense-blue)))
-   `(reb-match-1 ((,class :inherit modus-theme-intense-magenta)))
-   `(reb-match-2 ((,class :inherit modus-theme-intense-green)))
-   `(reb-match-3 ((,class :inherit modus-theme-intense-red)))
-   `(reb-regexp-grouping-backslash ((,class :inherit bold :foreground 
,fg-escape-char-backslash)))
-   `(reb-regexp-grouping-construct ((,class :inherit bold :foreground 
,fg-escape-char-construct)))
-;;;;; rg (rg.el)
-   `(rg-column-number-face ((,class :foreground ,magenta-alt-other)))
-   `(rg-context-face ((,class :foreground ,fg-unfocused)))
-   `(rg-error-face ((,class :inherit bold :foreground ,red)))
-   `(rg-file-tag-face ((,class :foreground ,fg-special-cold)))
-   `(rg-filename-face ((,class :inherit bold :foreground ,fg-special-cold)))
-   `(rg-line-number-face ((,class :foreground ,fg-special-warm)))
-   `(rg-literal-face ((,class :foreground ,blue-alt)))
-   `(rg-match-face ((,class :inherit modus-theme-special-calm)))
-   `(rg-regexp-face ((,class :foreground ,magenta-active)))
-   `(rg-toggle-off-face ((,class :inherit bold :foreground ,fg-inactive)))
-   `(rg-toggle-on-face ((,class :inherit bold :foreground ,cyan-active)))
-   `(rg-warning-face ((,class :inherit bold :foreground ,yellow)))
-;;;;; ripgrep
-   `(ripgrep-context-face ((,class :foreground ,fg-unfocused)))
-   `(ripgrep-error-face ((,class :inherit bold :foreground ,red)))
-   `(ripgrep-hit-face ((,class :foreground ,cyan)))
-   `(ripgrep-match-face ((,class :inherit modus-theme-special-calm)))
-;;;;; rmail
-   `(rmail-header-name ((,class :foreground ,cyan-alt-other)))
-   `(rmail-highlight ((,class :inherit bold :foreground ,magenta-alt)))
-;;;;; ruler-mode
-   `(ruler-mode-column-number ((,class :inherit (ruler-mode-default bold) 
:foreground ,fg-main)))
-   `(ruler-mode-comment-column ((,class :inherit ruler-mode-default 
:foreground ,red-active)))
-   `(ruler-mode-current-column ((,class :inherit ruler-mode-default 
:foreground ,cyan-active :box t)))
-   `(ruler-mode-default ((,class :background ,bg-inactive :foreground 
,fg-inactive)))
-   `(ruler-mode-fill-column ((,class :inherit ruler-mode-default :foreground 
,green-active)))
-   `(ruler-mode-fringes ((,class :inherit ruler-mode-default :foreground 
,blue-active)))
-   `(ruler-mode-goal-column ((,class :inherit ruler-mode-default :foreground 
,magenta-active)))
-   `(ruler-mode-margins ((,class :inherit ruler-mode-default :foreground 
,bg-main)))
-   `(ruler-mode-pad ((,class :background ,bg-active :foreground ,fg-inactive)))
-   `(ruler-mode-tab-stop ((,class :inherit ruler-mode-default :foreground 
,yellow-active)))
-;;;;; sallet
-   `(sallet-buffer-compressed ((,class :foreground ,yellow-nuanced :slant 
italic)))
-   `(sallet-buffer-default-directory ((,class :foreground ,cyan-nuanced)))
-   `(sallet-buffer-directory ((,class :foreground ,blue-nuanced)))
-   `(sallet-buffer-help ((,class :foreground ,fg-special-cold)))
-   `(sallet-buffer-modified ((,class :foreground ,yellow-alt-other :slant 
italic)))
-   `(sallet-buffer-ordinary ((,class :foreground ,fg-main)))
-   `(sallet-buffer-read-only ((,class :foreground ,yellow-alt)))
-   `(sallet-buffer-size ((,class :foreground ,fg-special-calm)))
-   `(sallet-buffer-special ((,class :foreground ,magenta-alt-other)))
-   `(sallet-flx-match ((,class ,@(modus-vivendi-theme-extra-completions
-                                  'modus-theme-subtle-cyan
-                                  'modus-theme-refine-cyan
-                                  'modus-theme-nuanced-cyan
-                                  cyan-alt-other))))
-   `(sallet-recentf-buffer-name ((,class :foreground ,blue-nuanced)))
-   `(sallet-recentf-file-path ((,class :foreground ,fg-special-mild)))
-   `(sallet-regexp-match ((,class ,@(modus-vivendi-theme-extra-completions
-                                     'modus-theme-subtle-magenta
-                                     'modus-theme-refine-magenta
-                                     'modus-theme-nuanced-magenta
-                                     magenta-alt-other))))
-   `(sallet-source-header ((,class :inherit bold :foreground ,red-alt
-                                   ,@(modus-vivendi-theme-scale 
modus-vivendi-theme-scale-4))))
-   `(sallet-substring-match ((,class ,@(modus-vivendi-theme-extra-completions
-                                        'modus-theme-subtle-blue
-                                        'modus-theme-refine-blue
-                                        'modus-theme-nuanced-blue
-                                        blue-alt-other))))
-;;;;; selectrum
-   `(selectrum-current-candidate
-     ((,class :inherit bold :foreground ,fg-main :underline ,fg-main
-              :background ,@(pcase modus-vivendi-theme-completions
-                              ('opinionated (list bg-active))
-                              (_ (list bg-inactive))))))
-   `(selectrum-primary-highlight ((,class :inherit bold
-                                          
,@(modus-vivendi-theme-standard-completions
-                                             magenta-alt magenta-nuanced-bg
-                                             magenta-refine-bg 
magenta-refine-fg))))
-   `(selectrum-secondary-highlight ((,class :inherit bold
-                                            
,@(modus-vivendi-theme-standard-completions
-                                               cyan-alt-other cyan-nuanced-bg
-                                               cyan-refine-bg 
cyan-refine-fg))))
-;;;;; semantic
-   `(semantic-complete-inline-face ((,class :foreground ,fg-special-warm 
:underline t)))
-   `(semantic-decoration-on-private-members-face ((,class :inherit 
modus-theme-refine-cyan)))
-   `(semantic-decoration-on-protected-members-face ((,class :background 
,bg-dim)))
-   `(semantic-highlight-edits-face ((,class :background ,bg-alt)))
-   `(semantic-highlight-func-current-tag-face ((,class :background ,bg-alt)))
-   `(semantic-idle-symbol-highlight ((,class :inherit 
modus-theme-special-mild)))
-   `(semantic-tag-boundary-face ((,class :overline ,blue-intense)))
-   `(semantic-unmatched-syntax-face ((,class :underline ,fg-lang-error)))
-;;;;; sesman
-   `(sesman-browser-button-face ((,class :foreground ,blue-alt-other 
:underline t)))
-   `(sesman-browser-highligh-face ((,class :inherit modus-theme-subtle-blue)))
-   `(sesman-buffer-face ((,class :foreground ,magenta)))
-   `(sesman-directory-face ((,class :inherit bold :foreground ,blue)))
-   `(sesman-project-face ((,class :inherit bold :foreground 
,magenta-alt-other)))
-;;;;; shell-script-mode
-   `(sh-heredoc ((,class :foreground ,blue-alt)))
-   `(sh-quoted-exec ((,class ,@(modus-vivendi-theme-bold-weight) :foreground 
,magenta-alt)))
-;;;;; show-paren-mode
-   `(show-paren-match ((,class ,@(modus-vivendi-theme-paren bg-paren-match
-                                                            
bg-paren-match-intense)
-                               :foreground ,fg-main)))
-   `(show-paren-match-expression ((,class :inherit modus-theme-special-calm)))
-   `(show-paren-mismatch ((,class :inherit modus-theme-intense-red)))
-;;;;; side-notes
-   `(side-notes ((,class :background ,bg-dim :foreground ,fg-dim)))
-;;;;; skewer-mode
-   `(skewer-error-face ((,class :foreground ,red :underline t)))
-;;;;; smart-mode-line
-   `(sml/charging ((,class :foreground ,green-active)))
-   `(sml/discharging ((,class :foreground ,red-active)))
-   `(sml/filename ((,class :inherit bold :foreground ,blue-active)))
-   `(sml/folder ((,class :foreground ,fg-active)))
-   `(sml/git ((,class :inherit bold :foreground ,green-active)))
-   `(sml/global ((,class :foreground ,fg-active)))
-   `(sml/line-number ((,class :inherit sml/global)))
-   `(sml/minor-modes ((,class :inherit sml/global)))
-   `(sml/modes ((,class :inherit bold :foreground ,fg-active)))
-   `(sml/modified ((,class :inherit bold :foreground ,magenta-active)))
-   `(sml/mule-info ((,class :inherit sml/global)))
-   `(sml/name-filling ((,class :foreground ,yellow-active)))
-   `(sml/not-modified ((,class :inherit sml/global)))
-   `(sml/numbers-separator ((,class :inherit sml/global)))
-   `(sml/outside-modified ((,class :inherit modus-theme-intense-red)))
-   `(sml/position-percentage ((,class :inherit sml/global)))
-   `(sml/prefix ((,class :foreground ,green-active)))
-   `(sml/process ((,class :inherit sml/prefix)))
-   `(sml/projectile ((,class :inherit sml/git)))
-   `(sml/read-only ((,class :inherit bold :foreground ,cyan-active)))
-   `(sml/remote ((,class :inherit sml/global)))
-   `(sml/sudo ((,class :inherit modus-theme-subtle-red)))
-   `(sml/time ((,class :inherit sml/global)))
-   `(sml/vc ((,class :inherit sml/git)))
-   `(sml/vc-edited ((,class :inherit bold :foreground ,yellow-active)))
-;;;;; smartparens
-   `(sp-pair-overlay-face ((,class :inherit modus-theme-special-warm)))
-   `(sp-show-pair-enclosing ((,class :inherit modus-theme-special-mild)))
-   `(sp-show-pair-match-face ((,class ,@(modus-vivendi-theme-paren 
bg-paren-match
-                                                                   
bg-paren-match-intense)
-                                      :foreground ,fg-main)))
-   `(sp-show-pair-mismatch-face ((,class :inherit modus-theme-intense-red)))
-   `(sp-wrap-overlay-closing-pair ((,class :inherit sp-pair-overlay-face)))
-   `(sp-wrap-overlay-face ((,class :inherit sp-pair-overlay-face)))
-   `(sp-wrap-overlay-opening-pair ((,class :inherit sp-pair-overlay-face)))
-   `(sp-wrap-tag-overlay-face ((,class :inherit sp-pair-overlay-face)))
-;;;;; smerge
-   `(smerge-base ((,class :inherit modus-theme-diff-changed)))
-   `(smerge-lower ((,class :inherit modus-theme-diff-added)))
-   `(smerge-markers ((,class :background ,bg-diff-neutral-2 :foreground 
,fg-diff-neutral-2)))
-   `(smerge-refined-added ((,class :inherit modus-theme-diff-refine-added)))
-   `(smerge-refined-changed ((,class)))
-   `(smerge-refined-removed ((,class :inherit 
modus-theme-diff-refine-removed)))
-   `(smerge-upper ((,class :inherit modus-theme-diff-removed)))
-;;;;; spaceline
-   `(spaceline-evil-emacs ((,class :inherit modus-theme-active-magenta)))
-   `(spaceline-evil-insert ((,class :inherit modus-theme-active-green)))
-   `(spaceline-evil-motion ((,class :inherit modus-theme-active-blue)))
-   `(spaceline-evil-normal ((,class :background ,fg-alt :foreground ,bg-alt)))
-   `(spaceline-evil-replace ((,class :inherit modus-theme-active-red)))
-   `(spaceline-evil-visual ((,class :inherit modus-theme-active-cyan)))
-   `(spaceline-flycheck-error ((,class :foreground ,red-active)))
-   `(spaceline-flycheck-info ((,class :foreground ,cyan-active)))
-   `(spaceline-flycheck-warning ((,class :foreground ,yellow-active)))
-   `(spaceline-highlight-face ((,class :inherit modus-theme-fringe-blue)))
-   `(spaceline-modified ((,class :inherit modus-theme-fringe-magenta)))
-   `(spaceline-python-venv ((,class :foreground ,magenta-active)))
-   `(spaceline-read-only ((,class :inherit modus-theme-fringe-red)))
-   `(spaceline-unmodified ((,class :inherit modus-theme-fringe-cyan)))
-;;;;; speedbar
-   `(speedbar-button-face ((,class :inherit link)))
-   `(speedbar-directory-face ((,class :inherit bold :foreground ,blue)))
-   `(speedbar-file-face ((,class :foreground ,fg-main)))
-   `(speedbar-highlight-face ((,class :inherit modus-theme-subtle-blue)))
-   `(speedbar-selected-face ((,class :inherit bold :foreground ,cyan)))
-   `(speedbar-separator-face ((,class :inherit modus-theme-intense-neutral)))
-   `(speedbar-tag-face ((,class :foreground ,yellow-alt-other)))
-;;;;; spell-fu
-   `(spell-fu-incorrect-face
-     ((,(append '((supports :underline (:style wave))) class)
-       :foreground ,fg-lang-error :underline (:style wave))
-      (,class :foreground ,fg-lang-error :underline t)))
-;;;;; stripes
-   `(stripes ((,class :inherit modus-theme-hl-line)))
-;;;;; success
-   `(suggest-heading ((,class :inherit bold :foreground ,yellow-alt-other)))
-;;;;; switch-window
-   `(switch-window-background ((,class :background ,bg-dim)))
-   `(switch-window-label ((,class :height 3.0 :foreground ,blue-intense)))
-;;;;; swiper
-   `(swiper-background-match-face-1 ((,class :inherit 
modus-theme-subtle-neutral)))
-   `(swiper-background-match-face-2 ((,class :inherit 
modus-theme-subtle-cyan)))
-   `(swiper-background-match-face-3 ((,class :inherit 
modus-theme-subtle-magenta)))
-   `(swiper-background-match-face-4 ((,class :inherit 
modus-theme-subtle-green)))
-   `(swiper-line-face ((,class ,@(and (>= emacs-major-version 27) '(:extend t))
-                               :inherit modus-theme-special-cold)))
-   `(swiper-match-face-1 ((,class :inherit swiper-line-face)))
-   `(swiper-match-face-2 ((,class :inherit swiper-line-face)))
-   `(swiper-match-face-3 ((,class :inherit swiper-line-face)))
-   `(swiper-match-face-4 ((,class :inherit swiper-line-face)))
-;;;;; swoop
-   `(swoop-face-header-format-line ((,class :inherit bold :foreground ,red-alt
-                                            ,@(modus-vivendi-theme-scale 
modus-vivendi-theme-scale-3))))
-   `(swoop-face-line-buffer-name ((,class :inherit bold :foreground ,blue-alt
-                                          ,@(modus-vivendi-theme-scale 
modus-vivendi-theme-scale-4))))
-   `(swoop-face-line-number ((,class :foreground ,fg-special-warm)))
-   `(swoop-face-target-line ((,class :inherit modus-theme-intense-blue
-                                     ,@(and (>= emacs-major-version 27) 
'(:extend t)))))
-   `(swoop-face-target-words ((,class :inherit modus-theme-refine-cyan)))
-;;;;; sx
-   `(sx-inbox-item-type ((,class :foreground ,magenta-alt-other)))
-   `(sx-inbox-item-type-unread ((,class :inherit (sx-inbox-item-type bold))))
-   `(sx-question-list-answers ((,class :foreground ,green)))
-   `(sx-question-list-answers-accepted ((,class :box t :foreground ,green)))
-   `(sx-question-list-bounty ((,class :inherit bold :background ,bg-alt 
:foreground ,yellow)))
-   `(sx-question-list-date ((,class :foreground ,fg-special-cold)))
-   `(sx-question-list-favorite ((,class :inherit bold :foreground 
,fg-special-warm)))
-   `(sx-question-list-parent ((,class :foreground ,fg-main)))
-   `(sx-question-list-read-question ((,class :foreground ,fg-alt)))
-   `(sx-question-list-score ((,class :foreground ,fg-special-mild)))
-   `(sx-question-list-score-upvoted ((,class :inherit (sx-question-list-score 
bold))))
-   `(sx-question-list-unread-question ((,class :inherit bold :foreground 
,fg-main)))
-   `(sx-question-mode-accepted ((,class :inherit bold :height 1.3 :foreground 
,green)))
-   `(sx-question-mode-closed ((,class :inherit modus-theme-active-yellow :box 
(:line-width 2 :color nil))))
-   `(sx-question-mode-closed-reason ((,class :box (:line-width 2 :color nil) 
:foreground ,fg-main)))
-   `(sx-question-mode-content-face ((,class :background ,bg-dim)))
-   `(sx-question-mode-date ((,class :foreground ,blue)))
-   `(sx-question-mode-header ((,class :inherit bold :foreground ,cyan)))
-   `(sx-question-mode-kbd-tag ((,class :inherit bold :height 0.9 :box 
(:line-width 3 :color ,fg-main :style released-button) :foreground ,fg-main)))
-   `(sx-question-mode-score ((,class :foreground ,fg-dim)))
-   `(sx-question-mode-score-downvoted ((,class :foreground ,yellow)))
-   `(sx-question-mode-score-upvoted ((,class :inherit bold :foreground 
,magenta)))
-   `(sx-question-mode-title ((,class :inherit bold :foreground ,fg-main)))
-   `(sx-question-mode-title-comments ((,class :inherit bold :foreground 
,fg-alt)))
-   `(sx-tag ((,class :foreground ,magenta-alt)))
-   `(sx-user-name ((,class :foreground ,blue-alt)))
-   `(sx-user-reputation ((,class :foreground ,fg-alt)))
-;;;;; symbol-overlay
-   `(symbol-overlay-default-face ((,class :inherit modus-theme-special-warm)))
-   `(symbol-overlay-face-1 ((,class :inherit modus-theme-intense-blue)))
-   `(symbol-overlay-face-2 ((,class :inherit modus-theme-refine-magenta)))
-   `(symbol-overlay-face-3 ((,class :inherit modus-theme-intense-yellow)))
-   `(symbol-overlay-face-4 ((,class :inherit modus-theme-intense-magenta)))
-   `(symbol-overlay-face-5 ((,class :inherit modus-theme-intense-red)))
-   `(symbol-overlay-face-6 ((,class :inherit modus-theme-refine-red)))
-   `(symbol-overlay-face-7 ((,class :inherit modus-theme-intense-cyan)))
-   `(symbol-overlay-face-8 ((,class :inherit modus-theme-refine-cyan)))
-;;;;; syslog-mode
-   `(syslog-debug ((,class :inherit bold :foreground ,cyan-alt-other)))
-   `(syslog-error ((,class :inherit bold :foreground ,red)))
-   `(syslog-file ((,class :inherit bold :foreground ,fg-special-cold)))
-   `(syslog-hide ((,class :background ,bg-main :foreground ,fg-main)))
-   `(syslog-hour ((,class :inherit bold :foreground ,magenta-alt-other)))
-   `(syslog-info ((,class :inherit bold :foreground ,blue-alt-other)))
-   `(syslog-ip ((,class :inherit bold :foreground ,fg-special-mild :underline 
t)))
-   `(syslog-su ((,class :inherit bold :foreground ,red-alt)))
-   `(syslog-warn ((,class :inherit bold :foreground ,yellow)))
-;;;;; table (built-in table.el)
-   `(table-cell ((,class :background ,blue-nuanced-bg)))
-;;;;; telephone-line
-   `(telephone-line-accent-active ((,class :background ,fg-inactive 
:foreground ,bg-inactive)))
-   `(telephone-line-accent-inactive ((,class :background ,bg-active 
:foreground ,fg-active)))
-   `(telephone-line-error ((,class :inherit bold :foreground ,red-active)))
-   `(telephone-line-evil ((,class :foreground ,fg-main)))
-   `(telephone-line-evil-emacs ((,class :inherit telephone-line-evil 
:background ,magenta-intense-bg)))
-   `(telephone-line-evil-insert ((,class :inherit telephone-line-evil 
:background ,green-intense-bg)))
-   `(telephone-line-evil-motion ((,class :inherit telephone-line-evil 
:background ,yellow-intense-bg)))
-   `(telephone-line-evil-normal ((,class :inherit telephone-line-evil 
:background ,bg-alt)))
-   `(telephone-line-evil-operator ((,class :inherit telephone-line-evil 
:background ,yellow-subtle-bg)))
-   `(telephone-line-evil-replace ((,class :inherit telephone-line-evil 
:background ,red-intense-bg)))
-   `(telephone-line-evil-visual ((,class :inherit telephone-line-evil 
:background ,cyan-intense-bg)))
-   `(telephone-line-projectile ((,class :foreground ,cyan-active)))
-   `(telephone-line-unimportant ((,class :foreground ,fg-inactive)))
-   `(telephone-line-warning ((,class :inherit bold :foreground 
,yellow-active)))
-;;;;; term
-   `(term ((,class :background ,bg-main :foreground ,fg-main)))
-   `(term-bold ((,class :inherit bold)))
-   `(term-color-blue ((,class :background ,blue :foreground ,blue)))
-   `(term-color-cyan ((,class :background ,cyan :foreground ,cyan)))
-   `(term-color-green ((,class :background ,green :foreground ,green)))
-   `(term-color-magenta ((,class :background ,magenta :foreground ,magenta)))
-   `(term-color-red ((,class :background ,red :foreground ,red)))
-   `(term-color-yellow ((,class :background ,yellow :foreground ,yellow)))
-   `(term-underline ((,class :underline t)))
-;;;;; tomatinho
-   `(tomatinho-ok-face ((,class :foreground ,blue-intense)))
-   `(tomatinho-pause-face ((,class :foreground ,yellow-intense)))
-   `(tomatinho-reset-face ((,class :foreground ,fg-alt)))
-;;;;; transient
-   `(transient-active-infix ((,class :inherit modus-theme-special-mild)))
-   `(transient-amaranth ((,class :inherit bold :foreground ,yellow)))
-   `(transient-argument ((,class :inherit bold :foreground ,red-alt)))
-   `(transient-blue ((,class :inherit bold :foreground ,blue)))
-   `(transient-disabled-suffix ((,class :inherit modus-theme-intense-red)))
-   `(transient-enabled-suffix ((,class :inherit modus-theme-intense-green)))
-   `(transient-heading ((,class :inherit bold :foreground ,fg-main)))
-   `(transient-inactive-argument ((,class :foreground ,fg-alt)))
-   `(transient-inactive-value ((,class :foreground ,fg-alt)))
-   `(transient-key ((,class :inherit bold :foreground ,blue)))
-   `(transient-mismatched-key ((,class :underline t)))
-   `(transient-nonstandard-key ((,class :underline t)))
-   `(transient-pink ((,class :inherit bold :foreground ,magenta)))
-   `(transient-red ((,class :inherit bold :foreground ,red-intense)))
-   `(transient-teal ((,class :inherit bold :foreground ,cyan-alt-other)))
-   `(transient-unreachable ((,class :foreground ,fg-unfocused)))
-   `(transient-unreachable-key ((,class :foreground ,fg-unfocused)))
-   `(transient-value ((,class :foreground ,magenta-alt)))
-;;;;; trashed
-   `(trashed-deleted ((,class :inherit modus-theme-mark-del)))
-   `(trashed-directory ((,class :foreground ,blue)))
-   `(trashed-mark ((,class :inherit modus-theme-mark-symbol)))
-   `(trashed-marked ((,class :inherit modus-theme-mark-alt)))
-   `(trashed-restored ((,class :inherit modus-theme-mark-sel)))
-   `(trashed-symlink ((,class :inherit button :foreground ,cyan-alt)))
-;;;;; treemacs
-   `(treemacs-directory-collapsed-face ((,class :foreground ,magenta-alt)))
-   `(treemacs-directory-face ((,class :inherit dired-directory)))
-   `(treemacs-file-face ((,class :foreground ,fg-main)))
-   `(treemacs-fringe-indicator-face ((,class :foreground ,fg-main)))
-   `(treemacs-git-added-face ((,class :foreground ,green-intense)))
-   `(treemacs-git-conflict-face ((,class :inherit (modus-theme-intense-red 
bold))))
-   `(treemacs-git-ignored-face ((,class :foreground ,fg-alt)))
-   `(treemacs-git-modified-face ((,class :foreground ,yellow-alt-other)))
-   `(treemacs-git-renamed-face ((,class :foreground ,cyan-alt-other)))
-   `(treemacs-git-unmodified-face ((,class :foreground ,fg-main)))
-   `(treemacs-git-untracked-face ((,class :foreground ,red-alt-other)))
-   `(treemacs-help-column-face ((,class ,@(modus-vivendi-theme-bold-weight) 
:foreground ,magenta-alt-other :underline t)))
-   `(treemacs-help-title-face ((,class :foreground ,blue-alt-other)))
-   `(treemacs-on-failure-pulse-face ((,class :inherit 
modus-theme-intense-red)))
-   `(treemacs-on-success-pulse-face ((,class :inherit 
modus-theme-intense-green)))
-   `(treemacs-root-face ((,class :inherit bold :foreground ,blue-alt-other 
:height 1.2 :underline t)))
-   `(treemacs-root-remote-disconnected-face ((,class :inherit 
treemacs-root-remote-face :foreground ,yellow)))
-   `(treemacs-root-remote-face ((,class :inherit treemacs-root-face 
:foreground ,magenta)))
-   `(treemacs-root-remote-unreadable-face ((,class :inherit 
treemacs-root-unreadable-face)))
-   `(treemacs-root-unreadable-face ((,class :inherit treemacs-root-face 
:strike-through t)))
-   `(treemacs-tags-face ((,class :foreground ,blue-alt)))
-   `(treemacs-tags-face ((,class :foreground ,magenta-alt)))
-;;;;; tty-menu
-   `(tty-menu-disabled-face ((,class :background ,bg-alt :foreground ,fg-alt)))
-   `(tty-menu-enabled-face ((,class :inherit bold :background ,bg-alt 
:foreground ,fg-main)))
-   `(tty-menu-selected-face ((,class :inherit modus-theme-intense-blue)))
-;;;;; tuareg
-   `(caml-types-def-face ((,class :inherit modus-theme-subtle-red)))
-   `(caml-types-expr-face ((,class :inherit modus-theme-subtle-green)))
-   `(caml-types-occ-face ((,class :inherit modus-theme-subtle-green)))
-   `(caml-types-scope-face ((,class :inherit modus-theme-subtle-blue)))
-   `(caml-types-typed-face ((,class :inherit modus-theme-subtle-magenta)))
-   `(tuareg-font-double-semicolon-face ((,class 
,@(modus-vivendi-theme-syntax-foreground
-                                                   red-alt red-alt-faint))))
-   `(tuareg-font-lock-attribute-face ((,class 
,@(modus-vivendi-theme-syntax-foreground
-                                                 magenta magenta-faint))))
-   `(tuareg-font-lock-constructor-face ((,class :foreground ,fg-main)))
-   `(tuareg-font-lock-error-face ((,class :inherit (modus-theme-intense-red 
bold))))
-   `(tuareg-font-lock-extension-node-face ((,class :background ,bg-alt 
:foreground ,magenta)))
-   `(tuareg-font-lock-governing-face ((,class :inherit bold :foreground 
,fg-main)))
-   `(tuareg-font-lock-infix-extension-node-face ((,class 
,@(modus-vivendi-theme-syntax-foreground
-                                                            magenta 
magenta-faint))))
-   `(tuareg-font-lock-interactive-directive-face ((,class :foreground 
,fg-special-cold)))
-   `(tuareg-font-lock-interactive-error-face ((,class :inherit bold
-                                                      
,@(modus-vivendi-theme-syntax-foreground
-                                                         red red-faint))))
-   `(tuareg-font-lock-interactive-output-face ((,class 
,@(modus-vivendi-theme-syntax-foreground
-                                                          blue-alt-other 
blue-alt-other-faint))))
-   `(tuareg-font-lock-label-face ((,class 
,@(modus-vivendi-theme-syntax-foreground
-                                             cyan-alt-other 
cyan-alt-other-faint))))
-   `(tuareg-font-lock-line-number-face ((,class :foreground ,fg-special-warm)))
-   `(tuareg-font-lock-module-face ((,class 
,@(modus-vivendi-theme-syntax-foreground
-                                              magenta-alt magenta-alt-faint))))
-   `(tuareg-font-lock-multistage-face ((,class :inherit bold :background 
,bg-alt
-                                               
,@(modus-vivendi-theme-syntax-foreground
-                                                  blue blue-faint))))
-   `(tuareg-font-lock-operator-face ((,class 
,@(modus-vivendi-theme-syntax-foreground
-                                                red-alt red-alt-faint))))
-   `(tuareg-opam-error-face ((,class :inherit bold
-                                     ,@(modus-vivendi-theme-syntax-foreground
-                                        red red-faint))))
-   `(tuareg-opam-pkg-variable-name-face ((,class 
,@(modus-vivendi-theme-syntax-foreground
-                                                    cyan cyan-faint)
-                                                 :slant ,modus-theme-slant)))
-;;;;; typescript
-   `(typescript-jsdoc-tag ((,class :foreground ,fg-special-mild :slant 
,modus-theme-slant)))
-   `(typescript-jsdoc-type ((,class :foreground ,fg-special-calm :slant 
,modus-theme-slant)))
-   `(typescript-jsdoc-value ((,class :foreground ,fg-special-cold :slant 
,modus-theme-slant)))
-;;;;; undo-tree
-   `(undo-tree-visualizer-active-branch-face ((,class :inherit bold 
:foreground ,fg-main)))
-   `(undo-tree-visualizer-current-face ((,class :foreground ,blue-intense)))
-   `(undo-tree-visualizer-default-face ((,class :foreground ,fg-alt)))
-   `(undo-tree-visualizer-register-face ((,class :foreground 
,magenta-intense)))
-   `(undo-tree-visualizer-unmodified-face ((,class :foreground 
,green-intense)))
-;;;;; vc (vc-hooks.el)
-   `(vc-conflict-state ((,class :foreground ,red-active :slant 
,modus-theme-slant)))
-   `(vc-edited-state ((,class :foreground ,yellow-active)))
-   `(vc-locally-added-state ((,class :foreground ,cyan-active)))
-   `(vc-locked-state ((,class :foreground ,blue-active)))
-   `(vc-missing-state ((,class :foreground ,magenta-active :slant 
,modus-theme-slant)))
-   `(vc-needs-update-state ((,class :foreground ,green-active :slant 
,modus-theme-slant)))
-   `(vc-removed-state ((,class :foreground ,red-active)))
-   `(vc-state-base ((,class :foreground ,fg-active)))
-   `(vc-up-to-date-state ((,class :foreground ,fg-special-cold)))
-;;;;; vdiff
-   `(vdiff-addition-face ((,class :inherit modus-theme-diff-added)))
-   `(vdiff-change-face ((,class :inherit modus-theme-diff-changed)))
-   `(vdiff-closed-fold-face ((,class :background ,bg-diff-neutral-1 
:foreground ,fg-diff-neutral-1)))
-   `(vdiff-refine-added ((,class :inherit modus-theme-diff-refine-added)))
-   `(vdiff-refine-changed ((,class :inherit modus-theme-diff-refine-changed)))
-   `(vdiff-subtraction-face ((,class :inherit modus-theme-diff-removed)))
-   `(vdiff-target-face ((,class :inherit modus-theme-intense-blue)))
-;;;;; vimish-fold
-   `(vimish-fold-fringe ((,class :foreground ,cyan-active)))
-   `(vimish-fold-mouse-face ((,class :inherit modus-theme-intense-blue)))
-   `(vimish-fold-overlay ((,class :background ,bg-alt :foreground 
,fg-special-cold)))
-;;;;; visible-mark
-   `(visible-mark-active ((,class :background ,blue-intense-bg)))
-   `(visible-mark-face1 ((,class :background ,cyan-intense-bg)))
-   `(visible-mark-face2 ((,class :background ,yellow-intense-bg)))
-   `(visible-mark-forward-face1 ((,class :background ,magenta-intense-bg)))
-   `(visible-mark-forward-face2 ((,class :background ,green-intense-bg)))
-;;;;; visual-regexp
-   `(vr/group-0 ((,class :inherit modus-theme-intense-blue)))
-   `(vr/group-1 ((,class :inherit modus-theme-intense-magenta)))
-   `(vr/group-2 ((,class :inherit modus-theme-intense-green)))
-   `(vr/match-0 ((,class :inherit modus-theme-refine-yellow)))
-   `(vr/match-1 ((,class :inherit modus-theme-refine-yellow)))
-   `(vr/match-separator-face ((,class :inherit (modus-theme-intense-neutral 
bold))))
-;;;;; volatile-highlights
-   `(vhl/default-face ((,class ,@(and (>= emacs-major-version 27) '(:extend t))
-                               :background ,bg-alt :foreground ,blue-nuanced)))
-;;;;; vterm
-   `(vterm-color-black ((,class :background "gray35" :foreground "gray35")))
-   `(vterm-color-blue ((,class :background ,blue :foreground ,blue)))
-   `(vterm-color-cyan ((,class :background ,cyan :foreground ,cyan)))
-   `(vterm-color-default ((,class :background ,bg-main :foreground ,fg-main)))
-   `(vterm-color-green ((,class :background ,green :foreground ,green)))
-   `(vterm-color-inverse-video ((,class :background ,bg-main :inverse-video 
t)))
-   `(vterm-color-magenta ((,class :background ,magenta :foreground ,magenta)))
-   `(vterm-color-red ((,class :background ,red :foreground ,red)))
-   `(vterm-color-underline ((,class :foreground ,fg-special-warm :underline 
t)))
-   `(vterm-color-white ((,class :background "gray65" :foreground "gray65")))
-   `(vterm-color-yellow ((,class :background ,yellow :foreground ,yellow)))
-;;;;; wcheck-mode
-   `(wcheck-default-face ((,class :foreground ,red :underline t)))
-;;;;; web-mode
-   `(web-mode-annotation-face ((,class :inherit web-mode-comment-face)))
-   `(web-mode-annotation-html-face ((,class :inherit web-mode-comment-face)))
-   `(web-mode-annotation-tag-face ((,class :inherit web-mode-comment-face 
:underline t)))
-   `(web-mode-block-attr-name-face ((,class 
,@(modus-vivendi-theme-syntax-foreground
-                                               blue blue-faint))))
-   `(web-mode-block-attr-value-face ((,class 
,@(modus-vivendi-theme-syntax-foreground
-                                                cyan-alt-other 
cyan-alt-other-faint))))
-   `(web-mode-block-comment-face ((,class :inherit web-mode-comment-face)))
-   `(web-mode-block-control-face ((,class 
,@(modus-vivendi-theme-syntax-foreground
-                                             magenta-alt magenta-alt-faint)
-                                          
,@(modus-vivendi-theme-bold-weight))))
-   `(web-mode-block-delimiter-face ((,class :foreground ,fg-main)))
-   `(web-mode-block-face ((,class :background ,bg-dim)))
-   `(web-mode-block-string-face ((,class :inherit web-mode-string-face)))
-   `(web-mode-bold-face ((,class :inherit bold)))
-   `(web-mode-builtin-face ((,class ,@(modus-vivendi-theme-syntax-foreground
-                                       magenta-alt magenta-alt-faint)
-                                    ,@(modus-vivendi-theme-bold-weight))))
-   `(web-mode-comment-face ((,class :foreground ,fg-alt :slant 
,modus-theme-slant)))
-   `(web-mode-comment-keyword-face ((,class :inherit bold :background ,bg-dim
-                                            
,@(modus-vivendi-theme-syntax-foreground
-                                               yellow yellow-faint))))
-   `(web-mode-constant-face ((,class ,@(modus-vivendi-theme-syntax-foreground
-                                        blue-alt-other blue-alt-other-faint))))
-   `(web-mode-css-at-rule-face ((,class 
,@(modus-vivendi-theme-syntax-foreground
-                                           blue-alt-other 
blue-alt-other-faint))))
-   `(web-mode-css-color-face ((,class ,@(modus-vivendi-theme-syntax-foreground
-                                         magenta-alt magenta-alt-faint)
-                                      ,@(modus-vivendi-theme-bold-weight))))
-   `(web-mode-css-comment-face ((,class :inherit web-mode-comment-face)))
-   `(web-mode-css-function-face ((,class 
,@(modus-vivendi-theme-syntax-foreground
-                                            magenta-alt magenta-alt-faint)
-                                         ,@(modus-vivendi-theme-bold-weight))))
-   `(web-mode-css-priority-face ((,class 
,@(modus-vivendi-theme-syntax-foreground
-                                            yellow-alt yellow-alt-faint)
-                                         ,@(modus-vivendi-theme-bold-weight))))
-   `(web-mode-css-property-name-face ((,class 
,@(modus-vivendi-theme-syntax-foreground
-                                                 cyan cyan-faint))))
-   `(web-mode-css-pseudo-class-face ((,class 
,@(modus-vivendi-theme-syntax-foreground
-                                                cyan-alt-other 
cyan-alt-other-faint))))
-   `(web-mode-css-selector-face ((,class 
,@(modus-vivendi-theme-syntax-foreground
-                                            magenta-alt-other 
magenta-alt-other-faint)
-                                         ,@(modus-vivendi-theme-bold-weight))))
-   `(web-mode-css-string-face ((,class :inherit web-mode-string-face)))
-   `(web-mode-css-variable-face ((,class :foreground ,fg-special-warm)))
-   `(web-mode-current-column-highlight-face ((,class :background ,bg-alt)))
-   `(web-mode-current-element-highlight-face ((,class :inherit 
modus-theme-special-mild)))
-   `(web-mode-doctype-face ((,class :foreground ,fg-special-cold :slant 
,modus-theme-slant)))
-   `(web-mode-error-face ((,class :inherit modus-theme-intense-red)))
-   `(web-mode-filter-face ((,class ,@(modus-vivendi-theme-syntax-foreground
-                                      magenta magenta-faint))))
-   `(web-mode-folded-face ((,class :underline t)))
-   `(web-mode-function-call-face ((,class 
,@(modus-vivendi-theme-syntax-foreground
-                                             magenta magenta-faint))))
-   `(web-mode-function-name-face ((,class 
,@(modus-vivendi-theme-syntax-foreground
-                                             magenta magenta-faint))))
-   `(web-mode-html-attr-custom-face ((,class 
,@(modus-vivendi-theme-syntax-foreground
-                                                cyan cyan-faint))))
-   `(web-mode-html-attr-engine-face ((,class :foreground ,fg-main)))
-   `(web-mode-html-attr-equal-face ((,class :foreground ,fg-main)))
-   `(web-mode-html-attr-name-face ((,class 
,@(modus-vivendi-theme-syntax-foreground
-                                              cyan cyan-faint))))
-   `(web-mode-html-attr-value-face ((,class 
,@(modus-vivendi-theme-syntax-foreground
-                                               blue-alt-other 
blue-alt-other-faint))))
-   `(web-mode-html-entity-face ((,class 
,@(modus-vivendi-theme-syntax-foreground
-                                           yellow-alt-other 
yellow-alt-other-faint)
-                                        :slant ,modus-theme-slant)))
-   `(web-mode-html-tag-bracket-face ((,class :foreground ,fg-dim)))
-   `(web-mode-html-tag-custom-face ((,class 
,@(modus-vivendi-theme-syntax-foreground
-                                               magenta magenta-faint))))
-   `(web-mode-html-tag-face ((,class ,@(modus-vivendi-theme-syntax-foreground
-                                        magenta magenta-faint))))
-   `(web-mode-html-tag-namespaced-face ((,class 
,@(modus-vivendi-theme-syntax-foreground
-                                                   magenta-alt 
magenta-alt-faint)
-                                                
,@(modus-vivendi-theme-bold-weight))))
-   `(web-mode-html-tag-unclosed-face ((,class 
,@(modus-vivendi-theme-syntax-foreground
-                                                 red red-faint)
-                                              :underline t)))
-   `(web-mode-inlay-face ((,class :background ,bg-alt)))
-   `(web-mode-italic-face ((,class :slant italic)))
-   `(web-mode-javascript-comment-face ((,class :inherit 
web-mode-comment-face)))
-   `(web-mode-javascript-string-face ((,class :inherit web-mode-string-face)))
-   `(web-mode-json-comment-face ((,class :inherit web-mode-comment-face)))
-   `(web-mode-json-context-face ((,class 
,@(modus-vivendi-theme-syntax-foreground
-                                            magenta-alt magenta-alt-faint))))
-   `(web-mode-json-key-face ((,class :foreground ,blue-nuanced)))
-   `(web-mode-json-string-face ((,class :inherit web-mode-string-face)))
-   `(web-mode-jsx-depth-1-face ((,class :background ,blue-intense-bg 
:foreground ,fg-main)))
-   `(web-mode-jsx-depth-2-face ((,class :background ,blue-subtle-bg 
:foreground ,fg-main)))
-   `(web-mode-jsx-depth-3-face ((,class :background ,bg-special-cold 
:foreground ,fg-special-cold)))
-   `(web-mode-jsx-depth-4-face ((,class :background ,bg-alt :foreground 
,blue-refine-fg)))
-   `(web-mode-jsx-depth-5-face ((,class :background ,bg-alt :foreground 
,blue-nuanced)))
-   `(web-mode-keyword-face ((,class ,@(modus-vivendi-theme-syntax-foreground
-                                       magenta-alt-other 
magenta-alt-other-faint)
-                                    ,@(modus-vivendi-theme-bold-weight))))
-   `(web-mode-param-name-face ((,class ,@(modus-vivendi-theme-syntax-foreground
-                                          magenta magenta-faint))))
-   `(web-mode-part-comment-face ((,class :inherit web-mode-comment-face)))
-   `(web-mode-part-face ((,class :inherit web-mode-block-face)))
-   `(web-mode-part-string-face ((,class :inherit web-mode-string-face)))
-   `(web-mode-preprocessor-face ((,class 
,@(modus-vivendi-theme-syntax-foreground
-                                            red-alt-other 
red-alt-other-faint))))
-   `(web-mode-script-face ((,class :inherit web-mode-part-face)))
-   `(web-mode-sql-keyword-face ((,class :inherit bold
-                                        
,@(modus-vivendi-theme-syntax-foreground
-                                           yellow yellow-faint))))
-   `(web-mode-string-face ((,class ,@(modus-vivendi-theme-syntax-foreground
-                                      blue-alt blue-alt-faint))))
-   `(web-mode-style-face ((,class :inherit web-mode-part-face)))
-   `(web-mode-symbol-face ((,class ,@(modus-vivendi-theme-syntax-foreground
-                                      blue-alt-other blue-alt-other-faint))))
-   `(web-mode-type-face ((,class ,@(modus-vivendi-theme-syntax-foreground
-                                    magenta-alt magenta-alt-faint))))
-   `(web-mode-underline-face ((,class :underline t)))
-   `(web-mode-variable-name-face ((,class 
,@(modus-vivendi-theme-syntax-foreground
-                                             cyan cyan-faint))))
-   `(web-mode-warning-face ((,class :inherit bold :background ,bg-alt
-                                    ,@(modus-vivendi-theme-syntax-foreground
-                                       yellow-alt-other 
yellow-alt-other-faint))))
-   `(web-mode-whitespace-face ((,class :background ,bg-whitespace :foreground 
,fg-whitespace)))
-;;;;; wgrep
-   `(wgrep-delete-face ((,class :inherit modus-theme-refine-yellow)))
-   `(wgrep-done-face ((,class :inherit modus-theme-refine-blue)))
-   `(wgrep-face ((,class :inherit modus-theme-refine-green)))
-   `(wgrep-file-face ((,class :foreground ,fg-special-warm)))
-   `(wgrep-reject-face ((,class :inherit (modus-theme-intense-red bold))))
-;;;;; which-function-mode
-   `(which-func ((,class :foreground ,magenta-active)))
-;;;;; which-key
-   `(which-key-command-description-face ((,class :foreground ,cyan)))
-   `(which-key-group-description-face ((,class :foreground ,magenta-alt)))
-   `(which-key-highlighted-command-face ((,class :foreground ,cyan-alt 
:underline t)))
-   `(which-key-key-face ((,class :inherit bold :foreground ,blue-intense)))
-   `(which-key-local-map-description-face ((,class :foreground ,fg-main)))
-   `(which-key-note-face ((,class :background ,bg-dim :foreground 
,fg-special-mild)))
-   `(which-key-separator-face ((,class :foreground ,fg-alt)))
-   `(which-key-special-key-face ((,class :inherit bold :foreground 
,yellow-intense)))
-;;;;; whitespace-mode
-   `(whitespace-big-indent ((,class :inherit modus-theme-subtle-red)))
-   `(whitespace-empty ((,class :inherit modus-theme-intense-magenta)))
-   `(whitespace-hspace ((,class :background ,bg-whitespace :foreground 
,fg-whitespace)))
-   `(whitespace-indentation ((,class :background ,bg-whitespace :foreground 
,fg-whitespace)))
-   `(whitespace-line ((,class :inherit modus-theme-special-warm)))
-   `(whitespace-newline ((,class :background ,bg-whitespace :foreground 
,fg-whitespace)))
-   `(whitespace-space ((,class :background ,bg-whitespace :foreground 
,fg-whitespace)))
-   `(whitespace-space-after-tab ((,class :inherit modus-theme-subtle-magenta)))
-   `(whitespace-space-before-tab ((,class :inherit modus-theme-subtle-cyan)))
-   `(whitespace-tab ((,class :background ,bg-whitespace :foreground 
,fg-whitespace)))
-   `(whitespace-trailing ((,class :inherit modus-theme-intense-red)))
-;;;;; window-divider-mode
-   `(window-divider ((,class :foreground ,fg-window-divider-inner)))
-   `(window-divider-first-pixel ((,class :foreground 
,fg-window-divider-outer)))
-   `(window-divider-last-pixel ((,class :foreground ,fg-window-divider-outer)))
-;;;;; winum
-   `(winum-face ((,class ,@(modus-vivendi-theme-bold-weight) :foreground 
,cyan-active)))
-;;;;; writegood-mode
-   `(writegood-duplicates-face ((,class :background ,bg-alt :foreground 
,red-alt :underline t)))
-   `(writegood-passive-voice-face ((,class :foreground ,yellow-nuanced 
:underline ,fg-lang-warning)))
-   `(writegood-weasels-face ((,class :foreground ,red-nuanced :underline 
,fg-lang-error)))
-;;;;; woman
-   `(woman-addition ((,class :foreground ,magenta-alt-other)))
-   `(woman-bold ((,class :inherit bold :foreground ,magenta)))
-   `(woman-italic ((,class :foreground ,cyan :slant italic)))
-   `(woman-unknown ((,class :foreground ,yellow :slant italic)))
-;;;;; xah-elisp-mode
-   `(xah-elisp-at-symbol ((,class :inherit bold
-                                  ,@(modus-vivendi-theme-syntax-foreground
-                                     red-alt red-alt-faint))))
-   `(xah-elisp-cap-variable ((,class ,@(modus-vivendi-theme-syntax-foreground
-                                        red-alt-other red-alt-other-faint))))
-   `(xah-elisp-command-face ((,class ,@(modus-vivendi-theme-syntax-foreground
-                                        cyan-alt-other cyan-alt-other-faint))))
-   `(xah-elisp-dollar-symbol ((,class ,@(modus-vivendi-theme-syntax-foreground
-                                         green green-faint))))
-;;;;; xref
-   `(xref-file-header ((,class :inherit bold :foreground ,fg-special-cold)))
-   `(xref-line-number ((,class :foreground ,fg-alt)))
-   `(xref-match ((,class :inherit match)))
-;;;;; yaml-mode
-   `(yaml-tab-face ((,class :inherit modus-theme-intense-red)))
-;;;;; yasnippet
-   `(yas-field-highlight-face ((,class :background ,bg-alt :foreground 
,fg-main)))
-;;;;; ztree
-   `(ztreep-arrow-face ((,class :foreground ,fg-inactive)))
-   `(ztreep-diff-header-face ((,class :inherit bold :height 1.2 :foreground 
,fg-special-cold)))
-   `(ztreep-diff-header-small-face ((,class :inherit bold :foreground 
,fg-special-mild)))
-   `(ztreep-diff-model-add-face ((,class :foreground ,green)))
-   `(ztreep-diff-model-diff-face ((,class :foreground ,red)))
-   `(ztreep-diff-model-ignored-face ((,class :foreground ,fg-alt 
:strike-through t)))
-   `(ztreep-diff-model-normal-face ((,class :foreground ,fg-alt)))
-   `(ztreep-expand-sign-face ((,class :foreground ,blue)))
-   `(ztreep-header-face ((,class :inherit bold :height 1.2 :foreground 
,fg-special-cold)))
-   `(ztreep-leaf-face ((,class :foreground ,cyan)))
-   `(ztreep-node-count-children-face ((,class :foreground ,fg-special-warm)))
-   `(ztreep-node-face ((,class :foreground ,fg-main))))
-;;;; Emacs 27+
-  (when (>= emacs-major-version 27)
-    (custom-theme-set-faces
-     'modus-vivendi
-;;;;; line numbers (`display-line-numbers-mode' and global variant)
-     ;; NOTE that this is specifically for the faces that were
-     ;; introduced in Emacs 27, as the other faces are already
-     ;; supported.
-     `(line-number-major-tick ((,class :inherit (bold default)
-                                       :background ,yellow-nuanced-bg
-                                       :foreground ,yellow-nuanced)))
-     `(line-number-minor-tick ((,class :inherit (bold default)
-                                       :background ,bg-inactive
-                                       :foreground ,fg-inactive)))
-;;;;; tab-bar-mode
-     `(tab-bar ((,class :background ,bg-tab-bar :foreground ,fg-main)))
-     `(tab-bar-tab ((,class :inherit bold :box (:line-width 2 :color 
,bg-tab-active)
-                            :background ,bg-tab-active :foreground ,fg-main)))
-     `(tab-bar-tab-inactive ((,class :box (:line-width 2 :color 
,bg-tab-inactive)
-                                     :background ,bg-tab-inactive :foreground 
,fg-dim)))
-;;;;; tab-line-mode
-     `(tab-line ((,class :height 0.95 :background ,bg-tab-bar :foreground 
,fg-main)))
-     `(tab-line-close-highlight ((,class :foreground ,red)))
-     `(tab-line-highlight ((,class :background ,blue-subtle-bg :foreground 
,fg-dim)))
-     `(tab-line-tab ((,class :inherit bold :box (:line-width 2 :color 
,bg-tab-active)
-                             :background ,bg-tab-active :foreground ,fg-main)))
-     `(tab-line-tab-current ((,class :inherit tab-line-tab)))
-     `(tab-line-tab-inactive ((,class :box (:line-width 2 :color 
,bg-tab-inactive)
-                                      :background ,bg-tab-inactive :foreground 
,fg-dim)))))
-;;;; Emacs 28+
-  (when (>= emacs-major-version 28)
-    (custom-theme-set-faces
-     'modus-vivendi
-;;;;; isearch regexp groups
-     `(isearch-group-1 ((,class :inherit modus-theme-intense-blue)))
-     `(isearch-group-2 ((,class :inherit modus-theme-intense-magenta)))))
-;;; variables
-  (custom-theme-set-variables
-   'modus-vivendi
-;;;; ansi-colors
-   `(ansi-color-faces-vector [default bold shadow italic underline success 
warning error])
-   `(ansi-color-names-vector [,bg-main ,red ,green ,yellow ,blue ,magenta 
,cyan ,fg-main])
-;;;; awesome-tray
-   `(awesome-tray-mode-line-active-color ,blue)
-   `(awesome-tray-mode-line-inactive-color ,bg-active)
-;;;; flymake fringe indicators
-   `(flymake-error-bitmap '(flymake-double-exclamation-mark 
modus-theme-fringe-red))
-   `(flymake-warning-bitmap '(exclamation-mark modus-theme-fringe-yellow))
-   `(flymake-note-bitmap '(exclamation-mark modus-theme-fringe-cyan))
-;;;; ibuffer
-   `(ibuffer-deletion-face 'modus-theme-mark-del)
-   `(ibuffer-filter-group-name-face 'modus-theme-mark-symbol)
-   `(ibuffer-marked-face 'modus-theme-mark-sel)
-   `(ibuffer-title-face 'modus-theme-pseudo-header)
-;;;; highlight-tail
-   `(highlight-tail-colors
-     '((,green-subtle-bg . 0)
-       (,cyan-subtle-bg . 20)))
-;;;; hl-todo
-   `(hl-todo-keyword-faces
-     '(("HOLD" . ,yellow-alt)
-       ("TODO" . ,magenta)
-       ("NEXT" . ,magenta-alt-other)
-       ("THEM" . ,magenta-alt)
-       ("PROG" . ,cyan)
-       ("OKAY" . ,cyan-alt)
-       ("DONT" . ,green-alt)
-       ("FAIL" . ,red)
-       ("BUG" . ,red)
-       ("DONE" . ,green)
-       ("NOTE" . ,yellow-alt-other)
-       ("KLUDGE" . ,yellow)
-       ("HACK" . ,yellow)
-       ("TEMP" . ,red-nuanced)
-       ("FIXME" . ,red-alt-other)
-       ("XXX+" . ,red-alt)
-       ("REVIEW" . ,cyan-alt-other)
-       ("DEPRECATED" . ,blue-nuanced)))
-;;;; vc-annotate (C-x v g)
-   `(vc-annotate-background nil)
-   `(vc-annotate-background-mode nil)
-   `(vc-annotate-color-map
-     '((20 . ,red)
-       (40 . ,magenta)
-       (60 . ,magenta-alt)
-       (80 . ,red-alt)
-       (100 . ,yellow)
-       (120 . ,yellow-alt)
-       (140 . ,fg-special-warm)
-       (160 . ,fg-special-mild)
-       (180 . ,green)
-       (200 . ,green-alt)
-       (220 . ,cyan-alt-other)
-       (240 . ,cyan-alt)
-       (260 . ,cyan)
-       (280 . ,fg-special-cold)
-       (300 . ,blue)
-       (320 . ,blue-alt)
-       (340 . ,blue-alt-other)
-       (360 . ,magenta-alt-other)))
-   `(vc-annotate-very-old-color nil)
-;;;; xterm-color
-   `(xterm-color-names [,bg-main ,red ,green ,yellow ,blue ,magenta ,cyan 
,fg-alt])
-   `(xterm-color-names-bright [,bg-alt ,red-alt ,green-alt ,yellow-alt 
,blue-alt ,magenta-alt ,cyan-alt ,fg-main]))
-;;; Conditional theme variables
-;;;; org-src-block-faces
-  ;; this is a user option to add a colour-coded background to source
-  ;; blocks for various programming languages
-  (when (eq modus-vivendi-theme-org-blocks 'rainbow)
-    (custom-theme-set-variables
-     'modus-vivendi
-     `(org-src-block-faces              ; TODO this list should be expanded
-       `(("emacs-lisp" modus-theme-nuanced-magenta)
-         ("elisp" modus-theme-nuanced-magenta)
-         ("clojure" modus-theme-nuanced-magenta)
-         ("clojurescript" modus-theme-nuanced-magenta)
-         ("c" modus-theme-nuanced-blue)
-         ("c++" modus-theme-nuanced-blue)
-         ("sh" modus-theme-nuanced-green)
-         ("shell" modus-theme-nuanced-green)
-         ("html" modus-theme-nuanced-yellow)
-         ("xml" modus-theme-nuanced-yellow)
-         ("css" modus-theme-nuanced-red)
-         ("scss" modus-theme-nuanced-red)
-         ("python" modus-theme-nuanced-green)
-         ("ipython" modus-theme-nuanced-magenta)
-         ("r" modus-theme-nuanced-cyan)
-         ("yaml" modus-theme-nuanced-cyan)
-         ("conf" modus-theme-nuanced-cyan)
-         ("docker" modus-theme-nuanced-cyan)
-         ("json" modus-theme-nuanced-cyan))))))
+(deftheme modus-vivendi
+  "Accessible and customizable dark theme (WCAG AAA standard).
+Conforms with the highest legibility standard for color contrast
+between background and foreground in any given piece of text,
+which corresponds to a minimum contrast in relative luminance of
+7:1.")
 
-;;; library provides
-;;;###autoload
-(when load-file-name
-  (add-to-list 'custom-theme-load-path
-               (file-name-as-directory (file-name-directory load-file-name))))
+(modus-themes-theme modus-vivendi)
 
 (provide-theme 'modus-vivendi)
 
-(provide 'modus-vivendi-theme)
-
 ;;; modus-vivendi-theme.el ends here
diff --git a/etc/themes/wombat-theme.el b/etc/themes/wombat-theme.el
index aaa7cce..d625b7f 100644
--- a/etc/themes/wombat-theme.el
+++ b/etc/themes/wombat-theme.el
@@ -57,6 +57,8 @@ are included.")
    `(font-lock-type-face ((,class (:foreground "#92a65e" :weight bold))))
    `(font-lock-variable-name-face ((,class (:foreground "#cae682"))))
    `(font-lock-warning-face ((,class (:foreground "#ccaa8f"))))
+   ;; Help faces
+   `(help-key-binding ((,class (:background "#333333" :foreground "#f6f3e8"))))
    ;; Button and link faces
    `(link ((,class (:foreground "#8ac6f2" :underline t))))
    `(link-visited ((,class (:foreground "#e5786d" :underline t))))
diff --git a/leim/Makefile.in b/leim/Makefile.in
index f3e530a..c2f9cf5 100644
--- a/leim/Makefile.in
+++ b/leim/Makefile.in
@@ -25,24 +25,14 @@ SHELL = @SHELL@
 
 # Here are the things that we expect ../configure to edit.
 srcdir=@srcdir@
+top_builddir = @top_builddir@
 
 # Where the generated files go.
 leimdir = ${srcdir}/../lisp/leim
 
 EXEEXT = @EXEEXT@
 
-# 'make' verbosity.
-AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
-
-AM_V_GEN = $(am__v_GEN_@AM_V@)
-am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
-am__v_GEN_0 = @echo "  GEN     " $@;
-am__v_GEN_1 =
-
-AM_V_at = $(am__v_at_@AM_V@)
-am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
-am__v_at_0 = @
-am__v_at_1 =
+-include ${top_builddir}/src/verbose.mk
 
 # Prevent any settings in the user environment causing problems.
 unexport EMACSDATA EMACSDOC EMACSPATH
diff --git a/lib-src/Makefile.in b/lib-src/Makefile.in
index 0a6dd82..05eb524 100644
--- a/lib-src/Makefile.in
+++ b/lib-src/Makefile.in
@@ -44,33 +44,8 @@ WERROR_CFLAGS = @WERROR_CFLAGS@
 # Program name transformation.
 TRANSFORM = @program_transform_name@
 
-# 'make' verbosity.
-AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
-
-AM_V_CC = $(am__v_CC_@AM_V@)
-am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@)
-am__v_CC_0 = @echo "  CC      " $@;
-am__v_CC_1 =
-
-AM_V_CCLD = $(am__v_CCLD_@AM_V@)
-am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@)
-am__v_CCLD_0 = @echo "  CCLD    " $@;
-am__v_CCLD_1 =
-
-AM_V_GEN = $(am__v_GEN_@AM_V@)
-am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
-am__v_GEN_0 = @echo "  GEN     " $@;
-am__v_GEN_1 =
-
-AM_V_RC = $(am__v_RC_@AM_V@)
-am__v_RC_ = $(am__v_RC_@AM_DEFAULT_V@)
-am__v_RC_0 = @echo "  RC      " $@;
-am__v_RC_1 =
-
-AM_V_at = $(am__v_at_@AM_V@)
-am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
-am__v_at_0 = @
-am__v_at_1 =
+top_builddir = @top_builddir@
+-include ${top_builddir}/src/verbose.mk
 
 # ==================== Where To Install Things ====================
 
diff --git a/lib/Makefile.in b/lib/Makefile.in
index 91a6b5f..043ace2 100644
--- a/lib/Makefile.in
+++ b/lib/Makefile.in
@@ -29,26 +29,7 @@ top_srcdir = @top_srcdir@
 all:
 .PHONY: all
 
-# 'make' verbosity.
-AM_V_AR = $(am__v_AR_@AM_V@)
-am__v_AR_ = $(am__v_AR_@AM_DEFAULT_V@)
-am__v_AR_0 = @echo "  AR      " $@;
-am__v_AR_1 =
-
-AM_V_CC = $(am__v_CC_@AM_V@)
-am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@)
-am__v_CC_0 = @echo "  CC      " $@;
-am__v_CC_1 =
-
-AM_V_GEN = $(am__v_GEN_@AM_V@)
-am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
-am__v_GEN_0 = @echo "  GEN     " $@;
-am__v_GEN_1 =
-
-AM_V_at = $(am__v_at_@AM_V@)
-am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
-am__v_at_0 = @
-am__v_at_1 =
+-include ${top_builddir}/src/verbose.mk
 
 ALL_CFLAGS= \
   $(C_SWITCH_SYSTEM) $(C_SWITCH_MACHINE) $(DEPFLAGS) \
diff --git a/lib/pipe2.c b/lib/pipe2.c
index 41493aa..adbaa4a 100644
--- a/lib/pipe2.c
+++ b/lib/pipe2.c
@@ -41,7 +41,7 @@ pipe2 (int fd[2], int flags)
 {
   /* Mingw _pipe() corrupts fd on failure; also, if we succeed at
      creating the pipe but later fail at changing fcntl, we want
-     to leave fd unchanged: http://austingroupbugs.net/view.php?id=467  */
+     to leave fd unchanged: https://austingroupbugs.net/view.php?id=467  */
   int tmp[2];
   tmp[0] = fd[0];
   tmp[1] = fd[1];
diff --git a/lisp/Makefile.in b/lisp/Makefile.in
index 72f7f16..8ea2841 100644
--- a/lisp/Makefile.in
+++ b/lisp/Makefile.in
@@ -21,6 +21,7 @@ SHELL = @SHELL@
 
 srcdir = @srcdir@
 top_srcdir = @top_srcdir@
+top_builddir = @top_builddir@
 lisp = $(srcdir)
 VPATH = $(srcdir)
 EXEEXT = @EXEEXT@
@@ -29,24 +30,7 @@ EXEEXT = @EXEEXT@
 # limitation.
 XARGS_LIMIT = @XARGS_LIMIT@
 
-# 'make' verbosity.
-AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
-
-AM_V_ELC = $(am__v_ELC_@AM_V@)
-am__v_ELC_ = $(am__v_ELC_@AM_DEFAULT_V@)
-am__v_ELC_0 = @echo "  ELC     " $@;
-am__v_ELC_1 =
-
-AM_V_GEN = $(am__v_GEN_@AM_V@)
-am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
-am__v_GEN_0 = @echo "  GEN     " $@;
-am__v_GEN_1 =
-
-AM_V_at = $(am__v_at_@AM_V@)
-am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
-am__v_at_0 = @
-am__v_at_1 =
-
+-include ${top_builddir}/src/verbose.mk
 
 FIND_DELETE = @FIND_DELETE@
 
diff --git a/lisp/align.el b/lisp/align.el
index 1a1d3dd..7ae067f 100644
--- a/lisp/align.el
+++ b/lisp/align.el
@@ -1310,7 +1310,7 @@ aligner would have dealt with are."
                 (thissep (if rulesep (cdr rulesep) separate))
                 same (eol 0)
                 search-start
-                groups group-c
+                groups ;; group-c
                 spacing spacing-c
                 tab-stop tab-stop-c
                 repeat repeat-c
@@ -1434,7 +1434,7 @@ aligner would have dealt with are."
 
                     ;; lookup the `group' attribute the first time
                     ;; that we need it
-                    (unless group-c
+                    (unless nil ;; group-c
                       (setq groups (or (cdr (assq 'group rule)) 1))
                       (unless (listp groups)
                         (setq groups (list groups)))
diff --git a/lisp/allout-widgets.el b/lisp/allout-widgets.el
index f251be8..931dfbc 100644
--- a/lisp/allout-widgets.el
+++ b/lisp/allout-widgets.el
@@ -1,4 +1,4 @@
-;; allout-widgets.el --- Visually highlight allout outline structure.
+;; allout-widgets.el --- Visually highlight allout outline structure.  -*- 
lexical-binding: t; -*-
 
 ;; Copyright (C) 2005-2021 Free Software Foundation, Inc.
 
@@ -6,7 +6,7 @@
 ;; Version: 1.0
 ;; Created: Dec 2005
 ;; Keywords: outlines
-;; Website: http://myriadicity.net/software-and-systems/craft/emacs-allout
+;; Website: https://myriadicity.net/software-and-systems/craft/emacs-allout
 
 ;; This file is part of GNU Emacs.
 
@@ -38,7 +38,7 @@
 ;; See the `allout-widgets-mode' docstring for more details.
 ;;
 ;; Info about allout and allout-widgets development are available at
-;; http://myriadicity.net/Sundry/EmacsAllout
+;; https://myriadicity.net/software-and-systems/craft/emacs-allout
 ;;
 ;; The graphics include:
 ;;
@@ -72,11 +72,11 @@
 (eval-when-compile (require 'cl-lib))
 
 ;;;_ : internal variables needed before user-customization variables
-;;; In order to enable activation of allout-widgets-mode via customization,
-;;; allout-widgets-auto-activation uses a setting function.  That function
-;;; is invoked when the customization variable definition is evaluated,
-;;; during file load, so the involved code must reside above that
-;;; definition in the file.
+;; In order to enable activation of allout-widgets-mode via customization,
+;; allout-widgets-auto-activation uses a setting function.  That function
+;; is invoked when the customization variable definition is evaluated,
+;; during file load, so the involved code must reside above that
+;; definition in the file.
 ;;;_  = allout-widgets-mode
 (defvar-local allout-widgets-mode nil
   "Allout mode enhanced with graphical widgets.")
@@ -100,8 +100,8 @@ with allout-mode."
 
 See `allout-widgets-mode-inhibit' for per-file/per-buffer
 inhibition of allout-widgets-mode."
-  (add-hook 'allout-mode-off-hook 'allout-widgets-mode-off)
-  (add-hook 'allout-mode-on-hook 'allout-widgets-mode-on)
+  (add-hook 'allout-mode-off-hook #'allout-widgets-mode-off)
+  (add-hook 'allout-mode-on-hook #'allout-widgets-mode-on)
   t)
 ;;;_  > allout-widgets-mode-disable
 (defun allout-widgets-mode-disable ()
@@ -109,8 +109,8 @@ inhibition of allout-widgets-mode."
 
 See `allout-widgets-mode-inhibit' for per-file/per-buffer
 inhibition of allout-widgets-mode."
-  (remove-hook 'allout-mode-off-hook 'allout-widgets-mode-off)
-  (remove-hook 'allout-mode-on-hook 'allout-widgets-mode-on)
+  (remove-hook 'allout-mode-off-hook #'allout-widgets-mode-off)
+  (remove-hook 'allout-mode-on-hook #'allout-widgets-mode-on)
   t)
 ;;;_  > allout-widgets-setup (varname value)
 ;;;###autoload
@@ -141,7 +141,7 @@ See `allout-widgets-mode' for allout widgets mode features."
   :version "24.1"
   :type 'boolean
   :group 'allout-widgets
-  :set 'allout-widgets-setup
+  :set #'allout-widgets-setup
  )
 ;; ;;;_  = allout-widgets-allow-unruly-edits
 ;; (defcustom allout-widgets-allow-unruly-edits nil
@@ -307,7 +307,7 @@ In addition, you can invoked `allout-widgets-mode' 
allout-mode
 buffers where this is set to enable and disable widget
 enhancements, directly.")
 ;;;###autoload
-(put 'allout-widgets-mode-inhibit 'safe-local-variable 'booleanp)
+(put 'allout-widgets-mode-inhibit 'safe-local-variable #'booleanp)
 ;;;_    = allout-inhibit-body-modification-hook
 (defvar-local allout-inhibit-body-modification-hook nil
   "Override de-escaping of text-prefixes in item bodies during specific 
changes.
@@ -402,14 +402,14 @@ not altered with an escape sequence.")
     (set-keymap-parent km as-parent)
     (dolist (digit '("0" "1" "2" "3"
                      "4" "5" "6" "7" "8" "9"))
-      (define-key km digit 'digit-argument))
-    (define-key km "-" 'negative-argument)
+      (define-key km digit #'digit-argument))
+    (define-key km "-" #'negative-argument)
     ;; Override underlying mouse-1 and mouse-2 bindings in icon territory:
-    (define-key km [(mouse-1)] (lambda () (interactive) nil))
-    (define-key km [(mouse-2)] (lambda () (interactive) nil))
+    (define-key km [(mouse-1)] #'ignore)
+    (define-key km [(mouse-2)] #'ignore)
 
     ;; Catchall, handles actual keybindings, dynamically doing keymap lookups:
-    (define-key km [t] 'allout-item-icon-key-handler)
+    (define-key km [t] #'allout-item-icon-key-handler)
 
     km)
   "General tree-node key bindings.")
@@ -535,7 +535,7 @@ outline hot-spot navigation (see `allout-mode')."
                      "\\1\\3"))
          )
 
-        (add-hook 'after-change-functions 'allout-widgets-after-change-handler
+        (add-hook 'after-change-functions #'allout-widgets-after-change-handler
                   nil t)
 
         (allout-setup-text-properties)
@@ -551,23 +551,23 @@ outline hot-spot navigation (see `allout-mode')."
           (set-keymap-parent allout-item-icon-keymap as-parent))
 
         (add-hook 'allout-exposure-change-functions
-                  'allout-widgets-exposure-change-recorder nil 'local)
+                  #'allout-widgets-exposure-change-recorder nil 'local)
         (add-hook 'allout-structure-added-functions
-                  'allout-widgets-additions-recorder nil 'local)
+                  #'allout-widgets-additions-recorder nil 'local)
         (add-hook 'allout-structure-deleted-functions
-                  'allout-widgets-deletions-recorder nil 'local)
+                  #'allout-widgets-deletions-recorder nil 'local)
         (add-hook 'allout-structure-shifted-functions
-                  'allout-widgets-shifts-recorder nil 'local)
+                  #'allout-widgets-shifts-recorder nil 'local)
         (add-hook 'allout-after-copy-or-kill-hook
-                  'allout-widgets-after-copy-or-kill-function nil 'local)
+                  #'allout-widgets-after-copy-or-kill-function nil 'local)
         (add-hook 'allout-post-undo-hook
-                  'allout-widgets-after-undo-function nil 'local)
+                  #'allout-widgets-after-undo-function nil 'local)
 
-        (add-hook 'before-change-functions 
'allout-widgets-before-change-handler
+        (add-hook 'before-change-functions
+                  #'allout-widgets-before-change-handler nil 'local)
+        (add-hook 'post-command-hook #'allout-widgets-post-command-business
                   nil 'local)
-        (add-hook 'post-command-hook 'allout-widgets-post-command-business
-                  nil 'local)
-        (add-hook 'pre-command-hook 'allout-widgets-pre-command-business
+        (add-hook 'pre-command-hook #'allout-widgets-pre-command-business
                   nil 'local)
 
         ;; init the widgets tally for debugging:
@@ -596,23 +596,23 @@ outline hot-spot navigation (see `allout-mode')."
       (remove-from-invisibility-spec 'allout-escapes)
 
       (remove-hook 'after-change-functions
-                   'allout-widgets-after-change-handler 'local)
+                   #'allout-widgets-after-change-handler 'local)
       (remove-hook 'allout-exposure-change-functions
-                   'allout-widgets-exposure-change-recorder 'local)
+                   #'allout-widgets-exposure-change-recorder 'local)
       (remove-hook 'allout-structure-added-functions
-                   'allout-widgets-additions-recorder 'local)
+                   #'allout-widgets-additions-recorder 'local)
       (remove-hook 'allout-structure-deleted-functions
-                   'allout-widgets-deletions-recorder 'local)
+                   #'allout-widgets-deletions-recorder 'local)
       (remove-hook 'allout-structure-shifted-functions
-                   'allout-widgets-shifts-recorder 'local)
+                   #'allout-widgets-shifts-recorder 'local)
       (remove-hook 'allout-after-copy-or-kill-hook
-                   'allout-widgets-after-copy-or-kill-function 'local)
+                   #'allout-widgets-after-copy-or-kill-function 'local)
       (remove-hook 'before-change-functions
-                   'allout-widgets-before-change-handler 'local)
+                   #'allout-widgets-before-change-handler 'local)
       (remove-hook 'post-command-hook
-                   'allout-widgets-post-command-business 'local)
+                   #'allout-widgets-post-command-business 'local)
       (remove-hook 'pre-command-hook
-                   'allout-widgets-pre-command-business 'local)
+                   #'allout-widgets-pre-command-business 'local)
       (assq-delete-all 'allout-widgets-mode-inhibit minor-mode-alist)
       (set-buffer-modified-p was-modified))))
 ;;;_   > allout-widgets-mode-off
@@ -710,7 +710,7 @@ Optional RECURSING is for internal use, to limit recursion."
 
         (when allout-widgets-reenable-before-change-handler
           (add-hook 'before-change-functions
-                    'allout-widgets-before-change-handler
+                    #'allout-widgets-before-change-handler
                     nil 'local)
           (setq allout-widgets-reenable-before-change-handler nil))
 
@@ -879,7 +879,7 @@ encompassing condition-case."
     (message header) (sit-for allout-widgets-hook-error-post-time)
     ;; reraise the error, or one concerning this function if unexpected:
     (if (equal mode 'error)
-        (apply 'signal args)
+        (apply #'signal args)
       (error "%s: unexpected mode, %s %s" this mode args))))
 ;;;_   > allout-widgets-changes-exceed-threshold-p ()
 (defun allout-widgets-adjusting-message (message)
@@ -973,9 +973,8 @@ Generally invoked via `allout-exposure-change-functions'."
         deactivate-mark)
 
     (dolist (change changes)
-      (let (handling
-            (from (cadr change))
-            bucket got
+      (let ((from (cadr change))
+            bucket
             (to (caddr change))
             (flag (cadddr change))
             parent)
@@ -986,10 +985,11 @@ Generally invoked via `allout-exposure-change-functions'."
                               from bucket))
 
         ;; have we already handled exposure changes in this region?
-        (setq handling (if flag 'handled-conceal 'handled-expose)
-              got (allout-range-overlaps from to (symbol-value handling))
-              covered (car got))
-        (set handling (cadr got))
+        (cl-callf (lambda (x)
+                    (let ((got (allout-range-overlaps from to x)))
+                      (setq covered (car got))
+                      (cadr got)))
+            (if flag handled-conceal handled-expose))
 
         (when (not covered)
           (save-excursion
@@ -1825,7 +1825,7 @@ reapplying this method will rectify the glyphs."
             (if (> increment 1) (setq increment 1))
             (when extenders
               ;; paint extenders after a connector, else leave spaces.
-              (dotimes (i extenders)
+              (dotimes (_ extenders)
                 (put-text-property
                  position (setq position (1+ position))
                  'display (allout-fetch-icon-image
diff --git a/lisp/allout.el b/lisp/allout.el
index ff0b675..f50f5fd 100644
--- a/lisp/allout.el
+++ b/lisp/allout.el
@@ -1,12 +1,12 @@
-;;; allout.el --- extensive outline mode for use alone and with other modes
+;;; allout.el --- extensive outline mode for use alone and with other modes  
-*- lexical-binding: t; -*-
 
-;; Copyright (C) 1992-1994, 2001-2021 Free Software Foundation, Inc.
+;; Copyright (C) 1992-2021 Free Software Foundation, Inc.
 
 ;; Author: Ken Manheimer <ken dot manheimer at gmail...>
 ;; Created: Dec 1991 -- first release to usenet
 ;; Version: 2.3
 ;; Keywords: outlines, wp, languages, PGP, GnuPG
-;; Website: http://myriadicity.net/software-and-systems/craft/emacs-allout
+;; Website: https://myriadicity.net/software-and-systems/craft/emacs-allout
 
 ;; This file is part of GNU Emacs.
 
@@ -57,7 +57,7 @@
 ;; mode.
 ;;
 ;; Directions to the latest development version and helpful notes are
-;; available at http://myriadicity.net/Sundry/EmacsAllout .
+;; available at 
https://myriadicity.net/software-and-systems/craft/emacs-allout .
 ;;
 ;; The outline menubar additions provide quick reference to many of the
 ;; features.  See the docstring of the variables `allout-layout' and
@@ -75,9 +75,6 @@
 (declare-function epa-passphrase-callback-function
                  "epa" (context key-id handback))
 
-;;;_* Dependency loads
-(require 'overlay)
-
 ;;;_* USER CUSTOMIZATION VARIABLES:
 
 ;;;_ > defgroup allout, allout-keybindings
@@ -136,13 +133,14 @@ respective allout-mode keybinding variables, 
`allout-command-prefix',
     (when (boundp 'allout-unprefixed-keybindings)
       (dolist (entry allout-unprefixed-keybindings)
         (define-key map (car (read-from-string (car entry))) (cadr entry))))
-    (substitute-key-definition 'beginning-of-line 'allout-beginning-of-line
+    (substitute-key-definition #'beginning-of-line #'allout-beginning-of-line
                                map global-map)
-    (substitute-key-definition 'move-beginning-of-line 
'allout-beginning-of-line
+    (substitute-key-definition #'move-beginning-of-line
+                               #'allout-beginning-of-line
                                map global-map)
-    (substitute-key-definition 'end-of-line 'allout-end-of-line
+    (substitute-key-definition #'end-of-line #'allout-end-of-line
                                map global-map)
-    (substitute-key-definition 'move-end-of-line 'allout-end-of-line
+    (substitute-key-definition #'move-end-of-line #'allout-end-of-line
                                map global-map)
     (allout-institute-keymap map)))
 ;;;_  > allout-institute-keymap (map)
@@ -172,7 +170,7 @@ Default is `\C-c<space>'; just `\C-c' is more 
short-and-sweet, if you're
 willing to let allout use a bunch of \C-c keybindings."
   :type 'string
   :group 'allout-keybindings
-  :set 'allout-compose-and-institute-keymap)
+  :set #'allout-compose-and-institute-keymap)
 ;;;_   = allout-keybindings-binding
 (define-widget 'allout-keybindings-binding 'lazy
   "Structure of allout keybindings customization items."
@@ -233,7 +231,7 @@ prevails."
   :version "24.1"
   :type 'allout-keybindings-binding
   :group 'allout-keybindings
-  :set 'allout-compose-and-institute-keymap
+  :set #'allout-compose-and-institute-keymap
  )
 ;;;_   = allout-unprefixed-keybindings
 (defcustom allout-unprefixed-keybindings
@@ -257,7 +255,7 @@ See the existing keys for examples."
   :version "24.1"
   :type 'allout-keybindings-binding
   :group 'allout-keybindings
-  :set 'allout-compose-and-institute-keymap
+  :set #'allout-compose-and-institute-keymap
   )
 
 ;;;_  > allout-auto-activation-helper (var value)
@@ -279,8 +277,8 @@ Establishes allout processing as part of visiting a file if
 The proper way to use this is through customizing the setting of
 `allout-auto-activation'."
   (if (not allout-auto-activation)
-      (remove-hook 'find-file-hook 'allout-find-file-hook)
-      (add-hook 'find-file-hook 'allout-find-file-hook)))
+      (remove-hook 'find-file-hook #'allout-find-file-hook)
+      (add-hook 'find-file-hook #'allout-find-file-hook)))
 ;;;_  = allout-auto-activation
 ;;;###autoload
 (defcustom allout-auto-activation nil
@@ -301,7 +299,7 @@ With value \"activate\", only auto-mode-activation is 
enabled.
 Auto-layout is not.
 
 With value nil, inhibit any automatic allout-mode activation."
-  :set 'allout-auto-activation-helper
+  :set #'allout-auto-activation-helper
   ;; FIXME: Using strings here is unusual and less efficient than symbols.
   :type '(choice (const :tag "On" t)
                 (const :tag "Ask about layout" "ask")
@@ -408,7 +406,7 @@ where auto-fill occurs."
   :group 'allout)
 (make-variable-buffer-local 'allout-use-hanging-indents)
 ;;;###autoload
-(put 'allout-use-hanging-indents 'safe-local-variable 'booleanp)
+(put 'allout-use-hanging-indents 'safe-local-variable #'booleanp)
 ;;;_  = allout-reindent-bodies
 (defcustom allout-reindent-bodies (if allout-use-hanging-indents
                                    'text)
@@ -437,7 +435,7 @@ just the header."
   :group 'allout)
 (make-variable-buffer-local 'allout-show-bodies)
 ;;;###autoload
-(put 'allout-show-bodies 'safe-local-variable 'booleanp)
+(put 'allout-show-bodies 'safe-local-variable #'booleanp)
 
 ;;;_  = allout-beginning-of-line-cycles
 (defcustom allout-beginning-of-line-cycles t
@@ -510,7 +508,7 @@ character, which is typically set to the 
`allout-primary-bullet'."
   :group 'allout)
 (make-variable-buffer-local 'allout-header-prefix)
 ;;;###autoload
-(put 'allout-header-prefix 'safe-local-variable 'stringp)
+(put 'allout-header-prefix 'safe-local-variable #'stringp)
 ;;;_  = allout-primary-bullet
 (defcustom allout-primary-bullet "*"
   "Bullet used for top-level outline topics.
@@ -527,7 +525,7 @@ bullets."
   :group 'allout)
 (make-variable-buffer-local 'allout-primary-bullet)
 ;;;###autoload
-(put 'allout-primary-bullet 'safe-local-variable 'stringp)
+(put 'allout-primary-bullet 'safe-local-variable #'stringp)
 ;;;_  = allout-plain-bullets-string
 (defcustom allout-plain-bullets-string ".,"
   "The bullets normally used in outline topic prefixes.
@@ -543,7 +541,7 @@ of this var to take effect."
   :group 'allout)
 (make-variable-buffer-local 'allout-plain-bullets-string)
 ;;;###autoload
-(put 'allout-plain-bullets-string 'safe-local-variable 'stringp)
+(put 'allout-plain-bullets-string 'safe-local-variable #'stringp)
 ;;;_  = allout-distinctive-bullets-string
 (defcustom allout-distinctive-bullets-string "*+-=>()[{}&!?#%\"X@$~_\\:;^"
   "Persistent outline header bullets used to distinguish special topics.
@@ -591,7 +589,7 @@ strings."
   :group 'allout)
 (make-variable-buffer-local 'allout-distinctive-bullets-string)
 ;;;###autoload
-(put 'allout-distinctive-bullets-string 'safe-local-variable 'stringp)
+(put 'allout-distinctive-bullets-string 'safe-local-variable #'stringp)
 
 ;;;_  = allout-use-mode-specific-leader
 (defcustom allout-use-mode-specific-leader t
@@ -658,7 +656,7 @@ are always respected by the topic maneuvering functions."
   :group 'allout)
 (make-variable-buffer-local 'allout-old-style-prefixes)
 ;;;###autoload
-(put 'allout-old-style-prefixes 'safe-local-variable 'booleanp)
+(put 'allout-old-style-prefixes 'safe-local-variable #'booleanp)
 ;;;_  = allout-stylish-prefixes -- alternating bullets
 (defcustom allout-stylish-prefixes t
   "Do fancy stuff with topic prefix bullets according to level, etc.
@@ -706,7 +704,7 @@ is non-nil."
   :group 'allout)
 (make-variable-buffer-local 'allout-stylish-prefixes)
 ;;;###autoload
-(put 'allout-stylish-prefixes 'safe-local-variable 'booleanp)
+(put 'allout-stylish-prefixes 'safe-local-variable #'booleanp)
 
 ;;;_  = allout-numbered-bullet
 (defcustom allout-numbered-bullet "#"
@@ -720,7 +718,7 @@ disables numbering maintenance."
   :group 'allout)
 (make-variable-buffer-local 'allout-numbered-bullet)
 ;;;###autoload
-(put 'allout-numbered-bullet 'safe-local-variable 'string-or-null-p)
+(put 'allout-numbered-bullet 'safe-local-variable #'string-or-null-p)
 ;;;_  = allout-file-xref-bullet
 (defcustom allout-file-xref-bullet "@"
   "Bullet signifying file cross-references, for `allout-resolve-xref'.
@@ -729,7 +727,7 @@ Set this var to the bullet you want to use for file 
cross-references."
   :type '(choice (const nil) string)
   :group 'allout)
 ;;;###autoload
-(put 'allout-file-xref-bullet 'safe-local-variable 'string-or-null-p)
+(put 'allout-file-xref-bullet 'safe-local-variable #'string-or-null-p)
 ;;;_  = allout-presentation-padding
 (defcustom allout-presentation-padding 2
   "Presentation-format white-space padding factor, for greater indent."
@@ -738,7 +736,7 @@ Set this var to the bullet you want to use for file 
cross-references."
 
 (make-variable-buffer-local 'allout-presentation-padding)
 ;;;###autoload
-(put 'allout-presentation-padding 'safe-local-variable 'integerp)
+(put 'allout-presentation-padding 'safe-local-variable #'integerp)
 
 ;;;_  = allout-flattened-numbering-abbreviation
 (define-obsolete-variable-alias 'allout-abbreviate-flattened-numbering
@@ -1059,7 +1057,7 @@ invoking it directly."
           (setq allout-primary-bullet leader))
       allout-header-prefix)))
 (defalias 'allout-infer-header-lead
-  'allout-infer-header-lead-and-primary-bullet)
+  #'allout-infer-header-lead-and-primary-bullet)
 ;;;_   > allout-infer-body-reindent ()
 (defun allout-infer-body-reindent ()
   "Determine proper setting for `allout-reindent-bodies'.
@@ -1199,14 +1197,13 @@ Also refresh various data structures that hinge on the 
regexp."
                             "[^" allout-primary-bullet "]"))
                   "\\)"
                   ))))
-(define-obsolete-function-alias 'set-allout-regexp 'allout-set-regexp "26.1")
+(define-obsolete-function-alias 'set-allout-regexp #'allout-set-regexp "26.1")
 ;;;_  : Menu bar
 (defvar allout-mode-exposure-menu)
 (defvar allout-mode-editing-menu)
 (defvar allout-mode-navigation-menu)
 (defvar allout-mode-misc-menu)
 (defun allout-produce-mode-menubar-entries ()
-  (require 'easymenu)
   (easy-menu-define allout-mode-exposure-menu
                    allout-mode-map-value
                    "Allout outline exposure menu."
@@ -1593,17 +1590,6 @@ non-nil in a lasting way.")
 (defvar-local allout-explicitly-deactivated nil
   "If t, `allout-mode's last deactivation was deliberate.
 So `allout-post-command-business' should not reactivate it...")
-;;;_  > allout-setup-menubar ()
-(defun allout-setup-menubar ()
-  "Populate the current buffer's menubar with `allout-mode' stuff."
-  (let ((menus (list allout-mode-exposure-menu
-                    allout-mode-editing-menu
-                    allout-mode-navigation-menu
-                    allout-mode-misc-menu))
-       cur)
-    (while menus
-      (setq cur (car menus)
-            menus (cdr menus)))))
 ;;;_  > allout-overlay-preparations
 (defun allout-overlay-preparations ()
   "Set the properties of the allout invisible-text overlay and others."
@@ -1617,7 +1603,7 @@ So `allout-post-command-business' should not reactivate 
it...")
   ;; property controls the isearch _arrival_ behavior.  This is the case at
   ;; least in emacs 21, 22.1, and xemacs 21.4.
   (put 'allout-exposure-category 'isearch-open-invisible
-       'allout-isearch-end-handler)
+       #'allout-isearch-end-handler)
   (put 'allout-exposure-category 'insert-in-front-hooks
        '(allout-overlay-insert-in-front-handler))
   (put 'allout-exposure-category 'modification-hooks
@@ -1907,12 +1893,12 @@ OPEN:   A TOPIC that is not CLOSED, though its 
OFFSPRING or BODY may be."
           (allout-do-resumptions)
 
           (remove-from-invisibility-spec '(allout . t))
-          (remove-hook 'pre-command-hook 'allout-pre-command-business t)
-          (remove-hook 'post-command-hook 'allout-post-command-business t)
-          (remove-hook 'before-change-functions 'allout-before-change-handler 
t)
-          (remove-hook 'isearch-mode-end-hook 'allout-isearch-end-handler t)
+          (remove-hook 'pre-command-hook #'allout-pre-command-business t)
+          (remove-hook 'post-command-hook #'allout-post-command-business t)
+          (remove-hook 'before-change-functions #'allout-before-change-handler 
t)
+          (remove-hook 'isearch-mode-end-hook #'allout-isearch-end-handler t)
           (remove-hook 'write-contents-functions
-                       'allout-write-contents-hook-handler t)
+                       #'allout-write-contents-hook-handler t)
 
           (remove-overlays (point-min) (point-max)
                            'category 'allout-exposure-category))
@@ -1941,11 +1927,11 @@ OPEN:   A TOPIC that is not CLOSED, though its 
OFFSPRING or BODY may be."
       (add-to-invisibility-spec '(allout . t))
 
       (allout-add-resumptions '(line-move-ignore-invisible t))
-      (add-hook 'pre-command-hook 'allout-pre-command-business nil t)
-      (add-hook 'post-command-hook 'allout-post-command-business nil t)
-      (add-hook 'before-change-functions 'allout-before-change-handler nil t)
-      (add-hook 'isearch-mode-end-hook 'allout-isearch-end-handler nil t)
-      (add-hook 'write-contents-functions 'allout-write-contents-hook-handler
+      (add-hook 'pre-command-hook #'allout-pre-command-business nil t)
+      (add-hook 'post-command-hook #'allout-post-command-business nil t)
+      (add-hook 'before-change-functions #'allout-before-change-handler nil t)
+      (add-hook 'isearch-mode-end-hook #'allout-isearch-end-handler nil t)
+      (add-hook 'write-contents-functions #'allout-write-contents-hook-handler
                 nil t)
 
       ;; Stash auto-fill settings and adjust so custom allout auto-fill
@@ -1970,8 +1956,6 @@ OPEN:     A TOPIC that is not CLOSED, though its 
OFFSPRING or BODY may be."
           ;; allout-auto-fill will use the stashed values and so forth.
           (allout-add-resumptions '(auto-fill-function allout-auto-fill)))
 
-      (allout-setup-menubar)
-
       ;; Do auto layout if warranted:
       (when (and allout-layout
                  allout-auto-activation
@@ -1991,7 +1975,7 @@ OPEN:     A TOPIC that is not CLOSED, though its 
OFFSPRING or BODY may be."
           (allout-this-or-next-heading)
           (condition-case err
               (progn
-                (apply 'allout-expose-topic (list use-layout))
+                (apply #'allout-expose-topic (list use-layout))
                 (message "Adjusting `%s' exposure... done."
                          (buffer-name)))
             ;; Problem applying exposure -- notify user, but don't
@@ -2003,7 +1987,7 @@ OPEN:     A TOPIC that is not CLOSED, though its 
OFFSPRING or BODY may be."
     )                                   ; let (())
   )                                    ; define-minor-mode
 ;;;_  > allout-minor-mode alias
-(defalias 'allout-minor-mode 'allout-mode)
+(defalias 'allout-minor-mode #'allout-mode)
 ;;;_  > allout-unload-function
 (defun allout-unload-function ()
   "Unload the allout outline library."
@@ -2072,7 +2056,7 @@ internal functions use this feature cohesively bunch 
changes."
                 (error "Concealed-text change abandoned, text reconcealed"))))
       (goto-char start))))
 ;;;_  > allout-before-change-handler (beg end)
-(defun allout-before-change-handler (beg end)
+(defun allout-before-change-handler (_beg _end)
   "Protect against changes to invisible text.
 
 See `allout-overlay-interior-modification-handler' for details."
@@ -2236,7 +2220,7 @@ Actually, returns prefix beginning point."
            (or (not (allout-do-doublecheck))
                (not (allout-aberrant-container-p)))))))
 ;;;_    > allout-on-heading-p ()
-(defalias 'allout-on-heading-p 'allout-on-current-heading-p)
+(defalias 'allout-on-heading-p #'allout-on-current-heading-p)
 ;;;_    > allout-e-o-prefix-p ()
 (defun allout-e-o-prefix-p ()
   "True if point is located where current topic prefix ends, heading begins."
@@ -2772,7 +2756,7 @@ of (before any) topics, in which case we return nil."
         (goto-char (point-min))
         nil))))
 ;;;_   > allout-back-to-heading ()
-(defalias 'allout-back-to-heading 'allout-back-to-current-heading)
+(defalias 'allout-back-to-heading #'allout-back-to-current-heading)
 ;;;_   > allout-pre-next-prefix ()
 (defun allout-pre-next-prefix ()
   "Skip forward to just before the next heading line.
@@ -2854,7 +2838,7 @@ collapsed."
   (allout-beginning-of-current-entry)
   (search-forward "\n" nil t)
   (forward-char -1))
-(defalias 'allout-end-of-heading 'allout-end-of-current-heading)
+(defalias 'allout-end-of-heading #'allout-end-of-current-heading)
 ;;;_   > allout-get-body-text ()
 (defun allout-get-body-text ()
   "Return the unmangled body text of the topic immediately containing point."
@@ -3293,10 +3277,6 @@ Returns the qualifying command, if any, else nil."
   (interactive)
   (let* ((modified (event-modifiers last-command-event))
          (key-num (cond ((numberp last-command-event) last-command-event)
-                        ;; for XEmacs character type:
-                        ((and (fboundp 'characterp)
-                              (apply 'characterp (list last-command-event)))
-                         (apply 'char-to-int (list last-command-event)))
                         (t 0)))
          mapped-binding)
 
@@ -5141,7 +5121,7 @@ Optional FOLLOWERS arguments dictate exposure for 
succeeding siblings."
             (if (and spec
                      (allout-descend-to-depth new-depth)
                      (not (allout-hidden-p)))
-                (progn (setq got (apply 'allout-old-expose-topic spec))
+                (progn (setq got (apply #'allout-old-expose-topic spec))
                        (if (and got (or (not max-pos) (> got max-pos)))
                            (setq max-pos got)))))))
     (while (and followers
@@ -5219,7 +5199,7 @@ Optional arg CONTEXT indicates interior levels to 
include."
            (setq flat-index (cdr flat-index)))
          ;; Dispose of single extra delim:
          (setq result (cdr result))))
-    (apply 'concat result)))
+    (apply #'concat result)))
 ;;;_   > allout-stringify-flat-index-plain (flat-index)
 (defun allout-stringify-flat-index-plain (flat-index)
   "Convert list representing section/subsection/... to document string."
@@ -5230,7 +5210,7 @@ Optional arg CONTEXT indicates interior levels to 
include."
                             (if result
                                 (cons delim result))))
          (setq flat-index (cdr flat-index)))
-    (apply 'concat result)))
+    (apply #'concat result)))
 ;;;_   > allout-stringify-flat-index-indented (flat-index)
 (defun allout-stringify-flat-index-indented (flat-index)
   "Convert list representing section/subsection/... to document string."
@@ -5259,7 +5239,7 @@ Optional arg CONTEXT indicates interior levels to 
include."
            (setq flat-index (cdr flat-index)))
          ;; Dispose of single extra delim:
          (setq result (cdr result))))
-    (apply 'concat result)))
+    (apply #'concat result)))
 ;;;_   > allout-listify-exposed (&optional start end format)
 (defun allout-listify-exposed (&optional start end format)
 
@@ -5385,7 +5365,7 @@ header and body.  The elements of that list are:
       ;; Put the list with first at front, to last at back:
       (nreverse result))))
 
-(define-obsolete-function-alias 'allout-region-active-p 'region-active-p 
"28.1")
+(define-obsolete-function-alias 'allout-region-active-p #'region-active-p 
"28.1")
 
 ;;_   > allout-process-exposed (&optional func from to frombuf
 ;;;                                        tobuf format)
@@ -5502,7 +5482,7 @@ alternate presentation format for the outline:
         (beg (if arg (allout-back-to-current-heading) (point-min)))
         (end (if arg (allout-end-of-current-subtree) (point-max)))
         (buf (current-buffer))
-        (start-list ()))
+        ) ;; (start-list ())
     (if (eq format 'flat)
        (setq format (if arg (save-excursion
                                   (goto-char beg)
@@ -5514,7 +5494,7 @@ alternate presentation format for the outline:
                             end
                             (current-buffer)
                             tobuf
-                            format start-list)
+                            format nil) ;; start-list
     (goto-char (point-min))
     (pop-to-buffer buf)
     (goto-char start-pt)))
@@ -5626,11 +5606,12 @@ environment.  Leaves point at the end of the line."
        (begindoc "\\begin{document}\n\\begin{center}\n")
        (title (format "%s%s%s%s"
                       "\\titlecmd{"
-                      (allout-latex-verb-quote (if allout-title
-                                               (condition-case nil
-                                                   (eval allout-title)
-                                                 (error "<unnamed buffer>"))
-                                             "Unnamed Outline"))
+                      (allout-latex-verb-quote
+                       (if allout-title
+                           (condition-case nil
+                               (eval allout-title t)
+                             (error "<unnamed buffer>"))
+                         "Unnamed Outline"))
                       "}\n"
                       "\\end{center}\n\n"))
        (hsize "\\hsize = 7.5 true in\n")
@@ -6223,7 +6204,7 @@ save.  See `allout-encrypt-unencrypted-on-saves' for more 
info."
 ;;;_   > outlineify-sticky ()
 ;; outlinify-sticky is correct spelling; provide this alias for sticklers:
 ;;;###autoload
-(defalias 'outlinify-sticky 'outlineify-sticky)
+(defalias 'outlinify-sticky #'outlineify-sticky)
 ;;;###autoload
 (defun outlineify-sticky (&optional _arg)
   "Activate outline mode and establish file var so it is started subsequently.
@@ -6445,7 +6426,7 @@ If BEG is bigger than END we return 0."
 ;;;_   > allout-format-quote (string)
 (defun allout-format-quote (string)
   "Return a copy of string with all \"%\" characters doubled."
-  (apply 'concat
+  (apply #'concat
          (mapcar (lambda (char) (if (= char ?%) "%%" (char-to-string char)))
                  string)))
 (define-obsolete-function-alias 'allout-flatten #'flatten-tree "27.1")
diff --git a/lisp/ansi-color.el b/lisp/ansi-color.el
index e5bfccd..44dc035 100644
--- a/lisp/ansi-color.el
+++ b/lisp/ansi-color.el
@@ -429,7 +429,8 @@ being deleted."
         ;; positions that overlap regions previously colored; these
         ;; `codes' should not be applied to that overlap, so we need
         ;; to know where they should really start.
-       (setq ansi-color-context-region (if codes (list codes end-marker)))))
+       (setq ansi-color-context-region
+              (if codes (list codes (copy-marker (point)))))))
     ;; Clean up our temporary markers.
     (unless (eq start-marker (cadr ansi-color-context-region))
       (set-marker start-marker nil))
diff --git a/lisp/arc-mode.el b/lisp/arc-mode.el
index 6c9ceb0..83c5161 100644
--- a/lisp/arc-mode.el
+++ b/lisp/arc-mode.el
@@ -660,11 +660,11 @@ Does not signal an error if optional argument NOERROR is 
non-nil."
 (defun archive-mode (&optional force)
   "Major mode for viewing an archive file in a dired-like way.
 You can move around using the usual cursor motion commands.
-Letters no longer insert themselves.
-Type `e' to pull a file out of the archive and into its own buffer;
+Letters no longer insert themselves.\\<archive-mode-map>
+Type \\[archive-extract] to pull a file out of the archive and into its own 
buffer;
 or click mouse-2 on the file's line in the archive mode buffer.
 
-If you edit a sub-file of this archive (as with the `e' command) and
+If you edit a sub-file of this archive (as with the \\[archive-extract] 
command) and
 save it, the contents of that buffer will be saved back into the
 archive.
 
diff --git a/lisp/auth-source-pass.el b/lisp/auth-source-pass.el
index 39db1a7..a7b959c 100644
--- a/lisp/auth-source-pass.el
+++ b/lisp/auth-source-pass.el
@@ -27,16 +27,18 @@
 
 ;;; Commentary:
 
-;; Integrates password-store (http://passwordstore.org/) within
+;; Integrates password-store (https://passwordstore.org/) within
 ;; auth-source.
 
 ;;; Code:
 
 (require 'seq)
-(eval-when-compile (require 'subr-x))
 (require 'cl-lib)
 (require 'auth-source)
 (require 'url-parse)
+;; Use `eval-when-compile' after the other `require's to avoid spurious
+;; "might not be defined at runtime" warnings.
+(eval-when-compile (require 'subr-x))
 
 (defgroup auth-source-pass nil
   "password-store integration within auth-source."
@@ -123,7 +125,7 @@ ENTRY is the name of a password-store entry.
 The key used to retrieve the password is the symbol `secret'.
 
 The convention used as the format for a password-store file is
-the following (see http://www.passwordstore.org/#organization):
+the following (see https://www.passwordstore.org/#organization):
 
 secret
 key1: value1
diff --git a/lisp/auth-source.el b/lisp/auth-source.el
index 14cae8a..2516b4b 100644
--- a/lisp/auth-source.el
+++ b/lisp/auth-source.el
@@ -162,7 +162,7 @@ let-binding."
 (defvar auth-source-creation-prompts nil
   "Default prompts for token values.  Usually let-bound.")
 
-(make-obsolete 'auth-source-hide-passwords nil "Emacs 24.1")
+(make-obsolete 'auth-source-hide-passwords nil "24.1")
 
 (defcustom auth-source-save-behavior 'ask
   "If set, auth-source will respect it for save behavior."
@@ -2307,9 +2307,9 @@ See `auth-source-search' for details on SPEC."
 
 ;; deprecate the old interface
 (make-obsolete 'auth-source-user-or-password
-               'auth-source-search "Emacs 24.1")
+               'auth-source-search "24.1")
 (make-obsolete 'auth-source-forget-user-or-password
-               'auth-source-forget "Emacs 24.1")
+               'auth-source-forget "24.1")
 
 (defun auth-source-user-or-password
   (mode host port &optional username create-missing delete-existing)
diff --git a/lisp/battery.el b/lisp/battery.el
index 77ad73d..59f6987 100644
--- a/lisp/battery.el
+++ b/lisp/battery.el
@@ -246,7 +246,7 @@ seconds."
        (add-to-list 'global-mode-string 'battery-mode-line-string t)
         (and (eq battery-status-function #'battery-upower)
              battery-upower-subscribe
-             (battery--upower-subsribe))
+             (battery--upower-subscribe))
        (setq battery-update-timer (run-at-time nil battery-update-interval
                                                 #'battery-update-handler))
        (battery-update))
@@ -634,7 +634,7 @@ Intended as a UPower PropertiesChanged signal handler."
   (mapc #'dbus-unregister-object battery--upower-signals)
   (setq battery--upower-signals ()))
 
-(defun battery--upower-subsribe ()
+(defun battery--upower-subscribe ()
   "Subscribe to UPower device change signals."
   (push (dbus-register-signal :system battery-upower-service
                               battery-upower-path
diff --git a/lisp/bindings.el b/lisp/bindings.el
index 2f4bab1..6eac528 100644
--- a/lisp/bindings.el
+++ b/lisp/bindings.el
@@ -950,6 +950,12 @@ if `inhibit-field-text-motion' is non-nil."
 ;; Richard said that we should not use C-x <uppercase letter> and I have
 ;; no idea whereas to bind it.  Any suggestion welcome.  -stef
 ;; (define-key ctl-x-map "U" 'undo-only)
+(defvar undo-repeat-map
+  (let ((map (make-sparse-keymap)))
+    (define-key map "u" 'undo)
+    map)
+  "Keymap to repeat undo key sequences `C-x u u'.  Used in `repeat-mode'.")
+(put 'undo 'repeat-map 'undo-repeat-map)
 
 (define-key esc-map "!" 'shell-command)
 (define-key esc-map "|" 'shell-command-on-region)
@@ -1036,6 +1042,17 @@ if `inhibit-field-text-motion' is non-nil."
 
 (define-key ctl-x-map "`" 'next-error)
 
+(defvar next-error-repeat-map
+  (let ((map (make-sparse-keymap)))
+    (define-key map    "n" 'next-error)
+    (define-key map "\M-n" 'next-error)
+    (define-key map    "p" 'previous-error)
+    (define-key map "\M-p" 'previous-error)
+    map)
+  "Keymap to repeat next-error key sequences.  Used in `repeat-mode'.")
+(put 'next-error 'repeat-map 'next-error-repeat-map)
+(put 'previous-error 'repeat-map 'next-error-repeat-map)
+
 (defvar goto-map (make-sparse-keymap)
   "Keymap for navigation commands.")
 (define-key esc-map "g" goto-map)
@@ -1194,7 +1211,7 @@ if `inhibit-field-text-motion' is non-nil."
 ;; (define-key global-map [kp-9]               'function-key-error)
 ;; (define-key global-map [kp-equal]   'function-key-error)
 
-;; X11R6 distinguishes these keys from the non-kp keys.
+;; X11 distinguishes these keys from the non-kp keys.
 ;; Make them behave like the non-kp keys unless otherwise bound.
 ;; FIXME: rather than list such mappings for every modifier-combination,
 ;;   we should come up with a way to do it generically, something like
@@ -1415,6 +1432,7 @@ if `inhibit-field-text-motion' is non-nil."
 
 (defvar ctl-x-x-map
   (let ((map (make-sparse-keymap)))
+    (define-key map "f" #'font-lock-update)
     (define-key map "g" #'revert-buffer)
     (define-key map "r" #'rename-buffer)
     (define-key map "u" #'rename-uniquely)
diff --git a/lisp/bookmark.el b/lisp/bookmark.el
index dcf8ff0..98797a0 100644
--- a/lisp/bookmark.el
+++ b/lisp/bookmark.el
@@ -953,7 +953,7 @@ When you have finished composing, type 
\\[bookmark-send-edited-annotation].
 (defun bookmark-send-edited-annotation ()
   "Use buffer contents as annotation for a bookmark.
 Lines beginning with `#' are ignored."
-  (interactive)
+  (interactive nil bookmark-edit-annotation-mode)
   (if (not (derived-mode-p 'bookmark-edit-annotation-mode))
       (error "Not in bookmark-edit-annotation-mode"))
   (goto-char (point-min))
@@ -1040,6 +1040,14 @@ it to the name of the bookmark currently being set, 
advancing
        (car dired-directory)))
     (t (error "Buffer not visiting a file or directory")))))
 
+(defvar bookmark--watch-already-asked-mtime nil
+  "Mtime for which we already queried about reloading.")
+
+(defun bookmark--watch-file-already-queried-p (new-mtime)
+  ;; Don't ask repeatedly if user already said "no" to reloading a
+  ;; file with this mtime:
+  (prog1 (equal new-mtime bookmark--watch-already-asked-mtime)
+    (setq bookmark--watch-already-asked-mtime new-mtime)))
 
 (defun bookmark-maybe-load-default-file ()
   "If bookmarks have not been loaded from the default place, load them."
@@ -1048,13 +1056,15 @@ it to the name of the bookmark currently being set, 
advancing
               (file-readable-p bookmark-default-file)
               (bookmark-load bookmark-default-file t t)))
         ((and bookmark-watch-bookmark-file
-              (not (equal (nth 5 (file-attributes
-                                  (car bookmark-bookmarks-timestamp)))
-                          (cdr bookmark-bookmarks-timestamp)))
-              (or (eq 'silent bookmark-watch-bookmark-file)
-                  (yes-or-no-p
-                   (format "Bookmarks %s changed on disk.  Reload? "
-                           (car bookmark-bookmarks-timestamp)))))
+              (let ((new-mtime (nth 5 (file-attributes
+                                       (car bookmark-bookmarks-timestamp))))
+                    (old-mtime (cdr bookmark-bookmarks-timestamp)))
+                (and (not (equal new-mtime old-mtime))
+                     (not (bookmark--watch-file-already-queried-p new-mtime))
+                     (or (eq 'silent bookmark-watch-bookmark-file)
+                         (yes-or-no-p
+                          (format "Bookmarks %s changed on disk.  Reload? "
+                                  (car bookmark-bookmarks-timestamp)))))))
          (bookmark-load (car bookmark-bookmarks-timestamp) t t))))
 
 (defun bookmark-maybe-sort-alist ()
@@ -1827,7 +1837,7 @@ This is used for `tabulated-list-format' in 
`bookmark-bmenu-mode'."
 (defun bookmark-bmenu-toggle-filenames (&optional show)
   "Toggle whether filenames are shown in the bookmark list.
 Optional argument SHOW means show them unconditionally."
-  (interactive)
+  (interactive nil bookmark-bmenu-mode)
   (cond
    (show
     (setq bookmark-bmenu-toggle-filenames t))
@@ -1912,14 +1922,14 @@ If the annotation does not exist, do nothing."
 
 (defun bookmark-bmenu-mark ()
   "Mark bookmark on this line to be displayed by 
\\<bookmark-bmenu-mode-map>\\[bookmark-bmenu-select]."
-  (interactive)
+  (interactive nil bookmark-bmenu-mode)
   (bookmark-bmenu-ensure-position)
   (tabulated-list-put-tag ">" t))
 
 
 (defun bookmark-bmenu-mark-all ()
   "Mark all listed bookmarks to be displayed by 
\\<bookmark-bmenu-mode-map>\\[bookmark-bmenu-select]."
-  (interactive)
+  (interactive nil bookmark-bmenu-mode)
   (save-excursion
     (goto-char (point-min))
     (bookmark-bmenu-ensure-position)
@@ -1930,7 +1940,7 @@ If the annotation does not exist, do nothing."
 (defun bookmark-bmenu-select ()
   "Select this line's bookmark; also display bookmarks marked with `>'.
 You can mark bookmarks with the 
\\<bookmark-bmenu-mode-map>\\[bookmark-bmenu-mark] or 
\\<bookmark-bmenu-mode-map>\\[bookmark-bmenu-mark-all] commands."
-  (interactive)
+  (interactive nil bookmark-bmenu-mode)
   (let ((bmrk (bookmark-bmenu-bookmark))
         (menu (current-buffer))
         (others ())
@@ -1975,7 +1985,7 @@ You can mark bookmarks with the 
\\<bookmark-bmenu-mode-map>\\[bookmark-bmenu-mar
 (defun bookmark-bmenu-save ()
   "Save the current list into a bookmark file.
 With a prefix arg, prompts for a file to save them in."
-  (interactive)
+  (interactive nil bookmark-bmenu-mode)
   (save-excursion
     (save-window-excursion
       (call-interactively 'bookmark-save)
@@ -1984,7 +1994,7 @@ With a prefix arg, prompts for a file to save them in."
 
 (defun bookmark-bmenu-load ()
   "Load the bookmark file and rebuild the bookmark menu-buffer."
-  (interactive)
+  (interactive nil bookmark-bmenu-mode)
   (bookmark-bmenu-ensure-position)
   (save-excursion
     (save-window-excursion
@@ -1994,7 +2004,7 @@ With a prefix arg, prompts for a file to save them in."
 
 (defun bookmark-bmenu-1-window ()
   "Select this line's bookmark, alone, in full frame."
-  (interactive)
+  (interactive nil bookmark-bmenu-mode)
   (bookmark-jump (bookmark-bmenu-bookmark))
   (bury-buffer (other-buffer))
   (delete-other-windows))
@@ -2002,7 +2012,7 @@ With a prefix arg, prompts for a file to save them in."
 
 (defun bookmark-bmenu-2-window ()
   "Select this line's bookmark, with previous buffer in second window."
-  (interactive)
+  (interactive nil bookmark-bmenu-mode)
   (let ((bmrk (bookmark-bmenu-bookmark))
         (menu (current-buffer))
         (pop-up-windows t))
@@ -2014,20 +2024,20 @@ With a prefix arg, prompts for a file to save them in."
 
 (defun bookmark-bmenu-this-window ()
   "Select this line's bookmark in this window."
-  (interactive)
+  (interactive nil bookmark-bmenu-mode)
   (bookmark-jump (bookmark-bmenu-bookmark)))
 
 
 (defun bookmark-bmenu-other-window ()
   "Select this line's bookmark in other window, leaving bookmark menu visible."
-  (interactive)
+  (interactive nil bookmark-bmenu-mode)
   (let ((bookmark (bookmark-bmenu-bookmark)))
     (bookmark--jump-via bookmark 'switch-to-buffer-other-window)))
 
 
 (defun bookmark-bmenu-other-frame ()
   "Select this line's bookmark in other frame."
-  (interactive)
+  (interactive nil bookmark-bmenu-mode)
   (let  ((bookmark (bookmark-bmenu-bookmark))
          (pop-up-frames t))
     (bookmark-jump-other-window bookmark)))
@@ -2035,7 +2045,7 @@ With a prefix arg, prompts for a file to save them in."
 (defun bookmark-bmenu-switch-other-window ()
   "Make the other window select this line's bookmark.
 The current window remains selected."
-  (interactive)
+  (interactive nil bookmark-bmenu-mode)
   (let ((bookmark (bookmark-bmenu-bookmark))
        (fun (lambda (b) (display-buffer b t))))
     (bookmark--jump-via bookmark fun)))
@@ -2044,7 +2054,7 @@ The current window remains selected."
   "Jump to bookmark at mouse EVENT position in other window.
 Move point in menu buffer to the position of EVENT and leave
 bookmark menu visible."
-  (interactive "e")
+  (interactive "e" bookmark-bmenu-mode)
   (with-current-buffer (window-buffer (posn-window (event-end event)))
     (save-excursion
       (goto-char (posn-point (event-end event)))
@@ -2053,20 +2063,20 @@ bookmark menu visible."
 
 (defun bookmark-bmenu-show-annotation ()
   "Show the annotation for the current bookmark in another window."
-  (interactive)
+  (interactive nil bookmark-bmenu-mode)
   (let ((bookmark (bookmark-bmenu-bookmark)))
     (bookmark-show-annotation bookmark)))
 
 
 (defun bookmark-bmenu-show-all-annotations ()
   "Show the annotation for all bookmarks in another window."
-  (interactive)
+  (interactive nil bookmark-bmenu-mode)
   (bookmark-show-all-annotations))
 
 
 (defun bookmark-bmenu-edit-annotation ()
   "Edit the annotation for the current bookmark in another window."
-  (interactive)
+  (interactive nil bookmark-bmenu-mode)
   (let ((bookmark (bookmark-bmenu-bookmark)))
     (bookmark-edit-annotation bookmark t)))
 
@@ -2074,7 +2084,7 @@ bookmark menu visible."
 (defun bookmark-bmenu-unmark (&optional backup)
   "Cancel all requested operations on bookmark on this line and move down.
 Optional BACKUP means move up."
-  (interactive "P")
+  (interactive "P" bookmark-bmenu-mode)
   ;; any flags to reset according to circumstances?  How about a
   ;; flag indicating whether this bookmark is being visited?
   ;; well, we don't have this now, so maybe later.
@@ -2085,7 +2095,7 @@ Optional BACKUP means move up."
 
 (defun bookmark-bmenu-backup-unmark ()
   "Move up and cancel all requested operations on bookmark on line above."
-  (interactive)
+  (interactive nil bookmark-bmenu-mode)
   (forward-line -1)
   (bookmark-bmenu-ensure-position)
   (bookmark-bmenu-unmark)
@@ -2095,7 +2105,7 @@ Optional BACKUP means move up."
 
 (defun bookmark-bmenu-unmark-all ()
   "Cancel all requested operations on all listed bookmarks."
-  (interactive)
+  (interactive nil bookmark-bmenu-mode)
   (save-excursion
     (goto-char (point-min))
     (bookmark-bmenu-ensure-position)
@@ -2106,7 +2116,7 @@ Optional BACKUP means move up."
 (defun bookmark-bmenu-delete ()
   "Mark bookmark on this line to be deleted.
 To carry out the deletions that you've marked, use 
\\<bookmark-bmenu-mode-map>\\[bookmark-bmenu-execute-deletions]."
-  (interactive)
+  (interactive nil bookmark-bmenu-mode)
   (bookmark-bmenu-ensure-position)
   (tabulated-list-put-tag "D" t))
 
@@ -2114,7 +2124,7 @@ To carry out the deletions that you've marked, use 
\\<bookmark-bmenu-mode-map>\\
 (defun bookmark-bmenu-delete-backwards ()
   "Mark bookmark on this line to be deleted, then move up one line.
 To carry out the deletions that you've marked, use 
\\<bookmark-bmenu-mode-map>\\[bookmark-bmenu-execute-deletions]."
-  (interactive)
+  (interactive nil bookmark-bmenu-mode)
   (bookmark-bmenu-delete)
   (forward-line -2))
 
@@ -2123,7 +2133,7 @@ To carry out the deletions that you've marked, use 
\\<bookmark-bmenu-mode-map>\\
   "Mark all listed bookmarks as to be deleted.
 To remove all deletion marks, use 
\\<bookmark-bmenu-mode-map>\\[bookmark-bmenu-unmark-all].
 To carry out the deletions that you've marked, use 
\\<bookmark-bmenu-mode-map>\\[bookmark-bmenu-execute-deletions]."
-  (interactive)
+  (interactive nil bookmark-bmenu-mode)
   (save-excursion
     (goto-char (point-min))
     (bookmark-bmenu-ensure-position)
@@ -2133,7 +2143,7 @@ To carry out the deletions that you've marked, use 
\\<bookmark-bmenu-mode-map>\\
 
 (defun bookmark-bmenu-execute-deletions ()
   "Delete bookmarks flagged `D'."
-  (interactive)
+  (interactive nil bookmark-bmenu-mode)
   (let ((reporter (make-progress-reporter "Deleting bookmarks..."))
         (o-point  (point))
         (o-str    (save-excursion
@@ -2160,7 +2170,7 @@ To carry out the deletions that you've marked, use 
\\<bookmark-bmenu-mode-map>\\
 
 (defun bookmark-bmenu-rename ()
   "Rename bookmark on current line.  Prompts for a new name."
-  (interactive)
+  (interactive nil bookmark-bmenu-mode)
   (let ((bmrk (bookmark-bmenu-bookmark))
         (thispoint (point)))
     (bookmark-rename bmrk)
@@ -2169,14 +2179,14 @@ To carry out the deletions that you've marked, use 
\\<bookmark-bmenu-mode-map>\\
 
 (defun bookmark-bmenu-locate ()
   "Display location of this bookmark.  Displays in the minibuffer."
-  (interactive)
+  (interactive nil bookmark-bmenu-mode)
   (let ((bmrk (bookmark-bmenu-bookmark)))
     (message "%s" (bookmark-location bmrk))))
 
 (defun bookmark-bmenu-relocate ()
   "Change the absolute file name of the bookmark on the current line.
 Prompt with completion for the new path."
-  (interactive)
+  (interactive nil bookmark-bmenu-mode)
   (let ((bmrk (bookmark-bmenu-bookmark))
         (thispoint (point)))
     (bookmark-relocate bmrk)
@@ -2196,7 +2206,7 @@ Prompt with completion for the new path."
 ;;;###autoload
 (defun bookmark-bmenu-search ()
   "Incremental search of bookmarks, hiding the non-matches as we go."
-  (interactive)
+  (interactive nil bookmark-bmenu-mode)
   (let ((bmk (bookmark-bmenu-bookmark))
         (timer nil))
     (unwind-protect
diff --git a/lisp/buff-menu.el b/lisp/buff-menu.el
index bb39e1f..340c926 100644
--- a/lisp/buff-menu.el
+++ b/lisp/buff-menu.el
@@ -117,8 +117,7 @@ This is set by the prefix argument to `buffer-menu' and 
related
 commands.")
 
 (defvar Buffer-menu-mode-map
-  (let ((map (make-sparse-keymap))
-       (menu-map (make-sparse-keymap)))
+  (let ((map (make-sparse-keymap)))
     (set-keymap-parent map tabulated-list-mode-map)
     (define-key map "v" 'Buffer-menu-select)
     (define-key map "2" 'Buffer-menu-2-window)
@@ -152,82 +151,63 @@ commands.")
 
     (define-key map [mouse-2] 'Buffer-menu-mouse-select)
     (define-key map [follow-link] 'mouse-face)
-
-    (define-key map [menu-bar Buffer-menu-mode] (cons (purecopy "Buffer-Menu") 
menu-map))
-    (bindings--define-key menu-map [quit]
-      '(menu-item "Quit" quit-window
-                :help "Remove the buffer menu from the display"))
-    (bindings--define-key menu-map [rev]
-      '(menu-item "Refresh" revert-buffer
-                :help "Refresh the *Buffer List* buffer contents"))
-    (bindings--define-key menu-map [s0] menu-bar-separator)
-    (bindings--define-key menu-map [tf]
-      '(menu-item "Show Only File Buffers" Buffer-menu-toggle-files-only
-                 :button (:toggle . Buffer-menu-files-only)
-                 :help "Toggle whether the current buffer-menu displays only 
file buffers"))
-    (bindings--define-key menu-map [s1] menu-bar-separator)
-    ;; FIXME: The "Select" entries could use better names...
-    (bindings--define-key menu-map [sel]
-      '(menu-item "Select Marked" Buffer-menu-select
-                :help "Select this line's buffer; also display buffers marked 
with `>'"))
-    (bindings--define-key menu-map [bm2]
-      '(menu-item "Select Two" Buffer-menu-2-window
-                :help "Select this line's buffer, with previous buffer in 
second window"))
-    (bindings--define-key menu-map [bm1]
-      '(menu-item "Select Current" Buffer-menu-1-window
-                :help "Select this line's buffer, alone, in full frame"))
-    (bindings--define-key menu-map [ow]
-      '(menu-item "Select in Other Window" Buffer-menu-other-window
-                :help "Select this line's buffer in other window, leaving 
buffer menu visible"))
-    (bindings--define-key menu-map [tw]
-      '(menu-item "Select in Current Window" Buffer-menu-this-window
-                :help "Select this line's buffer in this window"))
-    (bindings--define-key menu-map [s2] menu-bar-separator)
-    (bindings--define-key menu-map [is]
-      '(menu-item "Regexp Isearch Marked Buffers..." 
Buffer-menu-isearch-buffers-regexp
-                :help "Search for a regexp through all marked buffers using 
Isearch"))
-    (bindings--define-key menu-map [ir]
-      '(menu-item "Isearch Marked Buffers..." Buffer-menu-isearch-buffers
-                :help "Search for a string through all marked buffers using 
Isearch"))
-    (bindings--define-key menu-map [mo]
-      '(menu-item "Multi Occur Marked Buffers..." Buffer-menu-multi-occur
-                :help "Show lines matching a regexp in marked buffers using 
Occur"))
-    (bindings--define-key menu-map [s3] menu-bar-separator)
-    (bindings--define-key menu-map [by]
-      '(menu-item "Bury" Buffer-menu-bury
-                :help "Bury the buffer listed on this line"))
-    (bindings--define-key menu-map [vt]
-      '(menu-item "Set Unmodified" Buffer-menu-not-modified
-                :help "Mark buffer on this line as unmodified (no changes to 
save)"))
-    (bindings--define-key menu-map [ex]
-      '(menu-item "Execute" Buffer-menu-execute
-                :help "Save and/or delete buffers marked with s or k 
commands"))
-    (bindings--define-key menu-map [s4] menu-bar-separator)
-    (bindings--define-key menu-map [delb]
-      '(menu-item "Mark for Delete and Move Backwards" 
Buffer-menu-delete-backwards
-                :help "Mark buffer on this line to be deleted by x command and 
move up one line"))
-    (bindings--define-key menu-map [del]
-      '(menu-item "Mark for Delete" Buffer-menu-delete
-                :help "Mark buffer on this line to be deleted by x command"))
-
-    (bindings--define-key menu-map [sv]
-      '(menu-item "Mark for Save" Buffer-menu-save
-                :help "Mark buffer on this line to be saved by x command"))
-    (bindings--define-key menu-map [umk]
-      '(menu-item "Unmark" Buffer-menu-unmark
-                :help "Cancel all requested operations on buffer on this line 
and move down"))
-    (bindings--define-key menu-map [umkab]
-      '(menu-item "Remove marks..." Buffer-menu-unmark-all-buffers
-                  :help "Cancel a requested operation on all buffers"))
-    (bindings--define-key menu-map [umka]
-      '(menu-item "Unmark all" Buffer-menu-unmark-all
-                  :help "Cancel all requested operations on buffers"))
-    (bindings--define-key menu-map [mk]
-      '(menu-item "Mark" Buffer-menu-mark
-                :help "Mark buffer on this line for being displayed by v 
command"))
     map)
   "Local keymap for `Buffer-menu-mode' buffers.")
 
+(easy-menu-define Buffer-menu-mode-menu Buffer-menu-mode-map
+  "Menu for `Buffer-menu-mode' buffers."
+  '("Buffer-Menu"
+    ["Mark" Buffer-menu-mark
+     :help "Mark buffer on this line for being displayed by v command"]
+    ["Unmark all" Buffer-menu-unmark-all
+     :help "Cancel all requested operations on buffers"]
+    ["Remove marks..." Buffer-menu-unmark-all-buffers
+     :help "Cancel a requested operation on all buffers"]
+    ["Unmark" Buffer-menu-unmark
+     :help "Cancel all requested operations on buffer on this line and move 
down"]
+    ["Mark for Save" Buffer-menu-save
+     :help "Mark buffer on this line to be saved by x command"]
+    ["Mark for Delete" Buffer-menu-delete
+     :help "Mark buffer on this line to be deleted by x command"]
+    ["Mark for Delete and Move Backwards" Buffer-menu-delete-backwards
+     :help "Mark buffer on this line to be deleted by x command and move up 
one line"]
+    "---"
+    ["Execute" Buffer-menu-execute
+     :help "Save and/or delete buffers marked with s or k commands"]
+    ["Set Unmodified" Buffer-menu-not-modified
+     :help "Mark buffer on this line as unmodified (no changes to save)"]
+    ["Bury" Buffer-menu-bury
+     :help "Bury the buffer listed on this line"]
+    "---"
+    ["Multi Occur Marked Buffers..." Buffer-menu-multi-occur
+     :help "Show lines matching a regexp in marked buffers using Occur"]
+    ["Isearch Marked Buffers..." Buffer-menu-isearch-buffers
+     :help "Search for a string through all marked buffers using Isearch"]
+    ["Regexp Isearch Marked Buffers..." Buffer-menu-isearch-buffers-regexp
+     :help "Search for a regexp through all marked buffers using Isearch"]
+    "---"
+    ;; FIXME: The "Select" entries could use better names...
+    ["Select in Current Window" Buffer-menu-this-window
+     :help "Select this line's buffer in this window"]
+    ["Select in Other Window" Buffer-menu-other-window
+     :help "Select this line's buffer in other window, leaving buffer menu 
visible"]
+    ["Select Current" Buffer-menu-1-window
+     :help "Select this line's buffer, alone, in full frame"]
+    ["Select Two" Buffer-menu-2-window
+     :help "Select this line's buffer, with previous buffer in second window"]
+    ["Select Marked" Buffer-menu-select
+     :help "Select this line's buffer; also display buffers marked with `>'"]
+    "---"
+    ["Show Only File Buffers" Buffer-menu-toggle-files-only
+     :help "Toggle whether the current buffer-menu displays only file buffers"
+     :style toggle
+     :selected Buffer-menu-files-only]
+    "---"
+    ["Refresh" revert-buffer
+     :help "Refresh the *Buffer List* buffer contents"]
+    ["Quit" quit-window
+     :help "Remove the buffer menu from the display"]))
+
 (define-derived-mode Buffer-menu-mode tabulated-list-mode "Buffer Menu"
   "Major mode for Buffer Menu buffers.
 The Buffer Menu is invoked by the commands \\[list-buffers],
@@ -268,6 +248,7 @@ In Buffer Menu mode, the following commands are defined:
 \\[revert-buffer]    Update the list of buffers.
 \\[Buffer-menu-toggle-files-only]    Toggle whether the menu displays only 
file buffers.
 \\[Buffer-menu-bury]    Bury the buffer listed on this line."
+  :interactive nil
   (setq-local buffer-stale-function
               (lambda (&optional _noconfirm) 'fast))
   (add-hook 'tabulated-list-revert-hook 'list-buffers--refresh nil t))
@@ -328,7 +309,7 @@ ARG, show only buffers that are visiting files."
   "Toggle whether the current buffer-menu displays only file buffers.
 With a positive ARG, display only file buffers.  With zero or
 negative ARG, display other buffers as well."
-  (interactive "P")
+  (interactive "P" Buffer-menu-mode)
   (setq Buffer-menu-files-only
        (cond ((not arg) (not Buffer-menu-files-only))
              ((> (prefix-numeric-value arg) 0) t)))
@@ -337,7 +318,8 @@ negative ARG, display other buffers as well."
             "Showing all non-internal buffers."))
   (revert-buffer))
 
-(defalias 'Buffer-menu-sort 'tabulated-list-sort)
+(define-obsolete-function-alias 'Buffer-menu-sort 'tabulated-list-sort
+  "28.1")
 
 
 (defun Buffer-menu-buffer (&optional error-if-non-existent-p)
@@ -373,14 +355,14 @@ is nil or omitted, and signal an error otherwise."
 (defun Buffer-menu-mark ()
   "Mark the Buffer menu entry at point for later display.
 It will be displayed by the \\<Buffer-menu-mode-map>\\[Buffer-menu-select] 
command."
-  (interactive)
+  (interactive nil Buffer-menu-mode)
   (tabulated-list-set-col 0 (char-to-string Buffer-menu-marker-char) t)
   (forward-line))
 
 (defun Buffer-menu-unmark (&optional backup)
   "Cancel all requested operations on buffer on this line and move down.
 Optional prefix arg means move up."
-  (interactive "P")
+  (interactive "P" Buffer-menu-mode)
   (Buffer-menu--unmark)
   (forward-line (if backup -1 1)))
 
@@ -388,7 +370,7 @@ Optional prefix arg means move up."
   "Cancel a requested operation on all buffers.
 MARK is the character to flag the operation on the buffers.
 When called interactively prompt for MARK;  RET remove all marks."
-  (interactive "cRemove marks (RET means all):")
+  (interactive "cRemove marks (RET means all):" Buffer-menu-mode)
   (save-excursion
     (goto-char (point-min))
     (when (tabulated-list-header-overlay-p)
@@ -403,12 +385,12 @@ When called interactively prompt for MARK;  RET remove 
all marks."
 
 (defun Buffer-menu-unmark-all ()
   "Cancel all requested operations on buffers."
-  (interactive)
+  (interactive nil Buffer-menu-mode)
   (Buffer-menu-unmark-all-buffers ?\r))
 
 (defun Buffer-menu-backup-unmark ()
   "Move up and cancel all requested operations on buffer on line above."
-  (interactive)
+  (interactive nil Buffer-menu-mode)
   (forward-line -1)
   (Buffer-menu--unmark))
 
@@ -427,7 +409,7 @@ will delete it.
 
 If prefix argument ARG is non-nil, it specifies the number of
 buffers to delete; a negative ARG means to delete backwards."
-  (interactive "p")
+  (interactive "p" Buffer-menu-mode)
   (if (or (null arg) (= arg 0))
       (setq arg 1))
   (while (> arg 0)
@@ -446,14 +428,14 @@ buffers to delete; a negative ARG means to delete 
backwards."
 A subsequent \\<Buffer-menu-mode-map>`\\[Buffer-menu-execute]'
 command will delete the marked buffer.  Prefix ARG means move
 that many lines."
-  (interactive "p")
+  (interactive "p" Buffer-menu-mode)
   (Buffer-menu-delete (- (or arg 1))))
 
 (defun Buffer-menu-save ()
   "Mark the buffer on this Buffer Menu line for saving.
 A subsequent \\<Buffer-menu-mode-map>`\\[Buffer-menu-execute]' command
 will save it."
-  (interactive)
+  (interactive nil Buffer-menu-mode)
   (when (Buffer-menu-buffer)
     (tabulated-list-set-col 2 "S" t)
     (forward-line 1)))
@@ -462,7 +444,7 @@ will save it."
   "Mark the buffer on this line as unmodified (no changes to save).
 If ARG is non-nil (interactively, with a prefix argument), mark
 it as modified."
-  (interactive "P")
+  (interactive "P" Buffer-menu-mode)
   (with-current-buffer (Buffer-menu-buffer t)
     (set-buffer-modified-p arg))
   (tabulated-list-set-col 2 (if arg "*" " ") t))
@@ -471,7 +453,7 @@ it as modified."
   "Save and/or delete marked buffers in the Buffer Menu.
 Buffers marked with \\<Buffer-menu-mode-map>`\\[Buffer-menu-save]' are saved.
 Buffers marked with \\<Buffer-menu-mode-map>`\\[Buffer-menu-delete]' are 
deleted."
-  (interactive)
+  (interactive nil Buffer-menu-mode)
   (save-excursion
     (Buffer-menu-beginning)
     (while (not (eobp))
@@ -502,7 +484,7 @@ You can mark buffers with the 
\\<Buffer-menu-mode-map>`\\[Buffer-menu-mark]' com
 
 This command deletes and replaces all the previously existing windows
 in the selected frame, and will remove any marks."
-  (interactive)
+  (interactive nil Buffer-menu-mode)
   (let* ((this-buffer (Buffer-menu-buffer t))
         (menu-buffer (current-buffer))
         (others (delq this-buffer (Buffer-menu-marked-buffers t)))
@@ -533,23 +515,23 @@ If UNMARK is non-nil, unmark them."
 
 (defun Buffer-menu-isearch-buffers ()
   "Search for a string through all marked buffers using Isearch."
-  (interactive)
+  (interactive nil Buffer-menu-mode)
   (multi-isearch-buffers (Buffer-menu-marked-buffers)))
 
 (defun Buffer-menu-isearch-buffers-regexp ()
   "Search for a regexp through all marked buffers using Isearch."
-  (interactive)
+  (interactive nil Buffer-menu-mode)
   (multi-isearch-buffers-regexp (Buffer-menu-marked-buffers)))
 
 (defun Buffer-menu-multi-occur (regexp &optional nlines)
   "Show all lines in marked buffers containing a match for a regexp."
-  (interactive (occur-read-primary-args))
+  (interactive (occur-read-primary-args) Buffer-menu-mode)
   (multi-occur (Buffer-menu-marked-buffers) regexp nlines))
 
 
 (defun Buffer-menu-visit-tags-table ()
   "Visit the tags table in the buffer on this line.  See `visit-tags-table'."
-  (interactive)
+  (interactive nil Buffer-menu-mode)
   (let ((file (buffer-file-name (Buffer-menu-buffer t))))
     (if file
        (visit-tags-table file)
@@ -557,30 +539,30 @@ If UNMARK is non-nil, unmark them."
 
 (defun Buffer-menu-1-window ()
   "Select this line's buffer, alone, in full frame."
-  (interactive)
+  (interactive nil Buffer-menu-mode)
   (switch-to-buffer (Buffer-menu-buffer t))
   (bury-buffer (other-buffer))
   (delete-other-windows))
 
 (defun Buffer-menu-this-window ()
   "Select this line's buffer in this window."
-  (interactive)
+  (interactive nil Buffer-menu-mode)
   (switch-to-buffer (Buffer-menu-buffer t)))
 
 (defun Buffer-menu-other-window ()
   "Select this line's buffer in other window, leaving buffer menu visible."
-  (interactive)
+  (interactive nil Buffer-menu-mode)
   (switch-to-buffer-other-window (Buffer-menu-buffer t)))
 
 (defun Buffer-menu-switch-other-window ()
   "Make the other window select this line's buffer.
 The current window remains selected."
-  (interactive)
+  (interactive nil Buffer-menu-mode)
   (display-buffer (Buffer-menu-buffer t) t))
 
 (defun Buffer-menu-2-window ()
   "Select this line's buffer, with previous buffer in second window."
-  (interactive)
+  (interactive nil Buffer-menu-mode)
   (let ((buff (Buffer-menu-buffer t))
        (menu (current-buffer)))
     (delete-other-windows)
@@ -591,7 +573,7 @@ The current window remains selected."
 (defun Buffer-menu-toggle-read-only ()
   "Toggle read-only status of buffer on this line.
 This behaves like invoking \\[read-only-mode] in that buffer."
-  (interactive)
+  (interactive nil Buffer-menu-mode)
   (let ((read-only
          (with-current-buffer (Buffer-menu-buffer t)
            (read-only-mode 'toggle)
@@ -600,7 +582,7 @@ This behaves like invoking \\[read-only-mode] in that 
buffer."
 
 (defun Buffer-menu-bury ()
   "Bury the buffer listed on this line."
-  (interactive)
+  (interactive nil Buffer-menu-mode)
   (let ((buffer (tabulated-list-get-id)))
     (cond ((null buffer))
          ((buffer-live-p buffer)
@@ -616,12 +598,12 @@ This behaves like invoking \\[read-only-mode] in that 
buffer."
 
 (defun Buffer-menu-view ()
   "View this line's buffer in View mode."
-  (interactive)
+  (interactive nil Buffer-menu-mode)
   (view-buffer (Buffer-menu-buffer t)))
 
 (defun Buffer-menu-view-other-window ()
   "View this line's buffer in View mode in another window."
-  (interactive)
+  (interactive nil Buffer-menu-mode)
   (view-buffer-other-window (Buffer-menu-buffer t)))
 
 ;;; Functions for populating the Buffer Menu.
@@ -646,7 +628,7 @@ means list those buffers and no others."
 
 (defun Buffer-menu-mouse-select (event)
   "Select the buffer whose line you click on."
-  (interactive "e")
+  (interactive "e" Buffer-menu-mode)
   (select-window (posn-window (event-end event)))
   (let ((buffer (tabulated-list-get-id (posn-point (event-end event)))))
     (when (buffer-live-p buffer)
diff --git a/lisp/button.el b/lisp/button.el
index 043de8e..69d7054 100644
--- a/lisp/button.el
+++ b/lisp/button.el
@@ -472,8 +472,8 @@ mouse event is used.
 If there's no button at POS, do nothing and return nil, otherwise
 return t.
 
-To get a description of what function will called when pushing a
-butting, use the `button-describe' command."
+To get a description of the function that will be invoked when
+pushing a button, use the `button-describe' command."
   (interactive
    (list (if (integerp last-command-event) (point) last-command-event)))
   (if (and (not (integerp pos)) (eventp pos))
diff --git a/lisp/calc/calc-ext.el b/lisp/calc/calc-ext.el
index f4ddb84..24781ed 100644
--- a/lisp/calc/calc-ext.el
+++ b/lisp/calc/calc-ext.el
@@ -2565,9 +2565,9 @@ If X is not an error form, return 1."
 ;;; True if A is numerically equal to the integer B.  [P N S] [Public]
 ;;; B must not be a multiple of 10.
 (defun math-equal-int (a b)
-  (or (eq a b)
+  (or (eql a b)
       (and (eq (car-safe a) 'float)
-          (eq (nth 1 a) b)
+          (eql (nth 1 a) b)
           (= (nth 2 a) 0))))
 
 
diff --git a/lisp/calc/calc-menu.el b/lisp/calc/calc-menu.el
index 16cca05..ac14e36 100644
--- a/lisp/calc/calc-menu.el
+++ b/lisp/calc/calc-menu.el
@@ -781,7 +781,7 @@
                :active (>= (calc-stack-size) 2)
                :help "The cross product in R^3"]
               ["(2:) dot (1:)"
-               calc-mult
+               calc-times
                :keys "*"
                :active (>= (calc-stack-size) 2)
                :help "The dot product"]
diff --git a/lisp/calc/calc-prog.el b/lisp/calc/calc-prog.el
index 3097b09..dd22145 100644
--- a/lisp/calc/calc-prog.el
+++ b/lisp/calc/calc-prog.el
@@ -1985,22 +1985,37 @@ Redefine the corresponding command."
                      (cons 'quote
                            (math-define-lambda (nth 1 exp) math-exp-env))
                    exp))
-                ((memq func '(let let* for foreach))
-                 (let ((head (nth 1 exp))
-                       (body (cdr (cdr exp))))
-                   (if (memq func '(let let*))
-                       ()
-                     (setq func (cdr (assq func '((for . math-for)
-                                                  (foreach . math-foreach)))))
-                     (if (not (listp (car head)))
-                         (setq head (list head))))
-                   (macroexpand
-                    (cons func
-                          (cons (math-define-let head)
-                                (math-define-body body
-                                                  (nconc
-                                                   (math-define-let-env head)
-                                                   math-exp-env)))))))
+                 ((eq func 'let)
+                  (let ((bindings (nth 1 exp))
+                        (body (cddr exp)))
+                    `(let ,(math-define-let bindings)
+                       ,@(math-define-body
+                          body (append (math-define-let-env bindings)
+                                       math-exp-env)))))
+                 ((eq func 'let*)
+                  ;; Rewrite in terms of `let'.
+                  (let ((bindings (nth 1 exp))
+                        (body (cddr exp)))
+                    (math-define-exp
+                     (if (> (length bindings) 1)
+                         `(let ,(list (car bindings))
+                            (let* ,(cdr bindings) ,@body))
+                       `(let ,bindings ,@body)))))
+                ((memq func '(for foreach))
+                 (let ((bindings (nth 1 exp))
+                       (body (cddr exp)))
+                    (if (> (length bindings) 1)
+                        ;; Rewrite as nested loops.
+                        (math-define-exp
+                         `(,func ,(list (car bindings))
+                                 (,func ,(cdr bindings) ,@body)))
+                      (let ((mac (cdr (assq func '((for . math-for)
+                                                   (foreach . 
math-foreach))))))
+                        (macroexpand
+                         `(,mac ,(math-define-let bindings)
+                                ,@(math-define-body
+                                   body (append (math-define-let-env bindings)
+                                               math-exp-env))))))))
                 ((and (memq func '(setq setf))
                       (math-complicated-lhs (cdr exp)))
                  (if (> (length exp) 3)
@@ -2017,7 +2032,7 @@ Redefine the corresponding command."
                        (math-define-cond (cdr exp))))
                 ((and (consp func)   ; ('spam a b) == force use of plain spam
                       (eq (car func) 'quote))
-                 (cons func (math-define-list (cdr exp))))
+                 (cons (cadr func) (math-define-list (cdr exp))))
                 ((symbolp func)
                  (let ((args (math-define-list (cdr exp)))
                        (prim (assq func math-prim-funcs)))
@@ -2276,20 +2291,16 @@ Redefine the corresponding command."
 
 (defun math-handle-foreach (head body)
   (let ((var (nth 0 (car head)))
+        (loop-var (gensym "foreach"))
        (data (nth 1 (car head)))
        (body (if (cdr head)
                  (list (math-handle-foreach (cdr head) body))
                body)))
-    (cons 'let
-         (cons (list (list var data))
-               (list
-                (cons 'while
-                      (cons var
-                            (append body
-                                    (list (list 'setq
-                                                var
-                                                (list 'cdr var)))))))))))
-
+    `(let ((,loop-var ,data))
+       (while ,loop-var
+         (let ((,var (car ,loop-var)))
+           ,@(append body
+                     `((setq ,loop-var (cdr ,loop-var)))))))))
 
 (defun math-body-refers-to (body thing)
   (or (equal body thing)
diff --git a/lisp/calc/calc-sel.el b/lisp/calc/calc-sel.el
index 2b317ac..18fd483 100644
--- a/lisp/calc/calc-sel.el
+++ b/lisp/calc/calc-sel.el
@@ -486,8 +486,8 @@
 
 (defun calc-replace-sub-formula (expr rsf-old rsf-new)
   (let ((calc-rsf-old rsf-old)
-        (calc-rsf-new (calc-encase-atoms rsf-new))))
-  (calc-replace-sub-formula-rec expr))
+        (calc-rsf-new (calc-encase-atoms rsf-new)))
+    (calc-replace-sub-formula-rec expr)))
 
 (defun calc-replace-sub-formula-rec (expr)
   (cond ((eq expr calc-rsf-old) calc-rsf-new)
diff --git a/lisp/calc/calc-yank.el b/lisp/calc/calc-yank.el
index e5f0523..762adbd 100644
--- a/lisp/calc/calc-yank.el
+++ b/lisp/calc/calc-yank.el
@@ -639,7 +639,7 @@ Interactively, reads the register using 
`register-read-with-preview'."
   (calc-slow-wrapper
    (when (eq n 0)
      (setq n (calc-stack-size)))
-   (let* ((flag nil)
+   (let* (;; (flag nil)
          (allow-ret (> n 1))
          (list (math-showing-full-precision
                 (mapcar (if (> n 1)
@@ -651,7 +651,8 @@ Interactively, reads the register using 
`register-read-with-preview'."
                         (if (> n 0)
                             (calc-top-list n)
                           (calc-top-list 1 (- n)))))))
-     (calc--edit-mode (lambda () (calc-finish-stack-edit (or flag n))) 
allow-ret)
+     (calc--edit-mode (lambda () (calc-finish-stack-edit n)) ;; (or flag n)
+                      allow-ret)
      (while list
        (insert (car list) "\n")
        (setq list (cdr list)))))
diff --git a/lisp/calculator.el b/lisp/calculator.el
index b4c0075..6dd8d9a 100644
--- a/lisp/calculator.el
+++ b/lisp/calculator.el
@@ -20,23 +20,18 @@
 ;; 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:
-;;
+
 ;; A calculator for Emacs.
 ;; Why should you reach for your mouse to get xcalc (calc.exe, gcalc or
 ;; whatever), when you have Emacs running already?
 ;;
-;; If this is not part of your Emacs distribution, then simply bind
-;; `calculator' to a key and make it an autoloaded function, e.g.:
-;;   (autoload 'calculator "calculator"
-;;     "Run the Emacs calculator." t)
+;; You can bind this to a key by adding this to your Init file:
+;;
 ;;   (global-set-key [(control return)] 'calculator)
 ;;
 ;; Written by Eli Barzilay, eli@barzilay.org
-;;
 
-;;;=====================================================================
 ;;; Customization:
 
 (defgroup calculator nil
@@ -50,19 +45,16 @@
   "Run `calculator' electrically, in the echo area.
 Electric mode saves some place but changes the way you interact with the
 calculator."
-  :type  'boolean
-  :group 'calculator)
+  :type  'boolean)
 
 (defcustom calculator-use-menu t
   "Make `calculator' create a menu.
 Note that this requires easymenu.  Must be set before loading."
-  :type  'boolean
-  :group 'calculator)
+  :type  'boolean)
 
 (defcustom calculator-bind-escape nil
   "If non-nil, set escape to exit the calculator."
-  :type  'boolean
-  :group 'calculator)
+  :type  'boolean)
 
 (defcustom calculator-unary-style 'postfix
   "Value is either `prefix' or `postfix'.
@@ -75,44 +67,38 @@ This determines the default behavior of unary operators."
 It should contain a \"%s\" somewhere that will indicate the i/o radixes;
 this will be a two-character string as described in the documentation
 for `calculator-mode'."
-  :type  'string
-  :group 'calculator)
+  :type  'string)
 
 (defcustom calculator-number-digits 3
   "The calculator's number of digits used for standard display.
 Used by the `calculator-standard-display' function - it will use the
 format string \"%.NC\" where this number is N and C is a character given
 at runtime."
-  :type  'integer
-  :group 'calculator)
+  :type  'integer)
 
 (defcustom calculator-radix-grouping-mode t
   "Use digit grouping in radix output mode.
 If this is set, chunks of `calculator-radix-grouping-digits' characters
 will be separated by `calculator-radix-grouping-separator' when in radix
 output mode is active (determined by `calculator-output-radix')."
-  :type  'boolean
-  :group 'calculator)
+  :type  'boolean)
 
 (defcustom calculator-radix-grouping-digits 4
   "The number of digits used for grouping display in radix modes.
 See `calculator-radix-grouping-mode'."
-  :type  'integer
-  :group 'calculator)
+  :type  'integer)
 
 (defcustom calculator-radix-grouping-separator "'"
   "The separator used in radix grouping display.
 See `calculator-radix-grouping-mode'."
-  :type  'string
-  :group 'calculator)
+  :type  'string)
 
 (defcustom calculator-remove-zeros t
   "Non-nil value means delete all redundant zero decimal digits.
 If this value is not t and not nil, redundant zeros are removed except
 for one.
 Used by the `calculator-remove-zeros' function."
-  :type  '(choice (const t) (const leave-decimal) (const nil))
-  :group 'calculator)
+  :type  '(choice (const t) (const leave-decimal) (const nil)))
 
 (defcustom calculator-displayer '(std ?n)
   "A displayer specification for numerical values.
@@ -135,8 +121,7 @@ a character and G is an optional boolean, in this case the
 arguments."
   :type '(choice (function) (string) (sexp)
                  (list (const std) character)
-                 (list (const std) character boolean))
-  :group 'calculator)
+                 (list (const std) character boolean)))
 
 (defcustom calculator-displayers
   '(((std ?n) "Standard display, decimal point or scientific")
@@ -152,15 +137,13 @@ specification is the same as the values that can be 
stored in
 `calculator-displayer'.
 
 `calculator-rotate-displayer' rotates this list."
-  :type  'sexp
-  :group 'calculator)
+  :type  'sexp)
 
 (defcustom calculator-paste-decimals t
   "If non-nil, convert pasted integers so they have a decimal point.
 This makes it possible to paste big integers since they will be read as
 floats, otherwise the Emacs reader will fail on them."
-  :type  'boolean
-  :group 'calculator)
+  :type  'boolean)
 (make-obsolete-variable 'calculator-paste-decimals
                         "it is no longer used." "26.1")
 
@@ -169,14 +152,12 @@ floats, otherwise the Emacs reader will fail on them."
 `calculator-displayer', to format a string before copying it with
 `calculator-copy'.  If nil, then `calculator-displayer's normal value is
 used."
-  :type  'boolean
-  :group 'calculator)
+  :type  'boolean)
 
 (defcustom calculator-2s-complement nil
   "If non-nil, show negative numbers in 2s complement in radix modes.
 Otherwise show as a negative number."
-  :type  'boolean
-  :group 'calculator)
+  :type  'boolean)
 
 (defcustom calculator-mode-hook nil
   "List of hook functions for `calculator-mode' to run.
@@ -184,8 +165,7 @@ Note: if `calculator-electric-mode' is on, then this hook 
will get
 activated in the minibuffer -- in that case it should not do much more
 than local key settings and other effects that will change things
 outside the scope of calculator related code."
-  :type  'hook
-  :group 'calculator)
+  :type  'hook)
 
 (defcustom calculator-user-registers nil
   "An association list of user-defined register bindings.
@@ -200,8 +180,7 @@ before you load calculator."
            (when (boundp 'calculator-registers)
              (setq calculator-registers
                    (append val calculator-registers)))
-           (setq calculator-user-registers val))
-  :group 'calculator)
+           (setq calculator-user-registers val)))
 
 (defcustom calculator-user-operators nil
   "A list of additional operators.
@@ -234,8 +213,7 @@ Examples:
 
   Note that this will be either postfix or prefix, according to
   `calculator-unary-style'."
-  :type  '(repeat (list string symbol sexp integer integer))
-  :group 'calculator)
+  :type  '(repeat (list string symbol sexp integer integer)))
 
 ;;;=====================================================================
 ;;; Code:
@@ -313,7 +291,7 @@ user-defined operators, use `calculator-user-operators' 
instead.")
 5. The function's precedence -- should be in the range of 1 (lowest) to
    9 (highest) (optional, defaults to 1);
 
-It it possible have a unary prefix version of a binary operator if it
+It is possible have a unary prefix version of a binary operator if it
 comes later in this list.  If the list begins with the symbol `nobind',
 then no key binding will take place -- this is only used for predefined
 keys.
diff --git a/lisp/calendar/appt.el b/lisp/calendar/appt.el
index 281b89e..29bcd6d 100644
--- a/lisp/calendar/appt.el
+++ b/lisp/calendar/appt.el
@@ -700,7 +700,7 @@ ARG is positive, otherwise off."
   (let ((appt-active appt-timer))
     (setq appt-active (if arg (> (prefix-numeric-value arg) 0)
                         (not appt-active)))
-    (remove-hook 'write-file-functions #'appt-update-list 'local)
+    (remove-hook 'write-file-functions #'appt-update-list)
     (or global-mode-string (setq global-mode-string '("")))
     (delq 'appt-mode-string global-mode-string)
     (when appt-timer
@@ -708,7 +708,7 @@ ARG is positive, otherwise off."
       (setq appt-timer nil))
     (if appt-active
         (progn
-          (add-hook 'write-file-functions #'appt-update-list nil t)
+          (add-hook 'write-file-functions #'appt-update-list)
           (setq appt-timer (run-at-time t 60 #'appt-check)
                 global-mode-string
                 (append global-mode-string '(appt-mode-string)))
diff --git a/lisp/calendar/cal-bahai.el b/lisp/calendar/cal-bahai.el
index c2e4205..ff419c7 100644
--- a/lisp/calendar/cal-bahai.el
+++ b/lisp/calendar/cal-bahai.el
@@ -27,7 +27,7 @@
 ;; This collection of functions implements the features of calendar.el
 ;; and diary-lib.el that deal with the Bahá’í calendar.
 
-;; The Bahá’í (http://www.bahai.org) calendar system is based on a
+;; The Bahá’í (https://www.bahai.org) calendar system is based on a
 ;; solar cycle of 19 months with 19 days each.  The four remaining
 ;; "intercalary" days are called the Ayyám-i-Há (days of Há), and are
 ;; placed between the 18th and 19th months.  They are meant as a time
diff --git a/lisp/calendar/icalendar.el b/lisp/calendar/icalendar.el
index 1d7de4a..d9cd21e 100644
--- a/lisp/calendar/icalendar.el
+++ b/lisp/calendar/icalendar.el
@@ -66,7 +66,7 @@
 ;;  0.02:
 ;;  - Should work in XEmacs now.  Thanks to Len Trigg for the XEmacs patches!
 ;;  - Added exporting from Emacs diary to ical.
-;;  - Some bugfixes, after testing with calendars from http://icalshare.com.
+;;  - Some bugfixes, after testing with calendars from https://icalshare.com.
 ;;  - Tested with Emacs 21.3.2 and XEmacs 21.4.12
 
 ;;  0.01: (2003-03-21)
@@ -773,9 +773,6 @@ American format: \"month day year\"."
     ;; datetime == nil
     nil))
 
-(define-obsolete-function-alias 'icalendar--datetime-to-noneuropean-date
-  'icalendar--datetime-to-american-date "icalendar 0.19")
-
 (defun icalendar--datetime-to-european-date (datetime &optional separator)
   "Convert the decoded DATETIME to European format.
 Optional argument SEPARATOR gives the separator between month,
@@ -889,12 +886,14 @@ If DAY-SHIFT is non-nil, the result is shifted by 
DAY-SHIFT days."
     (format "%04d%02d%02d" (nth 2 mdy) (nth 0 mdy) (nth 1 mdy))))
 
 
-(defun icalendar--datestring-to-isodate (datestring &optional day-shift)
+(defun icalendar--datestring-to-isodate (datestring &optional day-shift 
year-shift)
   "Convert diary-style DATESTRING to iso-style date.
 If DAY-SHIFT is non-nil, the result is shifted by DAY-SHIFT days
--- DAY-SHIFT must be either nil or an integer.  This function
-tries to figure the date style from DATESTRING itself.  If that
-is not possible it uses the current calendar date style."
+-- DAY-SHIFT must be either nil or an integer.  If YEAR-SHIFT is
+non-nil, the result is shifted by YEAR-SHIFT years -- YEAR-SHIFT
+must be either nil or an integer.  This function tries to figure
+the date style from DATESTRING itself.  If that is not possible
+it uses the current calendar date style."
   (let ((day -1) month year)
     (save-match-data
       (cond ( ;; iso-style numeric date
@@ -904,7 +903,7 @@ is not possible it uses the current calendar date style."
                                    "0?\\([1-9][0-9]?\\)")
                            datestring)
              (setq year (read (substring datestring (match-beginning 1)
-                                         (match-end 1))))
+                                            (match-end 1))))
              (setq month (read (substring datestring (match-beginning 2)
                                           (match-end 2))))
              (setq day (read (substring datestring (match-beginning 3)
@@ -967,6 +966,9 @@ is not possible it uses the current calendar date style."
                                          (match-end 3)))))
             (t
              nil)))
+    (when year-shift
+      (setq year (+ year year-shift)))
+
     (if (> day 0)
         (let ((mdy (calendar-gregorian-from-absolute
                     (+ (calendar-absolute-from-gregorian (list month day
@@ -1916,9 +1918,9 @@ entries.  ENTRY-MAIN is the first line of the diary 
entry."
       (let* ((datetime (substring entry-main (match-beginning 1)
                                   (match-end 1)))
              (startisostring (icalendar--datestring-to-isodate
-                              datetime))
+                              datetime nil 1))
              (endisostring (icalendar--datestring-to-isodate
-                            datetime 1))
+                            datetime 1 1))
              (starttimestring (icalendar--diarytime-to-isotime
                                (if (match-beginning 3)
                                    (substring entry-main
@@ -2402,8 +2404,11 @@ END-T is the event's end time in diary format."
                                       (if end-t "-" "")
                                       (or end-t ""))))
              (setq result (format
-                           "%%%%(and (diary-anniversary %s)) %s%s%s"
-                           dtstart-conv
+                           "%%%%(diary-anniversary %s) %s%s%s"
+                           (let* ((year (nth 5 dtstart-dec))
+                                  (dtstart-1y-dec (copy-sequence dtstart-dec)))
+                             (setf (nth 5 dtstart-1y-dec) (1- year))
+                             (icalendar--datetime-to-diary-date 
dtstart-1y-dec))
                            (or start-t "")
                            (if end-t "-" "") (or end-t "")))))
           ;; monthly
diff --git a/lisp/calendar/iso8601.el b/lisp/calendar/iso8601.el
index 5a109a7..44c4811 100644
--- a/lisp/calendar/iso8601.el
+++ b/lisp/calendar/iso8601.el
@@ -41,7 +41,7 @@
 ;;
 ;; The standard can be found at:
 ;;
-;; 
http://www.loc.gov/standards/datetime/iso-tc154-wg5_n0038_iso_wd_8601-1_2016-02-16.pdf
+;; 
https://www.loc.gov/standards/datetime/iso-tc154-wg5_n0038_iso_wd_8601-1_2016-02-16.pdf
 ;;
 ;; The Wikipedia page on the standard is also informative:
 ;;
diff --git a/lisp/calendar/parse-time.el b/lisp/calendar/parse-time.el
index ba7418f..aa3236c 100644
--- a/lisp/calendar/parse-time.el
+++ b/lisp/calendar/parse-time.el
@@ -29,7 +29,7 @@
 
 ;; `parse-time-string' parses a time in a string and returns a list of
 ;; values, just like `decode-time', where unspecified elements in the
-;; string are returned as nil (except unspecfied DST is returned as -1).
+;; string are returned as nil (except unspecified DST is returned as -1).
 ;; `encode-time' may be applied on these values to obtain an internal
 ;; time value.
 
diff --git a/lisp/calendar/todo-mode.el b/lisp/calendar/todo-mode.el
index 0daa153..dab468d 100644
--- a/lisp/calendar/todo-mode.el
+++ b/lisp/calendar/todo-mode.el
@@ -2279,7 +2279,7 @@ made in the number or names of categories."
        (inc (prefix-numeric-value inc))
        (buffer-read-only nil)
        ndate ntime
-        year monthname month day dayname)
+        year monthname month day) ;; dayname
     (when marked (todo--user-error-if-marked-done-item))
     (save-excursion
       (or (and marked (goto-char (point-min))) (todo-item-start))
@@ -2437,7 +2437,7 @@ made in the number or names of categories."
                            (monthname monthname)
                            (month month)
                            (day day)
-                           (dayname dayname))
+                           (dayname nil)) ;; dayname
                         (mapconcat #'eval calendar-date-display-form "")))))
            (when ndate (replace-match ndate nil nil nil 1))
            ;; Add new time string to the header, if it was supplied.
@@ -3450,8 +3450,8 @@ containing only archived items, provided user option
 are shown in `todo-archived-only' face."
   (interactive)
   (todo-display-categories)
-  (let (sortkey)
-    (todo-update-categories-display sortkey)))
+  ;; (let (sortkey)
+  (todo-update-categories-display nil)) ;; sortkey
 
 (defun todo-next-button (n)
   "Move point to the Nth next button in the table of categories."
diff --git a/lisp/cedet/cedet-cscope.el b/lisp/cedet/cedet-cscope.el
index 75a69db..6ffc276 100644
--- a/lisp/cedet/cedet-cscope.el
+++ b/lisp/cedet/cedet-cscope.el
@@ -1,6 +1,6 @@
-;;; cedet-cscope.el --- CScope support for CEDET
+;;; cedet-cscope.el --- CScope support for CEDET  -*- lexical-binding: t; -*-
 
-;;; Copyright (C) 2009-2021 Free Software Foundation, Inc.
+;; Copyright (C) 2009-2021  Free Software Foundation, Inc.
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
 ;; Package: cedet
@@ -26,8 +26,6 @@
 
 ;;; Code:
 
-(declare-function inversion-check-version "inversion")
-
 (defvar cedet-cscope-min-version "15.7"
   "Minimum version of CScope required.")
 
@@ -36,7 +34,7 @@
   :type 'string
   :group 'cedet)
 
-(defun cedet-cscope-search (searchtext texttype type scope)
+(defun cedet-cscope-search (searchtext texttype type _scope)
   "Perform a search with CScope, return the created buffer.
 SEARCHTEXT is text to find.
 TEXTTYPE is the type of text, such as `regexp', `string', `tagname',
@@ -87,7 +85,7 @@ options -cR."
     (with-current-buffer b
       (setq default-directory cd)
       (erase-buffer))
-    (apply 'call-process cedet-cscope-command
+    (apply #'call-process cedet-cscope-command
           nil b nil
           flags)
     b))
@@ -139,7 +137,6 @@ If optional programmatic argument NOERROR is non-nil,
 then instead of throwing an error if CScope isn't available,
 return nil."
   (interactive)
-  (require 'inversion)
   (let ((b (condition-case nil
               (cedet-cscope-call (list "-V"))
             (error nil)))
@@ -153,7 +150,7 @@ return nil."
        (goto-char (point-min))
        (re-search-forward "cscope: version \\([0-9.]+\\)" nil t)
        (setq rev (match-string 1))
-       (if (inversion-check-version rev nil cedet-cscope-min-version)
+        (if (version< rev cedet-cscope-min-version)
            (if noerror
                nil
              (error "Version of CScope is %s.  Need at least %s"
diff --git a/lisp/cedet/cedet-files.el b/lisp/cedet/cedet-files.el
index 3160815..c9d557f597 100644
--- a/lisp/cedet/cedet-files.el
+++ b/lisp/cedet/cedet-files.el
@@ -1,4 +1,4 @@
-;;; cedet-files.el --- Common routines dealing with file names.
+;;; cedet-files.el --- Common routines dealing with file names.  -*- 
lexical-binding: t; -*-
 
 ;; Copyright (C) 2007-2021 Free Software Foundation, Inc.
 
diff --git a/lisp/cedet/cedet-global.el b/lisp/cedet/cedet-global.el
index 5878ec1..227ebd5 100644
--- a/lisp/cedet/cedet-global.el
+++ b/lisp/cedet/cedet-global.el
@@ -1,4 +1,4 @@
-;;; cedet-global.el --- GNU Global support for CEDET.
+;;; cedet-global.el --- GNU Global support for CEDET.  -*- lexical-binding: t; 
-*-
 
 ;; Copyright (C) 2008-2021 Free Software Foundation, Inc.
 
@@ -24,8 +24,6 @@
 ;;
 ;; Basic support for calling GNU Global, and testing version numbers.
 
-(declare-function inversion-check-version "inversion")
-
 (defvar cedet-global-min-version "5.0"
   "Minimum version of GNU Global required.")
 
@@ -77,7 +75,7 @@ SCOPE is the scope of the search, such as `project' or 
`subdirs'."
     (with-current-buffer b
       (setq default-directory cd)
       (erase-buffer))
-    (apply 'call-process cedet-global-command
+    (apply #'call-process cedet-global-command
           nil b nil
           flags)
     b))
@@ -90,7 +88,7 @@ SCOPE is the scope of the search, such as `project' or 
`subdirs'."
     (with-current-buffer b
       (setq default-directory cd)
       (erase-buffer))
-    (apply 'call-process cedet-global-gtags-command
+    (apply #'call-process cedet-global-gtags-command
           nil b nil
           flags)
 
@@ -143,7 +141,6 @@ If optional programmatic argument NOERROR is non-nil,
 then instead of throwing an error if Global isn't available,
 return nil."
   (interactive)
-  (require 'inversion)
   (let ((b (condition-case nil
               (cedet-gnu-global-call (list "--version"))
             (error nil)))
@@ -157,7 +154,7 @@ return nil."
        (goto-char (point-min))
        (re-search-forward "(?GNU GLOBAL)? \\([0-9.]+\\)" nil t)
        (setq rev (match-string 1))
-       (if (inversion-check-version rev nil cedet-global-min-version)
+        (if (version< rev cedet-global-min-version)
            (if noerror
                nil
              (error "Version of GNU Global is %s.  Need at least %s"
diff --git a/lisp/cedet/cedet-idutils.el b/lisp/cedet/cedet-idutils.el
index fc5e05a..a2b8cb3 100644
--- a/lisp/cedet/cedet-idutils.el
+++ b/lisp/cedet/cedet-idutils.el
@@ -1,4 +1,4 @@
-;;; cedet-idutils.el --- ID Utils support for CEDET.
+;;; cedet-idutils.el --- ID Utils support for CEDET.  -*- lexical-binding: t; 
-*-
 
 ;; Copyright (C) 2009-2021 Free Software Foundation, Inc.
 
@@ -29,8 +29,6 @@
 
 ;;; Code:
 
-(declare-function inversion-check-version "inversion")
-
 (defvar cedet-idutils-min-version "4.0"
   "Minimum version of ID Utils required.")
 
@@ -49,7 +47,7 @@
   :type 'string
   :group 'cedet)
 
-(defun cedet-idutils-search (searchtext texttype type scope)
+(defun cedet-idutils-search (searchtext texttype type _scope)
   "Perform a search with ID Utils, return the created buffer.
 SEARCHTEXT is text to find.
 TEXTTYPE is the type of text, such as `regexp', `string', `tagname',
@@ -66,7 +64,7 @@ Note: Scope is not yet supported."
     (let* ((resultflg (if (eq texttype 'tagcompletions)
                          (list "--key=token")
                        (list "--result=grep")))
-          (scopeflgs nil) ; (cond ((eq scope 'project) "" ) ((eq scope 
'target) "l")))
+          ;; (scopeflgs (cond ((eq scope 'project) "" ) ((eq scope 'target) 
"l")))
           (stflag (cond ((or (eq texttype 'tagname)
                              (eq texttype 'tagregexp))
                          (list "-r" "-w"))
@@ -79,7 +77,7 @@ Note: Scope is not yet supported."
                         ;; t means 'symbol
                         (t (list "-l" "-w"))))
           )
-      (cedet-idutils-lid-call (append resultflg scopeflgs stflag
+      (cedet-idutils-lid-call (append resultflg nil stflag ;; scopeflgs
                                      (list searchtext))))))
 
 (defun cedet-idutils-fnid-call (flags)
@@ -91,7 +89,7 @@ Return the created buffer with program output."
     (with-current-buffer b
       (setq default-directory cd)
       (erase-buffer))
-    (apply 'call-process cedet-idutils-file-command
+    (apply #'call-process cedet-idutils-file-command
           nil b nil
           flags)
     b))
@@ -105,7 +103,7 @@ Return the created buffer with program output."
     (with-current-buffer b
       (setq default-directory cd)
       (erase-buffer))
-    (apply 'call-process cedet-idutils-token-command
+    (apply #'call-process cedet-idutils-token-command
           nil b nil
           flags)
     b))
@@ -119,7 +117,7 @@ Return the created buffer with program output."
     (with-current-buffer b
       (setq default-directory cd)
       (erase-buffer))
-    (apply 'call-process cedet-idutils-make-command
+    (apply #'call-process cedet-idutils-make-command
           nil b nil
           flags)
     b))
@@ -135,7 +133,7 @@ Return a filename relative to the default directory."
               (if (looking-at "[^ \n]*fnid: ")
                   (error "ID Utils not available")
                 (split-string (buffer-string) "\n" t)))))
-    (setq ans (mapcar 'expand-file-name ans))
+    (setq ans (mapcar #'expand-file-name ans))
     (when (called-interactively-p 'interactive)
       (if ans
          (if (= (length ans) 1)
@@ -167,7 +165,6 @@ If optional programmatic argument NOERROR is non-nil,
 then instead of throwing an error if Global isn't available,
 return nil."
   (interactive)
-  (require 'inversion)
   (let ((b (condition-case nil
               (cedet-idutils-fnid-call (list "--version"))
             (error nil)))
@@ -182,7 +179,7 @@ return nil."
        (if (re-search-forward "fnid - \\([0-9.]+\\)" nil t)
            (setq rev (match-string 1))
          (setq rev "0"))
-       (if (inversion-check-version rev nil cedet-idutils-min-version)
+        (if (version< rev cedet-idutils-min-version)
            (if noerror
                nil
              (error "Version of ID Utils is %s.  Need at least %s"
diff --git a/lisp/cedet/cedet.el b/lisp/cedet/cedet.el
index caaec47..b6043f1 100644
--- a/lisp/cedet/cedet.el
+++ b/lisp/cedet/cedet.el
@@ -1,4 +1,4 @@
-;;; cedet.el --- Setup CEDET environment
+;;; cedet.el --- Setup CEDET environment  -*- lexical-binding: t; -*-
 
 ;; Copyright (C) 2002-2021 Free Software Foundation, Inc.
 
@@ -48,25 +48,25 @@
 
 (defvar cedet-menu-map ;(make-sparse-keymap "CEDET menu")
   (let ((map (make-sparse-keymap "CEDET menu")))
-    (define-key map [semantic-force-refresh]     'undefined)
-    (define-key map [semantic-edit-menu]         'undefined)
-    (define-key map [navigate-menu]              'undefined)
-    (define-key map [semantic-options-separator] 'undefined)
-    (define-key map [global-semantic-highlight-func-mode]   'undefined)
-    (define-key map [global-semantic-stickyfunc-mode]   'undefined)
-    (define-key map [global-semantic-decoration-mode]       'undefined)
-    (define-key map [global-semantic-idle-completions-mode] 'undefined)
-    (define-key map [global-semantic-idle-summary-mode]     'undefined)
-    (define-key map [global-semantic-idle-scheduler-mode]   'undefined)
-    (define-key map [global-semanticdb-minor-mode]          'undefined)
-    (define-key map [cedet-menu-separator] 'undefined)
-    (define-key map [ede-find-file]        'undefined)
-    (define-key map [ede-speedbar]         'undefined)
-    (define-key map [ede] 'undefined)
-    (define-key map [ede-new]              'undefined)
-    (define-key map [ede-target-options]   'undefined)
-    (define-key map [ede-project-options]  'undefined)
-    (define-key map [ede-build-forms-menu] 'undefined)
+    (define-key map [semantic-force-refresh]     #'undefined)
+    (define-key map [semantic-edit-menu]         #'undefined)
+    (define-key map [navigate-menu]              #'undefined)
+    (define-key map [semantic-options-separator] #'undefined)
+    (define-key map [global-semantic-highlight-func-mode]   #'undefined)
+    (define-key map [global-semantic-stickyfunc-mode]       #'undefined)
+    (define-key map [global-semantic-decoration-mode]       #'undefined)
+    (define-key map [global-semantic-idle-completions-mode] #'undefined)
+    (define-key map [global-semantic-idle-summary-mode]     #'undefined)
+    (define-key map [global-semantic-idle-scheduler-mode]   #'undefined)
+    (define-key map [global-semanticdb-minor-mode]          #'undefined)
+    (define-key map [cedet-menu-separator] #'undefined)
+    (define-key map [ede-find-file]        #'undefined)
+    (define-key map [ede-speedbar]         #'undefined)
+    (define-key map [ede]                  #'undefined)
+    (define-key map [ede-new]              #'undefined)
+    (define-key map [ede-target-options]   #'undefined)
+    (define-key map [ede-project-options]  #'undefined)
+    (define-key map [ede-build-forms-menu] #'undefined)
     map)
   "Menu keymap for the CEDET package.
 This is used by `semantic-mode' and `global-ede-mode'.")
@@ -85,6 +85,7 @@ for the specified PACKAGE.
 LOADED VERSION is the version of PACKAGE currently loaded in Emacs
 memory and (presumably) running in this Emacs instance.  Value is X
 if the package has not been loaded."
+  (declare (obsolete emacs-version "28.1"))
   (interactive)
   (require 'inversion)
   (with-output-to-temp-buffer "*CEDET*"
diff --git a/lisp/cedet/data-debug.el b/lisp/cedet/data-debug.el
index f0fa91b..428848b 100644
--- a/lisp/cedet/data-debug.el
+++ b/lisp/cedet/data-debug.el
@@ -1,4 +1,4 @@
-;;; data-debug.el --- Data structure debugger
+;;; data-debug.el --- Data structure debugger  -*- lexical-binding: t; -*-
 
 ;; Copyright (C) 2007-2021 Free Software Foundation, Inc.
 
@@ -48,9 +48,9 @@
 
 ;;; Compatibility
 ;;
-(define-obsolete-function-alias 'data-debug-overlay-properties 
'overlay-properties "28.1")
-(define-obsolete-function-alias 'data-debug-overlay-p 'overlayp "28.1")
-(define-obsolete-function-alias 'dd-propertize 'propertize "28.1")
+(define-obsolete-function-alias 'data-debug-overlay-properties 
#'overlay-properties "28.1")
+(define-obsolete-function-alias 'data-debug-overlay-p #'overlayp "28.1")
+(define-obsolete-function-alias 'dd-propertize #'propertize "28.1")
 
 ;;; GENERIC STUFF
 ;;
@@ -100,14 +100,14 @@ PREBUTTONTEXT is some text between prefix and the overlay 
button."
   (let ((start (point))
        (end nil)
        (str (format "%s" overlay))
-       (tip nil))
+       ) ;; (tip nil)
     (insert prefix prebuttontext str)
     (setq end (point))
     (put-text-property (- end (length str)) end 'face 'font-lock-comment-face)
     (put-text-property start end 'ddebug overlay)
     (put-text-property start end 'ddebug-indent(length prefix))
     (put-text-property start end 'ddebug-prefix prefix)
-    (put-text-property start end 'help-echo tip)
+    ;; (put-text-property start end 'help-echo tip)
     (put-text-property start end 'ddebug-function
                       'data-debug-insert-overlay-from-point)
     (insert "\n")
@@ -149,14 +149,14 @@ PREBUTTONTEXT is some text between prefix and the overlay 
list button."
   (let ((start (point))
        (end nil)
        (str (format "#<overlay list: %d entries>" (length overlaylist)))
-       (tip nil))
+       ) ;; (tip nil)
     (insert prefix prebuttontext str)
     (setq end (point))
     (put-text-property (- end (length str)) end 'face 'font-lock-comment-face)
     (put-text-property start end 'ddebug overlaylist)
     (put-text-property start end 'ddebug-indent(length prefix))
     (put-text-property start end 'ddebug-prefix prefix)
-    (put-text-property start end 'help-echo tip)
+    ;; (put-text-property start end 'help-echo tip)
     (put-text-property start end 'ddebug-function
                       'data-debug-insert-overlay-list-from-point)
     (insert "\n")
@@ -204,14 +204,14 @@ PREBUTTONTEXT is some text between prefix and the buffer 
button."
   (let ((start (point))
        (end nil)
        (str (format "%S" buffer))
-       (tip nil))
+       ) ;; (tip nil)
     (insert prefix prebuttontext str)
     (setq end (point))
     (put-text-property (- end (length str)) end 'face 'font-lock-comment-face)
     (put-text-property start end 'ddebug buffer)
     (put-text-property start end 'ddebug-indent(length prefix))
     (put-text-property start end 'ddebug-prefix prefix)
-    (put-text-property start end 'help-echo tip)
+    ;; (put-text-property start end 'help-echo tip)
     (put-text-property start end 'ddebug-function
                       'data-debug-insert-buffer-from-point)
     (insert "\n")
@@ -253,14 +253,14 @@ PREBUTTONTEXT is some text between prefix and the buffer 
list button."
   (let ((start (point))
        (end nil)
        (str (format "#<buffer list: %d entries>" (length bufferlist)))
-       (tip nil))
+       ) ;; (tip nil)
     (insert prefix prebuttontext str)
     (setq end (point))
     (put-text-property (- end (length str)) end 'face 'font-lock-comment-face)
     (put-text-property start end 'ddebug bufferlist)
     (put-text-property start end 'ddebug-indent(length prefix))
     (put-text-property start end 'ddebug-prefix prefix)
-    (put-text-property start end 'help-echo tip)
+    ;; (put-text-property start end 'help-echo tip)
     (put-text-property start end 'ddebug-function
                       'data-debug-insert-buffer-list-from-point)
     (insert "\n")
@@ -309,14 +309,14 @@ PREBUTTONTEXT is some text between prefix and the process 
button."
   (let ((start (point))
        (end nil)
        (str (format "%S : %s" process (process-status process)))
-       (tip nil))
+       ) ;; (tip nil)
     (insert prefix prebuttontext str)
     (setq end (point))
     (put-text-property (- end (length str)) end 'face 'font-lock-comment-face)
     (put-text-property start end 'ddebug process)
     (put-text-property start end 'ddebug-indent(length prefix))
     (put-text-property start end 'ddebug-prefix prefix)
-    (put-text-property start end 'help-echo tip)
+    ;; (put-text-property start end 'help-echo tip)
     (put-text-property start end 'ddebug-function
                       'data-debug-insert-process-from-point)
     (insert "\n")
@@ -363,8 +363,8 @@ PREBUTTONTEXT is some text between prefix and the stuff 
list button."
         (str (format "#<RING: %d, %d max>"
                      (ring-length ring)
                      (ring-size ring)))
-        (ringthing
-         (if (= (ring-length ring) 0) nil (ring-ref ring 0)))
+        ;; (ringthing
+        ;;  (if (= (ring-length ring) 0) nil (ring-ref ring 0)))
         (tip (format "Ring max-size %d, length %d."
                      (ring-size ring)
                      (ring-length ring)))
@@ -437,7 +437,7 @@ PREBUTTONTEXT is some text between prefix and the stuff 
list button."
 ;; Widgets have a long list of properties
 (defun data-debug-insert-widget-properties (widget prefix)
   "Insert the contents of WIDGET inserting PREFIX before each element."
-  (let ((type (car widget))
+  (let (;; (type (car widget))
        (rest (cdr widget)))
     (while rest
       (data-debug-insert-thing (car (cdr rest))
@@ -683,7 +683,7 @@ PREBUTTONTEXT is some text between prefix and the thing."
   )
 
 ;;; nil thing
-(defun data-debug-insert-nil (thing prefix prebuttontext)
+(defun data-debug-insert-nil (_thing prefix prebuttontext)
   "Insert one simple THING with a face.
 PREFIX is the text that precedes the button.
 PREBUTTONTEXT is some text between prefix and the thing.
@@ -856,19 +856,18 @@ If PARENT is non-nil, it is somehow related as a parent 
to thing."
 (defvar data-debug-mode-map
   (let ((km (make-sparse-keymap)))
     (suppress-keymap km)
-    (define-key km [mouse-2] 'data-debug-expand-or-contract-mouse)
-    (define-key km " " 'data-debug-expand-or-contract)
-    (define-key km "\C-m" 'data-debug-expand-or-contract)
-    (define-key km "n" 'data-debug-next)
-    (define-key km "p" 'data-debug-prev)
-    (define-key km "N" 'data-debug-next-expando)
-    (define-key km "P" 'data-debug-prev-expando)
+    (define-key km [mouse-2] #'data-debug-expand-or-contract-mouse)
+    (define-key km " " #'data-debug-expand-or-contract)
+    (define-key km "\C-m" #'data-debug-expand-or-contract)
+    (define-key km "n" #'data-debug-next)
+    (define-key km "p" #'data-debug-prev)
+    (define-key km "N" #'data-debug-next-expando)
+    (define-key km "P" #'data-debug-prev-expando)
     km)
   "Keymap used in data-debug.")
 
 (defcustom data-debug-mode-hook nil
   "Hook run when data-debug starts."
-  :group 'data-debug
   :type 'hook)
 
 (define-derived-mode data-debug-mode fundamental-mode "DATA-DEBUG"
@@ -1032,7 +1031,7 @@ Do nothing if already contracted."
                                 nil read-expression-map t
                                 'read-expression-history))
         ))
-  (let ((v (eval expr)))
+  (let ((v (eval expr t)))
     (if (not v)
        (message "Expression %s is nil." expr)
       (data-debug-show-stuff v "expression"))))
@@ -1049,12 +1048,12 @@ If the result is a list or vector, then use the data 
debugger to display it."
 
   (let (result)
     (if (null eval-expression-debug-on-error)
-        (setq result (values--store-value (eval expr)))
+        (setq result (values--store-value (eval expr t)))
       (let ((old-value (make-symbol "t")) new-value)
         ;; Bind debug-on-error to something unique so that we can
         ;; detect when evalled code changes it.
         (let ((debug-on-error old-value))
-         (setq result (values--store-value (eval expr)))
+         (setq result (values--store-value (eval expr t)))
          (setq new-value debug-on-error))
         ;; If evalled code has changed the value of debug-on-error,
         ;; propagate that change to the global binding.
diff --git a/lisp/cedet/ede.el b/lisp/cedet/ede.el
index e3cc906..2ec9f5d 100644
--- a/lisp/cedet/ede.el
+++ b/lisp/cedet/ede.el
@@ -1,4 +1,4 @@
-;;; ede.el --- Emacs Development Environment gloss
+;;; ede.el --- Emacs Development Environment gloss  -*- lexical-binding: t; -*-
 
 ;; Copyright (C) 1998-2005, 2007-2021 Free Software Foundation, Inc.
 
@@ -87,7 +87,6 @@ target wants the file, the user is asked.  If only one target 
wants
 the file, then it is automatically added to that target.  If the
 value is `ask', then the user is always asked, unless there is no
 target willing to take the file.  `never' means never perform the check."
-  :group 'ede
   :type '(choice (const always)
                 (const multi-ask)
                 (const ask)
@@ -95,7 +94,6 @@ target willing to take the file.  `never' means never perform 
the check."
 
 (defcustom ede-debug-program-function 'gdb
   "Default Emacs command used to debug a target."
-  :group 'ede
   :type 'function) ; make this be a list of options some day
 
 (defcustom ede-project-directories nil
@@ -112,7 +110,6 @@ If you invoke the commands \\[ede] or \\[ede-new] on a 
directory
 that is not listed, Emacs will offer to add it to the list.
 
 Any other value disables searching for EDE project files."
-  :group 'ede
   :type '(choice (const :tag "Any directory" t)
                 (repeat :tag "List of directories"
                         (directory))
@@ -186,21 +183,23 @@ Argument LIST-O-O is the list of objects to choose from."
 
 ;;; Menu and Keymap
 
+(declare-function ede-speedbar "ede/speedbar" ())
+
 (defvar ede-minor-mode-map
   (let ((map (make-sparse-keymap))
        (pmap (make-sparse-keymap)))
-    (define-key pmap "e" 'ede-edit-file-target)
-    (define-key pmap "a" 'ede-add-file)
-    (define-key pmap "d" 'ede-remove-file)
-    (define-key pmap "t" 'ede-new-target)
-    (define-key pmap "g" 'ede-rescan-toplevel)
-    (define-key pmap "s" 'ede-speedbar)
-    (define-key pmap "f" 'ede-find-file)
-    (define-key pmap "C" 'ede-compile-project)
-    (define-key pmap "c" 'ede-compile-target)
-    (define-key pmap "\C-c" 'ede-compile-selected)
-    (define-key pmap "D" 'ede-debug-target)
-    (define-key pmap "R" 'ede-run-target)
+    (define-key pmap "e" #'ede-edit-file-target)
+    (define-key pmap "a" #'ede-add-file)
+    (define-key pmap "d" #'ede-remove-file)
+    (define-key pmap "t" #'ede-new-target)
+    (define-key pmap "g" #'ede-rescan-toplevel)
+    (define-key pmap "s" #'ede-speedbar)
+    (define-key pmap "f" #'ede-find-file)
+    (define-key pmap "C" #'ede-compile-project)
+    (define-key pmap "c" #'ede-compile-target)
+    (define-key pmap "\C-c" #'ede-compile-selected)
+    (define-key pmap "D" #'ede-debug-target)
+    (define-key pmap "R" #'ede-run-target)
     ;; bind our submap into map
     (define-key map "\C-c." pmap)
     map)
@@ -476,7 +475,7 @@ To be used in hook functions."
 If this file is contained, or could be contained in an EDE
 controlled project, then this mode is activated automatically
 provided `global-ede-mode' is enabled."
-  :group 'ede
+  :global nil
   (cond ((or (eq major-mode 'dired-mode)
             (eq major-mode 'vc-dir-mode))
         (ede-dired-minor-mode (if ede-minor-mode 1 -1)))
@@ -486,6 +485,9 @@ provided `global-ede-mode' is enabled."
           ;; If we fail to have a project here, turn it back off.
           (ede-minor-mode -1)))))
 
+(declare-function ede-directory-project-cons "ede/files" (dir &optional force))
+(declare-function ede-toplevel-project-or-nil "ede/files" (dir))
+
 (defun ede-initialize-state-current-buffer ()
   "Initialize the current buffer's state for EDE.
 Sets buffer local variables for EDE."
@@ -496,7 +498,7 @@ Sets buffer local variables for EDE."
   ;; Init the buffer.
   (let* ((ROOT nil)
         (proj (ede-directory-get-open-project default-directory
-                                              'ROOT)))
+                                              (gv-ref ROOT))))
 
     (when (not proj)
       ;; If there is no open project, look up the project
@@ -517,7 +519,8 @@ Sets buffer local variables for EDE."
                      (ede-directory-safe-p top)))
 
            ;; The project is safe, so load it in.
-           (setq proj (ede-load-project-file default-directory projdetect 
'ROOT))))))
+           (setq proj (ede-load-project-file default-directory projdetect
+                                             (gv-ref ROOT)))))))
 
     ;; If PROJ is now loaded in, we can initialize our buffer to it.
     (when proj
@@ -561,30 +564,29 @@ Sets buffer local variables for EDE."
 This global minor mode enables `ede-minor-mode' in all buffers in
 an EDE controlled project."
   :global t
-  :group 'ede
   (if global-ede-mode
       ;; Turn on global-ede-mode
       (progn
        (if semantic-mode
            (define-key cedet-menu-map [cedet-menu-separator] '("--")))
-       (add-hook 'semanticdb-project-predicate-functions 
'ede-directory-project-p)
-       (add-hook 'semanticdb-project-root-functions 
'ede-toplevel-project-or-nil)
-       (add-hook 'ecb-source-path-functions 'ede-ecb-project-paths)
+       (add-hook 'semanticdb-project-predicate-functions 
#'ede-directory-project-p)
+       (add-hook 'semanticdb-project-root-functions 
#'ede-toplevel-project-or-nil)
+       (add-hook 'ecb-source-path-functions #'ede-ecb-project-paths)
        ;; Append our hook to the end.  This allows mode-local to finish
        ;; it's stuff before we start doing misc file loads, etc.
-       (add-hook 'find-file-hook 'ede-turn-on-hook t)
-       (add-hook 'dired-mode-hook 'ede-turn-on-hook)
-       (add-hook 'kill-emacs-hook 'ede-save-cache)
+       (add-hook 'find-file-hook #'ede-turn-on-hook t)
+       (add-hook 'dired-mode-hook #'ede-turn-on-hook)
+       (add-hook 'kill-emacs-hook #'ede-save-cache)
        (ede-load-cache)
        (ede-reset-all-buffers))
     ;; Turn off global-ede-mode
     (define-key cedet-menu-map [cedet-menu-separator] nil)
-    (remove-hook 'semanticdb-project-predicate-functions 
'ede-directory-project-p)
-    (remove-hook 'semanticdb-project-root-functions 
'ede-toplevel-project-or-nil)
-    (remove-hook 'ecb-source-path-functions 'ede-ecb-project-paths)
-    (remove-hook 'find-file-hook 'ede-turn-on-hook)
-    (remove-hook 'dired-mode-hook 'ede-turn-on-hook)
-    (remove-hook 'kill-emacs-hook 'ede-save-cache)
+    (remove-hook 'semanticdb-project-predicate-functions 
#'ede-directory-project-p)
+    (remove-hook 'semanticdb-project-root-functions 
#'ede-toplevel-project-or-nil)
+    (remove-hook 'ecb-source-path-functions #'ede-ecb-project-paths)
+    (remove-hook 'find-file-hook #'ede-turn-on-hook)
+    (remove-hook 'dired-mode-hook #'ede-turn-on-hook)
+    (remove-hook 'kill-emacs-hook #'ede-save-cache)
     (ede-save-cache)
     (ede-reset-all-buffers)))
 
@@ -1080,7 +1082,7 @@ Flush the dead projects from the project cache."
   (let ((dead nil))
     (dolist (P ede-projects)
       (when (not (file-exists-p (oref P file)))
-       (add-to-list 'dead P)))
+       (cl-pushnew P dead :test #'equal)))
     (dolist (D dead)
       (ede-delete-project-from-global-list D))
     ))
@@ -1108,7 +1110,7 @@ Flush the dead projects from the project cache."
   "Project file independent way to read a project in from DIR.
 Optional DETECTIN is an autoload cons from `ede-detect-directory-for-project'
 which can be passed in to save time.
-Optional ROOTRETURN will return the root project for DIR."
+Optional ROOTRETURN reference will return the root project for DIR."
   ;; Don't do anything if we are in the process of
   ;; constructing an EDE object.
   ;;
@@ -1147,7 +1149,8 @@ Optional ROOTRETURN will return the root project for DIR."
            (setq o (ede-auto-load-project autoloader toppath))))
 
        ;; Return the found root project.
-       (when rootreturn (set rootreturn o))
+       (when rootreturn (if (symbolp rootreturn) (set rootreturn o)
+                          (setf (gv-deref rootreturn) o)))
 
        ;; The project has been found (in the global list) or loaded from
        ;; disk (via autoloader.)  We can now search for the project asked
@@ -1504,6 +1507,8 @@ It does not apply the value to buffers."
 ;;; Integration with project.el
 
 (defun project-try-ede (dir)
+  ;; FIXME: This passes the `ROOT' dynbound variable, but I don't know
+  ;; where it comes from!
   (let ((project-dir
          (locate-dominating-file
           dir
@@ -1518,12 +1523,12 @@ It does not apply the value to buffers."
 ;;; FIXME: Could someone look into implementing `project-ignores' for
 ;;; EDE and/or a faster `project-files'?
 
-(add-hook 'project-find-functions #'project-try-ede)
+(add-hook 'project-find-functions #'project-try-ede 50)
 
 (provide 'ede)
 
 ;; Include this last because it depends on ede.
-(require 'ede/files)
+(if t (require 'ede/files)) ;; Don't bother loading it at compile-time.
 
 ;; If this does not occur after the provide, we can get a recursive
 ;; load.  Yuck!
diff --git a/lisp/cedet/ede/auto.el b/lisp/cedet/ede/auto.el
index e1417d7..ee9d011 100644
--- a/lisp/cedet/ede/auto.el
+++ b/lisp/cedet/ede/auto.el
@@ -1,4 +1,4 @@
-;;; ede/auto.el --- Autoload features for EDE
+;;; ede/auto.el --- Autoload features for EDE  -*- lexical-binding: t; -*-
 
 ;; Copyright (C) 2010-2021 Free Software Foundation, Inc.
 
@@ -325,13 +325,13 @@ NOTE: Do not call this - it should only be called from 
`ede-load-project-file'."
 ;; See if we can do without them.
 
 ;; @FIXME - delete from loaddefs to remove this.
-(cl-defmethod ede-project-root ((this ede-project-autoload))
+(cl-defmethod ede-project-root ((_this ede-project-autoload))
   "If a project knows its root, return it here.
 Allows for one-project-object-for-a-tree type systems."
   nil)
 
 ;; @FIXME - delete from loaddefs to remove this.
-(cl-defmethod ede-project-root-directory ((this ede-project-autoload) 
&optional file)
+(cl-defmethod ede-project-root-directory ((_this ede-project-autoload) 
&optional _file)
   "" nil)
 
 (provide 'ede/auto)
diff --git a/lisp/cedet/ede/autoconf-edit.el b/lisp/cedet/ede/autoconf-edit.el
index ca8535f..d6f0a86 100644
--- a/lisp/cedet/ede/autoconf-edit.el
+++ b/lisp/cedet/ede/autoconf-edit.el
@@ -1,4 +1,4 @@
-;;; ede/autoconf-edit.el --- Keymap for autoconf
+;;; ede/autoconf-edit.el --- Keymap for autoconf  -*- lexical-binding: t; -*-
 
 ;; Copyright (C) 1998-2000, 2009-2021 Free Software Foundation, Inc.
 
diff --git a/lisp/cedet/ede/base.el b/lisp/cedet/ede/base.el
index 810d6ef..3fcc023 100644
--- a/lisp/cedet/ede/base.el
+++ b/lisp/cedet/ede/base.el
@@ -1,4 +1,4 @@
-;;; ede/base.el --- Baseclasses for EDE.
+;;; ede/base.el --- Baseclasses for EDE  -*- lexical-binding: t; -*-
 
 ;; Copyright (C) 2010-2021 Free Software Foundation, Inc.
 
@@ -288,7 +288,7 @@ All specific project types must derive from this project."
 ;;
 (defmacro ede-with-projectfile (obj &rest forms)
   "For the project in which OBJ resides, execute FORMS."
-  (declare (indent 1))
+  (declare (indent 1) (debug t))
   (unless (symbolp obj)
     (message "Beware! ede-with-projectfile's first arg is copied: %S" obj))
   `(let* ((pf (if (obj-of-class-p ,obj 'ede-target)
@@ -317,13 +317,15 @@ If set to nil, then the cache is not saved."
 (defvar ede-project-cache-files nil
   "List of project files EDE has seen before.")
 
+(defvar recentf-exclude)
+
 (defun ede-save-cache ()
   "Save a cache of EDE objects that Emacs has seen before."
   (interactive)
   (when ede-project-placeholder-cache-file
     (let ((p ede-projects)
          (c ede-project-cache-files)
-         (recentf-exclude '( (lambda (f) t) ))
+         (recentf-exclude `( ,(lambda (_) t) ))
          )
       (condition-case nil
          (progn
@@ -461,7 +463,7 @@ Not all buffers need headers, so return nil if no 
applicable."
       (ede-buffer-header-file ede-object (current-buffer))
     nil))
 
-(cl-defmethod ede-buffer-header-file ((this ede-project) buffer)
+(cl-defmethod ede-buffer-header-file ((_this ede-project) _buffer)
   "Return nil, projects don't have header files."
   nil)
 
@@ -487,12 +489,12 @@ Some projects may have multiple documentation files, so 
return a list."
       (ede-buffer-documentation-files ede-object (current-buffer))
     nil))
 
-(cl-defmethod ede-buffer-documentation-files ((this ede-project) buffer)
+(cl-defmethod ede-buffer-documentation-files ((this ede-project) _buffer)
   "Return all documentation in project THIS based on BUFFER."
   ;; Find the info node.
   (ede-documentation this))
 
-(cl-defmethod ede-buffer-documentation-files ((this ede-target) buffer)
+(cl-defmethod ede-buffer-documentation-files ((_this ede-target) buffer)
   "Check for some documentation files for THIS.
 Also do a quick check to see if there is a Documentation tag in this BUFFER."
   (with-current-buffer buffer
@@ -518,7 +520,7 @@ files in the project."
            proj (cdr proj)))
     found))
 
-(cl-defmethod ede-documentation ((this ede-target))
+(cl-defmethod ede-documentation ((_this ede-target))
   "Return a list of files that provide documentation.
 Documentation is not for object THIS, but is provided by THIS for other
 files in the project."
@@ -529,7 +531,7 @@ files in the project."
   (ede-html-documentation (ede-toplevel))
   )
 
-(cl-defmethod ede-html-documentation ((this ede-project))
+(cl-defmethod ede-html-documentation ((_this ede-project))
   "Return a list of HTML files provided by project THIS."
 
   )
@@ -636,18 +638,7 @@ PROJECT-FILE-NAME is a name of project file (short name, 
like `pom.xml', etc."
     (oset this directory (file-name-directory (oref this file))))
   )
 
-
-
 
-;;; Hooks & Autoloads
-;;
-;;  These let us watch various activities, and respond appropriately.
-
-;; (add-hook 'edebug-setup-hook
-;;       (lambda ()
-;;         (def-edebug-spec ede-with-projectfile
-;;           (form def-body))))
-
 (provide 'ede/base)
 
 ;; Local variables:
diff --git a/lisp/cedet/ede/config.el b/lisp/cedet/ede/config.el
index 1968621..bc1810a 100644
--- a/lisp/cedet/ede/config.el
+++ b/lisp/cedet/ede/config.el
@@ -1,4 +1,4 @@
-;;; ede/config.el --- Configuration Handler baseclass
+;;; ede/config.el --- Configuration Handler baseclass  -*- lexical-binding: t; 
-*-
 
 ;; Copyright (C) 2014-2021 Free Software Foundation, Inc.
 
@@ -171,7 +171,7 @@ the directory isn't on the `safe' list, ask to add it to 
the safe list."
        (oset config project proj)))
     config))
 
-(cl-defmethod ede-config-setup-configuration ((proj ede-project-with-config) 
config)
+(cl-defmethod ede-config-setup-configuration ((_proj ede-project-with-config) 
_config)
   "Default configuration setup method."
   nil)
 
@@ -187,7 +187,7 @@ the directory isn't on the `safe' list, ask to add it to 
the safe list."
   (let ((config (ede-config-get-configuration proj t)))
     (eieio-customize-object config)))
 
-(cl-defmethod ede-customize ((target ede-target-with-config))
+(cl-defmethod ede-customize ((_target ede-target-with-config))
   "Customize the EDE TARGET by actually configuring the config object."
   ;; Nothing unique for the targets, use the project.
   (ede-customize-project))
@@ -302,14 +302,14 @@ This class brings in method overloads for building.")
   "Class to mix into a project with configuration for builds.
 This class brings in method overloads for building.")
 
-(cl-defmethod project-compile-project ((proj ede-project-with-config-build) 
&optional command)
+(cl-defmethod project-compile-project ((proj ede-project-with-config-build) 
&optional _command)
   "Compile the entire current project PROJ.
 Argument COMMAND is the command to use when compiling."
   (let* ((config (ede-config-get-configuration proj t))
         (comp (oref config build-command)))
     (compile comp)))
 
-(cl-defmethod project-compile-target ((obj ede-target-with-config-build) 
&optional command)
+(cl-defmethod project-compile-target ((_obj ede-target-with-config-build) 
&optional command)
   "Compile the current target OBJ.
 Argument COMMAND is the command to use for compiling the target."
   (project-compile-project (ede-current-project) command))
diff --git a/lisp/cedet/ede/cpp-root.el b/lisp/cedet/ede/cpp-root.el
index 41f0c68..652d647 100644
--- a/lisp/cedet/ede/cpp-root.el
+++ b/lisp/cedet/ede/cpp-root.el
@@ -1,4 +1,4 @@
-;;; ede/cpp-root.el --- A simple way to wrap a C++ project with a single root
+;;; ede/cpp-root.el --- A simple way to wrap a C++ project with a single root  
-*- lexical-binding: t; -*-
 
 ;; Copyright (C) 2007-2021 Free Software Foundation, Inc.
 
@@ -275,7 +275,7 @@ Each directory needs a project file to control it.")
 ;; objects is deleted.
 
 (cl-defmethod initialize-instance ((this ede-cpp-root-project)
-                               &rest fields)
+                                  &rest _fields)
   "Make sure the :file is fully expanded."
   ;; Add ourselves to the master list
   (cl-call-next-method)
@@ -310,7 +310,7 @@ Each directory needs a project file to control it.")
 ;; project, simplifying authoring new single-point projects.
 
 (cl-defmethod ede-find-subproject-for-directory ((proj ede-cpp-root-project)
-                                             dir)
+                                                _dir)
   "Return PROJ, for handling all subdirs below DIR."
   proj)
 
@@ -319,7 +319,7 @@ Each directory needs a project file to control it.")
 ;; Creating new targets on a per directory basis is a good way to keep
 ;; files organized.  See ede-emacs for an example with multiple file
 ;; types.
-(cl-defmethod ede-find-target ((proj ede-cpp-root-project) buffer)
+(cl-defmethod ede-find-target ((proj ede-cpp-root-project) _buffer)
   "Find an EDE target in PROJ for BUFFER.
 If one doesn't exist, create a new one for this directory."
   (let* ((targets (oref proj targets))
@@ -451,7 +451,7 @@ This is for project include paths and spp source files."
   "Get the pre-processor map for project THIS."
   (ede-preprocessor-map  (ede-target-parent this)))
 
-(cl-defmethod project-compile-project ((proj ede-cpp-root-project) &optional 
command)
+(cl-defmethod project-compile-project ((proj ede-cpp-root-project) &optional 
_command)
   "Compile the entire current project PROJ.
 Argument COMMAND is the command to use when compiling."
   ;; we need to be in the proj root dir for this to work
@@ -474,7 +474,7 @@ Argument COMMAND is the command to use for compiling the 
target."
     (project-compile-project (oref obj project) command)))
 
 
-(cl-defmethod project-rescan ((this ede-cpp-root-project))
+(cl-defmethod project-rescan ((_this ede-cpp-root-project))
   "Don't rescan this project from the sources."
   (message "cpp-root has nothing to rescan."))
 
diff --git a/lisp/cedet/ede/custom.el b/lisp/cedet/ede/custom.el
index aada872..ac4f9f6 100644
--- a/lisp/cedet/ede/custom.el
+++ b/lisp/cedet/ede/custom.el
@@ -1,4 +1,4 @@
-;;; ede/custom.el --- customization of EDE projects.
+;;; ede/custom.el --- customization of EDE projects.  -*- lexical-binding: t; 
-*-
 
 ;; Copyright (C) 2010-2021 Free Software Foundation, Inc.
 
@@ -53,7 +53,7 @@
     (setq-local eieio-ede-old-variables ov)))
 
 ;;;###autoload
-(defalias 'customize-project 'ede-customize-project)
+(defalias 'customize-project #'ede-customize-project)
 
 ;;;###autoload
 (defun ede-customize-current-target()
@@ -65,7 +65,7 @@
   (ede-customize-target ede-object))
 
 ;;;###autoload
-(defalias 'customize-target 'ede-customize-current-target)
+(defalias 'customize-target #'ede-customize-current-target)
 
 (defun ede-customize-target (obj)
   "Edit fields of the current target through EIEIO & Custom.
@@ -97,13 +97,13 @@ OBJ is the target object to customize."
   "Create a custom-like buffer for sorting targets of current project."
   (interactive)
   (let ((proj (ede-current-project))
-        (count 1)
-        current order)
+        ;; (count 1)
+        ) ;; current order
     (switch-to-buffer (get-buffer-create "*EDE sort targets*"))
     (erase-buffer)
     (setq ede-object-project proj)
     (widget-create 'push-button
-                   :notify (lambda (&rest ignore)
+                   :notify (lambda (&rest _ignore)
                              (let ((targets (oref ede-object-project targets))
                                    cur newtargets)
                                (while (setq cur (pop 
ede-project-sort-targets-order))
@@ -115,7 +115,7 @@ OBJ is the target object to customize."
                    " Accept ")
     (widget-insert "   ")
     (widget-create 'push-button
-                   :notify (lambda (&rest ignore)
+                   :notify (lambda (&rest _ignore)
                             (kill-buffer))
                    " Cancel ")
     (widget-insert "\n\n")
@@ -133,45 +133,45 @@ OBJ is the target object to customize."
 (defun ede-project-sort-targets-list ()
   "Sort the target list while using `ede-project-sort-targets'."
   (save-excursion
-    (let ((count 0)
-          (targets (oref ede-object-project targets))
+    (let ((targets (oref ede-object-project targets))
           (inhibit-read-only t)
           (inhibit-modification-hooks t))
       (goto-char (point-min))
       (forward-line 2)
       (delete-region (point) (point-max))
-      (while (< count (length targets))
+      (dotimes (count (length targets))
         (if (> count 0)
             (widget-create 'push-button
-                           :notify `(lambda (&rest ignore)
-                                      (let ((cur 
ede-project-sort-targets-order))
-                                        (add-to-ordered-list
-                                         'ede-project-sort-targets-order
-                                         (nth ,count cur)
-                                         (1- ,count))
-                                        (add-to-ordered-list
-                                         'ede-project-sort-targets-order
-                                         (nth (1- ,count) cur) ,count))
-                                      (ede-project-sort-targets-list))
+                           :notify (lambda (&rest _ignore)
+                                     (let ((cur 
ede-project-sort-targets-order))
+                                       (add-to-ordered-list
+                                        'ede-project-sort-targets-order
+                                        (nth count cur)
+                                        (1- count))
+                                       (add-to-ordered-list
+                                        'ede-project-sort-targets-order
+                                        (nth (1- count) cur) count))
+                                     (ede-project-sort-targets-list))
                            " Up ")
           (widget-insert "      "))
         (if (< count (1- (length targets)))
             (widget-create 'push-button
-                           :notify `(lambda (&rest ignore)
-                                      (let ((cur 
ede-project-sort-targets-order))
-                                        (add-to-ordered-list
-                                         'ede-project-sort-targets-order
-                                         (nth ,count cur) (1+ ,count))
-                                        (add-to-ordered-list
-                                         'ede-project-sort-targets-order
-                                         (nth (1+ ,count) cur) ,count))
-                                      (ede-project-sort-targets-list))
+                           :notify (lambda (&rest _ignore)
+                                     (let ((cur 
ede-project-sort-targets-order))
+                                       (add-to-ordered-list
+                                        'ede-project-sort-targets-order
+                                        (nth count cur) (1+ count))
+                                       (add-to-ordered-list
+                                        'ede-project-sort-targets-order
+                                        (nth (1+ count) cur) count))
+                                     (ede-project-sort-targets-list))
                            " Down ")
           (widget-insert "        "))
         (widget-insert (concat " " (number-to-string (1+ count)) ".:   "
                                (oref (nth (nth count 
ede-project-sort-targets-order)
-                                          targets) name) "\n"))
-        (setq count (1+ count))))))
+                                          targets)
+                                     name)
+                               "\n"))))))
 
 ;;; Customization hooks
 ;;
@@ -195,11 +195,11 @@ OBJ is the target object to customize."
 ;; These two methods should be implemented by subclasses of
 ;; project and targets in order to account for user specified
 ;; changes.
-(cl-defmethod eieio-done-customizing ((target ede-target))
+(cl-defmethod eieio-done-customizing ((_target ede-target))
   "Call this when a user finishes customizing TARGET."
   nil)
 
-(cl-defmethod ede-commit-project ((proj ede-project))
+(cl-defmethod ede-commit-project ((_proj ede-project))
   "Commit any change to PROJ to its file."
   nil
   )
diff --git a/lisp/cedet/ede/detect.el b/lisp/cedet/ede/detect.el
index 027d008..c933fc4 100644
--- a/lisp/cedet/ede/detect.el
+++ b/lisp/cedet/ede/detect.el
@@ -1,4 +1,4 @@
-;;; ede/detect.el --- EDE project detection and file associations
+;;; ede/detect.el --- EDE project detection and file associations  -*- 
lexical-binding: t; -*-
 
 ;; Copyright (C) 2014-2021 Free Software Foundation, Inc.
 
diff --git a/lisp/cedet/ede/dired.el b/lisp/cedet/ede/dired.el
index c85d4ee..2773517 100644
--- a/lisp/cedet/ede/dired.el
+++ b/lisp/cedet/ede/dired.el
@@ -1,4 +1,4 @@
-;;; ede/dired.el --- EDE extensions to dired.
+;;; ede/dired.el --- EDE extensions to dired.  -*- lexical-binding: t -*-
 
 ;; Copyright (C) 1998-2000, 2003, 2009-2021 Free Software Foundation,
 ;; Inc.
@@ -30,17 +30,16 @@
 
 ;;; Code:
 
-(require 'easymenu)
 (require 'dired)
 (require 'ede)
 
 (defvar ede-dired-keymap
   (let ((map (make-sparse-keymap)))
-    (define-key map ".a" 'ede-dired-add-to-target)
-    (define-key map ".t" 'ede-new-target)
-    (define-key map ".s" 'ede-speedbar)
-    (define-key map ".C" 'ede-compile-project)
-    (define-key map ".d" 'ede-make-dist)
+    (define-key map ".a" #'ede-dired-add-to-target)
+    (define-key map ".t" #'ede-new-target)
+    (define-key map ".s" #'ede-speedbar)
+    (define-key map ".C" #'ede-compile-project)
+    (define-key map ".d" #'ede-make-dist)
 
     (easy-menu-define
       ede-dired-menu map "EDE Dired Minor Mode Menu"
diff --git a/lisp/cedet/ede/emacs.el b/lisp/cedet/ede/emacs.el
index 1eb4c63..00496ac 100644
--- a/lisp/cedet/ede/emacs.el
+++ b/lisp/cedet/ede/emacs.el
@@ -1,4 +1,4 @@
-;;; ede/emacs.el --- Special project for Emacs
+;;; ede/emacs.el --- Special project for Emacs  -*- lexical-binding: t -*-
 
 ;; Copyright (C) 2008-2021 Free Software Foundation, Inc.
 
@@ -54,31 +54,6 @@ Return a tuple of ( EMACSNAME . VERSION )."
       (erase-buffer)
       (setq default-directory (file-name-as-directory dir))
       (cond
-       ;; Maybe XEmacs?
-       ((file-exists-p "version.sh")
-       (setq emacs "XEmacs")
-       (insert-file-contents "version.sh")
-       (goto-char (point-min))
-       (re-search-forward "emacs_major_version=\\([0-9]+\\)
-emacs_minor_version=\\([0-9]+\\)
-emacs_beta_version=\\([0-9]+\\)")
-       (setq ver (concat (match-string 1) "."
-                         (match-string 2) "."
-                         (match-string 3)))
-       )
-       ((file-exists-p "sxemacs.pc.in")
-       (setq emacs "SXEmacs")
-       (insert-file-contents "sxemacs_version.m4")
-       (goto-char (point-min))
-       (re-search-forward "m4_define(\\[SXEM4CS_MAJOR_VERSION\\], 
\\[\\([0-9]+\\)\\])
-m4_define(\\[SXEM4CS_MINOR_VERSION\\], \\[\\([0-9]+\\)\\])
-m4_define(\\[SXEM4CS_BETA_VERSION\\], \\[\\([0-9]+\\)\\])")
-       (setq ver (concat (match-string 1) "."
-                         (match-string 2) "."
-                         (match-string 3)))
-       )
-       ;; Insert other Emacs here...
-
        ;; Vaguely recent version of GNU Emacs?
        ((or (file-exists-p configure_ac)
            (file-exists-p (setq configure_ac "configure.in")))
diff --git a/lisp/cedet/ede/files.el b/lisp/cedet/ede/files.el
index cf5396a..6b7e159 100644
--- a/lisp/cedet/ede/files.el
+++ b/lisp/cedet/ede/files.el
@@ -1,4 +1,4 @@
-;;; ede/files.el --- Associate projects with files and directories.
+;;; ede/files.el --- Associate projects with files and directories.  -*- 
lexical-binding: t; -*-
 
 ;; Copyright (C) 2008-2021 Free Software Foundation, Inc.
 
@@ -33,6 +33,7 @@
 ;; till no ede-project-autoload structure matches.
 ;;
 
+(require 'eieio)
 (require 'ede)
 
 (declare-function ede-locate-file-in-hash "ede/locate")
@@ -75,13 +76,13 @@ Allows for one-project-object-for-a-tree type systems."
   (oref this rootproject))
 
 (cl-defmethod ede-project-root-directory ((this ede-project-placeholder)
-                                      &optional file)
+                                         &optional _file)
   "If a project knows its root, return it here.
 Allows for one-project-object-for-a-tree type systems.
 Optional FILE is the file to test.  It is ignored in preference
 of the anchor file for the project."
-  (let ((root (or (ede-project-root this) this)))
-    (file-name-directory (expand-file-name (oref this file)))))
+  ;; (let ((root (or (ede-project-root this) this)))
+  (file-name-directory (expand-file-name (oref this file)))) ;; )
 
 
 ;; Why INODEs?
@@ -141,7 +142,7 @@ Does not check subprojects."
 
 (defun ede-directory-get-open-project (dir &optional rootreturn)
   "Return an already open project that is managing DIR.
-Optional ROOTRETURN specifies a symbol to set to the root project.
+Optional ROOTRETURN specifies a `gv-ref' to set to the root project.
 If DIR is the root project, then it is the same."
   (let* ((inode (ede--inode-for-dir dir))
         (ft (file-name-as-directory (expand-file-name dir)))
@@ -153,7 +154,8 @@ If DIR is the root project, then it is the same."
     ;; Default answer is this project
     (setq ans proj)
     ;; Save.
-    (when rootreturn (set rootreturn proj))
+    (when rootreturn (if (symbolp rootreturn) (set rootreturn proj)
+                       (setf (gv-deref rootreturn) proj)))
     ;; Find subprojects.
     (when (and proj (if ede--disable-inode
                        (not (string= ft (expand-file-name
@@ -272,7 +274,7 @@ Do this whenever a new project is created, as opposed to 
loaded."
   (remhash (file-name-as-directory dir) ede-project-directory-hash)
   ;; Look for all subdirs of D, and remove them.
   (let ((match (concat "^" (regexp-quote dir))))
-    (maphash (lambda (K O)
+    (maphash (lambda (K _O)
                (when (string-match match K)
                  (remhash K ede-project-directory-hash)))
              ede-project-directory-hash)))
@@ -363,7 +365,7 @@ If DIR is not part of a project, return nil."
 
      (t nil))))
 
-(defalias 'ede-toplevel-project-or-nil 'ede-toplevel-project)
+(defalias 'ede-toplevel-project-or-nil #'ede-toplevel-project)
 
 ;;; DIRECTORY CONVERSION STUFF
 ;;
@@ -469,15 +471,15 @@ is returned."
 
     ans))
 
-(cl-defmethod ede-expand-filename-impl ((this ede-project) filename &optional 
force)
+(cl-defmethod ede-expand-filename-impl ((this ede-project) filename &optional 
_force)
   "Return a fully qualified file name based on project THIS.
 FILENAME should be just a filename which occurs in a directory controlled
 by this project.
 Optional argument FORCE forces the default filename to be provided even if it
 doesn't exist."
   (let ((loc (ede-get-locator-object this))
-       (path (ede-project-root-directory this))
-       (proj (oref this subproj))
+       ;; (path (ede-project-root-directory this))
+       ;; (proj (oref this subproj))
        (found nil))
     ;; find it Locally.
     (setq found (or (ede-expand-filename-local this filename)
diff --git a/lisp/cedet/ede/generic.el b/lisp/cedet/ede/generic.el
index 3d1e1c5..b3b59b5 100644
--- a/lisp/cedet/ede/generic.el
+++ b/lisp/cedet/ede/generic.el
@@ -1,4 +1,4 @@
-;;; ede/generic.el --- Base Support for generic build systems
+;;; ede/generic.el --- Base Support for generic build systems  -*- 
lexical-binding: t; -*-
 
 ;; Copyright (C) 2010-2021 Free Software Foundation, Inc.
 
@@ -93,7 +93,7 @@
    )
   "User Configuration object for a generic project.")
 
-(defun ede-generic-load (dir &optional rootproj)
+(defun ede-generic-load (dir &optional _rootproj)
   "Return a Generic Project object if there is a match.
 Return nil if there isn't one.
 Argument DIR is the directory it is created for.
@@ -149,7 +149,7 @@ The class allocated value is replace by different sub 
classes.")
   :abstract t)
 
 (cl-defmethod initialize-instance ((this ede-generic-project)
-                               &rest fields)
+                                  &rest _fields)
   "Make sure the targets slot is bound."
   (cl-call-next-method)
   (unless (slot-boundp this 'targets)
@@ -161,7 +161,7 @@ The class allocated value is replace by different sub 
classes.")
   this)
 
 (cl-defmethod ede-find-subproject-for-directory ((proj ede-generic-project)
-                                             dir)
+                                                _dir)
   "Return PROJ, for handling all subdirs below DIR."
   proj)
 
@@ -324,7 +324,7 @@ CLASS is the EIEIO class that is used to track this 
project.  It should subclass
    )
   "Generic Project for makefiles.")
 
-(cl-defmethod ede-generic-setup-configuration ((proj 
ede-generic-makefile-project) config)
+(cl-defmethod ede-generic-setup-configuration ((_proj 
ede-generic-makefile-project) config)
   "Setup a configuration for Make."
   (oset config build-command "make -k")
   (oset config debug-command "gdb ")
@@ -337,7 +337,7 @@ CLASS is the EIEIO class that is used to track this 
project.  It should subclass
    )
   "Generic Project for scons.")
 
-(cl-defmethod ede-generic-setup-configuration ((proj 
ede-generic-scons-project) config)
+(cl-defmethod ede-generic-setup-configuration ((_proj 
ede-generic-scons-project) config)
   "Setup a configuration for SCONS."
   (oset config build-command "scons")
   (oset config debug-command "gdb ")
@@ -350,7 +350,7 @@ CLASS is the EIEIO class that is used to track this 
project.  It should subclass
    )
   "Generic Project for cmake.")
 
-(cl-defmethod ede-generic-setup-configuration ((proj 
ede-generic-cmake-project) config)
+(cl-defmethod ede-generic-setup-configuration ((_proj 
ede-generic-cmake-project) config)
   "Setup a configuration for CMake."
   (oset config build-command "cmake")
   (oset config debug-command "gdb ")
@@ -361,9 +361,9 @@ CLASS is the EIEIO class that is used to track this 
project.  It should subclass
   ()
   "Generic project found via Version Control files.")
 
-(cl-defmethod ede-generic-setup-configuration ((proj ede-generic-vc-project) 
config)
+(cl-defmethod ede-generic-setup-configuration ((_proj ede-generic-vc-project) 
_config)
   "Setup a configuration for projects identified by revision control."
-  )
+  nil)
 
 (provide 'ede/generic)
 
diff --git a/lisp/cedet/ede/linux.el b/lisp/cedet/ede/linux.el
index 7a1c4c9..4b5530d 100644
--- a/lisp/cedet/ede/linux.el
+++ b/lisp/cedet/ede/linux.el
@@ -1,4 +1,4 @@
-;;; ede/linux.el --- Special project for Linux
+;;; ede/linux.el --- Special project for Linux  -*- lexical-binding: t; -*-
 
 ;; Copyright (C) 2008-2021 Free Software Foundation, Inc.
 
@@ -47,26 +47,22 @@
 (defcustom project-linux-build-directory-default 'ask
   "Build directory."
   :version "24.4"
-  :group 'project-linux
   :type '(choice (const :tag "Same as source directory" same)
                  (const :tag "Ask the user" ask)))
 
 (defcustom project-linux-architecture-default 'ask
   "Target architecture to assume when not auto-detected."
   :version "24.4"
-  :group 'project-linux
   :type '(choice (string :tag "Architecture name")
                  (const :tag "Ask the user" ask)))
 
 
 (defcustom project-linux-compile-target-command (concat ede-make-command " -k 
-C %s SUBDIRS=%s")
   "Default command used to compile a target."
-  :group 'project-linux
   :type 'string)
 
 (defcustom project-linux-compile-project-command (concat ede-make-command " -k 
-C %s")
   "Default command used to compile a project."
-  :group 'project-linux
   :type 'string)
 
 (defun ede-linux-version (dir)
diff --git a/lisp/cedet/ede/locate.el b/lisp/cedet/ede/locate.el
index e6a8953..016092c 100644
--- a/lisp/cedet/ede/locate.el
+++ b/lisp/cedet/ede/locate.el
@@ -1,4 +1,4 @@
-;;; ede/locate.el --- Locate support
+;;; ede/locate.el --- Locate support  -*- lexical-binding: t; -*-
 
 ;; Copyright (C) 2008-2021 Free Software Foundation, Inc.
 
@@ -110,7 +110,7 @@ based on `ede-locate-setup-options'."
    )
   "Baseclass for LOCATE feature in EDE.")
 
-(cl-defmethod initialize-instance ((loc ede-locate-base) &rest fields)
+(cl-defmethod initialize-instance ((loc ede-locate-base) &rest _fields)
   "Make sure we have a hash table."
   ;; Basic setup.
   (cl-call-next-method)
@@ -118,8 +118,8 @@ based on `ede-locate-setup-options'."
   (ede-locate-flush-hash loc)
   )
 
-(cl-defmethod ede-locate-ok-in-project ((loc (subclass ede-locate-base))
-                                            root)
+(cl-defmethod ede-locate-ok-in-project ((_loc (subclass ede-locate-base))
+                                       _root)
   "Is it ok to use this project type under ROOT."
   t)
 
@@ -149,17 +149,15 @@ that created this EDE locate object."
     (oset loc lastanswer ans)
     ans))
 
-(cl-defmethod ede-locate-file-in-project-impl ((loc ede-locate-base)
-                                           filesubstring
-                                           )
+(cl-defmethod ede-locate-file-in-project-impl ((_loc ede-locate-base)
+                                              _filesubstring)
   "Locate with LOC occurrences of FILESUBSTRING.
 Searches are done under the current root of the EDE project
 that created this EDE locate object."
-  nil
-  )
+  nil)
 
 (cl-defmethod ede-locate-create/update-root-database
-  ((loc (subclass ede-locate-base)) root)
+  ((loc (subclass ede-locate-base)) _root)
   "Create or update the database for the current project.
 You cannot create projects for the baseclass."
   (error "Cannot create/update a database of type %S"
@@ -177,8 +175,8 @@ You cannot create projects for the baseclass."
 Configure the Emacs `locate-program' variable to also
 configure the use of EDE locate.")
 
-(cl-defmethod ede-locate-ok-in-project ((loc (subclass ede-locate-locate))
-                                            root)
+(cl-defmethod ede-locate-ok-in-project ((_loc (subclass ede-locate-locate))
+                                       _root)
   "Is it ok to use this project type under ROOT."
   (or (featurep 'locate) (locate-library "locate"))
   )
@@ -198,7 +196,7 @@ that created this EDE locate object."
     (with-current-buffer b
       (setq default-directory cd)
       (erase-buffer))
-    (apply 'call-process locate-command
+    (apply #'call-process locate-command
           nil b nil
           searchstr nil)
     (with-current-buffer b
@@ -221,7 +219,7 @@ Configure EDE's use of GNU Global through the 
cedet-global.el
 variable `cedet-global-command'.")
 
 (cl-defmethod initialize-instance ((loc ede-locate-global)
-                               &rest slots)
+                                  &rest _slots)
   "Make sure that we can use GNU Global."
   (require 'cedet-global)
   ;; Get ourselves initialized.
@@ -235,8 +233,8 @@ variable `cedet-global-command'.")
             (oref loc root))))
   )
 
-(cl-defmethod ede-locate-ok-in-project ((loc (subclass ede-locate-global))
-                                            root)
+(cl-defmethod ede-locate-ok-in-project ((_loc (subclass ede-locate-global))
+                                       root)
   "Is it ok to use this project type under ROOT."
   (require 'cedet-global)
   (cedet-gnu-global-version-check)
@@ -252,7 +250,7 @@ variable `cedet-global-command'.")
     (cedet-gnu-global-expand-filename filesubstring)))
 
 (cl-defmethod ede-locate-create/update-root-database
-  ((loc (subclass ede-locate-global)) root)
+  ((_loc (subclass ede-locate-global)) root)
   "Create or update the GNU Global database for the current project."
   (cedet-gnu-global-create/update-database root))
 
@@ -271,7 +269,7 @@ Configure EDE's use of IDUtils through the cedet-idutils.el
 file name searching variable `cedet-idutils-file-command'.")
 
 (cl-defmethod initialize-instance ((loc ede-locate-idutils)
-                               &rest slots)
+                                  &rest _slots)
   "Make sure that we can use IDUtils."
   ;; Get ourselves initialized.
   (cl-call-next-method)
@@ -283,8 +281,8 @@ file name searching variable `cedet-idutils-file-command'.")
           (oref loc root)))
   )
 
-(cl-defmethod ede-locate-ok-in-project ((loc (subclass ede-locate-idutils))
-                                            root)
+(cl-defmethod ede-locate-ok-in-project ((_loc (subclass ede-locate-idutils))
+                                       root)
   "Is it ok to use this project type under ROOT."
   (require 'cedet-idutils)
   (cedet-idutils-version-check)
@@ -301,7 +299,7 @@ that created this EDE locate object."
     (cedet-idutils-expand-filename filesubstring)))
 
 (cl-defmethod ede-locate-create/update-root-database
-  ((loc (subclass ede-locate-idutils)) root)
+  ((_loc (subclass ede-locate-idutils)) root)
   "Create or update the GNU Global database for the current project."
   (cedet-idutils-create/update-database root))
 
@@ -320,7 +318,7 @@ Configure EDE's use of Cscope through the cedet-cscope.el
 file name searching variable `cedet-cscope-file-command'.")
 
 (cl-defmethod initialize-instance ((loc ede-locate-cscope)
-                               &rest slots)
+                                  &rest _slots)
   "Make sure that we can use Cscope."
   ;; Get ourselves initialized.
   (cl-call-next-method)
@@ -332,8 +330,8 @@ file name searching variable `cedet-cscope-file-command'.")
           (oref loc root)))
   )
 
-(cl-defmethod ede-locate-ok-in-project ((loc (subclass ede-locate-cscope))
-                                            root)
+(cl-defmethod ede-locate-ok-in-project ((_loc (subclass ede-locate-cscope))
+                                       root)
   "Is it ok to use this project type under ROOT."
   (require 'cedet-cscope)
   (cedet-cscope-version-check)
@@ -350,7 +348,7 @@ that created this EDE locate object."
     (cedet-cscope-expand-filename filesubstring)))
 
 (cl-defmethod ede-locate-create/update-root-database
-  ((loc (subclass ede-locate-cscope)) root)
+  ((_loc (subclass ede-locate-cscope)) root)
   "Create or update the Cscope database for the current project."
   (require 'cedet-cscope)
   (cedet-cscope-create/update-database root))
diff --git a/lisp/cedet/ede/make.el b/lisp/cedet/ede/make.el
index 863d715..3402020 100644
--- a/lisp/cedet/ede/make.el
+++ b/lisp/cedet/ede/make.el
@@ -1,6 +1,6 @@
-;;; ede/make.el --- General information about "make"
+;;; ede/make.el --- General information about "make"  -*- lexical-binding: t 
-*-
 
-;;; Copyright (C) 2009-2021 Free Software Foundation, Inc.
+;; Copyright (C) 2009-2021  Free Software Foundation, Inc.
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
 
@@ -30,8 +30,6 @@
 
 ;;; Code:
 
-(declare-function inversion-check-version "inversion")
-
 (defsubst ede--find-executable (exec)
   "Return an expanded file name for a program EXEC on the exec path."
   (declare (obsolete locate-file "28.1"))
@@ -60,8 +58,7 @@ If NOERROR is nil, then throw an error on failure.  Return t 
otherwise."
   (let ((b (get-buffer-create "*EDE Make Version*"))
        (cd default-directory)
        (rev nil)
-       (ans nil)
-       )
+        (ans nil))
     (with-current-buffer b
       ;; Setup, and execute make.
       (setq default-directory cd)
@@ -70,18 +67,18 @@ If NOERROR is nil, then throw an error on failure.  Return 
t otherwise."
                    "--version")
       ;; Check the buffer for the string
       (goto-char (point-min))
-      (when (looking-at "GNU Make\\(?: version\\)? \\([0-9][^,]+\\),")
+      (when (looking-at "GNU Make\\(?: version\\)? 
\\([0-9][^,[:space:]]+\\),?")
        (setq rev (match-string 1))
-       (require 'inversion)
-       (setq ans (not (inversion-check-version rev nil ede-make-min-version))))
+        (setq ans (not (version< rev ede-make-min-version))))
 
       ;; Answer reporting.
       (when (and (called-interactively-p 'interactive) ans)
        (message "GNU Make version %s.  Good enough for CEDET." rev))
 
       (when (and (not noerror) (not ans))
-       (error "EDE requires GNU Make version %s or later.  Configure 
`ede-make-command' to fix"
-              ede-make-min-version))
+        (error "EDE requires GNU Make version %s or later (found %s).  
Configure `ede-make-command' to fix"
+               ede-make-min-version
+               rev))
       ans)))
 
 (provide 'ede/make)
diff --git a/lisp/cedet/ede/makefile-edit.el b/lisp/cedet/ede/makefile-edit.el
index 43655a5..d696594 100644
--- a/lisp/cedet/ede/makefile-edit.el
+++ b/lisp/cedet/ede/makefile-edit.el
@@ -1,4 +1,4 @@
-;;; makefile-edit.el --- Makefile editing/scanning commands.
+;;; makefile-edit.el --- Makefile editing/scanning commands.  -*- 
lexical-binding: t; -*-
 
 ;; Copyright (C) 2009-2021 Free Software Foundation, Inc.
 
diff --git a/lisp/cedet/ede/pconf.el b/lisp/cedet/ede/pconf.el
index 5bed32f..c5b2ea4 100644
--- a/lisp/cedet/ede/pconf.el
+++ b/lisp/cedet/ede/pconf.el
@@ -1,7 +1,6 @@
-;;; ede/pconf.el --- configure.ac maintenance for EDE
+;;; ede/pconf.el --- configure.ac maintenance for EDE  -*- lexical-binding: t; 
-*-
 
-;;; Copyright (C) 1998-2000, 2005, 2008-2021 Free Software Foundation,
-;;; Inc.
+;; Copyright (C) 1998-2021  Free Software Foundation, Inc.
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
 ;; Keywords: project
@@ -67,7 +66,7 @@ don't do it.  A value of nil means to just do it.")
        ;;(td (file-name-directory (ede-proj-configure-file this)))
        (targs (oref this targets))
        (postcmd "")
-       (add-missing nil))
+       ) ;; (add-missing nil)
     ;; First, make sure we have a file.
     (if (not (file-exists-p (ede-proj-configure-file this)))
        (autoconf-new-program b (oref this name) "Project.ede"))
@@ -97,7 +96,7 @@ don't do it.  A value of nil means to just do it.")
        (ede-map-targets sp #'ede-proj-flush-autoconf)))
     (ede-map-all-subprojects
      this
-     (lambda (sp)
+     (lambda (_sp)
        (ede-map-targets this #'ede-proj-tweak-autoconf)))
     ;; Now save
     (save-buffer)
@@ -109,14 +108,15 @@ don't do it.  A value of nil means to just do it.")
     (ede-proj-configure-test-required-file this "README")
     (ede-proj-configure-test-required-file this "ChangeLog")
     ;; Let specific targets get missing files.
-    (mapc 'ede-proj-configure-create-missing targs)
+    (mapc #'ede-proj-configure-create-missing targs)
     ;; Verify that we have a make system.
     (if (or (not (ede-expand-filename (ede-toplevel this) "Makefile"))
            ;; Now is this one of our old Makefiles?
            (with-current-buffer
                 (find-file-noselect
                  (ede-expand-filename (ede-toplevel this)
-                                      "Makefile" t) t)
+                                      "Makefile" t)
+                 t)
              (goto-char (point-min))
              ;; Here is the unique piece for our makefiles.
              (re-search-forward "For use with: make" nil t)))
@@ -166,11 +166,11 @@ don't do it.  A value of nil means to just do it.")
   "Tweak the configure file (current buffer) to accommodate THIS."
   ;; Check the compilers belonging to THIS, and call the autoconf
   ;; setup for those compilers.
-  (mapc 'ede-proj-tweak-autoconf (ede-proj-compilers this))
-  (mapc 'ede-proj-tweak-autoconf (ede-proj-linkers this))
+  (mapc #'ede-proj-tweak-autoconf (ede-proj-compilers this))
+  (mapc #'ede-proj-tweak-autoconf (ede-proj-linkers this))
   )
 
-(cl-defmethod ede-proj-flush-autoconf ((this ede-proj-target))
+(cl-defmethod ede-proj-flush-autoconf ((_this ede-proj-target))
   "Flush the configure file (current buffer) to accommodate THIS.
 By flushing, remove any cruft that may be in the file.  Subsequent
 calls to `ede-proj-tweak-autoconf' can restore items removed by flush."
@@ -178,13 +178,13 @@ calls to `ede-proj-tweak-autoconf' can restore items 
removed by flush."
 
 
 ;; @TODO - No-one calls this ???
-(cl-defmethod ede-proj-configure-add-missing ((this ede-proj-target))
+(cl-defmethod ede-proj-configure-add-missing ((_this ede-proj-target))
   "Query if any files needed by THIS provided by automake are missing.
 Results in --add-missing being passed to automake."
   nil)
 
 ;; @TODO - No-one implements this yet.
-(cl-defmethod ede-proj-configure-create-missing ((this ede-proj-target))
+(cl-defmethod ede-proj-configure-create-missing ((_this ede-proj-target))
   "Add any missing files for THIS by creating them."
   nil)
 
diff --git a/lisp/cedet/ede/pmake.el b/lisp/cedet/ede/pmake.el
index 4c948df..fd6918c 100644
--- a/lisp/cedet/ede/pmake.el
+++ b/lisp/cedet/ede/pmake.el
@@ -1,4 +1,4 @@
-;;; ede-pmake.el --- EDE Generic Project Makefile code generator.
+;;; ede-pmake.el --- EDE Generic Project Makefile code generator  -*- 
lexical-binding: t; -*-
 
 ;; Copyright (C) 1998-2005, 2007-2021 Free Software Foundation, Inc.
 
@@ -46,6 +46,7 @@
 (require 'ede/proj)
 (require 'ede/proj-obj)
 (require 'ede/proj-comp)
+(require 'seq)
 
 (declare-function ede-srecode-setup "ede/srecode")
 (declare-function ede-srecode-insert "ede/srecode")
@@ -111,13 +112,13 @@ MFILENAME is the makefile to generate."
 
        (let* ((targ (if isdist (oref this targets) mt))
               (sp (oref this subproj))
-              (df (apply 'append
+              (df (apply #'append
                          (mapcar (lambda (tg)
                                    (ede-proj-makefile-dependency-files tg))
                                  targ))))
          ;; Distribution variables
          (ede-compiler-begin-unique
-           (mapc 'ede-proj-makefile-insert-variables targ))
+           (mapc #'ede-proj-makefile-insert-variables targ))
          ;; Only add the distribution stuff in when depth != 0
          (let ((top  (ede-toplevel this))
                (tmp this)
@@ -153,7 +154,8 @@ MFILENAME is the makefile to generate."
                                     (concat ".deps/"
                                             (file-name-nondirectory
                                              (file-name-sans-extension
-                                              f)) ".P"))
+                                              f))
+                                            ".P"))
                                   df " "))))
          ;;
          ;; Insert ALL Rule
@@ -188,11 +190,11 @@ MFILENAME is the makefile to generate."
          ;;
          (ede-compiler-begin-unique
            (ede-proj-makefile-insert-rules this)
-           (mapc 'ede-proj-makefile-insert-rules targ))
+           (mapc #'ede-proj-makefile-insert-rules targ))
          ;;
          ;; phony targets for sub projects
          ;;
-         (mapc 'ede-proj-makefile-insert-subproj-rules sp)
+         (mapc #'ede-proj-makefile-insert-subproj-rules sp)
          ;;
          ;; Distribution rules such as CLEAN and DIST
          ;;
@@ -210,11 +212,11 @@ MFILENAME is the makefile to generate."
        ;; Distribution variables
        (let ((targ (if isdist (oref this targets) mt)))
          (ede-compiler-begin-unique
-           (mapc 'ede-proj-makefile-insert-automake-pre-variables targ))
+           (mapc #'ede-proj-makefile-insert-automake-pre-variables targ))
          (ede-compiler-begin-unique
-           (mapc 'ede-proj-makefile-insert-source-variables targ))
+           (mapc #'ede-proj-makefile-insert-source-variables targ))
          (ede-compiler-begin-unique
-           (mapc 'ede-proj-makefile-insert-automake-post-variables targ))
+           (mapc #'ede-proj-makefile-insert-automake-post-variables targ))
          (ede-compiler-begin-unique
            (ede-proj-makefile-insert-user-rules this))
          (insert "\n# End of Makefile.am\n")
@@ -241,6 +243,7 @@ MFILENAME is the makefile to generate."
 (defmacro ede-pmake-insert-variable-shared (varname &rest body)
   "Add VARNAME into the current Makefile.
 Execute BODY in a location where a value can be placed."
+  (declare (debug t) (indent 1))
   `(let ((addcr t) (v ,varname))
      (if (save-excursion
           (goto-char (point-max))
@@ -258,20 +261,19 @@ Execute BODY in a location where a value can be placed."
      ,@body
      (if addcr (insert "\n"))
      (goto-char (point-max))))
-(put 'ede-pmake-insert-variable-shared 'lisp-indent-function 1)
 
 (defmacro ede-pmake-insert-variable-once (varname &rest body)
   "Add VARNAME into the current Makefile if it doesn't exist.
 Execute BODY in a location where a value can be placed."
-  `(let ((addcr t) (v ,varname))
-       (unless
-          (save-excursion
-            (re-search-backward (concat "^" v "\\s-*=") nil t))
-        (insert v "=")
-        ,@body
-        (when addcr (insert "\n"))
-        (goto-char (point-max)))))
-(put 'ede-pmake-insert-variable-once 'lisp-indent-function 1)
+  (declare (debug t) (indent 1))
+  `(let ((v ,varname))
+     (unless
+        (save-excursion
+          (re-search-backward (concat "^" v "\\s-*=") nil t))
+       (insert v "=")
+       ,@body
+       (insert "\n")
+       (goto-char (point-max)))))
 
 ;;; SOURCE VARIABLE NAME CONSTRUCTION
 
@@ -289,7 +291,7 @@ Change .  to _ in the variable name."
 
 ;;; DEPENDENCY FILE GENERATOR LISTS
 ;;
-(cl-defmethod ede-proj-makefile-dependency-files ((this ede-proj-target))
+(cl-defmethod ede-proj-makefile-dependency-files ((_this ede-proj-target))
   "Return a list of source files to convert to dependencies.
 Argument THIS is the target to get sources from."
   nil)
@@ -302,7 +304,7 @@ Argument THIS is the target to get sources from."
 Use CONFIGURATION as the current configuration to query."
   (cdr (assoc configuration (oref this configuration-variables))))
 
-(cl-defmethod ede-proj-makefile-insert-variables-new ((this ede-proj-project))
+(cl-defmethod ede-proj-makefile-insert-variables-new ((_this ede-proj-project))
   "Insert variables needed by target THIS.
 
 NOTE: Not yet in use!  This is part of an SRecode conversion of
@@ -420,7 +422,7 @@ Use CONFIGURATION as the current configuration to query."
   (cdr (assoc configuration (oref this configuration-variables))))
 
 (cl-defmethod ede-proj-makefile-insert-variables ((this 
ede-proj-target-makefile)
-                                              &optional moresource)
+                                              &optional _moresource)
   "Insert variables needed by target THIS.
 Optional argument MORESOURCE is a list of additional sources to add to the
 sources variable."
@@ -428,11 +430,11 @@ sources variable."
   (let* ((proj (ede-target-parent this))
         (conf-table (ede-proj-makefile-configuration-variables
                      this (oref proj configuration-default)))
-        (conf-done nil)
+        ;; (conf-done nil)
         )
     ;; Add in all variables from the configuration not already covered.
     (mapc (lambda (c)
-           (if (member (car c) conf-done)
+           (if nil ;; (member (car c) conf-done)
                nil
              (insert (car c) "=" (cdr c) "\n")))
          conf-table))
@@ -449,12 +451,12 @@ sources variable."
                            (ede-proj-makefile-insert-variables linker)))))
 
 (cl-defmethod ede-proj-makefile-insert-automake-pre-variables
-  ((this ede-proj-target))
+  ((_this ede-proj-target))
   "Insert variables needed by target THIS in Makefile.am before SOURCES."
   nil)
 
 (cl-defmethod ede-proj-makefile-insert-automake-post-variables
-  ((this ede-proj-target))
+  ((_this ede-proj-target))
   "Insert variables needed by target THIS in Makefile.am after SOURCES."
   nil)
 
@@ -464,9 +466,9 @@ sources variable."
   "Return a list of patterns that are considered garbage to THIS.
 These are removed with make clean."
   (let ((mc (ede-map-targets
-            this (lambda (c) (ede-proj-makefile-garbage-patterns c))))
+            this #'ede-proj-makefile-garbage-patterns))
        (uniq nil))
-    (setq mc (sort (apply 'append mc) 'string<))
+    (setq mc (sort (apply #'append mc) #'string<))
     ;; Filter out duplicates from the targets.
     (while mc
       (if (and (car uniq) (string= (car uniq) (car mc)))
@@ -502,16 +504,16 @@ These are removed with make clean."
 
 (cl-defmethod ede-proj-makefile-insert-rules ((this ede-proj-project))
   "Insert rules needed by THIS target."
-  (mapc 'ede-proj-makefile-insert-rules (oref this inference-rules))
+  (mapc #'ede-proj-makefile-insert-rules (oref this inference-rules))
   )
 
 (cl-defmethod ede-proj-makefile-insert-dist-dependencies ((this 
ede-proj-project))
   "Insert any symbols that the DIST rule should depend on.
 Argument THIS is the project that should insert stuff."
-  (mapc 'ede-proj-makefile-insert-dist-dependencies (oref this targets))
+  (mapc #'ede-proj-makefile-insert-dist-dependencies (oref this targets))
   )
 
-(cl-defmethod ede-proj-makefile-insert-dist-dependencies ((this 
ede-proj-target))
+(cl-defmethod ede-proj-makefile-insert-dist-dependencies ((_this 
ede-proj-target))
   "Insert any symbols that the DIST rule should depend on.
 Argument THIS is the target that should insert stuff."
   nil)
@@ -530,7 +532,7 @@ Argument THIS is the target that should insert stuff."
            (insert " " (ede-subproject-relative-path sproj))
            ))))
 
-(cl-defmethod ede-proj-makefile-automake-insert-extradist ((this 
ede-proj-project))
+(cl-defmethod ede-proj-makefile-automake-insert-extradist ((_this 
ede-proj-project))
   "Insert the EXTRADIST variable entries needed for Automake and EDE."
   (proj-comp-insert-variable-once "EXTRA_DIST" (insert "Project.ede")))
 
@@ -602,16 +604,16 @@ Argument THIS is the target that should insert stuff."
            "\t@false\n\n"
            "\n\n# End of Makefile\n")))
 
-(cl-defmethod ede-proj-makefile-insert-rules ((this ede-proj-target))
+(cl-defmethod ede-proj-makefile-insert-rules ((_this ede-proj-target))
   "Insert rules needed by THIS target."
   nil)
 
 (cl-defmethod ede-proj-makefile-insert-rules ((this ede-proj-target-makefile))
   "Insert rules needed by THIS target."
-  (mapc 'ede-proj-makefile-insert-rules (oref this rules))
+  (mapc #'ede-proj-makefile-insert-rules (oref this rules))
   (let ((c (ede-proj-compilers this)))
     (when c
-      (mapc 'ede-proj-makefile-insert-rules c)
+      (mapc #'ede-proj-makefile-insert-rules c)
       (if (oref this phony)
          (insert ".PHONY: " (ede-proj-makefile-target-name this) "\n"))
       (insert (ede-proj-makefile-target-name this) ": "
@@ -622,9 +624,9 @@ Argument THIS is the target that should insert stuff."
 (cl-defmethod ede-proj-makefile-insert-commands ((this 
ede-proj-target-makefile))
   "Insert the commands needed by target THIS.
 For targets, insert the commands needed by the chosen compiler."
-  (mapc 'ede-proj-makefile-insert-commands (ede-proj-compilers this))
+  (mapc #'ede-proj-makefile-insert-commands (ede-proj-compilers this))
   (when (object-assoc t :uselinker (ede-proj-compilers this))
-    (mapc 'ede-proj-makefile-insert-commands (ede-proj-linkers this))))
+    (mapc #'ede-proj-makefile-insert-commands (ede-proj-linkers this))))
 
 
 (cl-defmethod ede-proj-makefile-insert-user-rules ((this ede-proj-project))
@@ -632,11 +634,11 @@ For targets, insert the commands needed by the chosen 
compiler."
 This is different from `ede-proj-makefile-insert-rules' in that this
 function won't create the building rules which are auto created with
 automake."
-  (mapc 'ede-proj-makefile-insert-user-rules (oref this inference-rules)))
+  (mapc #'ede-proj-makefile-insert-user-rules (oref this inference-rules)))
 
 (cl-defmethod ede-proj-makefile-insert-user-rules ((this ede-proj-target))
   "Insert user specified rules needed by THIS target."
-  (mapc 'ede-proj-makefile-insert-rules (oref this rules)))
+  (mapc #'ede-proj-makefile-insert-rules (oref this rules)))
 
 (cl-defmethod ede-proj-makefile-dependencies ((this ede-proj-target-makefile))
   "Return a string representing the dependencies for THIS.
@@ -644,7 +646,7 @@ Some compilers only use the first element in the 
dependencies, others
 have a list of intermediates (object files), and others don't care.
 This allows customization of how these elements appear."
   (let* ((c (ede-proj-compilers this))
-        (io (eval (cons 'or (mapcar 'ede-compiler-intermediate-objects-p c))))
+        (io (seq-some #'ede-compiler-intermediate-objects-p c))
         (out nil))
     (if io
        (progn
@@ -652,7 +654,8 @@ This allows customization of how these elements appear."
            (setq out
                  (concat out "$(" (ede-compiler-intermediate-object-variable
                                    (car c)
-                                   (ede-proj-makefile-target-name this)) ")")
+                                   (ede-proj-makefile-target-name this))
+                         ")")
                  c (cdr c)))
          out)
       (let ((sv (ede-proj-makefile-sourcevar this))
diff --git a/lisp/cedet/ede/proj-archive.el b/lisp/cedet/ede/proj-archive.el
index 038f994..9da6374 100644
--- a/lisp/cedet/ede/proj-archive.el
+++ b/lisp/cedet/ede/proj-archive.el
@@ -1,4 +1,4 @@
-;;; ede/proj-archive.el --- EDE Generic Project archive support
+;;; ede/proj-archive.el --- EDE Generic Project archive support  -*- 
lexical-binding: t -*-
 
 ;;  Copyright (C) 1998-2001, 2009-2021 Free Software Foundation, Inc.
 
@@ -45,7 +45,7 @@
   "Linker object for creating an archive.")
 
 (cl-defmethod ede-proj-makefile-insert-source-variables :before
-  ((this ede-proj-target-makefile-archive) &optional moresource)
+  ((this ede-proj-target-makefile-archive) &optional _moresource)
   "Insert bin_PROGRAMS variables needed by target THIS.
 We aren't actually inserting SOURCE details, but this is used by the
 Makefile.am generator, so use it to add this important bin program."
diff --git a/lisp/cedet/ede/proj-aux.el b/lisp/cedet/ede/proj-aux.el
index f5bcebd..7325955 100644
--- a/lisp/cedet/ede/proj-aux.el
+++ b/lisp/cedet/ede/proj-aux.el
@@ -1,4 +1,4 @@
-;;; ede/proj-aux.el --- EDE Generic Project auxiliary file support
+;;; ede/proj-aux.el --- EDE Generic Project auxiliary file support  -*- 
lexical-binding: t -*-
 
 ;; Copyright (C) 1998-2000, 2007, 2009-2021 Free Software Foundation,
 ;; Inc.
diff --git a/lisp/cedet/ede/proj-comp.el b/lisp/cedet/ede/proj-comp.el
index 26aa668..0d797aa 100644
--- a/lisp/cedet/ede/proj-comp.el
+++ b/lisp/cedet/ede/proj-comp.el
@@ -1,4 +1,4 @@
-;;; ede/proj-comp.el --- EDE Generic Project compiler/rule driver
+;;; ede/proj-comp.el --- EDE Generic Project compiler/rule driver  -*- 
lexical-binding: t; -*-
 
 ;; Copyright (C) 1999-2001, 2004-2005, 2007, 2009-2021 Free Software
 ;; Foundation, Inc.
@@ -172,12 +172,12 @@ Adds this rule to a .PHONY list."))
 This is used when creating a Makefile to prevent duplicate variables and
 rules from being created.")
 
-(cl-defmethod initialize-instance :after ((this ede-compiler) &rest fields)
+(cl-defmethod initialize-instance :after ((this ede-compiler) &rest _fields)
   "Make sure that all ede compiler objects are cached in
 `ede-compiler-list'."
   (add-to-list 'ede-compiler-list this))
 
-(cl-defmethod initialize-instance :after ((this ede-linker) &rest fields)
+(cl-defmethod initialize-instance :after ((this ede-linker) &rest _fields)
   "Make sure that all ede compiler objects are cached in
 `ede-linker-list'."
   (add-to-list 'ede-linker-list this))
@@ -185,11 +185,13 @@ rules from being created.")
 (defmacro ede-compiler-begin-unique (&rest body)
   "Execute BODY, making sure that `ede-current-build-list' is maintained.
 This will prevent rules from creating duplicate variables or rules."
+  (declare (indent 0) (debug t))
   `(let ((ede-current-build-list nil))
     ,@body))
 
 (defmacro ede-compiler-only-once (object &rest body)
   "Using OBJECT, execute BODY only once per Makefile generation."
+  (declare (indent 1) (debug t))
   `(if (not (member ,object ede-current-build-list))
        (progn
         (add-to-list 'ede-current-build-list ,object)
@@ -198,25 +200,18 @@ This will prevent rules from creating duplicate variables 
or rules."
 (defmacro ede-linker-begin-unique (&rest body)
   "Execute BODY, making sure that `ede-current-build-list' is maintained.
 This will prevent rules from creating duplicate variables or rules."
+  (declare (indent 0) (debug t))
   `(let ((ede-current-build-list nil))
     ,@body))
 
 (defmacro ede-linker-only-once (object &rest body)
   "Using OBJECT, execute BODY only once per Makefile generation."
+  (declare (indent 1) (debug t))
   `(if (not (member ,object ede-current-build-list))
        (progn
         (add-to-list 'ede-current-build-list ,object)
         ,@body)))
 
-(add-hook 'edebug-setup-hook
-         (lambda ()
-           (def-edebug-spec ede-compiler-begin-unique def-body)
-           (def-edebug-spec ede-compiler-only-once (form def-body))
-           (def-edebug-spec ede-linker-begin-unique def-body)
-           (def-edebug-spec ede-linker-only-once (form def-body))
-           (def-edebug-spec ede-pmake-insert-variable-shared (form def-body))
-           ))
-
 ;;; Queries
 (defun ede-proj-find-compiler (compilers sourcetype)
   "Return a compiler from the list COMPILERS that will compile SOURCETYPE."
@@ -246,21 +241,20 @@ This will prevent rules from creating duplicate variables 
or rules."
      )
    (oref this autoconf)))
 
-(cl-defmethod ede-proj-flush-autoconf ((this ede-compilation-program))
+(cl-defmethod ede-proj-flush-autoconf ((_this ede-compilation-program))
   "Flush the configure file (current buffer) to accommodate THIS."
   nil)
 
 (defmacro proj-comp-insert-variable-once (varname &rest body)
   "Add VARNAME into the current Makefile if it doesn't exist.
 Execute BODY in a location where a value can be placed."
-  `(let ((addcr t) (v ,varname))
+  (declare (indent 1) (debug (sexp body)))
+  `(let ((v ,varname))
      (unless (re-search-backward (concat "^" v "\\s-*=") nil t)
        (insert v "=")
        ,@body
-       (if addcr (insert "\n"))
-       (goto-char (point-max)))
-     ))
-(put 'proj-comp-insert-variable-once 'lisp-indent-function 1)
+       (insert "\n")
+       (goto-char (point-max)))))
 
 (cl-defmethod ede-proj-makefile-insert-variables ((this 
ede-compilation-program))
   "Insert variables needed by the compiler THIS."
@@ -281,8 +275,8 @@ If this compiler creates code that can be linked together,
 then the object files created by the compiler are considered intermediate."
   (oref this uselinker))
 
-(cl-defmethod ede-compiler-intermediate-object-variable ((this ede-compiler)
-                                                     targetname)
+(cl-defmethod ede-compiler-intermediate-object-variable ((_this ede-compiler)
+                                                        targetname)
   "Return a string based on THIS representing a make object variable.
 TARGETNAME is the name of the target that these objects belong to."
   (concat targetname "_OBJ"))
@@ -314,7 +308,7 @@ Not all compilers do this."
 (cl-defmethod ede-proj-makefile-insert-rules ((this ede-compilation-program))
   "Insert rules needed for THIS compiler object."
   (ede-compiler-only-once this
-    (mapc 'ede-proj-makefile-insert-rules (oref this rules))))
+    (mapc #'ede-proj-makefile-insert-rules (oref this rules))))
 
 (cl-defmethod ede-proj-makefile-insert-rules ((this ede-makefile-rule))
   "Insert rules needed for THIS rule object."
@@ -343,16 +337,6 @@ compiler it decides to use after inserting in the rule."
        commands))
     (insert "\n")))
 
-;;; Some details about our new macro
-;;
-(add-hook 'edebug-setup-hook
-         (lambda ()
-           (def-edebug-spec ede-compiler-begin-unique def-body)))
-(put 'ede-compiler-begin-unique 'lisp-indent-function 0)
-(put 'ede-compiler-only-once 'lisp-indent-function 1)
-(put 'ede-linker-begin-unique 'lisp-indent-function 0)
-(put 'ede-linker-only-once 'lisp-indent-function 1)
-
 (provide 'ede/proj-comp)
 
 ;;; ede/proj-comp.el ends here
diff --git a/lisp/cedet/ede/proj-elisp.el b/lisp/cedet/ede/proj-elisp.el
index 9ec9694..7e0f5a8 100644
--- a/lisp/cedet/ede/proj-elisp.el
+++ b/lisp/cedet/ede/proj-elisp.el
@@ -1,4 +1,4 @@
-;;; ede-proj-elisp.el --- EDE Generic Project Emacs Lisp support
+;;; ede-proj-elisp.el --- EDE Generic Project Emacs Lisp support  -*- 
lexical-binding: t; -*-
 
 ;; Copyright (C) 1998-2005, 2007-2021 Free Software Foundation, Inc.
 
@@ -64,7 +64,7 @@ This inserts the PRELOADS target-local variable."
       (when preloads
        (insert (format "%s: PRELOADS=%s\n"
                        (oref this name)
-                       (mapconcat 'identity preloads " ")))))
+                       (mapconcat #'identity preloads " ")))))
     (insert "\n"))
 
 (cl-defmethod ede-proj-makefile-dependencies ((this ede-proj-target-elisp))
@@ -152,7 +152,7 @@ Bonus: Return a cons cell: (COMPILED . UPTODATE)."
         (utd 0))
     (mapc (lambda (src)
            (let* ((fsrc (expand-file-name src dir))
-                  (elc (concat (file-name-sans-extension fsrc) ".elc")))
+                  ) ;; (elc (concat (file-name-sans-extension fsrc) ".elc"))
              (with-no-warnings
                 (if (eq (byte-recompile-file fsrc nil 0) t)
                     (setq comp (1+ comp))
@@ -169,7 +169,7 @@ is found, such as a `-version' variable, or the standard 
header."
   (if (and (slot-boundp this 'versionsource)
           (oref this versionsource))
       (let ((vs (oref this versionsource))
-           (match nil))
+           ) ;; (match nil)
        (while vs
          (with-current-buffer (find-file-noselect
                                 (ede-expand-filename this (car vs)))
@@ -177,7 +177,7 @@ is found, such as a `-version' variable, or the standard 
header."
            (let ((case-fold-search t))
              (if (re-search-forward "-version\\s-+\"\\([^\"]+\\)\"" nil t)
                  (progn
-                   (setq match t)
+                   ;; (setq match t)
                    (delete-region (match-beginning 1)
                                   (match-end 1))
                    (goto-char (match-beginning 1))
@@ -331,27 +331,27 @@ Lays claim to all .elc files that match .el files in this 
target."
 If the `compiler' slot is empty, get the car of the compilers list."
   (let ((comp (oref obj compiler)))
     (if comp
-       (if (listp comp)
-           (setq comp (mapcar 'symbol-value comp))
-         (setq comp (list (symbol-value comp))))
+       (setq comp (if (listp comp)
+                      (mapcar #'symbol-value comp)
+                    (list (symbol-value comp))))
       ;; Get the first element from our list of compilers.
-      (let ((avail (mapcar 'symbol-value (oref obj availablecompilers))))
+      (let ((avail (mapcar #'symbol-value (oref obj availablecompilers))))
        (setq comp (list (car avail)))))
     comp))
 
-(cl-defmethod ede-proj-makefile-insert-source-variables ((this 
ede-proj-target-elisp-autoloads)
-                                                     &optional
-                                                     moresource)
+(cl-defmethod ede-proj-makefile-insert-source-variables ((_this 
ede-proj-target-elisp-autoloads)
+                                                        &optional
+                                                        _moresource)
   "Insert the source variables needed by THIS.
 Optional argument MORESOURCE is a list of additional sources to add to the
 sources variable."
   nil)
 
-(cl-defmethod ede-proj-makefile-sourcevar ((this 
ede-proj-target-elisp-autoloads))
+(cl-defmethod ede-proj-makefile-sourcevar ((_this 
ede-proj-target-elisp-autoloads))
   "Return the variable name for THIS's sources."
   nil) ; "LOADDEFS")
 
-(cl-defmethod ede-proj-makefile-dependencies ((this 
ede-proj-target-elisp-autoloads))
+(cl-defmethod ede-proj-makefile-dependencies ((_this 
ede-proj-target-elisp-autoloads))
   "Return a string representing the dependencies for THIS.
 Always return an empty string for an autoloads generator."
   "")
@@ -361,21 +361,22 @@ Always return an empty string for an autoloads generator."
   (ede-pmake-insert-variable-shared "LOADDEFS"
     (insert (oref this autoload-file)))
   (ede-pmake-insert-variable-shared "LOADDIRS"
-    (insert (mapconcat 'identity
+    (insert (mapconcat #'identity
                        (or (oref this autoload-dirs) '("."))
                        " ")))
   )
 
 (cl-defmethod project-compile-target ((obj ede-proj-target-elisp-autoloads))
   "Create or update the autoload target."
-  (require 'cedet-autogen)
+  (require 'cedet-autogen)              ;FIXME: We don't have this file!
+  (declare-function cedet-update-autoloads "cedet-autogen")
   (let ((default-directory (ede-expand-filename obj ".")))
-    (apply 'cedet-update-autoloads
+    (apply #'cedet-update-autoloads
           (oref obj autoload-file)
           (oref obj autoload-dirs))
     ))
 
-(cl-defmethod ede-update-version-in-source ((this 
ede-proj-target-elisp-autoloads) version)
+(cl-defmethod ede-update-version-in-source ((_this 
ede-proj-target-elisp-autoloads) _version)
   "In a Lisp file, updated a version string for THIS to VERSION.
 There are standards in Elisp files specifying how the version string
 is found, such as a `-version' variable, or the standard header."
@@ -397,11 +398,11 @@ Argument THIS is the target which needs to insert an info 
file."
   (insert " " (oref this autoload-file))
   )
 
-(cl-defmethod ede-proj-tweak-autoconf ((this ede-proj-target-elisp-autoloads))
+(cl-defmethod ede-proj-tweak-autoconf ((_this ede-proj-target-elisp-autoloads))
   "Tweak the configure file (current buffer) to accommodate THIS."
   (error "Autoloads not supported in autoconf yet"))
 
-(cl-defmethod ede-proj-flush-autoconf ((this ede-proj-target-elisp-autoloads))
+(cl-defmethod ede-proj-flush-autoconf ((_this ede-proj-target-elisp-autoloads))
   "Flush the configure file (current buffer) to accommodate THIS."
   nil)
 
diff --git a/lisp/cedet/ede/proj-info.el b/lisp/cedet/ede/proj-info.el
index 3d43701..dbb86ed 100644
--- a/lisp/cedet/ede/proj-info.el
+++ b/lisp/cedet/ede/proj-info.el
@@ -1,7 +1,6 @@
-;;; ede-proj-info.el --- EDE Generic Project texinfo support
+;;; ede-proj-info.el --- EDE Generic Project texinfo support  -*- 
lexical-binding: t; -*-
 
-;;; Copyright (C) 1998-2001, 2004, 2007-2021 Free Software Foundation,
-;;; Inc.
+;; Copyright (C) 1998-2021  Free Software Foundation, Inc.
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
 ;; Keywords: project, make
@@ -70,7 +69,7 @@ All other sources should be included independently."))
 ;;; Makefile generation
 ;;
 (cl-defmethod ede-proj-configure-add-missing
-  ((this ede-proj-target-makefile-info))
+  ((_this ede-proj-target-makefile-info))
   "Query if any files needed by THIS provided by automake are missing.
 Results in --add-missing being passed to automake."
   (not (ede-expand-filename (ede-toplevel) "texinfo.tex")))
@@ -97,7 +96,7 @@ when working in Automake mode."
        (insert menu))
       ;; Now insert the rest of the source elsewhere
       (ede-pmake-insert-variable-shared sv
-       (insert (mapconcat 'identity src " ")))
+       (insert (mapconcat #'identity src " ")))
       (if moresource
          (error "Texinfo files should not have moresource")))))
 
diff --git a/lisp/cedet/ede/proj-misc.el b/lisp/cedet/ede/proj-misc.el
index 70132af..068e998 100644
--- a/lisp/cedet/ede/proj-misc.el
+++ b/lisp/cedet/ede/proj-misc.el
@@ -1,4 +1,4 @@
-;;; ede-proj-misc.el --- EDE Generic Project Emacs Lisp support
+;;; ede-proj-misc.el --- EDE Generic Project Emacs Lisp support  -*- 
lexical-binding: t -*-
 
 ;; Copyright (C) 1998-2001, 2008-2021 Free Software Foundation, Inc.
 
diff --git a/lisp/cedet/ede/proj-obj.el b/lisp/cedet/ede/proj-obj.el
index 3aa4497..2ae62f4 100644
--- a/lisp/cedet/ede/proj-obj.el
+++ b/lisp/cedet/ede/proj-obj.el
@@ -1,7 +1,6 @@
-;;; ede/proj-obj.el --- EDE Generic Project Object code generation support
+;;; ede/proj-obj.el --- EDE Generic Project Object code generation support  
-*- lexical-binding: t; -*-
 
-;;; Copyright (C) 1998-2000, 2005, 2008-2021 Free Software Foundation,
-;;; Inc.
+;; Copyright (C) 1998-2021  Free Software Foundation, Inc.
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
 ;; Keywords: project, make
@@ -282,15 +281,15 @@ Argument THIS is the target to get sources from."
   (append (oref this source) (oref this auxsource)))
 
 (cl-defmethod ede-proj-makefile-insert-variables ((this 
ede-proj-target-makefile-objectcode)
-                                              &optional moresource)
+                                                 &optional _moresource)
   "Insert variables needed by target THIS.
 Optional argument MORESOURCE is not used."
   (let ((ede-proj-objectcode-dodependencies
         (oref (ede-target-parent this) automatic-dependencies)))
     (cl-call-next-method)))
 
-(cl-defmethod ede-buffer-header-file((this ede-proj-target-makefile-objectcode)
-                                 buffer)
+(cl-defmethod ede-buffer-header-file ((this 
ede-proj-target-makefile-objectcode)
+                                     _buffer)
   "There are no default header files."
   (or (cl-call-next-method)
       ;; Ok, nothing obvious. Try looking in ourselves.
diff --git a/lisp/cedet/ede/proj-prog.el b/lisp/cedet/ede/proj-prog.el
index 3817cd7..87b2ff7 100644
--- a/lisp/cedet/ede/proj-prog.el
+++ b/lisp/cedet/ede/proj-prog.el
@@ -1,4 +1,4 @@
-;;; ede-proj-prog.el --- EDE Generic Project program support
+;;; ede-proj-prog.el --- EDE Generic Project program support  -*- 
lexical-binding: t; -*-
 
 ;; Copyright (C) 1998-2001, 2005, 2008-2021 Free Software Foundation,
 ;; Inc.
@@ -90,11 +90,11 @@ Note: Currently only used for Automake projects."
 (cl-defmethod ede-proj-makefile-insert-variables ((this 
ede-proj-target-makefile-program))
   "Insert variables needed by the compiler THIS."
   (cl-call-next-method)
-  (let ((lf (mapconcat 'identity (oref this ldflags) " ")))
+  (let ((lf (mapconcat #'identity (oref this ldflags) " ")))
     (with-slots (ldlibs) this
       (if ldlibs
          (setq lf
-               (concat lf " -l" (mapconcat 'identity ldlibs " -l")))))
+               (concat lf " -l" (mapconcat #'identity ldlibs " -l")))))
     ;; LDFLAGS as needed.
     (when (and lf (not (string= "" lf)))
       (ede-pmake-insert-variable-once "LDDEPS" (insert lf)))))
diff --git a/lisp/cedet/ede/proj-scheme.el b/lisp/cedet/ede/proj-scheme.el
index 51844af..b0e2878 100644
--- a/lisp/cedet/ede/proj-scheme.el
+++ b/lisp/cedet/ede/proj-scheme.el
@@ -1,4 +1,4 @@
-;;; ede/proj-scheme.el --- EDE Generic Project scheme (guile) support
+;;; ede/proj-scheme.el --- EDE Generic Project scheme (guile) support  -*- 
lexical-binding: t -*-
 
 ;; Copyright (C) 1998-2000, 2009-2021 Free Software Foundation, Inc.
 
@@ -40,7 +40,7 @@
    )
   "This target consists of scheme files.")
 
-(cl-defmethod ede-proj-tweak-autoconf ((this ede-proj-target-scheme))
+(cl-defmethod ede-proj-tweak-autoconf ((_this ede-proj-target-scheme))
   "Tweak the configure file (current buffer) to accommodate THIS."
   (autoconf-insert-new-macro "AM_INIT_GUILE_MODULE"))
 
diff --git a/lisp/cedet/ede/proj-shared.el b/lisp/cedet/ede/proj-shared.el
index 130d7b8..01f19bc 100644
--- a/lisp/cedet/ede/proj-shared.el
+++ b/lisp/cedet/ede/proj-shared.el
@@ -1,6 +1,6 @@
-;;; ede-proj-shared.el --- EDE Generic Project shared library support
+;;; ede-proj-shared.el --- EDE Generic Project shared library support  -*- 
lexical-binding: t; -*-
 
-;;; Copyright (C) 1998-2000, 2009-2021 Free Software Foundation, Inc.
+;; Copyright (C) 1998-2021  Free Software Foundation, Inc.
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
 ;; Keywords: project, make
@@ -170,7 +170,7 @@ Use ldlibs to add addition libraries.")
   )
 
 (cl-defmethod ede-proj-configure-add-missing
-  ((this ede-proj-target-makefile-shared-object))
+  ((_this ede-proj-target-makefile-shared-object))
   "Query if any files needed by THIS provided by automake are missing.
 Results in --add-missing being passed to automake."
   (not (and (ede-expand-filename (ede-toplevel) "ltconfig")
@@ -185,7 +185,7 @@ Makefile.am generator, so use it to add this important bin 
program."
      (insert (concat "lib" (ede-name this) ".la"))))
 
 (cl-defmethod ede-proj-makefile-insert-automake-post-variables
-  ((this ede-proj-target-makefile-shared-object))
+  ((_this ede-proj-target-makefile-shared-object))
   "Insert bin_PROGRAMS variables needed by target THIS.
 We need to override -program which has an LDADD element."
   nil)
diff --git a/lisp/cedet/ede/proj.el b/lisp/cedet/ede/proj.el
index 4af8b41..6ff7630 100644
--- a/lisp/cedet/ede/proj.el
+++ b/lisp/cedet/ede/proj.el
@@ -1,4 +1,4 @@
-;;; ede/proj.el --- EDE Generic Project file driver
+;;; ede/proj.el --- EDE Generic Project file driver  -*- lexical-binding: t; 
-*-
 
 ;; Copyright (C) 1998-2003, 2007-2021 Free Software Foundation, Inc.
 
@@ -339,7 +339,7 @@ Argument PROJ is the project to save."
   (cl-call-next-method)
   (ede-proj-save proj))
 
-(cl-defmethod eieio-done-customizing ((target ede-proj-target))
+(cl-defmethod eieio-done-customizing ((_target ede-proj-target))
   "Call this when a user finishes customizing this object.
 Argument TARGET is the project we are completing customization on."
   (cl-call-next-method)
@@ -462,7 +462,7 @@ FILE must be massaged by `ede-convert-path'."
   (object-remove-from-list target 'auxsource (ede-convert-path target file))
   (ede-proj-save))
 
-(cl-defmethod project-update-version ((this ede-proj-project))
+(cl-defmethod project-update-version ((_this ede-proj-project))
   "The :version of project THIS has changed."
   (ede-proj-save))
 
@@ -486,7 +486,7 @@ FILE must be massaged by `ede-convert-path'."
    (concat (oref this name) "-" (oref this version) ".tar.gz")
    ))
 
-(cl-defmethod project-compile-project ((proj ede-proj-project) &optional 
command)
+(cl-defmethod project-compile-project ((proj ede-proj-project) &optional 
_command)
   "Compile the entire current project PROJ.
 Argument COMMAND is the command to use when compiling."
   (let ((pm (ede-proj-dist-makefile proj))
@@ -499,13 +499,13 @@ Argument COMMAND is the command to use when compiling."
 
 ;;; Target type specific compilations/debug
 ;;
-(cl-defmethod project-compile-target ((obj ede-proj-target) &optional command)
+(cl-defmethod project-compile-target ((_obj ede-proj-target) &optional command)
   "Compile the current target OBJ.
 Argument COMMAND is the command to use for compiling the target."
   (project-compile-project (ede-current-project) command))
 
 (cl-defmethod project-compile-target ((obj ede-proj-target-makefile)
-                                  &optional command)
+                                     &optional _command)
   "Compile the current target program OBJ.
 Optional argument COMMAND is the s the alternate command to use."
   (ede-proj-setup-buildenvironment (ede-current-project))
@@ -545,11 +545,11 @@ Converts all symbols into the objects to be used."
       (if comp
          ;; Now that we have a pre-set compilers to use, convert tye symbols
          ;; into objects for ease of use
-         (if (listp comp)
-             (setq comp (mapcar 'symbol-value comp))
-           (setq comp (list (symbol-value comp))))
+         (setq comp (if (listp comp)
+                        (mapcar #'symbol-value comp)
+                      (list (symbol-value comp))))
        (let* ((acomp (oref obj availablecompilers))
-              (avail (mapcar 'symbol-value acomp))
+              (avail (mapcar #'symbol-value acomp))
               (st (oref obj sourcetype))
               (sources (oref obj source)))
          ;; COMP is not specified, so generate a list from the available
@@ -585,7 +585,7 @@ Converts all symbols into the objects to be used."
              (setq link (list (symbol-value link)))
            (error ":linker is not a symbol.  Howd you do that?"))
        (let* ((alink (oref obj availablelinkers))
-              (avail (mapcar 'symbol-value alink))
+              (avail (mapcar #'symbol-value alink))
               (st (oref obj sourcetype))
               (sources (oref obj source)))
          ;; LINKER is not specified, so generate a list from the available
diff --git a/lisp/cedet/ede/project-am.el b/lisp/cedet/ede/project-am.el
index d676c57..258917f 100644
--- a/lisp/cedet/ede/project-am.el
+++ b/lisp/cedet/ede/project-am.el
@@ -596,10 +596,8 @@ Strip out duplicates, and recurse on variables."
                (project-am-expand-subdirlist
                 place (makefile-macro-file-list var))
              ;; Else, add SP in if it isn't a dup.
-             (if (member sp (symbol-value place))
-                 nil ; don't do it twice.
-               (set place (cons sp (symbol-value place))) ;; add
-               ))))
+             (cl-pushnew sp (gv-deref place) :test #'equal) ;; add
+             )))
        subdirs)
   )
 
@@ -645,7 +643,7 @@ Strip out duplicates, and recurse on variables."
       ;; We still have a list of targets.  For all buffers, make sure
       ;; their object still exists!
       ;; FIGURE THIS OUT
-      (project-am-expand-subdirlist 'csubprojexpanded csubproj)
+      (project-am-expand-subdirlist (gv-ref csubprojexpanded) csubproj)
       ;; Ok, now let's look at all our sub-projects.
       (mapc (lambda (sp)
              (let* ((subdir (file-name-as-directory
diff --git a/lisp/cedet/ede/shell.el b/lisp/cedet/ede/shell.el
index ba36fcc..371b04f 100644
--- a/lisp/cedet/ede/shell.el
+++ b/lisp/cedet/ede/shell.el
@@ -1,4 +1,4 @@
-;;; ede/shell.el --- A shell controlled by EDE.
+;;; ede/shell.el --- A shell controlled by EDE.  -*- lexical-binding: t; -*-
 ;;
 ;; Copyright (C) 2009-2021 Free Software Foundation, Inc.
 ;;
diff --git a/lisp/cedet/ede/simple.el b/lisp/cedet/ede/simple.el
index ea6162e..aaeb3f7 100644
--- a/lisp/cedet/ede/simple.el
+++ b/lisp/cedet/ede/simple.el
@@ -1,4 +1,4 @@
-;;; ede/simple.el --- Overlay an EDE structure on an existing project
+;;; ede/simple.el --- Overlay an EDE structure on an existing project  -*- 
lexical-binding: t; -*-
 
 ;; Copyright (C) 2007-2021 Free Software Foundation, Inc.
 
@@ -78,7 +78,7 @@ The directory has three parts:
      ede-simple-save-file-name)
     ))
 
-(defun ede-simple-load (dir &optional rootproj)
+(defun ede-simple-load (dir &optional _rootproj)
   "Load a project of type `Simple' for the directory DIR.
 Return nil if there isn't one.
 ROOTPROJ is nil, since we will only create a single EDE project here."
@@ -112,7 +112,7 @@ Each directory needs a project file to control it.")
   (eieio-persistent-save proj))
 
 (cl-defmethod ede-find-subproject-for-directory ((proj ede-simple-project)
-                                             dir)
+                                                _dir)
   "Return PROJ, for handling all subdirs below DIR."
   proj)
 
diff --git a/lisp/cedet/ede/source.el b/lisp/cedet/ede/source.el
index abdb07f..5dbad4f 100644
--- a/lisp/cedet/ede/source.el
+++ b/lisp/cedet/ede/source.el
@@ -1,4 +1,4 @@
-;; ede/source.el --- EDE source code object
+;; ede/source.el --- EDE source code object  -*- lexical-binding: t; -*-
 
 ;; Copyright (C) 2000, 2008-2021 Free Software Foundation, Inc.
 
@@ -72,7 +72,7 @@ that they are willing to use.")
 
 ;;; Methods
 ;;
-(cl-defmethod initialize-instance :after ((this ede-sourcecode) &rest fields)
+(cl-defmethod initialize-instance :after ((this ede-sourcecode) &rest _fields)
   "Make sure that all ede compiler objects are cached in
 `ede-compiler-list'."
   (let ((lst ede-sourcecode-list))
diff --git a/lisp/cedet/ede/speedbar.el b/lisp/cedet/ede/speedbar.el
index 48c4a89..01d4f94 100644
--- a/lisp/cedet/ede/speedbar.el
+++ b/lisp/cedet/ede/speedbar.el
@@ -1,4 +1,4 @@
-;;; ede/speedbar.el --- Speedbar viewing of EDE projects
+;;; ede/speedbar.el --- Speedbar viewing of EDE projects  -*- lexical-binding: 
t; -*-
 
 ;; Copyright (C) 1998-2001, 2003, 2005, 2007-2021 Free Software
 ;; Foundation, Inc.
@@ -42,21 +42,21 @@
   (setq ede-speedbar-key-map (speedbar-make-specialized-keymap))
 
   ;; General viewing things
-  (define-key ede-speedbar-key-map "\C-m" 'speedbar-edit-line)
-  (define-key ede-speedbar-key-map "+" 'speedbar-expand-line)
-  (define-key ede-speedbar-key-map "=" 'speedbar-expand-line)
-  (define-key ede-speedbar-key-map "-" 'speedbar-contract-line)
-  (define-key ede-speedbar-key-map " " 'speedbar-toggle-line-expansion)
+  (define-key ede-speedbar-key-map "\C-m" #'speedbar-edit-line)
+  (define-key ede-speedbar-key-map "+" #'speedbar-expand-line)
+  (define-key ede-speedbar-key-map "=" #'speedbar-expand-line)
+  (define-key ede-speedbar-key-map "-" #'speedbar-contract-line)
+  (define-key ede-speedbar-key-map " " #'speedbar-toggle-line-expansion)
 
   ;; Some object based things
-  (define-key ede-speedbar-key-map "C" 'eieio-speedbar-customize-line)
+  (define-key ede-speedbar-key-map "C" #'eieio-speedbar-customize-line)
 
   ;; Some project based things
-  (define-key ede-speedbar-key-map "R" 'ede-speedbar-remove-file-from-target)
-  (define-key ede-speedbar-key-map "b" 'ede-speedbar-compile-line)
-  (define-key ede-speedbar-key-map "B" 'ede-speedbar-compile-project)
-  (define-key ede-speedbar-key-map "D" 'ede-speedbar-make-distribution)
-  (define-key ede-speedbar-key-map "E" 'ede-speedbar-edit-projectfile)
+  (define-key ede-speedbar-key-map "R" #'ede-speedbar-remove-file-from-target)
+  (define-key ede-speedbar-key-map "b" #'ede-speedbar-compile-line)
+  (define-key ede-speedbar-key-map "B" #'ede-speedbar-compile-project)
+  (define-key ede-speedbar-key-map "D" #'ede-speedbar-make-distribution)
+  (define-key ede-speedbar-key-map "E" #'ede-speedbar-edit-projectfile)
   )
 
 (defvar ede-speedbar-menu
@@ -98,7 +98,7 @@
   (speedbar-get-focus)
   )
 
-(defun ede-speedbar-toplevel-buttons (dir)
+(defun ede-speedbar-toplevel-buttons (_dir)
   "Return a list of objects to display in speedbar.
 Argument DIR is the directory from which to derive the list of objects."
   ede-projects
@@ -180,13 +180,13 @@ Argument DIR is the directory from which to derive the 
list of objects."
        (setq depth (1- depth)))
       (speedbar-line-token))))
 
-(cl-defmethod eieio-speedbar-derive-line-path ((obj ede-project) &optional 
depth)
+(cl-defmethod eieio-speedbar-derive-line-path ((obj ede-project) &optional 
_depth)
   "Return the path to OBJ.
 Optional DEPTH is the depth we start at."
   (file-name-directory (oref obj file))
   )
 
-(cl-defmethod eieio-speedbar-derive-line-path ((obj ede-target) &optional 
depth)
+(cl-defmethod eieio-speedbar-derive-line-path ((obj ede-target) &optional 
_depth)
   "Return the path to OBJ.
 Optional DEPTH is the depth we start at."
   (let ((proj (ede-target-parent obj)))
@@ -208,7 +208,7 @@ Optional DEPTH is the depth we start at."
   "Provide a speedbar description for OBJ."
   (ede-description obj))
 
-(cl-defmethod eieio-speedbar-child-description ((obj ede-target))
+(cl-defmethod eieio-speedbar-child-description ((_obj ede-target))
   "Provide a speedbar description for a plain-child of OBJ.
 A plain child is a child element which is not an EIEIO object."
   (or (speedbar-item-info-file-helper)
@@ -251,7 +251,7 @@ It has depth DEPTH."
 
 ;;; Generic file management for TARGETS
 ;;
-(defun ede-file-find (text token indent)
+(defun ede-file-find (_text token indent)
   "Find the file TEXT at path TOKEN.
 INDENT is the current indentation level."
   (speedbar-find-file-in-frame
@@ -290,7 +290,7 @@ level."
        (t (error "Ooops...  not sure what to do")))
   (speedbar-center-buffer-smartly))
 
-(defun ede-tag-find (text token indent)
+(defun ede-tag-find (_text token _indent)
   "For the tag TEXT in a file TOKEN, goto that position.
 INDENT is the current indentation level."
   (let ((file (ede-find-nearest-file-line)))
@@ -314,21 +314,21 @@ INDENT is the current indentation level."
 (defvar ede-speedbar-file-menu-additions
   '("----"
     ["Create EDE Target" ede-new-target (ede-current-project) ]
-    ["Add to project" ede-speedbar-file-add-to-project (ede-current-project) ]
+    ;; ["Add to project" ede-speedbar-file-add-to-project 
(ede-current-project) ]
     ["Compile project" ede-speedbar-compile-project (ede-current-project) ]
-    ["Compile file target" ede-speedbar-compile-file-target 
(ede-current-project) ]
+    ;; ["Compile file target" ede-speedbar-compile-file-target 
(ede-current-project) ]
     ["Make distribution" ede-make-dist (ede-current-project) ]
     )
   "Set of menu items to splice into the speedbar menu.")
 
 (defvar ede-speedbar-file-keymap
   (let ((km (make-sparse-keymap)))
-    (define-key km "a" 'ede-speedbar-file-add-to-project)
-    (define-key km "t" 'ede-new-target)
-    (define-key km "s" 'ede-speedbar)
-    (define-key km "C" 'ede-speedbar-compile-project)
-    (define-key km "c" 'ede-speedbar-compile-file-target)
-    (define-key km "d" 'ede-make-dist)
+    ;; (define-key km "a" #'ede-speedbar-file-add-to-project)
+    (define-key km "t" #'ede-new-target)
+    (define-key km "s" #'ede-speedbar)
+    (define-key km "C" #'ede-speedbar-compile-project)
+    ;; (define-key km "c" #'ede-speedbar-compile-file-target)
+    (define-key km "d" #'ede-make-dist)
     km)
   "Keymap spliced into the speedbar keymap.")
 
diff --git a/lisp/cedet/ede/srecode.el b/lisp/cedet/ede/srecode.el
index 5dd0a7e..dd009bf 100644
--- a/lisp/cedet/ede/srecode.el
+++ b/lisp/cedet/ede/srecode.el
@@ -1,4 +1,4 @@
-;;; ede/srecode.el --- EDE utilities on top of SRecoder
+;;; ede/srecode.el --- EDE utilities on top of SRecoder  -*- lexical-binding: 
t -*-
 
 ;; Copyright (C) 2008-2021 Free Software Foundation, Inc.
 
@@ -86,7 +86,6 @@ Note: Just like `srecode-insert', but templates found in 
`ede' app."
                                    (car (cdr dictionary-entries)))
       (setq dictionary-entries
            (cdr (cdr dictionary-entries))))
-
     ))
 
 (provide 'ede/srecode)
diff --git a/lisp/cedet/ede/system.el b/lisp/cedet/ede/system.el
index d83d6d1..8ef38f0 100644
--- a/lisp/cedet/ede/system.el
+++ b/lisp/cedet/ede/system.el
@@ -1,4 +1,4 @@
-;;; ede-system.el --- EDE working with the system (VC, FTP, ETC)
+;;; ede-system.el --- EDE working with the system (VC, FTP, ETC)  -*- 
lexical-binding: t -*-
 
 ;; Copyright (C) 2001-2003, 2009-2021 Free Software Foundation, Inc.
 
diff --git a/lisp/cedet/ede/util.el b/lisp/cedet/ede/util.el
index 80cbc21..2b2402c 100644
--- a/lisp/cedet/ede/util.el
+++ b/lisp/cedet/ede/util.el
@@ -1,4 +1,4 @@
-;;; ede/util.el --- EDE utilities
+;;; ede/util.el --- EDE utilities  -*- lexical-binding: t; -*-
 
 ;; Copyright (C) 2000, 2005, 2009-2021 Free Software Foundation, Inc.
 
diff --git a/lisp/cedet/mode-local.el b/lisp/cedet/mode-local.el
index 63e0cef..4218b23 100644
--- a/lisp/cedet/mode-local.el
+++ b/lisp/cedet/mode-local.el
@@ -576,7 +576,7 @@ OVERARGS is a list of arguments passed to the override and
 (put :override-with-args 'lisp-indent-function 1)
 
 (define-obsolete-function-alias 'define-overload
-  'define-overloadable-function "27.1")
+  #'define-overloadable-function "27.1")
 
 (define-obsolete-function-alias 'function-overload-p
   #'mode-local--function-overload-p "27.1")
diff --git a/lisp/cedet/pulse.el b/lisp/cedet/pulse.el
index 3257feb..1e45067 100644
--- a/lisp/cedet/pulse.el
+++ b/lisp/cedet/pulse.el
@@ -30,10 +30,9 @@
 ;;
 ;; The following are useful entry points:
 ;;
-;; `pulse' - Cause `pulse-highlight-face' to shift toward background color.
+;; `pulse-tick' - Cause `pulse-highlight-face' to shift toward background 
color.
 ;;      Assumes you are using a version of Emacs that supports pulsing.
 ;;
-;;
 ;; `pulse-momentary-highlight-one-line' - Pulse a single line at POINT.
 ;; `pulse-momentary-highlight-region' - Pulse a region.
 ;; `pulse-momentary-highlight-overlay' - Pulse an overlay.
@@ -50,7 +49,9 @@
 ;;
 ;; Pulse is a part of CEDET.  http://cedet.sf.net
 
-(defun  pulse-available-p ()
+(require 'color)
+
+(defun pulse-available-p ()
   "Return non-nil if pulsing is available on the current frame."
   (condition-case nil
       (let ((v (color-values (face-background 'default))))
@@ -90,69 +91,27 @@ Face used for temporary highlighting of tags for effect."
   :group 'pulse)
 
 ;;; Code:
-;;
-(defun pulse-int-to-hex (int &optional nb-digits)
-  "Convert integer argument INT to a #XXXXXXXXXXXX format hex string.
-Each X in the output string is a hexadecimal digit.
-NB-DIGITS is the number of hex digits.  If INT is too large to be
-represented with NB-DIGITS, then the result is truncated from the
-left.  So, for example, INT=256 and NB-DIGITS=2 returns \"00\", since
-the hex equivalent of 256 decimal is 100, which is more than 2 digits.
-
-This function was blindly copied from hexrgb.el by Drew Adams.
-https://www.emacswiki.org/emacs/hexrgb.el";
-  (setq nb-digits (or nb-digits 4))
-  (substring (format (concat "%0" (int-to-string nb-digits) "X") int) (- 
nb-digits)))
-
-(defun pulse-color-values-to-hex (values)
-  "Convert list of rgb color VALUES to a hex string, #XXXXXXXXXXXX.
-Each X in the string is a hexadecimal digit.
-Input VALUES is as for the output of `x-color-values'.
-
-This function was blindly copied from hexrgb.el by Drew Adams.
-https://www.emacswiki.org/emacs/hexrgb.el";
-  (concat "#"
-          (pulse-int-to-hex (nth 0 values) 4) ; red
-          (pulse-int-to-hex (nth 1 values) 4) ; green
-          (pulse-int-to-hex (nth 2 values) 4))) ; blue
 
 (defcustom pulse-iterations 10
   "Number of iterations in a pulse operation."
   :group 'pulse
   :type 'number)
+
 (defcustom pulse-delay .03
   "Delay between face lightening iterations."
   :group 'pulse
   :type 'number)
 
-(defun pulse-lighten-highlight ()
-  "Lighten the face by 1/`pulse-iterations' toward the background color.
-Return t if there is more drift to do, nil if completed."
-  (if (>= (get 'pulse-highlight-face :iteration) pulse-iterations)
-      nil
-    (let* ((frame (color-values (face-background 'default)))
-          (pulse-background (face-background
-                             (get 'pulse-highlight-face
-                                  :startface)
-                              nil t)));; can be nil
-      (when pulse-background
-       (let* ((start (color-values pulse-background))
-              (frac  (list (/ (- (nth 0 frame) (nth 0 start)) pulse-iterations)
-                           (/ (- (nth 1 frame) (nth 1 start)) pulse-iterations)
-                           (/ (- (nth 2 frame) (nth 2 start)) 
pulse-iterations)))
-              (it (get 'pulse-highlight-face :iteration))
-              )
-         (set-face-background 'pulse-highlight-face
-                              (pulse-color-values-to-hex
-                               (list
-                                (+ (nth 0 start) (* (nth 0 frac) it))
-                                (+ (nth 1 start) (* (nth 1 frac) it))
-                                (+ (nth 2 start) (* (nth 2 frac) it)))))
-         (put 'pulse-highlight-face :iteration (1+ it))
-         (if (>= (1+ it) pulse-iterations)
-             nil
-           t)))
-      )))
+;;; Convenience Functions
+;;
+(defvar pulse-momentary-overlay nil
+  "The current pulsing overlay.")
+
+(defvar pulse-momentary-timer nil
+  "The current pulsing timer.")
+
+(defvar pulse-momentary-iteration 0
+  "The current pulsing iteration.")
 
 (defun pulse-reset-face (&optional face)
   "Reset the pulse highlighting FACE."
@@ -166,15 +125,7 @@ Return t if there is more drift to do, nil if completed."
                         (face-extend-p face nil t)))
   (put 'pulse-highlight-face :startface (or face
                                            'pulse-highlight-start-face))
-  (put 'pulse-highlight-face :iteration 0))
-
-;;; Convenience Functions
-;;
-(defvar pulse-momentary-overlay nil
-  "The current pulsing overlay.")
-
-(defvar pulse-momentary-timer nil
-  "The current pulsing timer.")
+  (setq pulse-momentary-iteration 0))
 
 (defun pulse-momentary-highlight-overlay (o &optional face)
   "Pulse the overlay O, unhighlighting before next command.
@@ -194,21 +145,30 @@ Optional argument FACE specifies the face to do the 
highlighting."
        (progn
          (overlay-put o 'face (or face 'pulse-highlight-start-face))
          (add-hook 'pre-command-hook
-                   'pulse-momentary-unhighlight))
+                   #'pulse-momentary-unhighlight))
       ;; Pulse it.
       (overlay-put o 'face 'pulse-highlight-face)
       ;; The pulse function puts FACE onto 'pulse-highlight-face.
       ;; Thus above we put our face on the overlay, but pulse
       ;; with a reference face needed for the color.
       (pulse-reset-face face)
-      (setq pulse-momentary-timer
-            (run-with-timer 0 pulse-delay #'pulse-tick
-                            (time-add nil
-                                      (* pulse-delay pulse-iterations)))))))
-
-(defun pulse-tick (stop-time)
+      (let* ((start (color-name-to-rgb
+                     (face-background 'pulse-highlight-start-face
+                                      nil 'default)))
+             (stop (color-name-to-rgb (face-background 'default)))
+             (colors (mapcar (apply-partially 'apply 'color-rgb-to-hex)
+                             (color-gradient start stop pulse-iterations))))
+        (setq pulse-momentary-timer
+              (run-with-timer 0 pulse-delay #'pulse-tick
+                              colors
+                              (time-add nil
+                                        (* pulse-delay pulse-iterations))))))))
+
+(defun pulse-tick (colors stop-time)
   (if (time-less-p nil stop-time)
-      (pulse-lighten-highlight)
+      (when-let (color (elt colors pulse-momentary-iteration))
+        (set-face-background 'pulse-highlight-face color)
+        (setq pulse-momentary-iteration (1+ pulse-momentary-iteration)))
     (pulse-momentary-unhighlight)))
 
 (defun pulse-momentary-unhighlight ()
@@ -233,7 +193,7 @@ Optional argument FACE specifies the face to do the 
highlighting."
     (cancel-timer pulse-momentary-timer))
 
   ;; Remove this hook.
-  (remove-hook 'pre-command-hook 'pulse-momentary-unhighlight))
+  (remove-hook 'pre-command-hook #'pulse-momentary-unhighlight))
 
 ;;;###autoload
 (defun pulse-momentary-highlight-one-line (point &optional face)
diff --git a/lisp/cedet/semantic.el b/lisp/cedet/semantic.el
index 44bd4b0..15388f0 100644
--- a/lisp/cedet/semantic.el
+++ b/lisp/cedet/semantic.el
@@ -1,4 +1,4 @@
-;;; semantic.el --- Semantic buffer evaluator.
+;;; semantic.el --- Semantic buffer evaluator.  -*- lexical-binding: t; -*-
 
 ;; Copyright (C) 1999-2021 Free Software Foundation, Inc.
 
@@ -57,6 +57,7 @@ excluded if a released version is required.
 It is assumed that if the current version is newer than that specified,
 everything passes.  Exceptions occur when known incompatibilities are
 introduced."
+  (declare (obsolete emacs-version "28.1"))
   (require 'inversion)
   (inversion-test 'semantic
                  (concat major "." minor
@@ -296,7 +297,7 @@ to use Semantic, and `semantic-init-hook' is run."
                    'semantic-inhibit-functions)))
     ;; Make sure that if this buffer is cloned, our tags and overlays
     ;; don't go along for the ride.
-    (add-hook 'clone-indirect-buffer-hook 'semantic-clear-toplevel-cache
+    (add-hook 'clone-indirect-buffer-hook #'semantic-clear-toplevel-cache
              nil t)
     ;; Specify that this function has done its work.  At this point
     ;; we can consider that semantic is active in this buffer.
@@ -465,12 +466,12 @@ is requested."
   ;; Nuke all semantic overlays.  This is faster than deleting based
   ;; on our data structure.
   (let ((l (overlay-lists)))
-    (mapc 'semantic-delete-overlay-maybe (car l))
-    (mapc 'semantic-delete-overlay-maybe (cdr l))
+    (mapc #'semantic-delete-overlay-maybe (car l))
+    (mapc #'semantic-delete-overlay-maybe (cdr l))
     )
   (semantic-parse-tree-set-needs-rebuild)
   ;; Remove this hook which tracks if a buffer is up to date or not.
-  (remove-hook 'after-change-functions 'semantic-change-function t)
+  (remove-hook 'after-change-functions #'semantic-change-function t)
 
   (run-hook-with-args 'semantic-after-toplevel-cache-change-hook
                      semantic--buffer-cache)
@@ -486,7 +487,7 @@ is requested."
   ;; This is specific to the bovine parser.
   (setq-local semantic-bovinate-nonterminal-check-obarray nil)
   (semantic-parse-tree-set-up-to-date)
-  (add-hook 'after-change-functions 'semantic-change-function nil t)
+  (add-hook 'after-change-functions #'semantic-change-function nil t)
   (run-hook-with-args 'semantic-after-toplevel-cache-change-hook
                      semantic--buffer-cache)
   (setq semantic--completion-cache nil)
@@ -778,25 +779,25 @@ Throw away all the old tags, and recreate the tag 
database."
 (defvar semantic-mode-map
   (let ((map (make-sparse-keymap)))
     ;; Key bindings:
-    ;; (define-key km "f"    'senator-search-set-tag-class-filter)
-    ;; (define-key km "i"    'senator-isearch-toggle-semantic-mode)
-    (define-key map "\C-c,j" 'semantic-complete-jump-local)
-    (define-key map "\C-c,J" 'semantic-complete-jump)
-    (define-key map "\C-c,m" 'semantic-complete-jump-local-members)
-    (define-key map "\C-c,g" 'semantic-symref-symbol)
-    (define-key map "\C-c,G" 'semantic-symref)
-    (define-key map "\C-c,p" 'senator-previous-tag)
-    (define-key map "\C-c,n" 'senator-next-tag)
-    (define-key map "\C-c,u" 'senator-go-to-up-reference)
-    (define-key map "\C-c, " 'semantic-complete-analyze-inline)
-    (define-key map "\C-c,\C-w" 'senator-kill-tag)
-    (define-key map "\C-c,\M-w" 'senator-copy-tag)
-    (define-key map "\C-c,\C-y" 'senator-yank-tag)
-    (define-key map "\C-c,r" 'senator-copy-tag-to-register)
-    (define-key map "\C-c,," 'semantic-force-refresh)
-    (define-key map [?\C-c ?, up] 'senator-transpose-tags-up)
-    (define-key map [?\C-c ?, down] 'senator-transpose-tags-down)
-    (define-key map "\C-c,l" 'semantic-analyze-possible-completions)
+    ;; (define-key km "f"    #'senator-search-set-tag-class-filter)
+    ;; (define-key km "i"    #'senator-isearch-toggle-semantic-mode)
+    (define-key map "\C-c,j" #'semantic-complete-jump-local)
+    (define-key map "\C-c,J" #'semantic-complete-jump)
+    (define-key map "\C-c,m" #'semantic-complete-jump-local-members)
+    (define-key map "\C-c,g" #'semantic-symref-symbol)
+    (define-key map "\C-c,G" #'semantic-symref)
+    (define-key map "\C-c,p" #'senator-previous-tag)
+    (define-key map "\C-c,n" #'senator-next-tag)
+    (define-key map "\C-c,u" #'senator-go-to-up-reference)
+    (define-key map "\C-c, " #'semantic-complete-analyze-inline)
+    (define-key map "\C-c,\C-w" #'senator-kill-tag)
+    (define-key map "\C-c,\M-w" #'senator-copy-tag)
+    (define-key map "\C-c,\C-y" #'senator-yank-tag)
+    (define-key map "\C-c,r" #'senator-copy-tag-to-register)
+    (define-key map "\C-c,," #'semantic-force-refresh)
+    (define-key map [?\C-c ?, up] #'senator-transpose-tags-up)
+    (define-key map [?\C-c ?, down] #'senator-transpose-tags-down)
+    (define-key map "\C-c,l" #'semantic-analyze-possible-completions)
     ;; This hack avoids showing the CEDET menu twice if ede-minor-mode
     ;; and Semantic are both enabled.  Is there a better way?
     (define-key map [menu-bar cedet-menu]
@@ -1028,7 +1029,7 @@ Semantic mode.
                     (file-exists-p semanticdb-default-system-save-directory))
            (require 'semantic/db-ebrowse)
            (semanticdb-load-ebrowse-caches)))
-       (add-hook 'mode-local-init-hook 'semantic-new-buffer-fcn)
+       (add-hook 'mode-local-init-hook #'semantic-new-buffer-fcn)
        ;; Add semantic-ia-complete-symbol to
        ;; completion-at-point-functions, so that it is run from
        ;; M-TAB.
@@ -1036,11 +1037,11 @@ Semantic mode.
        ;; Note: The first entry added is the last entry run, so the
        ;;       most specific entry should be last.
        (add-hook 'completion-at-point-functions
-                 'semantic-analyze-nolongprefix-completion-at-point-function)
+                 #'semantic-analyze-nolongprefix-completion-at-point-function)
        (add-hook 'completion-at-point-functions
-                 'semantic-analyze-notc-completion-at-point-function)
+                 #'semantic-analyze-notc-completion-at-point-function)
        (add-hook 'completion-at-point-functions
-                 'semantic-analyze-completion-at-point-function)
+                 #'semantic-analyze-completion-at-point-function)
 
        (if (bound-and-true-p global-ede-mode)
            (define-key cedet-menu-map [cedet-menu-separator] '("--")))
@@ -1051,21 +1052,21 @@ Semantic mode.
     ;; introduced in the buffer is pretty much futile, but we have to
     ;; clean the hooks and delete Semantic-related overlays, so that
     ;; Semantic can be re-activated cleanly.
-    (remove-hook 'mode-local-init-hook 'semantic-new-buffer-fcn)
+    (remove-hook 'mode-local-init-hook #'semantic-new-buffer-fcn)
     (remove-hook 'completion-at-point-functions
-                'semantic-analyze-completion-at-point-function)
+                #'semantic-analyze-completion-at-point-function)
     (remove-hook 'completion-at-point-functions
-                'semantic-analyze-notc-completion-at-point-function)
+                #'semantic-analyze-notc-completion-at-point-function)
     (remove-hook 'completion-at-point-functions
-                'semantic-analyze-nolongprefix-completion-at-point-function)
+                #'semantic-analyze-nolongprefix-completion-at-point-function)
 
     (remove-hook 'after-change-functions
-                'semantic-change-function)
+                #'semantic-change-function)
     (define-key cedet-menu-map [cedet-menu-separator] nil)
     (define-key cedet-menu-map [semantic-options-separator] nil)
     ;; FIXME: handle semanticdb-load-ebrowse-caches
     (dolist (mode semantic-submode-list)
-      (if (and (boundp mode) (eval mode))
+      (if (and (boundp mode) (symbol-value mode))
          (funcall mode -1)))
     ;; Unlink buffer and clear cache
     (semantic--tag-unlink-cache-from-buffer)
diff --git a/lisp/cedet/semantic/analyze.el b/lisp/cedet/semantic/analyze.el
index c0a054d..1a4be11 100644
--- a/lisp/cedet/semantic/analyze.el
+++ b/lisp/cedet/semantic/analyze.el
@@ -1,4 +1,4 @@
-;;; semantic/analyze.el --- Analyze semantic tags against local context
+;;; semantic/analyze.el --- Analyze semantic tags against local context  -*- 
lexical-binding: t; -*-
 
 ;; Copyright (C) 2000-2005, 2007-2021 Free Software Foundation, Inc.
 
@@ -167,7 +167,7 @@ of the parent function.")
 ;; Simple methods against the context classes.
 ;;
 (cl-defmethod semantic-analyze-type-constraint
-  ((context semantic-analyze-context) &optional desired-type)
+  ((_context semantic-analyze-context) &optional desired-type)
   "Return a type constraint for completing :prefix in CONTEXT.
 Optional argument DESIRED-TYPE may be a non-type tag to analyze."
   (when (semantic-tag-p desired-type)
@@ -344,8 +344,8 @@ This function knows of flags:
        (setq tagtype (cons tmptype tagtype))
        (when miniscope
          (let ((rawscope
-                (apply 'append
-                       (mapcar 'semantic-tag-type-members tagtype))))
+                (apply #'append
+                       (mapcar #'semantic-tag-type-members tagtype))))
            (oset miniscope fullscope rawscope)))
        )
       (setq s (cdr s)))
@@ -437,6 +437,8 @@ to provide a large number of non-cached analysis for 
filtering symbols."
       (:override)))
   )
 
+(defvar semantic--prefixtypes)
+
 (defun semantic-analyze-current-symbol-default (analyzehookfcn position)
   "Call ANALYZEHOOKFCN on the analyzed symbol at POSITION."
   (let* ((semantic-analyze-error-stack nil)
@@ -453,14 +455,14 @@ to provide a large number of non-cached analysis for 
filtering symbols."
          (catch 'unfindable
            ;; If debug on error is on, allow debugging in this fcn.
            (setq prefix (semantic-analyze-find-tag-sequence
-                         prefix scope 'prefixtypes 'unfindable)))
+                         prefix scope 'semantic--prefixtypes 'unfindable)))
        ;; Debug on error is off.  Capture errors and move on
        (condition-case err
            ;; NOTE: This line is duplicated in
            ;;       semantic-analyzer-debug-global-symbol
            ;;       You will need to update both places.
            (setq prefix (semantic-analyze-find-tag-sequence
-                         prefix scope 'prefixtypes))
+                         prefix scope 'semantic--prefixtypes))
          (error (semantic-analyze-push-error err))))
 
       ;;(message "Analysis took %.2f sec" (semantic-elapsed-time LLstart nil))
@@ -531,7 +533,7 @@ Returns an object based on symbol 
`semantic-analyze-context'."
         (bounds (nth 2 prefixandbounds))
         ;; @todo - vv too early to really know this answer! vv
         (prefixclass (semantic-ctxt-current-class-list))
-        (prefixtypes nil)
+        (semantic--prefixtypes nil)
         (scope (semantic-calculate-scope position))
         (function nil)
         (fntag nil)
@@ -611,13 +613,13 @@ Returns an object based on symbol 
`semantic-analyze-context'."
       (if debug-on-error
          (catch 'unfindable
            (setq prefix (semantic-analyze-find-tag-sequence
-                         prefix scope 'prefixtypes 'unfindable))
+                         prefix scope 'semantic--prefixtypes 'unfindable))
            ;; If there's an alias, dereference it and analyze
            ;; sequence again.
            (when (setq newseq
                        (semantic-analyze-dereference-alias prefix))
              (setq prefix (semantic-analyze-find-tag-sequence
-                           newseq scope 'prefixtypes 'unfindable))))
+                           newseq scope 'semantic--prefixtypes 'unfindable))))
        ;; Debug on error is off.  Capture errors and move on
        (condition-case err
            ;; NOTE: This line is duplicated in
@@ -625,11 +627,11 @@ Returns an object based on symbol 
`semantic-analyze-context'."
            ;;       You will need to update both places.
            (progn
              (setq prefix (semantic-analyze-find-tag-sequence
-                           prefix scope 'prefixtypes))
+                           prefix scope 'semantic--prefixtypes))
              (when (setq newseq
                          (semantic-analyze-dereference-alias prefix))
                (setq prefix (semantic-analyze-find-tag-sequence
-                             newseq scope 'prefixtypes))))
+                             newseq scope 'semantic--prefixtypes))))
          (error (semantic-analyze-push-error err))))
       )
 
@@ -650,7 +652,7 @@ Returns an object based on symbol 
`semantic-analyze-context'."
             :prefix prefix
             :prefixclass prefixclass
             :bounds bounds
-            :prefixtypes prefixtypes
+            :prefixtypes semantic--prefixtypes
             :errors semantic-analyze-error-stack)))
 
       ;; No function, try assignment
@@ -670,7 +672,7 @@ Returns an object based on symbol 
`semantic-analyze-context'."
             :bounds bounds
             :prefix prefix
             :prefixclass prefixclass
-            :prefixtypes prefixtypes
+            :prefixtypes semantic--prefixtypes
             :errors semantic-analyze-error-stack)))
 
      ;; TODO: Identify return value condition.
@@ -686,7 +688,7 @@ Returns an object based on symbol 
`semantic-analyze-context'."
             :bounds bounds
             :prefix prefix
             :prefixclass prefixclass
-            :prefixtypes prefixtypes
+            :prefixtypes semantic--prefixtypes
             :errors semantic-analyze-error-stack)))
 
      (t (setq context-return nil))
@@ -750,7 +752,7 @@ Some useful functions are found in 
`semantic-format-tag-functions'."
   :group 'semantic
   :type semantic-format-tag-custom-list)
 
-(defun semantic-analyze-princ-sequence (sequence &optional prefix buff)
+(defun semantic-analyze-princ-sequence (sequence &optional prefix _buff)
   "Send the tag SEQUENCE to standard out.
 Use PREFIX as a label.
 Use BUFF as a source of override methods."
diff --git a/lisp/cedet/semantic/analyze/complete.el 
b/lisp/cedet/semantic/analyze/complete.el
index e8139ab..ccf405d 100644
--- a/lisp/cedet/semantic/analyze/complete.el
+++ b/lisp/cedet/semantic/analyze/complete.el
@@ -1,4 +1,4 @@
-;;; semantic/analyze/complete.el --- Smart Completions
+;;; semantic/analyze/complete.el --- Smart Completions  -*- lexical-binding: 
t; -*-
 
 ;; Copyright (C) 2007-2021 Free Software Foundation, Inc.
 
@@ -45,7 +45,7 @@
   "For the tag TYPE, return any constant symbols of TYPE.
 Used as options when completing.")
 
-(defun semantic-analyze-type-constants-default (type)
+(defun semantic-analyze-type-constants-default (_type)
   "Do nothing with TYPE."
   nil)
 
@@ -54,7 +54,7 @@ Used as options when completing.")
   (let ((origc tags))
     ;; Accept only tags that are of the datatype specified by
     ;; the desired classes.
-    (setq tags (apply 'nconc ;; All input lists are permutable.
+    (setq tags (apply #'nconc ;; All input lists are permutable.
                      (mapcar (lambda (class)
                                (semantic-find-tags-by-class class origc))
                              classlist)))
@@ -109,6 +109,8 @@ in a buffer."
     (when (called-interactively-p 'any)
       (error "Buffer was not parsed by Semantic."))))
 
+(defvar semantic--prefixtypes)
+
 (defun semantic-analyze-possible-completions-default (context &optional flags)
   "Default method for producing smart completions.
 Argument CONTEXT is an object specifying the locally derived context.
@@ -121,14 +123,14 @@ FLAGS can be any number of:
         (desired-type (semantic-analyze-type-constraint a))
         (desired-class (oref a prefixclass))
         (prefix (oref a prefix))
-        (prefixtypes (oref a prefixtypes))
+        (semantic--prefixtypes (oref a prefixtypes))
         (completetext nil)
         (completetexttype nil)
         (scope (oref a scope))
         (localvar (when scope (oref scope localvar)))
         (origc nil)
         (c nil)
-        (any nil)
+        ;; (any nil)
         (do-typeconstraint (not (memq 'no-tc flags)))
         (do-longprefix (not (memq 'no-longprefix flags)))
         (do-unique (not (memq 'no-unique flags)))
@@ -138,7 +140,7 @@ FLAGS can be any number of:
       ;; If we are not doing the long prefix, shorten all the key
       ;; elements.
       (setq prefix (list (car (reverse prefix)))
-           prefixtypes nil))
+           semantic--prefixtypes nil))
 
     ;; Calculate what our prefix string is so that we can
     ;; find all our matching text.
@@ -155,7 +157,7 @@ FLAGS can be any number of:
     ;; The prefixtypes should always be at least 1 less than
     ;; the prefix since the type is never looked up for the last
     ;; item when calculating a sequence.
-    (setq completetexttype (car (reverse prefixtypes)))
+    (setq completetexttype (car (reverse semantic--prefixtypes)))
     (when (or (not completetexttype)
              (not (and (semantic-tag-p completetexttype)
                        (eq (semantic-tag-class completetexttype) 'type))))
diff --git a/lisp/cedet/semantic/analyze/debug.el 
b/lisp/cedet/semantic/analyze/debug.el
index 4947368..69b3b9c 100644
--- a/lisp/cedet/semantic/analyze/debug.el
+++ b/lisp/cedet/semantic/analyze/debug.el
@@ -1,6 +1,6 @@
-;;; semantic/analyze/debug.el --- Debug the analyzer
+;;; semantic/analyze/debug.el --- Debug the analyzer  -*- lexical-binding: t; 
-*-
 
-;;; Copyright (C) 2008-2021 Free Software Foundation, Inc.
+;; Copyright (C) 2008-2021 Free Software Foundation, Inc.
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
 
@@ -109,11 +109,11 @@ Argument COMP are possible completions here."
        (condition-case err
            (with-current-buffer origbuf
              (let* ((position (or (cdr-safe (oref ctxt bounds)) (point)))
-                    (prefixtypes nil) ; Used as type return
+                    ;; (semantic--prefixtypes nil) ; Used as type return
                     (scope (semantic-calculate-scope position))
                     )
                (semantic-analyze-find-tag-sequence
-                (list prefix "") scope 'prefixtypes)
+                (list prefix "") scope) ;; 'semantic--prefixtypes
                )
              )
          (error (setq finderr err)))
@@ -149,7 +149,7 @@ path was setup incorrectly.\n")
     (semantic-analyzer-debug-add-buttons)
     ))
 
-(defun semantic-analyzer-debug-missing-datatype (ctxt idx comp)
+(defun semantic-analyzer-debug-missing-datatype (ctxt idx _comp)
   "Debug why we can't find a datatype entry for CTXT prefix at IDX.
 Argument COMP are possible completions here."
   (let* ((prefixitem (nth idx (oref ctxt prefix)))
@@ -593,19 +593,20 @@ Look for key expressions, and add push-buttons near them."
         (setq-local semantic-analyzer-debug-orig orig-buffer)
        ;; First, add do-in buttons to recommendations.
        (while (re-search-forward "^\\s-*M-x \\(\\(\\w\\|\\s_\\)+\\) " nil t)
-         (let ((fcn (match-string 1)))
-           (when (not (fboundp (intern-soft fcn)))
+         (let* ((fcn (match-string 1))
+                (fsym (intern-soft fcn)))
+           (when (not (fboundp fsym))
              (error "Help Err: Can't find %s" fcn))
            (end-of-line)
            (insert "   ")
            (insert-button "[ Do It ]"
                           'mouse-face 'custom-button-pressed-face
                           'do-fcn fcn
-                          'action `(lambda (arg)
-                                     (let ((M semantic-analyzer-debug-orig))
-                                       (set-buffer (marker-buffer M))
-                                       (goto-char M))
-                                     (call-interactively (quote ,(intern-soft 
fcn))))))))
+                          'action (lambda (_arg)
+                                    (let ((M semantic-analyzer-debug-orig))
+                                      (set-buffer (marker-buffer M))
+                                      (goto-char M))
+                                    (call-interactively fsym))))))
       ;; Do something else?
       ;; Clean up the mess
       (set-buffer-modified-p nil))))
diff --git a/lisp/cedet/semantic/analyze/fcn.el 
b/lisp/cedet/semantic/analyze/fcn.el
index 10d11c3..d47e897 100644
--- a/lisp/cedet/semantic/analyze/fcn.el
+++ b/lisp/cedet/semantic/analyze/fcn.el
@@ -1,4 +1,4 @@
-;;; semantic/analyze/fcn.el --- Analyzer support functions.
+;;; semantic/analyze/fcn.el --- Analyzer support functions.  -*- 
lexical-binding: t; -*-
 
 ;; Copyright (C) 2007-2021 Free Software Foundation, Inc.
 
@@ -55,7 +55,7 @@ Return the string representing the compound name.")
 
 (defun semantic-analyze-unsplit-name-default (namelist)
   "Concatenate the names in NAMELIST with a . between."
-  (mapconcat 'identity namelist "."))
+  (mapconcat #'identity namelist "."))
 
 ;;; SELECTING
 ;;
diff --git a/lisp/cedet/semantic/analyze/refs.el 
b/lisp/cedet/semantic/analyze/refs.el
index a39ff6f..31cbb9e 100644
--- a/lisp/cedet/semantic/analyze/refs.el
+++ b/lisp/cedet/semantic/analyze/refs.el
@@ -1,4 +1,4 @@
-;;; semantic/analyze/refs.el --- Analysis of the references between tags.
+;;; semantic/analyze/refs.el --- Analysis of the references between tags.  -*- 
lexical-binding: t; -*-
 
 ;; Copyright (C) 2008-2021 Free Software Foundation, Inc.
 
@@ -296,7 +296,7 @@ Only works for tags in the global namespace."
        (let* ((classmatch (semantic-tag-class tag))
               (RES
                (semanticdb-find-tags-collector
-                (lambda (table tags)
+                (lambda (_table tags)
                   (semantic-find-tags-by-class classmatch tags)
                   ;; @todo - Add parent check also.
                   )
diff --git a/lisp/cedet/semantic/bovine.el b/lisp/cedet/semantic/bovine.el
index 3bc0e4d..6be6dfd 100644
--- a/lisp/cedet/semantic/bovine.el
+++ b/lisp/cedet/semantic/bovine.el
@@ -1,4 +1,4 @@
-;;; semantic/bovine.el --- LL Parser/Analyzer core.
+;;; semantic/bovine.el --- LL Parser/Analyzer core  -*- lexical-binding: t; -*-
 
 ;; Copyright (C) 1999-2004, 2006-2007, 2009-2021 Free Software
 ;; Foundation, Inc.
@@ -41,7 +41,7 @@
 
 ;;; Variables
 ;;
-(defvar-local semantic-bovinate-nonterminal-check-obarray nil
+(defvar-local semantic-bovinate-nonterminal-check-map nil
   "Obarray of streams already parsed for nonterminal symbols.
 Use this to detect infinite recursion during a parse.")
 
@@ -54,6 +54,7 @@ Use this to detect infinite recursion during a parse.")
   "Create a lambda expression to return a list including RETURN-VAL.
 The return list is a lambda expression to be used in a bovine table."
   `(lambda (vals start end)
+     (ignore vals)
      (append ,@return-val (list start end))))
 
 ;;; Semantic Bovination
@@ -78,21 +79,18 @@ environment of `semantic-bovinate-stream'."
 (defun semantic-bovinate-nonterminal-check (stream nonterminal)
   "Check if STREAM not already parsed for NONTERMINAL.
 If so abort because an infinite recursive parse is suspected."
-  (or (vectorp semantic-bovinate-nonterminal-check-obarray)
-      (setq semantic-bovinate-nonterminal-check-obarray
-            (make-vector 13 nil)))
-  (let* ((nt (symbol-name nonterminal))
-         (vs (symbol-value
-              (intern-soft
-               nt semantic-bovinate-nonterminal-check-obarray))))
+  (or (hash-table-p semantic-bovinate-nonterminal-check-map)
+      (setq semantic-bovinate-nonterminal-check-map
+            (make-hash-table :test #'eq)))
+  (let* ((vs (gethash nonterminal semantic-bovinate-nonterminal-check-map)))
     (if (memq stream vs)
         ;; Always enter debugger to see the backtrace
         (let ((debug-on-signal t)
               (debug-on-error  t))
-          (setq semantic-bovinate-nonterminal-check-obarray nil)
-          (error "Infinite recursive parse suspected on %s" nt))
-      (set (intern nt semantic-bovinate-nonterminal-check-obarray)
-           (cons stream vs)))))
+          (setq semantic-bovinate-nonterminal-check-map nil)
+          (error "Infinite recursive parse suspected on %s" nonterminal))
+      (push stream
+            (gethash nonterminal semantic-bovinate-nonterminal-check-map)))))
 
 ;;;###autoload
 (defun semantic-bovinate-stream (stream &optional nonterminal)
@@ -109,6 +107,9 @@ list of semantic tokens found."
   (or semantic--buffer-cache
       (semantic-bovinate-nonterminal-check stream nonterminal))
 
+  ;; FIXME: `semantic-parse-region-c-mode' inspects `lse' to try and
+  ;; detect a recursive call (used with macroexpansion, to avoid inf-loops).
+  (with-suppressed-warnings ((lexical lse)) (defvar lse))
   (let* ((table semantic--parse-table)
         (matchlist (cdr (assq nonterminal table)))
         (starting-stream stream)
@@ -215,7 +216,8 @@ list of semantic tokens found."
                             (setq cvl (cons
                                        (if (memq (semantic-lex-token-class lse)
                                                  '(comment semantic-list))
-                                           valdot val) cvl))) ;append 
unchecked value.
+                                           valdot val)
+                                       cvl))) ;append unchecked value.
                           (setq end (semantic-lex-token-end lse))
                           )
                       (setq lte nil cvl nil)) ;No more matches, exit
@@ -283,7 +285,7 @@ list of semantic tokens found."
 
 ;; Make it the default parser
 ;;;###autoload
-(defalias 'semantic-parse-stream-default 'semantic-bovinate-stream)
+(defalias 'semantic-parse-stream-default #'semantic-bovinate-stream)
 
 (provide 'semantic/bovine)
 
diff --git a/lisp/cedet/semantic/bovine/c.el b/lisp/cedet/semantic/bovine/c.el
index fb55139..5712f9b 100644
--- a/lisp/cedet/semantic/bovine/c.el
+++ b/lisp/cedet/semantic/bovine/c.el
@@ -1,4 +1,4 @@
-;;; semantic/bovine/c.el --- Semantic details for C
+;;; semantic/bovine/c.el --- Semantic details for C  -*- lexical-binding: t; 
-*-
 
 ;; Copyright (C) 1999-2021 Free Software Foundation, Inc.
 
@@ -114,7 +114,8 @@ part of the preprocessor map.")
   "Reset the C preprocessor symbol map based on all input variables."
   (when (and semantic-mode
             (featurep 'semantic/bovine/c))
-    (remove-hook 'mode-local-init-hook 
'semantic-c-reset-preprocessor-symbol-map)
+    (remove-hook 'mode-local-init-hook
+                 #'semantic-c-reset-preprocessor-symbol-map)
     ;; Initialize semantic-lex-spp-macro-symbol-obarray with symbols.
     (setq-mode-local c-mode
                     semantic-lex-spp-macro-symbol-obarray
@@ -154,7 +155,7 @@ part of the preprocessor map.")
 
 ;; Make sure the preprocessor symbols are set up when mode-local kicks
 ;; in.
-(add-hook 'mode-local-init-hook 'semantic-c-reset-preprocessor-symbol-map)
+(add-hook 'mode-local-init-hook #'semantic-c-reset-preprocessor-symbol-map)
 
 (defcustom semantic-lex-c-preprocessor-symbol-map nil
   "Table of C Preprocessor keywords used by the Semantic C lexer.
@@ -237,8 +238,8 @@ Return the defined symbol as a special spp lex token."
   (skip-chars-forward " \t")
   (if (eolp)
       nil
-    (let* ((name (buffer-substring-no-properties
-                 (match-beginning 1) (match-end 1)))
+    (let* (;; (name (buffer-substring-no-properties
+          ;;        (match-beginning 1) (match-end 1)))
           (beginning-of-define (match-end 1))
           (with-args (save-excursion
                        (goto-char (match-end 0))
@@ -488,7 +489,7 @@ code to parse."
            (error nil))))
 
     (let ((eval-form (condition-case err
-                        (eval parsedtokelist)
+                        (eval parsedtokelist t)
                       (error
                        (semantic-push-parser-warning
                         (format "Hideif forms produced an error.  Assuming 
false.\n%S" err)
@@ -499,11 +500,11 @@ code to parse."
                    (equal eval-form 0)));; ifdef line resulted in false
 
        ;; The if indicates to skip this preprocessor section
-       (let ((pt nil))
+       (let () ;; (pt nil)
          (semantic-push-parser-warning (format "Skip %s" 
(buffer-substring-no-properties (point-at-bol) (point-at-eol)))
                                        (point-at-bol) (point-at-eol))
          (beginning-of-line)
-         (setq pt (point))
+         ;; (setq pt (point))
          ;; This skips only a section of a conditional.  Once that section
          ;; is opened, encountering any new #else or related conditional
          ;; should be skipped.
@@ -818,7 +819,9 @@ MACRO expansion mode is handled through the nature of 
Emacs's non-lexical
 binding of variables.
 START, END, NONTERMINAL, DEPTH, and RETURNONERRORS are the same
 as for the parent."
-  (if (and (boundp 'lse) (or (/= start 1) (/= end (point-max))))
+  ;; FIXME: We shouldn't depend on the internals of `semantic-bovinate-stream'.
+  (with-suppressed-warnings ((lexical lse)) (defvar lse))
+  (if (and (boundp 'lse) (or (/= start (point-min)) (/= end (point-max))))
       (let* ((last-lexical-token lse)
             (llt-class (semantic-lex-token-class last-lexical-token))
             (llt-fakebits (car (cdr last-lexical-token)))
@@ -926,7 +929,7 @@ the regular parser."
          (semantic-lex-init)
          (semantic-clear-toplevel-cache)
          (remove-hook 'semantic-lex-reset-functions
-                      'semantic-lex-spp-reset-hook t)
+                      #'semantic-lex-spp-reset-hook t)
          )
        ;; Get the macro symbol table right.
        (setq semantic-lex-spp-dynamic-macro-symbol-obarray spp-syms)
@@ -970,7 +973,7 @@ the regular parser."
     ;; Notify about the debug
     (setq semantic-c-debug-mode-init-last-mode mm)
 
-    (add-hook 'post-command-hook 'semantic-c-debug-mode-init-pch)))
+    (add-hook 'post-command-hook #'semantic-c-debug-mode-init-pch)))
 
 (defun semantic-c-debug-mode-init-pch ()
   "Notify user about needing to debug their major mode hooks."
@@ -987,7 +990,7 @@ M-x semantic-c-debug-mode-init
 
 now.
 ")
-    (remove-hook 'post-command-hook 'semantic-c-debug-mode-init-pch)))
+    (remove-hook 'post-command-hook #'semantic-c-debug-mode-init-pch)))
 
 (defun semantic-expand-c-tag (tag)
   "Expand TAG into a list of equivalent tags, or nil."
@@ -1228,7 +1231,7 @@ Use `semantic-analyze-current-tag' to debug this fcn."
   (when (not (semantic-tag-p tag))  (signal 'wrong-type-argument (list 
'semantic-tag-p tag)))
   (let ((allhits nil)
        (scope nil)
-       (refs nil))
+       ) ;; (refs nil)
     (save-excursion
       (semantic-go-to-tag tag db)
       (setq scope (semantic-calculate-scope))
@@ -1250,11 +1253,12 @@ Use `semantic-analyze-current-tag' to debug this fcn."
                (reverse newparents)))
        (setq allhits (semantic--analyze-refs-full-lookup tag scope t)))
 
-      (setq refs (semantic-analyze-references (semantic-tag-name tag)
-                                   :tag tag
-                                   :tagdb db
-                                   :scope scope
-                                   :rawsearchdata allhits)))))
+      ;; (setq refs
+      (semantic-analyze-references (semantic-tag-name tag)
+                                  :tag tag
+                                  :tagdb db
+                                  :scope scope
+                                  :rawsearchdata allhits)))) ;;)
 
 (defun semantic-c-reconstitute-token (tokenpart declmods typedecl)
   "Reconstitute a token TOKENPART with DECLMODS and TYPEDECL.
@@ -1540,9 +1544,9 @@ This might be a string, or a list of tokens."
        ((semantic-tag-p templatespec)
         (semantic-format-tag-abbreviate templatespec))
        ((listp templatespec)
-        (mapconcat 'semantic-format-tag-abbreviate templatespec ", "))))
+        (mapconcat #'semantic-format-tag-abbreviate templatespec ", "))))
 
-(defun semantic-c-template-string (token &optional parent color)
+(defun semantic-c-template-string (token &optional parent _color)
   "Return a string representing the TEMPLATE attribute of TOKEN.
 This string is prefixed with a space, or is the empty string.
 Argument PARENT specifies a parent type.
@@ -1550,8 +1554,8 @@ Argument COLOR specifies that the string should be 
colorized."
   (let ((t2 (semantic-c-tag-template-specifier token))
        (t1 (semantic-c-tag-template token))
        ;; @todo - Need to account for a parent that is a template
-       (pt1 (if parent (semantic-c-tag-template parent)))
-       (pt2 (if parent (semantic-c-tag-template-specifier parent)))
+       (_pt1 (if parent (semantic-c-tag-template parent)))
+       (_pt2 (if parent (semantic-c-tag-template-specifier parent)))
        )
     (cond (t2 ;; we have a template with specifier
           (concat " <"
@@ -1610,7 +1614,7 @@ handled.  A class is abstract only if its destructor is 
virtual."
         (member "virtual" (semantic-tag-modifiers tag))))
    (t (semantic-tag-abstract-p-default tag parent))))
 
-(defun semantic-c-dereference-typedef (type scope &optional type-declaration)
+(defun semantic-c-dereference-typedef (type _scope &optional type-declaration)
   "If TYPE is a typedef, get TYPE's type by name or tag, and return.
 SCOPE is not used, and TYPE-DECLARATION is used only if TYPE is not a typedef."
   (if (and (eq (semantic-tag-class type) 'type)
@@ -1655,7 +1659,7 @@ return `ref<Foo,Bar>'."
   (concat (semantic-tag-name type)
          "<" (semantic-c--template-name-1 (cdr spec-list)) ">"))
 
-(defun semantic-c-dereference-template (type scope &optional type-declaration)
+(defun semantic-c-dereference-template (type _scope &optional type-declaration)
   "Dereference any template specifiers in TYPE within SCOPE.
 If TYPE is a template, return a TYPE copy with the templates types
 instantiated as specified in TYPE-DECLARATION."
@@ -1677,7 +1681,7 @@ instantiated as specified in TYPE-DECLARATION."
   (list type type-declaration))
 
 ;;; Patch here by "Raf" for instantiating templates.
-(defun semantic-c-dereference-member-of (type scope &optional type-declaration)
+(defun semantic-c-dereference-member-of (type _scope &optional 
type-declaration)
   "Dereference through the `->' operator of TYPE.
 Uses the return type of the `->' operator if it is contained in TYPE.
 SCOPE is the current local scope to perform searches in.
@@ -1700,7 +1704,7 @@ Such an alias can be created through `using' statements 
in a
 namespace declaration.  This function checks the namespaces in
 SCOPE for such statements."
   (let ((scopetypes (oref scope scopetypes))
-       typename currentns tmp usingname result namespaces)
+       typename currentns result namespaces) ;; usingname tmp
     (when (and (semantic-tag-p type-declaration)
               (or (null type) (semantic-tag-prototype-p type)))
       (setq typename (semantic-analyze-split-name (semantic-tag-name 
type-declaration)))
@@ -1739,11 +1743,11 @@ with a fully qualified name in the original namespace.  
Returns
 nil if NAMESPACE is not an alias."
   (when (eq (semantic-tag-get-attribute namespace :kind) 'alias)
     (let ((typename (semantic-analyze-split-name (semantic-tag-name type)))
-         ns nstype originaltype newtype)
+         ns nstype originaltype) ;; newtype
       ;; Make typename unqualified
-      (if (listp typename)
-         (setq typename (last typename))
-       (setq typename (list typename)))
+      (setq typename (if (listp typename)
+                        (last typename)
+                      (list typename)))
       (when
          (and
           ;; Get original namespace and make sure TYPE exists there.
@@ -1755,13 +1759,13 @@ nil if NAMESPACE is not an alias."
                               (semantic-tag-get-attribute nstype :members))))
        ;; Construct new type with name in original namespace.
        (setq ns (semantic-analyze-split-name ns))
-       (setq newtype
-             (semantic-tag-clone
-              (car originaltype)
-              (semantic-analyze-unsplit-name
-               (if (listp ns)
-                   (append ns typename)
-                 (append (list ns) typename)))))))))
+       ;; (setq newtype
+       (semantic-tag-clone
+        (car originaltype)
+        (semantic-analyze-unsplit-name
+         (if (listp ns)
+             (append ns typename)
+           (append (list ns) typename)))))))) ;; )
 
 ;; This searches a type in a namespace, following through all using
 ;; statements.
@@ -1769,7 +1773,7 @@ nil if NAMESPACE is not an alias."
   "Check if TYPE is accessible in NAMESPACE through a using statement.
 Returns the original type from the namespace where it is defined,
 or nil if it cannot be found."
-  (let (usings result usingname usingtype unqualifiedname members shortname 
tmp)
+  (let (usings result usingname usingtype unqualifiedname members) ;; 
shortname tmp
     ;; Get all using statements from NAMESPACE.
     (when (and (setq usings (semantic-tag-get-attribute namespace :members))
               (setq usings (semantic-find-tags-by-class 'using usings)))
@@ -1842,7 +1846,7 @@ These are constants which are of type TYPE."
 
 (define-mode-local-override semantic-analyze-unsplit-name c-mode (namelist)
   "Assemble the list of names NAMELIST into a namespace name."
-  (mapconcat 'identity namelist "::"))
+  (mapconcat #'identity namelist "::"))
 
 (define-mode-local-override semantic-ctxt-scoped-types c++-mode (&optional 
point)
   "Return a list of tags of CLASS type based on POINT.
@@ -1885,7 +1889,7 @@ DO NOT return the list of tags encompassing point."
                        (semantic-get-local-variables))))
        (setq tagreturn
              (append tagreturn
-                     (mapcar 'semantic-tag-type tmp))))))
+                     (mapcar #'semantic-tag-type tmp))))))
     ;; Return the stuff
     tagreturn))
 
@@ -1943,7 +1947,7 @@ namespace, since this means all tags inside this include 
will
 have to be wrapped in that namespace."
   (let ((inctable (semanticdb-find-table-for-include-default includetag table))
        (inside-ns (semantic-tag-get-attribute includetag :inside-ns))
-       tags newtags namespaces prefix parenttable newtable)
+       tags newtags namespaces parenttable newtable) ;; prefix
     (if (or (null inside-ns)
            (not inctable)
            (not (slot-boundp inctable 'tags)))
@@ -2111,13 +2115,11 @@ actually in their parent which is not accessible.")
   "Set up a buffer for semantic parsing of the C language."
   (semantic-c-by--install-parser)
   (setq semantic-lex-syntax-modifications '((?> ".")
-                                            (?< ".")
-                                            )
-        )
+                                            (?< ".")))
 
   (setq semantic-lex-analyzer #'semantic-c-lexer)
-  (add-hook 'semantic-lex-reset-functions 'semantic-lex-spp-reset-hook nil t)
-  (when (eq major-mode 'c++-mode)
+  (add-hook 'semantic-lex-reset-functions #'semantic-lex-spp-reset-hook nil t)
+  (when (derived-mode-p 'c++-mode)
     (add-to-list 'semantic-lex-c-preprocessor-symbol-map '("__cplusplus" . 
"")))
   )
 
@@ -2142,7 +2144,7 @@ actually in their parent which is not accessible.")
 (defun semantic-c-describe-environment ()
   "Describe the Semantic features of the current C environment."
   (interactive)
-  (if (not (member 'c-mode (mode-local-equivalent-mode-p major-mode)))
+  (if (not (derived-mode-p 'c-mode))
       (error "Not useful to query C mode in %s mode" major-mode))
   (let ((gcc (when (boundp 'semantic-gcc-setup-data)
               semantic-gcc-setup-data))
diff --git a/lisp/cedet/semantic/bovine/debug.el 
b/lisp/cedet/semantic/bovine/debug.el
index 8ea9ac2..47850a5 100644
--- a/lisp/cedet/semantic/bovine/debug.el
+++ b/lisp/cedet/semantic/bovine/debug.el
@@ -1,4 +1,4 @@
-;;; semantic/bovine/debug.el --- Debugger support for bovinator
+;;; semantic/bovine/debug.el --- Debugger support for bovinator  -*- 
lexical-binding: t; -*-
 
 ;; Copyright (C) 2003, 2009-2021 Free Software Foundation, Inc.
 
@@ -123,7 +123,7 @@ Argument CONDITION is the thrown error condition."
                              frame)
     frame))
 
-(cl-defmethod semantic-debug-frame-highlight ((frame 
semantic-bovine-debug-error-frame))
+(cl-defmethod semantic-debug-frame-highlight ((_frame 
semantic-bovine-debug-error-frame))
   "Highlight a frame from an action."
   ;; How do I get the location of the action in the source buffer?
   )
diff --git a/lisp/cedet/semantic/bovine/el.el b/lisp/cedet/semantic/bovine/el.el
index dc61734..1170e71 100644
--- a/lisp/cedet/semantic/bovine/el.el
+++ b/lisp/cedet/semantic/bovine/el.el
@@ -1,4 +1,4 @@
-;;; semantic/bovine/el.el --- Semantic details for Emacs Lisp
+;;; semantic/bovine/el.el --- Semantic details for Emacs Lisp  -*- 
lexical-binding: t; -*-
 
 ;; Copyright (C) 1999-2005, 2007-2021 Free Software Foundation, Inc.
 
@@ -169,10 +169,10 @@ where:
 - FORM is an Elisp form read from the current buffer.
 - START and END are the beginning and end location of the
   corresponding data in the current buffer."
+  (declare (indent 1))
   (let ((sym (make-symbol "sym")))
     `(dolist (,sym ',symbols)
        (put ,sym 'semantic-elisp-form-parser #',parser))))
-(put 'semantic-elisp-setup-form-parser 'lisp-indent-function 1)
 
 (defmacro semantic-elisp-reuse-form-parser (symbol &rest symbols)
   "Reuse the form parser of SYMBOL for forms identified by SYMBOLS.
@@ -210,7 +210,7 @@ Return a bovination list to use."
 ;;; Form parsers
 ;;
 (semantic-elisp-setup-form-parser
-    (lambda (form start end)
+    (lambda (form _start _end)
       (semantic-tag-new-function
        (symbol-name (nth 2 form))
        nil
@@ -234,7 +234,7 @@ Return a bovination list to use."
   )
 
 (semantic-elisp-setup-form-parser
-    (lambda (form start end)
+    (lambda (form _start _end)
       (semantic-tag-new-function
        (symbol-name (nth 1 form))
        nil
@@ -256,7 +256,7 @@ Return a bovination list to use."
   )
 
 (semantic-elisp-setup-form-parser
-    (lambda (form start end)
+    (lambda (form _start _end)
       (let ((doc (semantic-elisp-form-to-doc-string (nth 3 form))))
         (semantic-tag-new-variable
          (symbol-name (nth 1 form))
@@ -274,7 +274,7 @@ Return a bovination list to use."
   )
 
 (semantic-elisp-setup-form-parser
-    (lambda (form start end)
+    (lambda (form _start _end)
       (let ((doc (semantic-elisp-form-to-doc-string (nth 3 form))))
         (semantic-tag-new-variable
          (symbol-name (nth 1 form))
@@ -290,7 +290,7 @@ Return a bovination list to use."
 
 
 (semantic-elisp-setup-form-parser
-    (lambda (form start end)
+    (lambda (form _start _end)
       (let ((doc (semantic-elisp-form-to-doc-string (nth 3 form))))
         (semantic-tag-new-variable
          (symbol-name (nth 1 form))
@@ -307,7 +307,7 @@ Return a bovination list to use."
 
 
 (semantic-elisp-setup-form-parser
-    (lambda (form start end)
+    (lambda (form _start _end)
       (let ((doc (semantic-elisp-form-to-doc-string (nth 3 form))))
         (semantic-tag
          (symbol-name (nth 1 form))
@@ -321,7 +321,7 @@ Return a bovination list to use."
 
 
 (semantic-elisp-setup-form-parser
-    (lambda (form start end)
+    (lambda (form _start _end)
       (semantic-tag-new-function
        (symbol-name (cadr (cadr form)))
        nil nil
@@ -333,7 +333,7 @@ Return a bovination list to use."
   )
 
 (semantic-elisp-setup-form-parser
-    (lambda (form start end)
+    (lambda (form _start _end)
       (let* ((a2 (nth 2 form))
              (a3 (nth 3 form))
              (args (if (listp a2) a2 a3))
@@ -353,7 +353,7 @@ Return a bovination list to use."
   )
 
 (semantic-elisp-setup-form-parser
-    (lambda (form start end)
+    (lambda (form _start _end)
       (semantic-tag-new-function
        (symbol-name (nth 1 form))
        nil
@@ -363,7 +363,7 @@ Return a bovination list to use."
   )
 
 (semantic-elisp-setup-form-parser
-    (lambda (form start end)
+    (lambda (form _start _end)
       (let ((docpart (nthcdr 4 form)))
        (semantic-tag-new-type
         (symbol-name (nth 1 form))
@@ -381,7 +381,7 @@ Return a bovination list to use."
   )
 
 (semantic-elisp-setup-form-parser
-    (lambda (form start end)
+    (lambda (form _start _end)
       (let ((slots (nthcdr 2 form)))
         ;; Skip doc string if present.
         (and (stringp (car slots))
@@ -399,7 +399,7 @@ Return a bovination list to use."
   )
 
 (semantic-elisp-setup-form-parser
-    (lambda (form start end)
+    (lambda (form _start _end)
       (semantic-tag-new-function
        (symbol-name (nth 1 form))
        nil nil
@@ -410,7 +410,7 @@ Return a bovination list to use."
   )
 
 (semantic-elisp-setup-form-parser
-    (lambda (form start end)
+    (lambda (form _start _end)
       (let ((args (nth 3 form)))
        (semantic-tag-new-function
         (symbol-name (nth 1 form))
@@ -424,7 +424,7 @@ Return a bovination list to use."
   )
 
 (semantic-elisp-setup-form-parser
-    (lambda (form start end)
+    (lambda (form _start _end)
       (semantic-tag-new-variable
        (symbol-name (nth 2 form))
        nil
@@ -437,7 +437,7 @@ Return a bovination list to use."
   )
 
 (semantic-elisp-setup-form-parser
-    (lambda (form start end)
+    (lambda (form _start _end)
       (let ((name (nth 1 form)))
         (semantic-tag-new-include
          (symbol-name (if (eq (car-safe name) 'quote)
@@ -449,7 +449,7 @@ Return a bovination list to use."
   )
 
 (semantic-elisp-setup-form-parser
-    (lambda (form start end)
+    (lambda (form _start _end)
       (let ((name (nth 1 form)))
         (semantic-tag-new-package
          (symbol-name (if (eq (car-safe name) 'quote)
@@ -500,7 +500,7 @@ into Emacs Lisp's memory."
        ""))))
 
 (define-mode-local-override semantic-documentation-for-tag
-  emacs-lisp-mode (tag &optional nosnarf)
+  emacs-lisp-mode (tag &optional _nosnarf)
   "Return the documentation string for TAG.
 Optional argument NOSNARF is ignored."
   (let ((d (semantic-tag-docstring tag)))
@@ -577,7 +577,7 @@ Override function for `semantic-tag-protection'."
      ((string= prot "protected") 'protected))))
 
 (define-mode-local-override semantic-tag-static-p
-  emacs-lisp-mode (tag &optional parent)
+  emacs-lisp-mode (tag &optional _parent)
   "Return non-nil if TAG is static in PARENT class.
 Overrides `semantic-nonterminal-static'."
   ;; This can only be true (theoretically) in a class where it is assigned.
@@ -588,7 +588,7 @@ Overrides `semantic-nonterminal-static'."
 ;; Emacs lisp is very different from C,C++ which most context parsing
 ;; functions are written.  Support them here.
 (define-mode-local-override semantic-up-context emacs-lisp-mode
-  (&optional point bounds-type)
+  (&optional _point _bounds-type)
   "Move up one context in an Emacs Lisp function.
 A Context in many languages is a block with its own local variables.
 In Emacs, we will move up lists and stop when one starts with one of
@@ -652,7 +652,7 @@ define-mode-overload\\)\
 
 
 (define-mode-local-override semantic-get-local-variables emacs-lisp-mode
-  (&optional point)
+  (&optional _point)
   "Return a list of local variables for POINT.
 Scan backwards from point at each successive function.  For all occurrences
 of `let' or `let*', grab those variable names."
@@ -940,7 +940,7 @@ ELisp variables can be pretty long, so track this one too.")
   ;; loaded into Emacs.
   )
 
-(add-hook 'emacs-lisp-mode-hook 'semantic-default-elisp-setup)
+(add-hook 'emacs-lisp-mode-hook #'semantic-default-elisp-setup)
 
 ;;; LISP MODE
 ;;
@@ -950,7 +950,7 @@ ELisp variables can be pretty long, so track this one too.")
 ;; See this syntax:
 ;; (defun foo () /#A)
 ;;
-(add-hook 'lisp-mode-hook 'semantic-default-elisp-setup)
+(add-hook 'lisp-mode-hook #'semantic-default-elisp-setup)
 
 (eval-after-load "semantic/db"
   '(require 'semantic/db-el)
diff --git a/lisp/cedet/semantic/bovine/gcc.el 
b/lisp/cedet/semantic/bovine/gcc.el
index 9cd9cdc..02bd0de 100644
--- a/lisp/cedet/semantic/bovine/gcc.el
+++ b/lisp/cedet/semantic/bovine/gcc.el
@@ -47,11 +47,11 @@ to give to the program."
       (erase-buffer)
       (setenv "LC_ALL" "C")
       (condition-case nil
-          (setq err (apply 'call-process gcc-cmd options))
+          (setq err (apply #'call-process gcc-cmd options))
         (error ;; Some bogus directory for the first time perhaps?
          (let ((default-directory (expand-file-name "~/")))
            (condition-case nil
-               (setq err (apply 'call-process gcc-cmd options))
+               (setq err (apply #'call-process gcc-cmd options))
              (error ;; gcc doesn't exist???
               nil)))))
       (setenv "LC_ALL" old-lc-messages)
@@ -89,8 +89,9 @@ to give to the program."
               (let ((path (substring line 1)))
                 (when (and (file-accessible-directory-p path)
                            (file-name-absolute-p path))
-                  (cl-pushnew (expand-file-name path) inc-path))))))))
-    inc-path))
+                  (cl-pushnew (expand-file-name path) inc-path
+                              :test #'equal))))))))
+    (nreverse inc-path)))
 
 
 (defun semantic-cpp-defs (str)
@@ -150,12 +151,12 @@ It should also include other symbols GCC was compiled 
with.")
   (let* ((fields (or semantic-gcc-setup-data
                      (semantic-gcc-fields (semantic-gcc-query "gcc" "-v"))))
          (cpp-options `("-E" "-dM" "-x" "c++" ,null-device))
-         (query (let ((q (apply 'semantic-gcc-query "cpp" cpp-options)))
+         (query (let ((q (apply #'semantic-gcc-query "cpp" cpp-options)))
                   (if (stringp q)
                       q
                     ;; `cpp' command in `semantic-gcc-setup' doesn't work on
                     ;; Mac, try `gcc'.
-                    (apply 'semantic-gcc-query "gcc" cpp-options))))
+                    (apply #'semantic-gcc-query "gcc" cpp-options))))
          (defines (if (stringp query)
                      (semantic-cpp-defs query)
                    (message (concat "Could not query gcc for defines. "
diff --git a/lisp/cedet/semantic/bovine/grammar.el 
b/lisp/cedet/semantic/bovine/grammar.el
index 4914ec9..e3df7b1 100644
--- a/lisp/cedet/semantic/bovine/grammar.el
+++ b/lisp/cedet/semantic/bovine/grammar.el
@@ -1,4 +1,4 @@
-;;; semantic/bovine/grammar.el --- Bovine's input grammar mode
+;;; semantic/bovine/grammar.el --- Bovine's input grammar mode  -*- 
lexical-binding: t; -*-
 ;;
 ;; Copyright (C) 2002-2021 Free Software Foundation, Inc.
 ;;
@@ -243,7 +243,8 @@ QUOTEMODE is the mode in which quoted symbols are slurred."
       (insert "\n")
       (cond
        ((eq (car sexp) 'EXPAND)
-        (insert ",(lambda (vals start end)")
+        (insert ",(lambda (vals start end)"
+                "\n(ignore vals start end)")
         ;; The EXPAND macro definition is mandatory
         (bovine-grammar-expand-form
          (apply (cdr (assq 'EXPAND bovine--grammar-macros)) (cdr sexp))
@@ -520,7 +521,8 @@ Menu items are appended to the common grammar menu.")
        (goto-char (point-min))
        (delete-region (point-min) (line-end-position))
        (insert ";;; " packagename
-               " --- Generated parser support file")
+                 " --- Generated parser support file  "
+                 "-*- lexical-binding:t -*-")
        (delete-trailing-whitespace)
        (re-search-forward ";;; \\(.*\\) ends here")
        (replace-match packagename nil nil nil 1)))))
diff --git a/lisp/cedet/semantic/bovine/make.el 
b/lisp/cedet/semantic/bovine/make.el
index 8089556..bb579cf 100644
--- a/lisp/cedet/semantic/bovine/make.el
+++ b/lisp/cedet/semantic/bovine/make.el
@@ -1,4 +1,4 @@
-;;; semantic/bovine/make.el --- Makefile parsing rules.
+;;; semantic/bovine/make.el --- Makefile parsing rules.  -*- lexical-binding: 
t; -*-
 
 ;; Copyright (C) 2000-2004, 2008-2021 Free Software Foundation, Inc.
 
@@ -103,13 +103,13 @@ Ignore them."
     xpand))
 
 (define-mode-local-override semantic-get-local-variables
-  makefile-mode (&optional point)
+  makefile-mode (&optional _point)
   "Override `semantic-get-local-variables' so it does not throw an error.
 We never have local variables in Makefiles."
   nil)
 
 (define-mode-local-override semantic-ctxt-current-class-list
-  makefile-mode (&optional point)
+  makefile-mode (&optional _point)
   "List of classes that are valid to place at point."
   (let ((tag (semantic-current-tag)))
     (when tag
@@ -176,7 +176,7 @@ This is the same as a regular prototype."
   (semantic-format-tag-prototype tag parent color))
 
 (define-mode-local-override semantic-analyze-possible-completions
-  makefile-mode (context &rest flags)
+  makefile-mode (context &rest _flags)
   "Return a list of possible completions in a Makefile.
 Uses default implementation, and also gets a list of filenames."
   (require 'semantic/analyze/complete)
@@ -218,7 +218,7 @@ Uses default implementation, and also gets a list of 
filenames."
                                           ;; but not actually parsed.
                                           (file . "File"))
         semantic-case-fold t
-        semantic-tag-expand-function 'semantic-make-expand-tag
+        semantic-tag-expand-function #'semantic-make-expand-tag
         semantic-lex-syntax-modifications '((?. "_")
                                             (?= ".")
                                             (?/ "_")
@@ -226,7 +226,7 @@ Uses default implementation, and also gets a list of 
filenames."
                                             (?+ ".")
                                             (?\\ ".")
                                             )
-        imenu-create-index-function 'semantic-create-imenu-index
+        imenu-create-index-function #'semantic-create-imenu-index
         )
   (setq semantic-lex-analyzer #'semantic-make-lexer)
   )
diff --git a/lisp/cedet/semantic/bovine/scm.el 
b/lisp/cedet/semantic/bovine/scm.el
index aaa86a1..0395412 100644
--- a/lisp/cedet/semantic/bovine/scm.el
+++ b/lisp/cedet/semantic/bovine/scm.el
@@ -1,6 +1,6 @@
-;;; semantic/bovine/scm.el --- Semantic details for Scheme (guile)
+;;; semantic/bovine/scm.el --- Semantic details for Scheme (guile)  -*- 
lexical-binding: t; -*-
 
-;;; Copyright (C) 2001-2004, 2008-2021 Free Software Foundation, Inc.
+;; Copyright (C) 2001-2021  Free Software Foundation, Inc.
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
 
@@ -49,7 +49,7 @@ actually on the local machine.")
                ")")
       (semantic-format-tag-prototype-default tag parent color))))
 
-(define-mode-local-override semantic-documentation-for-tag scheme-mode (tag 
&optional nosnarf)
+(define-mode-local-override semantic-documentation-for-tag scheme-mode (tag 
&optional _nosnarf)
   "Return the documentation string for TAG.
 Optional argument NOSNARF is ignored."
   (let ((d (semantic-tag-docstring tag)))
@@ -57,7 +57,7 @@ Optional argument NOSNARF is ignored."
        (substring d 1)
       d)))
 
-(define-mode-local-override semantic-insert-foreign-tag scheme-mode (tag 
tagfile)
+(define-mode-local-override semantic-insert-foreign-tag scheme-mode (tag 
_tagfile)
   "Insert TAG from TAGFILE at point.
 Attempts a simple prototype for calling or using TAG."
   (cond ((eq (semantic-tag-class tag) 'function)
@@ -102,8 +102,7 @@ syntax as specified by the syntax table."
                                             (function . "Functions")
                                             (include  . "Loads")
                                             (package  . "DefineModule"))
-        imenu-create-index-function 'semantic-create-imenu-index
-        imenu-create-index-function 'semantic-create-imenu-index
+        imenu-create-index-function #'semantic-create-imenu-index
         )
   (setq semantic-lex-analyzer #'semantic-scheme-lexer)
   )
diff --git a/lisp/cedet/semantic/chart.el b/lisp/cedet/semantic/chart.el
index e7848fa..0abbe45 100644
--- a/lisp/cedet/semantic/chart.el
+++ b/lisp/cedet/semantic/chart.el
@@ -1,4 +1,4 @@
-;;; semantic/chart.el --- Utilities for use with semantic tag tables
+;;; semantic/chart.el --- Utilities for use with semantic tag tables  -*- 
lexical-binding: t; -*-
 
 ;; Copyright (C) 1999-2001, 2003, 2005, 2008-2021 Free Software
 ;; Foundation, Inc.
@@ -43,7 +43,7 @@ TAGTABLE is passed to `semantic-something-to-tag-table'."
   (interactive)
   (let* ((stream (semantic-something-to-tag-table
                  (or tagtable (current-buffer))))
-        (names (mapcar 'cdr semantic-symbol->name-assoc-list))
+        (names (mapcar #'cdr semantic-symbol->name-assoc-list))
         (nums (mapcar
                (lambda (symname)
                  (length
@@ -57,7 +57,7 @@ TAGTABLE is passed to `semantic-something-to-tag-table'."
                       nums "Volume")
     ))
 
-(defun semantic-chart-database-size (&optional tagtable)
+(defun semantic-chart-database-size (&optional _tagtable)
   "Create a bar chart representing the size of each file in semanticdb.
 Each bar represents how many toplevel tags in TAGTABLE
 exist in each database entry.
@@ -68,7 +68,7 @@ TAGTABLE is passed to `semantic-something-to-tag-table'."
     (error "Semanticdb is not enabled"))
   (let* ((db semanticdb-current-database)
         (dbt (semanticdb-get-database-tables db))
-        (names (mapcar 'car
+        (names (mapcar #'car
                        (object-assoc-list
                         'file
                         dbt)))
@@ -84,8 +84,8 @@ TAGTABLE is passed to `semantic-something-to-tag-table'."
         (nums nil)
         (fh (/ (- (frame-height) 7) 4)))
     (setq numnuts (sort numnuts (lambda (a b) (> (car a) (car b)))))
-    (setq names (mapcar 'cdr numnuts)
-         nums (mapcar 'car numnuts))
+    (setq names (mapcar #'cdr numnuts)
+         nums (mapcar #'car numnuts))
     (if (> (length names) fh)
        (progn
          (setcdr (nthcdr fh names) nil)
diff --git a/lisp/cedet/semantic/complete.el b/lisp/cedet/semantic/complete.el
index c835058..d6ef796 100644
--- a/lisp/cedet/semantic/complete.el
+++ b/lisp/cedet/semantic/complete.el
@@ -1,4 +1,4 @@
-;;; semantic/complete.el --- Routines for performing tag completion
+;;; semantic/complete.el --- Routines for performing tag completion  -*- 
lexical-binding: t; -*-
 
 ;; Copyright (C) 2003-2005, 2007-2021 Free Software Foundation, Inc.
 
@@ -154,8 +154,8 @@ Presumably if you call this you will insert something new 
there."
 (defun semantic-completion-message (fmt &rest args)
   "Display the string FMT formatted with ARGS at the end of the minibuffer."
   (if semantic-complete-inline-overlay
-      (apply 'message fmt args)
-    (apply 'message (concat "%s" fmt) (buffer-string) args)))
+      (apply #'message fmt args)
+    (apply #'message (concat "%s" fmt) (buffer-string) args)))
 
 ;;; ------------------------------------------------------------
 ;;; MINIBUFFER: Option Selection harnesses
@@ -171,14 +171,14 @@ Value should be a ... what?")
 
 (defvar semantic-complete-key-map
   (let ((km (make-sparse-keymap)))
-    (define-key km " " 'semantic-complete-complete-space)
-    (define-key km "\t" 'semantic-complete-complete-tab)
-    (define-key km "\C-m" 'semantic-complete-done)
-    (define-key km "\C-g" 'abort-recursive-edit)
-    (define-key km "\M-n" 'next-history-element)
-    (define-key km "\M-p" 'previous-history-element)
-    (define-key km "\C-n" 'next-history-element)
-    (define-key km "\C-p" 'previous-history-element)
+    (define-key km " " #'semantic-complete-complete-space)
+    (define-key km "\t" #'semantic-complete-complete-tab)
+    (define-key km "\C-m" #'semantic-complete-done)
+    (define-key km "\C-g" #'abort-recursive-edit)
+    (define-key km "\M-n" #'next-history-element)
+    (define-key km "\M-p" #'previous-history-element)
+    (define-key km "\C-n" #'next-history-element)
+    (define-key km "\C-p" #'previous-history-element)
     ;; Add history navigation
     km)
   "Keymap used while completing across a list of tags.")
@@ -488,7 +488,7 @@ If PARTIAL, do partial completion stopping at spaces."
       )
      (t nil))))
 
-(defun semantic-complete-do-completion (&optional partial inline)
+(defun semantic-complete-do-completion (&optional partial _inline)
   "Do a completion for the current minibuffer.
 If PARTIAL, do partial completion stopping at spaces.
 if INLINE, then completion is happening inline in a buffer."
@@ -550,12 +550,12 @@ if INLINE, then completion is happening inline in a 
buffer."
 ;; push ourselves out of this mode on alternate keypresses.
 (defvar semantic-complete-inline-map
   (let ((km (make-sparse-keymap)))
-    (define-key km "\C-i" 'semantic-complete-inline-TAB)
-    (define-key km "\M-p" 'semantic-complete-inline-up)
-    (define-key km "\M-n" 'semantic-complete-inline-down)
-    (define-key km "\C-m" 'semantic-complete-inline-done)
-    (define-key km "\C-\M-c" 'semantic-complete-inline-exit)
-    (define-key km "\C-g" 'semantic-complete-inline-quit)
+    (define-key km "\C-i" #'semantic-complete-inline-TAB)
+    (define-key km "\M-p" #'semantic-complete-inline-up)
+    (define-key km "\M-n" #'semantic-complete-inline-down)
+    (define-key km "\C-m" #'semantic-complete-inline-done)
+    (define-key km "\C-\M-c" #'semantic-complete-inline-exit)
+    (define-key km "\C-g" #'semantic-complete-inline-quit)
     (define-key km "?"
       (lambda () (interactive)
        (describe-variable 'semantic-complete-inline-map)))
@@ -620,7 +620,7 @@ Similar to `minibuffer-contents' when completing in the 
minibuffer."
   "Exit inline completion mode."
   (interactive)
   ;; Remove this hook FIRST!
-  (remove-hook 'pre-command-hook 'semantic-complete-pre-command-hook)
+  (remove-hook 'pre-command-hook #'semantic-complete-pre-command-hook)
 
   (condition-case nil
       (progn
@@ -649,7 +649,7 @@ Similar to `minibuffer-contents' when completing in the 
minibuffer."
   ;; Remove this hook LAST!!!
   ;; This will force us back through this function if there was
   ;; some sort of error above.
-  (remove-hook 'post-command-hook 'semantic-complete-post-command-hook)
+  (remove-hook 'post-command-hook #'semantic-complete-post-command-hook)
 
   ;;(message "Exiting inline completion.")
   )
@@ -770,8 +770,8 @@ END is at the end of the current symbol being completed."
   (overlay-put semantic-complete-inline-overlay
               'semantic-original-start start)
   ;; Install our command hooks
-  (add-hook 'pre-command-hook 'semantic-complete-pre-command-hook)
-  (add-hook 'post-command-hook 'semantic-complete-post-command-hook)
+  (add-hook 'pre-command-hook #'semantic-complete-pre-command-hook)
+  (add-hook 'post-command-hook #'semantic-complete-post-command-hook)
   ;; Go!
   (semantic-complete-inline-force-display)
   )
@@ -929,8 +929,8 @@ The only options available for completion are those which 
can be logically
 inserted into the current context.")
 
 (cl-defmethod semantic-collector-calculate-completions-raw
-  ((obj semantic-collector-analyze-completions) prefix completionlist)
-  "calculate the completions for prefix from completionlist."
+  ((obj semantic-collector-analyze-completions) prefix _completionlist)
+  "calculate the completions for prefix from COMPLETIONLIST."
   ;; if there are no completions yet, calculate them.
   (if (not (slot-boundp obj 'first-pass-completions))
       (oset obj first-pass-completions
@@ -943,7 +943,7 @@ inserted into the current context.")
               prefix
               (oref obj first-pass-completions)))))
 
-(cl-defmethod semantic-collector-cleanup ((obj semantic-collector-abstract))
+(cl-defmethod semantic-collector-cleanup ((_obj semantic-collector-abstract))
   "Clean up any mess this collector may have."
   nil)
 
@@ -1004,7 +1004,7 @@ Output must be in semanticdb Find result format."
        (list (cons table result)))))
 
 (cl-defmethod semantic-collector-calculate-completions
-  ((obj semantic-collector-abstract) prefix partial)
+  ((obj semantic-collector-abstract) prefix _partial)
   "Calculate completions for prefix as setup for other queries."
   (let* ((case-fold-search semantic-case-fold)
         (same-prefix-p (semantic-collector-last-prefix= obj prefix))
@@ -1014,7 +1014,8 @@ Output must be in semanticdb Find result format."
          (cond ((or same-prefix-p
                     (and last-prefix (eq (compare-strings
                                           last-prefix 0 nil
-                                          prefix 0 (length last-prefix)) t)))
+                                          prefix 0 (length last-prefix))
+                                         t)))
                 ;; We have the same prefix, or last-prefix is a
                 ;; substring of the of new prefix, in which case we are
                 ;; refining our symbol so just re-use cache.
@@ -1023,7 +1024,8 @@ Output must be in semanticdb Find result format."
                      (> (length prefix) 1)
                      (eq (compare-strings
                           prefix 0 nil
-                          last-prefix 0 (length prefix)) t))
+                          last-prefix 0 (length prefix))
+                         t))
                   ;; The new prefix is a substring of the old
                   ;; prefix, and it's longer than one character.
                   ;; Perform a full search to pull in additional
@@ -1134,7 +1136,7 @@ into a buffer."
     (semanticdb-find-result-nth-in-buffer (oref obj current-exact-match) 0)))
 
 (cl-defmethod semantic-collector-all-completions
-  ((obj semantic-collector-abstract) prefix)
+  ((obj semantic-collector-abstract) _prefix)
   "For OBJ, retrieve all completions matching PREFIX.
 The returned list consists of all the tags currently
 matching PREFIX."
@@ -1142,7 +1144,7 @@ matching PREFIX."
     (oref obj last-all-completions)))
 
 (cl-defmethod semantic-collector-try-completion
-  ((obj semantic-collector-abstract) prefix)
+  ((obj semantic-collector-abstract) _prefix)
   "For OBJ, attempt to match PREFIX.
 See `try-completion' for details on how this works.
 Return nil for no match.
@@ -1153,7 +1155,7 @@ with that name."
       (oref obj last-completion)))
 
 (cl-defmethod semantic-collector-calculate-cache
-  ((obj semantic-collector-abstract))
+  ((_obj semantic-collector-abstract))
   "Calculate the completion cache for OBJ."
   nil
   )
@@ -1176,7 +1178,7 @@ These collectors track themselves on a per-buffer basis."
   :abstract t)
 
 (cl-defmethod make-instance ((this (subclass 
semantic-collector-buffer-abstract))
-                            &rest args)
+                            &rest _args)
   "Reuse previously created objects of this type in buffer."
   (let ((old nil)
        (bl semantic-collector-per-buffer-list))
@@ -1193,7 +1195,7 @@ These collectors track themselves on a per-buffer basis."
     old))
 
 ;; Buffer specific collectors should flush themselves
-(defun semantic-collector-buffer-flush (newcache)
+(defun semantic-collector-buffer-flush (_newcache)
   "Flush all buffer collector objects.
 NEWCACHE is the new tag table, but we ignore it."
   (condition-case nil
@@ -1204,7 +1206,7 @@ NEWCACHE is the new tag table, but we ignore it."
     (error nil)))
 
 (add-hook 'semantic-after-toplevel-cache-change-hook
-         'semantic-collector-buffer-flush)
+         #'semantic-collector-buffer-flush)
 
 ;;; DEEP BUFFER SPECIFIC COMPLETION
 ;;
@@ -1246,8 +1248,8 @@ Uses semanticdb for searching all tags in the current 
project."
 
 
 (cl-defmethod semantic-collector-calculate-completions-raw
-  ((obj semantic-collector-project) prefix completionlist)
-  "Calculate the completions for prefix from completionlist."
+  ((obj semantic-collector-project) prefix _completionlist)
+  "Calculate the completions for prefix from COMPLETIONLIST."
   (semanticdb-find-tags-for-completion prefix (oref obj path)))
 
 ;;; Brutish Project search
@@ -1259,8 +1261,8 @@ Uses semanticdb for searching all tags in the current 
project."
                  "semantic/db-find")
 
 (cl-defmethod semantic-collector-calculate-completions-raw
-  ((obj semantic-collector-project-brutish) prefix completionlist)
-  "Calculate the completions for prefix from completionlist."
+  ((obj semantic-collector-project-brutish) prefix _completionlist)
+  "Calculate the completions for prefix from COMPLETIONLIST."
   (require 'semantic/db-find)
   (semanticdb-brute-deep-find-tags-for-completion prefix (oref obj path)))
 
@@ -1273,8 +1275,8 @@ Uses semanticdb for searching all tags in the current 
project."
   "Completion engine for tags in a project.")
 
 (cl-defmethod semantic-collector-calculate-completions-raw
-  ((obj semantic-collector-local-members) prefix completionlist)
-  "Calculate the completions for prefix from completionlist."
+  ((obj semantic-collector-local-members) prefix _completionlist)
+  "Calculate the completions for prefix from COMPLETIONLIST."
   (let* ((scope (or (oref obj scope)
                    (oset obj scope (semantic-calculate-scope))))
         (localstuff (oref scope scope)))
@@ -1323,7 +1325,7 @@ a collector, and tracking tables of completion to 
display."
 
 (define-obsolete-function-alias 'semantic-displayor-cleanup
   #'semantic-displayer-cleanup "27.1")
-(cl-defmethod semantic-displayer-cleanup ((obj semantic-displayer-abstract))
+(cl-defmethod semantic-displayer-cleanup ((_obj semantic-displayer-abstract))
   "Clean up any mess this displayer may have."
   nil)
 
@@ -1348,37 +1350,37 @@ a collector, and tracking tables of completion to 
display."
 
 (define-obsolete-function-alias 'semantic-displayor-show-request
   #'semantic-displayer-show-request "27.1")
-(cl-defmethod semantic-displayer-show-request ((obj 
semantic-displayer-abstract))
+(cl-defmethod semantic-displayer-show-request ((_obj 
semantic-displayer-abstract))
   "A request to show the current tags table."
   (ding))
 
 (define-obsolete-function-alias 'semantic-displayor-focus-request
   #'semantic-displayer-focus-request "27.1")
-(cl-defmethod semantic-displayer-focus-request ((obj 
semantic-displayer-abstract))
+(cl-defmethod semantic-displayer-focus-request ((_obj 
semantic-displayer-abstract))
   "A request to for the displayer to focus on some tag option."
   (ding))
 
 (define-obsolete-function-alias 'semantic-displayor-scroll-request
   #'semantic-displayer-scroll-request "27.1")
-(cl-defmethod semantic-displayer-scroll-request ((obj 
semantic-displayer-abstract))
+(cl-defmethod semantic-displayer-scroll-request ((_obj 
semantic-displayer-abstract))
   "A request to for the displayer to scroll the completion list (if needed)."
   (scroll-other-window))
 
 (define-obsolete-function-alias 'semantic-displayor-focus-previous
   #'semantic-displayer-focus-previous "27.1")
-(cl-defmethod semantic-displayer-focus-previous ((obj 
semantic-displayer-abstract))
+(cl-defmethod semantic-displayer-focus-previous ((_obj 
semantic-displayer-abstract))
   "Set the current focus to the previous item."
   nil)
 
 (define-obsolete-function-alias 'semantic-displayor-focus-next
   #'semantic-displayer-focus-next "27.1")
-(cl-defmethod semantic-displayer-focus-next ((obj semantic-displayer-abstract))
+(cl-defmethod semantic-displayer-focus-next ((_obj 
semantic-displayer-abstract))
   "Set the current focus to the next item."
   nil)
 
 (define-obsolete-function-alias 'semantic-displayor-current-focus
   #'semantic-displayer-current-focus "27.1")
-(cl-defmethod semantic-displayer-current-focus ((obj 
semantic-displayer-abstract))
+(cl-defmethod semantic-displayer-current-focus ((_obj 
semantic-displayer-abstract))
   "Return a single tag currently in focus.
 This object type doesn't do focus, so will never have a focus object."
   nil)
@@ -1452,7 +1454,7 @@ which have the same name."
 (define-obsolete-function-alias 'semantic-displayor-set-completions
   #'semantic-displayer-set-completions "27.1")
 (cl-defmethod semantic-displayer-set-completions ((obj 
semantic-displayer-focus-abstract)
-                                              table prefix)
+                                                 _table _prefix)
   "Set the list of tags to be completed over to TABLE."
   (cl-call-next-method)
   (slot-makeunbound obj 'focus))
@@ -1663,7 +1665,7 @@ This will not happen if you directly set this variable 
via `setq'."
   "Display completions options in a tooltip.
 Display mechanism using tooltip for a list of possible completions.")
 
-(cl-defmethod initialize-instance :after ((obj semantic-displayer-tooltip) 
&rest args)
+(cl-defmethod initialize-instance :after ((_obj semantic-displayer-tooltip) 
&rest _args)
   "Make sure we have tooltips required."
   (require 'tooltip))
 
@@ -1681,16 +1683,16 @@ Display mechanism using tooltip for a list of possible 
completions.")
           (table (semantic-unique-tag-table-by-name tablelong))
           (completions (mapcar 
semantic-completion-displayer-format-tag-function table))
           (numcompl (length completions))
-          (typing-count (oref obj typing-count))
+          ;; (typing-count (oref obj typing-count))
           (mode (oref obj mode))
           (max-tags (oref obj max-tags-initial))
           (matchtxt (semantic-completion-text))
           msg msg-tail)
       ;; Keep a count of the consecutive completion commands entered by the 
user.
-      (if (and (stringp (this-command-keys))
-              (string= (this-command-keys) "\C-i"))
-         (oset obj typing-count (1+ (oref obj typing-count)))
-       (oset obj typing-count 0))
+      (oset obj typing-count
+           (if (equal (this-command-keys) "\C-i")
+               (1+ (oref obj typing-count))
+             0))
       (cond
        ((eq mode 'quiet)
        ;; Switch back to standard mode if user presses key more than 5 times.
@@ -1730,7 +1732,7 @@ Display mechanism using tooltip for a list of possible 
completions.")
          (when semantic-idle-scheduler-verbose-flag
            (setq msg "[NO MATCH]"))))
        ;; Create the tooltip text.
-       (setq msg (concat msg (mapconcat 'identity completions "\n"))))
+       (setq msg (concat msg (mapconcat #'identity completions "\n"))))
       ;; Add any tail info.
       (setq msg (concat msg msg-tail))
       ;; Display tooltip.
@@ -1828,12 +1830,10 @@ text using overlay options.")
 (define-obsolete-function-alias 'semantic-displayor-set-completions
   #'semantic-displayer-set-completions "27.1")
 (cl-defmethod semantic-displayer-set-completions ((obj 
semantic-displayer-ghost)
-                                              table prefix)
+                                                 _table _prefix)
   "Set the list of tags to be completed over to TABLE."
   (cl-call-next-method)
-
-  (semantic-displayer-cleanup obj)
-  )
+  (semantic-displayer-cleanup obj))
 
 
 (define-obsolete-function-alias 'semantic-displayor-show-request
@@ -2058,9 +2058,8 @@ prompts.  these are calculated from the CONTEXT variable 
passed in."
      (semantic-displayer-traditional-with-focus-highlight)
      (with-current-buffer (oref context buffer)
        (goto-char (cdr (oref context bounds)))
-       (concat prompt (mapconcat 'identity syms ".")
-              (if syms "." "")
-              ))
+       (concat prompt (mapconcat #'identity syms ".")
+              (if syms "." "")))
      nil
      inp
      history)))
diff --git a/lisp/cedet/semantic/ctxt.el b/lisp/cedet/semantic/ctxt.el
index 8d5b5dc..17ffaef 100644
--- a/lisp/cedet/semantic/ctxt.el
+++ b/lisp/cedet/semantic/ctxt.el
@@ -1,4 +1,4 @@
-;;; semantic/ctxt.el --- Context calculations for Semantic tools.
+;;; semantic/ctxt.el --- Context calculations for Semantic tools  -*- 
lexical-binding: t; -*-
 
 ;; Copyright (C) 1999-2021 Free Software Foundation, Inc.
 
@@ -137,18 +137,16 @@ Return non-nil if there is no upper context."
 
 (defmacro semantic-with-buffer-narrowed-to-context (&rest body)
   "Execute BODY with the buffer narrowed to the current context."
+  (declare (indent 0) (debug t))
   `(save-restriction
      (semantic-narrow-to-context)
      ,@body))
-(put 'semantic-with-buffer-narrowed-to-context 'lisp-indent-function 0)
-(add-hook 'edebug-setup-hook
-         (lambda ()
-           (def-edebug-spec semantic-with-buffer-narrowed-to-context
-             (def-body))))
 
 ;;; Local Variables
 ;;
-;;
+
+(defvar semantic--progress-reporter)
+
 (define-overloadable-function semantic-get-local-variables (&optional point)
   "Get the local variables based on POINT's context.
 Local variables are returned in Semantic tag format.
@@ -345,14 +343,10 @@ beginning and end of a command."
 
 (defmacro semantic-with-buffer-narrowed-to-command (&rest body)
   "Execute BODY with the buffer narrowed to the current command."
+  (declare (indent 0) (debug t))
   `(save-restriction
      (semantic-narrow-to-command)
      ,@body))
-(put 'semantic-with-buffer-narrowed-to-command 'lisp-indent-function 0)
-(add-hook 'edebug-setup-hook
-         (lambda ()
-           (def-edebug-spec semantic-with-buffer-narrowed-to-command
-             (def-body))))
 
 (define-overloadable-function semantic-ctxt-end-of-symbol (&optional point)
   "Move point to the end of the current symbol under POINT.
@@ -374,7 +368,7 @@ work on C like languages."
         ;; NOTE: The [ \n] expression below should used \\s-, but that
         ;; doesn't work in C since \n means end-of-comment, and isn't
         ;; really whitespace.
-        (fieldsep (concat "[ \t\n\r]*\\(" fieldsep1 "\\)[ 
\t\n\r]*\\(\\w\\|\\s_\\)"))
+        ;;(fieldsep (concat "[ \t\n\r]*\\(" fieldsep1 "\\)[ 
\t\n\r]*\\(\\w\\|\\s_\\)"))
         (case-fold-search semantic-case-fold)
         (continuesearch t)
         (end nil)
@@ -655,7 +649,7 @@ POINT defaults to the value of point in current buffer.
 You should override this function in multiple mode buffers to
 determine which major mode apply at point.")
 
-(defun semantic-ctxt-current-mode-default (&optional point)
+(defun semantic-ctxt-current-mode-default (&optional _point)
   "Return the major mode active at POINT.
 POINT defaults to the value of point in current buffer.
 This default implementation returns the current major mode."
@@ -671,7 +665,7 @@ The return value can be a mixed list of either strings 
(names of
 types that are in scope) or actual tags (type declared locally
 that may or may not have a name.)")
 
-(defun semantic-ctxt-scoped-types-default (&optional point)
+(defun semantic-ctxt-scoped-types-default (&optional _point)
   "Return a list of scoped types by name for the current context at POINT.
 This is very different for various languages, and does nothing unless
 overridden."
diff --git a/lisp/cedet/semantic/db-debug.el b/lisp/cedet/semantic/db-debug.el
index c553ab4..d8f7034 100644
--- a/lisp/cedet/semantic/db-debug.el
+++ b/lisp/cedet/semantic/db-debug.el
@@ -1,6 +1,6 @@
-;;; semantic/db-debug.el --- Extra level debugging routines for Semantic
+;;; semantic/db-debug.el --- Extra level debugging routines for Semantic  -*- 
lexical-binding: t; -*-
 
-;;; Copyright (C) 2008-2021 Free Software Foundation, Inc.
+;; Copyright (C) 2008-2021  Free Software Foundation, Inc.
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
 
@@ -38,7 +38,7 @@
     (data-debug-new-buffer "*SEMANTICDB*")
     (data-debug-insert-stuff-list db "*")))
 
-(defalias 'semanticdb-adebug-database-list 'semanticdb-dump-all-table-summary)
+(defalias 'semanticdb-adebug-database-list #'semanticdb-dump-all-table-summary)
 
 (defun semanticdb-adebug-current-database ()
   "Run ADEBUG on the current database."
diff --git a/lisp/cedet/semantic/db-ebrowse.el 
b/lisp/cedet/semantic/db-ebrowse.el
index 946f9ef..db37512 100644
--- a/lisp/cedet/semantic/db-ebrowse.el
+++ b/lisp/cedet/semantic/db-ebrowse.el
@@ -1,4 +1,4 @@
-;;; semantic/db-ebrowse.el --- Semanticdb backend using ebrowse.
+;;; semantic/db-ebrowse.el --- Semanticdb backend using ebrowse.  -*- 
lexical-binding: t; -*-
 
 ;; Copyright (C) 2005-2021 Free Software Foundation, Inc.
 
@@ -135,8 +135,8 @@ is specified by `semanticdb-default-save-directory'."
   (let* ((savein (semanticdb-ebrowse-file-for-directory dir))
         (filebuff (get-buffer-create "*SEMANTICDB EBROWSE TMP*"))
         (files (directory-files (expand-file-name dir) t))
-        (mma auto-mode-alist)
-        (regexp nil)
+        ;; (mma auto-mode-alist)
+        ;; (regexp nil)
         )
     ;; Create the input to the ebrowse command
     (with-current-buffer filebuff
@@ -227,7 +227,7 @@ warn instead."
   ()
   "Search Ebrowse for symbols.")
 
-(cl-defmethod semanticdb-needs-refresh-p ((table semanticdb-table-ebrowse))
+(cl-defmethod semanticdb-needs-refresh-p ((_table semanticdb-table-ebrowse))
   "EBROWSE database do not need to be refreshed.
 
 JAVE: stub for needs-refresh, because, how do we know if BROWSE files
@@ -274,7 +274,7 @@ For instance: 
/home/<username>/.semanticdb/!usr!include!BROWSE"
       (insert-file-contents B)
       (let ((ans nil)
            (efcn (symbol-function 'ebrowse-show-progress)))
-       (fset 'ebrowse-show-progress #'(lambda (&rest junk) nil))
+       (fset 'ebrowse-show-progress #'(lambda (&rest _junk) nil))
        (unwind-protect ;; Protect against errors w/ ebrowse
            (setq ans (list B (ebrowse-read)))
          ;; These items must always happen
@@ -341,10 +341,10 @@ If there is no database for DIRECTORY available, then
     (while T
 
       (let* ((tree (car T))
-            (class (ebrowse-ts-class tree)); root class of tree
+            ;;(class (ebrowse-ts-class tree)); root class of tree
             ;; Something funny going on with this file thing...
-             (filename (or (ebrowse-cs-source-file class)
-                          (ebrowse-cs-file class)))
+             ;; (filename (or (ebrowse-cs-source-file class)
+            ;;            (ebrowse-cs-file class)))
             )
        (cond
         ((ebrowse-globals-tree-p tree)
@@ -363,18 +363,18 @@ If there is no database for DIRECTORY available, then
 
 ;;; Filename based methods
 ;;
-(defun semanticdb-ebrowse-add-globals-to-table (dbe tree)
+(defun semanticdb-ebrowse-add-globals-to-table (_dbe tree)
   "For database DBE, add the ebrowse TREE into the table."
   (if (or (not (ebrowse-ts-p tree))
          (not (ebrowse-globals-tree-p tree)))
       (signal 'wrong-type-argument (list 'ebrowse-ts-p tree)))
 
   (let* ((class (ebrowse-ts-class tree))
-        (fname (or (ebrowse-cs-source-file class)
-                   (ebrowse-cs-file class)
-                   ;; Not def'd here, assume our current
-                   ;; file
-                   (concat default-directory "/unknown-proxy.hh")))
+        ;; (fname (or (ebrowse-cs-source-file class)
+        ;;            (ebrowse-cs-file class)
+        ;;            ;; Not def'd here, assume our current
+        ;;            ;; file
+        ;;            (concat default-directory "/unknown-proxy.hh")))
         (vars (ebrowse-ts-member-functions tree))
         (fns (ebrowse-ts-member-variables tree))
         (toks nil)
@@ -573,7 +573,7 @@ return that."
 ;; how your new search routines are implemented.
 ;;
 (cl-defmethod semanticdb-find-tags-by-name-method
-  ((table semanticdb-table-ebrowse) name &optional tags)
+  ((_table semanticdb-table-ebrowse) _name &optional tags)
   "Find all tags named NAME in TABLE.
 Return a list of tags."
   ;;(message "semanticdb-find-tags-by-name-method name -- %s" name)
@@ -588,7 +588,7 @@ Return a list of tags."
   )
 
 (cl-defmethod semanticdb-find-tags-by-name-regexp-method
-  ((table semanticdb-table-ebrowse) regex &optional tags)
+  ((_table semanticdb-table-ebrowse) _regex &optional tags)
   "Find all tags with name matching REGEX in TABLE.
 Optional argument TAGS is a list of tags to search.
 Return a list of tags."
@@ -598,7 +598,7 @@ Return a list of tags."
     ))
 
 (cl-defmethod semanticdb-find-tags-for-completion-method
-  ((table semanticdb-table-ebrowse) prefix &optional tags)
+  ((_table semanticdb-table-ebrowse) _prefix &optional tags)
   "In TABLE, find all occurrences of tags matching PREFIX.
 Optional argument TAGS is a list of tags to search.
 Returns a table of all matching tags."
@@ -608,7 +608,7 @@ Returns a table of all matching tags."
     ))
 
 (cl-defmethod semanticdb-find-tags-by-class-method
-  ((table semanticdb-table-ebrowse) class &optional tags)
+  ((_table semanticdb-table-ebrowse) _class &optional tags)
   "In TABLE, find all occurrences of tags of CLASS.
 Optional argument TAGS is a list of tags to search.
 Returns a table of all matching tags."
@@ -625,7 +625,7 @@ Returns a table of all matching tags."
 ;;
 
 (cl-defmethod semanticdb-deep-find-tags-by-name-method
-  ((table semanticdb-table-ebrowse) name &optional tags)
+  ((_table semanticdb-table-ebrowse) _name &optional _tags)
   "Find all tags name NAME in TABLE.
 Optional argument TAGS is a list of tags to search.
 Like `semanticdb-find-tags-by-name-method' for ebrowse."
@@ -633,7 +633,7 @@ Like `semanticdb-find-tags-by-name-method' for ebrowse."
   (cl-call-next-method))
 
 (cl-defmethod semanticdb-deep-find-tags-by-name-regexp-method
-  ((table semanticdb-table-ebrowse) regex &optional tags)
+  ((_table semanticdb-table-ebrowse) _regex &optional _tags)
   "Find all tags with name matching REGEX in TABLE.
 Optional argument TAGS is a list of tags to search.
 Like `semanticdb-find-tags-by-name-method' for ebrowse."
@@ -641,7 +641,7 @@ Like `semanticdb-find-tags-by-name-method' for ebrowse."
   (cl-call-next-method))
 
 (cl-defmethod semanticdb-deep-find-tags-for-completion-method
-  ((table semanticdb-table-ebrowse) prefix &optional tags)
+  ((_table semanticdb-table-ebrowse) _prefix &optional _tags)
   "In TABLE, find all occurrences of tags matching PREFIX.
 Optional argument TAGS is a list of tags to search.
 Like `semanticdb-find-tags-for-completion-method' for ebrowse."
@@ -651,7 +651,7 @@ Like `semanticdb-find-tags-for-completion-method' for 
ebrowse."
 ;;; Advanced Searches
 ;;
 (cl-defmethod semanticdb-find-tags-external-children-of-type-method
-  ((table semanticdb-table-ebrowse) type &optional tags)
+  ((_table semanticdb-table-ebrowse) _type &optional tags)
   "Find all nonterminals which are child elements of TYPE
 Optional argument TAGS is a list of tags to search.
 Return a list of tags."
diff --git a/lisp/cedet/semantic/db-el.el b/lisp/cedet/semantic/db-el.el
index 4699e72..78339c3 100644
--- a/lisp/cedet/semantic/db-el.el
+++ b/lisp/cedet/semantic/db-el.el
@@ -1,6 +1,6 @@
-;;; semantic/db-el.el --- Semantic database extensions for Emacs Lisp
+;;; semantic/db-el.el --- Semantic database extensions for Emacs Lisp  -*- 
lexical-binding: t; -*-
 
-;;; Copyright (C) 2002-2021 Free Software Foundation, Inc.
+;; Copyright (C) 2002-2021  Free Software Foundation, Inc.
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
 ;; Keywords: tags
@@ -53,7 +53,7 @@ It does not need refreshing."
   "Return nil, we never need a refresh."
   nil)
 
-(cl-defmethod semanticdb-debug-info ((obj semanticdb-table-emacs-lisp))
+(cl-defmethod semanticdb-debug-info ((_obj semanticdb-table-emacs-lisp))
   (list "(proxy)"))
 
 (cl-defmethod cl-print-object ((obj semanticdb-table-emacs-lisp) stream)
@@ -195,9 +195,6 @@ If Emacs cannot resolve this symbol to a particular file, 
then return nil."
        (when tab (cons tab match))))))
 
 (autoload 'help-function-arglist "help-fns")
-(defalias 'semanticdb-elisp-sym-function-arglist 'help-function-arglist)
-(make-obsolete 'semanticdb-elisp-sym-function-arglist
-              'help-function-arglist "CEDET 1.1")
 
 (defun semanticdb-elisp-sym->tag (sym &optional toktype)
   "Convert SYM into a semantic tag.
@@ -347,6 +344,9 @@ Return a list of tags."
             )
        taglst))))
 
+(define-obsolete-function-alias 'semanticdb-elisp-sym-function-arglist
+  #'help-function-arglist "24.3")
+
 (provide 'semantic/db-el)
 
 ;;; semantic/db-el.el ends here
diff --git a/lisp/cedet/semantic/db-file.el b/lisp/cedet/semantic/db-file.el
index 59e9db9..c9007ac 100644
--- a/lisp/cedet/semantic/db-file.el
+++ b/lisp/cedet/semantic/db-file.el
@@ -1,6 +1,6 @@
-;;; semantic/db-file.el --- Save a semanticdb to a cache file.
+;;; semantic/db-file.el --- Save a semanticdb to a cache file.  -*- 
lexical-binding: t; -*-
 
-;;; Copyright (C) 2000-2005, 2007-2021 Free Software Foundation, Inc.
+;; Copyright (C) 2000-2021  Free Software Foundation, Inc.
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
 ;; Keywords: tags
@@ -154,8 +154,6 @@ If DIRECTORY doesn't exist, create a new one."
 
 ;;; File IO
 
-(declare-function inversion-test "inversion")
-
 (defun semanticdb-load-database (filename)
   "Load the database FILENAME."
   (condition-case foo
@@ -163,32 +161,19 @@ If DIRECTORY doesn't exist, create a new one."
                                        'semanticdb-project-database-file))
             (c (semanticdb-get-database-tables r))
             (tv (oref r semantic-tag-version))
-            (fv (oref r semanticdb-version))
-            )
+             (fv (oref r semanticdb-version)))
        ;; Restore the parent-db connection
        (while c
          (oset (car c) parent-db r)
          (setq c (cdr c)))
        (unless (and (equal semanticdb-file-version fv)
                     (equal semantic-tag-version tv))
-         ;; Try not to load inversion unless we need it:
-         (require 'inversion)
-         (if (not (inversion-test 'semanticdb-file fv))
-             (when (inversion-test 'semantic-tag tv)
-               ;; Incompatible version.  Flush tables.
-               (semanticdb-flush-database-tables r)
-               ;; Reset the version to new version.
-               (oset r semantic-tag-version semantic-tag-version)
-               ;; Warn user
-               (message "Semanticdb file is old.  Starting over for %s"
-                        filename))
-           ;; Version is not ok.  Flush whole system
-           (message "semanticdb file is old.  Starting over for %s"
-                    filename)
-           ;; This database is so old, we need to replace it.
-           ;; We also need to delete it from the instance tracker.
-           (delete-instance r)
-           (setq r nil)))
+          ;; Version is not ok.  Flush whole system
+          (message "semanticdb file is old.  Starting over for %s" filename)
+          ;; This database is so old, we need to replace it.
+          ;; We also need to delete it from the instance tracker.
+          (delete-instance r)
+          (setq r nil))
        r)
     (error (message "Cache Error: [%s] %s, Restart"
                    filename foo)
@@ -373,13 +358,13 @@ Uses `semanticdb-persistent-path' to determine the return 
value."
   (object-assoc (file-name-nondirectory filename) 'file (oref obj tables)))
 
 (cl-defmethod semanticdb-file-name-non-directory
-  ((dbclass (subclass semanticdb-project-database-file)))
+  ((_dbclass (subclass semanticdb-project-database-file)))
   "Return the file name DBCLASS will use.
 File name excludes any directory part."
   semanticdb-default-file-name)
 
 (cl-defmethod semanticdb-file-name-directory
-  ((dbclass (subclass semanticdb-project-database-file)) directory)
+  ((_dbclass (subclass semanticdb-project-database-file)) directory)
   "Return the relative directory to where DBCLASS will save its cache file.
 The returned path is related to DIRECTORY."
   (if semanticdb-default-save-directory
diff --git a/lisp/cedet/semantic/db-find.el b/lisp/cedet/semantic/db-find.el
index db88463..c96a426 100644
--- a/lisp/cedet/semantic/db-find.el
+++ b/lisp/cedet/semantic/db-find.el
@@ -1,4 +1,4 @@
-;;; semantic/db-find.el --- Searching through semantic databases.
+;;; semantic/db-find.el --- Searching through semantic databases.  -*- 
lexical-binding: t; -*-
 
 ;; Copyright (C) 2000-2021 Free Software Foundation, Inc.
 
@@ -209,14 +209,14 @@ This class will cache data derived during various 
searches.")
   )
 
 (cl-defmethod semanticdb-synchronize ((idx semanticdb-find-search-index)
-                                  new-tags)
+                                     _new-tags)
   "Synchronize the search index IDX with some NEW-TAGS."
   ;; Reset our parts.
   (semantic-reset idx)
   ;; Notify dependants by clearing their indices.
   (semanticdb-notify-references
    (oref idx table)
-   (lambda (tab me)
+   (lambda (tab _me)
      (semantic-reset (semanticdb-get-table-index tab))))
   )
 
@@ -230,7 +230,7 @@ This class will cache data derived during various 
searches.")
        ;; Notify dependants by clearing their indices.
        (semanticdb-notify-references
         (oref idx table)
-        (lambda (tab me)
+        (lambda (tab _me)
           (semantic-reset (semanticdb-get-table-index tab))))
        )
     ;; Else, not an include, by just a type.
@@ -240,7 +240,7 @@ This class will cache data derived during various 
searches.")
        ;; Notify dependants by clearing their indices.
        (semanticdb-notify-references
         (oref idx table)
-        (lambda (tab me)
+        (lambda (tab _me)
           (let ((tab-idx (semanticdb-get-table-index tab)))
             ;; Not a full reset?
             (when (oref tab-idx type-cache)
@@ -791,7 +791,8 @@ PREBUTTONTEXT is some text between prefix and the overlay 
button."
         (file (semantic-tag-file-name tag))
         (str1 (format "%S %s" mode name))
         (str2 (format " : %s" file))
-        (tip nil))
+        ;; (tip nil)
+        )
     (insert prefix prebuttontext str1)
     (setq end (point))
     (insert str2)
@@ -807,7 +808,7 @@ PREBUTTONTEXT is some text between prefix and the overlay 
button."
     (put-text-property start end 'ddebug (cdr consdata))
     (put-text-property start end 'ddebug-indent(length prefix))
     (put-text-property start end 'ddebug-prefix prefix)
-    (put-text-property start end 'help-echo tip)
+    ;; (put-text-property start end 'help-echo tip)
     (put-text-property start end 'ddebug-function
                       'data-debug-insert-tag-parts-from-point)
     (insert "\n")
@@ -1009,7 +1010,7 @@ is still made current."
          (when norm
            ;; The normalized tags can now be found based on that
            ;; tags table.
-           (condition-case foo
+           (condition-case nil
                (progn
                  (semanticdb-set-buffer (car norm))
                  ;; Now reset ans
diff --git a/lisp/cedet/semantic/db-global.el b/lisp/cedet/semantic/db-global.el
index 2f40082..6bdc7b3 100644
--- a/lisp/cedet/semantic/db-global.el
+++ b/lisp/cedet/semantic/db-global.el
@@ -1,4 +1,4 @@
-;;; semantic/db-global.el --- Semantic database extensions for GLOBAL
+;;; semantic/db-global.el --- Semantic database extensions for GLOBAL  -*- 
lexical-binding: t; -*-
 
 ;; Copyright (C) 2002-2006, 2008-2021 Free Software Foundation, Inc.
 
@@ -69,7 +69,8 @@ values."
     (let ((semanticdb--ih (mode-local-value mode 'semantic-init-mode-hook)))
       (eval `(setq-mode-local
               ,mode semantic-init-mode-hook
-              (cons 'semanticdb-enable-gnu-global-hook semanticdb--ih))))
+              (cons 'semanticdb-enable-gnu-global-hook ',semanticdb--ih))
+            t))
     t
     )
   )
@@ -114,7 +115,7 @@ if optional DONT-ERR-IF-NOT-AVAILABLE is non-nil; else 
throw an error."
    )
   "A table for returning search results from GNU Global.")
 
-(cl-defmethod semanticdb-debug-info ((obj semanticdb-table-global))
+(cl-defmethod semanticdb-debug-info ((_obj semanticdb-table-global))
   (list "(proxy)"))
 
 (cl-defmethod cl-print-object ((obj semanticdb-table-global) stream)
@@ -123,7 +124,7 @@ Adds the number of tags in this file to the object print 
name."
   (princ (eieio-object-name obj (semanticdb-debug-info obj))
          stream))
 
-(cl-defmethod semanticdb-equivalent-mode ((table semanticdb-table-global) 
&optional buffer)
+(cl-defmethod semanticdb-equivalent-mode ((_table semanticdb-table-global) 
&optional _buffer)
   "Return t, pretend that this table's mode is equivalent to BUFFER.
 Equivalent modes are specified by the `semantic-equivalent-major-modes'
 local variable."
@@ -146,7 +147,7 @@ For each file hit, get the traditional semantic table from 
that file."
 
   (cl-call-next-method))
 
-(cl-defmethod semanticdb-file-table ((obj semanticdb-project-database-global) 
filename)
+(cl-defmethod semanticdb-file-table ((obj semanticdb-project-database-global) 
_filename)
   "From OBJ, return FILENAME's associated table object."
   ;; We pass in "don't load".  I wonder if we need to avoid that or not?
   (car (semanticdb-get-database-tables obj))
@@ -157,7 +158,7 @@ For each file hit, get the traditional semantic table from 
that file."
 ;; Only NAME based searches work with GLOBAL as that is all it tracks.
 ;;
 (cl-defmethod semanticdb-find-tags-by-name-method
-  ((table semanticdb-table-global) name &optional tags)
+  ((_table semanticdb-table-global) name &optional tags)
   "Find all tags named NAME in TABLE.
 Return a list of tags."
   (if tags
@@ -174,7 +175,7 @@ Return a list of tags."
       )))
 
 (cl-defmethod semanticdb-find-tags-by-name-regexp-method
-  ((table semanticdb-table-global) regex &optional tags)
+  ((_table semanticdb-table-global) regex &optional tags)
   "Find all tags with name matching REGEX in TABLE.
 Optional argument TAGS is a list of tags to search.
 Return a list of tags."
@@ -187,7 +188,7 @@ Return a list of tags."
       )))
 
 (cl-defmethod semanticdb-find-tags-for-completion-method
-  ((table semanticdb-table-global) prefix &optional tags)
+  ((_table semanticdb-table-global) prefix &optional tags)
   "In TABLE, find all occurrences of tags matching PREFIX.
 Optional argument TAGS is a list of tags to search.
 Returns a table of all matching tags."
diff --git a/lisp/cedet/semantic/db-javascript.el 
b/lisp/cedet/semantic/db-javascript.el
index 2b13886..cad561e 100644
--- a/lisp/cedet/semantic/db-javascript.el
+++ b/lisp/cedet/semantic/db-javascript.el
@@ -1,4 +1,4 @@
-;;; semantic/db-javascript.el --- Semantic database extensions for javascript
+;;; semantic/db-javascript.el --- Semantic database extensions for javascript  
-*- lexical-binding: t; -*-
 
 ;; Copyright (C) 2002-2021 Free Software Foundation, Inc.
 
@@ -129,20 +129,20 @@ Create one of our special tables that can act as an 
intermediary."
   (cl-call-next-method)
   )
 
-(cl-defmethod semanticdb-file-table ((obj 
semanticdb-project-database-javascript) filename)
+(cl-defmethod semanticdb-file-table ((obj 
semanticdb-project-database-javascript) _filename)
   "From OBJ, return FILENAME's associated table object."
   ;; NOTE: See not for `semanticdb-get-database-tables'.
   (car (semanticdb-get-database-tables obj))
   )
 
-(cl-defmethod semanticdb-get-tags ((table semanticdb-table-javascript ))
+(cl-defmethod semanticdb-get-tags ((_table semanticdb-table-javascript ))
   "Return the list of tags belonging to TABLE."
   ;; NOTE: Omniscient databases probably don't want to keep large tables
   ;;       lolly-gagging about.  Keep internal Emacs tables empty and
   ;;       refer to alternate databases when you need something.
   semanticdb-javascript-tags)
 
-(cl-defmethod semanticdb-equivalent-mode ((table semanticdb-table-javascript) 
&optional buffer)
+(cl-defmethod semanticdb-equivalent-mode ((_table semanticdb-table-javascript) 
&optional buffer)
   "Return non-nil if TABLE's mode is equivalent to BUFFER.
 Equivalent modes are specified by the `semantic-equivalent-major-modes'
 local variable."
@@ -193,7 +193,7 @@ database (if available.)"
     result))
 
 (cl-defmethod semanticdb-find-tags-by-name-method
-  ((table semanticdb-table-javascript) name &optional tags)
+  ((_table semanticdb-table-javascript) name &optional tags)
   "Find all tags named NAME in TABLE.
 Return a list of tags."
   (if tags
@@ -203,7 +203,7 @@ Return a list of tags."
     ))
 
 (cl-defmethod semanticdb-find-tags-by-name-regexp-method
-  ((table semanticdb-table-javascript) regex &optional tags)
+  ((_table semanticdb-table-javascript) regex &optional tags)
   "Find all tags with name matching REGEX in TABLE.
 Optional argument TAGS is a list of tags to search.
 Return a list of tags."
@@ -214,7 +214,7 @@ Return a list of tags."
     ))
 
 (cl-defmethod semanticdb-find-tags-for-completion-method
-  ((table semanticdb-table-javascript) prefix &optional tags)
+  ((_table semanticdb-table-javascript) prefix &optional tags)
   "In TABLE, find all occurrences of tags matching PREFIX.
 Optional argument TAGS is a list of tags to search.
 Returns a table of all matching tags."
@@ -224,7 +224,7 @@ Returns a table of all matching tags."
     ))
 
 (cl-defmethod semanticdb-find-tags-by-class-method
-  ((table semanticdb-table-javascript) class &optional tags)
+  ((_table semanticdb-table-javascript) _class &optional tags)
   "In TABLE, find all occurrences of tags of CLASS.
 Optional argument TAGS is a list of tags to search.
 Returns a table of all matching tags."
@@ -268,7 +268,7 @@ Like `semanticdb-find-tags-for-completion-method' for 
javascript."
 ;;; Advanced Searches
 ;;
 (cl-defmethod semanticdb-find-tags-external-children-of-type-method
-  ((table semanticdb-table-javascript) type &optional tags)
+  ((_table semanticdb-table-javascript) _type &optional tags)
   "Find all nonterminals which are child elements of TYPE.
 Optional argument TAGS is a list of tags to search.
 Return a list of tags."
diff --git a/lisp/cedet/semantic/db-mode.el b/lisp/cedet/semantic/db-mode.el
index aa4634f..839dcb8 100644
--- a/lisp/cedet/semantic/db-mode.el
+++ b/lisp/cedet/semantic/db-mode.el
@@ -1,4 +1,4 @@
-;;; semantic/db-mode.el --- Semanticdb Minor Mode
+;;; semantic/db-mode.el --- Semanticdb Minor Mode  -*- lexical-binding: t; -*-
 
 ;; Copyright (C) 2008-2021 Free Software Foundation, Inc.
 
diff --git a/lisp/cedet/semantic/db-ref.el b/lisp/cedet/semantic/db-ref.el
index da09f98..10108d3 100644
--- a/lisp/cedet/semantic/db-ref.el
+++ b/lisp/cedet/semantic/db-ref.el
@@ -1,6 +1,6 @@
-;;; semantic/db-ref.el --- Handle cross-db file references
+;;; semantic/db-ref.el --- Handle cross-db file references  -*- 
lexical-binding: t; -*-
 
-;;; Copyright (C) 2007-2021 Free Software Foundation, Inc.
+;; Copyright (C) 2007-2021  Free Software Foundation, Inc.
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
 
@@ -67,7 +67,7 @@ will be added to the database that INCLUDE-TAG refers to."
       (object-add-to-list refdbt 'db-refs dbt)
       t)))
 
-(cl-defmethod semanticdb-check-references ((dbt semanticdb-abstract-table))
+(cl-defmethod semanticdb-check-references ((_dbt semanticdb-abstract-table))
   "Check and cleanup references in the database DBT.
 Abstract tables would be difficult to reference."
   ;; Not sure how an abstract table can have references.
@@ -109,7 +109,7 @@ refers to DBT will be removed."
          ))
       (setq refs (cdr refs)))))
 
-(cl-defmethod semanticdb-refresh-references ((dbt semanticdb-abstract-table))
+(cl-defmethod semanticdb-refresh-references ((_dbt semanticdb-abstract-table))
   "Refresh references to DBT in other files."
   ;; alternate tables can't be edited, so can't be changed.
   nil
diff --git a/lisp/cedet/semantic/db-typecache.el 
b/lisp/cedet/semantic/db-typecache.el
index 8c394cd..c0fee3b 100644
--- a/lisp/cedet/semantic/db-typecache.el
+++ b/lisp/cedet/semantic/db-typecache.el
@@ -1,4 +1,4 @@
-;;; semantic/db-typecache.el --- Manage Datatypes
+;;; semantic/db-typecache.el --- Manage Datatypes  -*- lexical-binding: t; -*-
 
 ;; Copyright (C) 2007-2021 Free Software Foundation, Inc.
 
@@ -74,14 +74,14 @@ Said object must support `semantic-reset' methods.")
 
   (oset tc stream nil)
 
-  (mapc 'semantic-reset (oref tc dependants))
+  (mapc #'semantic-reset (oref tc dependants))
   (oset tc dependants nil)
   )
 
 (cl-defmethod semanticdb-typecache-notify-reset ((tc semanticdb-typecache))
   "Do a reset from a notify from a table we depend on."
   (oset tc includestream nil)
-  (mapc 'semantic-reset (oref tc dependants))
+  (mapc #'semantic-reset (oref tc dependants))
   (oset tc dependants nil)
   )
 
@@ -90,7 +90,7 @@ Said object must support `semantic-reset' methods.")
   "Reset the typecache based on a partial reparse."
   (when (semantic-find-tags-by-class 'include new-tags)
     (oset tc includestream nil)
-    (mapc 'semantic-reset (oref tc dependants))
+    (mapc #'semantic-reset (oref tc dependants))
     (oset tc dependants nil)
     )
 
@@ -167,15 +167,15 @@ If there is no table, create one, and fill it in."
   (oset tc stream nil)
   )
 
-(cl-defmethod semanticdb-synchronize ((cache semanticdb-database-typecache)
-                                  new-tags)
+(cl-defmethod semanticdb-synchronize ((_cache semanticdb-database-typecache)
+                                     _new-tags)
   "Synchronize a CACHE with some NEW-TAGS."
-  )
+  nil)
 
-(cl-defmethod semanticdb-partial-synchronize ((cache 
semanticdb-database-typecache)
-                                          new-tags)
+(cl-defmethod semanticdb-partial-synchronize ((_cache 
semanticdb-database-typecache)
+                                             _new-tags)
   "Synchronize a CACHE with some changed NEW-TAGS."
-  )
+  nil)
 
 (cl-defmethod semanticdb-get-typecache ((db semanticdb-project-database))
   "Retrieve the typecache from the semantic database DB.
@@ -312,7 +312,7 @@ If TAG has fully qualified names, expand it to a series of 
nested
 namespaces instead."
   tag)
 
-(cl-defmethod semanticdb-typecache-file-tags ((table 
semanticdb-abstract-table))
+(cl-defmethod semanticdb-typecache-file-tags ((_table 
semanticdb-abstract-table))
   "No tags available from non-file based tables."
   nil)
 
@@ -338,7 +338,7 @@ all included files."
     (oref cache filestream)
     ))
 
-(cl-defmethod semanticdb-typecache-include-tags ((table 
semanticdb-abstract-table))
+(cl-defmethod semanticdb-typecache-include-tags ((_table 
semanticdb-abstract-table))
   "No tags available from non-file based tables."
   nil)
 
@@ -611,7 +611,7 @@ If there isn't one, create it.
   (require 'data-debug)
   (let* ((tab semanticdb-current-table)
         (idx (semanticdb-get-table-index tab))
-        (junk (oset idx type-cache nil)) ;; flush!
+        (_ (oset idx type-cache nil)) ;; flush!
         (start (current-time))
         (tc (semanticdb-typecache-for-database (oref tab parent-db)))
         (end (current-time))
diff --git a/lisp/cedet/semantic/debug.el b/lisp/cedet/semantic/debug.el
index ce4afbb..4f96746 100644
--- a/lisp/cedet/semantic/debug.el
+++ b/lisp/cedet/semantic/debug.el
@@ -1,4 +1,4 @@
-;;; semantic/debug.el --- Language Debugger framework
+;;; semantic/debug.el --- Language Debugger framework  -*- lexical-binding: t; 
-*-
 
 ;; Copyright (C) 2003-2005, 2008-2021 Free Software Foundation, Inc.
 
@@ -265,12 +265,12 @@ on different types of return values."
    )
   "One frame representation.")
 
-(cl-defmethod semantic-debug-frame-highlight ((frame semantic-debug-frame))
+(cl-defmethod semantic-debug-frame-highlight ((_frame semantic-debug-frame))
   "Highlight one parser frame."
 
   )
 
-(cl-defmethod semantic-debug-frame-info ((frame semantic-debug-frame))
+(cl-defmethod semantic-debug-frame-info ((_frame semantic-debug-frame))
   "Display info about this one parser frame."
 
   )
@@ -279,21 +279,21 @@ on different types of return values."
 ;;
 (defvar semantic-debug-mode-map
   (let ((km (make-sparse-keymap)))
-    (define-key km "n" 'semantic-debug-next)
-    (define-key km " " 'semantic-debug-next)
-    (define-key km "s" 'semantic-debug-step)
-    (define-key km "u" 'semantic-debug-up)
-    (define-key km "d" 'semantic-debug-down)
-    (define-key km "f" 'semantic-debug-fail-match)
-    (define-key km "h" 'semantic-debug-print-state)
-    (define-key km "s" 'semantic-debug-jump-to-source)
-    (define-key km "p" 'semantic-debug-jump-to-parser)
-    (define-key km "q" 'semantic-debug-quit)
-    (define-key km "a" 'semantic-debug-abort)
-    (define-key km "g" 'semantic-debug-go)
-    (define-key km "b" 'semantic-debug-set-breakpoint)
+    (define-key km "n" #'semantic-debug-next)
+    (define-key km " " #'semantic-debug-next)
+    (define-key km "s" #'semantic-debug-step)
+    (define-key km "u" #'semantic-debug-up)
+    (define-key km "d" #'semantic-debug-down)
+    (define-key km "f" #'semantic-debug-fail-match)
+    (define-key km "h" #'semantic-debug-print-state)
+    (define-key km "s" #'semantic-debug-jump-to-source)
+    (define-key km "p" #'semantic-debug-jump-to-parser)
+    (define-key km "q" #'semantic-debug-quit)
+    (define-key km "a" #'semantic-debug-abort)
+    (define-key km "g" #'semantic-debug-go)
+    (define-key km "b" #'semantic-debug-set-breakpoint)
     ;; Some boring bindings.
-    (define-key km "e" 'eval-expression)
+    (define-key km "e" #'eval-expression)
 
     km)
   "Keymap used when in semantic-debug-node.")
@@ -514,49 +514,49 @@ by overriding one of the command methods.  Be sure to use
 down to your parser later."
   :abstract t)
 
-(cl-defmethod semantic-debug-parser-next ((parser semantic-debug-parser))
+(cl-defmethod semantic-debug-parser-next ((_parser semantic-debug-parser))
   "Execute next for this PARSER."
   (setq semantic-debug-user-command 'next)
   )
 
-(cl-defmethod semantic-debug-parser-step ((parser semantic-debug-parser))
+(cl-defmethod semantic-debug-parser-step ((_parser semantic-debug-parser))
   "Execute a step for this PARSER."
   (setq semantic-debug-user-command 'step)
   )
 
-(cl-defmethod semantic-debug-parser-go ((parser semantic-debug-parser))
+(cl-defmethod semantic-debug-parser-go ((_parser semantic-debug-parser))
   "Continue execution in this PARSER until the next breakpoint."
   (setq semantic-debug-user-command 'go)
   )
 
-(cl-defmethod semantic-debug-parser-fail ((parser semantic-debug-parser))
+(cl-defmethod semantic-debug-parser-fail ((_parser semantic-debug-parser))
   "Continue execution in this PARSER until the next breakpoint."
   (setq semantic-debug-user-command 'fail)
   )
 
-(cl-defmethod semantic-debug-parser-quit ((parser semantic-debug-parser))
+(cl-defmethod semantic-debug-parser-quit ((_parser semantic-debug-parser))
   "Continue execution in this PARSER until the next breakpoint."
   (setq semantic-debug-user-command 'quit)
   )
 
-(cl-defmethod semantic-debug-parser-abort ((parser semantic-debug-parser))
+(cl-defmethod semantic-debug-parser-abort ((_parser semantic-debug-parser))
   "Continue execution in this PARSER until the next breakpoint."
   (setq semantic-debug-user-command 'abort)
   )
 
-(cl-defmethod semantic-debug-parser-print-state ((parser 
semantic-debug-parser))
+(cl-defmethod semantic-debug-parser-print-state ((_parser 
semantic-debug-parser))
   "Print state for this PARSER at the current breakpoint."
   (with-slots (current-frame) semantic-debug-current-interface
     (when current-frame
       (semantic-debug-frame-info current-frame)
       )))
 
-(cl-defmethod semantic-debug-parser-break ((parser semantic-debug-parser))
+(cl-defmethod semantic-debug-parser-break ((_parser semantic-debug-parser))
   "Set a breakpoint for this PARSER."
   )
 
 ;; Stack stuff
-(cl-defmethod semantic-debug-parser-frames ((parser semantic-debug-parser))
+(cl-defmethod semantic-debug-parser-frames ((_parser semantic-debug-parser))
   "Return a list of frames for the current parser.
 A frame is of the form:
   ( .. .what ? .. )
diff --git a/lisp/cedet/semantic/decorate.el b/lisp/cedet/semantic/decorate.el
index 53c54ab..3e6651d 100644
--- a/lisp/cedet/semantic/decorate.el
+++ b/lisp/cedet/semantic/decorate.el
@@ -1,7 +1,6 @@
-;;; semantic/decorate.el --- Utilities for decorating/highlighting tokens.
+;;; semantic/decorate.el --- Utilities for decorating/highlighting tokens.  
-*- lexical-binding: t; -*-
 
-;;; Copyright (C) 1999-2003, 2005-2007, 2009-2021 Free Software
-;;; Foundation, Inc.
+;; Copyright (C) 1999-2021  Free Software Foundation, Inc.
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
 ;; Keywords: syntax
@@ -51,7 +50,7 @@ Optional FACE specifies the face to use."
     ))
 
 ;;; Momentary Highlighting - One line
-(defun semantic-momentary-highlight-one-tag-line (tag &optional face)
+(defun semantic-momentary-highlight-one-tag-line (tag &optional _face)
   "Highlight the first line of TAG, unhighlighting before next command.
 Optional argument FACE specifies the face to do the highlighting."
   (save-excursion
@@ -88,7 +87,7 @@ If VISIBLE is non-nil, make the text visible."
   (overlay-get (semantic-tag-overlay tag) 'invisible))
 
 (defun semantic-overlay-signal-read-only
-  (overlay after start end &optional len)
+  (overlay after start end &optional _len)
   "Hook used in modification hooks to prevent modification.
 Allows deletion of the entire text.
 Argument OVERLAY, AFTER, START, END, and LEN are passed in by the system."
@@ -261,7 +260,7 @@ nil implies the tag should be fully shown."
 
 (declare-function semantic-current-tag "semantic/find")
 
-(defun semantic-set-tag-folded-isearch (overlay)
+(defun semantic-set-tag-folded-isearch (_overlay)
   "Called by isearch if it discovers text in the folded region.
 OVERLAY is passed in by isearch."
   (semantic-set-tag-folded (semantic-current-tag) nil)
diff --git a/lisp/cedet/semantic/decorate/include.el 
b/lisp/cedet/semantic/decorate/include.el
index ee7fad1..a3bf4e2 100644
--- a/lisp/cedet/semantic/decorate/include.el
+++ b/lisp/cedet/semantic/decorate/include.el
@@ -1,4 +1,4 @@
-;;; semantic/decorate/include.el --- Decoration modes for include statements
+;;; semantic/decorate/include.el --- Decoration modes for include statements  
-*- lexical-binding: t; -*-
 
 ;; Copyright (C) 2008-2021 Free Software Foundation, Inc.
 
@@ -55,7 +55,7 @@ Used by the decoration style: 
`semantic-decoration-on-includes'."
 
 (defvar semantic-decoration-on-include-map
   (let ((km (make-sparse-keymap)))
-    (define-key km semantic-decoration-mouse-3 
'semantic-decoration-include-menu)
+    (define-key km semantic-decoration-mouse-3 
#'semantic-decoration-include-menu)
     km)
   "Keymap used on includes.")
 
@@ -114,7 +114,7 @@ Used by the decoration style: 
`semantic-decoration-on-unknown-includes'."
 (defvar semantic-decoration-on-unknown-include-map
   (let ((km (make-sparse-keymap)))
     ;(define-key km [ mouse-2 ] 'semantic-decoration-unknown-include-describe)
-    (define-key km semantic-decoration-mouse-3 
'semantic-decoration-unknown-include-menu)
+    (define-key km semantic-decoration-mouse-3 
#'semantic-decoration-unknown-include-menu)
     km)
   "Keymap used on unparsed includes.")
 
@@ -169,7 +169,7 @@ Used by the decoration style: 
`semantic-decoration-on-fileless-includes'."
 (defvar semantic-decoration-on-fileless-include-map
   (let ((km (make-sparse-keymap)))
     ;(define-key km [ mouse-2 ] 'semantic-decoration-fileless-include-describe)
-    (define-key km semantic-decoration-mouse-3 
'semantic-decoration-fileless-include-menu)
+    (define-key km semantic-decoration-mouse-3 
#'semantic-decoration-fileless-include-menu)
     km)
   "Keymap used on unparsed includes.")
 
@@ -223,7 +223,7 @@ Used by the decoration style: 
`semantic-decoration-on-unparsed-includes'."
 
 (defvar semantic-decoration-on-unparsed-include-map
   (let ((km (make-sparse-keymap)))
-    (define-key km semantic-decoration-mouse-3 
'semantic-decoration-unparsed-include-menu)
+    (define-key km semantic-decoration-mouse-3 
#'semantic-decoration-unparsed-include-menu)
     km)
   "Keymap used on unparsed includes.")
 
@@ -535,7 +535,7 @@ Argument EVENT is the mouse clicked event."
   (interactive)
   (let* ((tag (semantic-current-tag))
         (table (semanticdb-find-table-for-include tag (current-buffer)))
-        (mm major-mode))
+        ) ;; (mm major-mode)
     (with-output-to-temp-buffer (help-buffer) ; "*Help*"
       (help-setup-xref (list #'semantic-decoration-fileless-include-describe)
                       (called-interactively-p 'interactive))
@@ -793,7 +793,7 @@ any decorated referring includes.")
   (let ((table (oref obj table)))
     ;; This is a hack.  Add in something better?
     (semanticdb-notify-references
-     table (lambda (tab me)
+     table (lambda (tab _me)
             (semantic-decoration-unparsed-include-refrence-reset tab)
             ))
     ))
@@ -805,7 +805,7 @@ any decorated referring includes.")
       (semantic-reset cache)))
 
 (cl-defmethod semanticdb-synchronize ((cache 
semantic-decoration-unparsed-include-cache)
-                                  new-tags)
+                                  _new-tags)
   "Synchronize a CACHE with some NEW-TAGS."
   (semantic-reset cache))
 
diff --git a/lisp/cedet/semantic/decorate/mode.el 
b/lisp/cedet/semantic/decorate/mode.el
index 884b066..7895015 100644
--- a/lisp/cedet/semantic/decorate/mode.el
+++ b/lisp/cedet/semantic/decorate/mode.el
@@ -1,4 +1,4 @@
-;;; semantic/decorate/mode.el --- Minor mode for decorating tags
+;;; semantic/decorate/mode.el --- Minor mode for decorating tags  -*- 
lexical-binding: t; -*-
 
 ;; Copyright (C) 2000-2005, 2007-2021 Free Software Foundation, Inc.
 
@@ -264,9 +264,9 @@ non-nil if the minor mode is enabled."
                    (buffer-name)))
         ;; Add hooks
         (add-hook 'semantic-after-partial-cache-change-hook
-                  'semantic-decorate-tags-after-partial-reparse nil t)
+                  #'semantic-decorate-tags-after-partial-reparse nil t)
         (add-hook 'semantic-after-toplevel-cache-change-hook
-                  'semantic-decorate-tags-after-full-reparse nil t)
+                  #'semantic-decorate-tags-after-full-reparse nil t)
         ;; Add decorations to available tags.  The above hooks ensure
         ;; that new tags will be decorated when they become available.
         ;; However, don't do this immediately, because EDE will be
@@ -282,9 +282,9 @@ non-nil if the minor mode is enabled."
     (semantic-decorate-flush-decorations)
     ;; Remove hooks
     (remove-hook 'semantic-after-partial-cache-change-hook
-                 'semantic-decorate-tags-after-partial-reparse t)
+                 #'semantic-decorate-tags-after-partial-reparse t)
     (remove-hook 'semantic-after-toplevel-cache-change-hook
-                 'semantic-decorate-tags-after-full-reparse t)))
+                 #'semantic-decorate-tags-after-full-reparse t)))
 
 (semantic-add-minor-mode 'semantic-decoration-mode
                          "")
@@ -350,20 +350,18 @@ Return non-nil if the decoration style is enabled."
 
 (defun semantic-decoration-build-style-menu (style)
   "Build a menu item for controlling a specific decoration STYLE."
-  (vector (car style)
-         `(lambda () (interactive)
-            (semantic-toggle-decoration-style
-             ,(car style)))
-         :style 'toggle
-         :selected `(semantic-decoration-style-enabled-p ,(car style))
-         ))
-
-(defun semantic-build-decoration-mode-menu (&rest ignore)
+  (let ((s (car style)))
+    (vector s
+           (lambda () (interactive) (semantic-toggle-decoration-style s))
+           :style 'toggle
+           :selected `(semantic-decoration-style-enabled-p ',s))))
+
+(defun semantic-build-decoration-mode-menu (&rest _ignore)
   "Create a menu listing all the known decorations for toggling.
 IGNORE any input arguments."
   (or semantic-decoration-menu-cache
       (setq semantic-decoration-menu-cache
-           (mapcar 'semantic-decoration-build-style-menu
+           (mapcar #'semantic-decoration-build-style-menu
                    (reverse semantic-decoration-styles))
            )))
 
diff --git a/lisp/cedet/semantic/dep.el b/lisp/cedet/semantic/dep.el
index db8be5e..efebe21 100644
--- a/lisp/cedet/semantic/dep.el
+++ b/lisp/cedet/semantic/dep.el
@@ -1,4 +1,4 @@
-;;; semantic/dep.el --- Methods for tracking dependencies (include files)
+;;; semantic/dep.el --- Methods for tracking dependencies (include files)  -*- 
lexical-binding: t; -*-
 
 ;; Copyright (C) 2006-2021 Free Software Foundation, Inc.
 
@@ -123,12 +123,12 @@ Changes made by this function are not persistent."
   (if (not mode) (setq mode major-mode))
   (let ((dirtmp (file-name-as-directory dir))
        (value
-        (mode-local-value mode 'semantic-dependency-system-include-path))
-       )
-    (add-to-list 'value dirtmp t)
+        (mode-local-value mode 'semantic-dependency-system-include-path)))
     (eval `(setq-mode-local ,mode
-                           semantic-dependency-system-include-path value))
-    ))
+                           semantic-dependency-system-include-path
+                           ',(if (member dirtmp value) value
+                               (append value (list dirtmp))))
+         t)))
 
 ;;;###autoload
 (defun semantic-remove-system-include (dir &optional mode)
@@ -146,10 +146,10 @@ Changes made by this function are not persistent."
        (value
         (mode-local-value mode 'semantic-dependency-system-include-path))
        )
-    (setq value (delete dirtmp value))
+    (setq value (remove dirtmp value))
     (eval `(setq-mode-local ,mode semantic-dependency-system-include-path
-                           value))
-    ))
+                           ',value)
+         t)))
 
 ;;;###autoload
 (defun semantic-reset-system-include (&optional mode)
@@ -157,10 +157,10 @@ Changes made by this function are not persistent."
 Modifies a mode-local version of
 `semantic-dependency-system-include-path'."
   (interactive)
-  (if (not mode) (setq mode major-mode))
-  (eval `(setq-mode-local ,mode semantic-dependency-system-include-path
-                         nil))
-  )
+  (eval `(setq-mode-local ,(or mode major-mode)
+                         semantic-dependency-system-include-path
+                         nil)
+       t))
 
 ;;;###autoload
 (defun semantic-customize-system-include-path (&optional mode)
diff --git a/lisp/cedet/semantic/doc.el b/lisp/cedet/semantic/doc.el
index d4dd928..413ed83 100644
--- a/lisp/cedet/semantic/doc.el
+++ b/lisp/cedet/semantic/doc.el
@@ -1,4 +1,4 @@
-;;; semantic/doc.el --- Routines for documentation strings
+;;; semantic/doc.el --- Routines for documentation strings  -*- 
lexical-binding: t; -*-
 
 ;; Copyright (C) 1999-2003, 2005, 2008-2021 Free Software Foundation,
 ;; Inc.
@@ -85,7 +85,7 @@ just the lexical token and not the string."
     ))
 (define-obsolete-function-alias
   'semantic-documentation-comment-preceeding-tag
-  'semantic-documentation-comment-preceding-tag
+  #'semantic-documentation-comment-preceding-tag
   "25.1")
 
 (defun semantic-doc-snarf-comment-for-tag (nosnarf)
diff --git a/lisp/cedet/semantic/ede-grammar.el 
b/lisp/cedet/semantic/ede-grammar.el
index bd0795a..6bb8352 100644
--- a/lisp/cedet/semantic/ede-grammar.el
+++ b/lisp/cedet/semantic/ede-grammar.el
@@ -1,4 +1,4 @@
-;;; semantic/ede-grammar.el --- EDE support for Semantic Grammar Files
+;;; semantic/ede-grammar.el --- EDE support for Semantic Grammar Files  -*- 
lexical-binding: t; -*-
 
 ;; Copyright (C) 2003-2004, 2007-2021 Free Software Foundation, Inc.
 
@@ -30,6 +30,7 @@
 (require 'ede/pconf)
 (require 'ede/proj-elisp)
 (require 'semantic/grammar)
+(eval-when-compile (require 'cl-lib))
 
 ;;; Code:
 (defclass semantic-ede-proj-target-grammar (ede-proj-target-elisp)
@@ -118,7 +119,7 @@ For Emacs Lisp, return addsuffix command on source files."
   "Compile Emacs Lisp programs.")
 
 ;;; Target options.
-(cl-defmethod ede-buffer-mine ((this semantic-ede-proj-target-grammar) buffer)
+(cl-defmethod ede-buffer-mine ((_this semantic-ede-proj-target-grammar) buffer)
   "Return t if object THIS lays claim to the file in BUFFER.
 Lays claim to all -by.el, and -wy.el files."
   ;; We need to be a little more careful than this, but at the moment it
@@ -130,7 +131,7 @@ Lays claim to all -by.el, and -wy.el files."
 
 (cl-defmethod project-compile-target ((obj semantic-ede-proj-target-grammar))
   "Compile all sources in a Lisp target OBJ."
-  (let* ((cb (current-buffer))
+  (let* (;; (cb (current-buffer))
         (proj (ede-target-parent obj))
         (default-directory (oref proj directory))
         (comp 0)
@@ -141,11 +142,10 @@ Lays claim to all -by.el, and -wy.el files."
                     (fname (progn (string-match ".*/\\(.+\\.el\\)" package)
                                   (match-string 1 package)))
                     (src (ede-expand-filename obj fname))
-                    (csrc (concat (file-name-sans-extension src) ".elc")))
-                (with-no-warnings
-                  (if (eq (byte-recompile-file src nil 0) t)
-                      (setq comp (1+ comp))
-                    (setq utd (1+ utd)))))))
+                    ;; (csrc (concat (file-name-sans-extension src) ".elc"))
+                    )
+                (cl-incf (if (eq (byte-recompile-file src nil 0) t)
+                             comp utd)))))
          (oref obj source))
     (message "All Semantic Grammar sources are up to date in %s" 
(eieio-object-name obj))
     (cons comp utd)))
@@ -162,10 +162,9 @@ Lays claim to all -by.el, and -wy.el files."
   "Insert variables needed by target THIS."
   (ede-proj-makefile-insert-loadpath-items
    (ede-proj-elisp-packages-to-loadpath
-    (list "eieio" "semantic" "inversion" "ede")))
+    (list "eieio" "semantic" "ede")))
   ;; eieio for object system needed in ede
   ;; semantic because it is
-  ;; Inversion for versioning system.
   ;; ede for project regeneration
   (ede-pmake-insert-variable-shared
       (concat (ede-pmake-varname this) "_SEMANTIC_GRAMMAR_EL")
@@ -174,8 +173,7 @@ Lays claim to all -by.el, and -wy.el files."
                  (with-current-buffer (find-file-noselect src)
                    (concat (semantic-grammar-package) ".el")))
                (oref this source)
-               " ")))
-  )
+                " "))))
 
 (cl-defmethod ede-proj-makefile-insert-rules :after ((this 
semantic-ede-proj-target-grammar))
     "Insert rules needed by THIS target.
diff --git a/lisp/cedet/semantic/edit.el b/lisp/cedet/semantic/edit.el
index f39cc09..0cca156 100644
--- a/lisp/cedet/semantic/edit.el
+++ b/lisp/cedet/semantic/edit.el
@@ -1,4 +1,4 @@
-;;; semantic/edit.el --- Edit Management for Semantic
+;;; semantic/edit.el --- Edit Management for Semantic  -*- lexical-binding: t; 
-*-
 
 ;; Copyright (C) 1999-2021 Free Software Foundation, Inc.
 
@@ -157,7 +157,7 @@ Optional argument BUFFER is the buffer to search for 
changes in."
       (sort ret #'(lambda (a b) (< (overlay-start a)
                                   (overlay-start b)))))))
 
-(defun semantic-edits-change-function-handle-changes  (start end length)
+(defun semantic-edits-change-function-handle-changes  (start end _length)
   "Run whenever a buffer controlled by `semantic-mode' change.
 Tracks when and how the buffer is re-parsed.
 Argument START, END, and LENGTH specify the bounds of the change."
@@ -356,7 +356,7 @@ See `semantic-edits-change-leaf-tag' for details on 
parents."
                   start end)))
         (parent nil)
         (overlapped-tags nil)
-        inner-start inner-end
+        inner-end ;; inner-start
         (list-to-search nil))
     ;; By the time this is already called, we know that it is
     ;; not a leaf change, nor a between tag change.  That leaves
@@ -370,7 +370,7 @@ See `semantic-edits-change-leaf-tag' for details on 
parents."
        (progn
          ;; We encompass one whole change.
          (setq overlapped-tags (list (car tags))
-               inner-start (semantic-tag-start (car tags))
+               ;; inner-start (semantic-tag-start (car tags))
                inner-end (semantic-tag-end (car tags))
                tags (cdr tags))
          ;; Keep looping while tags are inside the change.
@@ -386,13 +386,14 @@ See `semantic-edits-change-leaf-tag' for details on 
parents."
                ;; This is a parent.  Drop the children found
                ;; so far.
                (setq overlapped-tags (list (car tags))
-                     inner-start (semantic-tag-start (car tags))
+                     ;; inner-start (semantic-tag-start (car tags))
                      inner-end (semantic-tag-end (car tags))
                      )
              ;; It is not a parent encompassing tag
              (setq overlapped-tags (cons (car tags)
                                            overlapped-tags)
-                   inner-start (semantic-tag-start (car tags))))
+                   ;; inner-start (semantic-tag-start (car tags))
+                   ))
            (setq tags (cdr tags)))
          (if (not tags)
              ;; There are no tags left, and all tags originally
@@ -533,6 +534,7 @@ This function is for internal use by 
`semantic-edits-incremental-parser'."
                                        ;query this when debugging to find
                                        ;source of bugs.
          )
+    (ignore last-cond) ;; Don't warn about the var not being used.
     (or changes
         ;; If we were called, and there are no changes, then we
         ;; don't know what to do.  Force a full reparse.
@@ -828,8 +830,7 @@ This function is for internal use by 
`semantic-edits-incremental-parser'."
 
 ;; Make it the default changes parser
 ;;;###autoload
-(defalias 'semantic-parse-changes-default
-  'semantic-edits-incremental-parser)
+(defalias 'semantic-parse-changes-default #'semantic-edits-incremental-parser)
 
 ;;; Cache Splicing
 ;;
diff --git a/lisp/cedet/semantic/find.el b/lisp/cedet/semantic/find.el
index 706892b..17fb20f 100644
--- a/lisp/cedet/semantic/find.el
+++ b/lisp/cedet/semantic/find.el
@@ -1,4 +1,4 @@
-;;; semantic/find.el --- Search routines for Semantic
+;;; semantic/find.el --- Search routines for Semantic  -*- lexical-binding: t; 
-*-
 
 ;; Copyright (C) 1999-2005, 2008-2021 Free Software Foundation, Inc.
 
@@ -583,7 +583,7 @@ Optional argument SEARCH-PARTS and SEARCH-INCLUDES are 
passed to
   )
 
 (defun semantic-brute-find-tag-by-function
-  (function streamorbuffer &optional search-parts search-includes)
+  (function streamorbuffer &optional search-parts _search-includes)
   "Find all tags for which FUNCTION's value is non-nil within STREAMORBUFFER.
 FUNCTION must return non-nil if an element of STREAM will be included
 in the new list.
@@ -620,7 +620,7 @@ This parameter hasn't be active for a while and is 
obsolete."
     nl))
 
 (defun semantic-brute-find-first-tag-by-function
-  (function streamorbuffer &optional search-parts search-includes)
+  (function streamorbuffer &optional _search-parts _search-includes)
   "Find the first tag which FUNCTION match within STREAMORBUFFER.
 FUNCTION must return non-nil if an element of STREAM will be included
 in the new list.
diff --git a/lisp/cedet/semantic/format.el b/lisp/cedet/semantic/format.el
index 8927ccd..a68ef80 100644
--- a/lisp/cedet/semantic/format.el
+++ b/lisp/cedet/semantic/format.el
@@ -1,4 +1,4 @@
-;;; semantic/format.el --- Routines for formatting tags
+;;; semantic/format.el --- Routines for formatting tags  -*- lexical-binding: 
t; -*-
 
 ;; Copyright (C) 1999-2005, 2007-2021 Free Software Foundation, Inc.
 
@@ -162,7 +162,7 @@ COLOR specifies if color should be used."
               (car args) nil color 'variable))
            out)
       (setq args (cdr args)))
-    (mapconcat 'identity (nreverse out) semantic-function-argument-separator)
+    (mapconcat #'identity (nreverse out) semantic-function-argument-separator)
     ))
 
 ;;; Data Type
@@ -200,7 +200,7 @@ Argument COLOR specifies to colorize the text."
 ;;; Abstract formatting functions
 ;;
 
-(defun semantic-format-tag-prin1 (tag &optional parent color)
+(defun semantic-format-tag-prin1 (tag &optional _parent _color)
   "Convert TAG to a string that is the print name for TAG.
 PARENT and COLOR are ignored."
   (format "%S" tag))
@@ -237,7 +237,7 @@ The name is the shortest possible representation.
 Optional argument PARENT is the parent type if TAG is a detail.
 Optional argument COLOR means highlight the prototype with font-lock colors.")
 
-(defun semantic-format-tag-name-default (tag &optional parent color)
+(defun semantic-format-tag-name-default (tag &optional _parent color)
   "Return an abbreviated string describing TAG.
 Optional argument PARENT is the parent type if TAG is a detail.
 Optional argument COLOR means highlight the prototype with font-lock colors."
@@ -500,7 +500,7 @@ Optional argument COLOR means highlight the prototype with 
font-lock colors."
                      args
                      (if (eq class 'type) "}" ")"))))
     (when mods
-      (setq mods (concat (mapconcat 'identity mods " ") " ")))
+      (setq mods (concat (mapconcat #'identity mods " ") " ")))
     (concat (or mods "")
            (if type (concat type " "))
            name
diff --git a/lisp/cedet/semantic/fw.el b/lisp/cedet/semantic/fw.el
index 91944c4..2a3b0f5 100644
--- a/lisp/cedet/semantic/fw.el
+++ b/lisp/cedet/semantic/fw.el
@@ -1,6 +1,6 @@
-;;; semantic/fw.el --- Framework for Semantic
+;;; semantic/fw.el --- Framework for Semantic  -*- lexical-binding: t; -*-
 
-;;; Copyright (C) 1999-2021 Free Software Foundation, Inc.
+;; Copyright (C) 1999-2021  Free Software Foundation, Inc.
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
 
@@ -34,29 +34,29 @@
 
 ;;; Compatibility
 ;;
-(define-obsolete-function-alias 'semantic-overlay-live-p 'overlay-buffer 
"27.1")
-(define-obsolete-function-alias 'semantic-make-overlay 'make-overlay "27.1")
-(define-obsolete-function-alias 'semantic-overlay-put 'overlay-put "27.1")
-(define-obsolete-function-alias 'semantic-overlay-get 'overlay-get "27.1")
+(define-obsolete-function-alias 'semantic-overlay-live-p #'overlay-buffer 
"27.1")
+(define-obsolete-function-alias 'semantic-make-overlay #'make-overlay "27.1")
+(define-obsolete-function-alias 'semantic-overlay-put #'overlay-put "27.1")
+(define-obsolete-function-alias 'semantic-overlay-get #'overlay-get "27.1")
 (define-obsolete-function-alias 'semantic-overlay-properties
-  'overlay-properties "27.1")
-(define-obsolete-function-alias 'semantic-overlay-move 'move-overlay "27.1")
-(define-obsolete-function-alias 'semantic-overlay-delete 'delete-overlay 
"27.1")
-(define-obsolete-function-alias 'semantic-overlays-at 'overlays-at "27.1")
-(define-obsolete-function-alias 'semantic-overlays-in 'overlays-in "27.1")
-(define-obsolete-function-alias 'semantic-overlay-buffer 'overlay-buffer 
"27.1")
-(define-obsolete-function-alias 'semantic-overlay-start 'overlay-start "27.1")
-(define-obsolete-function-alias 'semantic-overlay-end 'overlay-end "27.1")
+  #'overlay-properties "27.1")
+(define-obsolete-function-alias 'semantic-overlay-move #'move-overlay "27.1")
+(define-obsolete-function-alias 'semantic-overlay-delete #'delete-overlay 
"27.1")
+(define-obsolete-function-alias 'semantic-overlays-at #'overlays-at "27.1")
+(define-obsolete-function-alias 'semantic-overlays-in #'overlays-in "27.1")
+(define-obsolete-function-alias 'semantic-overlay-buffer #'overlay-buffer 
"27.1")
+(define-obsolete-function-alias 'semantic-overlay-start #'overlay-start "27.1")
+(define-obsolete-function-alias 'semantic-overlay-end #'overlay-end "27.1")
 (define-obsolete-function-alias 'semantic-overlay-next-change
-  'next-overlay-change "27.1")
+  #'next-overlay-change "27.1")
 (define-obsolete-function-alias 'semantic-overlay-previous-change
-  'previous-overlay-change "27.1")
-(define-obsolete-function-alias 'semantic-overlay-lists 'overlay-lists "27.1")
-(define-obsolete-function-alias 'semantic-overlay-p 'overlayp "27.1")
-(define-obsolete-function-alias 'semantic-read-event 'read-event "27.1")
-(define-obsolete-function-alias 'semantic-popup-menu 'popup-menu "27.1")
+  #'previous-overlay-change "27.1")
+(define-obsolete-function-alias 'semantic-overlay-lists #'overlay-lists "27.1")
+(define-obsolete-function-alias 'semantic-overlay-p #'overlayp "27.1")
+(define-obsolete-function-alias 'semantic-read-event #'read-event "27.1")
+(define-obsolete-function-alias 'semantic-popup-menu #'popup-menu "27.1")
 (define-obsolete-function-alias 'semantic-buffer-local-value
-  'buffer-local-value "27.1")
+  #'buffer-local-value "27.1")
 
 (defun semantic-event-window (event)
   "Extract the window from EVENT."
@@ -68,11 +68,11 @@
 
 ;; Since Emacs 22 major mode functions should use `run-mode-hooks' to
 ;; run major mode hooks.
-(define-obsolete-function-alias 'semantic-run-mode-hooks 'run-mode-hooks 
"28.1")
+(define-obsolete-function-alias 'semantic-run-mode-hooks #'run-mode-hooks 
"28.1")
 
 ;; Fancy compat usage now handled in cedet-compat
 (define-obsolete-function-alias 'semantic-subst-char-in-string
-  'subst-char-in-string "28.1")
+  #'subst-char-in-string "28.1")
 
 (defun semantic-delete-overlay-maybe (overlay)
   "Delete OVERLAY if it is a semantic token overlay."
@@ -111,7 +111,7 @@ Possible Lifespans are:
     (setq semantic-cache-data-overlays
           (cons o semantic-cache-data-overlays))
     ;;(message "Adding to cache: %s" o)
-    (add-hook 'post-command-hook 'semantic-cache-data-post-command-hook)
+    (add-hook 'post-command-hook #'semantic-cache-data-post-command-hook)
     ))
 
 (defun semantic-cache-data-post-command-hook ()
@@ -137,7 +137,7 @@ Remove self from `post-command-hook' if it is empty."
   ;; Remove ourselves if we have removed all overlays.
   (unless semantic-cache-data-overlays
     (remove-hook 'post-command-hook
-                 'semantic-cache-data-post-command-hook)))
+                 #'semantic-cache-data-post-command-hook)))
 
 (defun semantic-get-cache-data (name &optional point)
   "Get cached data with NAME from optional POINT."
@@ -189,14 +189,13 @@ will throw a warning when it encounters this symbol."
   (when (and (mode-local--function-overload-p newfn)
              (not (mode-local--overload-obsoleted-by newfn))
              ;; Only throw this warning when byte compiling things.
-             (boundp 'byte-compile-current-file)
-             byte-compile-current-file
-            (not (string-match "cedet" byte-compile-current-file))
+             (macroexp-compiling-p)
+            (not (string-match "cedet" (macroexp-file-name)))
             )
     (make-obsolete-overload oldfnalias newfn when)
     (byte-compile-warn
      "%s: `%s' obsoletes overload `%s'"
-     byte-compile-current-file
+     (macroexp-file-name)
      newfn
      (with-suppressed-warnings ((obsolete 
semantic-overload-symbol-from-function))
        (semantic-overload-symbol-from-function oldfnalias)))))
@@ -211,8 +210,7 @@ will throw a warning when it encounters this symbol."
       (defvaralias oldvaralias newvar)
     (error
      ;; Only throw this warning when byte compiling things.
-     (when (and (boundp 'byte-compile-current-file)
-                byte-compile-current-file)
+     (when (macroexp-compiling-p)
        (byte-compile-warn
         "variable `%s' obsoletes, but isn't alias of `%s'"
         newvar oldvaralias)
@@ -256,7 +254,7 @@ FUNCTION does not have arguments.  When FUNCTION is entered
 `current-buffer' is a selected Semantic enabled buffer."
   (mode-local-map-file-buffers function #'semantic-active-p))
 
-(defalias 'semantic-map-mode-buffers 'mode-local-map-mode-buffers)
+(defalias 'semantic-map-mode-buffers #'mode-local-map-mode-buffers)
 
 (defun semantic-install-function-overrides (overrides &optional transient)
   "Install the function OVERRIDES in the specified environment.
@@ -320,21 +318,17 @@ calling this one."
 
 ;;; Special versions of Find File
 ;;
+(defvar recentf-exclude)
+(defvar semantic-init-hook)
+(defvar ede-auto-add-method)
+(defvar flymake-start-syntax-check-on-find-file)
+(defvar auto-insert)
+
 (defun semantic-find-file-noselect (file &optional nowarn rawfile wildcards)
   "Call `find-file-noselect' with various features turned off.
 Use this when referencing a file that will be soon deleted.
 FILE, NOWARN, RAWFILE, and WILDCARDS are passed into `find-file-noselect'."
-  ;; Hack -
-  ;; Check if we are in set-auto-mode, and if so, warn about this.
-  (when (boundp 'keep-mode-if-same)
-    (let ((filename (or (and (boundp 'filename) filename)
-                       "(unknown)")))
-      (message "WARNING: semantic-find-file-noselect called for \
-%s while in set-auto-mode for %s.  You should call the responsible function \
-into `mode-local-init-hook'." file filename)
-      (sit-for 1)))
-
-  (let* ((recentf-exclude '( (lambda (f) t) ))
+  (let* ((recentf-exclude #'always)
         ;; This is a brave statement.  Don't waste time loading in
         ;; lots of modes.  Especially decoration mode can waste a lot
         ;; of time for a buffer we intend to kill.
diff --git a/lisp/cedet/semantic/grammar-wy.el 
b/lisp/cedet/semantic/grammar-wy.el
index 12c9c04..b301403 100644
--- a/lisp/cedet/semantic/grammar-wy.el
+++ b/lisp/cedet/semantic/grammar-wy.el
@@ -1,6 +1,6 @@
-;;; semantic/grammar-wy.el --- Generated parser support file
+;;; semantic/grammar-wy.el --- Generated parser support file  -*- 
lexical-binding:t -*-
 
-;; Copyright (C) 2002-2004, 2009-2021 Free Software Foundation, Inc.
+;; Copyright (C) 2002-2021 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
@@ -23,8 +23,9 @@
 
 ;;; Code:
 
-(require 'semantic)
-
+(require 'semantic/lex)
+(require 'semantic/wisent)
+
 ;;; Prologue
 ;;
 (defvar semantic-grammar-lex-c-char-re)
@@ -36,16 +37,20 @@
 
 ;;; Declarations
 ;;
+(eval-and-compile (defconst semantic-grammar-wy--expected-conflicts
+                    nil
+                    "The number of expected shift/reduce conflicts in this 
grammar."))
+
 (defconst semantic-grammar-wy--keyword-table
   (semantic-lex-make-keyword-table
    '(("%default-prec" . DEFAULT-PREC)
      ("%no-default-prec" . NO-DEFAULT-PREC)
      ("%keyword" . KEYWORD)
-     ("%expectedconflicts" . EXPECTEDCONFLICTS)
      ("%languagemode" . LANGUAGEMODE)
      ("%left" . LEFT)
      ("%nonassoc" . NONASSOC)
      ("%package" . PACKAGE)
+     ("%expectedconflicts" . EXPECTEDCONFLICTS)
      ("%provide" . PROVIDE)
      ("%prec" . PREC)
      ("%put" . PUT)
@@ -107,315 +112,312 @@
   "Table of lexical tokens.")
 
 (defconst semantic-grammar-wy--parse-table
-  (progn
-    (eval-when-compile
-      (require 'semantic/wisent/comp))
-    (wisent-compile-grammar
-     '((DEFAULT-PREC NO-DEFAULT-PREC KEYWORD LANGUAGEMODE EXPECTEDCONFLICTS 
LEFT NONASSOC PACKAGE PROVIDE PREC PUT QUOTEMODE RIGHT SCOPESTART START TOKEN 
TYPE USE-MACROS STRING SYMBOL PERCENT_PERCENT CHARACTER PREFIXED_LIST SEXP 
PROLOGUE EPILOGUE PAREN_BLOCK BRACE_BLOCK LPAREN RPAREN LBRACE RBRACE COLON 
SEMI OR LT GT)
-       nil
-       (grammar
-       ((prologue))
-       ((epilogue))
-       ((declaration))
-       ((nonterminal))
-       ((PERCENT_PERCENT)))
-       (prologue
-       ((PROLOGUE)
-        (wisent-raw-tag
-         (semantic-tag-new-code "prologue" nil))))
-       (epilogue
-       ((EPILOGUE)
-        (wisent-raw-tag
-         (semantic-tag-new-code "epilogue" nil))))
-       (declaration
-       ((decl)
-        (eval $1)))
-       (decl
-       ((default_prec_decl))
-       ((no_default_prec_decl))
-       ((languagemode_decl))
-       ((expectedconflicts_decl))
-       ((package_decl))
-       ((provide_decl))
-       ((precedence_decl))
-       ((put_decl))
-       ((quotemode_decl))
-       ((scopestart_decl))
-       ((start_decl))
-       ((keyword_decl))
-       ((token_decl))
-       ((type_decl))
-       ((use_macros_decl)))
-       (default_prec_decl
-        ((DEFAULT-PREC)
-         `(wisent-raw-tag
-           (semantic-tag "default-prec" 'assoc :value
-                         '("t")))))
-       (no_default_prec_decl
-       ((NO-DEFAULT-PREC)
-        `(wisent-raw-tag
-          (semantic-tag "default-prec" 'assoc :value
-                        '("nil")))))
-       (languagemode_decl
-       ((LANGUAGEMODE symbols)
-        `(wisent-raw-tag
-          (semantic-tag ',(car $2)
-                        'languagemode :rest ',(cdr $2)))))
-       (expectedconflicts_decl
-       ((EXPECTEDCONFLICTS symbols)
-        `(wisent-raw-tag
-          (semantic-tag ',(car $2)
-                        'expectedconflicts :rest ',(cdr $2)))))
-       (package_decl
-       ((PACKAGE SYMBOL)
-        `(wisent-raw-tag
-          (semantic-tag-new-package ',$2 nil))))
-       (provide_decl
-       ((PROVIDE SYMBOL)
-        `(wisent-raw-tag
-          (semantic-tag ',$2 'provide))))
-       (precedence_decl
-       ((associativity token_type_opt items)
-        `(wisent-raw-tag
-          (semantic-tag ',$1 'assoc :type ',$2 :value ',$3))))
-       (associativity
-       ((LEFT)
-        (progn "left"))
-       ((RIGHT)
-        (progn "right"))
-       ((NONASSOC)
-        (progn "nonassoc")))
-       (put_decl
-       ((PUT put_name put_value)
-        `(wisent-raw-tag
-          (semantic-tag ',$2 'put :value ',(list $3))))
-       ((PUT put_name put_value_list)
-        `(wisent-raw-tag
-          (semantic-tag ',$2 'put :value ',$3)))
-       ((PUT put_name_list put_value)
-        `(wisent-raw-tag
-          (semantic-tag ',(car $2)
-                        'put :rest ',(cdr $2)
-                        :value ',(list $3))))
-       ((PUT put_name_list put_value_list)
-        `(wisent-raw-tag
-          (semantic-tag ',(car $2)
-                        'put :rest ',(cdr $2)
-                        :value ',$3))))
-       (put_name_list
-       ((BRACE_BLOCK)
-        (mapcar 'semantic-tag-name
-                (semantic-parse-region
-                 (car $region1)
-                 (cdr $region1)
-                 'put_names 1))))
-       (put_names
-       ((LBRACE)
-        nil)
-       ((RBRACE)
-        nil)
-       ((put_name)
-        (wisent-raw-tag
-         (semantic-tag $1 'put-name))))
-       (put_name
-       ((SYMBOL))
-       ((token_type)))
-       (put_value_list
-       ((BRACE_BLOCK)
-        (mapcar 'semantic-tag-code-detail
-                (semantic-parse-region
-                 (car $region1)
-                 (cdr $region1)
-                 'put_values 1))))
-       (put_values
-       ((LBRACE)
-        nil)
-       ((RBRACE)
-        nil)
-       ((put_value)
-        (wisent-raw-tag
-         (semantic-tag-new-code "put-value" $1))))
-       (put_value
-       ((SYMBOL any_value)
-        (cons $1 $2)))
-       (scopestart_decl
-       ((SCOPESTART SYMBOL)
-        `(wisent-raw-tag
-          (semantic-tag ',$2 'scopestart))))
-       (quotemode_decl
-       ((QUOTEMODE SYMBOL)
-        `(wisent-raw-tag
-          (semantic-tag ',$2 'quotemode))))
-       (start_decl
-       ((START symbols)
-        `(wisent-raw-tag
-          (semantic-tag ',(car $2)
-                        'start :rest ',(cdr $2)))))
-       (keyword_decl
-       ((KEYWORD SYMBOL string_value)
-        `(wisent-raw-tag
-          (semantic-tag ',$2 'keyword :value ',$3))))
-       (token_decl
-       ((TOKEN token_type_opt SYMBOL string_value)
-        `(wisent-raw-tag
-          (semantic-tag ',$3 ',(if $2 'token 'keyword)
-                        :type ',$2 :value ',$4)))
-       ((TOKEN token_type_opt symbols)
-        `(wisent-raw-tag
-          (semantic-tag ',(car $3)
-                        'token :type ',$2 :rest ',(cdr $3)))))
-       (token_type_opt
-       (nil)
-       ((token_type)))
-       (token_type
-       ((LT SYMBOL GT)
-        (progn $2)))
-       (type_decl
-       ((TYPE token_type plist_opt)
-        `(wisent-raw-tag
-          (semantic-tag ',$2 'type :value ',$3))))
-       (plist_opt
-       (nil)
-       ((plist)))
-       (plist
-       ((plist put_value)
-        (append
-         (list $2)
-         $1))
-       ((put_value)
-        (list $1)))
-       (use_name_list
-       ((BRACE_BLOCK)
-        (mapcar 'semantic-tag-name
-                (semantic-parse-region
-                 (car $region1)
-                 (cdr $region1)
-                 'use_names 1))))
-       (use_names
-       ((LBRACE)
-        nil)
-       ((RBRACE)
-        nil)
-       ((SYMBOL)
-        (wisent-raw-tag
-         (semantic-tag $1 'use-name))))
-       (use_macros_decl
-       ((USE-MACROS SYMBOL use_name_list)
-        `(wisent-raw-tag
-          (semantic-tag "macro" 'macro :type ',$2 :value ',$3))))
-       (string_value
-       ((STRING)
-        (read $1)))
-       (any_value
-       ((SYMBOL))
-       ((STRING))
-       ((PAREN_BLOCK))
-       ((PREFIXED_LIST))
-       ((SEXP)))
-       (symbols
-       ((lifo_symbols)
-        (nreverse $1)))
-       (lifo_symbols
-       ((lifo_symbols SYMBOL)
-        (cons $2 $1))
-       ((SYMBOL)
-        (list $1)))
-       (nonterminal
-       ((SYMBOL
-         (setq semantic-grammar-wy--nterm $1 semantic-grammar-wy--rindx 0)
-         COLON rules SEMI)
-        (wisent-raw-tag
-         (semantic-tag $1 'nonterminal :children $4))))
-       (rules
-       ((lifo_rules)
-        (apply 'nconc
-               (nreverse $1))))
-       (lifo_rules
-       ((lifo_rules OR rule)
-        (cons $3 $1))
-       ((rule)
-        (list $1)))
-       (rule
-       ((rhs)
-        (let*
-            ((nterm semantic-grammar-wy--nterm)
-             (rindx semantic-grammar-wy--rindx)
-             (rhs $1)
-             comps prec action elt)
-          (setq semantic-grammar-wy--rindx
-                (1+ semantic-grammar-wy--rindx))
-          (while rhs
-            (setq elt
-                  (car rhs)
-                  rhs
-                  (cdr rhs))
-            (cond
-             ((vectorp elt)
-              (if prec
-                  (error "Duplicate %%prec in `%s:%d' rule" nterm rindx))
-              (setq prec
-                    (aref elt 0)))
-             ((consp elt)
-              (if
-                  (or action comps)
-                  (setq comps
-                        (cons elt comps)
-                        semantic-grammar-wy--rindx
-                        (1+ semantic-grammar-wy--rindx))
-                (setq action
-                      (car elt))))
-             (t
-              (setq comps
-                    (cons elt comps)))))
-          (wisent-cook-tag
-           (wisent-raw-tag
-            (semantic-tag
-             (format "%s:%d" nterm rindx)
-             'rule :type
-             (if comps "group" "empty")
-             :value comps :prec prec :expr action))))))
-       (rhs
-       (nil)
-       ((rhs item)
-        (cons $2 $1))
-       ((rhs action)
-        (cons
-         (list $2)
-         $1))
-       ((rhs PREC item)
-        (cons
-         (vector $3)
-         $1)))
-       (action
-       ((PAREN_BLOCK))
-       ((PREFIXED_LIST))
-       ((BRACE_BLOCK)
-        (format "(progn\n%s)"
-                (let
-                    ((s $1))
-                  (if
-                      (string-match "^{[\r\n\t ]*" s)
-                      (setq s
-                            (substring s
-                                       (match-end 0))))
-                  (if
-                      (string-match "[\r\n\t ]*}$" s)
-                      (setq s
-                            (substring s 0
-                                       (match-beginning 0))))
-                  s))))
-       (items
-       ((lifo_items)
-        (nreverse $1)))
-       (lifo_items
-       ((lifo_items item)
-        (cons $2 $1))
-       ((item)
-        (list $1)))
-       (item
-       ((SYMBOL))
-       ((CHARACTER))))
-     '(grammar prologue epilogue declaration nonterminal rule put_names 
put_values use_names)))
+  (wisent-compiled-grammar
+   ((DEFAULT-PREC NO-DEFAULT-PREC KEYWORD LANGUAGEMODE LEFT NONASSOC PACKAGE 
EXPECTEDCONFLICTS PROVIDE PREC PUT QUOTEMODE RIGHT SCOPESTART START TOKEN TYPE 
USE-MACROS STRING SYMBOL PERCENT_PERCENT CHARACTER PREFIXED_LIST SEXP PROLOGUE 
EPILOGUE PAREN_BLOCK BRACE_BLOCK LPAREN RPAREN LBRACE RBRACE COLON SEMI OR LT 
GT)
+    nil
+    (grammar
+     ((prologue))
+     ((epilogue))
+     ((declaration))
+     ((nonterminal))
+     ((PERCENT_PERCENT)))
+    (prologue
+     ((PROLOGUE)
+      (wisent-raw-tag
+       (semantic-tag-new-code "prologue" nil))))
+    (epilogue
+     ((EPILOGUE)
+      (wisent-raw-tag
+       (semantic-tag-new-code "epilogue" nil))))
+    (declaration
+     ((decl)
+      (eval $1 t)))
+    (decl
+     ((default_prec_decl))
+     ((no_default_prec_decl))
+     ((languagemode_decl))
+     ((package_decl))
+     ((expectedconflicts_decl))
+     ((provide_decl))
+     ((precedence_decl))
+     ((put_decl))
+     ((quotemode_decl))
+     ((scopestart_decl))
+     ((start_decl))
+     ((keyword_decl))
+     ((token_decl))
+     ((type_decl))
+     ((use_macros_decl)))
+    (default_prec_decl
+      ((DEFAULT-PREC)
+       `(wisent-raw-tag
+         (semantic-tag "default-prec" 'assoc :value
+                      '("t")))))
+    (no_default_prec_decl
+     ((NO-DEFAULT-PREC)
+      `(wisent-raw-tag
+        (semantic-tag "default-prec" 'assoc :value
+                     '("nil")))))
+    (languagemode_decl
+     ((LANGUAGEMODE symbols)
+      `(wisent-raw-tag
+        (semantic-tag ',(car $2)
+                     'languagemode :rest ',(cdr $2)))))
+    (package_decl
+     ((PACKAGE SYMBOL)
+      `(wisent-raw-tag
+        (semantic-tag-new-package ',$2 nil))))
+    (expectedconflicts_decl
+     ((EXPECTEDCONFLICTS symbols)
+      `(wisent-raw-tag
+        (semantic-tag ',(car $2)
+                     'expectedconflicts :rest ',(cdr $2)))))
+    (provide_decl
+     ((PROVIDE SYMBOL)
+      `(wisent-raw-tag
+        (semantic-tag ',$2 'provide))))
+    (precedence_decl
+     ((associativity token_type_opt items)
+      `(wisent-raw-tag
+        (semantic-tag ',$1 'assoc :type ',$2 :value ',$3))))
+    (associativity
+     ((LEFT)
+      (progn "left"))
+     ((RIGHT)
+      (progn "right"))
+     ((NONASSOC)
+      (progn "nonassoc")))
+    (put_decl
+     ((PUT put_name put_value)
+      `(wisent-raw-tag
+        (semantic-tag ',$2 'put :value ',(list $3))))
+     ((PUT put_name put_value_list)
+      `(wisent-raw-tag
+        (semantic-tag ',$2 'put :value ',$3)))
+     ((PUT put_name_list put_value)
+      `(wisent-raw-tag
+        (semantic-tag ',(car $2)
+                     'put :rest ',(cdr $2)
+                     :value ',(list $3))))
+     ((PUT put_name_list put_value_list)
+      `(wisent-raw-tag
+        (semantic-tag ',(car $2)
+                     'put :rest ',(cdr $2)
+                     :value ',$3))))
+    (put_name_list
+     ((BRACE_BLOCK)
+      (mapcar #'semantic-tag-name
+             (semantic-parse-region
+              (car $region1)
+              (cdr $region1)
+              'put_names 1))))
+    (put_names
+     ((LBRACE)
+      nil)
+     ((RBRACE)
+      nil)
+     ((put_name)
+      (wisent-raw-tag
+       (semantic-tag $1 'put-name))))
+    (put_name
+     ((SYMBOL))
+     ((token_type)))
+    (put_value_list
+     ((BRACE_BLOCK)
+      (mapcar #'semantic-tag-code-detail
+             (semantic-parse-region
+              (car $region1)
+              (cdr $region1)
+              'put_values 1))))
+    (put_values
+     ((LBRACE)
+      nil)
+     ((RBRACE)
+      nil)
+     ((put_value)
+      (wisent-raw-tag
+       (semantic-tag-new-code "put-value" $1))))
+    (put_value
+     ((SYMBOL any_value)
+      (cons $1 $2)))
+    (scopestart_decl
+     ((SCOPESTART SYMBOL)
+      `(wisent-raw-tag
+        (semantic-tag ',$2 'scopestart))))
+    (quotemode_decl
+     ((QUOTEMODE SYMBOL)
+      `(wisent-raw-tag
+        (semantic-tag ',$2 'quotemode))))
+    (start_decl
+     ((START symbols)
+      `(wisent-raw-tag
+        (semantic-tag ',(car $2)
+                     'start :rest ',(cdr $2)))))
+    (keyword_decl
+     ((KEYWORD SYMBOL string_value)
+      `(wisent-raw-tag
+        (semantic-tag ',$2 'keyword :value ',$3))))
+    (token_decl
+     ((TOKEN token_type_opt SYMBOL string_value)
+      `(wisent-raw-tag
+        (semantic-tag ',$3 ',(if $2 'token 'keyword)
+                     :type ',$2 :value ',$4)))
+     ((TOKEN token_type_opt symbols)
+      `(wisent-raw-tag
+        (semantic-tag ',(car $3)
+                     'token :type ',$2 :rest ',(cdr $3)))))
+    (token_type_opt
+     (nil)
+     ((token_type)))
+    (token_type
+     ((LT SYMBOL GT)
+      (progn $2)))
+    (type_decl
+     ((TYPE token_type plist_opt)
+      `(wisent-raw-tag
+        (semantic-tag ',$2 'type :value ',$3))))
+    (plist_opt
+     (nil)
+     ((plist)))
+    (plist
+     ((plist put_value)
+      (append
+       (list $2)
+       $1))
+     ((put_value)
+      (list $1)))
+    (use_name_list
+     ((BRACE_BLOCK)
+      (mapcar #'semantic-tag-name
+             (semantic-parse-region
+              (car $region1)
+              (cdr $region1)
+              'use_names 1))))
+    (use_names
+     ((LBRACE)
+      nil)
+     ((RBRACE)
+      nil)
+     ((SYMBOL)
+      (wisent-raw-tag
+       (semantic-tag $1 'use-name))))
+    (use_macros_decl
+     ((USE-MACROS SYMBOL use_name_list)
+      `(wisent-raw-tag
+        (semantic-tag "macro" 'macro :type ',$2 :value ',$3))))
+    (string_value
+     ((STRING)
+      (read $1)))
+    (any_value
+     ((SYMBOL))
+     ((STRING))
+     ((PAREN_BLOCK))
+     ((PREFIXED_LIST))
+     ((SEXP)))
+    (symbols
+     ((lifo_symbols)
+      (nreverse $1)))
+    (lifo_symbols
+     ((lifo_symbols SYMBOL)
+      (cons $2 $1))
+     ((SYMBOL)
+      (list $1)))
+    (nonterminal
+     ((SYMBOL
+       (setq semantic-grammar-wy--nterm $1 semantic-grammar-wy--rindx 0)
+       COLON rules SEMI)
+      (wisent-raw-tag
+       (semantic-tag $1 'nonterminal :children $4))))
+    (rules
+     ((lifo_rules)
+      (apply #'nconc
+            (nreverse $1))))
+    (lifo_rules
+     ((lifo_rules OR rule)
+      (cons $3 $1))
+     ((rule)
+      (list $1)))
+    (rule
+     ((rhs)
+      (let*
+         ((nterm semantic-grammar-wy--nterm)
+          (rindx semantic-grammar-wy--rindx)
+          (rhs $1)
+          comps prec action elt)
+        (setq semantic-grammar-wy--rindx
+             (1+ semantic-grammar-wy--rindx))
+        (while rhs
+         (setq elt
+               (car rhs)
+               rhs
+               (cdr rhs))
+         (cond
+          ((vectorp elt)
+           (if prec
+               (error "Duplicate %%prec in `%s:%d' rule" nterm rindx))
+           (setq prec
+                 (aref elt 0)))
+          ((consp elt)
+           (if
+               (or action comps)
+               (setq comps
+                     (cons elt comps)
+                     semantic-grammar-wy--rindx
+                     (1+ semantic-grammar-wy--rindx))
+             (setq action
+                   (car elt))))
+          (t
+           (setq comps
+                 (cons elt comps)))))
+        (wisent-cook-tag
+         (wisent-raw-tag
+         (semantic-tag
+          (format "%s:%d" nterm rindx)
+          'rule :type
+          (if comps "group" "empty")
+          :value comps :prec prec :expr action))))))
+    (rhs
+     (nil)
+     ((rhs item)
+      (cons $2 $1))
+     ((rhs action)
+      (cons
+       (list $2)
+       $1))
+     ((rhs PREC item)
+      (cons
+       (vector $3)
+       $1)))
+    (action
+     ((PAREN_BLOCK))
+     ((PREFIXED_LIST))
+     ((BRACE_BLOCK)
+      (format "(progn\n%s)"
+             (let
+                 ((s $1))
+               (if
+                   (string-match "^{[
\n       ]*" s)
+                   (setq s
+                         (substring s
+                                    (match-end 0))))
+               (if
+                   (string-match "[
\n       ]*}$" s)
+                   (setq s
+                         (substring s 0
+                                    (match-beginning 0))))
+               s))))
+    (items
+     ((lifo_items)
+      (nreverse $1)))
+    (lifo_items
+     ((lifo_items item)
+      (cons $2 $1))
+     ((item)
+      (list $1)))
+    (item
+     ((SYMBOL))
+     ((CHARACTER))))
+   (grammar prologue epilogue declaration nonterminal rule put_names 
put_values use_names))
   "Parser table.")
 
 (defun semantic-grammar-wy--install-parser ()
@@ -423,25 +425,26 @@
   (semantic-install-function-overrides
    '((semantic-parse-stream . wisent-parse-stream)))
   (setq semantic-parser-name "LALR"
-       semantic--parse-table semantic-grammar-wy--parse-table
-       semantic-debug-parser-source "grammar.wy"
-       semantic-flex-keywords-obarray semantic-grammar-wy--keyword-table
-       semantic-lex-types-obarray semantic-grammar-wy--token-table)
+        semantic--parse-table semantic-grammar-wy--parse-table
+        semantic-debug-parser-source "grammar.wy"
+        semantic-flex-keywords-obarray semantic-grammar-wy--keyword-table
+        semantic-lex-types-obarray semantic-grammar-wy--token-table)
   ;; Collect unmatched syntax lexical tokens
   (add-hook 'wisent-discarding-token-functions
-           'wisent-collect-unmatched-syntax nil t))
+            #'wisent-collect-unmatched-syntax nil t))
 
 
 ;;; Analyzers
 ;;
-(define-lex-block-type-analyzer semantic-grammar-wy--<block>-block-analyzer
-  "block analyzer for <block> tokens."
-  "\\s(\\|\\s)"
-  '((("(" LPAREN PAREN_BLOCK)
-     ("{" LBRACE BRACE_BLOCK))
-    (")" RPAREN)
-    ("}" RBRACE))
-  )
+(define-lex-regex-type-analyzer semantic-grammar-wy--<symbol>-regexp-analyzer
+  "regexp analyzer for <symbol> tokens."
+  ":?\\(\\sw\\|\\s_\\)+"
+  '((PERCENT_PERCENT . "\\`%%\\'"))
+  'SYMBOL)
+
+(define-lex-keyword-type-analyzer 
semantic-grammar-wy--<keyword>-keyword-analyzer
+  "keyword analyzer for <keyword> tokens."
+  "\\(\\sw\\|\\s_\\)+")
 
 (define-lex-regex-type-analyzer semantic-grammar-wy--<char>-regexp-analyzer
   "regexp analyzer for <char> tokens."
@@ -449,21 +452,19 @@
   nil
   'CHARACTER)
 
-(define-lex-regex-type-analyzer semantic-grammar-wy--<symbol>-regexp-analyzer
-  "regexp analyzer for <symbol> tokens."
-  ":?\\(\\sw\\|\\s_\\)+"
-  '((PERCENT_PERCENT . "\\`%%\\'"))
-  'SYMBOL)
-
 (define-lex-sexp-type-analyzer semantic-grammar-wy--<qlist>-sexp-analyzer
   "sexp analyzer for <qlist> tokens."
   "\\s'\\s-*("
   'PREFIXED_LIST)
 
-(define-lex-sexp-type-analyzer semantic-grammar-wy--<string>-sexp-analyzer
-  "sexp analyzer for <string> tokens."
-  "\\s\""
-  'STRING)
+(define-lex-block-type-analyzer semantic-grammar-wy--<block>-block-analyzer
+  "block analyzer for <block> tokens."
+  "\\s(\\|\\s)"
+  '((("(" LPAREN PAREN_BLOCK)
+     ("{" LBRACE BRACE_BLOCK))
+    (")" RPAREN)
+    ("}" RBRACE))
+  )
 
 (define-lex-string-type-analyzer 
semantic-grammar-wy--<punctuation>-string-analyzer
   "string analyzer for <punctuation> tokens."
@@ -475,9 +476,10 @@
     (COLON . ":"))
   'punctuation)
 
-(define-lex-keyword-type-analyzer 
semantic-grammar-wy--<keyword>-keyword-analyzer
-  "keyword analyzer for <keyword> tokens."
-  "\\(\\sw\\|\\s_\\)+")
+(define-lex-sexp-type-analyzer semantic-grammar-wy--<string>-sexp-analyzer
+  "sexp analyzer for <string> tokens."
+  "\\s\""
+  'STRING)
 
 (define-lex-sexp-type-analyzer semantic-grammar-wy--<sexp>-sexp-analyzer
   "sexp analyzer for <sexp> tokens."
@@ -493,4 +495,9 @@
 
 (provide 'semantic/grammar-wy)
 
+;; Local Variables:
+;; version-control: never
+;; no-update-autoloads: t
+;; End:
+
 ;;; semantic/grammar-wy.el ends here
diff --git a/lisp/cedet/semantic/grammar.el b/lisp/cedet/semantic/grammar.el
index 4551811..8d8faac 100644
--- a/lisp/cedet/semantic/grammar.el
+++ b/lisp/cedet/semantic/grammar.el
@@ -1,4 +1,4 @@
-;;; semantic/grammar.el --- Major mode framework for Semantic grammars
+;;; semantic/grammar.el --- Major mode framework for Semantic grammars  -*- 
lexical-binding: t; -*-
 
 ;; Copyright (C) 2002-2005, 2007-2021 Free Software Foundation, Inc.
 
@@ -191,11 +191,11 @@ Warn if other tags of class CLASS exist."
 That is tag names plus names defined in tag attribute `:rest'."
   (let* ((tags (semantic-find-tags-by-class
                 class (current-buffer))))
-    (apply 'append
+    (apply #'append
            (mapcar
             #'(lambda (tag)
                 (mapcar
-                 'intern
+                 #'intern
                  (cons (semantic-tag-name tag)
                        (semantic-tag-get-attribute tag :rest))))
             tags))))
@@ -312,7 +312,7 @@ the keyword and TOKEN is the terminal symbol identifying 
the keyword."
       (setq put   (car puts)
             puts  (cdr puts)
             keys  (mapcar
-                   'intern
+                   #'intern
                    (cons (semantic-tag-name put)
                          (semantic-tag-get-attribute put :rest))))
       (while keys
@@ -565,6 +565,10 @@ Typically a DEFINE expression should look like this:
       (goto-char start)
       (indent-sexp))))
 
+(defvar semantic-grammar-require-form
+  '(eval-when-compile (require 'semantic/bovine))
+  "The form to use to load the parser engine.")
+
 (defconst semantic-grammar-header-template
   '("\
 ;;; " file " --- Generated parser support file
@@ -602,7 +606,7 @@ Typically a DEFINE expression should look like this:
 ;;; Code:
 
 (require 'semantic/lex)
-(eval-when-compile (require 'semantic/bovine))
+" require-form "
 ")
   "Generated header template.
 The symbols in the template are local variables in
@@ -651,6 +655,7 @@ The symbols in the list are local variables in
                semantic--grammar-output-buffer))
      (gram . ,(semantic-grammar-buffer-file))
      (date . ,(format-time-string "%Y-%m-%d %T%z"))
+     (require-form . ,(format "%S" semantic-grammar-require-form))
      (vcid . ,(concat "$" "Id" "$")) ;; Avoid expansion
      ;; Try to get the copyright from the input grammar, or
      ;; generate a new one if not found.
@@ -818,7 +823,7 @@ Block definitions are read from the current table of 
lexical types."
     (let ((semantic-lex-types-obarray
            (semantic-lex-make-type-table tokens props))
           semantic-grammar--lex-block-specs)
-      (mapatoms 'semantic-grammar-insert-defanalyzer
+      (mapatoms #'semantic-grammar-insert-defanalyzer
                 semantic-lex-types-obarray))))
 
 ;;; Generation of the grammar support file.
@@ -846,7 +851,8 @@ Lisp code."
          (semantic--grammar-package (semantic-grammar-package))
         (semantic--grammar-provide (semantic-grammar-first-tag-name 'provide))
          (output   (concat (or semantic--grammar-provide
-                              semantic--grammar-package) ".el"))
+                              semantic--grammar-package)
+                          ".el"))
          (semantic--grammar-input-buffer  (current-buffer))
          (semantic--grammar-output-buffer
          (find-file-noselect
@@ -1197,20 +1203,20 @@ END is the limit of the search."
 (defvar semantic-grammar-mode-map
   (let ((km (make-sparse-keymap)))
 
-    (define-key km "|" 'semantic-grammar-electric-punctuation)
-    (define-key km ";" 'semantic-grammar-electric-punctuation)
-    (define-key km "%" 'semantic-grammar-electric-punctuation)
-    (define-key km "(" 'semantic-grammar-electric-punctuation)
-    (define-key km ")" 'semantic-grammar-electric-punctuation)
-    (define-key km ":" 'semantic-grammar-electric-punctuation)
-
-    (define-key km "\t"       'semantic-grammar-indent)
-    (define-key km "\M-\t"    'semantic-grammar-complete)
-    (define-key km "\C-c\C-c" 'semantic-grammar-create-package)
-    (define-key km "\C-cm"    'semantic-grammar-find-macro-expander)
-    (define-key km "\C-cik"    'semantic-grammar-insert-keyword)
-;;  (define-key km "\C-cc"    'semantic-grammar-generate-and-load)
-;;  (define-key km "\C-cr"    'semantic-grammar-generate-one-rule)
+    (define-key km "|" #'semantic-grammar-electric-punctuation)
+    (define-key km ";" #'semantic-grammar-electric-punctuation)
+    (define-key km "%" #'semantic-grammar-electric-punctuation)
+    (define-key km "(" #'semantic-grammar-electric-punctuation)
+    (define-key km ")" #'semantic-grammar-electric-punctuation)
+    (define-key km ":" #'semantic-grammar-electric-punctuation)
+
+    (define-key km "\t"       #'semantic-grammar-indent)
+    (define-key km "\M-\t"    #'semantic-grammar-complete)
+    (define-key km "\C-c\C-c" #'semantic-grammar-create-package)
+    (define-key km "\C-cm"    #'semantic-grammar-find-macro-expander)
+    (define-key km "\C-cik"   #'semantic-grammar-insert-keyword)
+;;  (define-key km "\C-cc"    #'semantic-grammar-generate-and-load)
+;;  (define-key km "\C-cr"    #'semantic-grammar-generate-one-rule)
 
     km)
   "Keymap used in `semantic-grammar-mode'.")
@@ -1322,7 +1328,7 @@ the change bounds to encompass the whole nonterminal tag."
   ;; Setup Semantic to parse grammar
   (semantic-grammar-wy--install-parser)
   (setq semantic-lex-comment-regex ";;"
-        semantic-lex-analyzer 'semantic-grammar-lexer
+        semantic-lex-analyzer #'semantic-grammar-lexer
         semantic-type-relation-separator-character '(":")
         semantic-symbol->name-assoc-list
         '(
@@ -1343,10 +1349,10 @@ the change bounds to encompass the whole nonterminal 
tag."
   ;; Before each change, clear the cached regexp used to highlight
   ;; macros local in this grammar.
   (add-hook 'before-change-functions
-            'semantic--grammar-clear-macros-regexp-2 nil t)
+            #'semantic--grammar-clear-macros-regexp-2 nil t)
   ;; Handle safe re-parse of grammar rules.
   (add-hook 'semantic-edits-new-change-functions
-            'semantic-grammar-edits-new-change-hook-fcn
+            #'semantic-grammar-edits-new-change-hook-fcn
             nil t))
 
 ;;;;
@@ -1734,7 +1740,7 @@ If it is a macro name, return a description of the 
associated expander
 function parameter list.
 If it is a function name, return a description of this function
 parameter list.
-It it is a variable name, return a brief (one-line) documentation
+If it is a variable name, return a brief (one-line) documentation
 string for the variable.
 If a default description of the current context can be obtained,
 return it.
@@ -1876,7 +1882,7 @@ Optional argument COLOR determines if color is added to 
the text."
             (names (semantic-tag-get-attribute tag :rest))
             (type  (semantic-tag-type tag)))
         (if names
-            (setq name (mapconcat 'identity (cons name names) " ")))
+            (setq name (mapconcat #'identity (cons name names) " ")))
         (setq desc (concat
                     (if type
                         (format " <%s>" type)
@@ -1893,7 +1899,7 @@ Optional argument COLOR determines if color is added to 
the text."
                         (format " <%s>" type)
                       "")
                     (if val
-                        (concat " " (mapconcat 'identity val " "))
+                        (concat " " (mapconcat #'identity val " "))
                       "")))))
      (t
       (setq desc (semantic-format-tag-abbreviate tag parent color))))
@@ -1944,7 +1950,7 @@ Optional argument COLOR determines if color is added to 
the text."
       context-return)))
 
 (define-mode-local-override semantic-analyze-possible-completions
-  semantic-grammar-mode (context &rest flags)
+  semantic-grammar-mode (context &rest _flags)
   "Return a list of possible completions based on CONTEXT."
   (require 'semantic/analyze/complete)
   (if (semantic-grammar-in-lisp-p)
diff --git a/lisp/cedet/semantic/html.el b/lisp/cedet/semantic/html.el
index 658d218..ad5d2c7 100644
--- a/lisp/cedet/semantic/html.el
+++ b/lisp/cedet/semantic/html.el
@@ -1,4 +1,4 @@
-;;; semantic/html.el --- Semantic details for html files
+;;; semantic/html.el --- Semantic details for html files  -*- lexical-binding: 
t; -*-
 
 ;; Copyright (C) 2004-2005, 2007-2021 Free Software Foundation, Inc.
 
@@ -59,14 +59,14 @@
   "Alist of sectioning commands and their relative level.")
 
 (define-mode-local-override semantic-parse-region
-  html-mode (&rest ignore)
+  html-mode (&rest _ignore)
   "Parse the current html buffer for semantic tags.
 IGNORE any arguments.  Always parse the whole buffer.
 Each tag returned is of the form:
  (\"NAME\" section (:members CHILDREN))
 or
  (\"NAME\" anchor)"
-  (mapcar 'semantic-html-expand-tag
+  (mapcar #'semantic-html-expand-tag
          (semantic-html-parse-headings)))
 
 (define-mode-local-override semantic-parse-changes
@@ -79,7 +79,7 @@ or
   (let ((chil (semantic-html-components tag)))
     (if chil
         (semantic-tag-put-attribute
-         tag :members (mapcar 'semantic-html-expand-tag chil)))
+         tag :members (mapcar #'semantic-html-expand-tag chil)))
     (car (semantic--tag-expand tag))))
 
 (defun semantic-html-components (tag)
@@ -233,7 +233,7 @@ tag with greater section value than LEVEL is found."
   ;; This will use our parser.
   (setq semantic-parser-name "HTML"
         semantic--parse-table t
-        imenu-create-index-function 'semantic-create-imenu-index
+        imenu-create-index-function #'semantic-create-imenu-index
        semantic-command-separation-character ">"
        semantic-type-relation-separator-character '(":")
        semantic-symbol->name-assoc-list '((section . "Section")
diff --git a/lisp/cedet/semantic/ia-sb.el b/lisp/cedet/semantic/ia-sb.el
index b132d41..12a2f1d 100644
--- a/lisp/cedet/semantic/ia-sb.el
+++ b/lisp/cedet/semantic/ia-sb.el
@@ -1,7 +1,6 @@
-;;; semantic/ia-sb.el --- Speedbar analysis display interactor
+;;; semantic/ia-sb.el --- Speedbar analysis display interactor  -*- 
lexical-binding: t; -*-
 
-;;; Copyright (C) 2002-2004, 2006, 2008-2021 Free Software Foundation,
-;;; Inc.
+;; Copyright (C) 2002-2021  Free Software Foundation, Inc.
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
 ;; Keywords: syntax
@@ -30,18 +29,14 @@
 (require 'speedbar)
 
 ;;; Code:
-(defvar semantic-ia-sb-key-map nil
+(defvar semantic-ia-sb-key-map
+  (let ((map (speedbar-make-specialized-keymap)))
+    ;; Basic features.
+    (define-key map "\C-m" #'speedbar-edit-line)
+    (define-key map "I"    #'semantic-ia-sb-show-tag-info)
+    map)
   "Keymap used when in semantic analysis display mode.")
 
-(if semantic-ia-sb-key-map
-    nil
-  (setq semantic-ia-sb-key-map (speedbar-make-specialized-keymap))
-
-  ;; Basic features.
-  (define-key semantic-ia-sb-key-map "\C-m" 'speedbar-edit-line)
-  (define-key semantic-ia-sb-key-map "I" 'semantic-ia-sb-show-tag-info)
-  )
-
 (defvar semantic-ia-sb-easymenu-definition
   '( "---"
 ;     [ "Expand" speedbar-expand-line nil ]
@@ -75,7 +70,7 @@ list of possible completions."
   (speedbar-change-initial-expansion-list "Analyze")
   )
 
-(defun semantic-ia-speedbar (directory zero)
+(defun semantic-ia-speedbar (_directory _zero)
   "Create buttons in speedbar which define the current analysis at POINT.
 DIRECTORY is the current directory, which is ignored, and ZERO is 0."
   (let ((analysis nil)
@@ -195,7 +190,7 @@ DIRECTORY is the current directory, which is ignored, and 
ZERO is 0."
       ;; An index for the argument the prefix is in:
       (let ((arg (oref context argument))
            (args (semantic-tag-function-arguments (car func)))
-           (idx 0)
+           ;; (idx 0)
            )
        (speedbar-insert-separator
         (format "Argument #%d" (oref context index)))
@@ -275,7 +270,7 @@ See `semantic-ia-sb-tag-info' for more."
       (setq tok (get-text-property (point) 'speedbar-token)))
     (semantic-ia-sb-tag-info nil tok 0)))
 
-(defun semantic-ia-sb-tag-info (text tag indent)
+(defun semantic-ia-sb-tag-info (_text tag _indent)
   "Display as much information as we can about tag.
 Show the information in a shrunk split-buffer and expand
 out as many details as possible.
@@ -322,16 +317,15 @@ TEXT, TAG, and INDENT are speedbar function arguments."
           (get-buffer-window "*Tag Information*")))
       (select-frame speedbar-frame))))
 
-(defun semantic-ia-sb-line-path (&optional depth)
+(defun semantic-ia-sb-line-path (&optional _depth)
   "Return the file name associated with DEPTH."
   (save-match-data
     (let* ((tok (speedbar-line-token))
-          (buff (if (semantic-tag-buffer tok)
-                    (semantic-tag-buffer tok)
-                  (current-buffer))))
+          (buff (or (semantic-tag-buffer tok)
+                    (current-buffer))))
       (buffer-file-name buff))))
 
-(defun semantic-ia-sb-complete (text tag indent)
+(defun semantic-ia-sb-complete (_text tag _indent)
   "At point in the attached buffer, complete the symbol clicked on.
 TEXT TAG and INDENT are the details."
   ;; Find the specified bounds from the current analysis.
diff --git a/lisp/cedet/semantic/ia.el b/lisp/cedet/semantic/ia.el
index 6d3ec75..7186a78 100644
--- a/lisp/cedet/semantic/ia.el
+++ b/lisp/cedet/semantic/ia.el
@@ -1,6 +1,6 @@
-;;; semantic/ia.el --- Interactive Analysis functions
+;;; semantic/ia.el --- Interactive Analysis functions  -*- lexical-binding: t; 
-*-
 
-;;; Copyright (C) 2000-2021 Free Software Foundation, Inc.
+;; Copyright (C) 2000-2021  Free Software Foundation, Inc.
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
 ;; Keywords: syntax
@@ -79,13 +79,8 @@
           (insert "("))
          (t nil))))
 
-(defalias 'semantic-ia-get-completions 'semantic-ia-get-completions-deprecated)
-(make-obsolete 'semantic-ia-get-completions
-               #'semantic-analyze-possible-completions "28.1")
-
-(defun semantic-ia-get-completions-deprecated (context point)
-  "A function to help transition away from `semantic-ia-get-completions'.
-Return completions based on CONTEXT at POINT."
+(defun semantic-ia-get-completions (context _point)
+  "Fetch the completion of CONTEXT at POINT."
   (declare (obsolete semantic-analyze-possible-completions "28.1"))
   (semantic-analyze-possible-completions context))
 
diff --git a/lisp/cedet/semantic/idle.el b/lisp/cedet/semantic/idle.el
index 5af4607..b6633d7 100644
--- a/lisp/cedet/semantic/idle.el
+++ b/lisp/cedet/semantic/idle.el
@@ -47,8 +47,6 @@
 ;; For the semantic-find-tags-by-name macro.
 (eval-when-compile (require 'semantic/find))
 
-(defvar eldoc-last-message)
-(declare-function eldoc-message "eldoc")
 (declare-function semantic-analyze-unsplit-name "semantic/analyze/fcn")
 (declare-function semantic-complete-analyze-inline-idle "semantic/complete")
 (declare-function semanticdb-deep-find-tags-by-name "semantic/db-find")
@@ -350,54 +348,56 @@ Returns t if all processing succeeded."
 Visits Semantic controlled buffers, and makes sure all needed
 include files have been parsed, and that the typecache is up to date.
 Uses `semantic-idle-work-for-on-buffer' to do the work."
-  (let ((errbuf nil)
-       (interrupted
-        (semantic-exit-on-input 'idle-work-timer
-          (let* ((inhibit-quit nil)
-                 (cb (current-buffer))
-                 (buffers (delq (current-buffer)
-                                (delq nil
-                                      (mapcar #'(lambda (b)
-                                                  (and (buffer-file-name b)
-                                                       b))
-                                              (buffer-list)))))
-                 safe errbuf)
-            ;; First, handle long tasks in the current buffer.
-            (when (semantic-idle-scheduler-enabled-p)
-              (save-excursion
-                (setq safe (semantic-idle-work-for-one-buffer (current-buffer))
-                      )))
-            (when (not safe) (push (current-buffer) errbuf))
-
-            ;; Now loop over other buffers with same major mode, trying to
-            ;; update them as well.  Stop on keypress.
-            (dolist (b buffers)
-              (semantic-throw-on-input 'parsing-mode-buffers)
-              (with-current-buffer b
-                (when (semantic-idle-scheduler-enabled-p)
-                  (and (semantic-idle-scheduler-enabled-p)
-                       (unless (semantic-idle-work-for-one-buffer 
(current-buffer))
-                         (push (current-buffer) errbuf)))
-                  ))
-              )
-
-            (when (and (featurep 'semantic/db) (semanticdb-minor-mode-p))
-              ;; Save everything.
-              (semanticdb-save-all-db-idle)
-
-              ;; Parse up files near our active buffer
-              (when semantic-idle-work-parse-neighboring-files-flag
-                (semantic-safe "Idle Work Parse Neighboring Files: %S"
-                  (set-buffer cb)
-                  (semantic-idle-scheduler-work-parse-neighboring-files))
-                t)
+  (let*
+      ((errbuf nil)
+       (interrupted
+       (semantic-exit-on-input 'idle-work-timer
+         (let* ((inhibit-quit nil)
+                (cb (current-buffer))
+                (buffers (delq (current-buffer)
+                               (delq nil
+                                     (mapcar #'(lambda (b)
+                                                 (and (buffer-file-name b)
+                                                      b))
+                                             (buffer-list)))))
+                safe) ;; errbuf
+           ;; First, handle long tasks in the current buffer.
+           (when (semantic-idle-scheduler-enabled-p)
+             (save-excursion
+               (setq safe (semantic-idle-work-for-one-buffer (current-buffer))
+                     )))
+           (when (not safe) (push (current-buffer) errbuf))
+
+           ;; Now loop over other buffers with same major mode, trying to
+           ;; update them as well.  Stop on keypress.
+           (dolist (b buffers)
+             (semantic-throw-on-input 'parsing-mode-buffers)
+             (with-current-buffer b
+               (when (semantic-idle-scheduler-enabled-p)
+                 (and (semantic-idle-scheduler-enabled-p)
+                      (unless (semantic-idle-work-for-one-buffer
+                               (current-buffer))
+                        (push (current-buffer) errbuf)))
+                 ))
+             )
 
-              ;; Save everything... again
-              (semanticdb-save-all-db-idle)
-              )
+           (when (and (featurep 'semantic/db) (semanticdb-minor-mode-p))
+             ;; Save everything.
+             (semanticdb-save-all-db-idle)
+
+             ;; Parse up files near our active buffer
+             (when semantic-idle-work-parse-neighboring-files-flag
+               (semantic-safe "Idle Work Parse Neighboring Files: %S"
+                 (set-buffer cb)
+                 (semantic-idle-scheduler-work-parse-neighboring-files))
+               t)
+
+             ;; Save everything... again
+             (semanticdb-save-all-db-idle)
+             )
 
-            ;; Done w/ processing
-            nil))))
+           ;; Done w/ processing
+           nil))))
 
     ;; Done
     (if interrupted
@@ -730,32 +730,19 @@ specific to a major mode.  For example, in jde mode:
   :group 'semantic
   :type 'hook)
 
-(defun semantic-idle-summary-idle-function ()
-  "Display a tag summary of the lexical token under the cursor.
+(defun semantic--eldoc-info (_callback &rest _)
+  "Return the eldoc info for the current symbol.
 Call `semantic-idle-summary-current-symbol-info' for getting the
 current tag to display information."
   (or (eq major-mode 'emacs-lisp-mode)
       (not (semantic-idle-summary-useful-context-p))
-      (let* ((found (semantic-idle-summary-current-symbol-info))
+      (let* ((found (save-excursion
+                      (semantic-idle-summary-current-symbol-info)))
              (str (cond ((stringp found) found)
                         ((semantic-tag-p found)
                          (funcall semantic-idle-summary-function
                                   found nil t)))))
-       ;; Show the message with eldoc functions
-        (unless (and str (boundp 'eldoc-echo-area-use-multiline-p)
-                     eldoc-echo-area-use-multiline-p)
-          (let ((w (1- (window-width (minibuffer-window)))))
-            (if (> (length str) w)
-                (setq str (substring str 0 w)))))
-       ;; I borrowed some bits from eldoc to shorten the
-       ;; message.
-       (when semantic-idle-truncate-long-summaries
-         (let ((ea-width (1- (window-width (minibuffer-window))))
-               (strlen (length str)))
-           (when (> strlen ea-width)
-             (setq str (substring str 0 ea-width)))))
-       ;; Display it
-        (eldoc-message str))))
+        str)))
 
 (define-minor-mode semantic-idle-summary-mode
   "Toggle Semantic Idle Summary mode.
@@ -764,30 +751,16 @@ When this minor mode is enabled, the echo area displays a 
summary
 of the lexical token at point whenever Emacs is idle."
   :group 'semantic
   :group 'semantic-modes
-  (if semantic-idle-summary-mode
-      ;; Enable the mode
-      (progn
-       (unless (and (featurep 'semantic) (semantic-active-p))
-         ;; Disable minor mode if semantic stuff not available
-         (setq semantic-idle-summary-mode nil)
-         (error "Buffer %s was not set up for parsing"
-                (buffer-name)))
-       (require 'eldoc)
-       (semantic-idle-scheduler-add 'semantic-idle-summary-idle-function)
-       (add-hook 'pre-command-hook 'semantic-idle-summary-refresh-echo-area t))
-    ;; Disable the mode
-    (semantic-idle-scheduler-remove 'semantic-idle-summary-idle-function)
-    (remove-hook 'pre-command-hook 'semantic-idle-summary-refresh-echo-area 
t)))
-
-(defun semantic-idle-summary-refresh-echo-area ()
-  (and semantic-idle-summary-mode
-       eldoc-last-message
-       (if (and (not executing-kbd-macro)
-               (not (and (boundp 'edebug-active) edebug-active))
-               (not cursor-in-echo-area)
-               (not (eq (selected-window) (minibuffer-window))))
-           (eldoc-message eldoc-last-message)
-         (setq eldoc-last-message nil))))
+  (remove-hook 'eldoc-documentation-functions #'semantic--eldoc-info t)
+  (when semantic-idle-summary-mode
+    ;; Enable the mode
+    (unless (and (featurep 'semantic) (semantic-active-p))
+      ;; Disable minor mode if semantic stuff not available
+      (setq semantic-idle-summary-mode nil)
+      (error "Buffer %s was not set up for parsing"
+            (buffer-name)))
+    (add-hook 'eldoc-documentation-functions #'semantic--eldoc-info nil t)
+    (eldoc-mode 1)))
 
 (semantic-add-minor-mode 'semantic-idle-summary-mode "")
 
@@ -1065,21 +1038,20 @@ be called."
     (popup-menu semantic-idle-breadcrumbs-popup-menu)
     (select-window old-window)))
 
-(defmacro semantic-idle-breadcrumbs--tag-function (function)
+(defun semantic-idle-breadcrumbs--tag-function (function)
   "Return lambda expression calling FUNCTION when called from a popup."
-  `(lambda (event)
-     (interactive "e")
-     (let* ((old-window (selected-window))
-           (window     (semantic-event-window event))
-           (column     (car (nth 6 (nth 1 event)))) ;; TODO 
semantic-event-column?
-           (tag        (progn
-                         (select-window window t)
-                         (plist-get
-                          (text-properties-at column header-line-format)
-                          'tag))))
-       (,function tag)
-       (select-window old-window)))
-  )
+  (lambda (event)
+    (interactive "e")
+    (let* ((old-window (selected-window))
+          (window     (semantic-event-window event))
+          (column     (car (nth 6 (nth 1 event)))) ;; TODO 
semantic-event-column?
+          (tag        (progn
+                        (select-window window t)
+                        (plist-get
+                         (text-properties-at column header-line-format)
+                         'tag))))
+      (funcall function tag)
+      (select-window old-window))))
 
 ;; TODO does this work for mode-line case?
 (defvar semantic-idle-breadcrumbs-popup-map
@@ -1087,12 +1059,11 @@ be called."
     ;; mouse-1 goes to clicked tag
     (define-key map
       [ header-line mouse-1 ]
-      (semantic-idle-breadcrumbs--tag-function
-       semantic-go-to-tag))
+      (semantic-idle-breadcrumbs--tag-function #'semantic-go-to-tag))
     ;; mouse-3 pops up a context menu
     (define-key map
       [ header-line mouse-3 ]
-      'semantic-idle-breadcrumbs--popup-menu)
+      #'semantic-idle-breadcrumbs--popup-menu)
     map)
   "Keymap for semantic idle breadcrumbs minor mode.")
 
@@ -1104,8 +1075,7 @@ be called."
    "Breadcrumb Tag"
    (vector
     "Go to Tag"
-    (semantic-idle-breadcrumbs--tag-function
-     semantic-go-to-tag)
+    (semantic-idle-breadcrumbs--tag-function #'semantic-go-to-tag)
     :active t
     :help  "Jump to this tag")
    ;; TODO these entries need minor changes (optional tag argument) in
@@ -1113,37 +1083,32 @@ be called."
    ;;  (semantic-menu-item
    ;;   (vector
    ;;    "Copy Tag"
-   ;;    (semantic-idle-breadcrumbs--tag-function
-   ;;     senator-copy-tag)
+   ;;    (semantic-idle-breadcrumbs--tag-function #'senator-copy-tag)
    ;;    :active t
    ;;    :help   "Copy this tag"))
    ;;   (semantic-menu-item
    ;;    (vector
    ;;     "Kill Tag"
-   ;;     (semantic-idle-breadcrumbs--tag-function
-   ;;      senator-kill-tag)
+   ;;     (semantic-idle-breadcrumbs--tag-function #'senator-kill-tag)
    ;;     :active t
    ;;     :help   "Kill tag text to the kill ring, and copy the tag to
    ;; the tag ring"))
    ;;   (semantic-menu-item
    ;;    (vector
    ;;     "Copy Tag to Register"
-   ;;     (semantic-idle-breadcrumbs--tag-function
-   ;;      senator-copy-tag-to-register)
+   ;;     (semantic-idle-breadcrumbs--tag-function 
#'senator-copy-tag-to-register)
    ;;     :active t
    ;;     :help   "Copy this tag"))
    ;;   (semantic-menu-item
    ;;    (vector
    ;;     "Narrow to Tag"
-   ;;     (semantic-idle-breadcrumbs--tag-function
-   ;;      senator-narrow-to-defun)
+   ;;     (semantic-idle-breadcrumbs--tag-function #'senator-narrow-to-defun)
    ;;     :active t
    ;;     :help   "Narrow to the bounds of the current tag"))
    ;;   (semantic-menu-item
    ;;    (vector
    ;;     "Fold Tag"
-   ;;     (semantic-idle-breadcrumbs--tag-function
-   ;;      senator-fold-tag-toggle)
+   ;;     (semantic-idle-breadcrumbs--tag-function #'senator-fold-tag-toggle)
    ;;     :active   t
    ;;     :style    'toggle
    ;;     :selected '(let ((tag (semantic-current-tag)))
diff --git a/lisp/cedet/semantic/imenu.el b/lisp/cedet/semantic/imenu.el
index 4c13959..2c5f10a 100644
--- a/lisp/cedet/semantic/imenu.el
+++ b/lisp/cedet/semantic/imenu.el
@@ -1,4 +1,4 @@
-;;; semantic/imenu.el --- Use Semantic as an imenu tag generator
+;;; semantic/imenu.el --- Use Semantic as an imenu tag generator  -*- 
lexical-binding: t; -*-
 
 ;; Copyright (C) 2000-2005, 2007-2008, 2010-2021 Free Software
 ;; Foundation, Inc.
@@ -57,14 +57,12 @@
 (defcustom semantic-imenu-summary-function 'semantic-format-tag-abbreviate
   "Function to use when creating items in Imenu.
 Some useful functions are found in `semantic-format-tag-functions'."
-  :group 'semantic-imenu
   :type semantic-format-tag-custom-list)
 (make-variable-buffer-local 'semantic-imenu-summary-function)
 
 ;;;###autoload
 (defcustom semantic-imenu-bucketize-file t
   "Non-nil if tags in a file are to be grouped into buckets."
-  :group 'semantic-imenu
   :type 'boolean)
 (make-variable-buffer-local 'semantic-imenu-bucketize-file)
 
@@ -72,20 +70,17 @@ Some useful functions are found in 
`semantic-format-tag-functions'."
   "Non-nil if types in a file should adopt externally defined members.
 C++ and CLOS can define methods that are not in the body of a class
 definition."
-  :group 'semantic-imenu
   :type 'boolean)
 
 (defcustom semantic-imenu-buckets-to-submenu t
   "Non-nil if buckets of tags are to be turned into submenus.
 This option is ignored if `semantic-imenu-bucketize-file' is nil."
-  :group 'semantic-imenu
   :type 'boolean)
 (make-variable-buffer-local 'semantic-imenu-buckets-to-submenu)
 
 ;;;###autoload
 (defcustom semantic-imenu-expand-type-members t
   "Non-nil if types should have submenus with members in them."
-  :group 'semantic-imenu
   :type 'boolean)
 (make-variable-buffer-local 'semantic-imenu-expand-type-members)
 
@@ -93,7 +88,6 @@ This option is ignored if `semantic-imenu-bucketize-file' is 
nil."
   "Non-nil if members of a type should be grouped into buckets.
 A nil value means to keep them in the same order.
 Overridden to nil if `semantic-imenu-bucketize-file' is nil."
-  :group 'semantic-imenu
   :type 'boolean)
 (make-variable-buffer-local 'semantic-imenu-bucketize-type-members)
 
@@ -101,7 +95,6 @@ Overridden to nil if `semantic-imenu-bucketize-file' is nil."
   "Function to use when sorting tags in the buckets of functions.
 See `semantic-bucketize' and the FILTER argument for more details
 on this function."
-  :group 'semantic-imenu
   :type '(radio (const :tag "No Sorting" nil)
                (const semantic-sort-tags-by-name-increasing)
                (const semantic-sort-tags-by-name-decreasing)
@@ -119,14 +112,12 @@ on this function."
 Doesn't actually parse the entire directory, but displays tags for all files
 currently listed in the current Semantic database.
 This variable has no meaning if semanticdb is not active."
-  :group 'semantic-imenu
   :type 'boolean)
 
 (defcustom semantic-imenu-auto-rebuild-directory-indexes nil
   "If non-nil automatically rebuild directory index imenus.
 That is when a directory index imenu is updated, automatically rebuild
 other buffer local ones based on the same semanticdb."
-  :group 'semantic-imenu
   :type 'boolean)
 
 (defvar semantic-imenu-directory-current-file nil
@@ -206,7 +197,7 @@ Optional argument REST is some extra stuff."
            (setq imenu--index-alist nil)))))
     ))
 
-(defun semantic-imenu-flush-fcn (&optional ignore)
+(defun semantic-imenu-flush-fcn (&optional _ignore)
   "This function is called as a hook to clear the imenu cache.
 It is cleared after any parsing.
 IGNORE arguments."
@@ -214,9 +205,9 @@ IGNORE arguments."
       (setq imenu--index-alist nil
             imenu-menubar-modified-tick 0))
   (remove-hook 'semantic-after-toplevel-cache-change-hook
-               'semantic-imenu-flush-fcn t)
+               #'semantic-imenu-flush-fcn t)
   (remove-hook 'semantic-after-partial-cache-change-hook
-               'semantic-imenu-flush-fcn t)
+               #'semantic-imenu-flush-fcn t)
   )
 
 ;;;###autoload
@@ -224,7 +215,7 @@ IGNORE arguments."
   "Create an imenu index for any buffer which supports Semantic.
 Uses the output of the Semantic parser to create the index.
 Optional argument STREAM is an optional stream of tags used to create menus."
-  (setq imenu-default-goto-function 'semantic-imenu-goto-function)
+  (setq imenu-default-goto-function #'semantic-imenu-goto-function)
   (prog1
       (if (and semantic-imenu-index-directory
                (featurep 'semantic/db)
@@ -234,9 +225,9 @@ Optional argument STREAM is an optional stream of tags used 
to create menus."
         (semantic-create-imenu-index-1
         (or stream (semantic-fetch-tags-fast)) nil))
     (add-hook 'semantic-after-toplevel-cache-change-hook
-              'semantic-imenu-flush-fcn nil t)
+              #'semantic-imenu-flush-fcn nil t)
     (add-hook 'semantic-after-partial-cache-change-hook
-              'semantic-imenu-flush-fcn nil t)))
+              #'semantic-imenu-flush-fcn nil t)))
 
 (defun semantic-create-imenu-directory-index (&optional stream)
   "Create an imenu tag index based on all files active in semanticdb.
@@ -445,7 +436,7 @@ Clears all imenu menus that may be depending on the 
database."
        ;; Clear imenu cache to redraw the imenu.
        (semantic-imenu-flush-fcn))))
 
-(add-hook 'semanticdb-mode-hook 'semantic-imenu-semanticdb-hook)
+(add-hook 'semanticdb-mode-hook #'semantic-imenu-semanticdb-hook)
 
 ;;; Interactive Utilities
 ;;
@@ -484,7 +475,6 @@ Clears all imenu menus that may be depending on the 
database."
 
 (defcustom semantic-which-function-use-color nil
   "Use color when displaying the current function with `which-function'."
-  :group 'semantic-imenu
   :type 'boolean)
 
 (defun semantic-default-which-function (taglist)
diff --git a/lisp/cedet/semantic/java.el b/lisp/cedet/semantic/java.el
index f60f6e8..8cadffa 100644
--- a/lisp/cedet/semantic/java.el
+++ b/lisp/cedet/semantic/java.el
@@ -1,6 +1,6 @@
-;;; semantic/java.el --- Semantic functions for Java
+;;; semantic/java.el --- Semantic functions for Java  -*- lexical-binding: t; 
-*-
 
-;;; Copyright (C) 1999-2021 Free Software Foundation, Inc.
+;; Copyright (C) 1999-2021  Free Software Foundation, Inc.
 
 ;; Author: David Ponce <david@dponce.com>
 
@@ -148,7 +148,7 @@ corresponding compound declaration."
       (let* ((name (semantic-tag-name tag))
             (rsplit (nreverse (split-string name "\\." t)))
             (newclassname (car rsplit))
-            (newpkg (mapconcat 'identity (reverse (cdr rsplit)) ".")))
+            (newpkg (mapconcat #'identity (reverse (cdr rsplit)) ".")))
        (semantic-tag-set-name tag newclassname)
        (setq xpand
              (list tag
@@ -169,7 +169,7 @@ corresponding compound declaration."
 (define-mode-local-override semantic-ctxt-scoped-types
   java-mode (&optional point)
   "Return a list of type names currently in scope at POINT."
-  (mapcar 'semantic-tag-name
+  (mapcar #'semantic-tag-name
           (semantic-find-tags-by-class
            'type (semantic-find-tag-by-overlay point))))
 
@@ -184,7 +184,7 @@ Override function for `semantic-tag-protection'."
 
 ;; Prototype handler
 ;;
-(defun semantic-java-prototype-function (tag &optional parent color)
+(defun semantic-java-prototype-function (tag &optional _parent color)
   "Return a function (method) prototype for TAG.
 Optional argument PARENT is a parent (containing) item.
 Optional argument COLOR indicates that color should be mixed in.
@@ -212,7 +212,7 @@ See also `semantic-format-tag-prototype'."
             (or type "") (if type " " "")
             name "(" argp ")")))
 
-(defun semantic-java-prototype-variable (tag &optional parent color)
+(defun semantic-java-prototype-variable (tag &optional _parent color)
   "Return a variable (field) prototype for TAG.
 Optional argument PARENT is a parent (containing) item.
 Optional argument COLOR indicates that color should be mixed in.
@@ -227,7 +227,7 @@ See also `semantic-format-tag-prototype'."
                 (semantic--format-colorize-text name 'variable)
               name))))
 
-(defun semantic-java-prototype-type (tag &optional parent color)
+(defun semantic-java-prototype-type (tag &optional _parent color)
   "Return a type (class/interface) prototype for TAG.
 Optional argument PARENT is a parent (containing) item.
 Optional argument COLOR indicates that color should be mixed in.
@@ -260,7 +260,7 @@ Optional argument COLOR indicates that color should be 
mixed in."
 (define-mode-local-override semantic-tag-include-filename java-mode (tag)
   "Return a suitable path for (some) Java imports."
   (let ((name (semantic-tag-name tag)))
-    (concat (mapconcat 'identity (split-string name "\\.") "/") ".java")))
+    (concat (mapconcat #'identity (split-string name "\\.") "/") ".java")))
 
 ;; Documentation handler
 ;;
@@ -417,15 +417,13 @@ removed from the result list."
   (or semantic-java-doc-with-name-tags
       (setq semantic-java-doc-with-name-tags
             (semantic-java-doc-keywords-map
-             #'(lambda (k p)
-                 k)
+             #'(lambda (k _p) k)
              'with-name)))
 
   (or semantic-java-doc-with-ref-tags
       (setq semantic-java-doc-with-ref-tags
             (semantic-java-doc-keywords-map
-             #'(lambda (k p)
-                 k)
+             #'(lambda (k _p) k)
              'with-ref)))
 
   (or semantic-java-doc-extra-type-tags
diff --git a/lisp/cedet/semantic/lex-spp.el b/lisp/cedet/semantic/lex-spp.el
index 408011c..0b24bd2 100644
--- a/lisp/cedet/semantic/lex-spp.el
+++ b/lisp/cedet/semantic/lex-spp.el
@@ -1,4 +1,4 @@
-;;; semantic/lex-spp.el --- Semantic Lexical Pre-processor
+;;; semantic/lex-spp.el --- Semantic Lexical Pre-processor  -*- 
lexical-binding: t; -*-
 
 ;; Copyright (C) 2006-2021 Free Software Foundation, Inc.
 
@@ -106,22 +106,12 @@ added and removed from this symbol table.")
 Pushes NAME into the macro stack.  The above stack is checked
 by `semantic-lex-spp-symbol' to not return true for any symbol
 currently being expanded."
+  (declare (indent 1) (debug (symbolp def-body)))
   `(unwind-protect
        (progn
         (push ,name semantic-lex-spp-expanded-macro-stack)
         ,@body)
      (pop semantic-lex-spp-expanded-macro-stack)))
-(put 'semantic-lex-with-macro-used 'lisp-indent-function 1)
-
-(add-hook
- 'edebug-setup-hook
- #'(lambda ()
-
-     (def-edebug-spec semantic-lex-with-macro-used
-       (symbolp def-body)
-       )
-
-     ))
 
 ;;; MACRO TABLE UTILS
 ;;
@@ -190,7 +180,7 @@ Disable debugging by entering nothing."
       (setq semantic-lex-spp-debug-symbol nil)
     (setq semantic-lex-spp-debug-symbol sym)))
 
-(defmacro semantic-lex-spp-validate-value (name value)
+(defmacro semantic-lex-spp-validate-value (_name _value)
   "Validate the NAME and VALUE of a macro before it is set."
 ;  `(progn
 ;     (when (not (semantic-lex-spp-value-valid-p ,value))
@@ -212,12 +202,11 @@ the dynamic map."
                        (semantic-lex-spp-dynamic-map)))
        value))
 
-(defsubst semantic-lex-spp-symbol-remove (name &optional obarray)
+(defsubst semantic-lex-spp-symbol-remove (name &optional map)
   "Remove the spp symbol with NAME.
-If optional OBARRAY is non-nil, then use that obarray instead of
+If optional obarray MAP is non-nil, then use that obarray instead of
 the dynamic map."
-  (unintern name (or obarray
-                    (semantic-lex-spp-dynamic-map))))
+  (unintern name (or map (semantic-lex-spp-dynamic-map))))
 
 (defun semantic-lex-spp-symbol-push (name value)
   "Push macro NAME with VALUE into the map.
@@ -246,7 +235,7 @@ Reverse with `semantic-lex-spp-symbol-pop'."
         (stack (semantic-lex-spp-dynamic-map-stack))
         (mapsym (intern name map))
         (stacksym (intern name stack))
-        (oldvalue nil)
+        ;; (oldvalue nil)
         )
     (if (or (not (boundp stacksym) )
            (= (length (symbol-value stacksym)) 0))
@@ -324,7 +313,7 @@ For use with semanticdb restoration of state."
     ;; Default obarray for below is the dynamic map.
     (semantic-lex-spp-symbol-set (car e) (cdr e))))
 
-(defun semantic-lex-spp-reset-hook (start end)
+(defun semantic-lex-spp-reset-hook (start _end)
   "Reset anything needed by SPP for parsing.
 In this case, reset the dynamic macro symbol table if
 START is (point-min).
@@ -354,7 +343,7 @@ Return non-nil if it matches"
       (string-match regex value))
     ))
 
-(defun semantic-lex-spp-simple-macro-to-macro-stream (val beg end argvalues)
+(defun semantic-lex-spp-simple-macro-to-macro-stream (val beg end _argvalues)
   "Convert lexical macro contents VAL into a macro expansion stream.
 These are for simple macro expansions that a user may have typed in directly.
 As such, we need to analyze the input text, to figure out what kind of real
@@ -819,7 +808,7 @@ ARGVALUES are values for any arg list, or nil."
 ;; An analyzer that will push tokens from a macro in place
 ;; of the macro symbol.
 ;;
-(defun semantic-lex-spp-analyzer-do-replace (sym val beg end)
+(defun semantic-lex-spp-analyzer-do-replace (_sym val beg end)
   "Do the lexical replacement for SYM with VAL.
 Argument BEG and END specify the bounds of SYM in the buffer."
   (if (not val)
@@ -861,7 +850,7 @@ Argument BEG and END specify the bounds of SYM in the 
buffer."
     ))
 (define-obsolete-function-alias
   'semantic-lex-spp-anlyzer-do-replace
-  'semantic-lex-spp-analyzer-do-replace "25.1")
+  #'semantic-lex-spp-analyzer-do-replace "25.1")
 
 (defvar semantic-lex-spp-replacements-enabled t
   "Non-nil means do replacements when finding keywords.
@@ -1045,7 +1034,7 @@ and variable state from the current buffer."
         (fresh-toks nil)
         (toks nil)
         (origbuff (current-buffer))
-        (analyzer semantic-lex-analyzer)
+        ;; (analyzer semantic-lex-analyzer)
         (important-vars '(semantic-lex-spp-macro-symbol-obarray
                           semantic-lex-spp-project-macro-symbol-obarray
                           semantic-lex-spp-dynamic-macro-symbol-obarray
@@ -1081,7 +1070,7 @@ and variable state from the current buffer."
            (semantic-lex-init)
            (semantic-clear-toplevel-cache)
            (remove-hook 'semantic-lex-reset-functions
-                        'semantic-lex-spp-reset-hook t)
+                        #'semantic-lex-spp-reset-hook t)
            ))
 
        ;; Second Cheat: copy key variables regarding macro state from the
@@ -1176,6 +1165,7 @@ of type `spp-macro-def' is to be created.
 VALFORM are forms that return the value to be saved for this macro, or nil.
 When implementing a macro, you can use `semantic-lex-spp-stream-for-macro'
 to convert text into a lexical stream for storage in the macro."
+  (declare (debug (&define name stringp stringp form def-body)))
   (let ((start (make-symbol "start"))
        (end (make-symbol "end"))
        (val (make-symbol "val"))
@@ -1209,6 +1199,7 @@ REGEXP is a regular expression for the analyzer to match.
 See `define-lex-regex-analyzer' for more on regexp.
 TOKIDX is an index into REGEXP for which a new lexical token
 of type `spp-macro-undef' is to be created."
+  (declare (debug (&define name stringp stringp form)))
   (let ((start (make-symbol "start"))
        (end (make-symbol "end")))
     `(define-lex-regex-analyzer ,name
@@ -1244,7 +1235,7 @@ Note: Not implemented yet."
   :group 'semantic
   :type 'boolean)
 
-(defun semantic-lex-spp-merge-header (name)
+(defun semantic-lex-spp-merge-header (_name)
   "Extract and merge any macros from the header with NAME.
 Finds the header file belonging to NAME, gets the macros
 from that file, and then merge the macros with our current
@@ -1269,6 +1260,7 @@ type of include.  The return value should be of the form:
   (NAME . TYPE)
 where NAME is the name of the include, and TYPE is the type of the include,
 where a valid symbol is `system', or nil."
+  (declare (debug (&define name stringp stringp form def-body)))
   (let ((start (make-symbol "start"))
        (end (make-symbol "end"))
        (val (make-symbol "val"))
@@ -1369,23 +1361,6 @@ If BUFFER is not provided, use the current buffer."
        (princ "\n")
        ))))
 
-;;; EDEBUG Handlers
-;;
-(add-hook
- 'edebug-setup-hook
- #'(lambda ()
-
-     (def-edebug-spec define-lex-spp-macro-declaration-analyzer
-       (&define name stringp stringp form def-body)
-       )
-
-     (def-edebug-spec define-lex-spp-macro-undeclaration-analyzer
-       (&define name stringp stringp form)
-       )
-
-     (def-edebug-spec define-lex-spp-include-analyzer
-       (&define name stringp stringp form def-body))))
-
 (provide 'semantic/lex-spp)
 
 ;; Local variables:
diff --git a/lisp/cedet/semantic/lex.el b/lisp/cedet/semantic/lex.el
index ae70d5c..121e5c3 100644
--- a/lisp/cedet/semantic/lex.el
+++ b/lisp/cedet/semantic/lex.el
@@ -469,7 +469,7 @@ PROPERTY set."
 ;;; Lexical Analyzer framework settings
 ;;
 
-(defvar-local semantic-lex-analyzer 'semantic-lex
+(defvar-local semantic-lex-analyzer #'semantic-lex
   "The lexical analyzer used for a given buffer.
 See `semantic-lex' for documentation.")
 
@@ -760,6 +760,7 @@ If two analyzers can match the same text, it is important 
to order the
 analyzers so that the one you want to match first occurs first.  For
 example, it is good to put a number analyzer in front of a symbol
 analyzer which might mistake a number for a symbol."
+  (declare (debug (&define name stringp (&rest symbolp))))
   `(defun ,name  (start end &optional depth length)
      ,(concat doc "\nSee `semantic-lex' for more information.")
      ;; Make sure the state of block parsing starts over.
@@ -1064,14 +1065,13 @@ the desired syntax, and a position returned.
 If `debug-on-error' is set, errors are not caught, so that you can
 debug them.
 Avoid using a large FORMS since it is duplicated."
+  (declare (indent 1) (debug t))
   `(if (and debug-on-error semantic-lex-debug-analyzers)
        (progn ,@forms)
      (condition-case nil
          (progn ,@forms)
        (error
         (semantic-lex-unterminated-syntax-detected ,syntax)))))
-(put 'semantic-lex-unterminated-syntax-protection
-     'lisp-indent-function 1)
 
 (defmacro define-lex-analyzer (name doc condition &rest forms)
   "Create a single lexical analyzer NAME with DOC.
@@ -1096,32 +1096,29 @@ Proper action in FORMS is to move the value of 
`semantic-lex-end-point' to
 after the location of the analyzed entry, and to add any discovered tokens
 at the beginning of `semantic-lex-token-stream'.
 This can be done by using `semantic-lex-push-token'."
+  (declare (debug (&define name stringp form def-body)))
   `(eval-and-compile
-     (defvar ,name nil ,doc)
-     (defun ,name nil)
-     ;; Do this part separately so that re-evaluation rebuilds this code.
-     (setq ,name '(,condition ,@forms))
+     ;; This is the real info used by `define-lex' (via 
semantic-lex-one-token).
+     (defconst ,name '(,condition ,@forms) ,doc)
      ;; Build a single lexical analyzer function, so the doc for
      ;; function help is automatically provided, and perhaps the
      ;; function could be useful for testing and debugging one
      ;; analyzer.
-     (fset ',name (lambda () ,doc
-                   (let ((semantic-lex-token-stream nil)
-                         (semantic-lex-end-point (point))
-                         (semantic-lex-analysis-bounds
-                          (cons (point) (point-max)))
-                         (semantic-lex-current-depth 0)
-                         (semantic-lex-maximum-depth
-                          semantic-lex-depth)
-                         )
-                     (when ,condition ,@forms)
-                     semantic-lex-token-stream)))
-     ))
+     (defun ,name ()
+       ,doc
+       (let ((semantic-lex-token-stream nil)
+            (semantic-lex-end-point (point))
+            (semantic-lex-analysis-bounds (cons (point) (point-max)))
+            (semantic-lex-current-depth 0)
+            (semantic-lex-maximum-depth semantic-lex-depth))
+        (when ,condition ,@forms)
+        semantic-lex-token-stream))))
 
 (defmacro define-lex-regex-analyzer (name doc regexp &rest forms)
   "Create a lexical analyzer with NAME and DOC that will match REGEXP.
 FORMS are evaluated upon a successful match.
 See `define-lex-analyzer' for more about analyzers."
+  (declare (debug (&define name stringp form def-body)))
   `(define-lex-analyzer ,name
      ,doc
      (looking-at ,regexp)
@@ -1139,6 +1136,8 @@ expression.
 FORMS are evaluated upon a successful match BEFORE the new token is
 created.  It is valid to ignore FORMS.
 See `define-lex-analyzer' for more about analyzers."
+  (declare (debug
+            (&define name stringp form symbolp [ &optional form ] def-body)))
   `(define-lex-analyzer ,name
      ,doc
      (looking-at ,regexp)
@@ -1163,6 +1162,7 @@ where BLOCK-SYM is the symbol returned in a block token.  
OPEN-DELIM
 and CLOSE-DELIM are respectively the open and close delimiters
 identifying a block.  OPEN-SYM and CLOSE-SYM are respectively the
 symbols returned in open and close tokens."
+  (declare (debug (&define name stringp form (&rest form))))
   (let ((specs (cons spec1 specs))
         spec open olist clist)
     (while specs
@@ -1684,6 +1684,7 @@ the error will be caught here without the buffer's cache 
being thrown
 out of date.
 If there is an error, the syntax that failed is returned.
 If there is no error, then the last value of FORMS is returned."
+  (declare (indent 1) (debug (symbolp def-body)))
   (let ((ret (make-symbol "ret"))
         (syntax (make-symbol "syntax"))
         (start (make-symbol "start"))
@@ -1707,35 +1708,7 @@ If there is no error, then the last value of FORMS is 
returned."
          ;;(message "Buffer not currently parsable (%S)." ,ret)
          (semantic-parse-tree-unparseable))
        ,ret)))
-(put 'semantic-lex-catch-errors 'lisp-indent-function 1)
-
-
-;;; Interfacing with edebug
-;;
-(add-hook
- 'edebug-setup-hook
- #'(lambda ()
-
-     (def-edebug-spec define-lex
-       (&define name stringp (&rest symbolp))
-       )
-     (def-edebug-spec define-lex-analyzer
-       (&define name stringp form def-body)
-       )
-     (def-edebug-spec define-lex-regex-analyzer
-       (&define name stringp form def-body)
-       )
-     (def-edebug-spec define-lex-simple-regex-analyzer
-       (&define name stringp form symbolp [ &optional form ] def-body)
-       )
-     (def-edebug-spec define-lex-block-analyzer
-       (&define name stringp form (&rest form))
-       )
-     (def-edebug-spec semantic-lex-catch-errors
-       (symbolp def-body)
-       )
 
-     ))
 
 ;;; Compatibility with Semantic 1.x lexical analysis
 
diff --git a/lisp/cedet/semantic/mru-bookmark.el 
b/lisp/cedet/semantic/mru-bookmark.el
index 956eb68..2e77e6b 100644
--- a/lisp/cedet/semantic/mru-bookmark.el
+++ b/lisp/cedet/semantic/mru-bookmark.el
@@ -1,4 +1,4 @@
-;;; semantic/mru-bookmark.el --- Automatic bookmark tracking
+;;; semantic/mru-bookmark.el --- Automatic bookmark tracking  -*- 
lexical-binding: t; -*-
 
 ;; Copyright (C) 2007-2021 Free Software Foundation, Inc.
 
@@ -85,7 +85,7 @@ Nice values include the following:
    )
   "A single bookmark.")
 
-(cl-defmethod initialize-instance :after ((sbm semantic-bookmark) &rest fields)
+(cl-defmethod initialize-instance :after ((sbm semantic-bookmark) &rest 
_fields)
   "Initialize the bookmark SBM with details about :tag."
   (condition-case nil
       (save-excursion
@@ -216,7 +216,7 @@ Cause tags in the ring to become unlinked."
       (setq idx (1+ idx)))))
 
 (add-hook 'semantic-before-toplevel-cache-flush-hook
-         'semantic-mrub-cache-flush-fcn)
+         #'semantic-mrub-cache-flush-fcn)
 
 ;;; EDIT tracker
 ;;
@@ -246,8 +246,8 @@ been edited, and you can re-visit them with 
\\[semantic-mrub-switch-tags]."
   :group 'semantic-modes
   :type 'boolean
   :require 'semantic/util-modes
-  :initialize 'custom-initialize-default
-  :set (lambda (sym val)
+  :initialize #'custom-initialize-default
+  :set (lambda (_sym val)
          (global-semantic-mru-bookmark-mode (if val 1 -1))))
 
 ;;;###autoload
@@ -266,7 +266,7 @@ been edited, and you can re-visit them with 
\\[semantic-mrub-switch-tags]."
 
 (defvar semantic-mru-bookmark-mode-map
   (let ((km (make-sparse-keymap)))
-    (define-key km "\C-xB" 'semantic-mrub-switch-tags)
+    (define-key km "\C-xB" #'semantic-mrub-switch-tags)
     km)
   "Keymap for mru-bookmark minor mode.")
 
@@ -289,14 +289,14 @@ non-nil if the minor mode is enabled."
             (error "Buffer %s was not set up for parsing"
                    (buffer-name)))
         (add-hook 'semantic-edits-new-change-functions
-                  'semantic-mru-bookmark-change-hook-fcn nil t)
+                  #'semantic-mru-bookmark-change-hook-fcn nil t)
         (add-hook 'semantic-edits-move-change-hooks
-                  'semantic-mru-bookmark-change-hook-fcn nil t))
+                  #'semantic-mru-bookmark-change-hook-fcn nil t))
     ;; Remove hooks
     (remove-hook 'semantic-edits-new-change-functions
-                'semantic-mru-bookmark-change-hook-fcn t)
+                #'semantic-mru-bookmark-change-hook-fcn t)
     (remove-hook 'semantic-edits-move-change-hooks
-                'semantic-mru-bookmark-change-hook-fcn t)))
+                #'semantic-mru-bookmark-change-hook-fcn t)))
 
 (semantic-add-minor-mode 'semantic-mru-bookmark-mode
                          "k")
diff --git a/lisp/cedet/semantic/sb.el b/lisp/cedet/semantic/sb.el
index d7cd8e1..debdfd1 100644
--- a/lisp/cedet/semantic/sb.el
+++ b/lisp/cedet/semantic/sb.el
@@ -1,4 +1,4 @@
-;;; semantic/sb.el --- Semantic tag display for speedbar
+;;; semantic/sb.el --- Semantic tag display for speedbar  -*- lexical-binding: 
t; -*-
 
 ;; Copyright (C) 1999-2021 Free Software Foundation, Inc.
 
@@ -73,10 +73,10 @@ use the `speedbar-line-file' to get this info if needed."
 (defmacro semantic-sb-with-tag-buffer (tag &rest forms)
   "Set the current buffer to the origin of TAG and execute FORMS.
 Restore the old current buffer when completed."
+  (declare (indent 1) (debug t))
   `(save-excursion
      (semantic-sb-tag-set-buffer ,tag)
      ,@forms))
-(put 'semantic-sb-with-tag-buffer 'lisp-indent-function 1)
 
 ;;; Button Generation
 ;;
@@ -294,7 +294,7 @@ TEXT TOKEN and INDENT are the details."
        (t (error "Ooops...  not sure what to do")))
   (speedbar-center-buffer-smartly))
 
-(defun semantic-sb-token-jump (text token indent)
+(defun semantic-sb-token-jump (_text token indent)
   "Jump to the location specified in token.
 TEXT TOKEN and INDENT are the details."
   (let ((file
diff --git a/lisp/cedet/semantic/scope.el b/lisp/cedet/semantic/scope.el
index 6bd04b2..2d806e5 100644
--- a/lisp/cedet/semantic/scope.el
+++ b/lisp/cedet/semantic/scope.el
@@ -562,7 +562,7 @@ such as `public' or `private'."
           ;; @TODO - is this line needed??  Try w/out for a while
           ;; @note - I think C++ says no.  elisp might, but methods
           ;;         look like defuns, so it makes no difference.
-          (extmeth nil) ; (semantic-tag-external-member-children type t))
+          ;;(extmeth nil) ; (semantic-tag-external-member-children type t))
 
           ;; INHERITED are tags found in classes that our TYPE tag
           ;; inherits from.  Do not do this if it was not requested.
@@ -584,7 +584,7 @@ such as `public' or `private'."
          (setq slots (nreverse copyslots))
          ))
       ;; Flatten the database output.
-      (append slots extmeth inherited)
+      (append slots nil inherited) ;; extmeth
       )))
 
 (defun semantic-analyze-scoped-inherited-tags (type scope access)
diff --git a/lisp/cedet/semantic/senator.el b/lisp/cedet/semantic/senator.el
index f33356a..1953009 100644
--- a/lisp/cedet/semantic/senator.el
+++ b/lisp/cedet/semantic/senator.el
@@ -1,4 +1,4 @@
-;;; semantic/senator.el --- SEmantic NAvigaTOR
+;;; semantic/senator.el --- SEmantic NAvigaTOR  -*- lexical-binding: t; -*-
 
 ;; Copyright (C) 2000-2021 Free Software Foundation, Inc.
 
@@ -60,7 +60,6 @@ A tag class is a symbol, such as `variable', `function', or 
`type'.
 
 As a special exception, if the value is nil, Senator's navigation
 commands recognize all tag classes."
-  :group 'senator
   :type '(repeat (symbol)))
 ;;;###autoload
 (make-variable-buffer-local 'senator-step-at-tag-classes)
@@ -78,7 +77,6 @@ commands stop at the beginning of every tag.
 
 If t, the navigation commands stop at the start and end of any
 tag, where possible."
-  :group 'senator
   :type '(choice :tag "Identifiers"
                  (repeat :menu-tag "Symbols" (symbol))
                  (const  :tag "All" t)))
@@ -87,7 +85,6 @@ tag, where possible."
 
 (defcustom senator-highlight-found nil
   "If non-nil, Senator commands momentarily highlight found tags."
-  :group 'senator
   :type 'boolean)
 (make-variable-buffer-local 'senator-highlight-found)
 
@@ -193,7 +190,6 @@ source."
   '(code block)
   "List of ignored tag classes.
 Tags of those classes are excluded from search."
-  :group 'senator
   :type '(repeat (symbol :tag "class")))
 
 (defun senator-search-default-tag-filter (tag)
@@ -461,7 +457,7 @@ filters in `senator-search-tag-filter-functions' remain 
active."
          ((symbolp classes)
           (list classes))
          ((stringp classes)
-          (mapcar 'read (split-string classes)))
+          (mapcar #'read (split-string classes)))
          (t
           (signal 'wrong-type-argument (list classes)))
          ))
@@ -470,11 +466,10 @@ filters in `senator-search-tag-filter-functions' remain 
active."
                senator--search-filter t)
   (kill-local-variable 'senator--search-filter)
   (if classes
-      (let ((tag   (make-symbol "tag"))
-            (names (mapconcat 'symbol-name classes "', `")))
+      (let ((names (mapconcat #'symbol-name classes "', `")))
         (setq-local senator--search-filter
-                    `(lambda (,tag)
-                       (memq (semantic-tag-class ,tag) ',classes)))
+                    (lambda (tag)
+                      (memq (semantic-tag-class tag) classes)))
         (add-hook 'senator-search-tag-filter-functions
                   senator--search-filter nil t)
         (message "Limit search to `%s' tags" names))
@@ -605,7 +600,7 @@ Makes C/C++ language like assumptions."
   "Non-nil if isearch does semantic search.
 This is a buffer local variable.")
 
-(defun senator-beginning-of-defun (&optional arg)
+(defun senator-beginning-of-defun (&optional _arg)
   "Move backward to the beginning of a defun.
 Use semantic tags to navigate.
 ARG is the number of tags to navigate (not yet implemented)."
@@ -620,7 +615,7 @@ ARG is the number of tags to navigate (not yet 
implemented)."
           (goto-char (semantic-tag-start tag)))
       (beginning-of-line))))
 
-(defun senator-end-of-defun (&optional arg)
+(defun senator-end-of-defun (&optional _arg)
   "Move forward to next end of defun.
 Use semantic tags to navigate.
 ARG is the number of tags to navigate (not yet implemented)."
@@ -859,7 +854,7 @@ Use a senator search function when semantic isearch mode is 
enabled."
           (setq-local senator-old-isearch-search-fun
                       isearch-search-fun-function))
         (setq-local isearch-search-fun-function
-                    'senator-isearch-search-fun))
+                    #'senator-isearch-search-fun))
     ;; When `senator-isearch-semantic-mode' is off restore the
     ;; previous `isearch-search-fun-function'.
     (when (eq isearch-search-fun-function 'senator-isearch-search-fun)
diff --git a/lisp/cedet/semantic/sort.el b/lisp/cedet/semantic/sort.el
index 19f46ff..b4b09dc 100644
--- a/lisp/cedet/semantic/sort.el
+++ b/lisp/cedet/semantic/sort.el
@@ -1,6 +1,6 @@
-;;; semantic/sort.el --- Utilities for sorting and re-arranging tag tables.
+;;; semantic/sort.el --- Utilities for sorting and re-arranging tag tables.  
-*- lexical-binding: t; -*-
 
-;;; Copyright (C) 1999-2005, 2007-2021 Free Software Foundation, Inc.
+;; Copyright (C) 1999-2021  Free Software Foundation, Inc.
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
 ;; Keywords: syntax
@@ -233,8 +233,7 @@ unmodified as components of their parent tags."
                               (semantic-flatten-tags-table components)
                               lists)))))
          table)
-    (apply 'append (nreverse lists))
-    ))
+    (apply #'append (nreverse lists))))
 
 
 ;;; Buckets:
@@ -520,12 +519,11 @@ See `semantic-tag-external-member-children' for details."
                (semantic-tag-name tag) tag)))
        (if m (apply #'append (mapcar #'cdr m))))
     (semantic--find-tags-by-function
-     `(lambda (tok)
-       ;; This bit of annoying backquote forces the contents of
-       ;; tag into the generated lambda.
-       (semantic-tag-external-member-p ',tag tok))
-     (current-buffer))
-    ))
+     (lambda (tok)
+       ;; This bit of annoying backquote forces the contents of
+       ;; tag into the generated lambda.
+       (semantic-tag-external-member-p tag tok))
+     (current-buffer))))
 
 (define-overloadable-function semantic-tag-external-class (tag)
   "Return a list of real tags that faux TAG might represent.
@@ -540,6 +538,8 @@ likely derived, then this function is needed."
   (:override)
   )
 
+(defvar semanticdb-search-system-databases)
+
 (defun semantic-tag-external-class-default (tag)
   "Return a list of real tags that faux TAG might represent.
 See `semantic-tag-external-class' for details."
diff --git a/lisp/cedet/semantic/symref.el b/lisp/cedet/semantic/symref.el
index d7f9157..701f9ad 100644
--- a/lisp/cedet/semantic/symref.el
+++ b/lisp/cedet/semantic/symref.el
@@ -1,4 +1,4 @@
-;;; semantic/symref.el --- Symbol Reference API
+;;; semantic/symref.el --- Symbol Reference API  -*- lexical-binding: t; -*-
 
 ;; Copyright (C) 2008-2021 Free Software Foundation, Inc.
 
@@ -144,7 +144,7 @@ ARGS are the initialization arguments to pass to the 
created class."
         )
     (when (not (class-p class))
       (error "Unknown symref tool %s" semantic-symref-tool))
-    (setq inst (apply 'make-instance class args))
+    (setq inst (apply #'make-instance class args))
     inst))
 
 (defvar semantic-symref-last-result nil
@@ -427,7 +427,7 @@ until the next command is executed."
            (kill-buffer buff)))
        semantic-symref-recently-opened-buffers)
   (setq semantic-symref-recently-opened-buffers nil)
-  (remove-hook 'post-command-hook 'semantic-symref-cleanup-recent-buffers-fcn)
+  (remove-hook 'post-command-hook #'semantic-symref-cleanup-recent-buffers-fcn)
   )
 
 (cl-defmethod semantic-symref-result-get-tags ((result semantic-symref-result)
@@ -453,7 +453,7 @@ already."
                   lines)))
       ;; Kill off dead buffers, unless we were requested to leave them open.
       (if (not open-buffers)
-         (add-hook 'post-command-hook 
'semantic-symref-cleanup-recent-buffers-fcn)
+         (add-hook 'post-command-hook 
#'semantic-symref-cleanup-recent-buffers-fcn)
        ;; Else, just clear the saved buffers so they aren't deleted later.
        (setq semantic-symref-recently-opened-buffers nil)
        )
diff --git a/lisp/cedet/semantic/symref/cscope.el 
b/lisp/cedet/semantic/symref/cscope.el
index 3686e51..e63b7a7 100644
--- a/lisp/cedet/semantic/symref/cscope.el
+++ b/lisp/cedet/semantic/symref/cscope.el
@@ -1,6 +1,6 @@
-;;; semantic/symref/cscope.el --- Semantic-symref support via cscope.
+;;; semantic/symref/cscope.el --- Semantic-symref support via cscope  -*- 
lexical-binding: t; -*-
 
-;;; Copyright (C) 2009-2021 Free Software Foundation, Inc.
+;; Copyright (C) 2009-2021 Free Software Foundation, Inc.
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
 
diff --git a/lisp/cedet/semantic/symref/filter.el 
b/lisp/cedet/semantic/symref/filter.el
index a40ce13..7ef3cd9 100644
--- a/lisp/cedet/semantic/symref/filter.el
+++ b/lisp/cedet/semantic/symref/filter.el
@@ -1,4 +1,4 @@
-;;; semantic/symref/filter.el --- Filter symbol reference hits for accuracy.
+;;; semantic/symref/filter.el --- Filter symbol reference hits for accuracy  
-*- lexical-binding: t; -*-
 
 ;; Copyright (C) 2009-2021 Free Software Foundation, Inc.
 
@@ -48,7 +48,7 @@
   "Determine if the tag TARGET is used at POSITION in the current buffer.
 Return non-nil for a match."
   (semantic-analyze-current-symbol
-   (lambda (start end prefix)
+   (lambda (_start _end prefix)
      (let ((tag (car (nreverse prefix))))
        (and (semantic-tag-p tag)
            (semantic-equivalent-tag-p target tag))))
@@ -97,7 +97,7 @@ tag that contains point, and return that."
         (Lcount 0))
     (when (semantic-tag-p target)
       (semantic-symref-hits-in-region
-       target (lambda (start end prefix) (setq Lcount (1+ Lcount)))
+       target (lambda (_start _end _prefix) (setq Lcount (1+ Lcount)))
        (semantic-tag-start tag)
        (semantic-tag-end tag))
       (when (called-interactively-p 'interactive)
@@ -106,6 +106,8 @@ tag that contains point, and return that."
                 (semantic-elapsed-time start nil)))
       Lcount)))
 
+(defvar srecode-field-archive)
+
 (defun semantic-symref-rename-local-variable ()
   "Fancy way to rename the local variable under point.
 Depends on the SRecode Field editing API."
@@ -140,7 +142,7 @@ Depends on the SRecode Field editing API."
          (region nil)
          )
       (semantic-symref-hits-in-region
-       target (lambda (start end prefix)
+       target (lambda (start end _prefix)
                ;; For every valid hit, create one field.
                (srecode-field "LOCAL" :name "LOCAL" :start start :end end))
        (semantic-tag-start tag) (semantic-tag-end tag))
diff --git a/lisp/cedet/semantic/symref/global.el 
b/lisp/cedet/semantic/symref/global.el
index 7f63e4d..23e4034 100644
--- a/lisp/cedet/semantic/symref/global.el
+++ b/lisp/cedet/semantic/symref/global.el
@@ -1,4 +1,4 @@
-;;; semantic/symref/global.el --- Use GNU Global for symbol references
+;;; semantic/symref/global.el --- Use GNU Global for symbol references  -*- 
lexical-binding: t; -*-
 
 ;; Copyright (C) 2008-2021 Free Software Foundation, Inc.
 
diff --git a/lisp/cedet/semantic/symref/grep.el 
b/lisp/cedet/semantic/symref/grep.el
index 9f0ac38..46027f1 100644
--- a/lisp/cedet/semantic/symref/grep.el
+++ b/lisp/cedet/semantic/symref/grep.el
@@ -1,4 +1,4 @@
-;;; semantic/symref/grep.el --- Symref implementation using find/grep
+;;; semantic/symref/grep.el --- Symref implementation using find/grep  -*- 
lexical-binding: t; -*-
 
 ;; Copyright (C) 2008-2021 Free Software Foundation, Inc.
 
diff --git a/lisp/cedet/semantic/symref/idutils.el 
b/lisp/cedet/semantic/symref/idutils.el
index 4a41355..3e3e3b0 100644
--- a/lisp/cedet/semantic/symref/idutils.el
+++ b/lisp/cedet/semantic/symref/idutils.el
@@ -1,6 +1,6 @@
-;;; semantic/symref/idutils.el --- Symref implementation for idutils
+;;; semantic/symref/idutils.el --- Symref implementation for idutils  -*- 
lexical-binding: t; -*-
 
-;;; Copyright (C) 2009-2021 Free Software Foundation, Inc.
+;; Copyright (C) 2009-2021 Free Software Foundation, Inc.
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
 
diff --git a/lisp/cedet/semantic/symref/list.el 
b/lisp/cedet/semantic/symref/list.el
index 7d3a5dd..2e447bb 100644
--- a/lisp/cedet/semantic/symref/list.el
+++ b/lisp/cedet/semantic/symref/list.el
@@ -1,4 +1,4 @@
-;;; semantic/symref/list.el --- Symref Output List UI.
+;;; semantic/symref/list.el --- Symref Output List UI  -*- lexical-binding: t; 
-*-
 
 ;; Copyright (C) 2008-2021 Free Software Foundation, Inc.
 
@@ -108,20 +108,20 @@ Display the references in `semantic-symref-results-mode'."
 (defvar semantic-symref-results-mode-map
   (let ((km (make-sparse-keymap)))
     (suppress-keymap km)
-    (define-key km "\C-i" 'forward-button)
-    (define-key km "\M-C-i" 'backward-button)
-    (define-key km " " 'push-button)
-    (define-key km "-" 'semantic-symref-list-toggle-showing)
-    (define-key km "=" 'semantic-symref-list-toggle-showing)
-    (define-key km "+" 'semantic-symref-list-toggle-showing)
-    (define-key km "n" 'semantic-symref-list-next-line)
-    (define-key km "p" 'semantic-symref-list-prev-line)
-    (define-key km "q" 'quit-window)
-    (define-key km "\C-c\C-e" 'semantic-symref-list-expand-all)
-    (define-key km "\C-c\C-r" 'semantic-symref-list-contract-all)
-    (define-key km "R" 'semantic-symref-list-rename-open-hits)
-    (define-key km "(" 'semantic-symref-list-create-macro-on-open-hit)
-    (define-key km "E" 'semantic-symref-list-call-macro-on-open-hits)
+    (define-key km "\C-i" #'forward-button)
+    (define-key km "\M-C-i" #'backward-button)
+    (define-key km " " #'push-button)
+    (define-key km "-" #'semantic-symref-list-toggle-showing)
+    (define-key km "=" #'semantic-symref-list-toggle-showing)
+    (define-key km "+" #'semantic-symref-list-toggle-showing)
+    (define-key km "n" #'semantic-symref-list-next-line)
+    (define-key km "p" #'semantic-symref-list-prev-line)
+    (define-key km "q" #'quit-window)
+    (define-key km "\C-c\C-e" #'semantic-symref-list-expand-all)
+    (define-key km "\C-c\C-r" #'semantic-symref-list-contract-all)
+    (define-key km "R" #'semantic-symref-list-rename-open-hits)
+    (define-key km "(" #'semantic-symref-list-create-macro-on-open-hit)
+    (define-key km "E" #'semantic-symref-list-call-macro-on-open-hits)
     km)
   "Keymap used in `semantic-symref-results-mode'.")
 
diff --git a/lisp/cedet/semantic/tag-file.el b/lisp/cedet/semantic/tag-file.el
index fc5c277..06dd274 100644
--- a/lisp/cedet/semantic/tag-file.el
+++ b/lisp/cedet/semantic/tag-file.el
@@ -1,4 +1,4 @@
-;;; semantic/tag-file.el --- Routines that find files based on tags.
+;;; semantic/tag-file.el --- Routines that find files based on tags.  -*- 
lexical-binding: t; -*-
 
 ;; Copyright (C) 1999-2005, 2007-2021 Free Software Foundation, Inc.
 
diff --git a/lisp/cedet/semantic/tag-ls.el b/lisp/cedet/semantic/tag-ls.el
index 6cef603..3aa1a62 100644
--- a/lisp/cedet/semantic/tag-ls.el
+++ b/lisp/cedet/semantic/tag-ls.el
@@ -1,4 +1,4 @@
-;;; semantic/tag-ls.el --- Language Specific override functions for tags
+;;; semantic/tag-ls.el --- Language Specific override functions for tags  -*- 
lexical-binding: t; -*-
 
 ;; Copyright (C) 1999-2004, 2006-2021 Free Software Foundation, Inc.
 
@@ -97,7 +97,7 @@ Modes that override this function can call
 `semantic--tag-attribute-similar-p-default' to do the default equality tests if
 ATTR is not special for that mode.")
 
-(defun semantic--tag-attribute-similar-p-default (attr value1 value2 
ignorable-attributes)
+(defun semantic--tag-attribute-similar-p-default (_attr value1 value2 
ignorable-attributes)
   "For ATTR, VALUE1, VALUE2 and IGNORABLE-ATTRIBUTES, test for similarity."
   (cond
    ;; Tag sublists require special testing.
@@ -109,7 +109,7 @@ ATTR is not special for that mode.")
       (when (not (eq (length taglist1) (length taglist2)))
        (setq ans nil))
       (while (and ans taglist1 taglist2)
-       (setq ans (apply 'semantic-tag-similar-p
+       (setq ans (apply #'semantic-tag-similar-p
                         (car taglist1) (car taglist2)
                         ignorable-attributes)
              taglist1 (cdr taglist1)
@@ -205,7 +205,7 @@ stream for a tag of class `package', and return that."
                  (or stream-or-buffer tag))))
     (:override-with-args (tag stream))))
 
-(defun semantic-tag-full-package-default (tag stream)
+(defun semantic-tag-full-package-default (_tag stream)
   "Default method for `semantic-tag-full-package' for TAG.
 Return the name of the first tag of class `package' in STREAM."
   (let ((pack (car-safe (semantic-find-tags-by-class 'package stream))))
@@ -285,7 +285,7 @@ is to return a symbol based on type modifiers."
        (setq parent (semantic-tag-calculate-parent tag)))
   (:override))
 
-(defun semantic-tag-protection-default (tag &optional parent)
+(defun semantic-tag-protection-default (tag &optional _parent)
   "Return the protection of TAG as a child of PARENT default action.
 See `semantic-tag-protection'."
   (let ((mods (semantic-tag-modifiers tag))
@@ -295,9 +295,7 @@ See `semantic-tag-protection'."
          (let ((s (car mods)))
            (setq prot
                  ;; A few silly defaults to get things started.
-                 (cond ((or (string= s "public")
-                            (string= s "extern")
-                            (string= s "export"))
+                 (cond ((member s '("public" "extern" "export"))
                         'public)
                        ((string= s "private")
                         'private)
@@ -372,15 +370,14 @@ in how methods are overridden.  In UML, abstract methods 
are italicized.
 The default behavior (if not overridden with `tag-abstract-p'
 is to return true if `abstract' is in the type modifiers.")
 
-(defun semantic-tag-abstract-p-default (tag &optional parent)
+(defun semantic-tag-abstract-p-default (tag &optional _parent)
   "Return non-nil if TAG is abstract as a child of PARENT default action.
 See `semantic-tag-abstract-p'."
   (let ((mods (semantic-tag-modifiers tag))
        (abs nil))
     (while (and (not abs) mods)
       (if (stringp (car mods))
-         (setq abs (or (string= (car mods) "abstract")
-                       (string= (car mods) "virtual"))))
+         (setq abs (member (car mods) '("abstract" "virtual"))))
       (setq mods (cdr mods)))
     abs))
 
@@ -392,7 +389,7 @@ In UML, leaf methods and classes have special meaning and 
behavior.
 The default behavior (if not overridden with `tag-leaf-p'
 is to return true if `leaf' is in the type modifiers.")
 
-(defun semantic-tag-leaf-p-default (tag &optional parent)
+(defun semantic-tag-leaf-p-default (tag &optional _parent)
   "Return non-nil if TAG is leaf as a child of PARENT default action.
 See `semantic-tag-leaf-p'."
   (let ((mods (semantic-tag-modifiers tag))
@@ -412,7 +409,7 @@ In UML, static methods and attributes mean that they are 
allocated
 in the parent class, and are not instance specific.
 UML notation specifies that STATIC entries are underlined.")
 
-(defun semantic-tag-static-p-default (tag &optional parent)
+(defun semantic-tag-static-p-default (tag &optional _parent)
   "Return non-nil if TAG is static as a child of PARENT default action.
 See `semantic-tag-static-p'."
   (let ((mods (semantic-tag-modifiers tag))
diff --git a/lisp/cedet/semantic/tag-write.el b/lisp/cedet/semantic/tag-write.el
index f705c89..9d5aeea 100644
--- a/lisp/cedet/semantic/tag-write.el
+++ b/lisp/cedet/semantic/tag-write.el
@@ -1,4 +1,4 @@
-;;; semantic/tag-write.el --- Write tags to a text stream
+;;; semantic/tag-write.el --- Write tags to a text stream  -*- 
lexical-binding: t; -*-
 
 ;; Copyright (C) 2008-2021 Free Software Foundation, Inc.
 
@@ -88,7 +88,7 @@ INDENT is the amount of indentation to use for this tag."
   (if (semantic-tag-with-position-p tag)
       (let ((bounds (semantic-tag-bounds tag)))
        (princ " ")
-       (prin1 (apply 'vector bounds))
+       (prin1 (apply #'vector bounds))
        )
     (princ " nil"))
   ;; End it.
diff --git a/lisp/cedet/semantic/tag.el b/lisp/cedet/semantic/tag.el
index 85defe4..b6386d7 100644
--- a/lisp/cedet/semantic/tag.el
+++ b/lisp/cedet/semantic/tag.el
@@ -1,4 +1,4 @@
-;;; semantic/tag.el --- tag creation and access
+;;; semantic/tag.el --- Tag creation and access  -*- lexical-binding: t; -*-
 
 ;; Copyright (C) 1999-2005, 2007-2021 Free Software Foundation, Inc.
 
@@ -229,6 +229,28 @@ See also the function `semantic-ctxt-current-mode'."
           (require 'semantic/ctxt)
           (semantic-ctxt-current-mode)))))
 
+;; Is this function still necessary?
+(defun semantic-tag-make-plist (args)
+  "Create a property list with ARGS.
+Args is a property list of the form (KEY1 VALUE1 ... KEYN VALUEN).
+Where KEY is a symbol, and VALUE is the value for that symbol.
+The return value will be a new property list, with these KEY/VALUE
+pairs eliminated:
+
+  - KEY associated to nil VALUE.
+  - KEY associated to an empty string VALUE.
+  - KEY associated to a zero VALUE."
+  (let (plist key val)
+    (while args
+      (setq key  (car args)
+            val  (nth 1 args)
+            args (nthcdr 2 args))
+      (or (member val '("" nil))
+          (and (numberp val) (zerop val))
+          (setq plist (cons key (cons val plist)))))
+    ;; It is not useful to reverse the new plist.
+    plist))
+
 (defsubst semantic--tag-attributes-cdr (tag)
   "Return the cons cell whose car is the ATTRIBUTES part of TAG.
 That function is for internal use only."
@@ -441,28 +463,6 @@ class to store those methods."
 ;;; Tag creation
 ;;
 
-;; Is this function still necessary?
-(defun semantic-tag-make-plist (args)
-  "Create a property list with ARGS.
-Args is a property list of the form (KEY1 VALUE1 ... KEYN VALUEN).
-Where KEY is a symbol, and VALUE is the value for that symbol.
-The return value will be a new property list, with these KEY/VALUE
-pairs eliminated:
-
-  - KEY associated to nil VALUE.
-  - KEY associated to an empty string VALUE.
-  - KEY associated to a zero VALUE."
-  (let (plist key val)
-    (while args
-      (setq key  (car args)
-            val  (nth 1 args)
-            args (nthcdr 2 args))
-      (or (member val '("" nil))
-          (and (numberp val) (zerop val))
-          (setq plist (cons key (cons val plist)))))
-    ;; It is not useful to reverse the new plist.
-    plist))
-
 (defsubst semantic-tag (name class &rest attributes)
   "Create a generic semantic tag.
 NAME is a string representing the name of this tag.
@@ -478,7 +478,7 @@ TYPE is a string or semantic tag representing the type of 
this variable.
 Optional DEFAULT-VALUE is a string representing the default value of this
 variable.
 ATTRIBUTES is a list of additional attributes belonging to this tag."
-  (apply 'semantic-tag name 'variable
+  (apply #'semantic-tag name 'variable
          :type type
          :default-value default-value
          attributes))
@@ -490,7 +490,7 @@ TYPE is a string or semantic tag representing the type of 
this function.
 ARG-LIST is a list of strings or semantic tags representing the
 arguments of this function.
 ATTRIBUTES is a list of additional attributes belonging to this tag."
-  (apply 'semantic-tag name 'function
+  (apply #'semantic-tag name 'function
          :type type
          :arguments arg-list
          attributes))
@@ -513,7 +513,7 @@ This slot can be interesting because the form:
 is a valid parent where there is no explicit parent, and only an
 interface.
 ATTRIBUTES is a list of additional attributes belonging to this tag."
-  (apply 'semantic-tag name 'type
+  (apply #'semantic-tag name 'type
          :type type
          :members members
          :superclasses (car parents)
@@ -526,7 +526,7 @@ NAME is the name of this include.
 SYSTEM-FLAG represents that we were able to identify this include as
 belonging to the system, as opposed to belonging to the local project.
 ATTRIBUTES is a list of additional attributes belonging to this tag."
-  (apply 'semantic-tag name 'include
+  (apply #'semantic-tag name 'include
          :system-flag system-flag
          attributes))
 
@@ -536,7 +536,7 @@ NAME is the name of this package.
 DETAIL is extra information about this package, such as a location
 where it can be found.
 ATTRIBUTES is a list of additional attributes belonging to this tag."
-  (apply 'semantic-tag name 'package
+  (apply #'semantic-tag name 'package
          :detail detail
          attributes))
 
@@ -545,7 +545,7 @@ ATTRIBUTES is a list of additional attributes belonging to 
this tag."
 NAME is a name for this code.
 DETAIL is extra information about the code.
 ATTRIBUTES is a list of additional attributes belonging to this tag."
-  (apply 'semantic-tag name 'code
+  (apply #'semantic-tag name 'code
          :detail detail
          attributes))
 
@@ -685,7 +685,7 @@ FILTER takes TAG as an argument, and should return a 
`semantic-tag'.
 It is safe for FILTER to modify the input tag and return it."
   (when (not filter) (setq filter 'identity))
   (when (not (semantic-tag-p tag))
-    (signal 'wrong-type-argument (list tag 'semantic-tag-p)))
+    (signal 'wrong-type-argument (list tag #'semantic-tag-p)))
   (let ((ol (semantic-tag-overlay tag))
        (fn (semantic-tag-file-name tag)))
     (funcall filter (list (semantic-tag-name tag)
@@ -937,7 +937,7 @@ NAME is a name for this alias.
 META-TAG-CLASS is the class of the tag this tag is an alias.
 VALUE is the aliased definition.
 ATTRIBUTES is a list of additional attributes belonging to this tag."
-  (apply 'semantic-tag name 'alias
+  (apply #'semantic-tag name 'alias
          :aliasclass meta-tag-class
          :definition value
          attributes))
@@ -1038,25 +1038,17 @@ See `semantic-tag-bounds'."
 
 (defmacro semantic-with-buffer-narrowed-to-current-tag (&rest body)
   "Execute BODY with the buffer narrowed to the current tag."
+  (declare (indent 0) (debug t))
   `(save-restriction
      (semantic-narrow-to-tag (semantic-current-tag))
      ,@body))
-(put 'semantic-with-buffer-narrowed-to-current-tag 'lisp-indent-function 0)
-(add-hook 'edebug-setup-hook
-         (lambda ()
-           (def-edebug-spec semantic-with-buffer-narrowed-to-current-tag
-             (def-body))))
 
 (defmacro semantic-with-buffer-narrowed-to-tag (tag &rest body)
   "Narrow to TAG, and execute BODY."
+  (declare (indent 1) (debug t))
   `(save-restriction
      (semantic-narrow-to-tag ,tag)
      ,@body))
-(put 'semantic-with-buffer-narrowed-to-tag 'lisp-indent-function 1)
-(add-hook 'edebug-setup-hook
-         (lambda ()
-           (def-edebug-spec semantic-with-buffer-narrowed-to-tag
-             (def-body))))
 
 ;;; Tag Hooks
 ;;
@@ -1101,7 +1093,7 @@ For any given situation, additional ARGS may be passed."
     (condition-case err
        ;; If a hook bombs, ignore it!  Usually this is tied into
        ;; some sort of critical system.
-       (apply 'run-hook-with-args 'semantic--tag-hook-value arglist)
+       (apply #'run-hook-with-args 'semantic--tag-hook-value arglist)
       (error (message "Error: %S" err)))))
 
 ;;; Tags and Overlays
@@ -1112,7 +1104,7 @@ For any given situation, additional ARGS may be passed."
 (defsubst semantic--tag-unlink-list-from-buffer (tags)
   "Convert TAGS from using an overlay to using an overlay proxy.
 This function is for internal use only."
-  (mapcar 'semantic--tag-unlink-from-buffer tags))
+  (mapcar #'semantic--tag-unlink-from-buffer tags))
 
 (defun semantic--tag-unlink-from-buffer (tag)
   "Convert TAG from using an overlay to using an overlay proxy.
@@ -1133,7 +1125,7 @@ This function is for internal use only."
 (defsubst semantic--tag-link-list-to-buffer (tags)
   "Convert TAGS from using an overlay proxy to using an overlay.
 This function is for internal use only."
-  (mapc 'semantic--tag-link-to-buffer tags))
+  (mapc #'semantic--tag-link-to-buffer tags))
 
 (defun semantic--tag-link-to-buffer (tag)
   "Convert TAG from using an overlay proxy to using an overlay.
diff --git a/lisp/cedet/semantic/texi.el b/lisp/cedet/semantic/texi.el
index 377cec5..5a38280 100644
--- a/lisp/cedet/semantic/texi.el
+++ b/lisp/cedet/semantic/texi.el
@@ -1,4 +1,4 @@
-;;; semantic/texi.el --- Semantic details for Texinfo files
+;;; semantic/texi.el --- Semantic details for Texinfo files  -*- 
lexical-binding: t; -*-
 
 ;; Copyright (C) 2001-2005, 2007-2021 Free Software Foundation, Inc.
 
@@ -55,7 +55,7 @@ The field position is the field number (based at 1) where the
 name of this section is.")
 
 ;;; Code:
-(defun semantic-texi-parse-region (&rest ignore)
+(defun semantic-texi-parse-region (&rest _ignore)
   "Parse the current texinfo buffer for semantic tags.
 IGNORE any arguments, always parse the whole buffer.
 Each tag returned is of the form:
@@ -79,7 +79,7 @@ function `semantic-install-function-overrides'."
   (let ((chil (semantic-tag-components tag)))
     (if chil
         (semantic-tag-put-attribute
-         tag :members (mapcar 'semantic-texi-expand-tag chil)))
+         tag :members (mapcar #'semantic-texi-expand-tag chil)))
     (car (semantic--tag-expand tag))))
 
 (defun semantic-texi-parse-headings ()
@@ -297,7 +297,7 @@ can handle the @menu environment.")
     nil))
 
 (define-mode-local-override semantic-ctxt-current-class-list
-  texinfo-mode (&optional point)
+  texinfo-mode (&optional _point)
   "Determine the class of tags that can be used at POINT.
 For texinfo, there two possibilities returned.
 1) `function' - for a call to a texinfo function
@@ -368,7 +368,7 @@ Optional argument POINT is where to look for the 
environment."
 (declare-function semantic-analyze-context "semantic/analyze")
 
 (define-mode-local-override semantic-analyze-current-context
-  texinfo-mode (point)
+  texinfo-mode (_point)
   "Analysis context makes no sense for texinfo.  Return nil."
   (let* ((prefixandbounds (semantic-ctxt-current-symbol-and-bounds (point)))
         (prefix (car prefixandbounds))
@@ -408,7 +408,7 @@ Optional argument POINT is where to look for the 
environment."
   "List of commands that we might bother completing.")
 
 (define-mode-local-override semantic-analyze-possible-completions
-  texinfo-mode (context &rest flags)
+  texinfo-mode (context &rest _flags)
   "List smart completions at point.
 Since texinfo is not a programming language the default version is not
 useful.  Instead, look at the current symbol.  If it is a command
@@ -451,7 +451,7 @@ that start with that symbol."
   (setq semantic-parser-name "TEXI"
         ;; Setup a dummy parser table to enable parsing!
         semantic--parse-table t
-        imenu-create-index-function 'semantic-create-imenu-index
+        imenu-create-index-function #'semantic-create-imenu-index
        semantic-command-separation-character "@"
        semantic-type-relation-separator-character '(":")
        semantic-symbol->name-assoc-list '((section . "Section")
@@ -466,7 +466,7 @@ that start with that symbol."
   ;; (local-set-key [(f9)] 'semantic-texi-update-doc-from-texi)
   )
 
-(add-hook 'texinfo-mode-hook 'semantic-default-texi-setup)
+(add-hook 'texinfo-mode-hook #'semantic-default-texi-setup)
 
 
 ;;; Special features of Texinfo tag streams
@@ -500,7 +500,7 @@ that start with that symbol."
 
 ;; Turns out this might not be useful.
 ;; Delete later if that is true.
-(defun semantic-texi-find-documentation (name &optional type)
+(defun semantic-texi-find-documentation (name &optional _type)
   "Find the function or variable NAME of TYPE in the texinfo source.
 NAME is a string representing some functional symbol.
 TYPE is a string, such as \"variable\" or \"Command\" used to find
diff --git a/lisp/cedet/semantic/util-modes.el 
b/lisp/cedet/semantic/util-modes.el
index 0de66d2..a02d566 100644
--- a/lisp/cedet/semantic/util-modes.el
+++ b/lisp/cedet/semantic/util-modes.el
@@ -1,4 +1,4 @@
-;;; semantic/util-modes.el --- Semantic minor modes
+;;; semantic/util-modes.el --- Semantic minor modes  -*- lexical-binding: t; 
-*-
 
 ;; Copyright (C) 2000-2005, 2007-2021 Free Software Foundation, Inc.
 
@@ -48,7 +48,7 @@ line."
   :group 'semantic
   :type 'boolean
   :require 'semantic/util-modes
-  :initialize 'custom-initialize-default
+  :initialize #'custom-initialize-default
   :set (lambda (sym val)
          (set-default sym val)
          ;; Update status of all Semantic enabled buffers
@@ -60,7 +60,7 @@ line."
   :group 'semantic
   :type 'string
   :require 'semantic/util-modes
-  :initialize 'custom-initialize-default)
+  :initialize #'custom-initialize-default)
 
 (defvar semantic-minor-modes-format nil
   "Mode line format showing Semantic minor modes which are locally enabled.
@@ -93,7 +93,7 @@ Only minor modes that are locally enabled are shown in the 
mode line."
                           (match-string 1 semantic-mode-line-prefix)
                         "S")))
           (setq semantic-minor-modes-format
-                `((:eval (if (or ,@(mapcar 'car locals))
+                `((:eval (if (or ,@(mapcar #'car locals))
                              ,(concat " " prefix)))))
           ;; It would be easier to just put `locals' inside
           ;; semantic-minor-modes-format, but then things like
@@ -111,7 +111,7 @@ Only minor modes that are locally enabled are shown in the 
mode line."
                                  (cons elem minor-mode-alist)))))
             (setcdr tail (nconc locals (cdr tail)))))))))
 
-(defun semantic-desktop-ignore-this-minor-mode (buffer)
+(defun semantic-desktop-ignore-this-minor-mode (_buffer)
   "Installed as a minor-mode initializer for Desktop mode.
 BUFFER is the buffer to not initialize a Semantic minor mode in."
   nil)
@@ -221,10 +221,10 @@ non-nil if the minor mode is enabled."
            (error "Buffer %s was not set up for parsing"
                   (buffer-name)))
        (add-hook 'semantic-edits-new-change-functions
-                 'semantic-highlight-edits-new-change-hook-fcn nil t))
+                 #'semantic-highlight-edits-new-change-hook-fcn nil t))
     ;; Remove hooks
     (remove-hook 'semantic-edits-new-change-functions
-                'semantic-highlight-edits-new-change-hook-fcn t)))
+                #'semantic-highlight-edits-new-change-hook-fcn t)))
 
 (semantic-add-minor-mode 'semantic-highlight-edits-mode
                          "e")
@@ -345,7 +345,7 @@ Do not search past BOUND if non-nil."
 
 (defvar semantic-show-unmatched-syntax-mode-map
   (let ((km (make-sparse-keymap)))
-    (define-key km "\C-c,`" 'semantic-show-unmatched-syntax-next)
+    (define-key km "\C-c,`" #'semantic-show-unmatched-syntax-next)
     km)
   "Keymap for command `semantic-show-unmatched-syntax-mode'.")
 
@@ -372,18 +372,18 @@ non-nil if the minor mode is enabled.
                    (buffer-name)))
         ;; Add hooks
         (add-hook 'semantic-unmatched-syntax-hook
-                  'semantic-show-unmatched-syntax nil t)
+                  #'semantic-show-unmatched-syntax nil t)
        (add-hook 'semantic-pre-clean-token-hooks
-                 'semantic-clean-token-of-unmatched-syntax nil t)
+                 #'semantic-clean-token-of-unmatched-syntax nil t)
         ;; Show unmatched syntax elements
        (if (not (semantic--umatched-syntax-needs-refresh-p))
            (semantic-show-unmatched-syntax
             (semantic-unmatched-syntax-tokens))))
     ;; Remove hooks
     (remove-hook 'semantic-unmatched-syntax-hook
-                 'semantic-show-unmatched-syntax t)
+                 #'semantic-show-unmatched-syntax t)
     (remove-hook 'semantic-pre-clean-token-hooks
-                'semantic-clean-token-of-unmatched-syntax t)
+                #'semantic-clean-token-of-unmatched-syntax t)
     ;; Cleanup unmatched-syntax highlighting
     (semantic-clean-unmatched-syntax-in-buffer)))
 
@@ -454,46 +454,46 @@ non-nil if the minor mode is enabled."
                        '(semantic-show-parser-state-string))))
        ;; Add hooks
         (add-hook 'semantic-edits-new-change-functions
-                  'semantic-show-parser-state-marker nil t)
+                  #'semantic-show-parser-state-marker nil t)
        (add-hook 'semantic-edits-incremental-reparse-failed-hook
-                 'semantic-show-parser-state-marker nil t)
+                 #'semantic-show-parser-state-marker nil t)
        (add-hook 'semantic-after-partial-cache-change-hook
-                 'semantic-show-parser-state-marker nil t)
+                 #'semantic-show-parser-state-marker nil t)
        (add-hook 'semantic-after-toplevel-cache-change-hook
-                 'semantic-show-parser-state-marker nil t)
+                 #'semantic-show-parser-state-marker nil t)
        (semantic-show-parser-state-marker)
 
        (add-hook 'semantic-before-auto-parse-hooks
-                 'semantic-show-parser-state-auto-marker nil t)
+                 #'semantic-show-parser-state-auto-marker nil t)
        (add-hook 'semantic-after-auto-parse-hooks
-                 'semantic-show-parser-state-marker nil t)
+                 #'semantic-show-parser-state-marker nil t)
 
        (add-hook 'semantic-before-idle-scheduler-reparse-hook
-                 'semantic-show-parser-state-auto-marker nil t)
+                 #'semantic-show-parser-state-auto-marker nil t)
        (add-hook 'semantic-after-idle-scheduler-reparse-hook
-                 'semantic-show-parser-state-marker nil t))
+                 #'semantic-show-parser-state-marker nil t))
     ;; Remove parts of mode line
     (setq mode-line-modified
          (delq 'semantic-show-parser-state-string mode-line-modified))
     ;; Remove hooks
     (remove-hook 'semantic-edits-new-change-functions
-                'semantic-show-parser-state-marker t)
+                #'semantic-show-parser-state-marker t)
     (remove-hook 'semantic-edits-incremental-reparse-failed-hook
-                'semantic-show-parser-state-marker t)
+                #'semantic-show-parser-state-marker t)
     (remove-hook 'semantic-after-partial-cache-change-hook
-                'semantic-show-parser-state-marker t)
+                #'semantic-show-parser-state-marker t)
     (remove-hook 'semantic-after-toplevel-cache-change-hook
-                'semantic-show-parser-state-marker t)
+                #'semantic-show-parser-state-marker t)
 
     (remove-hook 'semantic-before-auto-parse-hooks
-                'semantic-show-parser-state-auto-marker t)
+                #'semantic-show-parser-state-auto-marker t)
     (remove-hook 'semantic-after-auto-parse-hooks
-                'semantic-show-parser-state-marker t)
+                #'semantic-show-parser-state-marker t)
 
     (remove-hook 'semantic-before-idle-scheduler-reparse-hook
-                'semantic-show-parser-state-auto-marker t)
+                #'semantic-show-parser-state-auto-marker t)
     (remove-hook 'semantic-after-idle-scheduler-reparse-hook
-                'semantic-show-parser-state-marker t)))
+                #'semantic-show-parser-state-marker t)))
 
 (semantic-add-minor-mode 'semantic-show-parser-state-mode
                          "")
@@ -502,7 +502,7 @@ non-nil if the minor mode is enabled."
   "String showing the parser state for this buffer.
 See `semantic-show-parser-state-marker' for details.")
 
-(defun semantic-show-parser-state-marker (&rest ignore)
+(defun semantic-show-parser-state-marker (&rest _ignore)
   "Set `semantic-show-parser-state-string' to indicate parser state.
 This marker is one of the following:
  `-'  ->  The cache is up to date.
@@ -555,7 +555,7 @@ to indicate a parse in progress."
 
 (defvar semantic-stickyfunc-mode-map
   (let ((km (make-sparse-keymap)))
-    (define-key km [ header-line down-mouse-1 ] 'semantic-stickyfunc-menu)
+    (define-key km [ header-line down-mouse-1 ] #'semantic-stickyfunc-menu)
     km)
   "Keymap for stickyfunc minor mode.")
 
@@ -826,7 +826,7 @@ Argument EVENT describes the event that caused this 
function to be called."
 
 (defvar semantic-highlight-func-mode-map
   (let ((km (make-sparse-keymap)))
-    (define-key km [mouse-3] 'semantic-highlight-func-menu)
+    (define-key km [mouse-3] #'semantic-highlight-func-menu)
     km)
   "Keymap for highlight-func minor mode.")
 
@@ -916,10 +916,10 @@ non-nil if the minor mode is enabled."
          (error "Buffer %s was not set up for parsing" (buffer-name)))
        ;; Setup our hook
        (add-hook 'post-command-hook
-                  'semantic-highlight-func-highlight-current-tag nil t))
+                  #'semantic-highlight-func-highlight-current-tag nil t))
     ;; Disable highlight func mode
     (remove-hook 'post-command-hook
-                 'semantic-highlight-func-highlight-current-tag t)
+                 #'semantic-highlight-func-highlight-current-tag t)
     (semantic-highlight-func-highlight-current-tag t)))
 
 (defun semantic-highlight-func-highlight-current-tag (&optional disable)
diff --git a/lisp/cedet/semantic/util.el b/lisp/cedet/semantic/util.el
index 8c487e1..bfc923c 100644
--- a/lisp/cedet/semantic/util.el
+++ b/lisp/cedet/semantic/util.el
@@ -1,6 +1,6 @@
-;;; semantic/util.el --- Utilities for use with semantic tag tables
+;;; semantic/util.el --- Utilities for use with semantic tag tables  -*- 
lexical-binding: t; -*-
 
-;;; Copyright (C) 1999-2005, 2007-2021 Free Software Foundation, Inc.
+;; Copyright (C) 1999-2021  Free Software Foundation, Inc.
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
 ;; Keywords: syntax
@@ -114,7 +114,10 @@ buffer, or a filename.  If SOMETHING is nil return nil."
    ((and (featurep 'semantic/db)
         (require 'semantic/db-mode)
         (semanticdb-minor-mode-p)
-        (cl-typep something 'semanticdb-abstract-table))
+        (progn
+          (declare-function semanticdb-abstract-table--eieio-childp
+                            "semantic/db")
+          (cl-typep something 'semanticdb-abstract-table)))
     (semanticdb-refresh-table something)
     (semanticdb-get-tags something))
    ;; Semanticdb find-results
@@ -427,7 +430,7 @@ determining which symbols are considered."
       (setq completion (try-completion pattern collection predicate))
       (if (string= pattern completion)
          (let ((list (all-completions pattern collection predicate)))
-           (setq list (sort list 'string<))
+           (setq list (sort list #'string<))
            (if (> (length list) 1)
                (with-output-to-temp-buffer "*Completions*"
                  (display-completion-list
diff --git a/lisp/cedet/semantic/wisent.el b/lisp/cedet/semantic/wisent.el
index d5b7324..f498e7e 100644
--- a/lisp/cedet/semantic/wisent.el
+++ b/lisp/cedet/semantic/wisent.el
@@ -1,4 +1,4 @@
-;;; semantic/wisent.el --- Wisent - Semantic gateway
+;;; semantic/wisent.el --- Wisent - Semantic gateway  -*- lexical-binding: t; 
-*-
 
 ;; Copyright (C) 2001-2007, 2009-2021 Free Software Foundation, Inc.
 
@@ -69,6 +69,7 @@ Returned tokens must have the form:
   (TOKSYM VALUE START . END)
 
 where VALUE is the buffer substring between START and END positions."
+  (declare (debug (&define name stringp def-body)))
   `(defun
      ,name () ,doc
      (cond
@@ -223,7 +224,7 @@ the standard function `semantic-parse-stream'."
                                     (error-message-string error-to-filter))
                            (message "wisent-parse-max-stack-size \
 might need to be increased"))
-                       (apply 'signal error-to-filter))))))
+                       (apply #'signal error-to-filter))))))
     ;; Manage returned lookahead token
     (if wisent-lookahead
         (if (eq (caar la-elt) wisent-lookahead)
@@ -251,6 +252,17 @@ might need to be increased"))
           (if (consp cache) cache '(nil))
           )))
 
+(defmacro wisent-compiled-grammar (grammar &optional start-list)
+  "Return a compiled form of the LALR(1) Wisent GRAMMAR.
+See `wisent--compile-grammar' for a description of the arguments
+and return value."
+  ;; Ensure that the grammar compiler is available.
+  (require 'semantic/wisent/comp)
+  (declare-function wisent-automaton-lisp-form "semantic/wisent/comp" (x))
+  (declare-function wisent--compile-grammar "semantic/wisent/comp" (grm st))
+  (wisent-automaton-lisp-form
+   (wisent--compile-grammar grammar start-list)))
+
 (defun wisent-parse-region (start end &optional goal depth returnonerror)
   "Parse the area between START and END using the Wisent LALR parser.
 Return the list of semantic tags found.
@@ -319,18 +331,6 @@ the standard function `semantic-parse-region'."
                       (point-max))))))
     ;; Return parse tree
     (nreverse ptree)))
-
-;;; Interfacing with edebug
-;;
-(add-hook
- 'edebug-setup-hook
- #'(lambda ()
-
-     (def-edebug-spec define-wisent-lexer
-       (&define name stringp def-body)
-       )
-
-     ))
 
 (provide 'semantic/wisent)
 
diff --git a/lisp/cedet/semantic/wisent/comp.el 
b/lisp/cedet/semantic/wisent/comp.el
index 755d30a..6addc13 100644
--- a/lisp/cedet/semantic/wisent/comp.el
+++ b/lisp/cedet/semantic/wisent/comp.el
@@ -1,4 +1,4 @@
-;;; semantic/wisent/comp.el --- GNU Bison for Emacs - Grammar compiler
+;;; semantic/wisent/comp.el --- GNU Bison for Emacs - Grammar compiler  -*- 
lexical-binding: t; -*-
 
 ;; Copyright (C) 1984, 1986, 1989, 1992, 1995, 2000-2007, 2009-2021 Free
 ;; Software Foundation, Inc.
@@ -54,15 +54,16 @@
 ;; bound locally, without all these "reference to free variable"
 ;; compiler warnings!
 
-(defmacro wisent-context-name (name)
-  "Return the context name from NAME."
-  `(if (and ,name (symbolp ,name))
-       (intern (format "wisent-context-%s" ,name))
-     (error "Invalid context name: %S" ,name)))
+(eval-when-compile
+  (defun wisent-context-name (name)
+    "Return the context name from NAME."
+    (if (and name (symbolp name))
+        (intern (format "wisent-context-%s" name))
+      (error "Invalid context name: %S" name)))
 
-(defmacro wisent-context-bindings (name)
-  "Return the variables in context NAME."
-  `(symbol-value (wisent-context-name ,name)))
+  (defun wisent-context-bindings (name)
+    "Return the variables in context NAME."
+    (symbol-value (wisent-context-name name))))
 
 (defmacro wisent-defcontext (name &rest vars)
   "Define a context NAME that will bind variables VARS."
@@ -77,12 +78,8 @@
 (defmacro wisent-with-context (name &rest body)
   "Bind variables in context NAME then eval BODY."
   (declare (indent 1))
-  (let ((bindings (wisent-context-bindings name)))
-    `(progn
-       ,@(mapcar (lambda (binding) `(defvar ,(or (car-safe binding) binding)))
-                 bindings)
-       (let* ,bindings
-         ,@body))))
+  `(dlet ,(wisent-context-bindings name)
+     ,@body))
 
 ;; Other utilities
 
@@ -101,6 +98,8 @@ If optional LEFT is non-nil insert spaces on left."
 ;;;; Environment dependencies
 ;;;; ------------------------
 
+;; FIXME: Use bignums or bool-vectors?
+
 (defconst wisent-BITS-PER-WORD (logcount most-positive-fixnum))
 
 (defsubst wisent-WORDSIZE (n)
@@ -159,13 +158,9 @@ Its name is defined in constant `wisent-log-buffer-name'."
   '(with-current-buffer (wisent-log-buffer)
      (erase-buffer)))
 
-(defvar byte-compile-current-file)
-
 (defun wisent-source ()
   "Return the current source file name or nil."
-  (let ((source (or (and (boundp 'byte-compile-current-file)
-                         byte-compile-current-file)
-                    load-file-name (buffer-file-name))))
+  (let ((source (macroexp-file-name)))
     (if source
         (file-relative-name source))))
 
@@ -2241,7 +2236,7 @@ there are any reduce/reduce conflicts."
           ;; output warnings.
           (and src
                (intern (format "wisent-%s--expected-conflicts"
-                               (replace-regexp-in-string "\\.el$" "" src))))))
+                               (replace-regexp-in-string "\\.el\\'" "" 
src))))))
     (when (or (not (zerop rrc-total))
               (and (not (zerop src-total))
                    (not (= src-total (or wisent-expected-conflicts 0)))
@@ -2778,7 +2773,7 @@ that likes a token gets to handle it."
   "Figure out the actions for every state.
 Return the action table."
   ;; Store the semantic action obarray in (unused) RCODE[0].
-  (aset rcode 0 (make-vector 13 0))
+  (aset rcode 0 (obarray-make 13))
   (let (i j action-table actrow action)
     (setq action-table (make-vector nstates nil)
           actrow (make-vector ntokens nil)
@@ -3392,7 +3387,7 @@ NONTERMS is the list of non terminal definitions (see 
function
 ;;;; Compile input grammar
 ;;;; ---------------------
 
-(defun wisent-compile-grammar (grammar &optional start-list)
+(defun wisent--compile-grammar (grammar start-list)
   "Compile the LALR(1) GRAMMAR.
 
 GRAMMAR is a list (TOKENS ASSOCS . NONTERMS) where:
@@ -3444,7 +3439,7 @@ where:
        (wisent-parser-automaton)))))
 
 ;;;; --------------------------
-;;;; Byte compile input grammar
+;;;; Obsolete byte compile support
 ;;;; --------------------------
 
 (require 'bytecomp)
@@ -3453,25 +3448,32 @@ where:
   "Byte compile the `wisent-compile-grammar' FORM.
 Automatically called by the Emacs Lisp byte compiler as a
 `byte-compile' handler."
-  ;; Eval the `wisent-compile-grammar' form to obtain an LALR
-  ;; automaton internal data structure.  Then, because the internal
-  ;; data structure contains an obarray, convert it to a lisp form so
-  ;; it can be byte-compiled.
   (byte-compile-form
-   ;; FIXME: we macroexpand here since `byte-compile-form' expects
-   ;; macroexpanded code, but that's just a workaround: for lexical-binding
-   ;; the lisp form should have to pass through closure-conversion and
-   ;; `wisent-byte-compile-grammar' is called much too late for that.
-   ;; Why isn't this `wisent-automaton-lisp-form' performed at
-   ;; macroexpansion time?  --Stef
    (macroexpand-all
-    (wisent-automaton-lisp-form (eval form)))))
+    (wisent-automaton-lisp-form (eval form t)))))
 
-;; FIXME: We shouldn't use a `byte-compile' handler.  Maybe using a hash-table
-;; instead of an obarray would work around the problem that obarrays
-;; aren't printable.  Then (put 'wisent-compile-grammar 'side-effect-free t).
-(put 'wisent-compile-grammar 'byte-compile 'wisent-byte-compile-grammar)
+(defun wisent-compile-grammar (grammar &optional start-list)
+  ;; This is kept for compatibility with FOO-wy.el files generated
+  ;; with older Emacsen.
+  (declare (obsolete wisent-compiled-grammar "Mar 2021"))
+  (wisent--compile-grammar grammar start-list))
+
+(put 'wisent-compile-grammar 'byte-compile #'wisent-byte-compile-grammar)
+
+;;;; --------------------------
+;;;; Byte compile input grammar
+;;;; --------------------------
 
+;; `wisent--compile-grammar' generates the actual parse table
+;; we need at run-time, but in order to be able to compile the code it
+;; contains, we need to "reify" it back into a piece of ELisp code
+;; which (re)builds it.
+;; This is needed for 2 reasons:
+;; - The parse tables include an obarray and these don't survive the print+read
+;;   steps involved in generating a `.elc' file and reading it back in.
+;; - Within the parse table vectors/obarrays we have ELisp functions which
+;;   we want to byte-compile, but if we were to just `quote' the table
+;;   we'd get them with the same non-compiled functions.
 (defun wisent-automaton-lisp-form (automaton)
   "Return a Lisp form that produces AUTOMATON.
 See also `wisent-compile-grammar' for more details on AUTOMATON."
@@ -3481,7 +3483,7 @@ See also `wisent-compile-grammar' for more details on 
AUTOMATON."
   (let ((obn (make-symbol "ob"))        ; Generated obarray name
         (obv (aref automaton 3))        ; Semantic actions obarray
         )
-    `(let ((,obn (make-vector 13 0)))
+    `(let ((,obn (obarray-make 13)))
        ;; Generate code to initialize the semantic actions obarray,
        ;; in local variable OBN.
        ,@(let (obcode)
@@ -3500,7 +3502,9 @@ See also `wisent-compile-grammar' for more details on 
AUTOMATON."
         ;; obarray.
         (vector
          ,@(mapcar
-            #'(lambda (state) ;; for each state
+            ;; Use name `st' rather than `state' since `state' is
+            ;; defined as dynbound in `semantic-actions' context above :-( !
+            #'(lambda (st) ;; for each state
                 `(list
                   ,@(mapcar
                      #'(lambda (tr) ;; for each transition
@@ -3511,7 +3515,7 @@ See also `wisent-compile-grammar' for more details on 
AUTOMATON."
                                `(cons ,(if (symbolp k) `(quote ,k) k)
                                       (intern-soft ,(symbol-name a) ,obn))
                              `(quote ,tr))))
-                     state)))
+                     st)))
             (aref automaton 0)))
         ;; The code of the goto table is unchanged.
         ,(aref automaton 1)
diff --git a/lisp/cedet/semantic/wisent/grammar.el 
b/lisp/cedet/semantic/wisent/grammar.el
index cfd4899..819ebd5 100644
--- a/lisp/cedet/semantic/wisent/grammar.el
+++ b/lisp/cedet/semantic/wisent/grammar.el
@@ -1,4 +1,4 @@
-;;; semantic/wisent/grammar.el --- Wisent's input grammar mode
+;;; semantic/wisent/grammar.el --- Wisent's input grammar mode  -*- 
lexical-binding: t; -*-
 
 ;; Copyright (C) 2002-2021 Free Software Foundation, Inc.
 ;;
@@ -228,7 +228,7 @@ Keep order of declaration in the WY file without 
duplicates."
 Return the expanded expression."
   (if (or (atom expr) (semantic-grammar-quote-p (car expr)))
       expr ;; Just return atom or quoted expression.
-    (let* ((expr  (mapcar 'wisent-grammar-expand-macros expr))
+    (let* ((expr  (mapcar #'wisent-grammar-expand-macros expr))
            (macro (assq (car expr) wisent--grammar-macros)))
       (if macro ;; Expand Semantic built-in.
           (apply (cdr macro) (cdr expr))
@@ -286,12 +286,9 @@ Return the expanded expression."
 
 (defun wisent-grammar-parsetable-builder ()
   "Return the value of the parser table."
-  `(progn
-     ;; Ensure that the grammar [byte-]compiler is available.
-     (eval-when-compile (require 'semantic/wisent/comp))
-     (wisent-compile-grammar
-      ',(wisent-grammar-grammar)
-      ',(semantic-grammar-start))))
+  `(wisent-compiled-grammar
+    ,(wisent-grammar-grammar)
+    ,(semantic-grammar-start)))
 
 (defun wisent-grammar-setupcode-builder ()
   "Return the parser setup code."
@@ -305,7 +302,7 @@ Return the expanded expression."
           semantic-lex-types-obarray %s)\n\
     ;; Collect unmatched syntax lexical tokens\n\
     (add-hook 'wisent-discarding-token-functions\n\
-              'wisent-collect-unmatched-syntax nil t)"
+              #'wisent-collect-unmatched-syntax nil t)"
    (semantic-grammar-parsetable)
    (buffer-name)
    (semantic-grammar-keywordtable)
@@ -325,6 +322,7 @@ Menu items are appended to the common grammar menu.")
 (define-derived-mode wisent-grammar-mode semantic-grammar-mode "WY"
   "Major mode for editing Wisent grammars."
   (semantic-grammar-setup-menu wisent-grammar-menu)
+  (setq-local semantic-grammar-require-form '(require 'semantic/wisent))
   (semantic-install-function-overrides
    '((semantic-grammar-parsetable-builder . wisent-grammar-parsetable-builder)
      (semantic-grammar-setupcode-builder  . 
wisent-grammar-setupcode-builder))))
@@ -514,7 +512,8 @@ Menu items are appended to the common grammar menu.")
          (goto-char (point-min))
          (delete-region (point-min) (line-end-position))
          (insert ";;; " packagename
-                 " --- Generated parser support file")
+                 " --- Generated parser support file  "
+                 "-*- lexical-binding:t -*-")
          (re-search-forward ";;; \\(.*\\) ends here")
          (replace-match packagename nil nil nil 1)
          (delete-trailing-whitespace))))))
diff --git a/lisp/cedet/semantic/wisent/java-tags.el 
b/lisp/cedet/semantic/wisent/java-tags.el
index d455c02..b4a87be 100644
--- a/lisp/cedet/semantic/wisent/java-tags.el
+++ b/lisp/cedet/semantic/wisent/java-tags.el
@@ -1,4 +1,4 @@
-;;; semantic/wisent/java-tags.el --- Java LALR parser for Emacs
+;;; semantic/wisent/java-tags.el --- Java LALR parser for Emacs  -*- 
lexical-binding: t; -*-
 
 ;; Copyright (C) 2001-2006, 2009-2021 Free Software Foundation, Inc.
 
@@ -92,7 +92,7 @@ This function override `get-local-variables'."
 
 (define-mode-local-override semantic-analyze-unsplit-name java-mode (namelist)
   "Assemble the list of names NAMELIST into a namespace name."
-  (mapconcat 'identity namelist "."))
+  (mapconcat #'identity namelist "."))
 
 
 
@@ -111,12 +111,12 @@ Use the alternate LALR(1) parser."
   (setq
    ;; Lexical analysis
    semantic-lex-number-expression semantic-java-number-regexp
-   semantic-lex-analyzer 'wisent-java-tags-lexer
+   semantic-lex-analyzer #'wisent-java-tags-lexer
    ;; Parsing
-   semantic-tag-expand-function 'semantic-java-expand-tag
+   semantic-tag-expand-function #'semantic-java-expand-tag
    ;; Environment
-   semantic-imenu-summary-function 'semantic-format-tag-prototype
-   imenu-create-index-function 'semantic-create-imenu-index
+   semantic-imenu-summary-function #'semantic-format-tag-prototype
+   imenu-create-index-function #'semantic-create-imenu-index
    semantic-type-relation-separator-character '(".")
    semantic-command-separation-character ";"
    ;; speedbar and imenu buckets name
diff --git a/lisp/cedet/semantic/wisent/javascript.el 
b/lisp/cedet/semantic/wisent/javascript.el
index 684eea1..1932f20 100644
--- a/lisp/cedet/semantic/wisent/javascript.el
+++ b/lisp/cedet/semantic/wisent/javascript.el
@@ -1,4 +1,4 @@
-;;; semantic/wisent/javascript.el --- javascript parser support
+;;; semantic/wisent/javascript.el --- javascript parser support  -*- 
lexical-binding: t; -*-
 
 ;; Copyright (C) 2005, 2009-2021 Free Software Foundation, Inc.
 
@@ -70,7 +70,7 @@ This function overrides `get-local-variables'."
   ;; Does javascript have identifiable local variables?
   nil)
 
-(define-mode-local-override semantic-tag-protection js-mode (tag &optional 
parent)
+(define-mode-local-override semantic-tag-protection js-mode (_tag &optional 
_parent)
   "Return protection information about TAG with optional PARENT.
 This function returns on of the following symbols:
    nil         - No special protection.  Language dependent.
@@ -85,7 +85,7 @@ The default behavior (if not overridden with `tag-protection'
 is to return a symbol based on type modifiers."
   nil)
 
-(define-mode-local-override semantic-analyze-scope-calculate-access js-mode 
(type scope)
+(define-mode-local-override semantic-analyze-scope-calculate-access js-mode 
(_type _scope)
   "Calculate the access class for TYPE as defined by the current SCOPE.
 Access is related to the :parents in SCOPE.  If type is a member of SCOPE
 then access would be `private'.  If TYPE is inherited by a member of SCOPE,
@@ -101,7 +101,7 @@ This is currently needed for the mozrepl omniscient 
database."
   (save-excursion
     (if point (goto-char point))
     (let* ((case-fold-search semantic-case-fold)
-          symlist tmp end)
+          tmp end) ;; symlist
       (with-syntax-table semantic-lex-syntax-table
        (save-excursion
          (when (looking-at "\\w\\|\\s_")
@@ -110,10 +110,11 @@ This is currently needed for the mozrepl omniscient 
database."
          (unless (re-search-backward "\\s-" (point-at-bol) t)
            (beginning-of-line))
          (setq tmp (buffer-substring-no-properties (point) end))
+         ;; (setq symlist
          (if (string-match "\\(.+\\)\\." tmp)
-           (setq symlist (list (match-string 1 tmp)
-                               (substring tmp (1+ (match-end 1)) (length 
tmp))))
-           (setq symlist (list tmp))))))))
+             (list (match-string 1 tmp)
+                   (substring tmp (1+ (match-end 1)) (length tmp)))
+           (list tmp)))))));; )
 
 ;;; Setup Function
 ;;
@@ -127,14 +128,14 @@ This is currently needed for the mozrepl omniscient 
database."
   (wisent-javascript-jv-wy--install-parser)
   (setq
    ;; Lexical Analysis
-   semantic-lex-analyzer 'javascript-lexer-jv
+   semantic-lex-analyzer #'javascript-lexer-jv
    semantic-lex-number-expression semantic-java-number-regexp
    ;; semantic-lex-depth nil ;; Full lexical analysis
    ;; Parsing
-   semantic-tag-expand-function 'wisent-javascript-jv-expand-tag
+   semantic-tag-expand-function #'wisent-javascript-jv-expand-tag
    ;; Environment
-   semantic-imenu-summary-function 'semantic-format-tag-name
-   imenu-create-index-function 'semantic-create-imenu-index
+   semantic-imenu-summary-function #'semantic-format-tag-name
+   imenu-create-index-function #'semantic-create-imenu-index
    semantic-command-separation-character ";"
    ))
 
diff --git a/lisp/cedet/semantic/wisent/python.el 
b/lisp/cedet/semantic/wisent/python.el
index 7769ad19..9ac4ed9 100644
--- a/lisp/cedet/semantic/wisent/python.el
+++ b/lisp/cedet/semantic/wisent/python.el
@@ -1,4 +1,4 @@
-;;; wisent-python.el --- Semantic support for Python
+;;; wisent-python.el --- Semantic support for Python  -*- lexical-binding: t; 
-*-
 
 ;; Copyright (C) 2002, 2004, 2006-2021 Free Software Foundation, Inc.
 
@@ -27,8 +27,6 @@
 
 ;;; Code:
 
-(require 'rx)
-
 ;; Try to load python support, but fail silently since it is only used
 ;; for optional functionality
 (require 'python nil t)
@@ -464,19 +462,19 @@ To be implemented for Python!  For now just return nil."
 (define-mode-local-override semantic-tag-include-filename python-mode (tag)
   "Return a suitable path for (some) Python imports."
   (let ((name (semantic-tag-name tag)))
-    (concat (mapconcat 'identity (split-string name "\\.") "/") ".py")))
+    (concat (mapconcat #'identity (split-string name "\\.") "/") ".py")))
 
 ;; Override ctxt-current-function/assignment defaults, since they do
 ;; not work properly with Python code, even leading to endless loops
 ;; (see bug #xxxxx).
-(define-mode-local-override semantic-ctxt-current-function python-mode 
(&optional point)
+(define-mode-local-override semantic-ctxt-current-function python-mode 
(&optional _point)
   "Return the current function call the cursor is in at POINT.
 The function returned is the one accepting the arguments that
 the cursor is currently in.  It will not return function symbol if the
 cursor is on the text representing that function."
   nil)
 
-(define-mode-local-override semantic-ctxt-current-assignment python-mode 
(&optional point)
+(define-mode-local-override semantic-ctxt-current-assignment python-mode 
(&optional _point)
   "Return the current assignment near the cursor at POINT.
 Return a list as per `semantic-ctxt-current-symbol'.
 Return nil if there is nothing relevant."
@@ -512,12 +510,12 @@ Shortens `code' tags, but passes through for others."
    semantic-type-relation-separator-character '(".")
    semantic-command-separation-character ";"
    ;; Parsing
-   semantic-tag-expand-function 'semantic-python-expand-tag
+   semantic-tag-expand-function #'semantic-python-expand-tag
 
    ;; Semantic to take over from the one provided by python.
    ;; The python one, if it uses the senator advice, will hang
    ;; Emacs unrecoverably.
-   imenu-create-index-function 'semantic-create-imenu-index
+   imenu-create-index-function #'semantic-create-imenu-index
 
    ;; I need a python guru to update this list:
    semantic-symbol->name-assoc-list-for-type-parts '((variable . "Variables")
diff --git a/lisp/cedet/semantic/wisent/wisent.el 
b/lisp/cedet/semantic/wisent/wisent.el
index 26cf87f..d205c0e 100644
--- a/lisp/cedet/semantic/wisent/wisent.el
+++ b/lisp/cedet/semantic/wisent/wisent.el
@@ -1,6 +1,6 @@
-;;; semantic/wisent/wisent.el --- GNU Bison for Emacs - Runtime
+;;; semantic/wisent/wisent.el --- GNU Bison for Emacs - Runtime  -*- 
lexical-binding: t; -*-
 
-;;; Copyright (C) 2002-2007, 2009-2021 Free Software Foundation, Inc.
+;; Copyright (C) 2002-2021  Free Software Foundation, Inc.
 
 ;; Author: David Ponce <david@dponce.com>
 ;; Created: 30 January 2002
@@ -139,7 +139,7 @@ POSITIONS are available."
   "Print a one-line message if `wisent-parse-verbose-flag' is set.
 Pass STRING and ARGS arguments to `message'."
   (and wisent-parse-verbose-flag
-       (apply 'message string args)))
+       (apply #'message string args)))
 
 ;;;; --------------------
 ;;;; The LR parser engine
@@ -147,13 +147,11 @@ Pass STRING and ARGS arguments to `message'."
 
 (defcustom wisent-parse-max-stack-size 500
   "The parser stack size."
-  :type 'integer
-  :group 'wisent)
+  :type 'integer)
 
 (defcustom wisent-parse-max-recover 3
   "Number of tokens to shift before turning off error status."
-  :type 'integer
-  :group 'wisent)
+  :type 'integer)
 
 (defvar wisent-discarding-token-functions nil
   "List of functions to be called when discarding a lexical token.
@@ -397,9 +395,9 @@ automaton has only one entry point."
             (wisent-error
              (format "Syntax error, unexpected %s, expecting %s"
                      (wisent-token-to-string wisent-input)
-                     (mapconcat 'wisent-item-to-string
+                     (mapconcat #'wisent-item-to-string
                                 (delq wisent-error-term
-                                      (mapcar 'car (cdr choices)))
+                                      (mapcar #'car (cdr choices)))
                                 ", "))))
         ;; Increment the error counter
         (setq wisent-nerrs (1+ wisent-nerrs))
diff --git a/lisp/cedet/srecode.el b/lisp/cedet/srecode.el
index aa4aa81..83e9754 100644
--- a/lisp/cedet/srecode.el
+++ b/lisp/cedet/srecode.el
@@ -1,6 +1,6 @@
 ;;; srecode.el --- Semantic buffer evaluator.  -*- lexical-binding: t -*-
 
-;;; Copyright (C) 2005, 2007-2021 Free Software Foundation, Inc.
+;; Copyright (C) 2005-2021  Free Software Foundation, Inc.
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
 ;; Keywords: codegeneration
diff --git a/lisp/cedet/srecode/args.el b/lisp/cedet/srecode/args.el
index 24c5f22..79d2700 100644
--- a/lisp/cedet/srecode/args.el
+++ b/lisp/cedet/srecode/args.el
@@ -1,4 +1,4 @@
-;;; srecode/args.el --- Provide some simple template arguments
+;;; srecode/args.el --- Provide some simple template arguments  -*- 
lexical-binding: t; -*-
 
 ;; Copyright (C) 2007-2021 Free Software Foundation, Inc.
 
diff --git a/lisp/cedet/srecode/compile.el b/lisp/cedet/srecode/compile.el
index 7146b64..36df1da 100644
--- a/lisp/cedet/srecode/compile.el
+++ b/lisp/cedet/srecode/compile.el
@@ -1,4 +1,4 @@
-;;; srecode/compile --- Compilation of srecode template files.
+;;; srecode/compile --- Compilation of srecode template files.  -*- 
lexical-binding: t; -*-
 
 ;; Copyright (C) 2005, 2007-2021 Free Software Foundation, Inc.
 
@@ -499,7 +499,7 @@ PROPS are additional properties that might need to be passed
 to the inserter constructor."
   ;;(message "Compile: %s %S" name props)
   (if (not key)
-      (apply 'srecode-template-inserter-variable name props)
+      (apply #'make-instance 'srecode-template-inserter-variable name props)
     (let ((classes (eieio-class-children 'srecode-template-inserter))
          (new nil))
       ;; Loop over the various subclasses and
@@ -510,7 +510,7 @@ to the inserter constructor."
        (when (and (not (class-abstract-p (car classes)))
                   (equal (oref-default (car classes) key) key))
          ;; Create the new class, and apply state.
-         (setq new (apply (car classes) name props))
+         (setq new (apply #'make-instance (car classes) name props))
          (srecode-inserter-apply-state new STATE)
          )
        (setq classes (cdr classes)))
diff --git a/lisp/cedet/srecode/cpp.el b/lisp/cedet/srecode/cpp.el
index 1b9610f..dc5e8da 100644
--- a/lisp/cedet/srecode/cpp.el
+++ b/lisp/cedet/srecode/cpp.el
@@ -1,4 +1,4 @@
-;;; srecode/cpp.el --- C++ specific handlers for Semantic Recoder
+;;; srecode/cpp.el --- C++ specific handlers for Semantic Recoder  -*- 
lexical-binding: t; -*-
 
 ;; Copyright (C) 2007, 2009-2021 Free Software Foundation, Inc.
 
@@ -44,7 +44,6 @@
 A dictionary entry of the named PREFIX_NAMESPACE with the value
 NAMESPACE:: is created for each namespace unless the current
 buffer contains a using NAMESPACE; statement."
-  :group 'srecode-cpp
   :type  '(repeat string))
 
 ;;; :c ARGUMENT HANDLING
@@ -165,7 +164,7 @@ specified in a C file."
       ;; when they make sense. My best bet would be
       ;; (semantic-tag-function-parent tag), but it is not there, when
       ;; the function is defined in the scope of a class.
-      (let ((member t)
+      (let (;; (member t)
            (templates (semantic-tag-get-attribute tag :template))
            (modifiers (semantic-tag-modifiers tag)))
 
@@ -186,7 +185,7 @@ specified in a C file."
 
        ;; When the function is a member function, it can have
        ;; additional modifiers.
-       (when member
+       (when t ;; member
 
          ;; For member functions, constness is called
          ;; 'methodconst-flag'.
diff --git a/lisp/cedet/srecode/ctxt.el b/lisp/cedet/srecode/ctxt.el
index 20334f9..c49237b 100644
--- a/lisp/cedet/srecode/ctxt.el
+++ b/lisp/cedet/srecode/ctxt.el
@@ -1,4 +1,4 @@
-;;; srecode/ctxt.el --- Derive a context from the source buffer.
+;;; srecode/ctxt.el --- Derive a context from the source buffer.  -*- 
lexical-binding: t; -*-
 
 ;; Copyright (C) 2007-2021 Free Software Foundation, Inc.
 
diff --git a/lisp/cedet/srecode/dictionary.el b/lisp/cedet/srecode/dictionary.el
index c1fe4b2..5da045e 100644
--- a/lisp/cedet/srecode/dictionary.el
+++ b/lisp/cedet/srecode/dictionary.el
@@ -1,4 +1,4 @@
-;;; srecode/dictionary.el --- Dictionary code for the semantic recoder.
+;;; srecode/dictionary.el --- Dictionary code for the semantic recoder.  -*- 
lexical-binding: t; -*-
 
 ;; Copyright (C) 2007-2021 Free Software Foundation, Inc.
 
@@ -443,8 +443,8 @@ The root dictionary is usually for a current or active 
insertion."
 ;; for use in converting the compound value into something insertable.
 
 (cl-defmethod srecode-compound-toString ((cp srecode-dictionary-compound-value)
-                                     function
-                                     dictionary)
+                                        _function
+                                        _dictionary)
   "Convert the compound dictionary value CP to a string.
 If FUNCTION is non-nil, then FUNCTION is somehow applied to an aspect
 of the compound value.  The FUNCTION could be a fraction
@@ -457,14 +457,15 @@ standard out is a buffer, and using `insert'."
   (eieio-object-name cp))
 
 (cl-defmethod srecode-dump ((cp srecode-dictionary-compound-value)
-                        &optional indent)
+                           &optional _indent)
   "Display information about this compound value."
   (princ (eieio-object-name cp))
   )
 
-(cl-defmethod srecode-compound-toString ((cp 
srecode-dictionary-compound-variable)
-                                     function
-                                     dictionary)
+(cl-defmethod srecode-compound-toString
+    ((cp srecode-dictionary-compound-variable)
+     _function
+     dictionary)
   "Convert the compound dictionary variable value CP into a string.
 FUNCTION and DICTIONARY are as for the baseclass."
   (require 'srecode/insert)
@@ -606,9 +607,9 @@ STATE is the current compiler state."
   (require 'srecode/find)
   (let* ((modesym major-mode)
         (start (current-time))
-        (junk (or (progn (srecode-load-tables-for-mode modesym)
-                         (srecode-get-mode-table modesym))
-                  (error "No table found for mode %S" modesym)))
+        (_ (or (progn (srecode-load-tables-for-mode modesym)
+                      (srecode-get-mode-table modesym))
+               (error "No table found for mode %S" modesym)))
         (dict (srecode-create-dictionary (current-buffer)))
         )
     (message "Creating a dictionary took %.2f seconds."
diff --git a/lisp/cedet/srecode/document.el b/lisp/cedet/srecode/document.el
index 0d1a4c0..270b80d 100644
--- a/lisp/cedet/srecode/document.el
+++ b/lisp/cedet/srecode/document.el
@@ -1,4 +1,4 @@
-;;; srecode/document.el --- Documentation (comment) generation
+;;; srecode/document.el --- Documentation (comment) generation  -*- 
lexical-binding: t; -*-
 
 ;; Copyright (C) 2008-2021 Free Software Foundation, Inc.
 
@@ -88,7 +88,6 @@ versions of names.  This is an alist with each element of the 
form:
  (MATCH . RESULT)
 MATCH is a regexp to match in the type field.
 RESULT is a string."
-  :group 'document
   :type '(repeat (cons (regexp :tag "Regexp")
                       (string :tag "Doc Text"))))
 
@@ -144,7 +143,6 @@ A string may end in a space, in which case, last-alist is 
searched to
 see how best to describe what can be returned.
 Doesn't always work correctly, but that is just because English
 doesn't always work correctly."
-  :group 'document
   :type '(repeat (cons (regexp :tag "Regexp")
                       (string :tag "Doc Text"))))
 
@@ -175,7 +173,6 @@ versions of names.  This is an alist with each element of 
the form:
  (MATCH . RESULT)
 MATCH is a regexp to match in the type field.
 RESULT is a string."
-  :group 'document
   :type '(repeat (cons (regexp :tag "Regexp")
                       (string :tag "Doc Text"))))
 
@@ -192,7 +189,6 @@ This is an alist with each element of the form:
  (MATCH . RESULT)
 MATCH is a regexp to match in the type field.
 RESULT is a string."
-  :group 'document
   :type '(repeat (cons (regexp :tag "Regexp")
                       (string :tag "Doc Text"))))
 
@@ -213,7 +209,6 @@ This is an alist with each element of the form:
 MATCH is a regexp to match in the type field.
 RESULT is a string, which can contain %s, which is replaced with
 `match-string' 1."
-  :group 'document
   :type '(repeat (cons (regexp :tag "Regexp")
                       (string :tag "Doc Text"))))
 
@@ -233,7 +228,6 @@ MATCH is a regexp to match in the type field.
 RESULT is a string of text to use to describe MATCH.
 When one is encountered, document-insert-parameters will automatically
 place this comment after the parameter name."
-  :group 'document
   :type '(repeat (cons (regexp :tag "Regexp")
                       (string :tag "Doc Text"))))
 
@@ -258,7 +252,6 @@ This is an alist with each element of the form:
  (MATCH . RESULT)
 MATCH is a regexp to match in the type field.
 RESULT is a string."
-  :group 'document
   :type '(repeat (cons (regexp :tag "Regexp")
                       (string :tag "Doc Text"))))
 
@@ -716,7 +709,7 @@ allocating something based on its type."
            (setq al (cdr al)))))
     news))
 
-(defun srecode-document-parameter-comment (param &optional commentlist)
+(defun srecode-document-parameter-comment (param &optional _commentlist)
   "Convert tag or string PARAM into a name,comment pair.
 Optional COMMENTLIST is list of previously existing comments to
 use instead in alist form.  If the name doesn't appear in the list of
diff --git a/lisp/cedet/srecode/el.el b/lisp/cedet/srecode/el.el
index 7e9dd10..974a4fa 100644
--- a/lisp/cedet/srecode/el.el
+++ b/lisp/cedet/srecode/el.el
@@ -1,4 +1,4 @@
-;;; srecode/el.el --- Emacs Lisp specific arguments
+;;; srecode/el.el --- Emacs Lisp specific arguments  -*- lexical-binding: t; 
-*-
 
 ;; Copyright (C) 2008-2021 Free Software Foundation, Inc.
 
diff --git a/lisp/cedet/srecode/expandproto.el 
b/lisp/cedet/srecode/expandproto.el
index cdb29d1..a40d5ae 100644
--- a/lisp/cedet/srecode/expandproto.el
+++ b/lisp/cedet/srecode/expandproto.el
@@ -1,4 +1,4 @@
-;;; srecode/expandproto.el --- Expanding prototypes.
+;;; srecode/expandproto.el --- Expanding prototypes.  -*- lexical-binding: t; 
-*-
 
 ;; Copyright (C) 2007, 2009-2021 Free Software Foundation, Inc.
 
diff --git a/lisp/cedet/srecode/extract.el b/lisp/cedet/srecode/extract.el
index 625b854..9e6a98f 100644
--- a/lisp/cedet/srecode/extract.el
+++ b/lisp/cedet/srecode/extract.el
@@ -1,4 +1,4 @@
-;;; srecode/extract.el --- Extract content from previously inserted macro.
+;;; srecode/extract.el --- Extract content from previously inserted macro.  
-*- lexical-binding: t; -*-
 
 ;; Copyright (C) 2008-2021 Free Software Foundation, Inc.
 
@@ -139,24 +139,24 @@ Uses STATE to maintain the current extraction state."
 
 ;;; Inserter Base Extractors
 ;;
-(cl-defmethod srecode-inserter-do-extract-p ((ins srecode-template-inserter))
+(cl-defmethod srecode-inserter-do-extract-p ((_ins srecode-template-inserter))
   "Return non-nil if this inserter can extract values."
   nil)
 
-(cl-defmethod srecode-inserter-extract ((ins srecode-template-inserter)
-                                    start end dict state)
+(cl-defmethod srecode-inserter-extract ((_ins srecode-template-inserter)
+                                       _start _end _dict _state)
   "Extract text from START/END and store in DICT.
 Return nil as this inserter will extract nothing."
   nil)
 
 ;;; Variable extractor is simple and can extract later.
 ;;
-(cl-defmethod srecode-inserter-do-extract-p ((ins 
srecode-template-inserter-variable))
+(cl-defmethod srecode-inserter-do-extract-p ((_ins 
srecode-template-inserter-variable))
   "Return non-nil if this inserter can extract values."
   'later)
 
 (cl-defmethod srecode-inserter-extract ((ins 
srecode-template-inserter-variable)
-                                    start end vdict state)
+                                       start end vdict _state)
   "Extract text from START/END and store in VDICT.
 Return t if something was extracted.
 Return nil if this inserter doesn't need to extract anything."
@@ -168,12 +168,12 @@ Return nil if this inserter doesn't need to extract 
anything."
 
 ;;; Section Inserter
 ;;
-(cl-defmethod srecode-inserter-do-extract-p ((ins 
srecode-template-inserter-section-start))
+(cl-defmethod srecode-inserter-do-extract-p ((_ins 
srecode-template-inserter-section-start))
   "Return non-nil if this inserter can extract values."
   'now)
 
 (cl-defmethod srecode-inserter-extract ((ins 
srecode-template-inserter-section-start)
-                                    start end indict state)
+                                       _start _end indict state)
   "Extract text from START/END and store in INDICT.
 Return the starting location of the first plain-text match.
 Return nil if nothing was extracted."
@@ -201,12 +201,12 @@ Return nil if nothing was extracted."
 
 ;;; Include Extractor must extract now.
 ;;
-(cl-defmethod srecode-inserter-do-extract-p ((ins 
srecode-template-inserter-include))
+(cl-defmethod srecode-inserter-do-extract-p ((_ins 
srecode-template-inserter-include))
   "Return non-nil if this inserter can extract values."
   'now)
 
 (cl-defmethod srecode-inserter-extract ((ins srecode-template-inserter-include)
-                                    start end dict state)
+                                       start _end dict state)
   "Extract text from START/END and store in DICT.
 Return the starting location of the first plain-text match.
 Return nil if nothing was extracted."
diff --git a/lisp/cedet/srecode/fields.el b/lisp/cedet/srecode/fields.el
index 71613bc..e65e319 100644
--- a/lisp/cedet/srecode/fields.el
+++ b/lisp/cedet/srecode/fields.el
@@ -1,4 +1,4 @@
-;;; srecode/fields.el --- Handling type-in fields in a buffer.
+;;; srecode/fields.el --- Handling type-in fields in a buffer.  -*- 
lexical-binding: t; -*-
 ;;
 ;; Copyright (C) 2009-2021 Free Software Foundation, Inc.
 ;;
@@ -193,7 +193,7 @@ If SET-TO is a string, then replace the text of OLAID with 
SET-TO."
   "Manage a buffer region in which fields exist.")
 
 (cl-defmethod initialize-instance ((ir srecode-template-inserted-region)
-                               &rest args)
+                                  &rest _args)
   "Initialize IR, capturing the active fields, and creating the overlay."
   ;; Fill in the fields
   (oset ir fields srecode-field-archive)
@@ -221,7 +221,7 @@ If SET-TO is a string, then replace the text of OLAID with 
SET-TO."
   (oset ir active-region ir)
 
   ;; Setup the post command hook.
-  (add-hook 'post-command-hook 'srecode-field-post-command t t)
+  (add-hook 'post-command-hook #'srecode-field-post-command t t)
   )
 
 (cl-defmethod srecode-delete ((ir srecode-template-inserted-region))
@@ -229,12 +229,11 @@ If SET-TO is a string, then replace the text of OLAID 
with SET-TO."
   ;; Clear us out of the baseclass.
   (oset ir active-region nil)
   ;; Clear our fields.
-  (mapc 'srecode-delete (oref ir fields))
+  (mapc #'srecode-delete (oref ir fields))
   ;; Call to our base
   (cl-call-next-method)
   ;; Clear our hook.
-  (remove-hook 'post-command-hook 'srecode-field-post-command t)
-  )
+  (remove-hook 'post-command-hook #'srecode-field-post-command t))
 
 (defsubst srecode-active-template-region ()
   "Return the active region for template fields."
@@ -246,7 +245,7 @@ If SET-TO is a string, then replace the text of OLAID with 
SET-TO."
        )
     (if (not ar)
        ;; Find a bug and fix it.
-       (remove-hook 'post-command-hook 'srecode-field-post-command t)
+       (remove-hook 'post-command-hook #'srecode-field-post-command t)
       (if (srecode-point-in-region-p ar)
          nil ;; Keep going
        ;; We moved out of the template.  Cancel the edits.
@@ -277,16 +276,16 @@ Try to use this to provide useful completion when 
available.")
 
 (defvar srecode-field-keymap
   (let ((km (make-sparse-keymap)))
-    (define-key km "\C-i" 'srecode-field-next)
-    (define-key km "\M-\C-i" 'srecode-field-prev)
-    (define-key km "\C-e" 'srecode-field-end)
-    (define-key km "\C-a" 'srecode-field-start)
-    (define-key km "\M-m" 'srecode-field-start)
-    (define-key km "\C-c\C-c" 'srecode-field-exit-ask)
+    (define-key km "\C-i" #'srecode-field-next)
+    (define-key km "\M-\C-i" #'srecode-field-prev)
+    (define-key km "\C-e" #'srecode-field-end)
+    (define-key km "\C-a" #'srecode-field-start)
+    (define-key km "\M-m" #'srecode-field-start)
+    (define-key km "\C-c\C-c" #'srecode-field-exit-ask)
     km)
   "Keymap applied to field overlays.")
 
-(cl-defmethod initialize-instance ((field srecode-field) &optional args)
+(cl-defmethod initialize-instance ((field srecode-field) &optional _args)
   "Initialize FIELD, being sure it archived."
   (add-to-list 'srecode-field-archive field t)
   (cl-call-next-method)
@@ -327,7 +326,7 @@ Try to use this to provide useful completion when 
available.")
 (defvar srecode-field-replication-max-size 100
   "Maximum size of a field before canceling replication.")
 
-(defun srecode-field-mod-hook (ol after start end &optional pre-len)
+(defun srecode-field-mod-hook (ol after _start _end &optional _pre-len)
   "Modification hook for the field overlay.
 OL is the overlay.
 AFTER is non-nil if it is called after the change.
@@ -374,7 +373,7 @@ AFTER is non-nil if it is called after the change.
 START and END are the bounds of the change.
 PRE-LEN is used in the after mode for the length of the changed text."
   (when after
-    (let* ((field (overlay-get ol 'srecode))
+    (let* (;; (field (overlay-get ol 'srecode))
           )
       (move-overlay ol (overlay-start ol) end)
       (srecode-field-mod-hook ol after start end pre-len))
diff --git a/lisp/cedet/srecode/filters.el b/lisp/cedet/srecode/filters.el
index 4a996cf..b76ce2c 100644
--- a/lisp/cedet/srecode/filters.el
+++ b/lisp/cedet/srecode/filters.el
@@ -1,4 +1,4 @@
-;;; srecode/filters.el --- Filters for use in template variables.
+;;; srecode/filters.el --- Filters for use in template variables.  -*- 
lexical-binding: t; -*-
 
 ;; Copyright (C) 2007-2021 Free Software Foundation, Inc.
 
diff --git a/lisp/cedet/srecode/find.el b/lisp/cedet/srecode/find.el
index aec73dc..1c208d0 100644
--- a/lisp/cedet/srecode/find.el
+++ b/lisp/cedet/srecode/find.el
@@ -1,4 +1,4 @@
-;;;; srecode/find.el --- Tools for finding templates in the database.
+;;;; srecode/find.el --- Tools for finding templates in the database.  -*- 
lexical-binding: t; -*-
 
 ;; Copyright (C) 2007-2021 Free Software Foundation, Inc.
 
@@ -58,17 +58,14 @@ See `srecode-get-maps' for more.
 APPNAME is the name of an application.  In this case,
 all template files for that application will be loaded."
   (let ((files
-        (if appname
-            (apply 'append
-                   (mapcar
+        (apply #'append
+               (mapcar
+                (if appname
                     (lambda (map)
                       (srecode-map-entries-for-app-and-mode map appname mmode))
-                    (srecode-get-maps)))
-          (apply 'append
-                 (mapcar
                   (lambda (map)
-                    (srecode-map-entries-for-mode map mmode))
-                  (srecode-get-maps)))))
+                    (srecode-map-entries-for-mode map mmode)))
+                (srecode-get-maps))))
        )
     ;; Don't recurse if we are already the 'default state.
     (when (not (eq mmode 'default))
@@ -112,8 +109,8 @@ If TAB is nil, then always return t."
 ;; Find a given template based on name, and features of the current
 ;; buffer.
 (cl-defmethod srecode-template-get-table ((tab srecode-template-table)
-                                      template-name &optional
-                                      context application)
+                                         template-name &optional
+                                         context _application)
   "Find in the template in table TAB, the template with TEMPLATE-NAME.
 Optional argument CONTEXT specifies that the template should part
 of a particular context.
@@ -218,7 +215,7 @@ tables that do not belong to an application will be 
searched."
 (defvar srecode-read-template-name-history nil
   "History for completing reads for template names.")
 
-(defun srecode-user-template-p (template)
+(defun srecode-user-template-p (_template)
   "Non-nil if TEMPLATE is intended for user insertion.
 Templates not matching this predicate are used for code
 generation or other internal purposes."
@@ -264,7 +261,7 @@ with `srecode-calculate-context'."
       ;; the prefix for the completing read
       (concat (nth 0 ctxt) ":"))))
 
-(defun srecode-read-template-name (prompt &optional initial hist default)
+(defun srecode-read-template-name (prompt &optional initial hist _default)
   "Completing read for Semantic Recoder template names.
 PROMPT is used to query for the name of the template desired.
 INITIAL is the initial string to use.
diff --git a/lisp/cedet/srecode/getset.el b/lisp/cedet/srecode/getset.el
index 1e48886..ce4c818 100644
--- a/lisp/cedet/srecode/getset.el
+++ b/lisp/cedet/srecode/getset.el
@@ -1,4 +1,4 @@
-;;; srecode/getset.el --- Package for inserting new get/set methods.
+;;; srecode/getset.el --- Package for inserting new get/set methods.  -*- 
lexical-binding: t; -*-
 
 ;; Copyright (C) 2007-2021 Free Software Foundation, Inc.
 
@@ -33,6 +33,8 @@
 (defvar srecode-insert-getset-fully-automatic-flag nil
   "Non-nil means accept choices srecode comes up with without asking.")
 
+(defvar srecode-semantic-selected-tag)
+
 ;;;###autoload
 (defun srecode-insert-getset (&optional class-in field-in)
   "Insert get/set methods for the current class.
diff --git a/lisp/cedet/srecode/java.el b/lisp/cedet/srecode/java.el
index 768d48a..0f0a80e 100644
--- a/lisp/cedet/srecode/java.el
+++ b/lisp/cedet/srecode/java.el
@@ -1,4 +1,4 @@
-;;; srecode/java.el --- Srecode Java support
+;;; srecode/java.el --- Srecode Java support  -*- lexical-binding: t; -*-
 
 ;; Copyright (C) 2009-2021 Free Software Foundation, Inc.
 
diff --git a/lisp/cedet/srecode/map.el b/lisp/cedet/srecode/map.el
index a94db0b..254b15e 100644
--- a/lisp/cedet/srecode/map.el
+++ b/lisp/cedet/srecode/map.el
@@ -1,4 +1,4 @@
-;;; srecode/map.el --- Manage a template file map
+;;; srecode/map.el --- Manage a template file map  -*- lexical-binding: t; -*-
 
 ;; Copyright (C) 2008-2021 Free Software Foundation, Inc.
 
@@ -245,7 +245,7 @@ Optional argument RESET forces a reset of the current map."
     (princ "\n")
     ))
 
-(defun srecode-map-file-still-valid-p (filename map)
+(defun srecode-map-file-still-valid-p (filename _map)
   "Return t if FILENAME should be in MAP still."
   (let ((valid nil))
     (and (file-exists-p filename)
@@ -407,7 +407,7 @@ Return non-nil if the map changed."
   "Global load path for SRecode template files."
   :group 'srecode
   :type '(repeat file)
-  :set 'srecode-map-load-path-set)
+  :set #'srecode-map-load-path-set)
 
 (provide 'srecode/map)
 
diff --git a/lisp/cedet/srecode/mode.el b/lisp/cedet/srecode/mode.el
index 159dc7a..9b1c849 100644
--- a/lisp/cedet/srecode/mode.el
+++ b/lisp/cedet/srecode/mode.el
@@ -1,4 +1,4 @@
-;;; srecode/mode.el --- Minor mode for managing and using SRecode templates
+;;; srecode/mode.el --- Minor mode for managing and using SRecode templates  
-*- lexical-binding: t; -*-
 
 ;; Copyright (C) 2008-2021 Free Software Foundation, Inc.
 
@@ -54,14 +54,14 @@
 (defvar srecode-prefix-map
   (let ((km (make-sparse-keymap)))
     ;; Basic template codes
-    (define-key km "/" 'srecode-insert)
-    (define-key km [insert] 'srecode-insert)
-    (define-key km "." 'srecode-insert-again)
-    (define-key km "E" 'srecode-edit)
+    (define-key km "/" #'srecode-insert)
+    (define-key km [insert] #'srecode-insert)
+    (define-key km "." #'srecode-insert-again)
+    (define-key km "E" #'srecode-edit)
     ;; Template indirect binding
     (let ((k ?a))
       (while (<= k ?z)
-       (define-key km (format "%c" k) 'srecode-bind-insert)
+       (define-key km (format "%c" k) #'srecode-bind-insert)
        (setq k (1+ k))))
     km)
   "Keymap used behind the srecode prefix key in srecode minor mode.")
@@ -141,16 +141,17 @@ non-nil if the minor mode is enabled.
   ;; this mode first.
   (if srecode-minor-mode
       (if (not (apply
-               'append
+               #'append
                (mapcar (lambda (map)
                          (srecode-map-entries-for-mode map major-mode))
                        (srecode-get-maps))))
          (setq srecode-minor-mode nil)
        ;; Else, we have success, do stuff
-       (add-hook 'cedet-m3-menu-do-hooks 'srecode-m3-items nil t)
-       )
-    (remove-hook 'cedet-m3-menu-do-hooks 'srecode-m3-items t)
-    )
+       ;; FIXME: Where are `cedet-m3-menu-do-hooks' nor `srecode-m3-items'?
+       (when (fboundp 'srecode-m3-items)
+         (add-hook 'cedet-m3-menu-do-hooks #'srecode-m3-items nil t)))
+    (when (fboundp 'srecode-m3-items)
+      (remove-hook 'cedet-m3-menu-do-hooks #'srecode-m3-items t)))
   ;; Run hooks if we are turning this on.
   (when srecode-minor-mode
     (run-hooks 'srecode-minor-mode-hook))
@@ -170,7 +171,7 @@ non-nil if the minor mode is enabled.
 
 ;;; Menu Filters
 ;;
-(defun srecode-minor-mode-templates-menu (menu-def)
+(defun srecode-minor-mode-templates-menu (_menu-def)
   "Create a menu item of cascading filters active for this mode.
 MENU-DEF is the menu to bind this into."
   ;; Doing this SEGVs Emacs on windows.
@@ -223,13 +224,11 @@ MENU-DEF is the menu to bind this into."
                          (if bind
                              (concat name "   (" bind ")")
                            name)
-                         `(lambda () (interactive)
-                            (srecode-insert (concat ,ctxt ":" ,name)))
+                         (lambda () (interactive)
+                           (srecode-insert (concat ctxt ":" name)))
                          t)))
 
-               (setcdr ctxtcons (cons
-                                 new
-                                 (cdr ctxtcons)))))
+               (push new (cdr ctxtcons))))
 
            (setq ltab (cdr ltab))))
        (setq subtab (cdr subtab)))
@@ -246,7 +245,7 @@ MENU-DEF is the menu to bind this into."
 (defvar srecode-minor-mode-generators nil
   "List of code generators to be displayed in the srecoder menu.")
 
-(defun srecode-minor-mode-generate-menu (menu-def)
+(defun srecode-minor-mode-generate-menu (_menu-def)
   "Create a menu item of cascading filters active for this mode.
 MENU-DEF is the menu to bind this into."
   ;; Doing this SEGVs Emacs on windows.
diff --git a/lisp/cedet/srecode/srt-mode.el b/lisp/cedet/srecode/srt-mode.el
index bbe1e5e..7157915 100644
--- a/lisp/cedet/srecode/srt-mode.el
+++ b/lisp/cedet/srecode/srt-mode.el
@@ -1,4 +1,4 @@
-;;; srecode/srt-mode.el --- Major mode for writing screcode macros
+;;; srecode/srt-mode.el --- Major mode for writing screcode macros  -*- 
lexical-binding: t; -*-
 
 ;; Copyright (C) 2005, 2007-2021 Free Software Foundation, Inc.
 
@@ -181,9 +181,9 @@ we can tell font lock about them.")
 
 (defvar srecode-template-mode-map
   (let ((km (make-sparse-keymap)))
-    (define-key km "\C-c\C-c" 'srecode-compile-templates)
-    (define-key km "\C-c\C-m" 'srecode-macro-help)
-    (define-key km "/" 'srecode-self-insert-complete-end-macro)
+    (define-key km "\C-c\C-c" #'srecode-compile-templates)
+    (define-key km "\C-c\C-m" #'srecode-macro-help)
+    (define-key km "/" #'srecode-self-insert-complete-end-macro)
     km)
   "Keymap used in srecode mode.")
 
@@ -205,7 +205,7 @@ we can tell font lock about them.")
                 ((?_ . "w") (?- . "w")))))
 
 ;;;###autoload
-(defalias 'srt-mode 'srecode-template-mode)
+(defalias 'srt-mode #'srecode-template-mode)
 
 ;;; Template Commands
 ;;
@@ -436,7 +436,7 @@ Moves to the end of one named section."
     (when point (goto-char (point)))
     (let* ((tag (semantic-current-tag))
           (args (semantic-tag-function-arguments tag))
-          (argsym (mapcar 'intern args))
+          (argsym (mapcar #'intern args))
           (argvars nil)
           ;; Create a temporary dictionary in which the
           ;; arguments can be resolved so we can extract
@@ -475,7 +475,7 @@ section or ? for an ask variable."
          (ee (regexp-quote (srecode-template-get-escape-end)))
          (start (point))
          (macrostart nil)
-         (raw nil)
+         ;; (raw nil)
          )
       (when (and tag (semantic-tag-of-class-p tag 'function)
                 (srecode-in-macro-p point)
@@ -627,7 +627,7 @@ section or ? for an ask variable."
        context-return)))
 
 (define-mode-local-override semantic-analyze-possible-completions
-  srecode-template-mode (context &rest flags)
+  srecode-template-mode (context &rest _flags)
   "Return a list of possible completions based on NONTEXT."
   (with-current-buffer (oref context buffer)
     (let* ((prefix (car (last (oref context prefix))))
diff --git a/lisp/cedet/srecode/srt.el b/lisp/cedet/srecode/srt.el
index e222997..161b510 100644
--- a/lisp/cedet/srecode/srt.el
+++ b/lisp/cedet/srecode/srt.el
@@ -1,4 +1,4 @@
-;;; srecode/srt.el --- argument handlers for SRT files
+;;; srecode/srt.el --- argument handlers for SRT files  -*- lexical-binding: 
t; -*-
 
 ;; Copyright (C) 2008-2021 Free Software Foundation, Inc.
 
@@ -43,7 +43,7 @@ DEFAULT is the default if RET is hit."
         (currfcn (semantic-current-tag))
         )
     (srecode-resolve-argument-list
-     (mapcar 'read
+     (mapcar #'read
             (semantic-tag-get-attribute currfcn :arguments))
      newdict)
 
@@ -56,7 +56,7 @@ DEFAULT is the default if RET is hit."
 (defvar srecode-read-major-mode-history nil
   "History for `srecode-read-variable-name'.")
 
-(defun srecode-read-major-mode-name (prompt &optional initial hist default)
+(defun srecode-read-major-mode-name (prompt &optional initial hist _default)
   "Read in the name of a desired `major-mode'.
 PROMPT is the prompt to use.
 INITIAL is the initial string.
@@ -64,7 +64,7 @@ HIST is the history value, otherwise 
`srecode-read-variable-name-history'
      is used.
 DEFAULT is the default if RET is hit."
   (completing-read prompt obarray
-                  (lambda (s) (string-match "-mode$" (symbol-name s)))
+                  (lambda (s) (string-match "-mode\\'" (symbol-name s)))
                   nil initial (or hist 'srecode-read-major-mode-history))
   )
 
diff --git a/lisp/cedet/srecode/table.el b/lisp/cedet/srecode/table.el
index 60a466f..7ce5cc7 100644
--- a/lisp/cedet/srecode/table.el
+++ b/lisp/cedet/srecode/table.el
@@ -1,4 +1,4 @@
-;;; srecode/table.el --- Tables of Semantic Recoders
+;;; srecode/table.el --- Tables of Semantic Recoders  -*- lexical-binding: t; 
-*-
 
 ;; Copyright (C) 2007-2021 Free Software Foundation, Inc.
 
@@ -169,7 +169,7 @@ calculate all inherited templates from parent modes."
                                      :modetables nil
                                      :tables nil)))
        ;; Save this new mode table in that mode's variable.
-       (eval `(setq-mode-local ,mode srecode-table ,new))
+       (eval `(setq-mode-local ,mode srecode-table ,new) t)
 
        new))))
 
@@ -184,7 +184,7 @@ INIT are the initialization parameters for the new template 
table."
   (let* ((mt (srecode-make-mode-table mode))
         (old (srecode-mode-table-find mt file))
         (attr (file-attributes file))
-        (new (apply 'srecode-template-table
+        (new (apply #'srecode-template-table
                     (file-name-nondirectory file)
                     :file file
                     :filesize (file-attribute-size attr)
diff --git a/lisp/cedet/srecode/template.el b/lisp/cedet/srecode/template.el
index e9e5115..1f6f0d3 100644
--- a/lisp/cedet/srecode/template.el
+++ b/lisp/cedet/srecode/template.el
@@ -1,4 +1,4 @@
-;;; srecode/template.el --- SRecoder template language parser support.
+;;; srecode/template.el --- SRecoder template language parser support.  -*- 
lexical-binding: t; -*-
 
 ;; Copyright (C) 2005, 2007-2021 Free Software Foundation, Inc.
 
@@ -49,11 +49,11 @@
 
   (setq
    ;; Lexical Analysis
-   semantic-lex-analyzer 'wisent-srecode-template-lexer
+   semantic-lex-analyzer #'wisent-srecode-template-lexer
    ;; Parsing
    ;; Environment
-   semantic-imenu-summary-function 'semantic-format-tag-name
-   imenu-create-index-function 'semantic-create-imenu-index
+   semantic-imenu-summary-function #'semantic-format-tag-name
+   imenu-create-index-function #'semantic-create-imenu-index
    semantic-command-separation-character "\n"
    semantic-lex-comment-regex ";;"
    ;; Speedbar
diff --git a/lisp/cedet/srecode/texi.el b/lisp/cedet/srecode/texi.el
index 892ae4e..1312a55 100644
--- a/lisp/cedet/srecode/texi.el
+++ b/lisp/cedet/srecode/texi.el
@@ -1,4 +1,4 @@
-;;; srecode/texi.el --- Srecode texinfo support.
+;;; srecode/texi.el --- Srecode texinfo support.  -*- lexical-binding: t; -*-
 
 ;; Copyright (C) 2008-2021 Free Software Foundation, Inc.
 
@@ -224,7 +224,7 @@ Takes a few very generic guesses as to what the formatting 
is."
     ;; Return our modified doc string.
     docstring))
 
-(defun srecode-texi-massage-to-texinfo (tag buffer string)
+(defun srecode-texi-massage-to-texinfo (_tag buffer string)
   "Massage TAG's documentation from BUFFER as STRING.
 This is to take advantage of TeXinfo's markup symbols."
   (save-excursion
diff --git a/lisp/cmuscheme.el b/lisp/cmuscheme.el
index 772891d..d43cdb1 100644
--- a/lisp/cmuscheme.el
+++ b/lisp/cmuscheme.el
@@ -421,7 +421,7 @@ in the next one.")
 
 (defun scheme-load-file (file-name)
   "Load a Scheme file FILE-NAME into the inferior Scheme process."
-  (interactive (comint-get-source "Load Scheme file: " scheme-prev-l/c-dir/file
+  (interactive (comint-get-source "Load Scheme file" scheme-prev-l/c-dir/file
                                  scheme-source-modes t)) ; t because `load'
                                                           ; needs an exact name
   (comint-check-source file-name) ; Check to see if buffer needs saved.
@@ -433,7 +433,7 @@ in the next one.")
 
 (defun scheme-compile-file (file-name)
   "Compile a Scheme file FILE-NAME in the inferior Scheme process."
-  (interactive (comint-get-source "Compile Scheme file: "
+  (interactive (comint-get-source "Compile Scheme file"
                                  scheme-prev-l/c-dir/file
                                  scheme-source-modes
                                  nil)) ; nil because COMPILE doesn't
diff --git a/lisp/comint.el b/lisp/comint.el
index 57df6bf..b04d404 100644
--- a/lisp/comint.el
+++ b/lisp/comint.el
@@ -104,6 +104,7 @@
 (require 'ring)
 (require 'ansi-color)
 (require 'regexp-opt)                   ;For regexp-opt-charset.
+(eval-when-compile (require 'subr-x))
 
 ;; Buffer Local Variables:
 ;;============================================================================
@@ -365,23 +366,25 @@ This variable is buffer-local."
 ;; OpenBSD doas prints "doas (user@host) password:".
 ;; See ert test `comint-test-password-regexp'.
 (defcustom comint-password-prompt-regexp
+  ;; When extending this, please also add a corresponding test where
+  ;; possible (see `comint-testsuite-password-strings').
   (concat
    "\\(^ *\\|"
    (regexp-opt
     '("Enter" "enter" "Enter same" "enter same" "Enter the" "enter the"
       "Enter Auth" "enter auth" "Old" "old" "New" "new" "'s" "login"
       "Kerberos" "CVS" "UNIX" " SMB" "LDAP" "PEM" "SUDO"
-      "[sudo]" "doas" "Repeat" "Bad" "Retype")
+      "[sudo]" "doas" "Repeat" "Bad" "Retype" "Verify")
     t)
    ;; Allow for user name to precede password equivalent (Bug#31075).
    " +.*\\)"
    "\\(?:" (regexp-opt password-word-equivalents) "\\|Response\\)"
    "\\(?:\\(?:, try\\)? *again\\| (empty for no passphrase)\\| (again)\\)?"
    ;; "[[:alpha:]]" used to be "for", which fails to match non-English.
-   "\\(?: [[:alpha:]]+ .+\\)?[[:blank:]]*[::៖][[:blank:]]*\\'")
+   "\\(?: [[:alpha:]]+ .+\\)?[[:blank:]]*[::៖][[:space:]]*\\'")
   "Regexp matching prompts for passwords in the inferior process.
 This is used by `comint-watch-for-password-prompt'."
-  :version "27.1"
+  :version "28.1"
   :type 'regexp
   :group 'comint)
 
@@ -2430,12 +2433,11 @@ This function could be in the list 
`comint-output-filter-functions'."
   (when (let ((case-fold-search t))
          (string-match comint-password-prompt-regexp
                         (replace-regexp-in-string "\r" "" string)))
-    (when (string-match "^[ \n\r\t\v\f\b\a]+" string)
-      (setq string (replace-match "" t t string)))
     (let ((comint--prompt-recursion-depth (1+ comint--prompt-recursion-depth)))
       (if (> comint--prompt-recursion-depth 10)
           (message "Password prompt recursion too deep")
-        (comint-send-invisible string)))))
+        (comint-send-invisible
+         (string-trim string "[ \n\r\t\v\f\b\a]+" "\n+"))))))
 
 ;; Low-level process communication
 
@@ -2944,7 +2946,7 @@ two arguments are used for determining defaults.)  If 
MUSTMATCH-P is true,
 then the filename reader will only accept a file that exists.
 
 A typical use:
- (interactive (comint-get-source \"Compile file: \" prev-lisp-dir/file
+ (interactive (comint-get-source \"Compile file\" prev-lisp-dir/file
                                  \\='(lisp-mode) t))"
   (let* ((def (comint-source-default prev-dir/file source-modes))
         (stringfile (comint-extract-string))
@@ -2957,9 +2959,7 @@ A typical use:
                     (car def)))
         (deffile (if sfile-p (file-name-nondirectory stringfile)
                     (cdr def)))
-        (ans (read-file-name (if deffile (format "%s(default %s) "
-                                                 prompt    deffile)
-                                prompt)
+        (ans (read-file-name (format-prompt prompt deffile)
                              defdir
                              (concat defdir deffile)
                              mustmatch-p)))
diff --git a/lisp/completion.el b/lisp/completion.el
index da2fb38..dc0af36 100644
--- a/lisp/completion.el
+++ b/lisp/completion.el
@@ -1,7 +1,6 @@
-;;; completion.el --- dynamic word-completion code
+;;; completion.el --- dynamic word-completion code  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 1990, 1993, 1995, 1997, 2001-2021 Free Software
-;; Foundation, Inc.
+;; Copyright (C) 1990-2021 Free Software Foundation, Inc.
 
 ;; Maintainer: emacs-devel@gnu.org
 ;; Keywords: abbrev convenience
@@ -286,62 +285,52 @@
 (defcustom enable-completion t
   "Non-nil means enable recording and saving of completions.
 If nil, no new words are added to the database or saved to the init file."
-  :type 'boolean
-  :group 'completion)
+  :type 'boolean)
 
 (defcustom save-completions-flag t
   "Non-nil means save most-used completions when exiting Emacs.
 See also `save-completions-retention-time'."
-  :type 'boolean
-  :group 'completion)
+  :type 'boolean)
 
 (defcustom save-completions-file-name
   (locate-user-emacs-file "completions" ".completions")
   "The filename to save completions to."
-  :type 'file
-  :group 'completion)
+  :type 'file)
 
 (defcustom save-completions-retention-time 336
   "Discard a completion if unused for this many hours.
 \(1 day = 24, 1 week = 168).  If this is 0, non-permanent completions
 will not be saved unless these are used.  Default is two weeks."
-  :type 'integer
-  :group 'completion)
+  :type 'integer)
 
 (defcustom completion-on-separator-character nil
   "Non-nil means separator characters mark previous word as used.
 This means the word will be saved as a completion."
-  :type 'boolean
-  :group 'completion)
+  :type 'boolean)
 
 (defcustom completions-file-versions-kept kept-new-versions
   "Number of versions to keep for the saved completions file."
-  :type 'integer
-  :group 'completion)
+  :type 'integer)
 
 (defcustom completion-prompt-speed-threshold 4800
   "Minimum output speed at which to display next potential completion."
-  :type 'integer
-  :group 'completion)
+  :type 'integer)
 
 (defcustom completion-cdabbrev-prompt-flag nil
   "If non-nil, the next completion prompt does a cdabbrev search.
 This can be time consuming."
-  :type 'boolean
-  :group 'completion)
+  :type 'boolean)
 
 (defcustom completion-search-distance 15000
   "How far to search in the buffer when looking for completions.
 In number of characters.  If nil, search the whole buffer."
-  :type 'integer
-  :group 'completion)
+  :type 'integer)
 
 (defcustom completions-merging-modes '(lisp c)
   "List of modes {`c' or `lisp'} for automatic completions merging.
 Definitions from visited files which have these modes
 are automatically added to the completion database."
-  :type '(set (const lisp) (const c))
-  :group 'completion)
+  :type '(set (const lisp) (const c)))
 
 ;;(defvar *completion-auto-save-period* 1800
 ;;  "The period in seconds to wait for emacs to be idle before autosaving
@@ -950,9 +939,9 @@ Each symbol is bound to a single completion entry.")
 
 ;; READER Macros
 
-(defalias 'cmpl-prefix-entry-head 'car)
+(defalias 'cmpl-prefix-entry-head #'car)
 
-(defalias 'cmpl-prefix-entry-tail 'cdr)
+(defalias 'cmpl-prefix-entry-tail #'cdr)
 
 ;; WRITER Macros
 
@@ -978,31 +967,27 @@ Each symbol is bound to a single completion entry.")
   (setq cmpl-prefix-obarray (make-vector cmpl-obarray-length 0))
   (setq cmpl-obarray (make-vector cmpl-obarray-length 0)))
 
-(defvar completions-list-return-value)
-
 (defun list-all-completions ()
   "Return a list of all the known completion entries."
-  (let ((completions-list-return-value nil))
-    (mapatoms 'list-all-completions-1 cmpl-prefix-obarray)
-    completions-list-return-value))
-
-(defun list-all-completions-1 (prefix-symbol)
-  (if (boundp prefix-symbol)
-      (setq completions-list-return-value
-           (append (cmpl-prefix-entry-head (symbol-value prefix-symbol))
-                   completions-list-return-value))))
-
-(defun list-all-completions-by-hash-bucket ()
+  (let ((return-value nil))
+    (mapatoms (lambda (prefix-symbol)
+                (if (boundp prefix-symbol)
+                    (setq return-value
+                         (append (cmpl-prefix-entry-head
+                                  (symbol-value prefix-symbol))
+                                 return-value))))
+             cmpl-prefix-obarray)
+    return-value))
+
+(defun list-all-completions-by-hash-bucket () ;FIXME: Unused!
   "Return list of lists of known completion entries, organized by hash bucket."
-  (let ((completions-list-return-value nil))
-    (mapatoms 'list-all-completions-by-hash-bucket-1 cmpl-prefix-obarray)
-    completions-list-return-value))
-
-(defun list-all-completions-by-hash-bucket-1 (prefix-symbol)
-  (if (boundp prefix-symbol)
-      (setq completions-list-return-value
-           (cons (cmpl-prefix-entry-head (symbol-value prefix-symbol))
-                 completions-list-return-value))))
+  (let ((return-value nil))
+    (mapatoms (lambda (prefix-symbol)
+                (if (boundp prefix-symbol)
+                    (push (cmpl-prefix-entry-head (symbol-value prefix-symbol))
+                         return-value)))
+             cmpl-prefix-obarray)
+    return-value))
 
 
 ;;-----------------------------------------------
@@ -2155,7 +2140,6 @@ TYPE is the type of the wrapper to be added.  Can be 
:before or :under."
 (define-minor-mode dynamic-completion-mode
   "Toggle dynamic word-completion on or off."
   :global t
-  :group 'completion
   ;; This is always good, not specific to dynamic-completion-mode.
   (define-key function-key-map [C-return] [?\C-\r])
 
@@ -2239,7 +2223,7 @@ TYPE is the type of the wrapper to be added.  Can be 
:before or :under."
 (completion-def-wrapper 'delete-backward-char-untabify :backward)
 
 ;; Old name, non-namespace-clean.
-(defalias 'initialize-completions 'completion-initialize)
+(defalias 'initialize-completions #'completion-initialize)
 
 (provide 'completion)
 
diff --git a/lisp/cus-start.el b/lisp/cus-start.el
index c0a4a6d..b7afef6 100644
--- a/lisp/cus-start.el
+++ b/lisp/cus-start.el
@@ -36,7 +36,7 @@
 (defun minibuffer-prompt-properties--setter (symbol value)
   (set-default symbol value)
   (if (memq 'cursor-intangible value)
-      (add-hook 'minibuffer-setup-hook 'cursor-intangible-mode)
+      (add-hook 'minibuffer-setup-hook #'cursor-intangible-mode)
     ;; Removing it is a bit trickier since it could have been added by someone
     ;; else as well, so let's just not bother.
     ))
@@ -302,6 +302,7 @@ Leaving \"Default\" unchecked is equivalent with specifying 
a default of
             ;; fns.c
             (use-dialog-box menu boolean "21.1")
             (use-file-dialog menu boolean "22.1")
+            (use-short-answers menu boolean "28.1")
             (focus-follows-mouse
               frames (choice
                       (const :tag "Off (nil)" :value nil)
diff --git a/lisp/custom.el b/lisp/custom.el
index 8338107..85e5d65 100644
--- a/lisp/custom.el
+++ b/lisp/custom.el
@@ -1200,6 +1200,32 @@ property `theme-feature' (which is usually a symbol 
created by
   (custom-check-theme theme)
   (provide (get theme 'theme-feature)))
 
+(defun require-theme (feature &optional noerror)
+  "Load FEATURE from a file along `custom-theme-load-path'.
+
+This function is like `require', but searches along
+`custom-theme-load-path' instead of `load-path'.  It can be used
+by Custom themes to load supporting Lisp files when `require' is
+unsuitable.
+
+If FEATURE is not already loaded, search for a file named FEATURE
+with an added `.elc' or `.el' suffix, in that order, in the
+directories specified by `custom-theme-load-path'.
+
+Return FEATURE if the file is successfully found and loaded, or
+if FEATURE was already loaded.  If the file fails to load, signal
+an error.  If optional argument NOERROR is non-nil, return nil
+instead of signaling an error.  If the file loads but does not
+provide FEATURE, signal an error.  This cannot be suppressed."
+  (cond
+   ((featurep feature) feature)
+   ((let* ((path (custom-theme--load-path))
+           (file (locate-file (symbol-name feature) path '(".elc" ".el"))))
+      (and file (require feature (file-name-sans-extension file) noerror))))
+   ((not noerror)
+    (signal 'file-missing `("Cannot open load file" "No such file or directory"
+                            ,(symbol-name feature))))))
+
 (defcustom custom-safe-themes '(default)
   "Themes that are considered safe to load.
 If the value is a list, each element should be either the SHA-256
diff --git a/lisp/dired-aux.el b/lisp/dired-aux.el
index a94bdf5..d5f4910 100644
--- a/lisp/dired-aux.el
+++ b/lisp/dired-aux.el
@@ -1072,8 +1072,13 @@ To kill an entire subdirectory \(without killing its 
line in the
 parent directory), go to its directory header line and use this
 command with a prefix argument (the value does not matter).
 
-To undo the killing, the undo command can be used as normally."
-  ;; Returns count of killed lines.  FMT="" suppresses message.
+To undo the killing, the undo command can be used as normally.
+
+This function returns the number of killed lines.
+
+FMT is a format string used for messaging the user about the
+killed lines, and defaults to \"Killed %d line%s.\" if not
+present.  A FMT of \"\" will suppress the messaging."
   (interactive "P")
   (if arg
       (if (dired-get-subdir)
diff --git a/lisp/dired-x.el b/lisp/dired-x.el
index 5a52ecc..5f31bc4 100644
--- a/lisp/dired-x.el
+++ b/lisp/dired-x.el
@@ -236,8 +236,6 @@ to nil: a pipe using `zcat' or `gunzip -c' will be used."
 
 ;;; MENU BINDINGS
 
-(require 'easymenu)
-
 (when-let ((menu (lookup-key dired-mode-map [menu-bar])))
   (easy-menu-add-item menu '("Operate")
                       ["Find Files" dired-do-find-marked-files
@@ -447,7 +445,7 @@ If it is `no-dir', omitting is much faster, but you can 
only match
 against the non-directory part of the file name.  Set it to nil if you
 need to match the entire file name.")
 
-;; \017=^O for Omit - other packages can chose other control characters.
+;; \017=^O for Omit - other packages can choose other control characters.
 (defvar dired-omit-marker-char ?\017
   "Temporary marker used by Dired-Omit.
 Should never be used as marker by the user or other packages.")
diff --git a/lisp/dired.el b/lisp/dired.el
index 553fb64..11df93e 100644
--- a/lisp/dired.el
+++ b/lisp/dired.el
@@ -60,10 +60,15 @@
 May contain all other options that don't contradict `-l';
 may contain even `F', `b', `i' and `s'.  See also the variable
 `dired-ls-F-marks-symlinks' concerning the `F' switch.
+
+If you have files with names with embedded newline characters, adding
+`b' to the switches will allow Dired to handle those files better.
+
 Options that include embedded whitespace must be quoted
 like this: \"--option=value with spaces\"; you can use
 `combine-and-quote-strings' to produce the correct quoting of
 each option.
+
 On systems such as MS-DOS and MS-Windows, which use `ls' emulation in Lisp,
 some of the `ls' switches are not supported; see the doc string of
 `insert-directory' in `ls-lisp.el' for more details."
@@ -1961,328 +1966,217 @@ Do so according to the former subdir alist 
OLD-SUBDIR-ALIST."
     (define-key map ":s" 'epa-dired-do-sign)
     (define-key map ":e" 'epa-dired-do-encrypt)
 
-    ;; Make menu bar items.
-
     ;; No need to do this, now that top-level items are fewer.
     ;;;;
     ;; Get rid of the Edit menu bar item to save space.
     ;(define-key map [menu-bar edit] 'undefined)
 
-    (define-key map [menu-bar subdir]
-      (cons "Subdir" (make-sparse-keymap "Subdir")))
-
-    (define-key map [menu-bar subdir hide-all]
-      '(menu-item "Hide All" dired-hide-all
-                 :help "Hide all subdirectories, leave only header lines"))
-    (define-key map [menu-bar subdir hide-subdir]
-      '(menu-item "Hide/UnHide Subdir" dired-hide-subdir
-                 :help "Hide or unhide current directory listing"))
-    (define-key map [menu-bar subdir tree-down]
-      '(menu-item "Tree Down" dired-tree-down
-                 :help "Go to first subdirectory header down the tree"))
-    (define-key map [menu-bar subdir tree-up]
-      '(menu-item "Tree Up" dired-tree-up
-                 :help "Go to first subdirectory header up the tree"))
-    (define-key map [menu-bar subdir up]
-      '(menu-item "Up Directory" dired-up-directory
-                 :help "Edit the parent directory"))
-    (define-key map [menu-bar subdir prev-subdir]
-      '(menu-item "Prev Subdir" dired-prev-subdir
-                 :help "Go to previous subdirectory header line"))
-    (define-key map [menu-bar subdir next-subdir]
-      '(menu-item "Next Subdir" dired-next-subdir
-                 :help "Go to next subdirectory header line"))
-    (define-key map [menu-bar subdir prev-dirline]
-      '(menu-item "Prev Dirline" dired-prev-dirline
-                 :help "Move to next directory-file line"))
-    (define-key map [menu-bar subdir next-dirline]
-      '(menu-item "Next Dirline" dired-next-dirline
-                 :help "Move to previous directory-file line"))
-    (define-key map [menu-bar subdir insert]
-      '(menu-item "Insert This Subdir" dired-maybe-insert-subdir
-                 :help "Insert contents of subdirectory"
-                 :enable (let ((f (dired-get-filename nil t)))
-                           (and f (file-directory-p f)))))
-    (define-key map [menu-bar immediate]
-      (cons "Immediate" (make-sparse-keymap "Immediate")))
-
-    (define-key map
-      [menu-bar immediate image-dired-dired-display-external]
-      '(menu-item "Display Image Externally" image-dired-dired-display-external
-                  :help "Display image in external viewer"))
-    (define-key map
-      [menu-bar immediate image-dired-dired-display-image]
-      '(menu-item "Display Image" image-dired-dired-display-image
-                  :help "Display sized image in a separate window"))
-    (define-key map
-      [menu-bar immediate image-dired-dired-toggle-marked-thumbs]
-      '(menu-item "Toggle Image Thumbnails in This Buffer" 
image-dired-dired-toggle-marked-thumbs
-                  :help "Add or remove image thumbnails in front of marked 
file names"))
-
-    (define-key map [menu-bar immediate hide-details]
-      '(menu-item "Hide Details" dired-hide-details-mode
-                 :help "Hide details in buffer"
-                 :button (:toggle . dired-hide-details-mode)))
-    (define-key map [menu-bar immediate revert-buffer]
-      '(menu-item "Refresh" revert-buffer
-                 :help "Update contents of shown directories"))
-    (define-key map [menu-bar immediate dired-number-of-marked-files]
-      '(menu-item "#Marked Files" dired-number-of-marked-files
-                 :help "Display the number and size of the marked files"))
-
-    (define-key map [menu-bar immediate dashes]
-      '("--"))
-
-    (define-key map [menu-bar immediate isearch-filenames-regexp]
-      '(menu-item "Isearch Regexp in File Names..." 
dired-isearch-filenames-regexp
-                 :help "Incrementally search for regexp in file names only"))
-    (define-key map [menu-bar immediate isearch-filenames]
-      '(menu-item "Isearch in File Names..." dired-isearch-filenames
-                 :help "Incrementally search for string in file names only."))
-    (define-key map [menu-bar immediate compare-directories]
-      '(menu-item "Compare Directories..." dired-compare-directories
-                 :help "Mark files with different attributes in two Dired 
buffers"))
-    (define-key map [menu-bar immediate backup-diff]
-      '(menu-item "Compare with Backup" dired-backup-diff
-                 :help "Diff file at cursor with its latest backup"))
-    (define-key map [menu-bar immediate diff]
-      '(menu-item "Diff..." dired-diff
-                 :help "Compare file at cursor with another file"))
-    (define-key map [menu-bar immediate view]
-      '(menu-item "View This File" dired-view-file
-                 :help "Examine file at cursor in read-only mode"))
-    (define-key map [menu-bar immediate display]
-      '(menu-item "Display in Other Window" dired-display-file
-                 :help "Display file at cursor in other window"))
-    (define-key map [menu-bar immediate find-file-other-window]
-      '(menu-item "Find in Other Window" dired-find-file-other-window
-                 :help "Edit file at cursor in other window"))
-    (define-key map [menu-bar immediate find-file]
-      '(menu-item "Find This File" dired-find-file
-                 :help "Edit file at cursor"))
-    (define-key map [menu-bar immediate create-directory]
-      '(menu-item "Create Directory..." dired-create-directory
-                 :help "Create a directory"))
-    (define-key map [menu-bar immediate create-empty-file]
-      '(menu-item "Create Empty file..." dired-create-empty-file
-                 :help "Create an empty file"))
-    (define-key map [menu-bar immediate wdired-mode]
-      '(menu-item "Edit File Names" wdired-change-to-wdired-mode
-                 :help "Put a Dired buffer in a mode in which filenames are 
editable"
-                 :keys "C-x C-q"
-                 :filter (lambda (x) (if (eq major-mode 'dired-mode) x))))
-
-    (define-key map [menu-bar regexp]
-      (cons "Regexp" (make-sparse-keymap "Regexp")))
-
-    (define-key map
-      [menu-bar regexp image-dired-mark-tagged-files]
-      '(menu-item "Mark From Image Tag..." image-dired-mark-tagged-files
-                  :help "Mark files whose image tags matches regexp"))
-
-    (define-key map [menu-bar regexp dashes-1]
-      '("--"))
-
-    (define-key map [menu-bar regexp downcase]
-      '(menu-item "Downcase" dired-downcase
-                 ;; When running on plain MS-DOS, there's only one
-                 ;; letter-case for file names.
-                 :enable (or (not (fboundp 'msdos-long-file-names))
-                             (msdos-long-file-names))
-                 :help "Rename marked files to lower-case name"))
-    (define-key map [menu-bar regexp upcase]
-      '(menu-item "Upcase" dired-upcase
-                 :enable (or (not (fboundp 'msdos-long-file-names))
-                             (msdos-long-file-names))
-                 :help "Rename marked files to upper-case name"))
-    (define-key map [menu-bar regexp hardlink]
-      '(menu-item "Hardlink..." dired-do-hardlink-regexp
-                 :help "Make hard links for files matching regexp"))
-    (define-key map [menu-bar regexp symlink]
-      '(menu-item "Symlink..." dired-do-symlink-regexp
-                 :visible (fboundp 'make-symbolic-link)
-                 :help "Make symbolic links for files matching regexp"))
-    (define-key map [menu-bar regexp rename]
-      '(menu-item "Rename..." dired-do-rename-regexp
-                 :help "Rename marked files matching regexp"))
-    (define-key map [menu-bar regexp copy]
-      '(menu-item "Copy..." dired-do-copy-regexp
-                 :help "Copy marked files matching regexp"))
-    (define-key map [menu-bar regexp flag]
-      '(menu-item "Flag..." dired-flag-files-regexp
-                 :help "Flag files matching regexp for deletion"))
-    (define-key map [menu-bar regexp mark]
-      '(menu-item "Mark..." dired-mark-files-regexp
-                 :help "Mark files matching regexp for future operations"))
-    (define-key map [menu-bar regexp mark-cont]
-      '(menu-item "Mark Containing..." dired-mark-files-containing-regexp
-                 :help "Mark files whose contents matches regexp"))
-
-    (define-key map [menu-bar mark]
-      (cons "Mark" (make-sparse-keymap "Mark")))
-
-    (define-key map [menu-bar mark prev]
-      '(menu-item "Previous Marked" dired-prev-marked-file
-                 :help "Move to previous marked file"))
-    (define-key map [menu-bar mark next]
-      '(menu-item "Next Marked" dired-next-marked-file
-                 :help "Move to next marked file"))
-    (define-key map [menu-bar mark marks]
-      '(menu-item "Change Marks..." dired-change-marks
-                 :help "Replace marker with another character"))
-    (define-key map [menu-bar mark unmark-all]
-      '(menu-item "Unmark All" dired-unmark-all-marks))
-    (define-key map [menu-bar mark symlinks]
-      '(menu-item "Mark Symlinks" dired-mark-symlinks
-                 :visible (fboundp 'make-symbolic-link)
-                 :help "Mark all symbolic links"))
-    (define-key map [menu-bar mark directories]
-      '(menu-item "Mark Directories" dired-mark-directories
-                 :help "Mark all directories except `.' and `..'"))
-    (define-key map [menu-bar mark directory]
-      '(menu-item "Mark Old Backups" dired-clean-directory
-                 :help "Flag old numbered backups for deletion"))
-    (define-key map [menu-bar mark executables]
-      '(menu-item "Mark Executables" dired-mark-executables
-                 :help "Mark all executable files"))
-    (define-key map [menu-bar mark garbage-files]
-      '(menu-item "Flag Garbage Files" dired-flag-garbage-files
-                 :help "Flag unneeded files for deletion"))
-    (define-key map [menu-bar mark backup-files]
-      '(menu-item "Flag Backup Files" dired-flag-backup-files
-                 :help "Flag all backup files for deletion"))
-    (define-key map [menu-bar mark auto-save-files]
-      '(menu-item "Flag Auto-save Files" dired-flag-auto-save-files
-                 :help "Flag auto-save files for deletion"))
-    (define-key map [menu-bar mark deletion]
-      '(menu-item "Flag" dired-flag-file-deletion
-                 :help "Flag current line's file for deletion"))
-    (define-key map [menu-bar mark unmark]
-      '(menu-item "Unmark" dired-unmark
-                 :help "Unmark or unflag current line's file"))
-    (define-key map [menu-bar mark mark]
-      '(menu-item "Mark" dired-mark
-                 :help "Mark current line's file for future operations"))
-    (define-key map [menu-bar mark toggle-marks]
-      '(menu-item "Toggle Marks" dired-toggle-marks
-                 :help "Mark unmarked files, unmark marked ones"))
-
-    (define-key map [menu-bar operate]
-      (cons "Operate" (make-sparse-keymap "Operate")))
-
-    (define-key map
-      [menu-bar operate image-dired-delete-tag]
-      '(menu-item "Delete Image Tag..." image-dired-delete-tag
-                  :help "Delete image tag from current or marked files"))
-    (define-key map
-      [menu-bar operate image-dired-tag-files]
-      '(menu-item "Add Image Tags..." image-dired-tag-files
-                  :help "Add image tags to current or marked files"))
-    (define-key map
-      [menu-bar operate image-dired-dired-comment-files]
-      '(menu-item "Add Image Comment..." image-dired-dired-comment-files
-                  :help "Add image comment to current or marked files"))
-    (define-key map
-      [menu-bar operate image-dired-display-thumbs]
-      '(menu-item "Display Image Thumbnails" image-dired-display-thumbs
-                  :help "Display image thumbnails for current or marked image 
files"))
-
-    (define-key map [menu-bar operate dashes-4]
-      '("--"))
-
-    (define-key map
-      [menu-bar operate epa-dired-do-decrypt]
-      '(menu-item "Decrypt..." epa-dired-do-decrypt
-                 :help "Decrypt current or marked files"))
-
-    (define-key map
-      [menu-bar operate epa-dired-do-verify]
-      '(menu-item "Verify" epa-dired-do-verify
-                 :help "Verify digital signature of current or marked files"))
-
-    (define-key map
-      [menu-bar operate epa-dired-do-sign]
-      '(menu-item "Sign..." epa-dired-do-sign
-                 :help "Create digital signature of current or marked files"))
-
-    (define-key map
-      [menu-bar operate epa-dired-do-encrypt]
-      '(menu-item "Encrypt..." epa-dired-do-encrypt
-                 :help "Encrypt current or marked files"))
-
-    (define-key map [menu-bar operate dashes-3]
-      '("--"))
-
-    (define-key map [menu-bar operate query-replace]
-      '(menu-item "Query Replace in Files..." dired-do-find-regexp-and-replace
-                 :help "Replace regexp matches in marked files"))
-    (define-key map [menu-bar operate search]
-      '(menu-item "Search Files..." dired-do-find-regexp
-                 :help "Search marked files for matches of regexp"))
-    (define-key map [menu-bar operate isearch-regexp]
-      '(menu-item "Isearch Regexp Files..." dired-do-isearch-regexp
-                 :help "Incrementally search marked files for regexp"))
-    (define-key map [menu-bar operate isearch]
-      '(menu-item "Isearch Files..." dired-do-isearch
-                 :help "Incrementally search marked files for string"))
-    (define-key map [menu-bar operate chown]
-      '(menu-item "Change Owner..." dired-do-chown
-                 :visible (not (memq system-type '(ms-dos windows-nt)))
-                 :help "Change the owner of marked files"))
-    (define-key map [menu-bar operate chgrp]
-      '(menu-item "Change Group..." dired-do-chgrp
-                 :visible (not (memq system-type '(ms-dos windows-nt)))
-                 :help "Change the group of marked files"))
-    (define-key map [menu-bar operate chmod]
-      '(menu-item "Change Mode..." dired-do-chmod
-                 :help "Change mode (attributes) of marked files"))
-    (define-key map [menu-bar operate touch]
-      '(menu-item "Change Timestamp..." dired-do-touch
-                 :help "Change timestamp of marked files"))
-    (define-key map [menu-bar operate load]
-      '(menu-item "Load" dired-do-load
-                 :help "Load marked Emacs Lisp files"))
-    (define-key map [menu-bar operate compile]
-      '(menu-item "Byte-compile" dired-do-byte-compile
-                 :help "Byte-compile marked Emacs Lisp files"))
-    (define-key map [menu-bar operate compress]
-      '(menu-item "Compress" dired-do-compress
-                 :help "Compress/uncompress marked files"))
-    (define-key map [menu-bar operate print]
-      '(menu-item "Print..." dired-do-print
-                 :help "Ask for print command and print marked files"))
-    (define-key map [menu-bar operate hardlink]
-      '(menu-item "Hardlink to..." dired-do-hardlink
-                 :help "Make hard links for current or marked files"))
-    (define-key map [menu-bar operate symlink]
-      '(menu-item "Symlink to..." dired-do-symlink
-                 :visible (fboundp 'make-symbolic-link)
-                 :help "Make symbolic links for current or marked files"))
-    (define-key map [menu-bar operate async-command]
-      '(menu-item "Asynchronous Shell Command..." dired-do-async-shell-command
-                 :help "Run a shell command asynchronously on current or 
marked files"))
-    (define-key map [menu-bar operate command]
-      '(menu-item "Shell Command..." dired-do-shell-command
-                 :help "Run a shell command on current or marked files"))
-    (define-key map [menu-bar operate delete]
-      `(menu-item "Delete"
-                  ,(let ((menu (make-sparse-keymap "Delete")))
-                     (define-key menu [delete-flagged]
-                       '(menu-item "Delete Flagged Files" 
dired-do-flagged-delete
-                                   :help "Delete all files flagged for 
deletion (D)"))
-                     (define-key menu [delete-marked]
-                       '(menu-item "Delete Marked (Not Flagged) Files" 
dired-do-delete
-                                   :help "Delete current file or all marked 
files (excluding flagged files)"))
-                     menu)))
-    (define-key map [menu-bar operate rename]
-      '(menu-item "Rename to..." dired-do-rename
-                 :help "Rename current file or move marked files"))
-    (define-key map [menu-bar operate copy]
-      '(menu-item "Copy to..." dired-do-copy
-                 :help "Copy current file or all marked files"))
-
     map)
   "Local keymap for Dired mode buffers.")
+
+(easy-menu-define dired-mode-subdir-menu dired-mode-map
+  "Subdir menu for Dired mode."
+  '("Subdir"
+    ["Insert This Subdir" dired-maybe-insert-subdir
+     :help "Insert contents of subdirectory"
+     :enable (let ((f (dired-get-filename nil t)))
+               (and f (file-directory-p f)))]
+    ["Next Dirline" dired-next-dirline
+     :help "Move to previous directory-file line"]
+    ["Prev Dirline" dired-prev-dirline
+     :help "Move to next directory-file line"]
+    ["Next Subdir" dired-next-subdir
+     :help "Go to next subdirectory header line"]
+    ["Prev Subdir" dired-prev-subdir
+     :help "Go to previous subdirectory header line"]
+    ["Up Directory" dired-up-directory
+     :help "Edit the parent directory"]
+    ["Tree Up" dired-tree-up
+     :help "Go to first subdirectory header up the tree"]
+    ["Tree Down" dired-tree-down
+     :help "Go to first subdirectory header down the tree"]
+    ["Hide/UnHide Subdir" dired-hide-subdir
+     :help "Hide or unhide current directory listing"]
+    ["Hide All" dired-hide-all
+     :help "Hide all subdirectories, leave only header lines"]))
+
+(easy-menu-define dired-mode-immediate-menu dired-mode-map
+  "Immediate menu for Dired mode."
+  '("Immediate"
+    ["Edit File Names" wdired-change-to-wdired-mode
+     :help "Put a Dired buffer in a mode in which filenames are editable"
+     :keys "C-x C-q"
+     :filter (lambda (x) (if (eq major-mode 'dired-mode) x))]
+    ["Create Empty file..." dired-create-empty-file
+     :help "Create an empty file"]
+    ["Create Directory..." dired-create-directory
+     :help "Create a directory"]
+    ["Find This File" dired-find-file
+     :help "Edit file at cursor"]
+    ["Find in Other Window" dired-find-file-other-window
+     :help "Edit file at cursor in other window"]
+    ["Display in Other Window" dired-display-file
+     :help "Display file at cursor in other window"]
+    ["View This File" dired-view-file
+     :help "Examine file at cursor in read-only mode"]
+    ["Diff..." dired-diff
+     :help "Compare file at cursor with another file"]
+    ["Compare with Backup" dired-backup-diff
+     :help "Diff file at cursor with its latest backup"]
+    ["Compare Directories..." dired-compare-directories
+     :help "Mark files with different attributes in two Dired buffers"]
+    ["Isearch in File Names..." dired-isearch-filenames
+     :help "Incrementally search for string in file names only."]
+    ["Isearch Regexp in File Names..." dired-isearch-filenames-regexp
+     :help "Incrementally search for regexp in file names only"]
+    "---"
+    ["#Marked Files" dired-number-of-marked-files
+     :help "Display the number and size of the marked files"]
+    ["Refresh" revert-buffer
+     :help "Update contents of shown directories"]
+    ["Hide Details" dired-hide-details-mode
+     :help "Hide details in buffer"
+     :style toggle
+     :selected dired-hide-details-mode]
+    ["Toggle Image Thumbnails in This Buffer" 
image-dired-dired-toggle-marked-thumbs
+     :help "Add or remove image thumbnails in front of marked file names"]
+    ["Display Image" image-dired-dired-display-image
+     :help "Display sized image in a separate window"]
+    ["Display Image Externally" image-dired-dired-display-external
+     :help "Display image in external viewer"]))
+
+(easy-menu-define dired-mode-regexp-menu dired-mode-map
+  "Regexp menu for Dired mode."
+  '("Regexp"
+    ["Mark Containing..." dired-mark-files-containing-regexp
+     :help "Mark files whose contents matches regexp"]
+    ["Mark..." dired-mark-files-regexp
+     :help "Mark files matching regexp for future operations"]
+    ["Flag..." dired-flag-files-regexp
+     :help "Flag files matching regexp for deletion"]
+    ["Copy..." dired-do-copy-regexp
+     :help "Copy marked files matching regexp"]
+    ["Rename..." dired-do-rename-regexp
+     :help "Rename marked files matching regexp"]
+    ["Symlink..." dired-do-symlink-regexp
+     :visible (fboundp 'make-symbolic-link)
+     :help "Make symbolic links for files matching regexp"]
+    ["Hardlink..." dired-do-hardlink-regexp
+     :help "Make hard links for files matching regexp"]
+    ["Upcase" dired-upcase
+     :enable (or (not (fboundp 'msdos-long-file-names))
+                 (msdos-long-file-names))
+     :help "Rename marked files to upper-case name"]
+    ["Downcase" dired-downcase
+     ;; When running on plain MS-DOS, there's only one
+     ;; letter-case for file names.
+     :enable (or (not (fboundp 'msdos-long-file-names))
+                 (msdos-long-file-names))
+     :help "Rename marked files to lower-case name"]
+    "---"
+    ["Mark From Image Tag..." image-dired-mark-tagged-files
+     :help "Mark files whose image tags matches regexp"]))
+
+(easy-menu-define dired-mode-mark-menu dired-mode-map
+  "Mark menu for Dired mode."
+  '("Mark"
+    ["Toggle Marks" dired-toggle-marks
+     :help "Mark unmarked files, unmark marked ones"]
+    ["Mark" dired-mark
+     :help "Mark current line's file for future operations"]
+    ["Unmark" dired-unmark
+     :help "Unmark or unflag current line's file"]
+    ["Flag" dired-flag-file-deletion
+     :help "Flag current line's file for deletion"]
+    ["Flag Auto-save Files" dired-flag-auto-save-files
+     :help "Flag auto-save files for deletion"]
+    ["Flag Backup Files" dired-flag-backup-files
+     :help "Flag all backup files for deletion"]
+    ["Flag Garbage Files" dired-flag-garbage-files
+     :help "Flag unneeded files for deletion"]
+    ["Mark Executables" dired-mark-executables
+     :help "Mark all executable files"]
+    ["Mark Old Backups" dired-clean-directory
+     :help "Flag old numbered backups for deletion"]
+    ["Mark Directories" dired-mark-directories
+     :help "Mark all directories except `.' and `..'"]
+    ["Mark Symlinks" dired-mark-symlinks
+     :visible (fboundp 'make-symbolic-link)
+     :help "Mark all symbolic links"]
+    ["Unmark All" dired-unmark-all-marks]
+    ["Change Marks..." dired-change-marks
+     :help "Replace marker with another character"]
+    ["Next Marked" dired-next-marked-file
+     :help "Move to next marked file"]
+    ["Previous Marked" dired-prev-marked-file
+     :help "Move to previous marked file"]))
+
+(easy-menu-define dired-mode-operate-menu dired-mode-map
+  "Operate menu for Dired mode."
+  '("Operate"
+    ["Copy to..." dired-do-copy
+     :help "Copy current file or all marked files"]
+    ["Rename to..." dired-do-rename
+     :help "Rename current file or move marked files"]
+    ("Delete"
+     ["Delete Flagged Files" dired-do-flagged-delete
+      :help "Delete all files flagged for deletion (D)"]
+     ["Delete Marked (Not Flagged) Files" dired-do-delete
+      :help "Delete current file or all marked files (excluding flagged 
files)"])
+    ["Shell Command..." dired-do-shell-command
+     :help "Run a shell command on current or marked files"]
+    ["Asynchronous Shell Command..." dired-do-async-shell-command
+     :help "Run a shell command asynchronously on current or marked files"]
+    ["Symlink to..." dired-do-symlink
+     :visible (fboundp 'make-symbolic-link)
+     :help "Make symbolic links for current or marked files"]
+    ["Hardlink to..." dired-do-hardlink
+     :help "Make hard links for current or marked files"]
+    ["Print..." dired-do-print
+     :help "Ask for print command and print marked files"]
+    ["Compress" dired-do-compress
+     :help "Compress/uncompress marked files"]
+    ["Byte-compile" dired-do-byte-compile
+     :help "Byte-compile marked Emacs Lisp files"]
+    ["Load" dired-do-load
+     :help "Load marked Emacs Lisp files"]
+    ["Change Timestamp..." dired-do-touch
+     :help "Change timestamp of marked files"]
+    ["Change Mode..." dired-do-chmod
+     :help "Change mode (attributes) of marked files"]
+    ["Change Group..." dired-do-chgrp
+     :visible (not (memq system-type '(ms-dos windows-nt)))
+     :help "Change the group of marked files"]
+    ["Change Owner..." dired-do-chown
+     :visible (not (memq system-type '(ms-dos windows-nt)))
+     :help "Change the owner of marked files"]
+    ["Isearch Files..." dired-do-isearch
+     :help "Incrementally search marked files for string"]
+    ["Isearch Regexp Files..." dired-do-isearch-regexp
+     :help "Incrementally search marked files for regexp"]
+    ["Search Files..." dired-do-find-regexp
+     :help "Search marked files for matches of regexp"]
+    ["Query Replace in Files..." dired-do-find-regexp-and-replace
+     :help "Replace regexp matches in marked files"]
+    "---"
+    ["Encrypt..." epa-dired-do-encrypt
+     :help "Encrypt current or marked files"]
+    ["Sign..." epa-dired-do-sign
+     :help "Create digital signature of current or marked files"]
+    ["Verify" epa-dired-do-verify
+     :help "Verify digital signature of current or marked files"]
+    ["Decrypt..." epa-dired-do-decrypt
+     :help "Decrypt current or marked files"]
+    "---"
+    ["Display Image Thumbnails" image-dired-display-thumbs
+     :help "Display image thumbnails for current or marked image files"]
+    ["Add Image Comment..." image-dired-dired-comment-files
+     :help "Add image comment to current or marked files"]
+    ["Add Image Tags..." image-dired-tag-files
+     :help "Add image tags to current or marked files"]
+    ["Delete Image Tag..." image-dired-delete-tag
+     :help "Delete image tag from current or marked files"]))
+
 
 ;; Dired mode is suitable only for specially formatted data.
 (put 'dired-mode 'mode-class 'special)
@@ -4235,7 +4129,8 @@ Possible values:
  * `as-is':  Show full switches.
  * Integer:  Show only the first N chars of full switches.
  * Function: Pass `dired-actual-switches' as arg and show result."
-  :group 'Dired-Plus
+  :group 'dired
+  :version "28.1"
   :type '(choice
           (const    :tag "Indicate by name or date, else full"   nil)
           (const    :tag "Show full switches"                    as-is)
diff --git a/lisp/doc-view.el b/lisp/doc-view.el
index f6fcfae..cef0900 100644
--- a/lisp/doc-view.el
+++ b/lisp/doc-view.el
@@ -1439,6 +1439,8 @@ ARGS is a list of image descriptors."
                            (apply #'create-image file doc-view--image-type nil 
args)
                          (unless (member :width args)
                            (setq args `(,@args :width ,doc-view-image-width)))
+                          (unless (member :transform-smoothing args)
+                            (setq args `(,@args :transform-smoothing t)))
                          (apply #'create-image file doc-view--image-type nil 
args))))
             (slice (doc-view-current-slice))
             (img-width (and image (car (image-size image))))
diff --git a/lisp/emacs-lisp/autoload.el b/lisp/emacs-lisp/autoload.el
index ec7492d..ae17039 100644
--- a/lisp/emacs-lisp/autoload.el
+++ b/lisp/emacs-lisp/autoload.el
@@ -141,9 +141,12 @@ expression, in which case we want to handle forms 
differently."
                       ((stringp (car-safe rest)) (car rest))))
            ;; Look for an interactive spec.
            (interactive (pcase body
-                          ((or `((interactive . ,_) . ,_)
-                               `(,_ (interactive . ,_) . ,_))
-                           t))))
+                          ((or `((interactive . ,iargs) . ,_)
+                               `(,_ (interactive . ,iargs) . ,_))
+                           ;; List of modes or just t.
+                           (if (nthcdr 1 iargs)
+                               (list 'quote (nthcdr 1 iargs))
+                             t)))))
         ;; Add the usage form at the end where describe-function-1
         ;; can recover it.
         (when (consp args) (setq doc (help-add-fundoc-usage doc args)))
@@ -207,7 +210,11 @@ expression, in which case we want to handle forms 
differently."
                                   easy-mmode-define-minor-mode
                                   define-minor-mode))
                      t)
-                (eq (car-safe (car body)) 'interactive))
+                (and (eq (car-safe (car body)) 'interactive)
+                     ;; List of modes or just t.
+                     (or (if (nthcdr 1 (car body))
+                             (list 'quote (nthcdr 1 (car body)))
+                           t))))
            ,(if macrop ''macro nil))))
 
      ;; For defclass forms, use `eieio-defclass-autoload'.
diff --git a/lisp/emacs-lisp/backtrace.el b/lisp/emacs-lisp/backtrace.el
index 3e1c329..ea70baa 100644
--- a/lisp/emacs-lisp/backtrace.el
+++ b/lisp/emacs-lisp/backtrace.el
@@ -190,7 +190,7 @@ This is commonly used to recompute `backtrace-frames'.")
 (defvar-local backtrace-print-function #'cl-prin1
   "Function used to print values in the current Backtrace buffer.")
 
-(defvar-local backtrace-goto-source-functions nil
+(defvar backtrace-goto-source-functions nil
   "Abnormal hook used to jump to the source code for the current frame.
 Each hook function is called with no argument, and should return
 non-nil if it is able to switch to the buffer containing the
@@ -638,10 +638,8 @@ content of the sexp."
          (source-available (plist-get (backtrace-frame-flags frame)
                                       :source-available)))
     (unless (and source-available
-                 (catch 'done
-                   (dolist (func backtrace-goto-source-functions)
-                     (when (funcall func)
-                       (throw 'done t)))))
+                 (run-hook-with-args-until-success
+                  'backtrace-goto-source-functions))
       (user-error "Source code location not known"))))
 
 (defun backtrace-help-follow-symbol (&optional pos)
diff --git a/lisp/emacs-lisp/benchmark.el b/lisp/emacs-lisp/benchmark.el
index 14bc281..439d3bd 100644
--- a/lisp/emacs-lisp/benchmark.el
+++ b/lisp/emacs-lisp/benchmark.el
@@ -31,6 +31,8 @@
 
 ;;; Code:
 
+(eval-when-compile (require 'subr-x))   ;For `named-let'.
+
 (defmacro benchmark-elapse (&rest forms)
   "Return the time in seconds elapsed for execution of FORMS."
   (declare (indent 0) (debug t))
@@ -41,6 +43,61 @@
        (float-time (time-since ,t1)))))
 
 ;;;###autoload
+(defun benchmark-call (func &optional repetitions)
+  "Measure the run time of calling FUNC a number REPETITIONS of times.
+The result is a list (TIME GC GCTIME)
+where TIME is the total time it took, in seconds.
+GCTIME is the amount of time that was spent in the GC
+and GC is the number of times the GC was called.
+
+REPETITIONS can also be a floating point number, in which case it
+specifies a minimum number of seconds that the benchmark execution
+should take.  In that case the return value is prepended with the
+number of repetitions actually used."
+  (if (floatp repetitions)
+      (benchmark--adaptive func repetitions)
+    (unless repetitions (setq repetitions 1))
+    (let ((gc gc-elapsed)
+         (gcs gcs-done)
+         (empty-func (lambda () 'empty-func)))
+      (list
+       (if (> repetitions 1)
+          (- (benchmark-elapse (dotimes (_ repetitions) (funcall func)))
+             (benchmark-elapse (dotimes (_ repetitions) (funcall empty-func))))
+        (- (benchmark-elapse (funcall func))
+            (benchmark-elapse (funcall empty-func))))
+       (- gcs-done gcs)
+       (- gc-elapsed gc)))))
+
+(defun benchmark--adaptive (func time)
+  "Measure the run time of FUNC, calling it enough times to last TIME seconds.
+Result is (REPETITIONS . DATA) where DATA is as returned by `branchmark-call'."
+  (named-let loop ((repetitions 1)
+                   (data (let ((x (list 0))) (setcdr x x) x)))
+    ;; (message "Running %d iteration" repetitions)
+    (let ((newdata (benchmark-call func repetitions)))
+      (if (<= (car newdata) 0)
+          ;; This can happen if we're unlucky, e.g. the process got preempted
+          ;; (or the GC ran) just during the empty-func loop.
+          ;; Just try again, hopefully this won't repeat itself.
+          (progn
+            ;; (message "Ignoring the %d iterations" repetitions)
+            (loop (* 2 repetitions) data))
+        (let* ((sum (cl-mapcar #'+ data (cons repetitions newdata)))
+               (totaltime (nth 1 sum)))
+          (if (>= totaltime time)
+              sum
+            (let* ((iter-time (/ totaltime (car sum)))
+                   (missing-time (- time totaltime))
+                   (missing-iter (/ missing-time iter-time)))
+              ;; `iter-time' is approximate because of effects like the GC,
+              ;; so multiply at most by 10, in case we are wildly off the mark.
+              (loop (max repetitions
+                         (min (ceiling missing-iter)
+                              (* 10 repetitions)))
+                    sum))))))))
+
+;;;###autoload
 (defmacro benchmark-run (&optional repetitions &rest forms)
   "Time execution of FORMS.
 If REPETITIONS is supplied as a number, run FORMS that many times,
@@ -53,19 +110,7 @@ See also `benchmark-run-compiled'."
   (unless (or (natnump repetitions) (and repetitions (symbolp repetitions)))
     (setq forms (cons repetitions forms)
          repetitions 1))
-  (let ((i (make-symbol "i"))
-       (gcs (make-symbol "gcs"))
-       (gc (make-symbol "gc")))
-    `(let ((,gc gc-elapsed)
-          (,gcs gcs-done))
-       (list ,(if (or (symbolp repetitions) (> repetitions 1))
-                 ;; Take account of the loop overhead.
-                 `(- (benchmark-elapse (dotimes (,i ,repetitions)
-                                         ,@forms))
-                     (benchmark-elapse (dotimes (,i ,repetitions))))
-               `(benchmark-elapse ,@forms))
-            (- gcs-done ,gcs)
-            (- gc-elapsed ,gc)))))
+  `(benchmark-call (lambda () ,@forms) ,repetitions))
 
 ;;;###autoload
 (defmacro benchmark-run-compiled (&optional repetitions &rest forms)
@@ -77,21 +122,7 @@ result.  The overhead of the `lambda's is accounted for."
   (unless (or (natnump repetitions) (and repetitions (symbolp repetitions)))
     (setq forms (cons repetitions forms)
          repetitions 1))
-  (let ((i (make-symbol "i"))
-       (gcs (make-symbol "gcs"))
-       (gc (make-symbol "gc"))
-       (code (byte-compile `(lambda () ,@forms)))
-        (lambda-code (byte-compile '(lambda ()))))
-    `(let ((,gc gc-elapsed)
-          (,gcs gcs-done))
-       (list ,(if (or (symbolp repetitions) (> repetitions 1))
-                 ;; Take account of the loop overhead.
-                 `(- (benchmark-elapse (dotimes (,i ,repetitions)
-                                         (funcall ,code)))
-                     (benchmark-elapse (dotimes (,i ,repetitions)
-                                         (funcall ,lambda-code))))
-               `(benchmark-elapse (funcall ,code)))
-            (- gcs-done ,gcs) (- gc-elapsed ,gc)))))
+  `(benchmark-call (byte-compile '(lambda () ,@forms)) ,repetitions))
 
 ;;;###autoload
 (defun benchmark (repetitions form)
@@ -99,9 +130,15 @@ result.  The overhead of the `lambda's is accounted for."
 Interactively, REPETITIONS is taken from the prefix arg, and
 the command prompts for the form to benchmark.
 For non-interactive use see also `benchmark-run' and
-`benchmark-run-compiled'."
+`benchmark-run-compiled'.
+FORM can also be a function in which case we measure the time it takes
+to call it without any argument."
   (interactive "p\nxForm: ")
-  (let ((result (eval `(benchmark-run ,repetitions ,form) t)))
+  (let ((result (benchmark-call (eval (pcase form
+                                        ((or `#',_ `(lambda . ,_)) form)
+                                        (_ `(lambda () ,form)))
+                                      t)
+                                repetitions)))
     (if (zerop (nth 1 result))
        (message "Elapsed time: %fs" (car result))
       (message "Elapsed time: %fs (%fs in %d GCs)" (car result)
diff --git a/lisp/emacs-lisp/bindat.el b/lisp/emacs-lisp/bindat.el
index 0d9ba57..9899496 100644
--- a/lisp/emacs-lisp/bindat.el
+++ b/lisp/emacs-lisp/bindat.el
@@ -26,7 +26,7 @@
 ;;  Packing and unpacking of (binary) data structures.
 ;;
 ;;  The data formats used in binary files and network protocols are
-;;  often structed data which can be described by a C-style structure
+;;  often structured data which can be described by a C-style structure
 ;;  such as the one shown below.  Using the bindat package, decoding
 ;;  and encoding binary data formats like these is made simple using a
 ;;  structure specification which closely resembles the C style
@@ -41,57 +41,61 @@
 ;;  Consider the following C structures:
 ;;
 ;;  struct header {
-;;     unsigned long   dest_ip;
-;;     unsigned long   src_ip;
-;;     unsigned short  dest_port;
-;;     unsigned short  src_port;
+;;     uint32_t        dest_ip;
+;;     uint32_t        src_ip;
+;;     uint16_t        dest_port;
+;;     uint16_t        src_port;
 ;;  };
 ;;
 ;;  struct data {
-;;     unsigned char   type;
-;;     unsigned char   opcode;
-;;     unsigned long   length;  /* In little endian order */
+;;     uint8_t         type;
+;;     uint8_t         opcode;
+;;     uint32_t        length;  /* In little endian order */
 ;;     unsigned char   id[8];   /* nul-terminated string  */
 ;;     unsigned char   data[/* (length + 3) & ~3 */];
 ;;  };
 ;;
 ;;  struct packet {
 ;;     struct header   header;
-;;     unsigned char   items;
+;;     uint8_t         items;
 ;;     unsigned char   filler[3];
 ;;     struct data     item[/* items */];
 ;;  };
 ;;
-;;  The corresponding Lisp bindat specification looks like this:
+;;  The corresponding Lisp bindat specification could look like this:
+;;
+;;  (bindat-defmacro ip () '(vec 4 byte))
 ;;
 ;;  (setq header-bindat-spec
-;;    '((dest-ip   ip)
+;;    (bindat-type
+;;      (dest-ip   ip)
 ;;     (src-ip    ip)
-;;     (dest-port u16)
-;;     (src-port  u16)))
+;;     (dest-port uint 16)
+;;     (src-port  uint 16)))
 ;;
 ;;  (setq data-bindat-spec
-;;    '((type      u8)
+;;    (bindat-type
+;;      (type      u8)
 ;;     (opcode    u8)
-;;     (length    u16r)  ;; little endian order
+;;     (length    uintr 32)  ;; little endian order
 ;;     (id        strz 8)
-;;     (data      vec (length))
-;;     (align     4)))
+;;     (data      vec length)
+;;     (_         align 4)))
 ;;
 ;;  (setq packet-bindat-spec
-;;    '((header    struct header-bindat-spec)
-;;     (items     u8)
-;;     (fill      3)
-;;     (item      repeat (items)
-;;                (struct data-bindat-spec))))
-;;
+;;    (bindat-type
+;;      (header    type header-bindat-spec)
+;;     (nitems    u8)
+;;     (_         fill 3)
+;;     (items     repeat nitems type data-bindat-spec)))
 ;;
 ;;  A binary data representation may look like
 ;;   [ 192 168 1 100 192 168 1 101 01 28 21 32 2 0 0 0
 ;;     2 3 5 0 ?A ?B ?C ?D ?E ?F 0 0 1 2 3 4 5 0 0 0
 ;;     1 4 7 0 ?B ?C ?D ?E ?F ?G 0 0 6 7 8 9 10 11 12 0 ]
 ;;
-;;  The corresponding decoded structure looks like
+;;  The corresponding decoded structure returned by `bindat-unpack' (or taken
+;;  by `bindat-pack') looks like:
 ;;
 ;;      ((header
 ;;        (dest-ip   . [192 168 1 100])
@@ -111,92 +115,28 @@
 ;;             (type . 1))))
 ;;
 ;;  To access a specific value in this structure, use the function
-;;  bindat-get-field with the structure as first arg followed by a list
+;;  `bindat-get-field' with the structure as first arg followed by a list
 ;;  of field names and array indexes, e.g. using the data above,
 ;;    (bindat-get-field decoded-structure 'item 1 'id)
 ;;  returns "BCDEFG".
 
-;; Binary Data Structure Specification Format
-;; ------------------------------------------
-
-;; We recommend using names that end in `-bindat-spec'; such names
-;; are recognized automatically as "risky" variables.
-
-;; The data specification is formatted as follows:
-
-;; SPEC    ::= ( ITEM... )
-
-;; ITEM    ::= ( [FIELD] TYPE )
-;;          |  ( [FIELD] eval FORM )    -- eval FORM for side-effect only
-;;          |  ( [FIELD] fill LEN )     -- skip LEN bytes
-;;          |  ( [FIELD] align LEN )    -- skip to next multiple of LEN bytes
-;;          |  ( [FIELD] struct SPEC_NAME )
-;;          |  ( [FIELD] union TAG_VAL (TAG SPEC)... [(t SPEC)] )
-;;          |  ( [FIELD] repeat COUNT ITEM... )
-
-;;          -- In (eval EXPR), the value of the last field is available in
-;;             the dynamically bound variable `last'.
-
-;; TYPE    ::= ( eval EXPR )           -- interpret result as TYPE
-;;         |  u8   | byte              -- length 1
-;;          |  u16  | word | short      -- length 2, network byte order
-;;          |  u24                      -- 3-byte value
-;;          |  u32  | dword | long      -- length 4, network byte order
-;;          |  u16r | u24r | u32r       -- little endian byte order.
-;;         |  str LEN                  -- LEN byte string
-;;          |  strz LEN                 -- LEN byte (zero-terminated) string
-;;          |  vec LEN [TYPE]           -- vector of LEN items of TYPE 
(default: u8)
-;;          |  ip                       -- 4 byte vector
-;;          |  bits LEN                 -- List with bits set in LEN bytes.
-;;
-;;          -- Example: `bits 2' will unpack 0x28 0x1c to (2 3 4 11 13)
-;;                                       and 0x1c 0x28 to (3 5 10 11 12).
-
-;; FIELD   ::= ( eval EXPR )           -- use result as NAME
-;;          |  NAME
-
-;; LEN     ::= ARG
-;;          |  <omitted> | nil         -- LEN = 1
-
-
-;; TAG_VAL ::= ARG
-
-;; TAG     ::= LISP_CONSTANT
-;;          |  ( eval EXPR )           -- return non-nil if tag match;
-;;                                        current TAG_VAL in `tag'.
-
-;; ARG     ::= ( eval EXPR )           -- interpret result as ARG
-;;          |  INTEGER_CONSTANT
-;;          |  DEREF
-
-;; DEREF   ::= ( [NAME | INTEGER]... ) -- Field NAME or Array index relative
-;;                                         to current structure spec.
-;;                                      -- see bindat-get-field
-
-;; A `union' specification
-;;    ([FIELD] union TAG_VAL (TAG SPEC) ... [(t SPEC)])
-;; is interpreted by evalling TAG_VAL and then comparing that to
-;; each TAG using equal; if a match is found, the corresponding SPEC
-;; is used.
-;; If TAG is a form (eval EXPR), EXPR is evalled with `tag' bound to the
-;; value of TAG_VAL; the corresponding SPEC is used if the result is non-nil.
-;; Finally, if TAG is t, the corresponding SPEC is used unconditionally.
-;;
-;; An `eval' specification
-;;  ([FIELD] eval FORM)
-;; is interpreted by evalling FORM for its side effects only.
-;; If FIELD is specified, the value is bound to that field.
-;; The FORM may access and update `bindat-raw' and `bindat-idx' (see 
`bindat-unpack').
-
 ;;; Code:
 
 ;; Helper functions for structure unpacking.
-;; Relies on dynamic binding of BINDAT-RAW and BINDAT-IDX
+;; Relies on dynamic binding of `bindat-raw' and `bindat-idx'.
+
+(eval-when-compile (require 'cl-lib))
+(eval-when-compile (require 'subr-x))   ;For `named-let'.
+
+(cl-defstruct (bindat--type
+               (:predicate nil)
+               (:constructor bindat--make))
+  le ue pe)
 
 (defvar bindat-raw)
 (defvar bindat-idx)
 
-(defun bindat--unpack-u8 ()
+(defsubst bindat--unpack-u8 ()
   (prog1
       (aref bindat-raw bindat-idx)
     (setq bindat-idx (1+ bindat-idx))))
@@ -219,77 +159,79 @@
 (defun bindat--unpack-u32r ()
   (logior (bindat--unpack-u16r) (ash (bindat--unpack-u16r) 16)))
 
+(defun bindat--unpack-str (len)
+  (let ((s (substring bindat-raw bindat-idx (+ bindat-idx len))))
+    (setq bindat-idx (+ bindat-idx len))
+    (if (stringp s) s
+      (apply #'unibyte-string s))))
+
+(defun bindat--unpack-strz (len)
+  (let ((i 0) s)
+    (while (and (< i len) (/= (aref bindat-raw (+ bindat-idx i)) 0))
+      (setq i (1+ i)))
+    (setq s (substring bindat-raw bindat-idx (+ bindat-idx i)))
+    (setq bindat-idx (+ bindat-idx len))
+    (if (stringp s) s
+      (apply #'unibyte-string s))))
+
+(defun bindat--unpack-bits (len)
+  (let ((bits nil) (bnum (1- (* 8 len))) j m)
+    (while (>= bnum 0)
+      (if (= (setq m (bindat--unpack-u8)) 0)
+         (setq bnum (- bnum 8))
+       (setq j 128)
+       (while (> j 0)
+         (if (/= 0 (logand m j))
+             (setq bits (cons bnum bits)))
+         (setq bnum (1- bnum)
+               j (ash j -1)))))
+    bits))
+
 (defun bindat--unpack-item (type len &optional vectype)
   (if (eq type 'ip)
       (setq type 'vec len 4))
-  (cond
-   ((memq type '(u8 byte))
-    (bindat--unpack-u8))
-   ((memq type '(u16 word short))
-    (bindat--unpack-u16))
-   ((eq type 'u24)
-    (bindat--unpack-u24))
-   ((memq type '(u32 dword long))
-    (bindat--unpack-u32))
-   ((eq type 'u16r)
-    (bindat--unpack-u16r))
-   ((eq type 'u24r)
-    (bindat--unpack-u24r))
-   ((eq type 'u32r)
-    (bindat--unpack-u32r))
-   ((eq type 'bits)
-    (let ((bits nil) (bnum (1- (* 8 len))) j m)
-      (while (>= bnum 0)
-       (if (= (setq m (bindat--unpack-u8)) 0)
-           (setq bnum (- bnum 8))
-         (setq j 128)
-         (while (> j 0)
-           (if (/= 0 (logand m j))
-               (setq bits (cons bnum bits)))
-           (setq bnum (1- bnum)
-                 j (ash j -1)))))
-      bits))
-   ((eq type 'str)
-    (let ((s (substring bindat-raw bindat-idx (+ bindat-idx len))))
-      (setq bindat-idx (+ bindat-idx len))
-      (if (stringp s) s
-       (apply #'unibyte-string s))))
-   ((eq type 'strz)
-    (let ((i 0) s)
-      (while (and (< i len) (/= (aref bindat-raw (+ bindat-idx i)) 0))
-       (setq i (1+ i)))
-      (setq s (substring bindat-raw bindat-idx (+ bindat-idx i)))
-      (setq bindat-idx (+ bindat-idx len))
-      (if (stringp s) s
-       (apply #'unibyte-string s))))
-   ((eq type 'vec)
-    (let ((v (make-vector len 0)) (i 0) (vlen 1))
+  (pcase type
+   ((or 'u8 'byte) (bindat--unpack-u8))
+   ((or 'u16 'word 'short) (bindat--unpack-u16))
+   ('u24 (bindat--unpack-u24))
+   ((or 'u32 'dword 'long) (bindat--unpack-u32))
+   ('u16r (bindat--unpack-u16r))
+   ('u24r (bindat--unpack-u24r))
+   ('u32r (bindat--unpack-u32r))
+   ('bits (bindat--unpack-bits len))
+   ('str (bindat--unpack-str len))
+   ('strz (bindat--unpack-strz len))
+   ('vec
+    (let ((v (make-vector len 0)) (vlen 1))
       (if (consp vectype)
          (setq vlen (nth 1 vectype)
                vectype (nth 2 vectype))
        (setq type (or vectype 'u8)
              vectype nil))
-      (while (< i len)
-       (aset v i (bindat--unpack-item type vlen vectype))
-       (setq i (1+ i)))
+      (dotimes (i len)
+       (aset v i (bindat--unpack-item type vlen vectype)))
       v))
-   (t nil)))
+   (_ nil)))
+
+(defsubst bindat--align (n len)
+  (* len (/ (+ n (1- len)) len)))       ;Isn't there a simpler way?
 
 (defun bindat--unpack-group (spec)
-  (with-suppressed-warnings ((lexical last))
-    (defvar last))
+  ;; FIXME: Introduce a new primitive so we can mark `bindat-unpack'
+  ;; as obsolete (maybe that primitive should be a macro which takes
+  ;; a bindat type *expression* as argument).
+  (if (cl-typep spec 'bindat--type)
+      (funcall (bindat--type-ue spec))
+  (with-suppressed-warnings ((lexical struct last))
+    (defvar struct) (defvar last))
   (let (struct last)
-    (while spec
-      (let* ((item (car spec))
-            (field (car item))
+    (dolist (item spec)
+      (let* ((field (car item))
             (type (nth 1 item))
             (len (nth 2 item))
             (vectype (and (eq type 'vec) (nth 3 item)))
             (tail 3)
             data)
-       (setq spec (cdr spec))
-       (if (and (consp field) (eq (car field) 'eval))
-           (setq field (eval (car (cdr field)) t)))
        (if (and type (consp type) (eq (car type) 'eval))
            (setq type (eval (car (cdr type)) t)))
        (if (and len (consp len) (eq (car len) 'eval))
@@ -299,29 +241,28 @@
                  len type
                  type field
                  field nil))
+       (if (and (consp field) (eq (car field) 'eval))
+           (setq field (eval (car (cdr field)) t)))
        (if (and (consp len) (not (eq type 'eval)))
             (setq len (apply #'bindat-get-field struct len)))
        (if (not len)
            (setq len 1))
-       (cond
-        ((eq type 'eval)
+       (pcase type
+        ('eval
          (if field
              (setq data (eval len t))
            (eval len t)))
-        ((eq type 'fill)
+        ('fill
          (setq bindat-idx (+ bindat-idx len)))
-        ((eq type 'align)
-         (while (/= (% bindat-idx len) 0)
-           (setq bindat-idx (1+ bindat-idx))))
-        ((eq type 'struct)
+        ('align
+         (setq bindat-idx (bindat--align bindat-idx len)))
+        ('struct
          (setq data (bindat--unpack-group (eval len t))))
-        ((eq type 'repeat)
-         (let ((index 0) (count len))
-           (while (< index count)
-             (push (bindat--unpack-group (nthcdr tail item)) data)
-             (setq index (1+ index)))
-           (setq data (nreverse data))))
-        ((eq type 'union)
+        ('repeat
+         (dotimes (_ len)
+           (push (bindat--unpack-group (nthcdr tail item)) data))
+         (setq data (nreverse data)))
+        ('union
          (with-suppressed-warnings ((lexical tag))
            (defvar tag))
          (let ((tag len) (cases (nthcdr tail item)) case cc)
@@ -333,14 +274,15 @@
                      (and (consp cc) (eval cc t)))
                  (setq data (bindat--unpack-group (cdr case))
                        cases nil)))))
-        (t
+        ((pred integerp) (debug t))
+        (_
          (setq data (bindat--unpack-item type len vectype)
                last data)))
        (if data
            (setq struct (if field
                             (cons (cons field data) struct)
                           (append data struct))))))
-    struct))
+    struct)))
 
 (defun bindat-unpack (spec raw &optional idx)
   "Return structured data according to SPEC for binary data in RAW.
@@ -361,14 +303,12 @@ An integer value in the field list is taken as an array 
index,
 e.g. corresponding to STRUCT.FIELD1[INDEX2].FIELD3..."
   (while (and struct field)
     (setq struct (if (integerp (car field))
-                    (nth (car field) struct)
-                  (let ((val (assq (car field) struct)))
-                    (if (consp val) (cdr val)))))
+                    (elt struct (car field))
+                  (cdr (assq (car field) struct))))
     (setq field (cdr field)))
   struct)
 
-
-;; Calculate bindat-raw length of structured data
+;;;; Calculate bindat-raw length of structured data
 
 (defvar bindat--fixed-length-alist
   '((u8 . 1) (byte . 1)
@@ -378,19 +318,17 @@ e.g. corresponding to STRUCT.FIELD1[INDEX2].FIELD3..."
     (ip . 4)))
 
 (defun bindat--length-group (struct spec)
-  (with-suppressed-warnings ((lexical last))
-    (defvar last))
-  (let (last)
-    (while spec
-      (let* ((item (car spec))
-            (field (car item))
+  (if (cl-typep spec 'bindat--type)
+      (funcall (bindat--type-le spec) struct)
+  (with-suppressed-warnings ((lexical struct last))
+    (defvar struct) (defvar last))
+  (let ((struct struct) last)
+    (dolist (item spec)
+      (let* ((field (car item))
             (type (nth 1 item))
             (len (nth 2 item))
             (vectype (and (eq type 'vec) (nth 3 item)))
             (tail 3))
-       (setq spec (cdr spec))
-       (if (and (consp field) (eq (car field) 'eval))
-           (setq field (eval (car (cdr field)) t)))
        (if (and type (consp type) (eq (car type) 'eval))
            (setq type (eval (car (cdr type)) t)))
        (if (and len (consp len) (eq (car len) 'eval))
@@ -400,6 +338,8 @@ e.g. corresponding to STRUCT.FIELD1[INDEX2].FIELD3..."
                  len type
                  type field
                  field nil))
+       (if (and (consp field) (eq (car field) 'eval))
+           (setq field (eval (car (cdr field)) t)))
        (if (and (consp len) (not (eq type 'eval)))
            (setq len (apply #'bindat-get-field struct len)))
        (if (not len)
@@ -410,27 +350,24 @@ e.g. corresponding to STRUCT.FIELD1[INDEX2].FIELD3..."
                    type (nth 2 vectype))
            (setq type (or vectype 'u8)
                  vectype nil)))
-       (cond
-        ((eq type 'eval)
+       (pcase type
+        ('eval
          (if field
              (setq struct (cons (cons field (eval len t)) struct))
            (eval len t)))
-        ((eq type 'fill)
+        ('fill
          (setq bindat-idx (+ bindat-idx len)))
-        ((eq type 'align)
-         (while (/= (% bindat-idx len) 0)
-           (setq bindat-idx (1+ bindat-idx))))
-        ((eq type 'struct)
+        ('align
+         (setq bindat-idx (bindat--align bindat-idx len)))
+        ('struct
          (bindat--length-group
           (if field (bindat-get-field struct field) struct) (eval len t)))
-        ((eq type 'repeat)
-         (let ((index 0) (count len))
-           (while (< index count)
-             (bindat--length-group
-               (nth index (bindat-get-field struct field))
-               (nthcdr tail item))
-             (setq index (1+ index)))))
-        ((eq type 'union)
+        ('repeat
+         (dotimes (index len)
+           (bindat--length-group
+             (nth index (bindat-get-field struct field))
+             (nthcdr tail item))))
+        ('union
          (with-suppressed-warnings ((lexical tag))
            (defvar tag))
          (let ((tag len) (cases (nthcdr tail item)) case cc)
@@ -443,23 +380,23 @@ e.g. corresponding to STRUCT.FIELD1[INDEX2].FIELD3..."
                  (progn
                    (bindat--length-group struct (cdr case))
                    (setq cases nil))))))
-        (t
+        (_
          (if (setq type (assq type bindat--fixed-length-alist))
              (setq len (* len (cdr type))))
          (if field
              (setq last (bindat-get-field struct field)))
-         (setq bindat-idx (+ bindat-idx len))))))))
+         (setq bindat-idx (+ bindat-idx len)))))))))
 
 (defun bindat-length (spec struct)
-  "Calculate bindat-raw length for STRUCT according to bindat SPEC."
+  "Calculate `bindat-raw' length for STRUCT according to bindat SPEC."
   (let ((bindat-idx 0))
     (bindat--length-group struct spec)
     bindat-idx))
 
 
-;; Pack structured data into bindat-raw
+;;;; Pack structured data into bindat-raw
 
-(defun bindat--pack-u8 (v)
+(defsubst bindat--pack-u8 (v)
   (aset bindat-raw bindat-idx (logand v 255))
   (setq bindat-idx (1+ bindat-idx)))
 
@@ -476,6 +413,10 @@ e.g. corresponding to STRUCT.FIELD1[INDEX2].FIELD3..."
   (bindat--pack-u16 (ash v -16))
   (bindat--pack-u16 v))
 
+(defun bindat--pack-u64 (v)
+  (bindat--pack-u32 (ash v -32))
+  (bindat--pack-u32 v))
+
 (defun bindat--pack-u16r (v)
   (aset bindat-raw (1+ bindat-idx) (logand (ash v -8) 255))
   (aset bindat-raw bindat-idx (logand v 255))
@@ -489,74 +430,68 @@ e.g. corresponding to STRUCT.FIELD1[INDEX2].FIELD3..."
   (bindat--pack-u16r v)
   (bindat--pack-u16r (ash v -16)))
 
+(defun bindat--pack-u64r (v)
+  (bindat--pack-u32r v)
+  (bindat--pack-u32r (ash v -32)))
+
+(defun bindat--pack-str (len v)
+  (dotimes (i (min len (length v)))
+    (aset bindat-raw (+ bindat-idx i) (aref v i)))
+  (setq bindat-idx (+ bindat-idx len)))
+
+(defun bindat--pack-bits (len v)
+  (let ((bnum (1- (* 8 len))) j m)
+    (while (>= bnum 0)
+      (setq m 0)
+      (if (null v)
+         (setq bnum (- bnum 8))
+       (setq j 128)
+       (while (> j 0)
+         (if (memq bnum v)
+             (setq m (logior m j)))
+         (setq bnum (1- bnum)
+               j (ash j -1))))
+      (bindat--pack-u8 m))))
+
 (defun bindat--pack-item (v type len &optional vectype)
   (if (eq type 'ip)
       (setq type 'vec len 4))
-  (cond
-   ((null v)
-    (setq bindat-idx (+ bindat-idx len)))
-   ((memq type '(u8 byte))
-    (bindat--pack-u8 v))
-   ((memq type '(u16 word short))
-    (bindat--pack-u16 v))
-   ((eq type 'u24)
-    (bindat--pack-u24 v))
-   ((memq type '(u32 dword long))
-    (bindat--pack-u32 v))
-   ((eq type 'u16r)
-    (bindat--pack-u16r v))
-   ((eq type 'u24r)
-    (bindat--pack-u24r v))
-   ((eq type 'u32r)
-    (bindat--pack-u32r v))
-   ((eq type 'bits)
-    (let ((bnum (1- (* 8 len))) j m)
-      (while (>= bnum 0)
-       (setq m 0)
-       (if (null v)
-           (setq bnum (- bnum 8))
-         (setq j 128)
-         (while (> j 0)
-           (if (memq bnum v)
-               (setq m (logior m j)))
-           (setq bnum (1- bnum)
-                 j (ash j -1))))
-       (bindat--pack-u8 m))))
-   ((memq type '(str strz))
-    (let ((l (length v)) (i 0))
-      (if (> l len) (setq l len))
-      (while (< i l)
-       (aset bindat-raw (+ bindat-idx i) (aref v i))
-       (setq i (1+ i)))
-      (setq bindat-idx (+ bindat-idx len))))
-   ((eq type 'vec)
-    (let ((l (length v)) (i 0) (vlen 1))
+  (pcase type
+   ((guard (null v)) (setq bindat-idx (+ bindat-idx len)))
+   ((or 'u8 'byte) (bindat--pack-u8 v))
+   ((or 'u16 'word 'short) (bindat--pack-u16 v))
+   ('u24 (bindat--pack-u24 v))
+   ((or 'u32 'dword 'long) (bindat--pack-u32 v))
+   ('u16r (bindat--pack-u16r v))
+   ('u24r (bindat--pack-u24r v))
+   ('u32r (bindat--pack-u32r v))
+   ('bits (bindat--pack-bits len v))
+   ((or 'str 'strz) (bindat--pack-str len v))
+   ('vec
+    (let ((l (length v)) (vlen 1))
       (if (consp vectype)
          (setq vlen (nth 1 vectype)
                vectype (nth 2 vectype))
        (setq type (or vectype 'u8)
              vectype nil))
       (if (> l len) (setq l len))
-      (while (< i l)
-       (bindat--pack-item (aref v i) type vlen vectype)
-       (setq i (1+ i)))))
-   (t
+      (dotimes (i l)
+       (bindat--pack-item (aref v i) type vlen vectype))))
+   (_
     (setq bindat-idx (+ bindat-idx len)))))
 
 (defun bindat--pack-group (struct spec)
-  (with-suppressed-warnings ((lexical last))
-    (defvar last))
-  (let (last)
-    (while spec
-      (let* ((item (car spec))
-            (field (car item))
+  (if (cl-typep spec 'bindat--type)
+      (funcall (bindat--type-pe spec) struct)
+  (with-suppressed-warnings ((lexical struct last))
+    (defvar struct) (defvar last))
+  (let ((struct struct) last)
+    (dolist (item spec)
+      (let* ((field (car item))
             (type (nth 1 item))
             (len (nth 2 item))
             (vectype (and (eq type 'vec) (nth 3 item)))
             (tail 3))
-       (setq spec (cdr spec))
-       (if (and (consp field) (eq (car field) 'eval))
-           (setq field (eval (car (cdr field)) t)))
        (if (and type (consp type) (eq (car type) 'eval))
            (setq type (eval (car (cdr type)) t)))
        (if (and len (consp len) (eq (car len) 'eval))
@@ -566,31 +501,30 @@ e.g. corresponding to STRUCT.FIELD1[INDEX2].FIELD3..."
                  len type
                  type field
                  field nil))
+       (if (and (consp field) (eq (car field) 'eval))
+           (setq field (eval (car (cdr field)) t)))
        (if (and (consp len) (not (eq type 'eval)))
             (setq len (apply #'bindat-get-field struct len)))
        (if (not len)
            (setq len 1))
-       (cond
-        ((eq type 'eval)
+       (pcase type
+        ('eval
          (if field
              (setq struct (cons (cons field (eval len t)) struct))
            (eval len t)))
-        ((eq type 'fill)
+        ('fill
          (setq bindat-idx (+ bindat-idx len)))
-        ((eq type 'align)
-         (while (/= (% bindat-idx len) 0)
-           (setq bindat-idx (1+ bindat-idx))))
-        ((eq type 'struct)
+        ('align
+         (setq bindat-idx (bindat--align bindat-idx len)))
+        ('struct
          (bindat--pack-group
           (if field (bindat-get-field struct field) struct) (eval len t)))
-        ((eq type 'repeat)
-         (let ((index 0) (count len))
-           (while (< index count)
-             (bindat--pack-group
-               (nth index (bindat-get-field struct field))
-               (nthcdr tail item))
-             (setq index (1+ index)))))
-        ((eq type 'union)
+        ('repeat
+         (dotimes (index len)
+           (bindat--pack-group
+             (nth index (bindat-get-field struct field))
+             (nthcdr tail item))))
+        ('union
          (with-suppressed-warnings ((lexical tag))
            (defvar tag))
          (let ((tag len) (cases (nthcdr tail item)) case cc)
@@ -603,10 +537,10 @@ e.g. corresponding to STRUCT.FIELD1[INDEX2].FIELD3..."
                  (progn
                    (bindat--pack-group struct (cdr case))
                    (setq cases nil))))))
-        (t
+        (_
          (setq last (bindat-get-field struct field))
          (bindat--pack-item last type len vectype)
-         ))))))
+         )))))))
 
 (defun bindat-pack (spec struct &optional raw idx)
   "Return binary data packed according to SPEC for structured data STRUCT.
@@ -622,21 +556,15 @@ Optional fourth arg IDX is the starting offset into RAW."
     (bindat--pack-group struct spec)
     (if raw nil bindat-raw)))
 
-
-;; Misc. format conversions
+;;;; Misc. format conversions
 
 (defun bindat-format-vector (vect fmt sep &optional len)
   "Format vector VECT using element format FMT and separator SEP.
 Result is a string with each element of VECT formatted using FMT and
 separated by the string SEP.  If optional fourth arg LEN is given, use
 only that many elements from VECT."
-  (unless len
-    (setq len (length vect)))
-  (let ((i len) (fmt2 (concat sep fmt)) (s nil))
-    (while (> i 0)
-      (setq i (1- i)
-           s (cons (format (if (= i 0) fmt fmt2) (aref vect i)) s)))
-    (apply #'concat s)))
+  (when len (setq vect (substring vect 0 len)))
+  (mapconcat (lambda (x) (format fmt x)) vect sep))
 
 (defun bindat-vector-to-dec (vect &optional sep)
   "Format vector VECT in decimal format separated by dots.
@@ -656,6 +584,384 @@ The port (if any) is omitted.  IP can be a string, as 
well."
     (format "%d.%d.%d.%d"
             (aref ip 0) (aref ip 1) (aref ip 2) (aref ip 3))))
 
+;;;; New approach based on macro-expansion
+
+;; Further improvements suggested by reading websocket.el:
+;; - Support for bit-sized fields?
+;;
+;; - Add some way to verify redundant/checksum fields's contents without
+;;   having to provide a complete `:unpack-val' expression.
+;;   The `:pack-val' thingy can work nicely to compute checksum fields
+;;   based on previous fields's contents (without impacting or being impacted
+;;   by the unpacked representation), but if we want to verify
+;;   those checksums when unpacking, we have to use the :unpack-val
+;;   and build the whole object by hand instead of being able to focus
+;;   just on the checksum field.
+;;   Maybe this could be related to `unit' type fields where we might like
+;;   to make sure that the "value" we write into it is the same as the
+;;   value it holds (tho those checks don't happen at the same time (pack
+;;   vs unpack).
+;;
+;; - Support for packing/unpacking to/from something else than
+;;   a unibyte string, e.g. from a buffer.  Problems to do that are:
+;;   - the `str' and `strz' types which use `substring' rather than reading
+;;     one byte at a time.
+;;   - the `align' and `fill' which just want to skip without reading/writing
+;;   - the `pack-uint' case, which would prefer writing the LSB first.
+;;   - the `align' case needs to now the current position in order to know
+;;     how far to advance
+;;
+;; - Don't write triple code when the type is only ever used at a single place
+;;   (e.g. to unpack).
+
+(defun bindat--unpack-uint (bitlen)
+  (let ((v 0) (bitsdone 0))
+    (while (< bitsdone bitlen)
+      (setq v (logior (ash v 8) (bindat--unpack-u8)))
+      (setq bitsdone (+ bitsdone 8)))
+    v))
+
+(defun bindat--unpack-uintr (bitlen)
+  (let ((v 0) (bitsdone 0))
+    (while (< bitsdone bitlen)
+      (setq v (logior v (ash (bindat--unpack-u8) bitsdone)))
+      (setq bitsdone (+ bitsdone 8)))
+    v))
+
+(defun bindat--pack-uint (bitlen v)
+  (let* ((len (/ bitlen 8))
+         (shift (- (* 8 (1- len)))))
+    (dotimes (_ len)
+      (bindat--pack-u8 (logand 255 (ash v shift)))
+      (setq shift (+ 8 shift)))))
+
+(defun bindat--pack-uintr (bitlen v)
+  (let* ((len (/ bitlen 8)))
+    (dotimes (_ len)
+      (bindat--pack-u8 (logand v 255))
+      (setq v (ash v -8)))))
+
+(defmacro bindat--pcase (&rest args)
+  "Like `pcase' but optimize the code under the assumption that it's 
exhaustive."
+  (declare (indent 1) (debug pcase))
+  `(pcase ,@args (pcase--dontcare nil)))
+
+(cl-defgeneric bindat--type (op head &rest args)
+  "Return the code for the operation OP of the Bindat type (HEAD . ARGS).
+OP can be one of: unpack', (pack VAL), or (length VAL) where VAL
+is the name of a variable that will hold the value we need to pack.")
+
+(cl-defmethod bindat--type (op (_ (eql byte)))
+  (bindat--pcase op
+    ('unpack `(bindat--unpack-u8))
+    (`(length . ,_) `(cl-incf bindat-idx 1))
+    (`(pack . ,args) `(bindat--pack-u8 . ,args))))
+
+(cl-defmethod bindat--type (op (_ (eql uint))  n)
+  (if (eq n 8) (bindat--type op 'byte)
+    (bindat--pcase op
+      ('unpack `(bindat--unpack-uint ,n))
+      (`(length . ,_) `(cl-incf bindat-idx (/ ,n 8)))
+      (`(pack . ,args) `(bindat--pack-uint ,n . ,args)))))
+
+(cl-defmethod bindat--type (op (_ (eql uintr)) n)
+  (if (eq n 8) (bindat--type op 'byte)
+    (bindat--pcase op
+      ('unpack `(bindat--unpack-uintr ,n))
+      (`(length . ,_) `(cl-incf bindat-idx (/ ,n 8)))
+      (`(pack . ,args) `(bindat--pack-uintr ,n . ,args)))))
+
+(cl-defmethod bindat--type (op (_ (eql str))   len)
+  (bindat--pcase op
+    ('unpack `(bindat--unpack-str ,len))
+    (`(length . ,_) `(cl-incf bindat-idx ,len))
+    (`(pack . ,args) `(bindat--pack-str ,len . ,args))))
+
+(cl-defmethod bindat--type (op (_ (eql strz))  len)
+  (bindat--pcase op
+    ('unpack `(bindat--unpack-strz ,len))
+    (`(length . ,_) `(cl-incf bindat-idx ,len))
+    ;; Here we don't add the terminating zero because we rely
+    ;; on the fact that `bindat-raw' was presumably initialized with
+    ;; all-zeroes before we started.
+    (`(pack . ,args) `(bindat--pack-str ,len . ,args))))
+
+(cl-defmethod bindat--type (op (_ (eql bits))  len)
+  (bindat--pcase op
+    ('unpack `(bindat--unpack-bits ,len))
+    (`(length . ,_) `(cl-incf bindat-idx ,len))
+    (`(pack . ,args) `(bindat--pack-bits ,len . ,args))))
+
+(cl-defmethod bindat--type (_op (_ (eql fill))  len)
+  `(progn (cl-incf bindat-idx ,len) nil))
+
+(cl-defmethod bindat--type (_op (_ (eql align)) len)
+  `(progn (cl-callf bindat--align bindat-idx ,len) nil))
+
+(cl-defmethod bindat--type (op (_ (eql type)) exp)
+  (bindat--pcase op
+    ('unpack        `(funcall (bindat--type-ue ,exp)))
+    (`(length . ,args) `(funcall (bindat--type-le ,exp) . ,args))
+    (`(pack . ,args)   `(funcall (bindat--type-pe ,exp) . ,args))))
+
+(cl-defmethod bindat--type (op (_ (eql vec)) count &rest type)
+  (unless type (setq type '(byte)))
+  (let ((fun (macroexpand-all (bindat--fun type) macroexpand-all-environment)))
+    (bindat--pcase op
+      ('unpack
+       `(let* ((bindat--len ,count)
+               (bindat--v (make-vector bindat--len 0)))
+          (dotimes (bindat--i bindat--len)
+            (aset bindat--v bindat--i (funcall ,fun)))
+         bindat--v))
+      ((and `(length . ,_)
+            ;; FIXME: Improve the pattern match to recognize more complex
+            ;; "constant" functions?
+            (let `#'(lambda (,val) (setq bindat-idx (+ bindat-idx ,len))) fun)
+            (guard (not (macroexp--fgrep `((,val)) len))))
+       ;; Optimize the case where the size of each element is constant.
+       `(cl-incf bindat-idx (* ,count ,len)))
+      ;; FIXME: It's tempting to use `(mapc (lambda (,val) ,exp) ,val)'
+      ;; which would be more efficient when `val' is a list,
+      ;; but that's only right if length of `val' is indeed `count'.
+      (`(,_ ,val)
+       `(dotimes (bindat--i ,count)
+         (funcall ,fun (elt ,val bindat--i)))))))
+
+(cl-defmethod bindat--type (op (_ (eql unit)) val)
+  (pcase op ('unpack val) (_ nil)))
+
+(cl-defmethod bindat--type (op (_ (eql struct)) &rest args)
+  (apply #'bindat--type op args))
+
+(cl-defmethod bindat--type (op (_ (eql :pack-var)) var &rest fields)
+  (unless (consp (cdr fields))
+    (error "`:pack-var VAR' needs to be followed by fields"))
+  (bindat--pcase op
+    ((or 'unpack (guard (null var)))
+     (apply #'bindat--type op fields))
+    (`(,_ ,val)
+     `(let ((,var ,val)) ,(apply #'bindat--type op fields)))))
+
+(cl-defmethod bindat--type (op (field cons) &rest fields)
+  (named-let loop
+      ((fields (cons field fields))
+       (labels ()))
+    (bindat--pcase fields
+      ('nil
+       (bindat--pcase op
+         ('unpack
+          (let ((exp ()))
+            (pcase-dolist (`(,label . ,labelvar) labels)
+              (setq exp
+                    (if (eq label '_)
+                        (if exp `(nconc ,labelvar ,exp) labelvar)
+                      `(cons (cons ',label ,labelvar) ,exp))))
+            exp))
+         (_ nil)))
+      (`(:unpack-val ,exp)
+       ;; Make it so `:kwd nil' is the same as the absence of the keyword arg.
+       (if exp (pcase op ('unpack exp)) (loop nil labels)))
+
+      (`((,label . ,type) . ,fields)
+       (let* ((get-field-val
+               (let ((tail (memq :pack-val type)))
+                 ;; FIXME: This `TYPE.. :pack EXP' syntax doesn't work well
+                 ;; when TYPE is a struct (a list of fields) or with extensions
+                 ;; such as allowing TYPE to be `if ...'.
+                 (if tail
+                     (prog1 (cadr tail)
+                       (setq type (butlast type (length tail)))))))
+              (fieldvar (make-symbol (format "field%d" (length fields))))
+              (labelvar
+               (cond
+                ((eq label '_) fieldvar)
+                ((keywordp label)
+                 (intern (substring (symbol-name label) 1)))
+                (t label)))
+              (field-fun (bindat--fun type))
+              (rest-exp (loop fields `((,label . ,labelvar) . ,labels))))
+         (bindat--pcase op
+           ('unpack
+            (let ((code
+                   `(let ((,labelvar (funcall ,field-fun)))
+                      ,rest-exp)))
+              (if (or (eq label '_) (not (assq label labels)))
+                  code
+                (macroexp-warn-and-return
+                 (format "Duplicate label: %S" label)
+                 code))))
+           (`(,_ ,val)
+            ;; `cdr-safe' is easier to optimize (can't signal an error).
+            `(let ((,fieldvar ,(or get-field-val
+                                   (if (eq label '_) val
+                                     `(cdr-safe (assq ',label ,val))))))
+               (funcall ,field-fun ,fieldvar)
+               ,@(when rest-exp
+                   `((let ,(unless (eq labelvar fieldvar)
+                             `((,labelvar ,fieldvar)))
+                       (ignore ,labelvar)
+                       ,rest-exp))))))))
+      (_ (error "Unrecognized format in bindat fields: %S" fields)))))
+
+(def-edebug-elem-spec 'bindat-struct
+  '([&rest (symbolp bindat-type &optional ":pack-val" def-form)]
+    &optional ":unpack-val" def-form))
+
+(def-edebug-elem-spec 'bindat-type
+  '(&or ["uint" def-form]
+        ["uintr" def-form]
+        ["str" def-form]
+        ["strz" def-form]
+        ["bits" def-form]
+        ["fill" def-form]
+        ["align" def-form]
+        ["vec" def-form bindat-type]
+        ["repeat" def-form bindat-type]
+        ["type" def-form]
+        ["struct" bindat-struct]
+        ["unit" def-form]
+        [":pack-var" symbolp bindat-type]
+        symbolp ;; u8, u16, etc...
+        bindat-struct))
+
+(defmacro bindat-type (&rest type)
+  "Return the Bindat type value to pack&unpack TYPE.
+TYPE is a Bindat type expression.  It can take the following forms:
+
+  uint BITLEN          - Big-endian unsigned integer
+  uintr BITLEN         - Little-endian unsigned integer
+  str LEN              - Byte string
+  strz LEN             - Zero-terminated byte-string
+  bits LEN             - Bit vector (LEN is counted in bytes)
+  fill LEN             - Just a filler
+  align LEN            - Fill up to the next multiple of LEN bytes
+  vec COUNT TYPE       - COUNT repetitions of TYPE
+  type EXP             - Indirection; EXP should return a Bindat type value
+  unit EXP              - 0-width type holding the value returned by EXP
+  struct FIELDS...      - A composite type
+
+When the context makes it clear, the symbol `struct' can be omitted.
+A composite type is a list of FIELDS where each FIELD is of the form
+
+  (LABEL TYPE)
+
+where LABEL can be `_' if the field should not deserve a name.
+
+Composite types get normally packed/unpacked to/from alists, but this can be
+controlled in the following way:
+- If the list of fields ends with `:unpack-val EXP', then unpacking will
+  return the value of EXP (which has the previous fields in its scope).
+- If a field's TYPE is followed by `:pack-val EXP', then the value placed
+  into this field will be that returned by EXP instead of looking up the alist.
+- If the list of fields is preceded with `:pack-var VAR' then the object to
+  be packed is bound to VAR when evaluating the EXPs of `:pack-val'.
+
+All the above BITLEN, LEN, COUNT, and EXP are ELisp expressions evaluated
+in the current lexical context extended with the previous fields.
+
+TYPE can additionally be one of the Bindat type macros defined with
+`bindat-defmacro' (and listed below) or an ELisp expression which returns
+a bindat type expression."
+  (declare (indent 0) (debug (bindat-type)))
+  `(progn
+     (defvar bindat-idx)
+     (bindat--make :ue ,(bindat--toplevel 'unpack type)
+                   :le ,(bindat--toplevel 'length type)
+                   :pe ,(bindat--toplevel 'pack   type))))
+
+(eval-and-compile
+  (defconst bindat--primitives '(byte uint uintr str strz bits fill align
+                                 struct type vec unit)))
+
+(eval-and-compile
+  (defvar bindat--macroenv
+    (mapcar (lambda (s) (cons s (lambda (&rest args)
+                             (bindat--makefun (cons s args)))))
+            bindat--primitives)))
+
+(defmacro bindat-defmacro (name args &rest body)
+  "Define a new Bindat type as a macro."
+  (declare (indent 2) (doc-string 3) (debug (&define name sexp def-body)))
+  (let ((leaders ()))
+    (while (and (cdr body)
+                (or (stringp (car body))
+                    (memq (car-safe (car body)) '(:documentation declare))))
+      (push (pop body) leaders))
+    ;; FIXME: Add support for Edebug decls to those macros.
+    `(eval-and-compile ;; Yuck!  But needed to define types where you use them!
+       (setf (alist-get ',name bindat--macroenv)
+             (lambda ,args ,@(nreverse leaders)
+               (bindat--fun ,(macroexp-progn body)))))))
+
+(put 'bindat-type 'function-documentation '(bindat--make-docstring))
+(defun bindat--make-docstring ()
+  ;; Largely inspired from `pcase--make-docstring'.
+  (let* ((main (documentation (symbol-function 'bindat-type) 'raw))
+         (ud (help-split-fundoc main 'bindat-type)))
+    (require 'help-fns)
+    (declare-function help-fns--signature "help-fns")
+    (with-temp-buffer
+      (insert (or (cdr ud) main))
+      (pcase-dolist (`(,name . ,me) (reverse bindat--macroenv))
+        (unless (memq name bindat--primitives)
+          (let ((doc (documentation me 'raw)))
+            (insert "\n\n-- ")
+            (setq doc (help-fns--signature name doc me
+                                           (indirect-function me)
+                                           nil))
+            (insert "\n" (or doc "Not documented.")))))
+      (let ((combined-doc (buffer-string)))
+        (if ud (help-add-fundoc-usage combined-doc (car ud)) combined-doc)))))
+
+(bindat-defmacro u8 () "Unsigned 8bit integer." '(byte))
+(bindat-defmacro sint (bitlen r)
+  "Signed integer of size BITLEN.
+Bigendian if R is nil and little endian if not."
+  (let ((bl (make-symbol "bitlen"))
+        (max (make-symbol "max"))
+        (wrap (make-symbol "wrap")))
+    `(let* ((,bl ,bitlen)
+            (,max (ash 1 (1- ,bl)))
+            (,wrap (+ ,max ,max)))
+       (struct :pack-var v
+               (n if ,r (uintr ,bl) (uint ,bl)
+                  :pack-val (if (< v 0) (+ v ,wrap) v))
+               :unpack-val (if (>= n ,max) (- n ,wrap) n)))))
+
+(bindat-defmacro repeat (count &rest type)
+  "Like `vec', but unpacks to a list rather than a vector."
+  `(:pack-var v
+    (v vec ,count ,@type :pack-val v)
+    :unpack-val (append v nil)))
+
+(defvar bindat--op nil
+  "The operation we're currently building.
+This is a simple symbol and can be one of: `unpack', `pack', or `length'.
+This is used during macroexpansion of `bindat-type' so that the
+macros know which code to generate.
+FIXME: this is closely related and very similar to the `op' argument passed
+to `bindat--type', yet it's annoyingly different.")
+
+(defun bindat--fun (type)
+  (if (or (keywordp (car type)) (consp (car type))) (cons 'struct type)
+    type))
+
+(defun bindat--makefun (type)
+  (let* ((v (make-symbol "v"))
+         (args (pcase bindat--op ('unpack ()) (_ (list v)))))
+    (pcase (apply #'bindat--type
+                  (pcase bindat--op ('unpack 'unpack) (op `(,op . ,args)))
+                  type)
+      (`(funcall ,f . ,(pred (equal args))) f)  ;η-reduce.
+      (exp `(lambda ,args ,exp)))))
+
+(defun bindat--toplevel (op type)
+  (let* ((bindat--op op)
+         (env `(,@bindat--macroenv
+                ,@macroexpand-all-environment)))
+    (macroexpand-all (bindat--fun type) env)))
+
 (provide 'bindat)
 
 ;;; bindat.el ends here
diff --git a/lisp/emacs-lisp/byte-opt.el b/lisp/emacs-lisp/byte-opt.el
index 4fa2c75..db8d825 100644
--- a/lisp/emacs-lisp/byte-opt.el
+++ b/lisp/emacs-lisp/byte-opt.el
@@ -458,16 +458,22 @@ Same format as `byte-optimize--lexvars', with shared 
structure and contents.")
        (cons fn (byte-optimize-body exps for-effect)))
 
       (`(if ,test ,then . ,else)
+       ;; FIXME: We are conservative here: any variable changed in the
+       ;; THEN branch will be barred from substitution in the ELSE
+       ;; branch, despite the branches being mutually exclusive.
+
        ;; The test is always executed.
        (let* ((test-opt (byte-optimize-form test nil))
-              ;; The THEN and ELSE branches are executed conditionally.
-              ;;
-              ;; FIXME: We are conservative here: any variable changed in the
-              ;; THEN branch will be barred from substitution in the ELSE
-              ;; branch, despite the branches being  mutually exclusive.
-              (byte-optimize--vars-outside-condition byte-optimize--lexvars)
-              (then-opt (byte-optimize-form then for-effect))
-              (else-opt (byte-optimize-body else for-effect)))
+              (const (macroexp-const-p test-opt))
+              ;; The branches are traversed unconditionally when possible.
+              (byte-optimize--vars-outside-condition
+               (if const
+                   byte-optimize--vars-outside-condition
+                 byte-optimize--lexvars))
+              ;; Avoid traversing dead branches.
+              (then-opt (and test-opt (byte-optimize-form then for-effect)))
+              (else-opt (and (not (and test-opt const))
+                             (byte-optimize-body else for-effect))))
          `(if ,test-opt ,then-opt . ,else-opt)))
 
       (`(,(or 'and 'or) . ,exps) ; Remember, and/or are control structures.
@@ -587,24 +593,26 @@ Same format as `byte-optimize--lexvars', with shared 
structure and contents.")
                   (lexvar (assq var byte-optimize--lexvars))
                   (value (byte-optimize-form expr nil)))
              (when lexvar
-               ;; If it's bound outside conditional, invalidate.
-               (if (assq var byte-optimize--vars-outside-condition)
-                   ;; We are in conditional code and the variable was
-                   ;; bound outside: cancel substitutions.
-                   (setcdr (cdr lexvar) nil)
-                 ;; Set a new value (if substitutable).
-                 (setcdr (cdr lexvar)
-                         (and (byte-optimize--substitutable-p value)
-                              (list value))))
-               (setcar (cdr lexvar) t)) ; Mark variable to be kept.
+               ;; Set a new value or inhibit further substitution.
+               (setcdr (cdr lexvar)
+                       (and
+                        ;; Inhibit if bound outside conditional code.
+                        (not (assq var byte-optimize--vars-outside-condition))
+                        ;; The new value must be substitutable.
+                        (byte-optimize--substitutable-p value)
+                        (list value)))
+               (setcar (cdr lexvar) t))   ; Mark variable to be kept.
              (push var var-expr-list)
              (push value var-expr-list))
            (setq args (cddr args)))
          (cons fn (nreverse var-expr-list))))
 
-      (`(defvar ,(and (pred symbolp) name) . ,_)
-       (push name byte-optimize--dynamic-vars)
-       form)
+      (`(defvar ,(and (pred symbolp) name) . ,rest)
+       (let ((optimized-rest (and rest
+                                  (cons (byte-optimize-form (car rest) nil)
+                                        (cdr rest)))))
+         (push name byte-optimize--dynamic-vars)
+         `(defvar ,name . ,optimized-rest)))
 
       (`(,(pred byte-code-function-p) . ,exps)
        (cons fn (mapcar #'byte-optimize-form exps)))
@@ -638,30 +646,24 @@ Same format as `byte-optimize--lexvars', with shared 
structure and contents.")
 
 (defun byte-optimize-form (form &optional for-effect)
   "The source-level pass of the optimizer."
-  ;;
-  ;; First, optimize all sub-forms of this one.
-  (setq form (byte-optimize-form-code-walker form for-effect))
-  ;;
-  ;; after optimizing all subforms, optimize this form until it doesn't
-  ;; optimize any further.  This means that some forms will be passed through
-  ;; the optimizer many times, but that's necessary to make the for-effect
-  ;; processing do as much as possible.
-  ;;
-  (let (opt new)
-    (if (and (consp form)
-            (symbolp (car form))
-            (or ;; (and for-effect
-                ;;      ;; We don't have any of these yet, but we might.
-                ;;      (setq opt (get (car form)
-                 ;;                     'byte-for-effect-optimizer)))
-                (setq opt (function-get (car form) 'byte-optimizer)))
-            (not (eq form (setq new (funcall opt form)))))
-       (progn
-;;       (if (equal form new) (error "bogus optimizer -- %s" opt))
-         (byte-compile-log "  %s\t==>\t%s" form new)
-         (setq new (byte-optimize-form new for-effect))
-         new)
-      form)))
+  (while
+      (progn
+        ;; First, optimize all sub-forms of this one.
+        (setq form (byte-optimize-form-code-walker form for-effect))
+
+        ;; If a form-specific optimiser is available, run it and start over
+        ;; until a fixpoint has been reached.
+        (and (consp form)
+             (symbolp (car form))
+             (let ((opt (function-get (car form) 'byte-optimizer)))
+               (and opt
+                    (let ((old form)
+                          (new (funcall opt form)))
+                     (byte-compile-log "  %s\t==>\t%s" old new)
+                      (setq form new)
+                      (not (eq new old))))))))
+  ;; Normalise (quote nil) to nil, for a single representation of constant nil.
+  (and (not (equal form '(quote nil))) form))
 
 (defun byte-optimize-let-form (head form for-effect)
   ;; Recursively enter the optimizer for the bindings and body
@@ -698,7 +700,8 @@ Same format as `byte-optimize--lexvars', with shared 
structure and contents.")
               (append new-lexvars byte-optimize--lexvars))
         ;; Walk the body expressions, which may mutate some of the records,
         ;; and generate new bindings that exclude unused variables.
-        (let* ((opt-body (byte-optimize-body (cdr form) for-effect))
+        (let* ((byte-optimize--dynamic-vars byte-optimize--dynamic-vars)
+               (opt-body (byte-optimize-body (cdr form) for-effect))
                (bindings nil))
           (dolist (var let-vars)
             ;; VAR is (NAME EXPR [KEEP [VALUE]])
@@ -730,7 +733,6 @@ Same format as `byte-optimize--lexvars', with shared 
structure and contents.")
   ;; all-for-effect is true.  returns a new list of forms.
   (let ((rest forms)
        (result nil)
-        (byte-optimize--dynamic-vars byte-optimize--dynamic-vars)
        fe new)
     (while rest
       (setq fe (or all-for-effect (cdr rest)))
@@ -1325,6 +1327,8 @@ Same format as `byte-optimize--lexvars', with shared 
structure and contents.")
         radians-to-degrees rassq rassoc read-from-string regexp-opt
          regexp-quote region-beginning region-end reverse round
         sin sqrt string string< string= string-equal string-lessp
+         string> string-greaterp string-empty-p
+         string-prefix-p string-suffix-p string-blank-p
          string-search string-to-char
         string-to-number string-to-syntax substring
         sxhash sxhash-equal sxhash-eq sxhash-eql
@@ -1349,7 +1353,7 @@ Same format as `byte-optimize--lexvars', with shared 
structure and contents.")
         window-total-height window-total-width window-use-time window-vscroll
         window-width zerop))
       (side-effect-and-error-free-fns
-       '(arrayp atom
+       '(always arrayp atom
         bignump bobp bolp bool-vector-p
         buffer-end buffer-list buffer-size buffer-string bufferp
         car-safe case-table-p cdr-safe char-or-string-p characterp
@@ -1414,7 +1418,8 @@ Same format as `byte-optimize--lexvars', with shared 
structure and contents.")
          copysign isnan ldexp float logb
          floor ceiling round truncate
          ffloor fceiling fround ftruncate
-         string= string-equal string< string-lessp
+         string= string-equal string< string-lessp string> string-greaterp
+         string-empty-p string-blank-p string-prefix-p string-suffix-p
          string-search
          consp atom listp nlistp proper-list-p
          sequencep arrayp vectorp stringp bool-vector-p hash-table-p
@@ -1563,10 +1568,7 @@ Same format as `byte-optimize--lexvars', with shared 
structure and contents.")
              ;; so we create a copy of it, and replace the addresses with
              ;; TAGs.
              (let ((orig-table last-constant))
-               (cl-loop for e across constvec
-                        when (eq e last-constant)
-                        do (setq last-constant (copy-hash-table e))
-                        and return nil)
+               (setq last-constant (copy-hash-table last-constant))
                ;; Replace all addresses with TAGs.
                (maphash #'(lambda (value offset)
                             (let ((match (assq offset tags)))
diff --git a/lisp/emacs-lisp/byte-run.el b/lisp/emacs-lisp/byte-run.el
index 88f362d..119d397 100644
--- a/lisp/emacs-lisp/byte-run.el
+++ b/lisp/emacs-lisp/byte-run.el
@@ -113,6 +113,9 @@ The return value of this function is not used."
       (list 'function-put (list 'quote f)
             ''side-effect-free (list 'quote val))))
 
+(put 'compiler-macro 'edebug-declaration-spec
+     '(&or symbolp ("lambda" &define lambda-list lambda-doc def-body)))
+
 (defalias 'byte-run--set-compiler-macro
   #'(lambda (f args compiler-function)
       (if (not (eq (car-safe compiler-function) 'lambda))
@@ -143,6 +146,16 @@ The return value of this function is not used."
       (list 'function-put (list 'quote f)
             ''lisp-indent-function (list 'quote val))))
 
+(defalias 'byte-run--set-completion
+  #'(lambda (f _args val)
+      (list 'function-put (list 'quote f)
+            ''completion-predicate (list 'function val))))
+
+(defalias 'byte-run--set-modes
+  #'(lambda (f _args &rest val)
+      (list 'function-put (list 'quote f)
+            ''command-modes (list 'quote val))))
+
 ;; Add any new entries to info node `(elisp)Declare Form'.
 (defvar defun-declarations-alist
   (list
@@ -159,7 +172,9 @@ This may shift errors from run-time to compile-time.")
 If `error-free', drop calls even if `byte-compile-delete-errors' is nil.")
    (list 'compiler-macro #'byte-run--set-compiler-macro)
    (list 'doc-string #'byte-run--set-doc-string)
-   (list 'indent #'byte-run--set-indent))
+   (list 'indent #'byte-run--set-indent)
+   (list 'completion #'byte-run--set-completion)
+   (list 'modes #'byte-run--set-modes))
   "List associating function properties to their macro expansion.
 Each element of the list takes the form (PROP FUN) where FUN is
 a function.  For each (PROP . VALUES) in a function's declaration,
@@ -232,7 +247,7 @@ The return value is undefined.
                  #'(lambda (x)
                      (let ((f (cdr (assq (car x) macro-declarations-alist))))
                        (if f (apply (car f) name arglist (cdr x))
-                         (macroexp--warn-and-return
+                         (macroexp-warn-and-return
                           (format-message
                            "Unknown macro property %S in %S"
                            (car x) name)
@@ -305,7 +320,7 @@ The return value is undefined.
                               body)))
                     nil)
                    (t
-                    (macroexp--warn-and-return
+                    (macroexp-warn-and-return
                      (format-message "Unknown defun property `%S' in %S"
                                      (car x) name)
                      nil)))))
diff --git a/lisp/emacs-lisp/bytecomp.el b/lisp/emacs-lisp/bytecomp.el
index 89068a1..0babbbb 100644
--- a/lisp/emacs-lisp/bytecomp.el
+++ b/lisp/emacs-lisp/bytecomp.el
@@ -548,6 +548,10 @@ has the form (autoload . FILENAME).")
 
 (defvar byte-compile-unresolved-functions nil
   "Alist of undefined functions to which calls have been compiled.
+Each element in the list has the form (FUNCTION POSITION . CALLS)
+where CALLS is a list whose elements are integers (indicating the
+number of arguments passed in the function call) or the constant `t'
+if the function is called indirectly.
 This variable is only significant whilst compiling an entire buffer.
 Used for warnings when a function is not known to be defined or is later
 defined with incorrect args.")
@@ -1423,9 +1427,9 @@ when printing the error message."
       ;; Remember number of args in call.
       (let ((cons (assq f byte-compile-unresolved-functions)))
         (if cons
-            (or (memq nargs (cdr cons))
-                (push nargs (cdr cons)))
-          (push (list f nargs)
+            (or (memq nargs (cddr cons))
+                (push nargs (cddr cons)))
+          (push (list f byte-compile-last-position nargs)
                 byte-compile-unresolved-functions)))))
 
 ;; Warn if the form is calling a function with the wrong number of arguments.
@@ -1525,14 +1529,14 @@ extra args."
     (setq byte-compile-unresolved-functions
           (delq calls byte-compile-unresolved-functions))
     (setq calls (delq t calls))      ;Ignore higher-order uses of the function.
-    (when (cdr calls)
+    (when (cddr calls)
       (when (and (symbolp name)
                  (eq (function-get name 'byte-optimizer)
                      'byte-compile-inline-expand))
         (byte-compile-warn "defsubst `%s' was used before it was defined"
                            name))
       (setq sig (byte-compile-arglist-signature arglist)
-            nums (sort (copy-sequence (cdr calls)) (function <))
+            nums (sort (copy-sequence (cddr calls)) (function <))
             min (car nums)
             max (car (nreverse nums)))
       (when (or (< min (car sig))
@@ -1640,56 +1644,21 @@ It is too wide if it has any lines longer than the 
largest of
                            kind name col))))
   form)
 
-(defun byte-compile-print-syms (str1 strn syms)
-  (when syms
-    (byte-compile-set-symbol-position (car syms) t))
-  (cond ((and (cdr syms) (not noninteractive))
-        (let* ((str strn)
-               (L (length str))
-               s)
-          (while syms
-            (setq s (symbol-name (pop syms))
-                  L (+ L (length s) 2))
-            (if (< L (1- (buffer-local-value 'fill-column
-                                              (or (get-buffer
-                                                   byte-compile-log-buffer)
-                                                  (current-buffer)))))
-                (setq str (concat str " " s (and syms ",")))
-              (setq str (concat str "\n    " s (and syms ","))
-                    L (+ (length s) 4))))
-          (byte-compile-warn "%s" str)))
-       ((cdr syms)
-        (byte-compile-warn "%s %s"
-                           strn
-                           (mapconcat #'symbol-name syms ", ")))
-
-       (syms
-        (byte-compile-warn str1 (car syms)))))
-
 ;; If we have compiled any calls to functions which are not known to be
 ;; defined, issue a warning enumerating them.
 ;; `unresolved' in the list `byte-compile-warnings' disables this.
 (defun byte-compile-warn-about-unresolved-functions ()
   (when (byte-compile-warning-enabled-p 'unresolved)
-    (let ((byte-compile-current-form :end)
-         (noruntime nil)
-         (unresolved nil))
+    (let ((byte-compile-current-form :end))
       ;; Separate the functions that will not be available at runtime
       ;; from the truly unresolved ones.
-      (dolist (f byte-compile-unresolved-functions)
-        (setq f (car f))
-        (when (not (memq f byte-compile-new-defuns))
-          (if (fboundp f) (push f noruntime) (push f unresolved))))
-      ;; Complain about the no-run-time functions
-      (byte-compile-print-syms
-       "the function `%s' might not be defined at runtime."
-       "the following functions might not be defined at runtime:"
-       noruntime)
-      ;; Complain about the unresolved functions
-      (byte-compile-print-syms
-       "the function `%s' is not known to be defined."
-       "the following functions are not known to be defined:"
-       unresolved)))
+      (dolist (urf byte-compile-unresolved-functions)
+        (let ((f (car urf)))
+          (when (not (memq f byte-compile-new-defuns))
+            (let ((byte-compile-last-position (cadr urf)))
+              (byte-compile-warn
+               (if (fboundp f) "the function `%s' might not be defined at 
runtime." "the function `%s' is not known to be defined.")
+               (car urf))))))))
   nil)
 
 
@@ -1727,6 +1696,11 @@ It is too wide if it has any lines longer than the 
largest of
          ;;            (byte-compile-generate-emacs19-bytecodes
          ;;             byte-compile-generate-emacs19-bytecodes)
          (byte-compile-warnings byte-compile-warnings)
+         ;; Indicate that we're not currently loading some file.
+         ;; This is used in `macroexp-file-name' to make sure that
+         ;; loading file A which does (byte-compile-file B) won't
+         ;; cause macro calls in B to think they come from A.
+         (current-load-list (list nil))
          )
      ,@body))
 
@@ -2417,8 +2391,6 @@ list that represents a doc string reference.
              byte-compile-output nil
               byte-compile-jump-tables nil))))
 
-(defvar byte-compile-force-lexical-warnings nil)
-
 (defun byte-compile-preprocess (form &optional _for-effect)
   (setq form (macroexpand-all form byte-compile-macro-environment))
   ;; FIXME: We should run byte-optimize-form here, but it currently does not
@@ -2429,7 +2401,6 @@ list that represents a doc string reference.
   ;;     (setq form (byte-optimize-form form for-effect)))
   (cond
    (lexical-binding (cconv-closure-convert form))
-   (byte-compile-force-lexical-warnings (cconv-warnings-only form))
    (t form)))
 
 ;; byte-hunk-handlers cannot call this!
@@ -2495,12 +2466,14 @@ list that represents a doc string reference.
 (put 'defvar   'byte-hunk-handler 'byte-compile-file-form-defvar)
 (put 'defconst 'byte-hunk-handler 'byte-compile-file-form-defvar)
 
-(defun byte-compile--declare-var (sym)
+(defun byte-compile--check-prefixed-var (sym)
   (when (and (symbolp sym)
              (not (string-match "[-*/:$]" (symbol-name sym)))
              (byte-compile-warning-enabled-p 'lexical sym))
-    (byte-compile-warn "global/dynamic var `%s' lacks a prefix"
-                       sym))
+    (byte-compile-warn "global/dynamic var `%s' lacks a prefix" sym)))
+
+(defun byte-compile--declare-var (sym)
+  (byte-compile--check-prefixed-var sym)
   (when (memq sym byte-compile-lexical-variables)
     (setq byte-compile-lexical-variables
           (delq sym byte-compile-lexical-variables))
@@ -2783,16 +2756,12 @@ FUN should be either a `lambda' value or a `closure' 
value."
     (dolist (binding env)
       (cond
        ((consp binding)
-        ;; We check shadowing by the args, so that the `let' can be moved
-        ;; within the lambda, which can then be unfolded.  FIXME: Some of those
-        ;; bindings might be unused in `body'.
-        (unless (memq (car binding) args) ;Shadowed.
-          (push `(,(car binding) ',(cdr binding)) renv)))
+        (push `(,(car binding) ',(cdr binding)) renv))
        ((eq binding t))
        (t (push `(defvar ,binding) body))))
     (if (null renv)
         `(lambda ,args ,@preamble ,@body)
-      `(lambda ,args ,@preamble (let ,(nreverse renv) ,@body)))))
+      `(let ,renv (lambda ,args ,@preamble ,@body)))))
 
 ;;;###autoload
 (defun byte-compile (form)
@@ -2817,23 +2786,27 @@ If FORM is a lambda or a macro, byte-compile it as a 
function."
                  (if (symbolp form) form "provided"))
         fun)
        (t
-        (when (or (symbolp form) (eq (car-safe fun) 'closure))
-          ;; `fun' is a function *value*, so try to recover its corresponding
-          ;; source code.
-          (setq lexical-binding (eq (car fun) 'closure))
-          (setq fun (byte-compile--reify-function fun)))
-        ;; Expand macros.
-        (setq fun (byte-compile-preprocess fun))
-        (setq fun (byte-compile-top-level fun nil 'eval))
-        (if (symbolp form)
-            ;; byte-compile-top-level returns an *expression* equivalent to the
-            ;; `fun' expression, so we need to evaluate it, tho normally
-            ;; this is not needed because the expression is just a constant
-            ;; byte-code object, which is self-evaluating.
-            (setq fun (eval fun t)))
-        (if macro (push 'macro fun))
-        (if (symbolp form) (fset form fun))
-        fun))))))
+        (let (final-eval)
+          (when (or (symbolp form) (eq (car-safe fun) 'closure))
+            ;; `fun' is a function *value*, so try to recover its corresponding
+            ;; source code.
+            (setq lexical-binding (eq (car fun) 'closure))
+            (setq fun (byte-compile--reify-function fun))
+            (setq final-eval t))
+          ;; Expand macros.
+          (setq fun (byte-compile-preprocess fun))
+          (setq fun (byte-compile-top-level fun nil 'eval))
+          (if (symbolp form)
+              ;; byte-compile-top-level returns an *expression* equivalent to 
the
+              ;; `fun' expression, so we need to evaluate it, tho normally
+              ;; this is not needed because the expression is just a constant
+              ;; byte-code object, which is self-evaluating.
+              (setq fun (eval fun t)))
+          (if final-eval
+              (setq fun (eval fun t)))
+          (if macro (push 'macro fun))
+          (if (symbolp form) (fset form fun))
+          fun)))))))
 
 (defun byte-compile-sexp (sexp)
   "Compile and return SEXP."
@@ -2859,7 +2832,9 @@ If FORM is a lambda or a macro, byte-compile it as a 
function."
              ((eq arg '&optional)
                (when (memq '&optional (cdr list))
                  (error "Duplicate &optional")))
-             ((memq arg vars)
+             ((and (memq arg vars)
+                   ;; Allow repetitions for unused args.
+                   (not (string-match "\\`_" (symbol-name arg))))
               (byte-compile-warn "repeated variable %s in lambda-list" arg))
              (t
               (push arg vars))))
@@ -2939,7 +2914,8 @@ for symbols generated by the byte compiler itself."
                     ;; unless it is the last element of the body.
                     (if (cdr body)
                         (setq body (cdr body))))))
-        (int (assq 'interactive body)))
+        (int (assq 'interactive body))
+         command-modes)
     (when lexical-binding
       (dolist (var arglistvars)
         (when (assq var byte-compile--known-dynamic-vars)
@@ -2950,10 +2926,13 @@ for symbols generated by the byte compiler itself."
       ;; Skip (interactive) if it is in front (the most usual location).
       (if (eq int (car body))
          (setq body (cdr body)))
-      (cond ((consp (cdr int))
-            (if (cdr (cdr int))
-                (byte-compile-warn "malformed interactive spec: %s"
-                                   (prin1-to-string int)))
+      (cond ((consp (cdr int))       ; There is an `interactive' spec.
+             ;; Check that the bit after the `interactive' spec is
+             ;; just a list of symbols (i.e., modes).
+            (unless (seq-every-p #'symbolp (cdr (cdr int)))
+              (byte-compile-warn "malformed interactive specc: %s"
+                                 (prin1-to-string int)))
+             (setq command-modes (cdr (cdr int)))
             ;; If the interactive spec is a call to `list', don't
             ;; compile it, because `call-interactively' looks at the
             ;; args of `list'.  Actually, compile it to get warnings,
@@ -2964,15 +2943,14 @@ for symbols generated by the byte compiler itself."
                 (while (consp (cdr form))
                   (setq form (cdr form)))
                 (setq form (car form)))
-              (if (and (eq (car-safe form) 'list)
-                        ;; For code using lexical-binding, form is not
-                        ;; valid lisp, but rather an intermediate form
-                        ;; which may include "calls" to
-                        ;; internal-make-closure (Bug#29988).
-                        (not lexical-binding))
-                  nil
-                (setq int `(interactive ,newform)))))
-           ((cdr int)
+              (when (or (not (eq (car-safe form) 'list))
+                         ;; For code using lexical-binding, form is not
+                         ;; valid lisp, but rather an intermediate form
+                         ;; which may include "calls" to
+                         ;; internal-make-closure (Bug#29988).
+                         lexical-binding)
+                 (setq int `(interactive ,newform)))))
+            ((cdr int)                  ; Invalid (interactive . something).
             (byte-compile-warn "malformed interactive spec: %s"
                                (prin1-to-string int)))))
     ;; Process the body.
@@ -3002,9 +2980,16 @@ for symbols generated by the byte compiler itself."
                      (list (help-add-fundoc-usage doc arglist)))
                     ((or doc int)
                      (list doc)))
-              ;; optionally, the interactive spec.
-              (if int
-                  (list (nth 1 int))))))))
+              ;; optionally, the interactive spec (and the modes the
+              ;; command applies to).
+              (cond
+               ;; We have some command modes, so use the vector form.
+               (command-modes
+                (list (vector (nth 1 int) command-modes)))
+               ;; No command modes, use the simple form with just the
+               ;; interactive spec.
+               (int
+                (list (nth 1 int)))))))))
 
 (defvar byte-compile-reserved-constants 0)
 
@@ -3805,15 +3790,38 @@ discarding."
       (cl-assert (or (> (length env) 0)
                     docstring-exp))    ;Otherwise, we don't need a closure.
       (cl-assert (byte-code-function-p fun))
-      (byte-compile-form `(make-byte-code
-                           ',(aref fun 0) ',(aref fun 1)
-                           (vconcat (vector . ,env) ',(aref fun 2))
-                           ,@(let ((rest (nthcdr 3 (mapcar (lambda (x) `',x) 
fun))))
-                               (if docstring-exp
-                                   `(,(car rest)
-                                     ,docstring-exp
-                                     ,@(cddr rest))
-                                 rest)))))))
+      (byte-compile-form
+       (if (or (not docstring-exp) (stringp docstring-exp))
+           ;; Use symbols V0, V1 ... as placeholders for closure variables:
+           ;; they should be short (to save space in the .elc file), yet
+           ;; distinct when disassembled.
+           (let* ((dummy-vars (mapcar (lambda (i) (intern (format "V%d" i)))
+                                      (number-sequence 0 (1- (length env)))))
+                  (opt-args (mapcar (lambda (i) (aref fun i))
+                                    (number-sequence 4 (1- (length fun)))))
+                  (proto-fun
+                   (apply #'make-byte-code
+                          (aref fun 0) (aref fun 1)
+                          ;; Prepend dummy cells to the constant vector,
+                          ;; to get the indices right when disassembling.
+                          (vconcat dummy-vars (aref fun 2))
+                          (aref fun 3)
+                          (if docstring-exp
+                              (cons docstring-exp (cdr opt-args))
+                            opt-args))))
+             `(make-closure ,proto-fun ,@env))
+         ;; Nontrivial doc string expression: create a bytecode object
+         ;; from small pieces at run time.
+         `(make-byte-code
+           ',(aref fun 0) ',(aref fun 1)
+           (vconcat (vector . ,env) ',(aref fun 2))
+           ,@(let ((rest (nthcdr 3 (mapcar (lambda (x) `',x) fun))))
+               (if docstring-exp
+                   `(,(car rest)
+                     ,docstring-exp
+                     ,@(cddr rest))
+                 rest))))
+         ))))
 
 (defun byte-compile-get-closed-var (form)
   "Byte-compile the special `internal-get-closed-var' form."
@@ -4147,9 +4155,15 @@ that suppresses all warnings during execution of BODY."
                        byte-compile-unresolved-functions))
          (bound-list (byte-compile-find-bound-condition
                        ,condition '(boundp default-boundp local-variable-p)))
+          (new-bound-list
+           ;; (seq-difference  byte-compile-bound-variables))
+           (delq nil (mapcar (lambda (s)
+                               (if (memq s byte-compile-bound-variables) nil 
s))
+                             bound-list)))
          ;; Maybe add to the bound list.
          (byte-compile-bound-variables
-           (append bound-list byte-compile-bound-variables)))
+           (append new-bound-list byte-compile-bound-variables)))
+     (mapc #'byte-compile--check-prefixed-var new-bound-list)
      (unwind-protect
         ;; If things not being bound at all is ok, so must them being
         ;; obsolete.  Note that we add to the existing lists since Tramp
@@ -4867,10 +4881,10 @@ binding slots have been popped."
      (byte-compile-push-constant op)
      (byte-compile-form fun)
      (byte-compile-form prop)
-     (let* ((fun (eval fun))
-            (prop (eval prop))
+     (let* ((fun (eval fun t))
+            (prop (eval prop t))
             (val (if (macroexp-const-p val)
-                     (eval val)
+                     (eval val t)
                    (byte-compile-lambda (cadr val)))))
        (push `(,fun
                . (,prop ,val ,@(alist-get fun overriding-plist-environment)))
@@ -5188,8 +5202,9 @@ already up-to-date."
   "Reload any Lisp file that was changed since Emacs was dumped.
 Use with caution."
   (let* ((argv0 (car command-line-args))
-         (emacs-file (executable-find argv0)))
-    (if (not (and emacs-file (file-executable-p emacs-file)))
+         (emacs-file (or (cdr (nth 2 (pdumper-stats)))
+                         (executable-find argv0))))
+    (if (not (and emacs-file (file-exists-p emacs-file)))
         (message "Can't find %s to refresh preloaded Lisp files" argv0)
       (dolist (f (reverse load-history))
         (setq f (car f))
diff --git a/lisp/emacs-lisp/cconv.el b/lisp/emacs-lisp/cconv.el
index e795839..afaa13a 100644
--- a/lisp/emacs-lisp/cconv.el
+++ b/lisp/emacs-lisp/cconv.el
@@ -121,19 +121,22 @@
 (defconst cconv-liftwhen 6
   "Try to do lambda lifting if the number of arguments + free variables
 is less than this number.")
-;; List of all the variables that are both captured by a closure
-;; and mutated.  Each entry in the list takes the form
-;; (BINDER . PARENTFORM) where BINDER is the (VAR VAL) that introduces the
-;; variable (or is just (VAR) for variables not introduced by let).
-(defvar cconv-captured+mutated)
-
-;; List of candidates for lambda lifting.
-;; Each candidate has the form (BINDER . PARENTFORM).  A candidate
-;; is a variable that is only passed to `funcall' or `apply'.
-(defvar cconv-lambda-candidates)
-
-;; Alist associating to each function body the list of its free variables.
-(defvar cconv-freevars-alist)
+(defvar cconv-var-classification
+  ;; Alist mapping variables to a given class.
+  ;; The keys are of the form (BINDER . PARENTFORM) where BINDER
+  ;; is the (VAR VAL) that introduces it (or is just (VAR) for variables
+  ;; not introduced by let).
+  ;; The class can be one of:
+  ;; - :unused
+  ;; - :lambda-candidate
+  ;; - :captured+mutated
+  ;; - nil for "normal" variables, which would then just not appear
+  ;;   in the alist at all.
+  )
+
+(defvar cconv-freevars-alist
+  ;; Alist associating to each function body the list of its free variables.
+  )
 
 ;;;###autoload
 (defun cconv-closure-convert (form)
@@ -144,25 +147,13 @@ is less than this number.")
 Returns a form where all lambdas don't have any free variables."
   ;; (message "Entering cconv-closure-convert...")
   (let ((cconv-freevars-alist '())
-       (cconv-lambda-candidates '())
-       (cconv-captured+mutated '()))
+       (cconv-var-classification '()))
     ;; Analyze form - fill these variables with new information.
     (cconv-analyze-form form '())
     (setq cconv-freevars-alist (nreverse cconv-freevars-alist))
     (prog1 (cconv-convert form nil nil) ; Env initially empty.
       (cl-assert (null cconv-freevars-alist)))))
 
-;;;###autoload
-(defun cconv-warnings-only (form)
-  "Add the warnings that closure conversion would encounter."
-  (let ((cconv-freevars-alist '())
-       (cconv-lambda-candidates '())
-       (cconv-captured+mutated '()))
-    ;; Analyze form - fill these variables with new information.
-    (cconv-analyze-form form '())
-    ;; But don't perform the closure conversion.
-    form))
-
 (defconst cconv--dummy-var (make-symbol "ignored"))
 
 (defun cconv--set-diff (s1 s2)
@@ -261,28 +252,56 @@ Returns a form where all lambdas don't have any free 
variables."
                           (nthcdr 3 mapping)))))
           new-env))
 
+(defun cconv--warn-unused-msg (var varkind)
+  (unless (or ;; Uninterned symbols typically come from macro-expansion, so
+              ;; it is often non-trivial for the programmer to avoid such
+              ;; unused vars.
+              (not (intern-soft var))
+              (eq ?_ (aref (symbol-name var) 0))
+             ;; As a special exception, ignore "ignore".
+             (eq var 'ignored))
+       (let ((suggestions (help-uni-confusable-suggestions (symbol-name var))))
+         (format "Unused lexical %s `%S'%s"
+                 varkind var
+                 (if suggestions (concat "\n  " suggestions) "")))))
+
+(define-inline cconv--var-classification (binder form)
+  (inline-quote
+   (alist-get (cons ,binder ,form) cconv-var-classification
+              nil nil #'equal)))
+
 (defun cconv--convert-funcbody (funargs funcbody env parentform)
   "Run `cconv-convert' on FUNCBODY, the forms of a lambda expression.
 PARENTFORM is the form containing the lambda expression.  ENV is a
 lexical environment (same format as for `cconv-convert'), not
 including FUNARGS, the function's argument list.  Return a list
 of converted forms."
-  (let ((letbind ()))
+  (let ((wrappers ()))
     (dolist (arg funargs)
-      (if (not (member (cons (list arg) parentform) cconv-captured+mutated))
-          (if (assq arg env) (push `(,arg . nil) env))
-        (push `(,arg . (car-safe ,arg)) env)
-        (push `(,arg (list ,arg)) letbind)))
+      (pcase (cconv--var-classification (list arg) parentform)
+        (:captured+mutated
+         (push `(,arg . (car-safe ,arg)) env)
+         (push (lambda (body) `(let ((,arg (list ,arg))) ,body)) wrappers))
+        ((and :unused
+              (let (and (pred stringp) msg)
+                (cconv--warn-unused-msg arg "argument")))
+         (if (assq arg env) (push `(,arg . nil) env)) ;FIXME: Is it needed?
+         (push (lambda (body) (macroexp--warn-wrap msg body)) wrappers))
+        (_
+         (if (assq arg env) (push `(,arg . nil) env)))))
     (setq funcbody (mapcar (lambda (form)
                              (cconv-convert form env nil))
                            funcbody))
-    (if letbind
+    (if wrappers
         (let ((special-forms '()))
           ;; Keep special forms at the beginning of the body.
-          (while (or (stringp (car funcbody)) ;docstring.
-                     (memq (car-safe (car funcbody)) '(interactive declare)))
+          (while (or (and (cdr funcbody) (stringp (car funcbody))) ;docstring.
+                     (memq (car-safe (car funcbody))
+                           '(interactive declare :documentation)))
             (push (pop funcbody) special-forms))
-          `(,@(nreverse special-forms) (let ,letbind . ,funcbody)))
+          (let ((body (macroexp-progn funcbody)))
+            (dolist (wrapper wrappers) (setq body (funcall wrapper body)))
+            `(,@(nreverse special-forms) ,@(macroexp-unprogn body))))
       funcbody)))
 
 (defun cconv-convert (form env extend)
@@ -340,46 +359,58 @@ places where they originally did not directly appear."
                       (setq value (cadr binder))
                       (car binder)))
                (new-val
-                (cond
-                  ;; Check if var is a candidate for lambda lifting.
-                  ((and (member (cons binder form) cconv-lambda-candidates)
-                        (progn
-                          (cl-assert (and (eq (car value) 'function)
-                                          (eq (car (cadr value)) 'lambda)))
-                          (cl-assert (equal (cddr (cadr value))
-                                            (caar cconv-freevars-alist)))
-                          ;; Peek at the freevars to decide whether to λ-lift.
-                          (let* ((fvs (cdr (car cconv-freevars-alist)))
-                                 (fun (cadr value))
-                                 (funargs (cadr fun))
-                                 (funcvars (append fvs funargs)))
+                (pcase (cconv--var-classification binder form)
+                   ;; Check if var is a candidate for lambda lifting.
+                   ((and :lambda-candidate
+                         (guard
+                          (progn
+                            (cl-assert (and (eq (car value) 'function)
+                                            (eq (car (cadr value)) 'lambda)))
+                            (cl-assert (equal (cddr (cadr value))
+                                              (caar cconv-freevars-alist)))
+                            ;; Peek at the freevars to decide whether to 
λ-lift.
+                            (let* ((fvs (cdr (car cconv-freevars-alist)))
+                                   (fun (cadr value))
+                                   (funargs (cadr fun))
+                                   (funcvars (append fvs funargs)))
                                        ; lambda lifting condition
-                            (and fvs (>= cconv-liftwhen (length funcvars))))))
+                              (and fvs (>= cconv-liftwhen
+                                          (length funcvars)))))))
                                        ; Lift.
-                   (let* ((fvs (cdr (pop cconv-freevars-alist)))
-                          (fun (cadr value))
-                          (funargs (cadr fun))
-                          (funcvars (append fvs funargs))
-                          (funcbody (cddr fun))
-                          (funcbody-env ()))
-                     (push `(,var . (apply-partially ,var . ,fvs)) new-env)
-                     (dolist (fv fvs)
-                       (cl-pushnew fv new-extend)
-                       (if (and (eq 'car-safe (car-safe (cdr (assq fv env))))
-                                (not (memq fv funargs)))
-                           (push `(,fv . (car-safe ,fv)) funcbody-env)))
-                     `(function (lambda ,funcvars .
-                                  ,(cconv--convert-funcbody
-                                    funargs funcbody funcbody-env value)))))
+                    (let* ((fvs (cdr (pop cconv-freevars-alist)))
+                           (fun (cadr value))
+                           (funargs (cadr fun))
+                           (funcvars (append fvs funargs))
+                           (funcbody (cddr fun))
+                           (funcbody-env ()))
+                      (push `(,var . (apply-partially ,var . ,fvs)) new-env)
+                      (dolist (fv fvs)
+                        (cl-pushnew fv new-extend)
+                        (if (and (eq 'car-safe (car-safe (cdr (assq fv env))))
+                                 (not (memq fv funargs)))
+                            (push `(,fv . (car-safe ,fv)) funcbody-env)))
+                      `(function (lambda ,funcvars .
+                                   ,(cconv--convert-funcbody
+                                     funargs funcbody funcbody-env value)))))
 
                   ;; Check if it needs to be turned into a "ref-cell".
-                  ((member (cons binder form) cconv-captured+mutated)
+                  (:captured+mutated
                    ;; Declared variable is mutated and captured.
                    (push `(,var . (car-safe ,var)) new-env)
                    `(list ,(cconv-convert value env extend)))
 
+                  ;; Check if it needs to be turned into a "ref-cell".
+                  (:unused
+                   ;; Declared variable is unused.
+                   (if (assq var new-env) (push `(,var) new-env)) 
;FIXME:Needed?
+                   (let ((newval
+                          `(ignore ,(cconv-convert value env extend)))
+                         (msg (cconv--warn-unused-msg var "variable")))
+                     (if (null msg) newval
+                       (macroexp--warn-wrap msg newval))))
+
                   ;; Normal default case.
-                  (t
+                  (_
                    (if (assq var new-env) (push `(,var) new-env))
                    (cconv-convert value env extend)))))
 
@@ -464,22 +495,28 @@ places where they originally did not directly appear."
 
                                         ; condition-case
     (`(condition-case ,var ,protected-form . ,handlers)
-     `(condition-case ,var
-          ,(cconv-convert protected-form env extend)
-        ,@(let* ((cm (and var (member (cons (list var) form)
-                                      cconv-captured+mutated)))
-                 (newenv
-                  (cond (cm (cons `(,var . (car-save ,var)) env))
-                        ((assq var env) (cons `(,var) env))
-                        (t env))))
-            (mapcar
+     (let* ((class (and var (cconv--var-classification (list var) form)))
+            (newenv
+             (cond ((eq class :captured+mutated)
+                    (cons `(,var . (car-save ,var)) env))
+                   ((assq var env) (cons `(,var) env))
+                   (t env)))
+            (msg (when (eq class :unused)
+                   (cconv--warn-unused-msg var "variable")))
+            (newprotform (cconv-convert protected-form env extend)))
+       `(condition-case ,var
+            ,(if msg
+                 (macroexp--warn-wrap msg newprotform)
+               newprotform)
+          ,@(mapcar
              (lambda (handler)
                `(,(car handler)
                  ,@(let ((body
                           (mapcar (lambda (form)
                                     (cconv-convert form newenv extend))
                                   (cdr handler))))
-                     (if (not cm) body
+                     (if (not (eq class :captured+mutated))
+                         body
                        `((let ((,var (list ,var))) ,@body))))))
              handlers))))
 
@@ -548,9 +585,6 @@ places where they originally did not directly appear."
 
     (_ (or (cdr (assq form env)) form))))
 
-(unless (fboundp 'byte-compile-not-lexical-var-p)
-  ;; Only used to test the code in non-lexbind Emacs.
-  (defalias 'byte-compile-not-lexical-var-p 'boundp))
 (defvar byte-compile-lexical-variables)
 
 (defun cconv--analyze-use (vardata form varkind)
@@ -563,29 +597,28 @@ FORM is the parent form that binds this var."
     (`(,_ nil nil nil nil) nil)
     (`((,(and var (guard (eq ?_ (aref (symbol-name var) 0)))) . ,_)
        ,_ ,_ ,_ ,_)
+     ;; FIXME: Convert this warning to use `macroexp--warn-wrap'
+     ;; so as to give better position information.
      (byte-compile-warn
-      "%s `%S' not left unused" varkind var)))
+      "%s `%S' not left unused" varkind var))
+    ((and (let (or 'let* 'let) (car form))
+          `((,var) ;; (or `(,var nil) : Too many false positives: bug#47080
+            t nil ,_ ,_))
+     ;; FIXME: Convert this warning to use `macroexp--warn-wrap'
+     ;; so as to give better position information.
+     (unless (not (intern-soft var))
+       (byte-compile-warn "Variable `%S' left uninitialized" var))))
   (pcase vardata
-    (`((,var . ,_) nil ,_ ,_ nil)
-     ;; FIXME: This gives warnings in the wrong order, with imprecise line
-     ;; numbers and without function name info.
-     (unless (or ;; Uninterned symbols typically come from macro-expansion, so
-              ;; it is often non-trivial for the programmer to avoid such
-              ;; unused vars.
-              (not (intern-soft var))
-              (eq ?_ (aref (symbol-name var) 0))
-             ;; As a special exception, ignore "ignore".
-             (eq var 'ignored))
-       (let ((suggestions (help-uni-confusable-suggestions (symbol-name var))))
-         (byte-compile-warn "Unused lexical %s `%S'%s"
-                            varkind var
-                            (if suggestions (concat "\n  " suggestions) "")))))
+    (`(,binder nil ,_ ,_ nil)
+     (push (cons (cons binder form) :unused) cconv-var-classification))
     ;; If it's unused, there's no point converting it into a cons-cell, even if
     ;; it's captured and mutated.
     (`(,binder ,_ t t ,_)
-     (push (cons binder form) cconv-captured+mutated))
+     (push (cons (cons binder form) :captured+mutated)
+           cconv-var-classification))
     (`(,(and binder `(,_ (function (lambda . ,_)))) nil nil nil t)
-     (push (cons binder form) cconv-lambda-candidates))))
+     (push (cons (cons binder form) :lambda-candidate)
+           cconv-var-classification))))
 
 (defun cconv--analyze-function (args body env parentform)
   (let* ((newvars nil)
@@ -638,8 +671,7 @@ Analyze lambdas if they are suitable for lambda lifting.
 - ENV is an alist mapping each enclosing lexical variable to its info.
    I.e. each element has the form (VAR . (READ MUTATED CAPTURED CALLED)).
 This function does not return anything but instead fills the
-`cconv-captured+mutated' and `cconv-lambda-candidates' variables
-and updates the data stored in ENV."
+`cconv-var-classification' variable and updates the data stored in ENV."
   (pcase form
                                        ; let special form
     (`(,(and (or 'let* 'let) letsym) ,binders . ,body-forms)
@@ -756,7 +788,7 @@ and updates the data stored in ENV."
      (let ((dv (assq form env)))        ; dv = declared and visible
        (when dv
          (setf (nth 1 dv) t))))))
-(define-obsolete-function-alias 'cconv-analyse-form 'cconv-analyze-form "25.1")
+(define-obsolete-function-alias 'cconv-analyse-form #'cconv-analyze-form 
"25.1")
 
 (provide 'cconv)
 ;;; cconv.el ends here
diff --git a/lisp/emacs-lisp/chart.el b/lisp/emacs-lisp/chart.el
index 7d760ff..5afc6d3 100644
--- a/lisp/emacs-lisp/chart.el
+++ b/lisp/emacs-lisp/chart.el
@@ -89,33 +89,39 @@ Useful if new Emacs is used on B&W display.")
 
 (declare-function x-display-color-cells "xfns.c" (&optional terminal))
 
-(defvar chart-face-list
-  (if (display-color-p)
-      (let ((cl chart-face-color-list)
-            (pl chart-face-pixmap-list)
-            (faces ())
-            nf)
-        (while cl
-          (setq nf (make-face
-                    (intern (concat "chart-" (car cl) "-" (car pl)))))
-          (set-face-background nf (if (condition-case nil
-                                          (> (x-display-color-cells) 4)
-                                        (error t))
-                                      (car cl)
-                                    "white"))
-          (set-face-foreground nf "black")
-          (if (and chart-face-use-pixmaps pl)
-              (condition-case nil
-                  (set-face-background-pixmap nf (car pl))
-                (error (message "Cannot set background pixmap %s" (car pl)))))
-          (push nf faces)
-          (setq cl (cdr cl)
-                pl (cdr pl)))
-        faces))
+(defvar chart-face-list #'chart--face-list
   "Faces used to colorize charts.
+This should either be a list of faces, or a function that returns
+a list of faces.
+
 List is limited currently, which is ok since you really can't display
 too much in text characters anyways.")
 
+(defun chart--face-list ()
+  (and
+   (display-color-p)
+   (let ((cl chart-face-color-list)
+         (pl chart-face-pixmap-list)
+         (faces ())
+         nf)
+     (while cl
+       (setq nf (make-face
+                 (intern (concat "chart-" (car cl) "-" (car pl)))))
+       (set-face-background nf (if (condition-case nil
+                                       (> (x-display-color-cells) 4)
+                                     (error t))
+                                   (car cl)
+                                 "white"))
+       (set-face-foreground nf "black")
+       (if (and chart-face-use-pixmaps pl)
+           (condition-case nil
+               (set-face-background-pixmap nf (car pl))
+             (error (message "Cannot set background pixmap %s" (car pl)))))
+       (push nf faces)
+       (setq cl (cdr cl)
+             pl (cdr pl)))
+     faces)))
+
 (define-derived-mode chart-mode special-mode "Chart"
   "Define a mode in Emacs for displaying a chart."
   (buffer-disable-undo)
@@ -187,7 +193,7 @@ Make sure the width/height is correct."
    )
   "Class used to display an axis which represents different named items.")
 
-(defclass chart-sequece ()
+(defclass chart-sequence ()
   ((data :initarg :data
         :initform nil)
    (name :initarg :name
@@ -374,7 +380,10 @@ of the drawing."
   (let* ((data (oref c sequences))
         (dir (oref c direction))
         (odir (if (eq dir 'vertical) 'horizontal 'vertical))
-       )
+         (faces
+          (if (functionp chart-face-list)
+              (funcall chart-face-list)
+            chart-face-list)))
     (while data
       (if (stringp (car (oref (car data) data)))
          ;; skip string lists...
@@ -390,10 +399,9 @@ of the drawing."
                  (zp (if (eq dir 'vertical)
                          (chart-translate-ypos c 0)
                        (chart-translate-xpos c 0)))
-                 (fc (if chart-face-list
-                         (nth (% i (length chart-face-list)) chart-face-list)
-                       'default))
-                 )
+                 (fc (if faces
+                         (nth (% i (length faces)) faces)
+                       'default)))
              (if (< dp zp)
                  (progn
                    (chart-draw-line dir (car rng) dp zp)
@@ -583,12 +591,12 @@ SORT-PRED if desired."
                           ))
        (iv (eq dir 'vertical)))
     (chart-add-sequence nc
-                       (make-instance 'chart-sequece
+                       (make-instance 'chart-sequence
                                       :data namelst
                                       :name nametitle)
                        (if iv 'x-axis 'y-axis))
     (chart-add-sequence nc
-                       (make-instance 'chart-sequece
+                       (make-instance 'chart-sequence
                                       :data numlst
                                       :name numtitle)
                        (if iv 'y-axis 'x-axis))
diff --git a/lisp/emacs-lisp/checkdoc.el b/lisp/emacs-lisp/checkdoc.el
index 75aefdc..6285166 100644
--- a/lisp/emacs-lisp/checkdoc.el
+++ b/lisp/emacs-lisp/checkdoc.el
@@ -931,16 +931,20 @@ don't move point."
                            ;; Don't bug out if the file is empty (or a
                            ;; definition ends prematurely.
                            (end-of-file)))
-    (`(,(or 'defun 'defvar 'defcustom 'defmacro 'defconst 'defsubst 'defadvice
-            'cl-defun 'cl-defgeneric 'cl-defmethod 'cl-defmacro)
+    (`(,(and (pred symbolp) def
+             (let (and doc (guard doc)) (function-get def 'doc-string-elt)))
        ,(pred symbolp)
        ;; Require an initializer, i.e. ignore single-argument `defvar'
        ;; forms, which never have a doc string.
        ,_ . ,_)
      (down-list)
-     ;; Skip over function or macro name, symbol to be defined, and
-     ;; initializer or argument list.
-     (forward-sexp 3)
+     ;; Skip over function or macro name.
+     (forward-sexp 1)
+     ;; And now skip until the docstring.
+     (forward-sexp (1- ; We already skipped the function or macro name.
+                    (cond
+                     ((numberp doc) doc)
+                     ((functionp doc) (funcall doc)))))
      (skip-chars-forward " \n\t")
      t)))
 
@@ -2130,8 +2134,8 @@ buffer, otherwise stop after the first error."
       (user-error "No spellchecker installed: check the variable 
`ispell-program-name'"))
     (save-excursion
       (skip-chars-forward "^a-zA-Z")
-      (let (word sym case-fold-search err word-beginning word-end)
-        (while (and (not err) (< (point) end))
+      (let (word sym case-fold-search word-beginning word-end) ;; err
+        (while (and (< (point) end)) ;; (not err)
           (if (save-excursion (forward-char -1) (looking-at "[('`]"))
               ;; Skip lists describing meta-syntax, or bound variables
               (forward-sexp 1)
@@ -2163,7 +2167,7 @@ buffer, otherwise stop after the first error."
                           (sit-for 0)
                           (message "Continuing..."))))))))
           (skip-chars-forward "^a-zA-Z"))
-        err))))
+        nil)))) ;; err
 
 ;;; Rogue space checking engine
 ;;
diff --git a/lisp/emacs-lisp/cl-extra.el b/lisp/emacs-lisp/cl-extra.el
index 28ce6b1..eabba27 100644
--- a/lisp/emacs-lisp/cl-extra.el
+++ b/lisp/emacs-lisp/cl-extra.el
@@ -94,7 +94,7 @@ strings case-insensitively."
 (defun cl--mapcar-many (cl-func cl-seqs &optional acc)
   (if (cdr (cdr cl-seqs))
       (let* ((cl-res nil)
-            (cl-n (apply 'min (mapcar 'length cl-seqs)))
+            (cl-n (apply #'min (mapcar #'length cl-seqs)))
             (cl-i 0)
             (cl-args (copy-sequence cl-seqs))
             cl-p1 cl-p2)
@@ -131,7 +131,7 @@ strings case-insensitively."
   "Map a FUNCTION across one or more SEQUENCEs, returning a sequence.
 TYPE is the sequence type to return.
 \n(fn TYPE FUNCTION SEQUENCE...)"
-  (let ((cl-res (apply 'cl-mapcar cl-func cl-seq cl-rest)))
+  (let ((cl-res (apply #'cl-mapcar cl-func cl-seq cl-rest)))
     (and cl-type (cl-coerce cl-res cl-type))))
 
 ;;;###autoload
@@ -190,14 +190,14 @@ the elements themselves.
   "Like `cl-mapcar', but nconc's together the values returned by the function.
 \n(fn FUNCTION SEQUENCE...)"
   (if cl-rest
-      (apply 'nconc (apply 'cl-mapcar cl-func cl-seq cl-rest))
+      (apply #'nconc (apply #'cl-mapcar cl-func cl-seq cl-rest))
     (mapcan cl-func cl-seq)))
 
 ;;;###autoload
 (defun cl-mapcon (cl-func cl-list &rest cl-rest)
   "Like `cl-maplist', but nconc's together the values returned by the function.
 \n(fn FUNCTION LIST...)"
-  (apply 'nconc (apply 'cl-maplist cl-func cl-list cl-rest)))
+  (apply #'nconc (apply #'cl-maplist cl-func cl-list cl-rest)))
 
 ;;;###autoload
 (defun cl-some (cl-pred cl-seq &rest cl-rest)
@@ -236,13 +236,13 @@ non-nil value.
 (defun cl-notany (cl-pred cl-seq &rest cl-rest)
   "Return true if PREDICATE is false of every element of SEQ or SEQs.
 \n(fn PREDICATE SEQ...)"
-  (not (apply 'cl-some cl-pred cl-seq cl-rest)))
+  (not (apply #'cl-some cl-pred cl-seq cl-rest)))
 
 ;;;###autoload
 (defun cl-notevery (cl-pred cl-seq &rest cl-rest)
   "Return true if PREDICATE is false of some element of SEQ or SEQs.
 \n(fn PREDICATE SEQ...)"
-  (not (apply 'cl-every cl-pred cl-seq cl-rest)))
+  (not (apply #'cl-every cl-pred cl-seq cl-rest)))
 
 ;;;###autoload
 (defun cl--map-keymap-recursively (cl-func-rec cl-map &optional cl-base)
@@ -693,12 +693,11 @@ PROPLIST is a list of the sort returned by `symbol-plist'.
   "Expand macros in FORM and insert the pretty-printed result."
   (declare (advertised-calling-convention (form) "27.1"))
   (message "Expanding...")
-  (let ((byte-compile-macro-environment nil))
-    (setq form (macroexpand-all form))
-    (message "Formatting...")
-    (prog1
-        (cl-prettyprint form)
-      (message ""))))
+  (setq form (macroexpand-all form))
+  (message "Formatting...")
+  (prog1
+      (cl-prettyprint form)
+    (message "")))
 
 ;;; Integration into the online help system.
 
@@ -898,8 +897,8 @@ Outputs to the current buffer."
                (list (cl-prin1-to-string (cl--slot-descriptor-name slot))
                      (cl-prin1-to-string (cl--slot-descriptor-type slot))
                      (cl-prin1-to-string (cl--slot-descriptor-initform slot))
-                     (let ((doc (alist-get :documentation
-                                           (cl--slot-descriptor-props slot))))
+                     (let ((doc (plist-get (cl--slot-descriptor-props slot)
+                                           :documentation)))
                        (if (not doc) ""
                          (setq has-doc t)
                          (substitute-command-keys doc)))))
diff --git a/lisp/emacs-lisp/cl-generic.el b/lisp/emacs-lisp/cl-generic.el
index 8e36dbe..f5b8c7b 100644
--- a/lisp/emacs-lisp/cl-generic.el
+++ b/lisp/emacs-lisp/cl-generic.el
@@ -189,6 +189,32 @@ SPECIALIZERS-FUNCTION takes as first argument a tag value 
TAG
       (setf (cl--generic name) (setq generic (cl--generic-make name))))
     generic))
 
+(defvar cl--generic-edebug-name nil)
+
+(defun cl--generic-edebug-remember-name (name pf &rest specs)
+  ;; Remember the name in `cl-defgeneric' so we can use it when building
+  ;; the names of its `:methods'.
+  (let ((cl--generic-edebug-name (car name)))
+    (funcall pf specs)))
+
+(defun cl--generic-edebug-make-name (in:method _oldname &rest quals-and-args)
+  ;; The name to use in Edebug for a method: use the generic
+  ;; function's name plus all its qualifiers and finish with
+  ;; its specializers.
+  (pcase-let*
+      ((basename (if in:method cl--generic-edebug-name (pop quals-and-args)))
+       (args (car (last quals-and-args)))
+       (`(,spec-args . ,_) (cl--generic-split-args args))
+       (specializers (mapcar (lambda (spec-arg)
+                               (if (eq '&context (car-safe (car spec-arg)))
+                                   spec-arg (cdr spec-arg)))
+                             spec-args)))
+    (format "%s %s"
+            (mapconcat (lambda (sexp) (format "%s" sexp))
+                       (cons basename (butlast quals-and-args))
+                       " ")
+            specializers)))
+
 ;;;###autoload
 (defmacro cl-defgeneric (name args &rest options-and-methods)
   "Create a generic function NAME.
@@ -206,24 +232,22 @@ DEFAULT-BODY, if present, is used as the body of a 
default method.
 \(fn NAME ARGS [DOC-STRING] [OPTIONS-AND-METHODS...] &rest DEFAULT-BODY)"
   (declare (indent 2) (doc-string 3)
            (debug
-            (&define [&or name ("setf" name :name setf)] listp
-                     lambda-doc
-                     [&rest [&or
-                             ("declare" &rest sexp)
-                             (":argument-precedence-order" &rest sexp)
-                             (&define ":method"
-                                      ;; FIXME: The `:unique'
-                                      ;; construct works around
-                                      ;; Bug#42672.  We'd rather want
-                                      ;; names like those generated by
-                                      ;; `cl-defmethod', but that
-                                      ;; requires larger changes to
-                                      ;; Edebug.
-                                      :unique "cl-generic-:method@"
-                                      [&rest cl-generic-method-qualifier]
-                                      cl-generic-method-args lambda-doc
-                                      def-body)]]
-                     def-body)))
+            (&define
+             &interpose
+             [&name sexp] ;Allow (setf ...) additionally to symbols.
+             cl--generic-edebug-remember-name
+             listp lambda-doc
+             [&rest [&or
+                     ("declare" &rest sexp)
+                     (":argument-precedence-order" &rest sexp)
+                     (&define ":method"
+                              [&name
+                               [[&rest cl-generic--method-qualifier-p]
+                                listp] ;Formal args
+                               cl--generic-edebug-make-name in:method]
+                              lambda-doc
+                              def-body)]]
+             def-body)))
   (let* ((doc (if (stringp (car-safe options-and-methods))
                   (pop options-and-methods)))
          (declarations nil)
@@ -398,6 +422,19 @@ the specializer used will be the one returned by BODY."
       (let ((combined-doc (buffer-string)))
         (if ud (help-add-fundoc-usage combined-doc (car ud)) combined-doc)))))
 
+(defun cl-generic--method-qualifier-p (x)
+  (not (listp x)))
+
+(defun cl--defmethod-doc-pos ()
+  "Return the index of the docstring for a `cl-defmethod'.
+Presumes point is at the end of the `cl-defmethod' symbol."
+  (save-excursion
+    (let ((n 2))
+      (while (and (ignore-errors (forward-sexp 1) t)
+                  (not (eq (char-before) ?\))))
+        (cl-incf n))
+      n)))
+
 ;;;###autoload
 (defmacro cl-defmethod (name args &rest body)
   "Define a new method for generic function NAME.
@@ -418,8 +455,12 @@ all methods of NAME have to use the same set of arguments 
for dispatch.
 Each dispatch argument and TYPE are specified in ARGS where the corresponding
 formal argument appears as (VAR TYPE) rather than just VAR.
 
-The optional second argument QUALIFIER is a specifier that
-modifies how the method is combined with other methods, including:
+The optional EXTRA element, on the form `:extra STRING', allows
+you to add more methods for the same specializers and qualifiers.
+These are distinguished by STRING.
+
+The optional argument QUALIFIER is a specifier that modifies how
+the method is combined with other methods, including:
    :before  - Method will be called before the primary
    :after   - Method will be called after the primary
    :around  - Method will be called around everything else
@@ -436,19 +477,18 @@ method to be applicable.
 The set of acceptable TYPEs (also called \"specializers\") is defined
 \(and can be extended) by the various methods of `cl-generic-generalizers'.
 
-\(fn NAME [QUALIFIER] ARGS &rest [DOCSTRING] BODY)"
-  (declare (doc-string 3) (indent defun)
+\(fn NAME [EXTRA] [QUALIFIER] ARGS &rest [DOCSTRING] BODY)"
+  (declare (doc-string cl--defmethod-doc-pos) (indent defun)
            (debug
             (&define                    ; this means we are defining something
-             [&or name ("setf" name :name setf)]
-             ;; ^^ This is the methods symbol
-             [ &rest cl-generic-method-qualifier ]
-             ;; Multiple qualifiers are allowed.
-             cl-generic-method-args     ; arguments
+             [&name [sexp   ;Allow (setf ...) additionally to symbols.
+                     [&rest cl-generic--method-qualifier-p] ;qualifiers
+                     listp]             ; arguments
+                    cl--generic-edebug-make-name nil]
              lambda-doc                 ; documentation string
              def-body)))                ; part to be debugged
   (let ((qualifiers nil))
-    (while (not (listp args))
+    (while (cl-generic--method-qualifier-p args)
       (push args qualifiers)
       (setq args (pop body)))
     (when (eq 'setf (car-safe name))
@@ -461,7 +501,7 @@ The set of acceptable TYPEs (also called \"specializers\") 
is defined
                (or (not (fboundp 'byte-compile-warning-enabled-p))
                    (byte-compile-warning-enabled-p 'obsolete name))
                (let* ((obsolete (get name 'byte-obsolete-info)))
-                 (macroexp--warn-and-return
+                 (macroexp-warn-and-return
                   (macroexp--obsolete-warning name obsolete "generic function")
                   nil)))
          ;; You could argue that `defmethod' modifies rather than defines the
diff --git a/lisp/emacs-lisp/cl-lib.el b/lisp/emacs-lisp/cl-lib.el
index 3bf3fd2..7f7eb96 100644
--- a/lisp/emacs-lisp/cl-lib.el
+++ b/lisp/emacs-lisp/cl-lib.el
@@ -140,7 +140,7 @@ to an element already in the list stored in PLACE.
 \n(fn X PLACE [KEYWORD VALUE]...)"
   (declare (debug
             (form place &rest
-                  &or [[&or ":test" ":test-not" ":key"] function-form]
+                  &or [[&or ":test" ":test-not" ":key"] form]
                   [keywordp form])))
   (if (symbolp place)
       (if (null keys)
@@ -232,13 +232,8 @@ one value.
 
 ;;; Declarations.
 
-(defvar cl--compiling-file nil)
-(defun cl--compiling-file ()
-  (or cl--compiling-file
-      (and (boundp 'byte-compile--outbuffer)
-           (bufferp (symbol-value 'byte-compile--outbuffer))
-          (equal (buffer-name (symbol-value 'byte-compile--outbuffer))
-                 " *Compiler Output*"))))
+(define-obsolete-function-alias 'cl--compiling-file
+  #'macroexp-compiling-p "28.1")
 
 (defvar cl--proclaims-deferred nil)
 
@@ -253,7 +248,7 @@ one value.
 Puts `(cl-eval-when (compile load eval) ...)' around the declarations
 so that they are registered at compile-time as well as run-time."
   (let ((body (mapcar (lambda (x) `(cl-proclaim ',x)) specs)))
-    (if (cl--compiling-file) `(cl-eval-when (compile load eval) ,@body)
+    (if (macroexp-compiling-p) `(cl-eval-when (compile load eval) ,@body)
       `(progn ,@body))))           ; Avoid loading cl-macs.el for cl-eval-when.
 
 
diff --git a/lisp/emacs-lisp/cl-macs.el b/lisp/emacs-lisp/cl-macs.el
index c2bf02c..27ed07b 100644
--- a/lisp/emacs-lisp/cl-macs.el
+++ b/lisp/emacs-lisp/cl-macs.el
@@ -186,14 +186,14 @@ The name is made by appending a number to PREFIX, default 
\"T\"."
 
 ;;; Program structure.
 
-(def-edebug-spec cl-declarations
-  (&rest ("cl-declare" &rest sexp)))
+(def-edebug-elem-spec 'cl-declarations
+  '(&rest ("cl-declare" &rest sexp)))
 
-(def-edebug-spec cl-declarations-or-string
-  (&or lambda-doc cl-declarations))
+(def-edebug-elem-spec 'cl-declarations-or-string
+  '(lambda-doc &or ("declare" def-declarations) cl-declarations))
 
-(def-edebug-spec cl-lambda-list
-  (([&rest cl-lambda-arg]
+(def-edebug-elem-spec 'cl-lambda-list
+  '(([&rest cl-lambda-arg]
     [&optional ["&optional" cl-&optional-arg &rest cl-&optional-arg]]
     [&optional ["&rest" cl-lambda-arg]]
     [&optional ["&key" [cl-&key-arg &rest cl-&key-arg]
@@ -202,27 +202,27 @@ The name is made by appending a number to PREFIX, default 
\"T\"."
                &or (cl-lambda-arg &optional def-form) arg]]
     . [&or arg nil])))
 
-(def-edebug-spec cl-&optional-arg
-  (&or (cl-lambda-arg &optional def-form arg) arg))
+(def-edebug-elem-spec 'cl-&optional-arg
+  '(&or (cl-lambda-arg &optional def-form arg) arg))
 
-(def-edebug-spec cl-&key-arg
-  (&or ([&or (symbolp cl-lambda-arg) arg] &optional def-form arg) arg))
+(def-edebug-elem-spec 'cl-&key-arg
+  '(&or ([&or (symbolp cl-lambda-arg) arg] &optional def-form arg) arg))
 
-(def-edebug-spec cl-lambda-arg
-  (&or arg cl-lambda-list1))
+(def-edebug-elem-spec 'cl-lambda-arg
+  '(&or arg cl-lambda-list1))
 
-(def-edebug-spec cl-lambda-list1
-  (([&optional ["&whole" arg]]  ;; only allowed at lower levels
-    [&rest cl-lambda-arg]
-    [&optional ["&optional" cl-&optional-arg &rest cl-&optional-arg]]
-    [&optional ["&rest" cl-lambda-arg]]
-    [&optional ["&key" cl-&key-arg &rest cl-&key-arg
-                &optional "&allow-other-keys"]]
-    [&optional ["&aux" &rest
-                &or (cl-lambda-arg &optional def-form) arg]]
-    . [&or arg nil])))
+(def-edebug-elem-spec 'cl-lambda-list1
+  '(([&optional ["&whole" arg]] ;; only allowed at lower levels
+     [&rest cl-lambda-arg]
+     [&optional ["&optional" cl-&optional-arg &rest cl-&optional-arg]]
+     [&optional ["&rest" cl-lambda-arg]]
+     [&optional ["&key" cl-&key-arg &rest cl-&key-arg
+                 &optional "&allow-other-keys"]]
+     [&optional ["&aux" &rest
+                 &or (cl-lambda-arg &optional def-form) arg]]
+     . [&or arg nil])))
 
-(def-edebug-spec cl-type-spec sexp)
+(def-edebug-elem-spec 'cl-type-spec '(sexp))
 
 (defconst cl--lambda-list-keywords
   '(&optional &rest &key &allow-other-keys &aux &whole &body &environment))
@@ -358,7 +358,7 @@ more details.
 \(fn NAME ARGLIST [DOCSTRING] BODY...)"
   (declare (debug
             ;; Same as defun but use cl-lambda-list.
-            (&define [&or name ("setf" :name setf name)]
+            (&define [&name sexp]   ;Allow (setf ...) additionally to symbols.
                      cl-lambda-list
                      cl-declarations-or-string
                      [&optional ("interactive" interactive)]
@@ -376,7 +376,7 @@ and BODY is implicitly surrounded by (cl-block NAME ...).
 \(fn NAME ARGLIST [DOCSTRING] BODY...)"
   (declare (debug
             ;; Same as iter-defun but use cl-lambda-list.
-            (&define [&or name ("setf" :name setf name)]
+            (&define [&name sexp]   ;Allow (setf ...) additionally to symbols.
                      cl-lambda-list
                      cl-declarations-or-string
                      [&optional ("interactive" interactive)]
@@ -390,39 +390,39 @@ and BODY is implicitly surrounded by (cl-block NAME ...).
 ;; Note that &environment is only allowed as first or last items in the
 ;; top level list.
 
-(def-edebug-spec cl-macro-list
-  (([&optional "&environment" arg]
-    [&rest cl-macro-arg]
-    [&optional ["&optional" &rest
-               &or (cl-macro-arg &optional def-form cl-macro-arg) arg]]
-    [&optional [[&or "&rest" "&body"] cl-macro-arg]]
-    [&optional ["&key" [&rest
-                       [&or ([&or (symbolp cl-macro-arg) arg]
-                             &optional def-form cl-macro-arg)
-                            arg]]
-               &optional "&allow-other-keys"]]
-    [&optional ["&aux" &rest
-               &or (cl-macro-arg &optional def-form) arg]]
-    [&optional "&environment" arg]
-    )))
-
-(def-edebug-spec cl-macro-arg
-  (&or arg cl-macro-list1))
-
-(def-edebug-spec cl-macro-list1
-  (([&optional "&whole" arg]  ;; only allowed at lower levels
-    [&rest cl-macro-arg]
-    [&optional ["&optional" &rest
-               &or (cl-macro-arg &optional def-form cl-macro-arg) arg]]
-    [&optional [[&or "&rest" "&body"] cl-macro-arg]]
-    [&optional ["&key" [&rest
-                       [&or ([&or (symbolp cl-macro-arg) arg]
-                             &optional def-form cl-macro-arg)
-                            arg]]
-               &optional "&allow-other-keys"]]
-    [&optional ["&aux" &rest
-               &or (cl-macro-arg &optional def-form) arg]]
-    . [&or arg nil])))
+(def-edebug-elem-spec 'cl-macro-list
+  '(([&optional "&environment" arg]
+     [&rest cl-macro-arg]
+     [&optional ["&optional" &rest
+                &or (cl-macro-arg &optional def-form cl-macro-arg) arg]]
+     [&optional [[&or "&rest" "&body"] cl-macro-arg]]
+     [&optional ["&key" [&rest
+                        [&or ([&or (symbolp cl-macro-arg) arg]
+                              &optional def-form cl-macro-arg)
+                             arg]]
+                &optional "&allow-other-keys"]]
+     [&optional ["&aux" &rest
+                &or (cl-macro-arg &optional def-form) arg]]
+     [&optional "&environment" arg]
+     )))
+
+(def-edebug-elem-spec 'cl-macro-arg
+  '(&or arg cl-macro-list1))
+
+(def-edebug-elem-spec 'cl-macro-list1
+  '(([&optional "&whole" arg] ;; only allowed at lower levels
+     [&rest cl-macro-arg]
+     [&optional ["&optional" &rest
+                &or (cl-macro-arg &optional def-form cl-macro-arg) arg]]
+     [&optional [[&or "&rest" "&body"] cl-macro-arg]]
+     [&optional ["&key" [&rest
+                        [&or ([&or (symbolp cl-macro-arg) arg]
+                              &optional def-form cl-macro-arg)
+                             arg]]
+                &optional "&allow-other-keys"]]
+     [&optional ["&aux" &rest
+                &or (cl-macro-arg &optional def-form) arg]]
+     . [&or arg nil])))
 
 ;;;###autoload
 (defmacro cl-defmacro (name args &rest body)
@@ -452,19 +452,19 @@ more details.
            (indent 2))
   `(defmacro ,name ,@(cl--transform-lambda (cons args body) name)))
 
-(def-edebug-spec cl-lambda-expr
-  (&define ("lambda" cl-lambda-list
-           cl-declarations-or-string
-           [&optional ("interactive" interactive)]
-           def-body)))
+(def-edebug-elem-spec 'cl-lambda-expr
+  '(&define ("lambda" cl-lambda-list
+            cl-declarations-or-string
+            [&optional ("interactive" interactive)]
+            def-body)))
 
 ;; Redefine function-form to also match cl-function
-(def-edebug-spec function-form
+(def-edebug-elem-spec 'function-form
   ;; form at the end could also handle "function",
   ;; but recognize it specially to avoid wrapping function forms.
-  (&or ([&or "quote" "function"] &or symbolp lambda-expr)
-       ("cl-function" cl-function)
-       form))
+  '(&or ([&or "quote" "function"] &or symbolp lambda-expr)
+        ("cl-function" cl-function)
+        form))
 
 ;;;###autoload
 (defmacro cl-function (func)
@@ -545,7 +545,7 @@ its argument list allows full Common Lisp conventions."
     (let ((p (memq '&body args))) (if p (setcar p '&rest)))
     (if (memq '&environment args) (error "&environment used incorrectly"))
     (let ((restarg (memq '&rest args))
-         (safety (if (cl--compiling-file) cl--optimize-safety 3))
+         (safety (if (macroexp-compiling-p) cl--optimize-safety 3))
          (keys t)
          (laterarg nil) (exactarg nil) minarg)
       (or num (setq num 0))
@@ -565,7 +565,7 @@ its argument list allows full Common Lisp conventions."
                              ,(length (cl-ldiff args p)))
                  exactarg (not (eq args p)))))
       (while (and args (not (memq (car args) cl--lambda-list-keywords)))
-       (let ((poparg (list (if (or (cdr args) (not exactarg)) 'pop 'car)
+       (let ((poparg (list (if (or (cdr args) (not exactarg)) 'pop 'car-safe)
                            restarg)))
          (cl--do-arglist
           (pop args)
@@ -709,7 +709,7 @@ If `eval' is in WHEN, BODY is evaluated when interpreted or 
at non-top-level.
 
 \(fn (WHEN...) BODY...)"
   (declare (indent 1) (debug (sexp body)))
-  (if (and (fboundp 'cl--compiling-file) (cl--compiling-file)
+  (if (and (macroexp-compiling-p)
           (not cl--not-toplevel) (not (boundp 'for-effect))) ;Horrible kludge.
       (let ((comp (or (memq 'compile when) (memq :compile-toplevel when)))
            (cl--not-toplevel t))
@@ -723,7 +723,7 @@ If `eval' is in WHEN, BODY is evaluated when interpreted or 
at non-top-level.
 (defun cl--compile-time-too (form)
   (or (and (symbolp (car-safe form)) (get (car-safe form) 'byte-hunk-handler))
       (setq form (macroexpand
-                 form (cons '(cl-eval-when) byte-compile-macro-environment))))
+                 form (cons '(cl-eval-when) macroexpand-all-environment))))
   (cond ((eq (car-safe form) 'progn)
         (cons 'progn (mapcar #'cl--compile-time-too (cdr form))))
        ((eq (car-safe form) 'cl-eval-when)
@@ -738,7 +738,7 @@ If `eval' is in WHEN, BODY is evaluated when interpreted or 
at non-top-level.
   "Like `progn', but evaluates the body at load time.
 The result of the body appears to the compiler as a quoted constant."
   (declare (debug (form &optional sexp)))
-  (if (cl--compiling-file)
+  (if (macroexp-compiling-p)
       (let* ((temp (cl-gentemp "--cl-load-time--"))
             (set `(setq ,temp ,form)))
        (if (and (fboundp 'byte-compile-file-form-defmumble)
@@ -1051,20 +1051,20 @@ For more details, see Info node `(cl)Loop Facility'.
 ;;    [&rest loop-clause]
 ;;    ))
 
-;; (def-edebug-spec loop-with
-;;   ("with" loop-var
+;; (def-edebug-elem-spec 'loop-with
+;;  '("with" loop-var
 ;;    loop-type-spec
 ;;    [&optional ["=" form]]
 ;;    &rest ["and" loop-var
 ;;       loop-type-spec
 ;;       [&optional ["=" form]]]))
 
-;; (def-edebug-spec loop-for-as
-;;   ([&or "for" "as"] loop-for-as-subclause
+;; (def-edebug-elem-spec 'loop-for-as
+;;  '([&or "for" "as"] loop-for-as-subclause
 ;;    &rest ["and" loop-for-as-subclause]))
 
-;; (def-edebug-spec loop-for-as-subclause
-;;   (loop-var
+;; (def-edebug-elem-spec 'loop-for-as-subclause
+;;  '(loop-var
 ;;    loop-type-spec
 ;;    &or
 ;;    [[&or "in" "on" "in-ref" "across-ref"]
@@ -1124,19 +1124,19 @@ For more details, see Info node `(cl)Loop Facility'.
 ;;     [&optional ["by" form]]
 ;;     ]))
 
-;; (def-edebug-spec loop-initial-final
-;;   (&or ["initially"
+;; (def-edebug-elem-spec 'loop-initial-final
+;;  '(&or ["initially"
 ;;     ;; [&optional &or "do" "doing"]  ;; CLtL2 doesn't allow this.
 ;;     &rest loop-non-atomic-expr]
 ;;        ["finally" &or
 ;;     [[&optional &or "do" "doing"] &rest loop-non-atomic-expr]
 ;;     ["return" form]]))
 
-;; (def-edebug-spec loop-and-clause
-;;   (loop-clause &rest ["and" loop-clause]))
+;; (def-edebug-elem-spec 'loop-and-clause
+;;   '(loop-clause &rest ["and" loop-clause]))
 
-;; (def-edebug-spec loop-clause
-;;   (&or
+;; (def-edebug-elem-spec 'loop-clause
+;;  '(&or
 ;;    [[&or "while" "until" "always" "never" "thereis"] form]
 
 ;;    [[&or "collect" "collecting"
@@ -1163,10 +1163,10 @@ For more details, see Info node `(cl)Loop Facility'.
 ;;    loop-initial-final
 ;;    ))
 
-;; (def-edebug-spec loop-non-atomic-expr
-;;   ([&not atom] form))
+;; (def-edebug-elem-spec 'loop-non-atomic-expr
+;;   '([&not atom] form))
 
-;; (def-edebug-spec loop-var
+;; (def-edebug-elem-spec 'loop-var
 ;;   ;; The symbolp must be last alternative to recognize e.g. (a b . c)
 ;;   ;; loop-var =>
 ;;   ;; (loop-var . [&or nil loop-var])
@@ -1175,13 +1175,13 @@ For more details, see Info node `(cl)Loop Facility'.
 ;;   ;; (symbolp . (symbolp . [&or nil loop-var]))
 ;;   ;; (symbolp . (symbolp . loop-var))
 ;;   ;; (symbolp . (symbolp . symbolp)) == (symbolp symbolp . symbolp)
-;;   (&or (loop-var . [&or nil loop-var]) [gate symbolp]))
+;;   '(&or (loop-var . [&or nil loop-var]) [gate symbolp]))
 
-;; (def-edebug-spec loop-type-spec
-;;   (&optional ["of-type" loop-d-type-spec]))
+;; (def-edebug-elem-spec 'loop-type-spec
+;;   '(&optional ["of-type" loop-d-type-spec]))
 
-;; (def-edebug-spec loop-d-type-spec
-;;   (&or (loop-d-type-spec . [&or nil loop-d-type-spec]) cl-type-spec))
+;; (def-edebug-elem-spec 'loop-d-type-spec
+;;   '(&or (loop-d-type-spec . [&or nil loop-d-type-spec]) cl-type-spec))
 
 (defun cl--parse-loop-clause ()                ; uses loop-*
   (let ((word (pop cl--loop-args))
@@ -1976,7 +1976,8 @@ a `let' form, except that the list of symbols can be 
computed at run-time."
               (,binds ()))
          (while ,syms
            (push (list (pop ,syms) (list 'quote (pop ,vals))) ,binds))
-         (eval (list 'let ,binds (list 'funcall (list 'quote ,bodyfun))))))))
+         (eval (list 'let (nreverse ,binds)
+                     (list 'funcall (list 'quote ,bodyfun))))))))
 
 (defconst cl--labels-magic (make-symbol "cl--labels-magic"))
 
@@ -2016,8 +2017,9 @@ info node `(cl) Function Bindings' for details.
 
 \(fn ((FUNC ARGLIST BODY...) ...) FORM...)"
   (declare (indent 1)
-           (debug ((&rest [&or (&define name :unique "cl-flet@" function-form)
-                               (&define name :unique "cl-flet@"
+           (debug ((&rest [&or (symbolp form)
+                               (&define [&name symbolp "@cl-flet@"]
+                                        [&name [] gensym] ;Make it unique!
                                         cl-lambda-list
                                         cl-declarations-or-string
                                         [&optional ("interactive" interactive)]
@@ -2067,6 +2069,8 @@ Like `cl-flet' but the definitions can refer to previous 
ones.
   ;; even handle mutually recursive functions.
   (letrec
       ((done nil) ;; Non-nil if some TCO happened.
+       ;; This var always holds the value `nil' until (just before) we
+       ;; exit the loop.
        (retvar (make-symbol "retval"))
        (ofargs (mapcar (lambda (s) (if (memq s cl--lambda-list-keywords) s
                                 (make-symbol (symbol-name s))))
@@ -2099,6 +2103,12 @@ Like `cl-flet' but the definitions can refer to previous 
ones.
             (`(progn . ,exps) `(progn . ,(funcall opt-exps exps)))
             (`(if ,cond ,then . ,else)
              `(if ,cond ,(funcall opt then) . ,(funcall opt-exps else)))
+            (`(and  . ,exps) `(and . ,(funcall opt-exps exps)))
+            (`(or ,arg) (funcall opt arg))
+            (`(or ,arg . ,args)
+             (let ((val (make-symbol "val")))
+               `(let ((,val ,arg))
+                  (if ,val ,(funcall opt val) ,(funcall opt `(or . ,args))))))
             (`(cond . ,conds)
              (let ((cs '()))
                (while conds
@@ -2108,14 +2118,18 @@ Like `cl-flet' but the definitions can refer to 
previous ones.
                               ;; This returns the value of `exp' but it's
                               ;; only in tail position if it's the
                               ;; last condition.
+                              ;; Note: This may set the var before we
+                              ;; actually exit the loop, but luckily it's
+                              ;; only the case if we set the var to nil,
+                              ;; so it does preserve the invariant that
+                              ;; the var is nil until we exit the loop.
                               `((setq ,retvar ,exp) nil)
                             `(,(funcall opt exp)))
                           cs))
                    (exps
                     (push (funcall opt-exps exps) cs))))
-               (if (eq t (caar cs))
-                   `(cond . ,(nreverse cs))
-                 `(cond ,@(nreverse cs) (t (setq ,retvar nil))))))
+               ;; No need to set `retvar' to return nil.
+               `(cond . ,(nreverse cs))))
             ((and `(,(or 'let 'let*) ,bindings . ,exps)
                   (guard
                    ;; Note: it's OK for this `let' to shadow any
@@ -2127,8 +2141,8 @@ Like `cl-flet' but the definitions can refer to previous 
ones.
                      ;; tail-called any more.
                      (not (memq var shadowings)))))
              `(,(car exp) ,bindings . ,(funcall opt-exps exps)))
-            (_
-             `(progn (setq ,retvar ,exp) nil))))))
+            ('nil nil)  ;No need to set `retvar' to return nil.
+            (_ `(progn (setq ,retvar ,exp) nil))))))
 
     (let ((optimized-body (funcall opt-exps body)))
       (if (not done)
@@ -2192,6 +2206,20 @@ details.
             (macroexp-progn body)
             newenv)))))
 
+(defvar edebug-lexical-macro-ctx)
+
+(defun cl--edebug-macrolet-interposer (bindings pf &rest specs)
+  ;; (cl-assert (null (cdr bindings)))
+  (setq bindings (car bindings))
+  (let ((edebug-lexical-macro-ctx
+         (nconc (mapcar (lambda (binding)
+                          (cons (car binding)
+                                (when (eq 'declare (car-safe (nth 2 binding)))
+                                  (nth 1 (assq 'debug (cdr (nth 2 
binding)))))))
+                        bindings)
+                edebug-lexical-macro-ctx)))
+    (funcall pf specs)))
+
 ;; The following ought to have a better definition for use with newer
 ;; byte compilers.
 ;;;###autoload
@@ -2201,7 +2229,13 @@ This is like `cl-flet', but for macros instead of 
functions.
 
 \(fn ((NAME ARGLIST BODY...) ...) FORM...)"
   (declare (indent 1)
-           (debug (cl-macrolet-expr)))
+           (debug (&interpose (&rest (&define [&name symbolp "@cl-macrolet@"]
+                                              [&name [] gensym] ;Make it 
unique!
+                                              cl-macro-list
+                                              cl-declarations-or-string
+                                              def-body))
+                              cl--edebug-macrolet-interposer
+                              cl-declarations body)))
   (if (cdr bindings)
       `(cl-macrolet (,(car bindings)) (cl-macrolet ,(cdr bindings) ,@body))
     (if (null bindings) (macroexp-progn body)
@@ -2254,7 +2288,7 @@ of `cl-symbol-macrolet' to additionally expand symbol 
macros."
             ;; on this behavior (haven't found any yet).
             ;; Such code should explicitly use `cl-letf' instead, I think.
             ;;
-            ;; (`(,(or `let `let*) . ,(or `(,bindings . ,body) dontcare))
+            ;; (`(,(or `let `let*) . ,(or `(,bindings . ,body) 
pcase--dontcare))
             ;;  (let ((letf nil) (found nil) (nbs ()))
             ;;    (dolist (binding bindings)
             ;;      (let* ((var (if (symbolp binding) binding (car binding)))
@@ -2277,7 +2311,7 @@ of `cl-symbol-macrolet' to additionally expand symbol 
macros."
             ;; The behavior of CL made sense in a dynamically scoped
             ;; language, but nowadays, lexical scoping semantics is more often
             ;; expected.
-            (`(,(or 'let 'let*) . ,(or `(,bindings . ,body) dontcare))
+            (`(,(or 'let 'let*) . ,(or `(,bindings . ,body) pcase--dontcare))
              (let ((nbs ()) (found nil))
                (dolist (binding bindings)
                  (let* ((var (if (symbolp binding) binding (car binding)))
@@ -2372,7 +2406,7 @@ by EXPANSION, and (setq NAME ...) will act like (setf 
EXPANSION ...).
                                                (append bindings venv))
                                          macroexpand-all-environment))))
             (if malformed-bindings
-                (macroexp--warn-and-return
+                (macroexp-warn-and-return
                  (format-message "Malformed `cl-symbol-macrolet' binding(s): 
%S"
                                  (nreverse malformed-bindings))
                  expansion)
@@ -2434,7 +2468,7 @@ values.  For compatibility, (cl-values A B C) is a 
synonym for (list A B C).
 (defmacro cl-the (type form)
   "Return FORM.  If type-checking is enabled, assert that it is of TYPE."
   (declare (indent 1) (debug (cl-type-spec form)))
-  (if (not (or (not (cl--compiling-file))
+  (if (not (or (not (macroexp-compiling-p))
                (< cl--optimize-speed 3)
                (= cl--optimize-safety 3)))
       form
@@ -2460,12 +2494,12 @@ values.  For compatibility, (cl-values A B C) is a 
synonym for (list A B C).
                     '(nil byte-compile-inline-expand))
               (error "%s already has a byte-optimizer, can't make it inline"
                      (car spec)))
-          (put (car spec) 'byte-optimizer 'byte-compile-inline-expand)))
+          (put (car spec) 'byte-optimizer #'byte-compile-inline-expand)))
 
        ((eq (car-safe spec) 'notinline)
         (while (setq spec (cdr spec))
           (if (eq (get (car spec) 'byte-optimizer)
-                  'byte-compile-inline-expand)
+                  #'byte-compile-inline-expand)
               (put (car spec) 'byte-optimizer nil))))
 
        ((eq (car-safe spec) 'optimize)
@@ -2501,7 +2535,7 @@ For instance
 
 will turn off byte-compile warnings in the function.
 See Info node `(cl)Declarations' for details."
-  (if (cl--compiling-file)
+  (if (macroexp-compiling-p)
       (while specs
        (if (listp cl--declare-stack) (push (car specs) cl--declare-stack))
        (cl--do-proclaim (pop specs) nil)))
@@ -2838,7 +2872,7 @@ Supported keywords for slots are:
         (copier (intern (format "copy-%s" name)))
         (predicate (intern (format "%s-p" name)))
         (print-func nil) (print-auto nil)
-        (safety (if (cl--compiling-file) cl--optimize-safety 3))
+        (safety (if (macroexp-compiling-p) cl--optimize-safety 3))
         (include nil)
          ;; There are 4 types of structs:
          ;; - `vector' type: means we should use a vector, which can come
@@ -3011,7 +3045,7 @@ Supported keywords for slots are:
                     forms)
               (when (cl-oddp (length desc))
                 (push
-                 (macroexp--warn-and-return
+                 (macroexp-warn-and-return
                   (format "Missing value for option `%S' of slot `%s' in 
struct %s!"
                           (car (last desc)) slot name)
                   'nil)
@@ -3020,7 +3054,7 @@ Supported keywords for slots are:
                            (not (keywordp (car desc))))
                   (let ((kw (car defaults)))
                     (push
-                     (macroexp--warn-and-return
+                     (macroexp-warn-and-return
                       (format "  I'll take `%s' to be an option rather than a 
default value."
                               kw)
                       'nil)
@@ -3236,15 +3270,14 @@ does not contain SLOT-NAME."
       (signal 'cl-struct-unknown-slot (list struct-type slot-name))))
 
 (defvar byte-compile-function-environment)
-(defvar byte-compile-macro-environment)
 
 (defun cl--macroexp-fboundp (sym)
   "Return non-nil if SYM will be bound when we run the code.
 Of course, we really can't know that for sure, so it's just a heuristic."
   (or (fboundp sym)
-      (and (cl--compiling-file)
+      (and (macroexp-compiling-p)
            (or (cdr (assq sym byte-compile-function-environment))
-               (cdr (assq sym byte-compile-macro-environment))))))
+               (cdr (assq sym macroexpand-all-environment))))))
 
 (pcase-dolist (`(,type . ,pred)
                ;; Mostly kept in alphabetical order.
@@ -3338,7 +3371,7 @@ Of course, we really can't know that for sure, so it's 
just a heuristic."
   "Verify that FORM is of type TYPE; signal an error if not.
 STRING is an optional description of the desired type."
   (declare (debug (place cl-type-spec &optional stringp)))
-  (and (or (not (cl--compiling-file))
+  (and (or (not (macroexp-compiling-p))
           (< cl--optimize-speed 3) (= cl--optimize-safety 3))
        (macroexp-let2 macroexp-copyable-p temp form
          `(progn (or (cl-typep ,temp ',type)
@@ -3358,7 +3391,7 @@ Other args STRING and ARGS... are arguments to be passed 
to `error'.
 They are not evaluated unless the assertion fails.  If STRING is
 omitted, a default message listing FORM itself is used."
   (declare (debug (form &rest form)))
-  (and (or (not (cl--compiling-file))
+  (and (or (not (macroexp-compiling-p))
           (< cl--optimize-speed 3) (= cl--optimize-safety 3))
        (let ((sargs (and show-args
                          (delq nil (mapcar (lambda (x)
diff --git a/lisp/emacs-lisp/debug.el b/lisp/emacs-lisp/debug.el
index d9da0db..b2d54c7 100644
--- a/lisp/emacs-lisp/debug.el
+++ b/lisp/emacs-lisp/debug.el
@@ -321,7 +321,7 @@ the debugger will not be entered."
 
 (make-obsolete 'debugger-insert-backtrace
                "use a `backtrace-mode' buffer or `backtrace-to-string'."
-               "Emacs 27.1")
+               "27.1")
 
 (defun debugger-insert-backtrace (frames do-xrefs)
   "Format and insert the backtrace FRAMES at point.
diff --git a/lisp/emacs-lisp/derived.el b/lisp/emacs-lisp/derived.el
index 54528b2..43d6dfd 100644
--- a/lisp/emacs-lisp/derived.el
+++ b/lisp/emacs-lisp/derived.el
@@ -141,6 +141,9 @@ KEYWORD-ARGS:
            :after-hook FORM
                    A single lisp form which is evaluated after the mode
                    hooks have been run.  It should not be quoted.
+           :interactive BOOLEAN
+                   Whether the derived mode should be `interactive' or not.
+                   The default is t.
 
 BODY:      forms to execute just before running the
            hooks for the new mode.  Do not use `interactive' here.
@@ -194,6 +197,7 @@ See Info node `(elisp)Derived Modes' for more details.
        (declare-syntax t)
        (hook (derived-mode-hook-name child))
        (group nil)
+        (interactive t)
         (after-hook nil))
 
     ;; Process the keyword args.
@@ -203,6 +207,7 @@ See Info node `(elisp)Derived Modes' for more details.
        (:abbrev-table (setq abbrev (pop body)) (setq declare-abbrev nil))
        (:syntax-table (setq syntax (pop body)) (setq declare-syntax nil))
         (:after-hook (setq after-hook (pop body)))
+        (:interactive (setq interactive (pop body)))
        (_ (pop body))))
 
     (setq docstring (derived-mode-make-docstring
@@ -246,7 +251,7 @@ No problems result if this variable is not bound.
 
        (defun ,child ()
         ,docstring
-        (interactive)
+        ,(and interactive '(interactive))
                                        ; Run the parent.
         (delay-mode-hooks
 
diff --git a/lisp/emacs-lisp/easy-mmode.el b/lisp/emacs-lisp/easy-mmode.el
index 2916ae4..addb58c 100644
--- a/lisp/emacs-lisp/easy-mmode.el
+++ b/lisp/emacs-lisp/easy-mmode.el
@@ -172,6 +172,10 @@ BODY contains code to execute each time the mode is 
enabled or disabled.
 :lighter SPEC  Same as the LIGHTER argument.
 :keymap MAP    Same as the KEYMAP argument.
 :require SYM   Same as in `defcustom'.
+:interactive VAL  Whether this mode should be a command or not.  The default
+                is to make it one; use nil to avoid that.  If VAL is a list,
+                it's interpreted as a list of major modes this minor mode
+                is useful in.
 :variable PLACE        The location to use instead of the variable MODE to 
store
                the state of the mode.  This can be simply a different
                named variable, or a generalized variable.
@@ -226,6 +230,7 @@ For example, you could write
         (hook (intern (concat mode-name "-hook")))
         (hook-on (intern (concat mode-name "-on-hook")))
         (hook-off (intern (concat mode-name "-off-hook")))
+         (interactive t)
         keyw keymap-sym tmp)
 
     ;; Check keys.
@@ -245,6 +250,7 @@ For example, you could write
        (:type (setq type (list :type (pop body))))
        (:require (setq require (pop body)))
        (:keymap (setq keymap (pop body)))
+       (:interactive (setq interactive (pop body)))
         (:variable (setq variable (pop body))
                    (if (not (and (setq tmp (cdr-safe variable))
                                  (or (symbolp tmp)
@@ -303,11 +309,18 @@ or call the function `%s'."))))
        ;; The actual function.
        (defun ,modefun (&optional arg ,@extra-args)
          ,(easy-mmode--mode-docstring doc pretty-name keymap-sym)
-        ;; Use `toggle' rather than (if ,mode 0 1) so that using
-        ;; repeat-command still does the toggling correctly.
-        (interactive (list (if current-prefix-arg
-                                (prefix-numeric-value current-prefix-arg)
-                              'toggle)))
+         ,(when interactive
+           ;; Use `toggle' rather than (if ,mode 0 1) so that using
+           ;; repeat-command still does the toggling correctly.
+            (if (consp interactive)
+                `(interactive
+                  (list (if current-prefix-arg
+                            (prefix-numeric-value current-prefix-arg)
+                          'toggle))
+                  ,@interactive)
+             '(interactive (list (if current-prefix-arg
+                                     (prefix-numeric-value current-prefix-arg)
+                                   'toggle)))))
         (let ((,last-message (current-message)))
            (,@setter
             (cond ((eq arg 'toggle)
@@ -317,6 +330,22 @@ or call the function `%s'."))))
                    nil)
                   (t
                    t)))
+           ;; Keep minor modes list up to date.
+           ,@(if globalp
+                 ;; When running this byte-compiled code in earlier
+                 ;; Emacs versions, these variables may not be defined
+                 ;; there.  So check defensively, even if they're
+                 ;; always defined in Emacs 28 and up.
+                 `((when (boundp 'global-minor-modes)
+                     (setq global-minor-modes
+                           (delq ',modefun global-minor-modes))
+                     (when ,getter
+                       (push ',modefun global-minor-modes))))
+               ;; Ditto check.
+               `((when (boundp 'local-minor-modes)
+                   (setq local-minor-modes (delq ',modefun local-minor-modes))
+                   (when ,getter
+                     (push ',modefun local-minor-modes)))))
            ,@body
            ;; The on/off hooks are here for backward compatibility only.
            (run-hooks ',hook (if ,getter ',hook-on ',hook-off))
diff --git a/lisp/emacs-lisp/easymenu.el b/lisp/emacs-lisp/easymenu.el
index 5303da3..87b34e7 100644
--- a/lisp/emacs-lisp/easymenu.el
+++ b/lisp/emacs-lisp/easymenu.el
@@ -23,6 +23,9 @@
 
 ;;; Commentary:
 
+;; The `easy-menu-define' macro provides a convenient way to define
+;; pop-up menus and/or menu bar menus.
+;;
 ;; This is compatible with easymenu.el by Per Abrahamsen
 ;; but it is much simpler as it doesn't try to support other Emacs versions.
 ;; The code was mostly derived from lmenu.el.
@@ -32,7 +35,6 @@
 (defsubst easy-menu-intern (s)
   (if (stringp s) (intern s) s))
 
-;;;###autoload
 (defmacro easy-menu-define (symbol maps doc menu)
   "Define a pop-up menu and/or menu bar menu specified by MENU.
 If SYMBOL is non-nil, define SYMBOL as a function to pop up the
@@ -140,7 +142,7 @@ solely of dashes is displayed as a menu separator.
 
 Alternatively, a menu item can be a list with the same format as
 MENU.  This is a submenu."
-  (declare (indent defun) (debug (symbolp body)))
+  (declare (indent defun) (debug (symbolp body)) (doc-string 3))
   `(progn
      ,(if symbol `(defvar ,symbol nil ,doc))
      (easy-menu-do-define (quote ,symbol) ,maps ,doc ,menu)))
@@ -163,7 +165,6 @@ This is expected to be bound to a mouse event."
                       ""))
                 (cons menu props)))))
 
-;;;###autoload
 (defun easy-menu-do-define (symbol maps doc menu)
   ;; We can't do anything that might differ between Emacs dialects in
   ;; `easy-menu-define' in order to make byte compiled files
@@ -181,12 +182,19 @@ This is expected to be bound to a mouse event."
                                  (funcall
                                   (or (plist-get (get symbol 'menu-prop)
                                                  :filter)
-                                      'identity)
+                                       #'identity)
                                   (symbol-function symbol)))
-                            symbol)))))
+                            symbol))))
+      ;; These symbols are commands, but not interesting for users
+      ;; to `M-x TAB'.
+      (function-put symbol 'completion-predicate #'ignore))
     (dolist (map (if (keymapp maps) (list maps) maps))
       (define-key map
-        (vector 'menu-bar (easy-menu-intern (car menu)))
+        (vector 'menu-bar (if (symbolp (car menu))
+                              (car menu)
+                            ;; If a string, then use the downcased
+                            ;; version for greater backwards compatibility.
+                            (intern (downcase (car menu)))))
         (easy-menu-binding keymap (car menu))))))
 
 (defun easy-menu-filter-return (menu &optional name)
@@ -212,7 +220,6 @@ If NAME is provided, it is used for the keymap."
 If it holds a list, this is expected to be a list of keys already seen in the
 menu we're processing.  Else it means we're not processing a menu.")
 
-;;;###autoload
 (defun easy-menu-create-menu (menu-name menu-items)
   "Create a menu called MENU-NAME with items described in MENU-ITEMS.
 MENU-NAME is a string, the name of the menu.  MENU-ITEMS is a list of items
@@ -468,7 +475,6 @@ When non-nil, NOEXP indicates that CALLBACK cannot be an 
expression
            (eval `(lambda () (interactive) ,callback) t)))
     command))
 
-;;;###autoload
 (defun easy-menu-change (path name items &optional before map)
   "Change menu found at PATH as item NAME to contain ITEMS.
 PATH is a list of strings for locating the menu that
diff --git a/lisp/emacs-lisp/edebug.el b/lisp/emacs-lisp/edebug.el
index 41768f2..f1455ff 100644
--- a/lisp/emacs-lisp/edebug.el
+++ b/lisp/emacs-lisp/edebug.el
@@ -55,6 +55,7 @@
 (require 'backtrace)
 (require 'macroexp)
 (require 'cl-lib)
+(require 'seq)
 (eval-when-compile (require 'pcase))
 
 ;;; Options
@@ -87,7 +88,6 @@ using, but only when you also use Edebug."
 ;; because the byte compiler binds them; as a result, if edebug
 ;; is first loaded for a require in a compilation, they will be left unbound.
 
-;;;###autoload
 (defcustom edebug-all-defs nil
   "If non-nil, evaluating defining forms instruments for Edebug.
 This applies to `eval-defun', `eval-region', `eval-buffer', and
@@ -100,11 +100,6 @@ variable.  You may wish to make it local to each buffer 
with
 `emacs-lisp-mode-hook'."
   :type 'boolean)
 
-;; edebug-all-defs and edebug-all-forms need to be autoloaded
-;; because the byte compiler binds them; as a result, if edebug
-;; is first loaded for a require in a compilation, they will be left unbound.
-
-;;;###autoload
 (defcustom edebug-all-forms nil
   "Non-nil means evaluation of all forms will instrument for Edebug.
 This doesn't apply to loading or evaluations in the minibuffer.
@@ -244,19 +239,30 @@ If the result is non-nil, then break.  Errors are 
ignored."
 
 ;;; Form spec utilities.
 
-(defun get-edebug-spec (symbol)
+(defun edebug-get-spec (symbol)
+  "Return the Edebug spec of a given Lisp expression's head SYMBOL.
+The argument is usually a symbol, but it doesn't have to be."
   ;; Get the spec of symbol resolving all indirection.
   (let ((spec nil)
        (indirect symbol))
     (while
-        (progn
-          (and (symbolp indirect)
-               (setq indirect
-                     (function-get indirect 'edebug-form-spec 'macro))))
+        (and (symbolp indirect)
+             (setq indirect
+                   (function-get indirect 'edebug-form-spec 'macro)))
       ;; (edebug-trace "indirection: %s" edebug-form-spec)
       (setq spec indirect))
     spec))
 
+(define-obsolete-function-alias 'get-edebug-spec #'edebug-get-spec "28.1")
+
+(defun edebug--get-elem-spec (elem)
+  "Return the specs of the Edebug element ELEM, if any.
+ELEM has to be a symbol."
+  (or (get elem 'edebug-elem-spec)
+      ;; For backward compatibility, we also allow the use of
+      ;; a form's name as a shorthand to refer to its spec.
+      (edebug-get-spec elem)))
+
 ;;;###autoload
 (defun edebug-basic-spec (spec)
   "Return t if SPEC uses only extant spec symbols.
@@ -445,66 +451,24 @@ the option `edebug-all-forms'."
 
 ;; We should somehow arrange to be able to do this
 ;; without actually replacing the eval-defun command.
-(defun edebug-eval-defun (edebug-it)
-  "Evaluate the top-level form containing point, or after point.
-
-If the current defun is actually a call to `defvar', then reset the
-variable using its initial value expression even if the variable
-already has some other value.  (Normally `defvar' does not change the
-variable's value if it already has a value.)  Treat `defcustom'
-similarly.  Reinitialize the face according to `defface' specification.
-
-With a prefix argument, instrument the code for Edebug.
-
-Setting option `edebug-all-defs' to a non-nil value reverses the meaning
+(defun edebug--eval-defun (orig-fun edebug-it)
+  "Setting option `edebug-all-defs' to a non-nil value reverses the meaning
 of the prefix argument.  Code is then instrumented when this function is
 invoked without a prefix argument.
 
 If acting on a `defun' for FUNCTION, and the function was instrumented,
 `Edebug: FUNCTION' is printed in the minibuffer.  If not instrumented,
-just FUNCTION is printed.
+just FUNCTION is printed."
+  (let* ((edebug-all-forms (not (eq (not edebug-it) (not edebug-all-defs))))
+        (edebug-all-defs  edebug-all-forms))
+    (funcall orig-fun nil)))
 
-If not acting on a `defun', the result of evaluation is displayed in
-the minibuffer."
+(defun edebug-eval-defun (edebug-it)
+  (declare (obsolete "use eval-defun or edebug--eval-defun instead" "28.1"))
   (interactive "P")
-  (let* ((edebugging (not (eq (not edebug-it) (not edebug-all-defs))))
-        (edebug-result)
-        (form
-         (let ((edebug-all-forms edebugging)
-               (edebug-all-defs (eq edebug-all-defs (not edebug-it))))
-           (edebug-read-top-level-form))))
-    ;; This should be consistent with `eval-defun-1', but not the
-    ;; same, since that gets a macroexpanded form.
-    (cond ((and (eq (car form) 'defvar)
-               (cdr-safe (cdr-safe form)))
-          ;; Force variable to be bound.
-          (makunbound (nth 1 form)))
-         ((and (eq (car form) 'defcustom)
-               (default-boundp (nth 1 form)))
-          ;; Force variable to be bound.
-           ;; FIXME: Shouldn't this use the :setter or :initializer?
-          (set-default (nth 1 form) (eval (nth 2 form) lexical-binding)))
-          ((eq (car form) 'defface)
-           ;; Reset the face.
-           (setq face-new-frame-defaults
-                 (assq-delete-all (nth 1 form) face-new-frame-defaults))
-           (put (nth 1 form) 'face-defface-spec nil)
-           (put (nth 1 form) 'face-documentation (nth 3 form))
-          ;; See comments in `eval-defun-1' for purpose of code below
-          (setq form (prog1 `(prog1 ,form
-                               (put ',(nth 1 form) 'saved-face
-                                    ',(get (nth 1 form) 'saved-face))
-                               (put ',(nth 1 form) 'customized-face
-                                    ,(nth 2 form)))
-                       (put (nth 1 form) 'saved-face nil)))))
-    (setq edebug-result (eval (eval-sexp-add-defvars form) lexical-binding))
-    (if (not edebugging)
-       (prog1
-           (prin1 edebug-result)
-         (let ((str (eval-expression-print-format edebug-result)))
-           (if str (princ str))))
-      edebug-result)))
-
+  (if (advice-member-p #'edebug--eval-defun 'eval-defun)
+      (eval-defun edebug-it)
+    (edebug--eval-defun #'eval-defun edebug-it)))
 
 ;;;###autoload
 (defalias 'edebug-defun 'edebug-eval-top-level-form)
@@ -576,12 +540,12 @@ already is one.)"
 (defun edebug-install-read-eval-functions ()
   (interactive)
   (add-function :around load-read-function #'edebug--read)
-  (advice-add 'eval-defun :override #'edebug-eval-defun))
+  (advice-add 'eval-defun :around #'edebug--eval-defun))
 
 (defun edebug-uninstall-read-eval-functions ()
   (interactive)
   (remove-function load-read-function #'edebug--read)
-  (advice-remove 'eval-defun #'edebug-eval-defun))
+  (advice-remove 'eval-defun #'edebug--eval-defun))
 
 ;;; Edebug internal data
 
@@ -961,6 +925,18 @@ circular objects.  Let `read' read everything else."
 
 ;;; Cursors for traversal of list and vector elements with offsets.
 
+;; Edebug's instrumentation is based on parsing the sexps, which come with
+;; auxiliary position information.  Instead of keeping the position
+;; information together with the sexps, it is kept in a "parallel
+;; tree" of offsets.
+;;
+;; An "edebug cursor" is a pair of a *list of sexps* (called the
+;; "expressions") together with a matching list of offsets.
+;; When we're parsing the content of a list, the
+;; `edebug-cursor-expressions' is simply the list but when parsing
+;; a vector, the `edebug-cursor-expressions' is a list formed of the
+;; elements of the vector.
+
 (defvar edebug-dotted-spec nil
   "Set to t when matching after the dot in a dotted spec list.")
 
@@ -1015,8 +991,8 @@ circular objects.  Let `read' read everything else."
   ;; The following test should always fail.
   (if (edebug-empty-cursor cursor)
       (edebug-no-match cursor "Not enough arguments."))
-  (setcar cursor (cdr (car cursor)))
-  (setcdr cursor (cdr (cdr cursor)))
+  (cl-callf cdr (car cursor))
+  (cl-callf cdr (cdr cursor))
   cursor)
 
 
@@ -1067,8 +1043,6 @@ circular objects.  Let `read' read everything else."
 ;; This data is shared by all embedded definitions.
 (defvar edebug-top-window-data)
 
-(defvar edebug-&optional)
-(defvar edebug-&rest)
 (defvar edebug-gate nil) ;; whether no-match forces an error.
 
 (defvar edebug-def-name nil) ; name of definition, used by interactive-form
@@ -1119,8 +1093,6 @@ purpose by adding an entry to this alist, and setting
        edebug-top-window-data
        edebug-def-name;; make sure it is locally nil
        ;; I don't like these here!!
-       edebug-&optional
-       edebug-&rest
        edebug-gate
        edebug-best-error
        edebug-error-point
@@ -1153,7 +1125,7 @@ purpose by adding an entry to this alist, and setting
               (eq 'symbol (progn (forward-char 1) (edebug-next-token-class))))
          ;; Find out if this is a defining form from first symbol
          (setq def-kind (read (current-buffer))
-               spec (and (symbolp def-kind) (get-edebug-spec def-kind))
+               spec (and (symbolp def-kind) (edebug-get-spec def-kind))
                defining-form-p (and (listp spec)
                                     (eq '&define (car spec)))
                ;; This is incorrect in general!! But OK most of the time.
@@ -1164,6 +1136,9 @@ purpose by adding an entry to this alist, and setting
 ;;;(message "all defs: %s   all forms: %s"  edebug-all-defs edebug-all-forms)
     (let ((result
            (cond
+            ;; IIUC, `&define' is treated specially here so as to avoid
+            ;; entering Edebug during the actual function's definition:
+            ;; we only want to enter Edebug later when the thing is called.
             (defining-form-p
               (if (or edebug-all-defs edebug-all-forms)
                   ;; If it is a defining form and we are edebugging defs,
@@ -1211,26 +1186,12 @@ purpose by adding an entry to this alist, and setting
       (funcall edebug-after-instrumentation-function result))))
 
 (defvar edebug-def-args) ; args of defining form.
-(defvar edebug-def-interactive) ; is it an emacs interactive function?
 (defvar edebug-inside-func)  ;; whether code is inside function context.
 ;; Currently def-form sets this to nil; def-body sets it to t.
 
-(defvar edebug--cl-macrolet-defs) ;; Fully defined below.
-
-(defun edebug-interactive-p-name ()
-  ;; Return a unique symbol for the variable used to store the
-  ;; status of interactive-p for this function.
-  (intern (format "edebug-%s-interactive-p" edebug-def-name)))
-
-
-(defun edebug-wrap-def-body (forms)
-  "Wrap the FORMS of a definition body."
-  (if edebug-def-interactive
-      `(let ((,(edebug-interactive-p-name)
-             (called-interactively-p 'interactive)))
-        ,(edebug-make-enter-wrapper forms))
-    (edebug-make-enter-wrapper forms)))
 
+(defvar edebug-lexical-macro-ctx nil
+  "Alist mapping lexically scoped macro names to their debug spec.")
 
 (defun edebug-make-enter-wrapper (forms)
   ;; Generate the enter wrapper for some forms of a definition.
@@ -1380,7 +1341,6 @@ contains a circular object."
          (edebug-old-def-name (edebug--form-data-name form-data-entry))
          edebug-def-name
          edebug-def-args
-         edebug-def-interactive
          edebug-inside-func;; whether wrapped code executes inside a function.
          )
 
@@ -1500,9 +1460,12 @@ contains a circular object."
         ((consp form)
          ;; The first offset for a list form is for the list form itself.
          (if (eq 'quote (car form))
+             ;; This makes sure we don't instrument 'foo
+              ;; which would cause the debugger to single-step
+             ;; the trivial evaluation of a constant.
              form
            (let* ((head (car form))
-                  (spec (and (symbolp head) (get-edebug-spec head)))
+                  (spec (and (symbolp head) (edebug-get-spec head)))
                   (new-cursor (edebug-new-cursor form offset)))
              ;; Find out if this is a defining form from first symbol.
              ;; An indirect spec would not work here, yet.
@@ -1542,13 +1505,10 @@ contains a circular object."
 (defsubst edebug-list-form-args (head cursor)
   ;; Process the arguments of a list form given that head of form is a symbol.
   ;; Helper for edebug-list-form
-  (let ((spec (get-edebug-spec head)))
+  (let* ((lex-spec (assq head edebug-lexical-macro-ctx))
+         (spec (if lex-spec (cdr lex-spec)
+                 (edebug-get-spec head))))
     (cond
-     ;; Treat cl-macrolet bindings like macros with no spec.
-     ((member head edebug--cl-macrolet-defs)
-      (if edebug-eval-macro-args
-         (edebug-forms cursor)
-       (edebug-sexps cursor)))
      (spec
       (cond
        ((consp spec)
@@ -1562,7 +1522,7 @@ contains a circular object."
                                        ; but leave it in for compatibility.
        ))
      ;; No edebug-form-spec provided.
-     ((macrop head)
+     ((or lex-spec (macrop head))
       (if edebug-eval-macro-args
          (edebug-forms cursor)
        (edebug-sexps cursor)))
@@ -1575,10 +1535,7 @@ contains a circular object."
   ;; The after offset will be left in the cursor after processing the form.
   (let ((head (edebug-top-element-required cursor "Expected elements"))
        ;; Prevent backtracking whenever instrumenting.
-       (edebug-gate t)
-       ;; A list form is never optional because it matches anything.
-       (edebug-&optional nil)
-       (edebug-&rest nil))
+       (edebug-gate t))
     ;; Skip the first offset.
     (edebug-set-cursor cursor (edebug-cursor-expressions cursor)
                       (cdr (edebug-cursor-offsets cursor)))
@@ -1586,11 +1543,6 @@ contains a circular object."
      ((symbolp head)
       (cond
        ((null head) nil) ; () is valid.
-       ((eq head 'interactive-p)
-       ;; Special case: replace (interactive-p) with variable
-       (setq edebug-def-interactive 'check-it)
-       (edebug-move-cursor cursor)
-       (edebug-interactive-p-name))
        (t
        (cons head (edebug-list-form-args
                    head (edebug-move-cursor cursor))))))
@@ -1628,7 +1580,7 @@ contains a circular object."
   (setq edebug-error-point (or edebug-error-point
                               (edebug-before-offset cursor))
        edebug-best-error (or edebug-best-error args))
-  (if (and edebug-gate (not edebug-&optional))
+  (if edebug-gate
       (progn
        (if edebug-error-point
            (goto-char edebug-error-point))
@@ -1639,13 +1591,11 @@ contains a circular object."
 (defun edebug-match (cursor specs)
   ;; Top level spec matching function.
   ;; Used also at each lower level of specs.
-  (let (edebug-&optional
-       edebug-&rest
-       edebug-best-error
+  (let (edebug-best-error
        edebug-error-point
        (edebug-gate edebug-gate)  ;; locally bound to limit effect
        )
-    (edebug-match-specs cursor specs 'edebug-match-specs)))
+    (edebug-match-specs cursor specs #'edebug-match-specs)))
 
 
 (defun edebug-match-one-spec (cursor spec)
@@ -1687,10 +1637,10 @@ contains a circular object."
             (first-char (and (symbolp spec) (aref (symbol-name spec) 0)))
             (match (cond
                     ((eq ?& first-char);; "&" symbols take all following specs.
-                     (funcall (get-edebug-spec spec) cursor (cdr specs)))
+                     (edebug--match-&-spec-op spec cursor (cdr specs)))
                     ((eq ?: first-char);; ":" symbols take one following spec.
                      (setq rest (cdr (cdr specs)))
-                     (funcall (get-edebug-spec spec) cursor (car (cdr specs))))
+                     (edebug--handle-:-spec-op spec cursor (car (cdr specs))))
                     (t;; Any other normal spec.
                      (setq rest (cdr specs))
                      (edebug-match-one-spec cursor spec)))))
@@ -1721,40 +1671,23 @@ contains a circular object."
 ;; user may want to define macros or functions with the same names.
 ;; We could use an internal obarray for these primitive specs.
 
-(dolist (pair '((&optional . edebug-match-&optional)
-               (&rest . edebug-match-&rest)
-               (&or . edebug-match-&or)
-               (form . edebug-match-form)
+(dolist (pair '((form . edebug-match-form)
                (sexp . edebug-match-sexp)
                (body . edebug-match-body)
-               (&define . edebug-match-&define)
-               (name . edebug-match-name)
-               (:name . edebug-match-colon-name)
-                (:unique . edebug-match-:unique)
                (arg . edebug-match-arg)
                (def-body . edebug-match-def-body)
                (def-form . edebug-match-def-form)
                ;; Less frequently used:
                ;; (function . edebug-match-function)
-               (lambda-expr . edebug-match-lambda-expr)
-                (cl-generic-method-qualifier
-                 . edebug-match-cl-generic-method-qualifier)
-                (cl-generic-method-args . edebug-match-cl-generic-method-args)
-                (cl-macrolet-expr . edebug-match-cl-macrolet-expr)
-                (cl-macrolet-name . edebug-match-cl-macrolet-name)
-                (cl-macrolet-body . edebug-match-cl-macrolet-body)
-               (&not . edebug-match-&not)
-               (&key . edebug-match-&key)
-               (&error . edebug-match-&error)
                (place . edebug-match-place)
                (gate . edebug-match-gate)
                ;;   (nil . edebug-match-nil)  not this one - special case it.
                ))
-  (put (car pair) 'edebug-form-spec (cdr pair)))
+  (put (car pair) 'edebug-elem-spec (cdr pair)))
 
 (defun edebug-match-symbol (cursor symbol)
   ;; Match a symbol spec.
-  (let* ((spec (get-edebug-spec symbol)))
+  (let* ((spec (edebug--get-elem-spec symbol)))
     (cond
      (spec
       (if (consp spec)
@@ -1793,13 +1726,12 @@ contains a circular object."
 
 (defsubst edebug-match-body (cursor) (edebug-forms cursor))
 
-(defun edebug-match-&optional (cursor specs)
+(cl-defmethod edebug--match-&-spec-op ((_ (eql &optional)) cursor specs)
   ;; Keep matching until one spec fails.
-  (edebug-&optional-wrapper cursor specs 'edebug-&optional-wrapper))
+  (edebug-&optional-wrapper cursor specs #'edebug-&optional-wrapper))
 
 (defun edebug-&optional-wrapper (cursor specs remainder-handler)
   (let (result
-       (edebug-&optional specs)
        (edebug-gate nil)
        (this-form (edebug-cursor-expressions cursor))
        (this-offset (edebug-cursor-offsets cursor)))
@@ -1814,20 +1746,24 @@ contains a circular object."
       nil)))
 
 
-(defun edebug-&rest-wrapper (cursor specs remainder-handler)
-  (if (null specs) (setq specs edebug-&rest))
-  ;; Reuse the &optional handler with this as the remainder handler.
-  (edebug-&optional-wrapper cursor specs remainder-handler))
+(cl-defgeneric edebug--match-&-spec-op (op cursor specs)
+  "Handle &foo spec operators.
+&foo spec operators operate on all the subsequent SPECS.")
 
-(defun edebug-match-&rest (cursor specs)
+(cl-defmethod edebug--match-&-spec-op ((_ (eql &rest)) cursor specs)
   ;; Repeatedly use specs until failure.
-  (let ((edebug-&rest specs) ;; remember these
-       edebug-best-error
+  (let (edebug-best-error
        edebug-error-point)
-    (edebug-&rest-wrapper cursor specs 'edebug-&rest-wrapper)))
+    ;; Reuse the &optional handler with this as the remainder handler.
+    (edebug-&optional-wrapper
+     cursor specs
+     (lambda (c s rh)
+       ;; `s' is the remaining spec to match.
+       ;; When it's nil, start over matching `specs'.
+       (edebug-&optional-wrapper c (or s specs) rh)))))
 
 
-(defun edebug-match-&or (cursor specs)
+(cl-defmethod edebug--match-&-spec-op ((_ (eql &or)) cursor specs)
   ;; Keep matching until one spec succeeds, and return its results.
   ;; If none match, fail.
   ;; This needs to be optimized since most specs spend time here.
@@ -1851,24 +1787,49 @@ contains a circular object."
       (apply #'edebug-no-match cursor "Expected one of" original-specs))
     ))
 
-
-(defun edebug-match-&not (cursor specs)
+(cl-defmethod edebug--match-&-spec-op ((_ (eql &interpose)) cursor specs)
+  "Compute the specs for `&interpose SPEC FUN ARGS...'.
+Extracts the head of the data by matching it against SPEC,
+and then matches the rest by calling (FUN HEAD PF ARGS...)
+where PF is the parsing function which FUN can call exactly once,
+passing it the specs that it needs to match.
+Note that HEAD will always be a list, since specs are defined to match
+a sequence of elements."
+  (pcase-let*
+      ((`(,spec ,fun . ,args) specs)
+       (exps (edebug-cursor-expressions cursor))
+       (instrumented-head (edebug-match-one-spec cursor spec))
+       (consumed (- (length exps)
+                    (length (edebug-cursor-expressions cursor))))
+       (head (seq-subseq exps 0 consumed)))
+    (cl-assert (eq (edebug-cursor-expressions cursor) (nthcdr consumed exps)))
+    (apply fun `(,head
+                 ,(lambda (newspecs)
+                    ;; FIXME: What'd be the difference if we used
+                    ;; `edebug-match-sublist', which is what
+                    ;; `edebug-list-form-args' uses for the similar purpose
+                    ;; when matching "normal" forms?
+                    (append instrumented-head (edebug-match cursor newspecs)))
+                 ,@args))))
+
+(cl-defmethod edebug--match-&-spec-op ((_ (eql &not)) cursor specs)
   ;; If any specs match, then fail
   (if (null (catch 'no-match
              (let ((edebug-gate nil))
                (save-excursion
-                 (edebug-match-&or cursor specs)))
+                 (edebug--match-&-spec-op '&or cursor specs)))
              nil))
       ;; This means something matched, so it is a no match.
       (edebug-no-match cursor "Unexpected"))
   ;; This means nothing matched, so it is OK.
   nil) ;; So, return nothing
 
-(defun edebug-match-&key (cursor specs)
+(cl-defmethod edebug--match-&-spec-op ((_ (eql &key)) cursor specs)
   ;; Following specs must look like (<name> <spec>) ...
   ;; where <name> is the name of a keyword, and spec is its spec.
   ;; This really doesn't save much over the expanded form and takes time.
-  (edebug-match-&rest
+  (edebug--match-&-spec-op
+   '&rest
    cursor
    (cons '&or
         (mapcar (lambda (pair)
@@ -1876,7 +1837,7 @@ contains a circular object."
                            (car (cdr pair))))
                 specs))))
 
-(defun edebug-match-&error (cursor specs)
+(cl-defmethod edebug--match-&-spec-op ((_ (eql &error)) cursor specs)
   ;; Signal an error, using the following string in the spec as argument.
   (let ((error-string (car specs))
         (edebug-error-point (edebug-before-offset cursor)))
@@ -1945,19 +1906,15 @@ contains a circular object."
 
 (defun edebug-match-sublist (cursor specs)
   ;; Match a sublist of specs.
-  (let (edebug-&optional
-       ;;edebug-best-error
-       ;;edebug-error-point
-       )
-    (prog1
-       ;; match with edebug-match-specs so edebug-best-error is not bound.
-       (edebug-match-specs cursor specs 'edebug-match-specs)
-      (if (not (edebug-empty-cursor cursor))
-         (if edebug-best-error
-             (apply #'edebug-no-match cursor edebug-best-error)
-           ;; A failed &rest or &optional spec may leave some args.
-           (edebug-no-match cursor "Failed matching" specs)
-           )))))
+  (prog1
+      ;; match with edebug-match-specs so edebug-best-error is not bound.
+      (edebug-match-specs cursor specs 'edebug-match-specs)
+    (if (not (edebug-empty-cursor cursor))
+       (if edebug-best-error
+           (apply #'edebug-no-match cursor edebug-best-error)
+         ;; A failed &rest or &optional spec may leave some args.
+         (edebug-no-match cursor "Failed matching" specs)
+         ))))
 
 
 (defun edebug-match-string (cursor spec)
@@ -1980,7 +1937,7 @@ contains a circular object."
 (defun edebug-match-function (_cursor)
   (error "Use function-form instead of function in edebug spec"))
 
-(defun edebug-match-&define (cursor specs)
+(cl-defmethod edebug--match-&-spec-op ((_ (eql &define)) cursor specs)
   ;; Match a defining form.
   ;; Normally, &define is interpreted specially other places.
   ;; This should only be called inside of a spec list to match the remainder
@@ -1994,47 +1951,67 @@ contains a circular object."
       offsets)
     specs))
 
-(defun edebug-match-lambda-expr (cursor)
-  ;; The expression must be a function.
-  ;; This will match any list form that begins with a symbol
-  ;; that has an edebug-form-spec beginning with &define.  In
-  ;; practice, only lambda expressions should be used.
-  ;; I could add a &lambda specification to avoid confusion.
-  (let* ((sexp (edebug-top-element-required
-               cursor "Expected lambda expression"))
-        (offset (edebug-top-offset cursor))
-        (head (and (consp sexp) (car sexp)))
-        (spec (and (symbolp head) (get-edebug-spec head)))
-        (edebug-inside-func nil))
-    ;; Find out if this is a defining form from first symbol.
-    (if (and (consp spec) (eq '&define (car spec)))
-       (prog1
-           (list
-            (edebug-defining-form
-             (edebug-new-cursor sexp offset)
-             (car offset);; before the sexp
-             (edebug-after-offset cursor)
-             (cons (symbol-name head) (cdr spec))))
-         (edebug-move-cursor cursor))
-      (edebug-no-match cursor "Expected lambda expression")
-      )))
-
-
-(defun edebug-match-name (cursor)
-  ;; Set the edebug-def-name bound in edebug-defining-form.
-  (let ((name (edebug-top-element-required cursor "Expected name")))
-    ;; Maybe strings and numbers could be used.
-    (if (not (symbolp name))
-       (edebug-no-match cursor "Symbol expected for name of definition"))
-    (setq edebug-def-name
-         (if edebug-def-name
-             ;; Construct a new name by appending to previous name.
-             (intern (format "%s@%s" edebug-def-name name))
-           name))
-    (edebug-move-cursor cursor)
-    (list name)))
-
-(defun edebug-match-colon-name (_cursor spec)
+(cl-defmethod edebug--match-&-spec-op ((_ (eql &name)) cursor specs)
+  "Compute the name for `&name SPEC FUN` spec operator.
+
+The full syntax of that operator is:
+    &name [PRESTRING] SPEC [POSTSTRING] FUN ARGS...
+
+Extracts the head of the data by matching it against SPEC,
+and then get the new name to use by calling
+  (FUN ARGS... OLDNAME [PRESTRING] HEAD [POSTSTRING])
+FUN should return either a string or a symbol.
+FUN can be missing in which case it defaults to concatenating
+the new name to the end of the old with an \"@\" char between the two.
+PRESTRING and POSTSTRING are optional strings that get prepended
+or appended to the actual name."
+  (pcase-let*
+      ((`(,spec ,fun . ,args) specs)
+       (prestrings (when (stringp spec)
+                     (prog1 (list spec) (setq spec fun fun (pop args)))))
+       (poststrings (when (stringp fun)
+                      (prog1 (list fun) (setq fun (pop args)))))
+       (exps (edebug-cursor-expressions cursor))
+       (instrumented (edebug-match-one-spec cursor spec))
+       (consumed (- (length exps)
+                    (length (edebug-cursor-expressions cursor))))
+       (newname (apply (or fun #'edebug--concat-name)
+                       `(,@args ,edebug-def-name
+                                ,@prestrings
+                                ,@(seq-subseq exps 0 consumed)
+                                ,@poststrings))))
+    (cl-assert (eq (edebug-cursor-expressions cursor) (nthcdr consumed exps)))
+    (setq edebug-def-name (if (stringp newname) (intern newname) newname))
+    instrumented))
+
+(defun edebug--concat-name (oldname &rest newnames)
+  (let ((newname (if (null (cdr newnames))
+                     (car newnames)
+                   ;; Put spaces between each name, but not for the
+                   ;; leading and trailing strings, if any.
+                   (let (beg mid end)
+                     (dolist (name newnames)
+                       (if (stringp name)
+                           (push name (if mid end beg))
+                         (when end (setq mid (nconc end mid) end nil))
+                         (push name mid)))
+                     (apply #'concat `(,@(nreverse beg)
+                                       ,(mapconcat (lambda (x) (format "%s" x))
+                                                   (nreverse mid) " ")
+                                       ,@(nreverse end)))))))
+    (if (null oldname)
+        (if (or (stringp newname) (symbolp newname))
+            newname
+          (format "%s" newname))
+      (format "%s@%s" edebug-def-name newname))))
+
+(def-edebug-elem-spec 'name '(&name symbolp))
+
+(cl-defgeneric edebug--handle-:-spec-op (op cursor spec)
+  "Handle :foo spec operators.
+:foo spec operators operate on just the one subsequent SPEC element.")
+
+(cl-defmethod edebug--handle-:-spec-op ((_ (eql :name)) _cursor spec)
   ;; Set the edebug-def-name to the spec.
   (setq edebug-def-name
        (if edebug-def-name
@@ -2043,7 +2020,7 @@ contains a circular object."
          spec))
   nil)
 
-(defun edebug-match-:unique (_cursor spec)
+(cl-defmethod edebug--handle-:-spec-op ((_ (eql :unique)) _cursor spec)
   "Match a `:unique PREFIX' specifier.
 SPEC is the symbol name prefix for `gensym'."
   (let ((suffix (gensym spec)))
@@ -2054,63 +2031,6 @@ SPEC is the symbol name prefix for `gensym'."
            suffix)))
   nil)
 
-(defun edebug-match-cl-generic-method-qualifier (cursor)
-  "Match a QUALIFIER for `cl-defmethod' at CURSOR."
-  (let ((args (edebug-top-element-required cursor "Expected qualifier")))
-    ;; Like in CLOS spec, we support any non-list values.
-    (unless (atom args) (edebug-no-match cursor "Atom expected"))
-    ;; Append the arguments to `edebug-def-name' (Bug#42671).
-    (setq edebug-def-name (intern (format "%s %s" edebug-def-name args)))
-    (edebug-move-cursor cursor)
-    (list args)))
-
-(defun edebug-match-cl-generic-method-args (cursor)
-  (let ((args (edebug-top-element-required cursor "Expected arguments")))
-    (if (not (consp args))
-        (edebug-no-match cursor "List expected"))
-    ;; Append the arguments to edebug-def-name.
-    (setq edebug-def-name
-          (intern (format "%s %s" edebug-def-name args)))
-    (edebug-move-cursor cursor)
-    (list args)))
-
-(defvar edebug--cl-macrolet-defs nil
-  "List of symbols found within the bindings of enclosing `cl-macrolet' 
forms.")
-(defvar edebug--current-cl-macrolet-defs nil
-  "List of symbols found within the bindings of the current `cl-macrolet' 
form.")
-
-(defun edebug-match-cl-macrolet-expr (cursor)
-  "Match a `cl-macrolet' form at CURSOR."
-  (let (edebug--current-cl-macrolet-defs)
-    (edebug-match cursor
-                  '((&rest (&define cl-macrolet-name cl-macro-list
-                                    cl-declarations-or-string
-                                    def-body))
-                    cl-declarations cl-macrolet-body))))
-
-(defun edebug-match-cl-macrolet-name (cursor)
-  "Match the name in a `cl-macrolet' binding at CURSOR.
-Collect the names in `edebug--cl-macrolet-defs' where they
-will be checked by `edebug-list-form-args' and treated as
-macros without a spec."
-  (let ((name (edebug-top-element-required cursor "Expected name")))
-    (when (not (symbolp name))
-      (edebug-no-match cursor "Bad name:" name))
-    ;; Change edebug-def-name to avoid conflicts with
-    ;; names at global scope.
-    (setq edebug-def-name (gensym "edebug-anon"))
-    (edebug-move-cursor cursor)
-    (push name edebug--current-cl-macrolet-defs)
-    (list name)))
-
-(defun edebug-match-cl-macrolet-body (cursor)
-  "Match the body of a `cl-macrolet' expression at CURSOR.
-Put the definitions collected in `edebug--current-cl-macrolet-defs'
-into `edebug--cl-macrolet-defs' which is checked in `edebug-list-form-args'."
-  (let ((edebug--cl-macrolet-defs (nconc edebug--current-cl-macrolet-defs
-                                         edebug--cl-macrolet-defs)))
-    (edebug-match-body cursor)))
-
 (defun edebug-match-arg (cursor)
   ;; set the def-args bound in edebug-defining-form
   (let ((edebug-arg (edebug-top-element-required cursor "Expected arg")))
@@ -2139,151 +2059,135 @@ into `edebug--cl-macrolet-defs' which is checked in 
`edebug-list-form-args'."
     ;; This happens to handle bug#20281, tho maybe a better fix would be to
     ;; improve the `defun' spec.
     (when forms
-      (list (edebug-wrap-def-body forms)))))
+      (list (edebug-make-enter-wrapper forms)))))
 
 
 ;;;; Edebug Form Specs
 ;;; ==========================================================
 
-;;;;* Spec for def-edebug-spec
-;;; Out of date.
-
-(defun edebug-spec-p (object)
-  "Return non-nil if OBJECT is a symbol with an edebug-form-spec property."
-  (and (symbolp object)
-       (get object 'edebug-form-spec)))
-
-(def-edebug-spec def-edebug-spec
-  ;; Top level is different from lower levels.
-  (&define :name edebug-spec name
-          &or "nil" edebug-spec-p "t" "0" (&rest edebug-spec)))
-
-(def-edebug-spec edebug-spec-list
-  ;; A list must have something in it, or it is nil, a symbolp
-  ((edebug-spec . [&or nil edebug-spec])))
-
-(def-edebug-spec edebug-spec
-  (&or
-   edebug-spec-list
-   (vector &rest edebug-spec)          ; matches a vector
-   ("vector" &rest edebug-spec)                ; matches a vector spec
-   ("quote" symbolp)
-   stringp
-   [edebug-lambda-list-keywordp &rest edebug-spec]
-   [keywordp gate edebug-spec]
-   edebug-spec-p  ;; Including all the special ones e.g. form.
-   symbolp;; a predicate
-   ))
-
-
 ;;;* Emacs special forms and some functions.
 
-;; quote expects only one argument, although it allows any number.
-(def-edebug-spec quote sexp)
+(pcase-dolist
+    (`(,name ,spec)
+
+     '((quote (sexp)) ;quote expects only one arg, tho it allows any number.
+
+       ;; The standard defining forms.
+       (defvar (symbolp &optional form stringp))
+       (defconst defvar)
+
+       ;; Contrary to macros, special forms default to assuming that all args
+       ;; are normal forms, so we don't need to do anything about those
+       ;; special forms:
+       ;;(save-current-buffer t)
+       ;;(save-excursion t)
+       ;;...
+       ;;(progn t)
+
+       ;; `defun' and `defmacro' are not special forms (any more), but it's
+       ;; more convenient to define their Edebug spec here.
+       (defun ( &define name lambda-list lambda-doc
+               [&optional ("declare" def-declarations)]
+               [&optional ("interactive" &optional [&or stringp def-form]
+                            &rest symbolp)]
+               def-body))
+
+       (defmacro ( &define name lambda-list lambda-doc
+                   [&optional ("declare" def-declarations)]
+                   def-body))
+
+       ;; function expects a symbol or a lambda or macro expression
+       ;; A macro is allowed by Emacs.
+       (function (&or symbolp lambda-expr))
+
+       ;; FIXME?  The manual uses this form (maybe that's just
+       ;; for illustration purposes?):
+       ;; (let ((&rest &or symbolp (gate symbolp &optional form)) body))
+       (let ((&rest &or (symbolp &optional form) symbolp) body))
+       (let* let)
+
+       (setq (&rest symbolp form))
+       (cond (&rest (&rest form)))
+
+       (condition-case ( symbolp form
+                         &rest ([&or symbolp (&rest symbolp)] body)))
+
+       (\` (backquote-form))
+
+       ;; Assume immediate quote in unquotes mean backquote at next
+       ;;  higher level.
+       (\, (&or ("quote" edebug-\`) def-form))
+       (\,@ (&define  ;; so (,@ form) is never wrapped.
+            &or ("quote" edebug-\`) def-form))
+       ))
+    (put name 'edebug-form-spec spec))
+
+(defun edebug--match-declare-arg (head pf)
+  (funcall pf (get (car head) 'edebug-declaration-spec)))
 
-;; The standard defining forms.
-(def-edebug-spec defconst defvar)
-(def-edebug-spec defvar (symbolp &optional form stringp))
+(def-edebug-elem-spec 'def-declarations
+  '(&rest &or (&interpose symbolp edebug--match-declare-arg) sexp))
 
-(def-edebug-spec defun
-  (&define name lambda-list lambda-doc
-           [&optional ("declare" &rest sexp)]
-          [&optional ("interactive" interactive)]
-          def-body))
-(def-edebug-spec defmacro
-  ;; FIXME: Improve `declare' so we can Edebug gv-expander and
-  ;; gv-setter declarations.
-  (&define name lambda-list lambda-doc
-           [&optional ("declare" &rest sexp)] def-body))
+(def-edebug-elem-spec 'lambda-list
+  '(([&rest arg]
+     [&optional ["&optional" arg &rest arg]]
+     &optional ["&rest" arg]
+     )))
 
-(def-edebug-spec arglist lambda-list)  ;; deprecated - use lambda-list.
+(def-edebug-elem-spec 'lambda-expr
+  '(("lambda" &define lambda-list lambda-doc
+     [&optional ("interactive" interactive)]
+     def-body)))
 
-(def-edebug-spec lambda-list
-  (([&rest arg]
-    [&optional ["&optional" arg &rest arg]]
-    &optional ["&rest" arg]
-    )))
+(def-edebug-elem-spec 'arglist '(lambda-list))  ;; deprecated - use 
lambda-list.
 
-(def-edebug-spec lambda-doc
-  (&optional [&or stringp
-                  (&define ":documentation" def-form)]))
+(def-edebug-elem-spec 'lambda-doc
+  '(&optional [&or stringp
+                   (&define ":documentation" def-form)]))
 
-(def-edebug-spec interactive
-  (&optional &or stringp def-form))
+(def-edebug-elem-spec 'interactive '(&optional [&or stringp def-form]
+                                               &rest symbolp))
 
 ;; A function-form is for an argument that may be a function or a form.
 ;; This specially recognizes anonymous functions quoted with quote.
-(def-edebug-spec function-form
+(def-edebug-elem-spec 'function-form          ;Deprecated, use `form'!
   ;; form at the end could also handle "function",
   ;; but recognize it specially to avoid wrapping function forms.
-  (&or ([&or "quote" "function"] &or symbolp lambda-expr) form))
-
-;; function expects a symbol or a lambda or macro expression
-;; A macro is allowed by Emacs.
-(def-edebug-spec function (&or symbolp lambda-expr))
-
-;; A macro expression is a lambda expression with "macro" prepended.
-(def-edebug-spec macro (&define "lambda" lambda-list def-body))
-
-;; (def-edebug-spec anonymous-form ((&or ["lambda" lambda] ["macro" macro])))
-
-;; Standard functions that take function-forms arguments.
-
-;; FIXME?  The manual uses this form (maybe that's just for illustration?):
-;; (def-edebug-spec let
-;;   ((&rest &or symbolp (gate symbolp &optional form))
-;;    body))
-(def-edebug-spec let
-  ((&rest &or (symbolp &optional form) symbolp)
-   body))
-
-(def-edebug-spec let* let)
-
-(def-edebug-spec setq (&rest symbolp form))
-
-(def-edebug-spec cond (&rest (&rest form)))
-
-(def-edebug-spec condition-case
-  (symbolp
-   form
-   &rest ([&or symbolp (&rest symbolp)] body)))
-
-
-(def-edebug-spec \` (backquote-form))
+  '(&or ([&or "quote" "function"] &or symbolp lambda-expr) form))
 
 ;; Supports quotes inside backquotes,
 ;; but only at the top level inside unquotes.
-(def-edebug-spec backquote-form
-  (&or
-   ;; Disallow instrumentation of , and ,@ inside a nested backquote, since
-   ;; these are likely to be forms generated by a macro being debugged.
-   ("`" nested-backquote-form)
-   ([&or "," ",@"] &or ("quote" backquote-form) form)
-   ;; The simple version:
-   ;;   (backquote-form &rest backquote-form)
-   ;; doesn't handle (a . ,b).  The straightforward fix:
-   ;;   (backquote-form . [&or nil backquote-form])
-   ;; uses up too much stack space.
-   ;; Note that `(foo . ,@bar) is not valid, so we don't need to handle it.
-   (backquote-form [&rest [&not ","] backquote-form]
-                  . [&or nil backquote-form])
-   ;; If you use dotted forms in backquotes, replace the previous line
-   ;; with the following.  This takes quite a bit more stack space, however.
-   ;; (backquote-form . [&or nil backquote-form])
-   (vector &rest backquote-form)
-   sexp))
-
-(def-edebug-spec nested-backquote-form
-  (&or
-   ("`" &error "Triply nested backquotes (without commas \"between\" them) \
+(def-edebug-elem-spec 'backquote-form
+  '(&or
+    ;; Disallow instrumentation of , and ,@ inside a nested backquote, since
+    ;; these are likely to be forms generated by a macro being debugged.
+    ("`" nested-backquote-form)
+    ([&or "," ",@"] &or ("quote" backquote-form) form)
+    ;; The simple version:
+    ;;   (backquote-form &rest backquote-form)
+    ;; doesn't handle (a . ,b).  The straightforward fix:
+    ;;   (backquote-form . [&or nil backquote-form])
+    ;; uses up too much stack space.
+    ;; Note that `(foo . ,@bar) is not valid, so we don't need to handle it.
+    (backquote-form [&rest [&not ","] backquote-form]
+                   . [&or nil backquote-form])
+    ;; If you use dotted forms in backquotes, replace the previous line
+    ;; with the following.  This takes quite a bit more stack space, however.
+    ;; (backquote-form . [&or nil backquote-form])
+    (vector &rest backquote-form)
+    sexp))
+
+(def-edebug-elem-spec 'nested-backquote-form
+  '(&or
+    ("`" &error "Triply nested backquotes (without commas \"between\" them) \
 are too difficult to instrument")
-   ;; Allow instrumentation of any , or ,@ contained within the (\, ...) or
-   ;; (\,@ ...) matched on the next line.
-   ([&or "," ",@"] backquote-form)
-   (nested-backquote-form [&rest [&not "," ",@"] nested-backquote-form]
-                          . [&or nil nested-backquote-form])
-   (vector &rest nested-backquote-form)
-   sexp))
+    ;; Allow instrumentation of any , or ,@ contained within the (\, ...) or
+    ;; (\,@ ...) matched on the next line.
+    ([&or "," ",@"] backquote-form)
+    (nested-backquote-form [&rest [&not "," ",@"] nested-backquote-form]
+                           . [&or nil nested-backquote-form])
+    (vector &rest nested-backquote-form)
+    sexp))
 
 ;; Special version of backquote that instruments backquoted forms
 ;; destined to be evaluated, usually as the result of a
@@ -2298,20 +2202,9 @@ are too difficult to instrument")
 
 ;; ,@ might have some problems.
 
-(defalias 'edebug-\` '\`)  ;; same macro as regular backquote.
-(def-edebug-spec edebug-\` (def-form))
-
-;; Assume immediate quote in unquotes mean backquote at next higher level.
-(def-edebug-spec \, (&or ("quote" edebug-\`) def-form))
-(def-edebug-spec \,@ (&define  ;; so (,@ form) is never wrapped.
-                    &or ("quote" edebug-\`) def-form))
-
-;; New byte compiler.
-
-(def-edebug-spec save-selected-window t)
-(def-edebug-spec save-current-buffer t)
-
-;; Anything else?
+(defmacro edebug-\` (exp)
+  (declare (debug (def-form)))
+  (list '\` exp))
 
 ;;; The debugger itself
 
@@ -2485,11 +2378,10 @@ STATUS should be a list returned by 
`edebug-var-status'."
       (edebug-print-trace-after
        (format "%s result: %s" function edebug-result)))))
 
-(def-edebug-spec edebug-tracing (form body))
-
 (defmacro edebug-tracing (msg &rest body)
   "Print MSG in *edebug-trace* before and after evaluating BODY.
 The result of BODY is also printed."
+  (declare (debug (form body)))
   `(let ((edebug-stack-depth (1+ edebug-stack-depth))
         edebug-result)
      (edebug-print-trace-before ,msg)
@@ -2921,7 +2813,6 @@ See `edebug-behavior-alist' for implementations.")
 (defvar edebug-outside-match-data) ; match data outside of edebug
 (defvar edebug-backtrace-buffer) ; each recursive edit gets its own
 (defvar edebug-inside-windows)
-(defvar edebug-interactive-p)
 
 (defvar edebug-mode-map)               ; will be defined fully later.
 
@@ -2937,7 +2828,6 @@ See `edebug-behavior-alist' for implementations.")
        ;;(edebug-number-of-recursions (1+ edebug-number-of-recursions))
        (edebug-recursion-depth (recursion-depth))
        edebug-entered                  ; bind locally to nil
-       (edebug-interactive-p nil)      ; again non-interactive
        edebug-backtrace-buffer         ; each recursive edit gets its own
        ;; The window configuration may be saved and restored
        ;; during a recursive-edit
@@ -3601,7 +3491,10 @@ canceled the first time the function is entered."
   ;; Could store this in the edebug data instead.
   (put function 'edebug-on-entry (if flag 'temp t)))
 
-(defalias 'edebug-cancel-edebug-on-entry #'cancel-edebug-on-entry)
+(define-obsolete-function-alias 'edebug-cancel-edebug-on-entry
+  #'edebug-cancel-on-entry "28.1")
+(define-obsolete-function-alias 'cancel-edebug-on-entry
+  #'edebug-cancel-on-entry "28.1")
 
 (defun edebug--edebug-on-entry-functions ()
   (let ((functions nil))
@@ -3613,9 +3506,9 @@ canceled the first time the function is entered."
      obarray)
     functions))
 
-(defun cancel-edebug-on-entry (function)
+(defun edebug-cancel-on-entry (function)
   "Cause Edebug to not stop when FUNCTION is called.
-The removes the effect of `edebug-on-entry'.  If FUNCTION is is
+The removes the effect of `edebug-on-entry'.  If FUNCTION is
 nil, remove `edebug-on-entry' on all functions."
   (interactive
    (list (let ((name (completing-read
@@ -3937,10 +3830,14 @@ be installed in `emacs-lisp-mode-map'.")
 ;; Autoloading these global bindings doesn't make sense because
 ;; they cannot be used anyway unless Edebug is already loaded and active.
 
-(defvar global-edebug-prefix "\^XX"
+(define-obsolete-variable-alias 'global-edebug-prefix
+  'edebug-global-prefix "28.1")
+(defvar edebug-global-prefix "\^XX"
   "Prefix key for global edebug commands, available from any buffer.")
 
-(defvar global-edebug-map
+(define-obsolete-variable-alias 'global-edebug-map
+  'edebug-global-map "28.1")
+(defvar edebug-global-map
   (let ((map (make-sparse-keymap)))
 
     (define-key map " " 'edebug-step-mode)
@@ -3973,9 +3870,9 @@ be installed in `emacs-lisp-mode-map'.")
     map)
   "Global map of edebug commands, available from any buffer.")
 
-(when global-edebug-prefix
-  (global-unset-key global-edebug-prefix)
-  (global-set-key global-edebug-prefix global-edebug-map))
+(when edebug-global-prefix
+  (global-unset-key edebug-global-prefix)
+  (global-set-key edebug-global-prefix edebug-global-map))
 
 
 (defun edebug-help ()
@@ -4237,7 +4134,8 @@ This should be a list of `edebug---frame' objects.")
   (pop-to-buffer edebug-backtrace-buffer)
   (unless (derived-mode-p 'backtrace-mode)
     (backtrace-mode)
-    (add-hook 'backtrace-goto-source-functions 
#'edebug--backtrace-goto-source))
+    (add-hook 'backtrace-goto-source-functions
+              #'edebug--backtrace-goto-source nil t))
   (setq edebug-instrumented-backtrace-frames
         (backtrace-get-frames 'edebug-debugger
                               :constructor #'edebug--make-frame)
@@ -4471,10 +4369,6 @@ It is removed when you hit any char."
   (set variable (not (symbol-value variable)))
   (message "%s: %s" variable (symbol-value variable)))
 
-;; We have to require easymenu (even for Emacs 18) just so
-;; the easy-menu-define macro call is compiled correctly.
-(require 'easymenu)
-
 (defconst edebug-mode-menus
   '("Edebug"
      ["Stop" edebug-stop t]
@@ -4579,13 +4473,18 @@ With prefix argument, make it a temporary breakpoint."
 (add-hook 'called-interactively-p-functions
           #'edebug--called-interactively-skip)
 (defun edebug--called-interactively-skip (i frame1 frame2)
-  (when (and (eq (car-safe (nth 1 frame1)) 'lambda)
-             (eq (nth 1 (nth 1 frame1)) '())
-             (eq (nth 1 frame2) 'edebug-enter))
+  (when (and (memq (car-safe (nth 1 frame1)) '(lambda closure))
+             ;; Lambda value with no arguments.
+             (null (nth (if (eq (car-safe (nth 1 frame1)) 'lambda) 1 2)
+                        (nth 1 frame1)))
+             (memq (nth 1 frame2) '(edebug-enter edebug-default-enter)))
     ;; `edebug-enter' calls itself on its first invocation.
-    (if (eq (nth 1 (backtrace-frame i 'called-interactively-p))
-            'edebug-enter)
-        2 1)))
+    (let ((s 1))
+      (while (memq (nth 1 (backtrace-frame i 'called-interactively-p))
+                   '(edebug-enter edebug-default-enter))
+        (cl-incf s)
+        (cl-incf i))
+      s)))
 
 ;; Finally, hook edebug into the rest of Emacs.
 ;; There are probably some other things that could go here.
diff --git a/lisp/emacs-lisp/eieio-compat.el b/lisp/emacs-lisp/eieio-compat.el
index db97d4c..6d84839 100644
--- a/lisp/emacs-lisp/eieio-compat.el
+++ b/lisp/emacs-lisp/eieio-compat.el
@@ -105,7 +105,7 @@ Summary:
   (declare (doc-string 3) (obsolete cl-defmethod "25.1")
            (debug
             (&define                    ; this means we are defining something
-             [&or name ("setf" name :name setf)]
+             [&name sexp]   ;Allow (setf ...) additionally to symbols.
              ;; ^^ This is the methods symbol
              [ &optional symbolp ]                ; this is key :before etc
              cl-generic-method-args               ; arguments
diff --git a/lisp/emacs-lisp/eieio-core.el b/lisp/emacs-lisp/eieio-core.el
index a8361c0..e7727fd 100644
--- a/lisp/emacs-lisp/eieio-core.el
+++ b/lisp/emacs-lisp/eieio-core.el
@@ -729,7 +729,7 @@ Argument FN is the function calling this verifier."
               (pcase slot
                 ((and (or `',name (and name (pred keywordp)))
                       (guard (not (memq name eieio--known-slot-names))))
-                 (macroexp--warn-and-return
+                 (macroexp-warn-and-return
                   (format-message "Unknown slot `%S'" name) exp 'compile-only))
                 (_ exp))))
            (gv-setter eieio-oset))
diff --git a/lisp/emacs-lisp/eieio.el b/lisp/emacs-lisp/eieio.el
index a095ad0..910023b 100644
--- a/lisp/emacs-lisp/eieio.el
+++ b/lisp/emacs-lisp/eieio.el
@@ -233,7 +233,7 @@ This method is obsolete."
 
        ,@(when eieio-backward-compatibility
            (let ((f (intern (format "%s-child-p" name))))
-             `((defalias ',f ',testsym2)
+             `((defalias ',f #',testsym2)
                (make-obsolete
                 ',f ,(format "use (cl-typep ... \\='%s) instead" name)
                 "25.1"))))
@@ -269,7 +269,7 @@ This method is obsolete."
                        (lambda (whole)
                          (if (not (stringp (car slots)))
                              whole
-                           (macroexp--warn-and-return
+                           (macroexp-warn-and-return
                             (format "Obsolete name arg %S to constructor %S"
                                     (car slots) (car whole))
                             ;; Keep the name arg, for backward compatibility,
@@ -288,8 +288,8 @@ created by the :initarg tag."
   (declare (debug (form symbolp)))
   `(eieio-oref ,obj (quote ,slot)))
 
-(defalias 'slot-value 'eieio-oref)
-(defalias 'set-slot-value 'eieio-oset)
+(defalias 'slot-value #'eieio-oref)
+(defalias 'set-slot-value #'eieio-oset)
 (make-obsolete 'set-slot-value "use (setf (slot-value ..) ..) instead" "25.1")
 
 (defmacro oref-default (obj slot)
@@ -418,7 +418,7 @@ If EXTRA, include that in the string returned to represent 
the symbol."
   (cl-check-type obj eieio-object)
   (eieio-class-name (eieio--object-class obj)))
 (define-obsolete-function-alias
-  'object-class-name 'eieio-object-class-name "24.4")
+  'object-class-name #'eieio-object-class-name "24.4")
 
 (defun eieio-class-parents (class)
   ;; FIXME: What does "(overload of variable)" mean here?
@@ -446,7 +446,7 @@ The CLOS function `class-direct-subclasses' is aliased to 
this function."
 (defmacro eieio-class-parent (class)
   "Return first parent class to CLASS.  (overload of variable)."
   `(car (eieio-class-parents ,class)))
-(define-obsolete-function-alias 'class-parent 'eieio-class-parent "24.4")
+(define-obsolete-function-alias 'class-parent #'eieio-class-parent "24.4")
 
 (defun same-class-p (obj class)
   "Return t if OBJ is of class-type CLASS."
@@ -461,7 +461,7 @@ The CLOS function `class-direct-subclasses' is aliased to 
this function."
   ;; class will be checked one layer down
   (child-of-class-p (eieio--object-class obj) class))
 ;; Backwards compatibility
-(defalias 'obj-of-class-p 'object-of-class-p)
+(defalias 'obj-of-class-p #'object-of-class-p)
 
 (defun child-of-class-p (child class)
   "Return non-nil if CHILD class is a subclass of CLASS."
@@ -665,7 +665,7 @@ This class is not stored in the `parent' slot of a class 
vector."
 (setq eieio-default-superclass (cl--find-class 'eieio-default-superclass))
 
 (define-obsolete-function-alias 'standard-class
-  'eieio-default-superclass "26.1")
+  #'eieio-default-superclass "26.1")
 
 (cl-defgeneric make-instance (class &rest initargs)
   "Make a new instance of CLASS based on INITARGS.
@@ -972,12 +972,12 @@ this object."
 This may create or delete slots, but does not affect the return value
 of `eq'."
   (error "EIEIO: `change-class' is unimplemented"))
-(define-obsolete-function-alias 'change-class 'eieio-change-class "26.1")
+(define-obsolete-function-alias 'change-class #'eieio-change-class "26.1")
 
 ;; Hook ourselves into help system for describing classes and methods.
 ;; FIXME: This is not actually needed any more since we can click on the
 ;; hyperlink from the constructor's docstring to see the type definition.
-(add-hook 'help-fns-describe-function-functions 'eieio-help-constructor)
+(add-hook 'help-fns-describe-function-functions #'eieio-help-constructor)
 
 (provide 'eieio)
 
diff --git a/lisp/emacs-lisp/eldoc.el b/lisp/emacs-lisp/eldoc.el
index 90e075b..a02406a 100644
--- a/lisp/emacs-lisp/eldoc.el
+++ b/lisp/emacs-lisp/eldoc.el
@@ -100,7 +100,7 @@ If the value is a positive number, it is used to calculate a
 number of logical lines of documentation that ElDoc is allowed to
 put in the echo area.  If a positive integer, the number is used
 directly, while a float specifies the number of lines as a
-proporting of the echo area frame's height.
+proportion of the echo area frame's height.
 
 If value is the symbol `truncate-sym-name-if-fit' t, the part of
 the doc string that represents a symbol's name may be truncated
@@ -248,7 +248,8 @@ expression point is on." :lighter eldoc-minor-mode-string
                      #'elisp-eldoc-var-docstring nil t)
            (add-hook 'eldoc-documentation-functions
                      #'elisp-eldoc-funcall nil t)
-           (setq eldoc-documentation-strategy 'eldoc-documentation-default)))
+           (setq-local eldoc-documentation-strategy
+                       'eldoc-documentation-default)))
   (eldoc-mode +1))
 
 ;;;###autoload
@@ -691,7 +692,7 @@ following values are allowed:
 
 - `eldoc-documentation-compose-eagerly': calls all functions in
   the special hook and display as many of the resulting doc
-  strings as possible, as soon as possibl.  Preserving the
+  strings as possible, as soon as possible.  Preserving the
   relative order of doc strings;
 
 - `eldoc-documentation-enthusiast': calls all functions in the
diff --git a/lisp/emacs-lisp/elp.el b/lisp/emacs-lisp/elp.el
index cc2927c..411ea2a 100644
--- a/lisp/emacs-lisp/elp.el
+++ b/lisp/emacs-lisp/elp.el
@@ -583,7 +583,7 @@ displayed."
   ;; continue standard unloading
   nil)
 
-(cl-defmethod loadhist-unload-element :before :extra "elp" ((x (head defun)))
+(cl-defmethod loadhist-unload-element :extra "elp" :before ((x (head defun)))
   "Un-instrument before unloading a function."
   (elp-restore-function (cdr x)))
 
diff --git a/lisp/emacs-lisp/ert-x.el b/lisp/emacs-lisp/ert-x.el
index d058d3d..1191fb8 100644
--- a/lisp/emacs-lisp/ert-x.el
+++ b/lisp/emacs-lisp/ert-x.el
@@ -102,15 +102,6 @@ the name of the test and the result of NAME-FORM."
            (indent 1))
   `(ert--call-with-test-buffer ,name-form (lambda () ,@body)))
 
-;; We use these `put' forms in addition to the (declare (indent)) in
-;; the defmacro form since the `declare' alone does not lead to
-;; correct indentation before the .el/.elc file is loaded.
-;; Autoloading these `put' forms solves this.
-;;;###autoload
-(progn
-  ;; TODO(ohler): Figure out what these mean and make sure they are correct.
-  (put 'ert-with-test-buffer 'lisp-indent-function 1))
-
 ;;;###autoload
 (defun ert-kill-all-test-buffers ()
   "Kill all test buffers that are still live."
@@ -376,8 +367,7 @@ different resource directory naming scheme, set the variable
 name will be trimmed using `string-trim' with arguments
 `ert-resource-directory-trim-left-regexp' and
 `ert-resource-directory-trim-right-regexp'."
-  `(let* ((testfile ,(or (bound-and-true-p byte-compile-current-file)
-                         (and load-in-progress load-file-name)
+  `(let* ((testfile ,(or (macroexp-file-name)
                          buffer-file-name))
           (default-directory (file-name-directory testfile)))
      (file-truename
diff --git a/lisp/emacs-lisp/ert.el b/lisp/emacs-lisp/ert.el
index fdbf953..e91ec0a 100644
--- a/lisp/emacs-lisp/ert.el
+++ b/lisp/emacs-lisp/ert.el
@@ -60,7 +60,6 @@
 (require 'cl-lib)
 (require 'debug)
 (require 'backtrace)
-(require 'easymenu)
 (require 'ewoc)
 (require 'find-func)
 (require 'pp)
@@ -81,15 +80,13 @@ Use nil for no limit (caution: backtrace lines can be very 
long)."
                                      :background "green1")
                                     (((class color) (background dark))
                                      :background "green3"))
-  "Face used for expected results in the ERT results buffer."
-  :group 'ert)
+  "Face used for expected results in the ERT results buffer.")
 
 (defface ert-test-result-unexpected '((((class color) (background light))
                                        :background "red1")
                                       (((class color) (background dark))
                                        :background "red3"))
-  "Face used for unexpected results in the ERT results buffer."
-  :group 'ert)
+  "Face used for unexpected results in the ERT results buffer.")
 
 
 ;;; Copies/reimplementations of cl functions.
@@ -196,8 +193,8 @@ it has to be wrapped in `(eval (quote ...))'.
 
 \(fn NAME () [DOCSTRING] [:expected-result RESULT-TYPE] \
 [:tags \\='(TAG...)] BODY...)"
-  (declare (debug (&define :name test
-                           name sexp [&optional stringp]
+  (declare (debug (&define [&name "test@" symbolp]
+                          sexp [&optional stringp]
                           [&rest keywordp sexp] def-body))
            (doc-string 3)
            (indent 2))
@@ -224,16 +221,6 @@ it has to be wrapped in `(eval (quote ...))'.
                         :body (lambda () ,@body)))
          ',name))))
 
-;; We use these `put' forms in addition to the (declare (indent)) in
-;; the defmacro form since the `declare' alone does not lead to
-;; correct indentation before the .el/.elc file is loaded.
-;; Autoloading these `put' forms solves this.
-;;;###autoload
-(progn
-  ;; TODO(ohler): Figure out what these mean and make sure they are correct.
-  (put 'ert-deftest 'lisp-indent-function 2)
-  (put 'ert-info 'lisp-indent-function 1))
-
 (defvar ert--find-test-regexp
   (concat "^\\s-*(ert-deftest"
           find-function-space-re
@@ -274,7 +261,7 @@ DATA is displayed to the user and should state the reason 
for skipping."
 It should only be stopped when ran from inside ert--run-test-internal."
   (when (and (not (symbolp debugger))   ; only run on anonymous debugger
              (memq error-symbol '(ert-test-failed ert-test-skipped)))
-    (funcall debugger 'error (list error-symbol data))))
+    (funcall debugger 'error (cons error-symbol data))))
 
 (defun ert--special-operator-p (thing)
   "Return non-nil if THING is a symbol naming a special operator."
@@ -290,14 +277,7 @@ It should only be stopped when ran from inside 
ert--run-test-internal."
   (let ((form
          ;; catch macroexpansion errors
          (condition-case err
-             (macroexpand-all form
-                              (append (bound-and-true-p
-                                       byte-compile-macro-environment)
-                                      (cond
-                                       ((boundp 'macroexpand-all-environment)
-                                        macroexpand-all-environment)
-                                       ((boundp 'cl-macro-environment)
-                                        cl-macro-environment))))
+             (macroexpand-all form macroexpand-all-environment)
            (error `(signal ',(car err) ',(cdr err))))))
     (cond
      ((or (atom form) (ert--special-operator-p (car form)))
@@ -1563,7 +1543,7 @@ Ran \\([0-9]+\\) tests, \\([0-9]+\\) results as expected\
       (message "------------------")
       (setq tests (sort tests (lambda (x y) (> (car x) (car y)))))
       (when (< high (length tests)) (setcdr (nthcdr (1- high) tests) nil))
-      (message "%s" (mapconcat 'cdr tests "\n")))
+      (message "%s" (mapconcat #'cdr tests "\n")))
     ;; More details on hydra, where the logs are harder to get to.
     (when (and (getenv "EMACS_HYDRA_CI")
                (not (zerop (+ nunexpected nskipped))))
@@ -1653,7 +1633,7 @@ default (if any)."
 
 (defun ert-find-test-other-window (test-name)
   "Find, in another window, the definition of TEST-NAME."
-  (interactive (list (ert-read-test-name-at-point "Find test definition: ")))
+  (interactive (list (ert-read-test-name-at-point "Find test definition")))
   (find-function-do-it test-name 'ert--test 'switch-to-buffer-other-window))
 
 (defun ert-delete-test (test-name)
@@ -2090,7 +2070,7 @@ and how to display message."
     (ert-run-tests selector listener t)))
 
 ;;;###autoload
-(defalias 'ert 'ert-run-tests-interactively)
+(defalias 'ert #'ert-run-tests-interactively)
 
 
 ;;; Simple view mode for auxiliary information like stack traces or
@@ -2103,6 +2083,7 @@ and how to display message."
 
 (define-derived-mode ert-results-mode special-mode "ERT-Results"
   "Major mode for viewing results of ERT test runs."
+  :interactive nil
   (setq-local revert-buffer-function
               (lambda (&rest _) (ert-results-rerun-all-tests))))
 
@@ -2198,7 +2179,7 @@ To be used in the ERT results buffer."
   "Move point to the next test.
 
 To be used in the ERT results buffer."
-  (interactive)
+  (interactive nil ert-results-mode)
   (ert--results-move (ewoc-locate ert--results-ewoc) 'ewoc-next
                      "No tests below"))
 
@@ -2206,7 +2187,7 @@ To be used in the ERT results buffer."
   "Move point to the previous test.
 
 To be used in the ERT results buffer."
-  (interactive)
+  (interactive nil ert-results-mode)
   (ert--results-move (ewoc-locate ert--results-ewoc) 'ewoc-prev
                      "No tests above"))
 
@@ -2239,7 +2220,7 @@ user-error is signaled with the message ERROR-MESSAGE."
   "Find the definition of the test at point in another window.
 
 To be used in the ERT results buffer."
-  (interactive)
+  (interactive nil ert-results-mode)
   (let ((name (ert-test-at-point)))
     (unless name
       (user-error "No test at point"))
@@ -2273,7 +2254,7 @@ To be used in the ERT results buffer."
   ;; the summary apparently needs to be easily accessible from the
   ;; error log, and perhaps it would be better to have it in a
   ;; separate buffer to keep it visible.
-  (interactive)
+  (interactive nil ert-results-mode)
   (let ((ewoc ert--results-ewoc)
         (progress-bar-begin ert--results-progress-bar-button-begin))
     (cond ((ert--results-test-node-or-null-at-point)
@@ -2390,7 +2371,7 @@ definition."
   "Re-run all tests, using the same selector.
 
 To be used in the ERT results buffer."
-  (interactive)
+  (interactive nil ert-results-mode)
   (cl-assert (eql major-mode 'ert-results-mode))
   (let ((selector (ert--stats-selector ert--results-stats)))
     (ert-run-tests-interactively selector (buffer-name))))
@@ -2399,7 +2380,7 @@ To be used in the ERT results buffer."
   "Re-run the test at point.
 
 To be used in the ERT results buffer."
-  (interactive)
+  (interactive nil ert-results-mode)
   (cl-destructuring-bind (test redefinition-state)
       (ert--results-test-at-point-allow-redefinition)
     (when (null test)
@@ -2434,7 +2415,7 @@ To be used in the ERT results buffer."
   "Re-run the test at point with `ert-debug-on-error' bound to t.
 
 To be used in the ERT results buffer."
-  (interactive)
+  (interactive nil ert-results-mode)
   (let ((ert-debug-on-error t))
     (ert-results-rerun-test-at-point)))
 
@@ -2442,7 +2423,7 @@ To be used in the ERT results buffer."
   "Display the backtrace for the test at point.
 
 To be used in the ERT results buffer."
-  (interactive)
+  (interactive nil ert-results-mode)
   (let* ((test (ert--results-test-at-point-no-redefinition t))
          (stats ert--results-stats)
          (pos (ert--stats-test-pos stats test))
@@ -2469,7 +2450,7 @@ To be used in the ERT results buffer."
   "Display the part of the *Messages* buffer generated during the test at 
point.
 
 To be used in the ERT results buffer."
-  (interactive)
+  (interactive nil ert-results-mode)
   (let* ((test (ert--results-test-at-point-no-redefinition t))
          (stats ert--results-stats)
          (pos (ert--stats-test-pos stats test))
@@ -2490,7 +2471,7 @@ To be used in the ERT results buffer."
   "Display the list of `should' forms executed during the test at point.
 
 To be used in the ERT results buffer."
-  (interactive)
+  (interactive nil ert-results-mode)
   (let* ((test (ert--results-test-at-point-no-redefinition t))
          (stats ert--results-stats)
          (pos (ert--stats-test-pos stats test))
@@ -2526,7 +2507,7 @@ To be used in the ERT results buffer."
   "Toggle how much of the condition to print for the test at point.
 
 To be used in the ERT results buffer."
-  (interactive)
+  (interactive nil ert-results-mode)
   (let* ((ewoc ert--results-ewoc)
          (node (ert--results-test-node-at-point))
          (entry (ewoc-data node)))
@@ -2538,7 +2519,7 @@ To be used in the ERT results buffer."
   "Display test timings for the last run.
 
 To be used in the ERT results buffer."
-  (interactive)
+  (interactive nil ert-results-mode)
   (let* ((stats ert--results-stats)
          (buffer (get-buffer-create "*ERT timings*"))
          (data (cl-loop for test across (ert--stats-tests stats)
@@ -2617,7 +2598,7 @@ To be used in the ERT results buffer."
   "Display the documentation of the test at point.
 
 To be used in the ERT results buffer."
-  (interactive)
+  (interactive nil ert-results-mode)
   (ert-describe-test (ert--results-test-at-point-no-redefinition t)))
 
 
diff --git a/lisp/emacs-lisp/generator.el b/lisp/emacs-lisp/generator.el
index e45260c..4ae20ba 100644
--- a/lisp/emacs-lisp/generator.el
+++ b/lisp/emacs-lisp/generator.el
@@ -1,6 +1,6 @@
 ;;; generator.el --- generators  -*- lexical-binding: t -*-
 
-;;; Copyright (C) 2015-2021 Free Software Foundation, Inc.
+;; Copyright (C) 2015-2021  Free Software Foundation, Inc.
 
 ;; Author: Daniel Colascione <dancol@dancol.org>
 ;; Keywords: extensions, elisp
diff --git a/lisp/emacs-lisp/gv.el b/lisp/emacs-lisp/gv.el
index 29f8230..ce48e57 100644
--- a/lisp/emacs-lisp/gv.el
+++ b/lisp/emacs-lisp/gv.el
@@ -187,6 +187,13 @@ arguments as NAME.  DO is a function as defined in 
`gv-get'."
     (push (list 'gv-setter #'gv--setter-defun-declaration)
          defun-declarations-alist))
 
+;;;###autoload
+(let ((spec (get 'compiler-macro 'edebug-declaration-spec)))
+  ;; It so happens that it's the same spec for gv-* as for compiler-macros.
+  ;; '(&or symbolp ("lambda" &define lambda-list lambda-doc def-body))
+  (put 'gv-expander 'edebug-declaration-spec spec)
+  (put 'gv-setter 'edebug-declaration-spec spec))
+
 ;; (defmacro gv-define-expand (name expander)
 ;;   "Use EXPANDER to handle NAME as a generalized var.
 ;; NAME is a symbol: the name of a function, macro, or special form.
@@ -224,7 +231,8 @@ The first arg in ARGLIST (the one that receives VAL) 
receives an expression
 which can do arbitrary things, whereas the other arguments are all guaranteed
 to be pure and copyable.  Example use:
   (gv-define-setter aref (v a i) \\=`(aset ,a ,i ,v))"
-  (declare (indent 2) (debug (&define name :name gv-setter sexp def-body)))
+  (declare (indent 2)
+           (debug (&define [&name symbolp "@gv-setter"] sexp def-body)))
   `(gv-define-expander ,name
      (lambda (do &rest args)
        (declare-function
@@ -307,7 +315,7 @@ The return value is the last VAL in the list.
 ;; Autoload this `put' since a user might use C-u C-M-x on an expression
 ;; containing a non-trivial `push' even before gv.el was loaded.
 ;;;###autoload
-(put 'gv-place 'edebug-form-spec 'edebug-match-form)
+(def-edebug-elem-spec 'gv-place '(form))
 
 ;; CL did the equivalent of:
 ;;(gv-define-macroexpand edebug-after (lambda (before index place) place))
@@ -316,8 +324,7 @@ The return value is the last VAL in the list.
        (gv-letplace (getter setter) place
          (funcall do `(edebug-after ,before ,index ,getter)
                   (lambda (store)
-                    `(progn (edebug-after ,before ,index ,getter)
-                            ,(funcall setter store)))))))
+                    `(edebug-after ,before ,index ,(funcall setter store)))))))
 
 ;;; The common generalized variables.
 
@@ -585,7 +592,7 @@ binding mode."
             ;; dynamic binding mode as well.
             (eq (car-safe code) 'cons))
         code
-      (macroexp--warn-and-return
+      (macroexp-warn-and-return
        "Use of gv-ref probably requires lexical-binding"
        code))))
 
diff --git a/lisp/emacs-lisp/inline.el b/lisp/emacs-lisp/inline.el
index d6106fe..36d71a8 100644
--- a/lisp/emacs-lisp/inline.el
+++ b/lisp/emacs-lisp/inline.el
@@ -262,7 +262,7 @@ See Info node `(elisp)Defining Functions' for more details."
   '(throw 'inline--just-use
           ;; FIXME: This would inf-loop by calling us right back when
           ;; macroexpand-all recurses to expand inline--form.
-          ;; (macroexp--warn-and-return (format ,@args)
+          ;; (macroexp-warn-and-return (format ,@args)
           ;;                            inline--form)
           inline--form))
 
diff --git a/lisp/emacs-lisp/lisp-mode.el b/lisp/emacs-lisp/lisp-mode.el
index 54089c4..67b7546 100644
--- a/lisp/emacs-lisp/lisp-mode.el
+++ b/lisp/emacs-lisp/lisp-mode.el
@@ -527,7 +527,7 @@ This will generate compile-time constants from BINDINGS."
          ;; This is too general -- rms.
          ;; A user complained that he has functions whose names start with `do'
          ;; and that they get the wrong color.
-         ;; That user has violated the http://www.cliki.net/Naming+conventions:
+         ;; That user has violated the 
https://www.cliki.net/Naming+conventions:
          ;; CL (but not EL!) `with-' (context) and `do-' (iteration)
          (,(concat "(\\(\\(do-\\|with-\\)" lisp-mode-symbol-regexp "\\)")
            (1 font-lock-keyword-face))
@@ -740,25 +740,24 @@ font-lock keywords will not be case sensitive."
 ;;; Generic Lisp mode.
 
 (defvar lisp-mode-map
-  (let ((map (make-sparse-keymap))
-       (menu-map (make-sparse-keymap "Lisp")))
+  (let ((map (make-sparse-keymap)))
     (set-keymap-parent map lisp-mode-shared-map)
     (define-key map "\e\C-x" 'lisp-eval-defun)
     (define-key map "\C-c\C-z" 'run-lisp)
-    (bindings--define-key map [menu-bar lisp] (cons "Lisp" menu-map))
-    (bindings--define-key menu-map [run-lisp]
-      '(menu-item "Run inferior Lisp" run-lisp
-                 :help "Run an inferior Lisp process, input and output via 
buffer `*inferior-lisp*'"))
-    (bindings--define-key menu-map [ev-def]
-      '(menu-item "Eval defun" lisp-eval-defun
-                 :help "Send the current defun to the Lisp process made by M-x 
run-lisp"))
-    (bindings--define-key menu-map [ind-sexp]
-      '(menu-item "Indent sexp" indent-sexp
-                 :help "Indent each line of the list starting just after 
point"))
     map)
   "Keymap for ordinary Lisp mode.
 All commands in `lisp-mode-shared-map' are inherited by this map.")
 
+(easy-menu-define lisp-mode-menu lisp-mode-map
+  "Menu for ordinary Lisp mode."
+  '("Lisp"
+    ["Indent sexp" indent-sexp
+     :help "Indent each line of the list starting just after point"]
+    ["Eval defun" lisp-eval-defun
+     :help "Send the current defun to the Lisp process made by M-x run-lisp"]
+    ["Run inferior Lisp" run-lisp
+     :help "Run an inferior Lisp process, input and output via buffer 
`*inferior-lisp*'"]))
+
 (define-derived-mode lisp-mode lisp-data-mode "Lisp"
   "Major mode for editing Lisp code for Lisps other than GNU Emacs Lisp.
 Commands:
@@ -1372,7 +1371,8 @@ and initial semicolons."
                            fill-column)))
         (save-restriction
           (save-excursion
-          (let ((ppss (syntax-ppss)))
+          (let ((ppss (syntax-ppss))
+                (start (point)))
             ;; If we're in a string, then narrow (roughly) to that
             ;; string before filling.  This avoids filling Lisp
             ;; statements that follow the string.
@@ -1387,6 +1387,8 @@ and initial semicolons."
                         t))
                 (narrow-to-region (ppss-comment-or-string-start ppss)
                                   (point))))
+            ;; Move back to where we were.
+            (goto-char start)
            (fill-paragraph justify)))))
       ;; Never return nil.
       t))
diff --git a/lisp/emacs-lisp/macroexp.el b/lisp/emacs-lisp/macroexp.el
index 042061c..59ada5e 100644
--- a/lisp/emacs-lisp/macroexp.el
+++ b/lisp/emacs-lisp/macroexp.el
@@ -112,7 +112,7 @@ and also to avoid outputting the warning during normal 
execution."
        (funcall (eval (cadr form)))
        (byte-compile-constant nil)))
 
-(defun macroexp--compiling-p ()
+(defun macroexp-compiling-p ()
   "Return non-nil if we're macroexpanding for the compiler."
   ;; FIXME: ¡¡Major Ugly Hack!! To determine whether the output of this
   ;; macro-expansion will be processed by the byte-compiler, we check
@@ -120,30 +120,48 @@ and also to avoid outputting the warning during normal 
execution."
   (member '(declare-function . byte-compile-macroexpand-declare-function)
           macroexpand-all-environment))
 
+(defun macroexp-file-name ()
+  "Return the name of the file from which the code comes.
+Returns nil when we do not know.
+A non-nil result is expected to be reliable when called from a macro in order
+to find the file in which the macro's call was found, and it should be
+reliable as well when used at the top-level of a file.
+Other uses risk returning non-nil value that point to the wrong file."
+  ;; `eval-buffer' binds `current-load-list' but not `load-file-name',
+  ;; so prefer using it over using `load-file-name'.
+  (let ((file (car (last current-load-list))))
+    (or (if (stringp file) file)
+        (bound-and-true-p byte-compile-current-file))))
+
 (defvar macroexp--warned (make-hash-table :test #'equal :weakness 'key))
 
-(defun macroexp--warn-and-return (msg form &optional compile-only)
+(defun macroexp--warn-wrap (msg form)
   (let ((when-compiled (lambda () (byte-compile-warn "%s" msg))))
-    (cond
-     ((null msg) form)
-     ((macroexp--compiling-p)
-      (if (and (consp form) (gethash form macroexp--warned))
-          ;; Already wrapped this exp with a warning: avoid inf-looping
-          ;; where we keep adding the same warning onto `form' because
-          ;; macroexpand-all gets right back to macroexpanding `form'.
-          form
-        (puthash form form macroexp--warned)
-        `(progn
-           (macroexp--funcall-if-compiled ',when-compiled)
-           ,form)))
-     (t
-      (unless compile-only
-        (message "%sWarning: %s"
-                 (if (stringp load-file-name)
-                     (concat (file-relative-name load-file-name) ": ")
-                   "")
-                 msg))
-      form))))
+    `(progn
+       (macroexp--funcall-if-compiled ',when-compiled)
+       ,form)))
+
+(define-obsolete-function-alias 'macroexp--warn-and-return
+  #'macroexp-warn-and-return "28.1")
+(defun macroexp-warn-and-return (msg form &optional compile-only)
+  (cond
+   ((null msg) form)
+   ((macroexp-compiling-p)
+    (if (and (consp form) (gethash form macroexp--warned))
+        ;; Already wrapped this exp with a warning: avoid inf-looping
+        ;; where we keep adding the same warning onto `form' because
+        ;; macroexpand-all gets right back to macroexpanding `form'.
+        form
+      (puthash form form macroexp--warned)
+      (macroexp--warn-wrap msg form)))
+   (t
+    (unless compile-only
+      (message "%sWarning: %s"
+               (if (stringp load-file-name)
+                   (concat (file-relative-name load-file-name) ": ")
+                 "")
+               msg))
+    form)))
 
 (defun macroexp--obsolete-warning (fun obsolescence-data type)
   (let ((instead (car obsolescence-data))
@@ -192,7 +210,7 @@ and also to avoid outputting the warning during normal 
execution."
                  (byte-compile-warning-enabled-p 'obsolete (car form))))
         (let* ((fun (car form))
                (obsolete (get fun 'byte-obsolete-info)))
-          (macroexp--warn-and-return
+          (macroexp-warn-and-return
            (macroexp--obsolete-warning
             fun obsolete
             (if (symbolp (symbol-function fun))
@@ -247,7 +265,7 @@ and also to avoid outputting the warning during normal 
execution."
                    values (cdr values))))
       (setq arglist (cdr arglist)))
     (if values
-        (macroexp--warn-and-return
+        (macroexp-warn-and-return
          (format (if (eq values 'too-few)
                      "attempt to open-code `%s' with too few arguments"
                    "attempt to open-code `%s' with too many arguments")
@@ -276,10 +294,12 @@ Assumes the caller has bound 
`macroexpand-all-environment'."
                   macroexpand-all-environment)
     ;; Normal form; get its expansion, and then expand arguments.
     (setq form (macroexp-macroexpand form macroexpand-all-environment))
+    ;; FIXME: It'd be nice to use `byte-optimize--pcase' here, but when
+    ;; I tried it, it broke the bootstrap :-(
     (pcase form
       (`(cond . ,clauses)
        (macroexp--cons 'cond (macroexp--all-clauses clauses) form))
-      (`(condition-case . ,(or `(,err ,body . ,handlers) dontcare))
+      (`(condition-case . ,(or `(,err ,body . ,handlers) pcase--dontcare))
        (macroexp--cons
         'condition-case
         (macroexp--cons err
@@ -296,10 +316,16 @@ Assumes the caller has bound 
`macroexpand-all-environment'."
                                        (cdr form))
                        form))
       (`(,(or 'function 'quote) . ,_) form)
-      (`(,(and fun (or 'let 'let*)) . ,(or `(,bindings . ,body) dontcare))
+      (`(,(and fun (or 'let 'let*)) . ,(or `(,bindings . ,body)
+                                           pcase--dontcare))
        (macroexp--cons fun
                        (macroexp--cons (macroexp--all-clauses bindings 1)
-                                       (macroexp--all-forms body)
+                                       (if (null body)
+                                           (macroexp-unprogn
+                                            (macroexp-warn-and-return
+                                             (format "Empty %s body" fun)
+                                             nil t))
+                                         (macroexp--all-forms body))
                                        (cdr form))
                        form))
       (`(,(and fun `(lambda . ,_)) . ,args)
@@ -316,27 +342,7 @@ Assumes the caller has bound 
`macroexpand-all-environment'."
                              form)
           (macroexp--expand-all newform))))
 
-      ;; The following few cases are for normal function calls that
-      ;; are known to funcall one of their arguments.  The byte
-      ;; compiler has traditionally handled these functions specially
-      ;; by treating a lambda expression quoted by `quote' as if it
-      ;; were quoted by `function'.  We make the same transformation
-      ;; here, so that any code that cares about the difference will
-      ;; see the same transformation.
-      ;; First arg is a function:
-      (`(,(and fun (or 'funcall 'apply 'mapcar 'mapatoms 'mapconcat 'mapc))
-         ',(and f `(lambda . ,_)) . ,args)
-       (macroexp--warn-and-return
-        (format "%s quoted with ' rather than with #'"
-                (list 'lambda (nth 1 f) '...))
-        (macroexp--expand-all `(,fun #',f . ,args))))
-      ;; Second arg is a function:
-      (`(,(and fun (or 'sort)) ,arg1 ',(and f `(lambda . ,_)) . ,args)
-       (macroexp--warn-and-return
-        (format "%s quoted with ' rather than with #'"
-                (list 'lambda (nth 1 f) '...))
-        (macroexp--expand-all `(,fun ,arg1 #',f . ,args))))
-      (`(funcall ,exp . ,args)
+      (`(funcall . ,(or `(,exp . ,args) pcase--dontcare))
        (let ((eexp (macroexp--expand-all exp))
              (eargs (macroexp--all-forms args)))
          ;; Rewrite (funcall #'foo bar) to (foo bar), in case `foo'
@@ -345,10 +351,22 @@ Assumes the caller has bound 
`macroexpand-all-environment'."
            (`#',f (macroexp--expand-all `(,f . ,eargs)))
            (_ `(funcall ,eexp . ,eargs)))))
       (`(,func . ,_)
-       ;; Macro expand compiler macros.  This cannot be delayed to
-       ;; byte-optimize-form because the output of the compiler-macro can
-       ;; use macros.
-       (let ((handler (function-get func 'compiler-macro)))
+       (let ((handler (function-get func 'compiler-macro))
+             (funargs (function-get func 'funarg-positions)))
+         ;; Check functions quoted with ' rather than with #'
+         (dolist (funarg funargs)
+           (let ((arg (nth funarg form)))
+             (when (and (eq 'quote (car-safe arg))
+                        (eq 'lambda (car-safe (cadr arg))))
+               (setcar (nthcdr funarg form)
+                       (macroexp-warn-and-return
+                        (format "%S quoted with ' rather than with #'"
+                                (let ((f (cadr arg)))
+                                  (if (symbolp f) f `(lambda ,(nth 1 f) ...))))
+                        arg)))))
+         ;; Macro expand compiler macros.  This cannot be delayed to
+         ;; byte-optimize-form because the output of the compiler-macro can
+         ;; use macros.
          (if (null handler)
              ;; No compiler macro.  We just expand each argument (for
              ;; setq/setq-default this works alright because the variable names
@@ -374,6 +392,18 @@ Assumes the caller has bound 
`macroexpand-all-environment'."
 
       (_ form))))
 
+;; Record which arguments expect functions, so we can warn when those
+;; are accidentally quoted with ' rather than with #'
+(dolist (f '(funcall apply mapcar mapatoms mapconcat mapc cl-mapcar maphash))
+  (put f 'funarg-positions '(1)))
+(dolist (f '( add-hook remove-hook advice-remove advice--remove-function
+              defalias fset global-set-key run-after-idle-timeout
+              set-process-filter set-process-sentinel sort))
+  (put f 'funarg-positions '(2)))
+(dolist (f '( advice-add define-key
+              run-at-time run-with-idle-timer run-with-timer ))
+  (put f 'funarg-positions '(3)))
+
 ;;;###autoload
 (defun macroexpand-all (form &optional environment)
   "Return result of expanding macros at all levels in FORM.
@@ -572,20 +602,35 @@ test of free variables in the following ways:
 - For the same reason it may cause the result to fail to include bindings
   which will be used if SEXP is not yet fully macro-expanded and the
   use of the binding will only be revealed by macro expansion."
-  (let ((res '()))
-    (while (and (consp sexp) bindings)
-      (dolist (binding (macroexp--fgrep bindings (pop sexp)))
-        (push binding res)
-        (setq bindings (remove binding bindings))))
-    (if (or (vectorp sexp) (byte-code-function-p sexp))
-        ;; With backquote, code can appear within vectors as well.
-        ;; This wouldn't be needed if we `macroexpand-all' before
-        ;; calling macroexp--fgrep, OTOH.
-        (macroexp--fgrep bindings (mapcar #'identity sexp))
-      (let ((tmp (assq sexp bindings)))
-        (if tmp
-            (cons tmp res)
-          res)))))
+  (let ((res '())
+        ;; Cyclic code should not happen, but code can contain cyclic data :-(
+        (seen (make-hash-table :test #'eq))
+        (sexpss (list (list sexp))))
+    ;; Use a nested while loop to reduce the amount of heap allocations for
+    ;; pushes to `sexpss' and the `gethash' overhead.
+    (while (and sexpss bindings)
+      (let ((sexps (pop sexpss)))
+        (unless (gethash sexps seen)
+          (puthash sexps t seen) ;; Using `setf' here causes bootstrap 
problems.
+          (if (vectorp sexps) (setq sexps (mapcar #'identity sexps)))
+          (let ((tortoise sexps) (skip t))
+            (while sexps
+              (let ((sexp (if (consp sexps) (pop sexps)
+                            (prog1 sexps (setq sexps nil)))))
+                (if skip
+                    (setq skip nil)
+                  (setq tortoise (cdr tortoise))
+                  (if (eq tortoise sexps)
+                      (setq sexps nil) ;; Found a cycle: we're done!
+                    (setq skip t)))
+                (cond
+                 ((or (consp sexp) (vectorp sexp)) (push sexp sexpss))
+                 (t
+                  (let ((tmp (assq sexp bindings)))
+                    (when tmp
+                      (push tmp res)
+                      (setq bindings (remove tmp bindings))))))))))))
+    res))
 
 ;;; Load-time macro-expansion.
 
diff --git a/lisp/emacs-lisp/map-ynp.el b/lisp/emacs-lisp/map-ynp.el
index 14112a1..86a0c76 100644
--- a/lisp/emacs-lisp/map-ynp.el
+++ b/lisp/emacs-lisp/map-ynp.el
@@ -265,7 +265,8 @@ C-g to quit (cancel the whole command);
   "If non-nil, `read-answer' accepts single-character answers.
 If t, accept short (single key-press) answers to the question.
 If nil, require long answers.  If `auto', accept short answers if
-the function cell of `yes-or-no-p' is set to `y-or-n-p'."
+`use-short-answers' is non-nil, or the function cell of `yes-or-no-p'
+is set to `y-or-n-p'."
   :type '(choice (const :tag "Accept short answers" t)
                  (const :tag "Require long answer" nil)
                  (const :tag "Guess preference" auto))
@@ -304,7 +305,8 @@ Return a long answer even in case of accepting short ones.
 
 When `use-dialog-box' is t, pop up a dialog window to get user input."
   (let* ((short (if (eq read-answer-short 'auto)
-                    (eq (symbol-function 'yes-or-no-p) 'y-or-n-p)
+                    (or use-short-answers
+                        (eq (symbol-function 'yes-or-no-p) 'y-or-n-p))
                   read-answer-short))
          (answers-with-help
           (if (assoc "help" answers)
diff --git a/lisp/emacs-lisp/map.el b/lisp/emacs-lisp/map.el
index 46a1bd2..c0cbc7b 100644
--- a/lisp/emacs-lisp/map.el
+++ b/lisp/emacs-lisp/map.el
@@ -3,12 +3,10 @@
 ;; Copyright (C) 2015-2021 Free Software Foundation, Inc.
 
 ;; Author: Nicolas Petton <nicolas@petton.fr>
-;; Keywords: convenience, map, hash-table, alist, array
-;; Version: 2.1
-;; Package-Requires: ((emacs "25"))
-;; Package: map
-
 ;; Maintainer: emacs-devel@gnu.org
+;; Keywords: extensions, lisp
+;; Version: 3.0
+;; Package-Requires: ((emacs "26"))
 
 ;; This file is part of GNU Emacs.
 
@@ -27,8 +25,9 @@
 
 ;;; Commentary:
 
-;; map.el provides map-manipulation functions that work on alists,
-;; hash-table and arrays.  All functions are prefixed with "map-".
+;; map.el provides generic map-manipulation functions that work on
+;; alists, plists, hash-tables, and arrays.  All functions are
+;; prefixed with "map-".
 ;;
 ;; Functions taking a predicate or iterating over a map using a
 ;; function take the function as their first argument.  All other
@@ -54,7 +53,7 @@ ARGS is a list of elements to be matched in the map.
 Each element of ARGS can be of the form (KEY PAT), in which case KEY is
 evaluated and searched for in the map.  The match fails if for any KEY
 found in the map, the corresponding PAT doesn't match the value
-associated to the KEY.
+associated with the KEY.
 
 Each element can also be a SYMBOL, which is an abbreviation of
 a (KEY PAT) tuple of the form (\\='SYMBOL SYMBOL).  When SYMBOL
@@ -75,7 +74,7 @@ bound to the looked up value in MAP.
 KEYS can also be a list of (KEY VARNAME) pairs, in which case
 KEY is an unquoted form.
 
-MAP can be a list, hash-table or array."
+MAP can be an alist, plist, hash-table, or array."
   (declare (indent 2)
            (debug ((&rest &or symbolp ([form symbolp])) form body)))
   `(pcase-let ((,(map--make-pcase-patterns keys) ,map))
@@ -101,7 +100,7 @@ Returns the result of evaluating the form associated with 
MAP-VAR's type."
 (define-error 'map-not-inplace "Cannot modify map in-place")
 
 (defsubst map--plist-p (list)
-  (and (consp list) (not (listp (car list)))))
+  (and (consp list) (atom (car list))))
 
 (cl-defgeneric map-elt (map key &optional default testfn)
   "Lookup KEY in MAP and return its associated value.
@@ -109,7 +108,8 @@ If KEY is not found, return DEFAULT which defaults to nil.
 
 TESTFN is deprecated.  Its default depends on the MAP argument.
 
-In the base definition, MAP can be an alist, hash-table, or array."
+In the base definition, MAP can be an alist, plist, hash-table,
+or array."
   (declare
    (gv-expander
     (lambda (do)
@@ -127,26 +127,25 @@ In the base definition, MAP can be an alist, hash-table, 
or array."
                                    `(map-insert ,mgetter ,key ,v))))))))))
    ;; `testfn' is deprecated.
    (advertised-calling-convention (map key &optional default) "27.1"))
+  ;; Can't use `cl-defmethod' with `advertised-calling-convention'.
   (map--dispatch map
     :list (if (map--plist-p map)
-              (let ((res (plist-get map key)))
-                (if (and default (null res) (not (plist-member map key)))
-                    default
-                  res))
+              (let ((res (plist-member map key)))
+                (if res (cadr res) default))
             (alist-get key map default nil testfn))
     :hash-table (gethash key map default)
-    :array (if (and (>= key 0) (< key (seq-length map)))
-               (seq-elt map key)
+    :array (if (map-contains-key map key)
+               (aref map key)
              default)))
 
 (defmacro map-put (map key value &optional testfn)
   "Associate KEY with VALUE in MAP and return VALUE.
 If KEY is already present in MAP, replace the associated value
 with VALUE.
-When MAP is a list, test equality with TESTFN if non-nil,
+When MAP is an alist, test equality with TESTFN if non-nil,
 otherwise use `eql'.
 
-MAP can be a list, hash-table or array."
+MAP can be an alist, plist, hash-table, or array."
   (declare (obsolete "use map-put! or (setf (map-elt ...) ...) instead" 
"27.1"))
   `(setf (map-elt ,map ,key nil ,testfn) ,value))
 
@@ -168,23 +167,30 @@ MAP can be a list, hash-table or array."
 
 (cl-defgeneric map-delete (map key)
   "Delete KEY in-place from MAP and return MAP.
-No error is signaled if KEY is not a key of MAP.
-If MAP is an array, store nil at the index KEY."
-  (map--dispatch map
-    ;; FIXME: Signal map-not-inplace i.s.o returning a different list?
-    :list (if (map--plist-p map)
-              (setq map (map--plist-delete map key))
-            (setf (alist-get key map nil t) nil))
-    :hash-table (remhash key map)
-    :array (and (>= key 0)
-                (<= key (seq-length map))
-                (aset map key nil)))
+Keys not present in MAP are ignored.")
+
+(cl-defmethod map-delete ((map list) key)
+  ;; FIXME: Signal map-not-inplace i.s.o returning a different list?
+  (if (map--plist-p map)
+      (map--plist-delete map key)
+    (setf (alist-get key map nil t) nil)
+    map))
+
+(cl-defmethod map-delete ((map hash-table) key)
+  (remhash key map)
+  map)
+
+(cl-defmethod map-delete ((map array) key)
+  "Store nil at index KEY."
+  (when (map-contains-key map key)
+    (aset map key nil))
   map)
 
 (defun map-nested-elt (map keys &optional default)
   "Traverse MAP using KEYS and return the looked up value or DEFAULT if nil.
 
-Map can be a nested map composed of alists, hash-tables and arrays."
+MAP can be a nested map composed of alists, plists, hash-tables,
+and arrays."
   (or (seq-reduce (lambda (acc key)
                     (when (mapp acc)
                       (map-elt acc key)))
@@ -202,30 +208,49 @@ The default implementation delegates to `map-apply'."
 The default implementation delegates to `map-apply'."
   (map-apply (lambda (_ value) value) map))
 
+(cl-defmethod map-values ((map array))
+  "Convert MAP into a list."
+  (append map ()))
+
 (cl-defgeneric map-pairs (map)
-  "Return the elements of MAP as key/value association lists.
+  "Return the key/value pairs in MAP as an alist.
 The default implementation delegates to `map-apply'."
   (map-apply #'cons map))
 
 (cl-defgeneric map-length (map)
   ;; FIXME: Should we rename this to `map-size'?
-  "Return the number of elements in the map.
-The default implementation counts `map-keys'."
-  (cond
-   ((hash-table-p map) (hash-table-count map))
-   ((listp map)
-    ;; FIXME: What about repeated/shadowed keys?
-    (if (map--plist-p map) (/ (length map) 2) (length map)))
-   ((arrayp map) (length map))
-   (t (length (map-keys map)))))
+  "Return the number of key/value pairs in MAP.
+Note that this does not always reflect the number of unique keys.
+The default implementation delegates to `map-do'."
+  (let ((size 0))
+    (map-do (lambda (_k _v) (setq size (1+ size))) map)
+    size))
+
+(cl-defmethod map-length ((map hash-table))
+  (hash-table-count map))
+
+(cl-defmethod map-length ((map list))
+  (if (map--plist-p map)
+      (/ (length map) 2)
+    (length map)))
+
+(cl-defmethod map-length ((map array))
+  (length map))
 
 (cl-defgeneric map-copy (map)
-  "Return a copy of MAP."
-  ;; FIXME: Clarify how deep is the copy!
-  (map--dispatch map
-    :list (seq-copy map)           ;FIXME: Probably not deep enough for alists!
-    :hash-table (copy-hash-table map)
-    :array (seq-copy map)))
+  "Return a copy of MAP.")
+
+(cl-defmethod map-copy ((map list))
+  "Use `copy-alist' on alists and `copy-sequence' on plists."
+  (if (map--plist-p map)
+      (copy-sequence map)
+    (copy-alist map)))
+
+(cl-defmethod map-copy ((map hash-table))
+  (copy-hash-table map))
+
+(cl-defmethod map-copy ((map array))
+  (copy-sequence map))
 
 (cl-defgeneric map-apply (function map)
   "Apply FUNCTION to each element of MAP and return the result as a list.
@@ -243,26 +268,28 @@ FUNCTION is called with two arguments, the key and the 
value.")
 (cl-defmethod map-do (function (map hash-table)) (maphash function map))
 
 (cl-defgeneric map-keys-apply (function map)
-  "Return the result of applying FUNCTION to each key of MAP.
+  "Return the result of applying FUNCTION to each key in MAP.
 The default implementation delegates to `map-apply'."
   (map-apply (lambda (key _)
                (funcall function key))
              map))
 
 (cl-defgeneric map-values-apply (function map)
-  "Return the result of applying FUNCTION to each value of MAP.
+  "Return the result of applying FUNCTION to each value in MAP.
 The default implementation delegates to `map-apply'."
   (map-apply (lambda (_ val)
                (funcall function val))
              map))
 
+(cl-defmethod map-values-apply (function (map array))
+  (mapcar function map))
+
 (cl-defgeneric map-filter (pred map)
   "Return an alist of key/val pairs for which (PRED key val) is non-nil in MAP.
 The default implementation delegates to `map-apply'."
   (delq nil (map-apply (lambda (key val)
-                         (if (funcall pred key val)
-                             (cons key val)
-                           nil))
+                         (and (funcall pred key val)
+                              (cons key val)))
                        map)))
 
 (cl-defgeneric map-remove (pred map)
@@ -272,7 +299,7 @@ The default implementation delegates to `map-filter'."
               map))
 
 (cl-defgeneric mapp (map)
-  "Return non-nil if MAP is a map (alist, hash-table, array, ...)."
+  "Return non-nil if MAP is a map (alist/plist, hash-table, array, ...)."
   (or (listp map)
       (hash-table-p map)
       (arrayp map)))
@@ -292,56 +319,58 @@ The default implementation delegates to `map-length'."
   ;; test function!
   "Return non-nil if and only if MAP contains KEY.
 TESTFN is deprecated.  Its default depends on MAP.
-The default implementation delegates to `map-do'."
+The default implementation delegates to `map-some'."
   (unless testfn (setq testfn #'equal))
-  (catch 'map--catch
-    (map-do (lambda (k _v)
-              (if (funcall testfn key k) (throw 'map--catch t)))
-            map)
-    nil))
+  (map-some (lambda (k _v) (funcall testfn key k)) map))
 
 (cl-defmethod map-contains-key ((map list) key &optional testfn)
-  (let ((v '(nil)))
-    (not (eq v (alist-get key map v nil (or testfn #'equal))))))
+  "Return non-nil if MAP contains KEY.
+If MAP is an alist, TESTFN defaults to `equal'.
+If MAP is a plist, `plist-member' is used instead."
+  (if (map--plist-p map)
+      (plist-member map key)
+    (let ((v '(nil)))
+      (not (eq v (alist-get key map v nil (or testfn #'equal)))))))
 
 (cl-defmethod map-contains-key ((map array) key &optional _testfn)
-  (and (integerp key)
-       (>= key 0)
-       (< key (length map))))
+  "Return non-nil if KEY is an index of MAP, ignoring TESTFN."
+  (and (natnump key) (< key (length map))))
 
 (cl-defmethod map-contains-key ((map hash-table) key &optional _testfn)
+  "Return non-nil if MAP contains KEY, ignoring TESTFN."
   (let ((v '(nil)))
     (not (eq v (gethash key map v)))))
 
 (cl-defgeneric map-some (pred map)
   "Return the first non-nil (PRED key val) in MAP.
-The default implementation delegates to `map-apply'."
+Return nil if no such element is found.
+The default implementation delegates to `map-do'."
   ;; FIXME: Not sure if there's much benefit to defining it as defgeneric,
   ;; since as defined, I can't think of a map-type where we could provide an
   ;; algorithmically more efficient algorithm than the default.
   (catch 'map--break
-    (map-apply (lambda (key value)
-                 (let ((result (funcall pred key value)))
-                   (when result
-                     (throw 'map--break result))))
-               map)
+    (map-do (lambda (key value)
+              (let ((result (funcall pred key value)))
+                (when result
+                  (throw 'map--break result))))
+            map)
     nil))
 
 (cl-defgeneric map-every-p (pred map)
   "Return non-nil if (PRED key val) is non-nil for all elements of MAP.
-The default implementation delegates to `map-apply'."
+The default implementation delegates to `map-do'."
   ;; FIXME: Not sure if there's much benefit to defining it as defgeneric,
   ;; since as defined, I can't think of a map-type where we could provide an
   ;; algorithmically more efficient algorithm than the default.
   (catch 'map--break
-    (map-apply (lambda (key value)
+    (map-do (lambda (key value)
               (or (funcall pred key value)
                   (throw 'map--break nil)))
             map)
     t))
 
 (defun map-merge (type &rest maps)
-  "Merge into a map of type TYPE all the key/value pairs in MAPS.
+  "Merge into a map of TYPE all the key/value pairs in MAPS.
 See `map-into' for all supported values of TYPE."
   (let ((result (map-into (pop maps) type)))
     (while maps
@@ -349,48 +378,57 @@ See `map-into' for all supported values of TYPE."
       ;; For small tables, this is fine, but for large tables, we
       ;; should probably use a hash-table internally which we convert
       ;; to an alist in the end.
-      (map-apply (lambda (key value)
-                   (setf (map-elt result key) value))
-                 (pop maps)))
+      (map-do (lambda (key value)
+                (setf (map-elt result key) value))
+              (pop maps)))
     result))
 
 (defun map-merge-with (type function &rest maps)
-  "Merge into a map of type TYPE all the key/value pairs in MAPS.
-When two maps contain the same key (`eql'), call FUNCTION on the two
+  "Merge into a map of TYPE all the key/value pairs in MAPS.
+When two maps contain the same (`eql') key, call FUNCTION on the two
 values and use the value returned by it.
-MAP can be a list, hash-table or array.
+Each of MAPS can be an alist, plist, hash-table, or array.
 See `map-into' for all supported values of TYPE."
   (let ((result (map-into (pop maps) type))
-        (not-found (cons nil nil)))
+        (not-found (list nil)))
     (while maps
-      (map-apply (lambda (key value)
-                   (cl-callf (lambda (old)
-                               (if (eql old not-found)
-                                   value
-                                 (funcall function old value)))
-                       (map-elt result key not-found)))
-                 (pop maps)))
+      (map-do (lambda (key value)
+                (cl-callf (lambda (old)
+                            (if (eql old not-found)
+                                value
+                              (funcall function old value)))
+                    (map-elt result key not-found)))
+              (pop maps)))
     result))
 
 (cl-defgeneric map-into (map type)
-  "Convert the map MAP into a map of type TYPE.")
+  "Convert MAP into a map of TYPE.")
+
 ;; FIXME: I wish there was a way to avoid this η-redex!
-(cl-defmethod map-into (map (_type (eql list))) (map-pairs map))
-(cl-defmethod map-into (map (_type (eql alist))) (map-pairs map))
+(cl-defmethod map-into (map (_type (eql list)))
+  "Convert MAP into an alist."
+  (map-pairs map))
+
+(cl-defmethod map-into (map (_type (eql alist)))
+  "Convert MAP into an alist."
+  (map-pairs map))
+
 (cl-defmethod map-into (map (_type (eql plist)))
-  (let ((plist '()))
-    (map-do (lambda (k v) (setq plist `(,k ,v ,@plist))) map)
-    plist))
+  "Convert MAP into a plist."
+  (let (plist)
+    (map-do (lambda (k v) (setq plist `(,v ,k ,@plist))) map)
+    (nreverse plist)))
 
 (cl-defgeneric map-put! (map key value &optional testfn)
   "Associate KEY with VALUE in MAP.
 If KEY is already present in MAP, replace the associated value
 with VALUE.
 This operates by modifying MAP in place.
-If it cannot do that, it signals the `map-not-inplace' error.
-If you want to insert an element without modifying MAP, use `map-insert'."
+If it cannot do that, it signals a `map-not-inplace' error.
+To insert an element without modifying MAP, use `map-insert'."
   ;; `testfn' only exists for backward compatibility with `map-put'!
   (declare (advertised-calling-convention (map key value) "27.1"))
+  ;; Can't use `cl-defmethod' with `advertised-calling-convention'.
   (map--dispatch map
     :list
     (if (map--plist-p map)
@@ -404,18 +442,20 @@ If you want to insert an element without modifying MAP, 
use `map-insert'."
     ;; and let `map-insert' grow the array?
     :array (aset map key value)))
 
-(define-error 'map-inplace "Can only modify map in place")
-
 (cl-defgeneric map-insert (map key value)
   "Return a new map like MAP except that it associates KEY with VALUE.
 This does not modify MAP.
-If you want to insert an element in place, use `map-put!'."
-  (if (listp map)
-      (if (map--plist-p map)
-          `(,key ,value ,@map)
-        (cons (cons key value) map))
-    ;; FIXME: Should we signal an error or use copy+put! ?
-    (signal 'map-inplace (list map))))
+If you want to insert an element in place, use `map-put!'.
+The default implementation defaults to `map-copy' and `map-put!'."
+  (let ((copy (map-copy map)))
+    (map-put! copy key value)
+    copy))
+
+(cl-defmethod map-insert ((map list) key value)
+  "Cons KEY and VALUE to the front of MAP."
+  (if (map--plist-p map)
+      (cons key (cons value map))
+    (cons (cons key value) map)))
 
 ;; There shouldn't be old source code referring to `map--put', yet we do
 ;; need to keep it for backward compatibility with .elc files where the
@@ -425,11 +465,9 @@ If you want to insert an element in place, use `map-put!'."
 (cl-defmethod map-apply (function (map list))
   (if (map--plist-p map)
       (cl-call-next-method)
-    (seq-map (lambda (pair)
-               (funcall function
-                        (car pair)
-                        (cdr pair)))
-             map)))
+    (mapcar (lambda (pair)
+              (funcall function (car pair) (cdr pair)))
+            map)))
 
 (cl-defmethod map-apply (function (map hash-table))
   (let (result)
@@ -439,46 +477,40 @@ If you want to insert an element in place, use 
`map-put!'."
     (nreverse result)))
 
 (cl-defmethod map-apply (function (map array))
-  (let ((index 0))
-    (seq-map (lambda (elt)
-               (prog1
-                   (funcall function index elt)
-                 (setq index (1+ index))))
-             map)))
+  (seq-map-indexed (lambda (elt index)
+                     (funcall function index elt))
+                   map))
 
 (cl-defmethod map-do (function (map list))
-  "Private function used to iterate over ALIST using FUNCTION."
   (if (map--plist-p map)
       (while map
         (funcall function (pop map) (pop map)))
-    (seq-do (lambda (pair)
-              (funcall function
-                       (car pair)
-                       (cdr pair)))
-            map)))
+    (mapc (lambda (pair)
+            (funcall function (car pair) (cdr pair)))
+          map)
+    nil))
 
-(cl-defmethod map-do (function (array array))
-  "Private function used to iterate over ARRAY using FUNCTION."
+(cl-defmethod map-do (function (map array))
   (seq-do-indexed (lambda (elt index)
-                     (funcall function index elt))
-                   array))
+                    (funcall function index elt))
+                  map))
 
 (defun map--into-hash (map keyword-args)
   "Convert MAP into a hash-table.
 KEYWORD-ARGS are forwarded to `make-hash-table'."
   (let ((ht (apply #'make-hash-table keyword-args)))
-    (map-apply (lambda (key value)
-                 (setf (gethash key ht) value))
-               map)
+    (map-do (lambda (key value)
+              (puthash key value ht))
+            map)
     ht))
 
 (cl-defmethod map-into (map (_type (eql hash-table)))
-  "Convert MAP into a hash-table."
-  (map--into-hash map (list :size (map-length map) :test 'equal)))
+  "Convert MAP into a hash-table with keys compared with `equal'."
+  (map--into-hash map (list :size (map-length map) :test #'equal)))
 
 (cl-defmethod map-into (map (type (head hash-table)))
   "Convert MAP into a hash-table.
-TYPE is a list where the car is `hash-table' and the cdr are the
+TYPE is a list whose car is `hash-table' and cdr a list of
 keyword-args forwarded to `make-hash-table'.
 
 Example:
@@ -487,23 +519,23 @@ Example:
 
 (defun map--make-pcase-bindings (args)
   "Return a list of pcase bindings from ARGS to the elements of a map."
-  (seq-map (lambda (elt)
-             (cond ((consp elt)
-                    `(app (pcase--flip map-elt ,(car elt)) ,(cadr elt)))
-                   ((keywordp elt)
-                    (let ((var (intern (substring (symbol-name elt) 1))))
-                      `(app (pcase--flip map-elt ,elt) ,var)))
-                   (t `(app (pcase--flip map-elt ',elt) ,elt))))
-           args))
+  (mapcar (lambda (elt)
+            (cond ((consp elt)
+                   `(app (pcase--flip map-elt ,(car elt)) ,(cadr elt)))
+                  ((keywordp elt)
+                   (let ((var (intern (substring (symbol-name elt) 1))))
+                     `(app (pcase--flip map-elt ,elt) ,var)))
+                  (t `(app (pcase--flip map-elt ',elt) ,elt))))
+          args))
 
 (defun map--make-pcase-patterns (args)
   "Return a list of `(map ...)' pcase patterns built from ARGS."
   (cons 'map
-        (seq-map (lambda (elt)
-                   (if (and (consp elt) (eq 'map (car elt)))
-                       (map--make-pcase-patterns elt)
-                     elt))
-                 args)))
+        (mapcar (lambda (elt)
+                  (if (eq (car-safe elt) 'map)
+                      (map--make-pcase-patterns elt)
+                    elt))
+                args)))
 
 (provide 'map)
 ;;; map.el ends here
diff --git a/lisp/emacs-lisp/memory-report.el b/lisp/emacs-lisp/memory-report.el
index 3d6ca95..ecbca28 100644
--- a/lisp/emacs-lisp/memory-report.el
+++ b/lisp/emacs-lisp/memory-report.el
@@ -295,7 +295,7 @@ by counted more than once."
               (- (position-bytes (point-min)))
               (gap-size)))
           (seq-reduce #'+ (mapcar (lambda (elem)
-                                    (if (cdr elem)
+                                    (if (and (consp elem) (cdr elem))
                                         (memory-report--object-size
                                          (make-hash-table :test #'eq)
                                          (cdr elem))
diff --git a/lisp/emacs-lisp/package.el b/lisp/emacs-lisp/package.el
index 90b7b88..2ecd92c 100644
--- a/lisp/emacs-lisp/package.el
+++ b/lisp/emacs-lisp/package.el
@@ -2206,10 +2206,13 @@ directory."
     (package-install-from-buffer)))
 
 ;;;###autoload
-(defun package-install-selected-packages ()
+(defun package-install-selected-packages (&optional noconfirm)
   "Ensure packages in `package-selected-packages' are installed.
-If some packages are not installed propose to install them."
+If some packages are not installed, propose to install them.
+If optional argument NOCONFIRM is non-nil, don't ask for
+confirmation to install packages."
   (interactive)
+  (package--archives-initialize)
   ;; We don't need to populate `package-selected-packages' before
   ;; using here, because the outcome is the same either way (nothing
   ;; gets installed).
@@ -2220,10 +2223,11 @@ If some packages are not installed propose to install 
them."
            (difference (- (length not-installed) (length available))))
       (cond
        (available
-        (when (y-or-n-p
-               (format "Packages to install: %d (%s), proceed? "
-                       (length available)
-                       (mapconcat #'symbol-name available " ")))
+        (when (or noconfirm
+                  (y-or-n-p
+                   (format "Packages to install: %d (%s), proceed? "
+                           (length available)
+                           (mapconcat #'symbol-name available " "))))
           (mapc (lambda (p) (package-install p 'dont-select)) available)))
        ((> difference 0)
         (message "Packages that are not available: %d (the rest is already 
installed), maybe you need to `M-x package-refresh-contents'"
@@ -2731,6 +2735,7 @@ either a full name or nil, and EMAIL is a valid email 
address."
     (define-key map "U" 'package-menu-mark-upgrades)
     (define-key map "r" 'revert-buffer)
     (define-key map "~" 'package-menu-mark-obsolete-for-deletion)
+    (define-key map "w" 'package-browse-url)
     (define-key map "x" 'package-menu-execute)
     (define-key map "h" 'package-menu-quick-help)
     (define-key map "H" #'package-menu-hide-package)
@@ -2753,6 +2758,8 @@ either a full name or nil, and EMAIL is a valid email 
address."
   "Menu for `package-menu-mode'."
   '("Package"
     ["Describe Package" package-menu-describe-package :help "Display 
information about this package"]
+    ["Open Package Homepage" package-browse-url
+     :help "Open the homepage of this package"]
     ["Help" package-menu-quick-help :help "Show short key binding help for 
package-menu-mode"]
     "--"
     ["Refresh Package List" revert-buffer
@@ -2802,6 +2809,7 @@ either a full name or nil, and EMAIL is a valid email 
address."
 Letters do not insert themselves; instead, they are commands.
 \\<package-menu-mode-map>
 \\{package-menu-mode-map}"
+  :interactive nil
   (setq mode-line-process '((package--downloads-in-progress ":Loading")
                             (package-menu--transaction-status
                              package-menu--transaction-status)))
@@ -2924,7 +2932,7 @@ Installed obsolete packages are always displayed.")
 Also hide packages whose name matches a regexp in user option
 `package-hidden-regexps' (a list).  To add regexps to this list,
 use `package-menu-hide-package'."
-  (interactive)
+  (interactive nil package-menu-mode)
   (package--ensure-package-menu-mode)
   (setq package-menu--hide-packages
         (not package-menu--hide-packages))
@@ -3261,7 +3269,7 @@ To unhide a package, type
 
 Type \\[package-menu-toggle-hiding] to toggle package hiding."
   (declare (interactive-only "change `package-hidden-regexps' instead."))
-  (interactive)
+  (interactive nil package-menu-mode)
   (package--ensure-package-menu-mode)
   (let* ((name (when (derived-mode-p 'package-menu-mode)
                  (concat "\\`" (regexp-quote (symbol-name (package-desc-name
@@ -3285,7 +3293,7 @@ Type \\[package-menu-toggle-hiding] to toggle package 
hiding."
 (defun package-menu-describe-package (&optional button)
   "Describe the current package.
 If optional arg BUTTON is non-nil, describe its associated package."
-  (interactive)
+  (interactive nil package-menu-mode)
   (let ((pkg-desc (if button (button-get button 'package-desc)
                     (tabulated-list-get-id))))
     (if pkg-desc
@@ -3295,7 +3303,7 @@ If optional arg BUTTON is non-nil, describe its 
associated package."
 ;; fixme numeric argument
 (defun package-menu-mark-delete (&optional _num)
   "Mark a package for deletion and move to the next line."
-  (interactive "p")
+  (interactive "p" package-menu-mode)
   (package--ensure-package-menu-mode)
   (if (member (package-menu-get-status)
               '("installed" "dependency" "obsolete" "unsigned"))
@@ -3304,7 +3312,7 @@ If optional arg BUTTON is non-nil, describe its 
associated package."
 
 (defun package-menu-mark-install (&optional _num)
   "Mark a package for installation and move to the next line."
-  (interactive "p")
+  (interactive "p" package-menu-mode)
   (package--ensure-package-menu-mode)
   (if (member (package-menu-get-status) '("available" "avail-obso" "new" 
"dependency"))
       (tabulated-list-put-tag "I" t)
@@ -3312,20 +3320,20 @@ If optional arg BUTTON is non-nil, describe its 
associated package."
 
 (defun package-menu-mark-unmark (&optional _num)
   "Clear any marks on a package and move to the next line."
-  (interactive "p")
+  (interactive "p" package-menu-mode)
   (package--ensure-package-menu-mode)
   (tabulated-list-put-tag " " t))
 
 (defun package-menu-backup-unmark ()
   "Back up one line and clear any marks on that package."
-  (interactive)
+  (interactive nil package-menu-mode)
   (package--ensure-package-menu-mode)
   (forward-line -1)
   (tabulated-list-put-tag " "))
 
 (defun package-menu-mark-obsolete-for-deletion ()
   "Mark all obsolete packages for deletion."
-  (interactive)
+  (interactive nil package-menu-mode)
   (package--ensure-package-menu-mode)
   (save-excursion
     (goto-char (point-min))
@@ -3356,7 +3364,7 @@ If optional arg BUTTON is non-nil, describe its 
associated package."
 (defun package-menu-quick-help ()
   "Show short key binding help for `package-menu-mode'.
 The full list of keys can be viewed with \\[describe-mode]."
-  (interactive)
+  (interactive nil package-menu-mode)
   (package--ensure-package-menu-mode)
   (message (mapconcat #'package--prettify-quick-help-key
                       package--quick-help-keys "\n")))
@@ -3452,7 +3460,7 @@ call will upgrade the package.
 If there's an async refresh operation in progress, the flags will
 be placed as part of `package-menu--post-refresh' instead of
 immediately."
-  (interactive)
+  (interactive nil package-menu-mode)
   (package--ensure-package-menu-mode)
   (if (not package--downloads-in-progress)
       (package-menu--mark-upgrades-1)
@@ -3546,7 +3554,7 @@ packages list, respectively."
 Packages marked for installation are downloaded and installed;
 packages marked for deletion are removed.
 Optional argument NOQUERY non-nil means do not ask the user to confirm."
-  (interactive)
+  (interactive nil package-menu-mode)
   (package--ensure-package-menu-mode)
   (let (install-list delete-list cmd pkg-desc)
     (save-excursion
@@ -3791,7 +3799,8 @@ strings.  If ARCHIVE is nil or the empty string, show all
 packages."
   (interactive (list (completing-read-multiple
                       "Filter by archive (comma separated): "
-                      (mapcar #'car package-archives))))
+                      (mapcar #'car package-archives)))
+               package-menu-mode)
   (package--ensure-package-menu-mode)
   (let ((re (if (listp archive)
                 (regexp-opt archive)
@@ -3812,7 +3821,8 @@ DESCRIPTION.
 When called interactively, prompt for DESCRIPTION.
 
 If DESCRIPTION is nil or the empty string, show all packages."
-  (interactive (list (read-regexp "Filter by description (regexp)")))
+  (interactive (list (read-regexp "Filter by description (regexp)"))
+               package-menu-mode)
   (package--ensure-package-menu-mode)
   (if (or (not description) (string-empty-p description))
       (package-menu--generate t t)
@@ -3833,10 +3843,11 @@ strings.  If KEYWORD is nil or the empty string, show 
all
 packages."
   (interactive (list (completing-read-multiple
                       "Keywords (comma separated): "
-                      (package-all-keywords))))
+                      (package-all-keywords)))
+               package-menu-mode)
+  (package--ensure-package-menu-mode)
   (when (stringp keyword)
     (setq keyword (list keyword)))
-  (package--ensure-package-menu-mode)
   (if (not keyword)
       (package-menu--generate t t)
     (package-menu--filter-by (lambda (pkg-desc)
@@ -3855,7 +3866,8 @@ When called interactively, prompt for NAME-OR-DESCRIPTION.
 
 If NAME-OR-DESCRIPTION is nil or the empty string, show all
 packages."
-  (interactive (list (read-regexp "Filter by name or description (regexp)")))
+  (interactive (list (read-regexp "Filter by name or description (regexp)"))
+               package-menu-mode)
   (package--ensure-package-menu-mode)
   (if (or (not name-or-description) (string-empty-p name-or-description))
       (package-menu--generate t t)
@@ -3874,7 +3886,8 @@ Display only packages with name that matches regexp NAME.
 When called interactively, prompt for NAME.
 
 If NAME is nil or the empty string, show all packages."
-  (interactive (list (read-regexp "Filter by name (regexp)")))
+  (interactive (list (read-regexp "Filter by name (regexp)"))
+               package-menu-mode)
   (package--ensure-package-menu-mode)
   (if (or (not name) (string-empty-p name))
       (package-menu--generate t t)
@@ -3904,7 +3917,8 @@ packages."
                                         "incompat"
                                         "installed"
                                         "new"
-                                        "unsigned"))))
+                                        "unsigned")))
+               package-menu-mode)
   (package--ensure-package-menu-mode)
   (if (or (not status) (string-empty-p status))
       (package-menu--generate t t)
@@ -3939,7 +3953,9 @@ If VERSION is nil or the empty string, show all packages."
                                     ('< "< less than")
                                     ('> "> greater than"))
                                   "): "))
-                         choice))))
+                         choice)))
+               package-menu-mode)
+  (package--ensure-package-menu-mode)
   (unless (equal predicate 'quit)
     (if (or (not version) (string-empty-p version))
         (package-menu--generate t t)
@@ -3957,7 +3973,7 @@ If VERSION is nil or the empty string, show all packages."
 (defun package-menu-filter-marked ()
   "Filter \"*Packages*\" buffer by non-empty upgrade mark.
 Unlike other filters, this leaves the marks intact."
-  (interactive)
+  (interactive nil package-menu-mode)
   (package--ensure-package-menu-mode)
   (widen)
   (let (found-entries mark pkg-id entry marks)
@@ -3985,7 +4001,7 @@ Unlike other filters, this leaves the marks intact."
 
 (defun package-menu-filter-upgradable ()
   "Filter \"*Packages*\" buffer to show only upgradable packages."
-  (interactive)
+  (interactive nil package-menu-mode)
   (let ((pkgs (mapcar #'car (package-menu--find-upgrades))))
     (package-menu--filter-by
      (lambda (pkg)
@@ -3994,7 +4010,7 @@ Unlike other filters, this leaves the marks intact."
 
 (defun package-menu-clear-filter ()
   "Clear any filter currently applied to the \"*Packages*\" buffer."
-  (interactive)
+  (interactive nil package-menu-mode)
   (package--ensure-package-menu-mode)
   (package-menu--generate t t))
 
@@ -4015,10 +4031,7 @@ The return value is a string (or nil in case we can't 
find it)."
   ;; the version at compile time and hardcodes it into the .elc file!
   (declare (pure t))
   ;; Hack alert!
-  (let ((file
-         (or (if (boundp 'byte-compile-current-file) byte-compile-current-file)
-             load-file-name
-             buffer-file-name)))
+  (let ((file (or (macroexp-file-name) buffer-file-name)))
     (cond
      ((null file) nil)
      ;; Packages are normally installed into directories named "<pkg>-<vers>",
@@ -4154,6 +4167,22 @@ beginning of the line."
             (package-version-join (package-desc-version package-desc))
             (package-desc-summary package-desc))))
 
+(defun package-browse-url (desc &optional secondary)
+  "Open the home page of the package under point in a browser.
+`browse-url' is used to determine the browser to be used.
+If SECONDARY (interactively, the prefix), use the secondary browser."
+  (interactive (list (tabulated-list-get-id)
+                     current-prefix-arg)
+               package-menu-mode)
+  (unless desc
+    (user-error "No package here"))
+  (let ((url (cdr (assoc :url (package-desc-extras desc)))))
+    (unless url
+      (user-error "No home page for %s" (package-desc-name desc)))
+    (if secondary
+       (funcall browse-url-secondary-browser-function url)
+      (browse-url url))))
+
 ;;;; Introspection
 
 (defun package-get-descriptor (pkg-name)
diff --git a/lisp/emacs-lisp/pcase.el b/lisp/emacs-lisp/pcase.el
index ec746fa..006517d 100644
--- a/lisp/emacs-lisp/pcase.el
+++ b/lisp/emacs-lisp/pcase.el
@@ -27,19 +27,10 @@
 
 ;; Todo:
 
-;; - (pcase e (`(,x . ,x) foo)) signals an "x unused" warning if `foo' doesn't
-;;   use x, because x is bound separately for the equality constraint
-;;   (as well as any pred/guard) and for the body, so uses at one place don't
-;;   count for the other.
-;; - provide ways to extend the set of primitives, with some kind of
-;;   define-pcase-matcher.  We could easily make it so that (guard BOOLEXP)
-;;   could be defined this way, as a shorthand for (pred (lambda (_) BOOLEXP)).
-;;   But better would be if we could define new ways to match by having the
-;;   extension provide its own `pcase--split-<foo>' thingy.
-;; - along these lines, provide patterns to match CL structs.
+;; - Allow to provide new `pcase--split-<foo>' thingy.
 ;; - provide something like (setq VAR) so a var can be set rather than
 ;;   let-bound.
-;; - provide a way to fallthrough to subsequent cases
+;; - provide a way to continue matching to subsequent cases
 ;;   (e.g. Like Racket's (=> ID).
 ;; - try and be more clever to reduce the size of the decision tree, and
 ;;   to reduce the number of leaves that need to be turned into functions:
@@ -71,48 +62,37 @@
 
 (defvar pcase--dontwarn-upats '(pcase--dontcare))
 
-(def-edebug-spec
-  pcase-PAT
-  (&or symbolp
-       ("or" &rest pcase-PAT)
-       ("and" &rest pcase-PAT)
-       ("guard" form)
-       ("let" pcase-PAT form)
-       ("pred" pcase-FUN)
-       ("app" pcase-FUN pcase-PAT)
-       pcase-MACRO
-       sexp))
-
-(def-edebug-spec
-  pcase-FUN
-  (&or lambda-expr
-       ;; Punt on macros/special forms.
-       (functionp &rest form)
-       sexp))
-
-;; See bug#24717
-(put 'pcase-MACRO 'edebug-form-spec 'pcase--edebug-match-macro)
+(def-edebug-elem-spec 'pcase-PAT
+  '(&or (&interpose symbolp pcase--edebug-match-pat-args) sexp))
+
+(def-edebug-elem-spec 'pcase-FUN
+  '(&or lambda-expr
+        ;; Punt on macros/special forms.
+        (functionp &rest form)
+        sexp))
 
 ;; Only called from edebug.
-(declare-function get-edebug-spec "edebug" (symbol))
-(declare-function edebug-match "edebug" (cursor specs))
+(declare-function edebug-get-spec "edebug" (symbol))
+(defun pcase--edebug-match-pat-args (head pf)
+  ;; (cl-assert (null (cdr head)))
+  (setq head (car head))
+  (or (alist-get head '((quote sexp)
+                        (or    &rest pcase-PAT)
+                        (and   &rest pcase-PAT)
+                        (guard form)
+                        (pred  &or ("not" pcase-FUN) pcase-FUN)
+                        (app   pcase-FUN pcase-PAT)))
+      (let ((me (pcase--get-macroexpander head)))
+        (funcall pf (and me (symbolp me) (edebug-get-spec me))))))
 
 (defun pcase--get-macroexpander (s)
   "Return the macroexpander for pcase pattern head S, or nil"
   (get s 'pcase-macroexpander))
 
-(defun pcase--edebug-match-macro (cursor)
-  (let (specs)
-    (mapatoms
-     (lambda (s)
-       (let ((m (pcase--get-macroexpander s)))
-        (when (and m (get-edebug-spec m))
-          (push (cons (symbol-name s) (get-edebug-spec m))
-                specs)))))
-    (edebug-match cursor (cons '&or specs))))
-
 ;;;###autoload
 (defmacro pcase (exp &rest cases)
+  ;; FIXME: Add some "global pattern" to wrap every case?
+  ;; Could be used to wrap all cases in a `
   "Evaluate EXP to get EXPVAL; try passing control to one of CASES.
 CASES is a list of elements of the form (PATTERN CODE...).
 For the first CASE whose PATTERN \"matches\" EXPVAL,
@@ -227,6 +207,7 @@ If EXP fails to match any of the patterns in CASES, an 
error is signaled."
          (pcase--dontwarn-upats (cons x pcase--dontwarn-upats)))
     (pcase--expand
      ;; FIXME: Could we add the FILE:LINE data in the error message?
+     ;; FILE is available from `macroexp-file-name'.
      exp (append cases `((,x (error "No clause matching `%S'" ,x)))))))
 
 ;;;###autoload
@@ -340,82 +321,124 @@ of the elements of LIST is performed as if by 
`pcase-let'.
 (defun pcase--trivial-upat-p (upat)
   (and (symbolp upat) (not (memq upat pcase--dontcare-upats))))
 
-(defun pcase--expand (exp cases)
-  ;; (message "pid=%S (pcase--expand %S ...hash=%S)"
-  ;;          (emacs-pid) exp (sxhash cases))
+(defun pcase-compile-patterns (exp cases)
+  "Compile the set of patterns in CASES.
+EXP is the expression that will be matched against the patterns.
+CASES is a list of elements (PAT . CODEGEN)
+where CODEGEN is a function that returns the code to use when
+PAT matches.  That code has to be in the form of a cons cell.
+
+CODEGEN will be called with at least 2 arguments, VARVALS and COUNT.
+VARVALS is a list of elements of the form (VAR VAL . RESERVED) where VAR
+is a variable bound by the pattern and VAL is a duplicable expression
+that returns the value this variable should be bound to.
+If the pattern PAT uses `or', CODEGEN may be called multiple times,
+in which case it may want to generate the code differently to avoid
+a potential code explosion.  For this reason the COUNT argument indicates
+how many time this CODEGEN is called."
   (macroexp-let2 macroexp-copyable-p val exp
-    (let* ((defs ())
-           (seen '())
-           (codegen
-            (lambda (code vars)
-              (let ((vars (macroexp--fgrep vars code))
-                    (prev (assq code seen)))
-                (if (not prev)
-                    (let ((res (pcase-codegen code vars)))
-                      (push (list code vars res) seen)
-                      res)
-                  ;; Since we use a tree-based pattern matching
-                  ;; technique, the leaves (the places that contain the
-                  ;; code to run once a pattern is matched) can get
-                  ;; copied a very large number of times, so to avoid
-                  ;; code explosion, we need to keep track of how many
-                  ;; times we've used each leaf and move it
-                  ;; to a separate function if that number is too high.
-                  ;;
-                  ;; We've already used this branch.  So it is shared.
-                  (let* ((code (car prev))         (cdrprev (cdr prev))
-                         (prevvars (car cdrprev))  (cddrprev (cdr cdrprev))
-                         (res (car cddrprev)))
-                    (unless (symbolp res)
-                      ;; This is the first repeat, so we have to move
-                      ;; the branch to a separate function.
-                      (let ((bsym
-                             (make-symbol (format "pcase-%d" (length defs)))))
-                        (push `(,bsym (lambda ,(mapcar #'car prevvars) ,@code))
-                              defs)
-                        (setcar res 'funcall)
-                        (setcdr res (cons bsym (mapcar #'cdr prevvars)))
-                        (setcar (cddr prev) bsym)
-                        (setq res bsym)))
-                    (setq vars (copy-sequence vars))
-                    (let ((args (mapcar (lambda (pa)
-                                          (let ((v (assq (car pa) vars)))
-                                            (setq vars (delq v vars))
-                                            (cdr v)))
-                                        prevvars)))
-                      ;; If some of `vars' were not found in `prevvars', that's
-                      ;; OK it just means those vars aren't present in all
-                      ;; branches, so they can be used within the pattern
-                      ;; (e.g. by a `guard/let/pred') but not in the branch.
-                      ;; FIXME: But if some of `prevvars' are not in `vars' we
-                      ;; should remove them from `prevvars'!
-                      `(funcall ,res ,@args)))))))
-           (used-cases ())
+    (let* ((seen '())
+           (phcounter 0)
            (main
             (pcase--u
-             (mapcar (lambda (case)
-                       `(,(pcase--match val (pcase--macroexpand (car case)))
-                         ,(lambda (vars)
-                            (unless (memq case used-cases)
-                              ;; Keep track of the cases that are used.
-                              (push case used-cases))
-                            (funcall
-                             (if (pcase--small-branch-p (cdr case))
-                                 ;; Don't bother sharing multiple
-                                 ;; occurrences of this leaf since it's small.
-                                 (lambda (code vars)
-                                   (pcase-codegen code
-                                                  (macroexp--fgrep vars code)))
-                               codegen)
-                             (cdr case)
-                             vars))))
-                     cases))))
+             (mapcar
+              (lambda (case)
+                `(,(pcase--match val (pcase--macroexpand (car case)))
+                  ,(lambda (vars)
+                     (let ((prev (assq case seen)))
+                       (unless prev
+                         ;; Keep track of the cases that are used.
+                         (push (setq prev (list case)) seen))
+                       ;; Put a counter in the cdr just so that not
+                       ;; all branches look identical (to avoid things
+                       ;; like `macroexp--if' optimizing them too
+                       ;; optimistically).
+                       (let ((ph (cons 'pcase--placeholder
+                                       (setq phcounter (1+ phcounter)))))
+                         (setcdr prev (cons (cons vars ph) (cdr prev)))
+                         ph)))))
+              cases))))
+      ;; Take care of the place holders now.
+      (dolist (branch seen)
+        (let ((codegen (cdar branch))
+              (uses (cdr branch)))
+          ;; Find all the vars that are in scope (the union of the
+          ;; vars provided in each use case).
+          (let* ((allvarinfo '())
+                 (_ (dolist (use uses)
+                      (dolist (v (car use))
+                        (let ((vi (assq (car v) allvarinfo)))
+                          (if vi
+                              (if (cddr v) (setcdr vi 'used))
+                            (push (cons (car v) (cddr v)) allvarinfo))))))
+                 (allvars (mapcar #'car allvarinfo)))
+            (dolist (use uses)
+              (let* ((vars (car use))
+                     (varvals
+                      (mapcar (lambda (v)
+                                `(,v ,(cadr (assq v vars))
+                                     ,(cdr (assq v allvarinfo))))
+                              allvars))
+                     (placeholder (cdr use))
+                     (code (funcall codegen varvals (length uses))))
+                ;; (cl-assert (eq (car placeholder) 'pcase--placeholder))
+                (setcar placeholder (car code))
+                (setcdr placeholder (cdr code)))))))
       (dolist (case cases)
-        (unless (or (memq case used-cases)
+        (unless (or (assq case seen)
                     (memq (car case) pcase--dontwarn-upats))
-          (message "pcase pattern %S shadowed by previous pcase pattern"
-                   (car case))))
-      (macroexp-let* defs main))))
+          (setq main
+                (macroexp-warn-and-return
+                 (format "pcase pattern %S shadowed by previous pcase pattern"
+                         (car case))
+                 main))))
+      main)))
+
+(defun pcase--expand (exp cases)
+  ;; (message "pid=%S (pcase--expand %S ...hash=%S)"
+  ;;          (emacs-pid) exp (sxhash cases))
+  (let* ((defs ())
+         (codegen
+          (lambda (code)
+            (if (member code '(nil (nil) ('nil)))
+                (lambda (&rest _) ''nil)
+              (let ((bsym ()))
+                (lambda (varvals count &rest _)
+                  (let* ((ignored-vars
+                          (delq nil (mapcar (lambda (vv) (if (nth 2 vv) (car 
vv)))
+                                            varvals)))
+                         (ignores (if ignored-vars
+                                      `((ignore . ,ignored-vars)))))
+                    ;; Since we use a tree-based pattern matching
+                    ;; technique, the leaves (the places that contain the
+                    ;; code to run once a pattern is matched) can get
+                    ;; copied a very large number of times, so to avoid
+                    ;; code explosion, we need to keep track of how many
+                    ;; times we've used each leaf and move it
+                    ;; to a separate function if that number is too high.
+                    (if (or (< count 2) (pcase--small-branch-p code))
+                        `(let ,(mapcar (lambda (vv) (list (car vv) (cadr vv)))
+                                       varvals)
+                           ;; Try and silence some of the most common
+                           ;; spurious "unused var" warnings.
+                           ,@ignores
+                           ,@code)
+                    ;; Several occurrence of this non-small branch in
+                    ;; the output.
+                    (unless bsym
+                      (setq bsym (make-symbol
+                                  (format "pcase-%d" (length defs))))
+                      (push `(,bsym (lambda ,(mapcar #'car varvals)
+                                      ,@ignores ,@code))
+                            defs))
+                    `(funcall ,bsym ,@(mapcar #'cadr varvals)))))))))
+         (main
+          (pcase-compile-patterns
+           exp
+           (mapcar (lambda (case)
+                     (cons (car case) (funcall codegen (cdr case))))
+                   cases))))
+    (macroexp-let* defs main)))
 
 (defun pcase--macroexpand (pat)
   "Expands all macro-patterns in PAT."
@@ -452,7 +475,13 @@ for the result of evaluating EXP (first arg to `pcase').
        (decl (assq 'declare body)))
     (when decl (setq body (remove decl body)))
     `(progn
-       (defun ,fsym ,args ,@body)
+       ;; FIXME: We use `eval-and-compile' here so that the pcase macro can be
+       ;; used in the same file where it's defined, but ideally, we should
+       ;; handle this using something similar to `overriding-plist-environment'
+       ;; but for `symbol-function' slots so compiling a file doesn't have the
+       ;; side-effect of defining the function.
+       (eval-and-compile
+         (defun ,fsym ,args ,@body))
        (define-symbol-prop ',fsym 'edebug-form-spec ',(cadr (assq 'debug 
decl)))
        (define-symbol-prop ',name 'pcase-macroexpander #',fsym))))
 
@@ -468,15 +497,6 @@ for the result of evaluating EXP (first arg to `pcase').
    (t
     `(match ,val . ,upat))))
 
-(defun pcase-codegen (code vars)
-  ;; Don't use let*, otherwise macroexp-let* may merge it with some surrounding
-  ;; let* which might prevent the setcar/setcdr in pcase--expand's fancy
-  ;; codegen from later metamorphosing this let into a funcall.
-  (if vars
-      `(let ,(mapcar (lambda (b) (list (car b) (cdr b))) vars)
-         ,@code)
-    `(progn ,@code)))
-
 (defun pcase--small-branch-p (code)
   (and (= 1 (length code))
        (or (not (consp (car code)))
@@ -489,8 +509,10 @@ for the result of evaluating EXP (first arg to `pcase').
 ;; the depth of the generated tree.
 (defun pcase--if (test then else)
   (cond
-   ((eq else :pcase--dontcare) then)
-   ((eq then :pcase--dontcare) (debug) else) ;Can/should this ever happen?
+   ((eq else :pcase--dontcare) `(progn (ignore ,test) ,then))
+   ;; This happens very rarely.  Known case:
+   ;;     (pcase EXP ((and 1 pcase--dontcare) FOO))
+   ((eq then :pcase--dontcare) `(progn (ignore ,test) ,else))
    (t (macroexp-if test then else))))
 
 ;; Note about MATCH:
@@ -515,11 +537,14 @@ for the result of evaluating EXP (first arg to `pcase').
   "Expand matcher for rules BRANCHES.
 Each BRANCH has the form (MATCH CODE . VARS) where
 CODE is the code generator for that branch.
-VARS is the set of vars already bound by earlier matches.
 MATCH is the pattern that needs to be matched, of the form:
   (match VAR . PAT)
   (and MATCH ...)
-  (or MATCH ...)"
+  (or MATCH ...)
+VARS is the set of vars already bound by earlier matches.
+It is a list of (NAME VAL . USED) where NAME is the variable's symbol,
+VAL is the expression to which it should be bound and USED is a boolean
+recording whether the var has been referenced by earlier parts of the match."
   (when (setq branches (delq nil branches))
     (let* ((carbranch (car branches))
            (match (car carbranch)) (cdarbranch (cdr carbranch))
@@ -662,7 +687,7 @@ MATCH is the pattern that needs to be matched, of the form:
 
 (defun pcase--split-pred (vars upat pat)
   "Indicate the overlap or mutual-exclusion between UPAT and PAT.
-More specifically retuns a pair (A . B) where A indicates whether PAT
+More specifically returns a pair (A . B) where A indicates whether PAT
 can match when UPAT has matched, and B does the same for the case
 where UPAT failed to match.
 A and B can be one of:
@@ -679,7 +704,7 @@ A and B can be one of:
                ;; run, but we don't have the environment in which `pat' will
                ;; run, so we can't do a reliable verification.  But let's try
                ;; and catch at least the easy cases such as (bug#14773).
-               (not (macroexp--fgrep (mapcar #'car vars) (cadr upat)))))
+               (not (macroexp--fgrep vars (cadr upat)))))
       '(:pcase--succeed . :pcase--fail))
      ;; In case PAT is of the form (pred (not PRED))
      ((and (eq 'pred (car-safe pat)) (eq 'not (car-safe (cadr pat))))
@@ -766,8 +791,11 @@ A and B can be one of:
    ((symbolp fun) `(,fun ,arg))
    ((eq 'not (car-safe fun)) `(not ,(pcase--funcall (cadr fun) arg vars)))
    (t
-    (let* (;; `env' is an upper bound on the bindings we need.
-           (env (mapcar (lambda (x) (list (car x) (cdr x)))
+    (let* (;; `env' is hopefully an upper bound on the bindings we need,
+           ;; FIXME: See bug#46786 for a counter example :-(
+           (env (mapcar (lambda (x)
+                          (setcdr (cdr x) 'used)
+                          (list (car x) (cadr x)))
                         (macroexp--fgrep vars fun)))
            (call (progn
                    (when (assq arg env)
@@ -775,7 +803,7 @@ A and B can be one of:
                      (let ((newsym (gensym "x")))
                        (push (list newsym arg) env)
                        (setq arg newsym)))
-                   (if (functionp fun)
+                   (if (or (functionp fun) (not (consp fun)))
                        `(funcall #',fun ,arg)
                      `(,@fun ,arg)))))
       (if (null env)
@@ -788,10 +816,12 @@ A and B can be one of:
 (defun pcase--eval (exp vars)
   "Build an expression that will evaluate EXP."
   (let* ((found (assq exp vars)))
-    (if found (cdr found)
+    (if found (progn (setcdr (cdr found) 'used) (cadr found))
       (let* ((env (macroexp--fgrep vars exp)))
         (if env
-            (macroexp-let* (mapcar (lambda (x) (list (car x) (cdr x)))
+            (macroexp-let* (mapcar (lambda (x)
+                                     (setcdr (cdr x) 'used)
+                                     (list (car x) (cadr x)))
                                    env)
                            exp)
           exp)))))
@@ -804,7 +834,7 @@ Otherwise, it defers to REST which is a list of branches of 
the form
 \(ELSE-MATCH ELSE-CODE . ELSE-VARS)."
   ;; Depending on the order in which we choose to check each of the MATCHES,
   ;; the resulting tree may be smaller or bigger.  So in general, we'd want
-  ;; to be careful to chose the "optimal" order.  But predicate
+  ;; to be careful to choose the "optimal" order.  But predicate
   ;; patterns make this harder because they create dependencies
   ;; between matches.  So we don't bother trying to reorder anything.
   (cond
@@ -865,7 +895,7 @@ Otherwise, it defers to REST which is a list of branches of 
the form
        ((memq upat '(t _))
         (let ((code (pcase--u1 matches code vars rest)))
           (if (eq upat '_) code
-            (macroexp--warn-and-return
+            (macroexp-warn-and-return
              "Pattern t is deprecated.  Use `_' instead"
              code))))
        ((eq upat 'pcase--dontcare) :pcase--dontcare)
@@ -883,12 +913,14 @@ Otherwise, it defers to REST which is a list of branches 
of the form
                      (pcase--u else-rest))))
        ((and (symbolp upat) upat)
         (pcase--mark-used sym)
-        (if (not (assq upat vars))
-            (pcase--u1 matches code (cons (cons upat sym) vars) rest)
-          ;; Non-linear pattern.  Turn it into an `eq' test.
-          (pcase--u1 (cons `(match ,sym . (pred (eql ,(cdr (assq upat vars)))))
-                           matches)
-                     code vars rest)))
+        (let ((v (assq upat vars)))
+          (if (not v)
+              (pcase--u1 matches code (cons (list upat sym) vars) rest)
+            ;; Non-linear pattern.  Turn it into an `eq' test.
+            (setcdr (cdr v) 'used)
+            (pcase--u1 (cons `(match ,sym . (pred (eql ,(cadr v))))
+                             matches)
+                       code vars rest))))
        ((eq (car-safe upat) 'app)
         ;; A upat of the form (app FUN PAT)
         (pcase--mark-used sym)
@@ -946,14 +978,13 @@ Otherwise, it defers to REST which is a list of branches 
of the form
        (t (error "Unknown pattern `%S'" upat)))))
    (t (error "Incorrect MATCH %S" (car matches)))))
 
-(def-edebug-spec
-  pcase-QPAT
+(def-edebug-elem-spec 'pcase-QPAT
   ;; Cf. edebug spec for `backquote-form' in edebug.el.
-  (&or ("," pcase-PAT)
-       (pcase-QPAT [&rest [&not ","] pcase-QPAT]
-                  . [&or nil pcase-QPAT])
-       (vector &rest pcase-QPAT)
-       sexp))
+  '(&or ("," pcase-PAT)
+        (pcase-QPAT [&rest [&not ","] pcase-QPAT]
+                   . [&or nil pcase-QPAT])
+       (vector &rest pcase-QPAT)
+       sexp))
 
 (pcase-defmacro \` (qpat)
   "Backquote-style pcase patterns: \\=`QPAT
@@ -992,8 +1023,8 @@ The predicate is the logical-AND of:
               (nreverse upats))))
    ((consp qpat)
     `(and (pred consp)
-          (app car ,(list '\` (car qpat)))
-          (app cdr ,(list '\` (cdr qpat)))))
+          (app car-safe ,(list '\` (car qpat)))
+          (app cdr-safe ,(list '\` (cdr qpat)))))
    ((or (stringp qpat) (numberp qpat) (symbolp qpat)) `',qpat)
    ;; In all other cases just raise an error so we can't break
    ;; backward compatibility when adding \` support for other
@@ -1002,7 +1033,13 @@ The predicate is the logical-AND of:
 
 (pcase-defmacro let (pat expr)
   "Matches if EXPR matches PAT."
+  (declare (debug (pcase-PAT form)))
   `(app (lambda (_) ,expr) ,pat))
 
+;; (pcase-defmacro guard (expr)
+;;   "Matches if EXPR is non-nil."
+;;   (declare (debug (form)))
+;;   `(pred (lambda (_) ,expr)))
+
 (provide 'pcase)
 ;;; pcase.el ends here
diff --git a/lisp/emacs-lisp/radix-tree.el b/lisp/emacs-lisp/radix-tree.el
index 0905ac6..fb65975 100644
--- a/lisp/emacs-lisp/radix-tree.el
+++ b/lisp/emacs-lisp/radix-tree.el
@@ -194,14 +194,13 @@ If not found, return nil."
   "Return an alist of all bindings in TREE for prefixes of STRING."
   (radix-tree--prefixes tree string 0 nil))
 
-(eval-and-compile
-  (pcase-defmacro radix-tree-leaf (vpat)
-    "Pattern which matches a radix-tree leaf.
+(pcase-defmacro radix-tree-leaf (vpat)
+  "Pattern which matches a radix-tree leaf.
 The pattern VPAT is matched against the leaf's carried value."
-    ;; We used to use `(pred atom)', but `pcase' doesn't understand that
-    ;; `atom' is equivalent to the negation of `consp' and hence generates
-    ;; suboptimal code.
-    `(or `(t . ,,vpat) (and (pred (not consp)) ,vpat))))
+  ;; We used to use `(pred atom)', but `pcase' doesn't understand that
+  ;; `atom' is equivalent to the negation of `consp' and hence generates
+  ;; suboptimal code.
+  `(or `(t . ,,vpat) (and (pred (not consp)) ,vpat)))
 
 (defun radix-tree-iter-subtrees (tree fun)
   "Apply FUN to every immediate subtree of radix TREE.
diff --git a/lisp/emacs-lisp/re-builder.el b/lisp/emacs-lisp/re-builder.el
index ce8d98d..455fcac 100644
--- a/lisp/emacs-lisp/re-builder.el
+++ b/lisp/emacs-lisp/re-builder.el
@@ -217,8 +217,7 @@ Except for Lisp syntax this is the same as `reb-regexp'.")
 
 ;; Define the local "\C-c" keymap
 (defvar reb-mode-map
-  (let ((map (make-sparse-keymap))
-       (menu-map (make-sparse-keymap)))
+  (let ((map (make-sparse-keymap)))
     (define-key map "\C-c\C-c" 'reb-toggle-case)
     (define-key map "\C-c\C-q" 'reb-quit)
     (define-key map "\C-c\C-w" 'reb-copy)
@@ -228,43 +227,37 @@ Except for Lisp syntax this is the same as `reb-regexp'.")
     (define-key map "\C-c\C-e" 'reb-enter-subexp-mode)
     (define-key map "\C-c\C-b" 'reb-change-target-buffer)
     (define-key map "\C-c\C-u" 'reb-force-update)
-    (define-key map [menu-bar reb-mode] (cons "Re-Builder" menu-map))
-    (define-key menu-map [rq]
-      '(menu-item "Quit" reb-quit
-                 :help "Quit the RE Builder mode"))
-    (define-key menu-map [div1] '(menu-item "--"))
-    (define-key menu-map [rt]
-      '(menu-item "Case sensitive" reb-toggle-case
-                 :button (:toggle . (with-current-buffer
-                                        reb-target-buffer
-                                      (null case-fold-search)))
-                 :help "Toggle case sensitivity of searches for RE Builder 
target buffer"))
-    (define-key menu-map [rb]
-      '(menu-item "Change target buffer..." reb-change-target-buffer
-                 :help "Change the target buffer and display it in the target 
window"))
-    (define-key menu-map [rs]
-      '(menu-item "Change syntax..." reb-change-syntax
-                 :help "Change the syntax used by the RE Builder"))
-    (define-key menu-map [div2] '(menu-item "--"))
-    (define-key menu-map [re]
-      '(menu-item "Enter subexpression mode" reb-enter-subexp-mode
-                 :help "Enter the subexpression mode in the RE Builder"))
-    (define-key menu-map [ru]
-      '(menu-item "Force update" reb-force-update
-                 :help "Force an update in the RE Builder target window 
without a match limit"))
-    (define-key menu-map [rn]
-      '(menu-item "Go to next match" reb-next-match
-                 :help "Go to next match in the RE Builder target window"))
-    (define-key menu-map [rp]
-      '(menu-item "Go to previous match" reb-prev-match
-                 :help "Go to previous match in the RE Builder target window"))
-    (define-key menu-map [div3] '(menu-item "--"))
-    (define-key menu-map [rc]
-      '(menu-item "Copy current RE" reb-copy
-                 :help "Copy current RE into the kill ring for later 
insertion"))
     map)
   "Keymap used by the RE Builder.")
 
+(easy-menu-define reb-mode-menu reb-mode-map
+  "Menu for the RE Builder."
+  '("Re-Builder"
+    ["Copy current RE" reb-copy
+     :help "Copy current RE into the kill ring for later insertion"]
+    "---"
+    ["Go to previous match" reb-prev-match
+     :help "Go to previous match in the RE Builder target window"]
+    ["Go to next match" reb-next-match
+     :help "Go to next match in the RE Builder target window"]
+    ["Force update" reb-force-update
+     :help "Force an update in the RE Builder target window without a match 
limit"]
+    ["Enter subexpression mode" reb-enter-subexp-mode
+     :help "Enter the subexpression mode in the RE Builder"]
+    "---"
+    ["Change syntax..." reb-change-syntax
+     :help "Change the syntax used by the RE Builder"]
+    ["Change target buffer..." reb-change-target-buffer
+     :help "Change the target buffer and display it in the target window"]
+    ["Case sensitive" reb-toggle-case
+     :style toggle
+     :selected (with-current-buffer reb-target-buffer
+                 (null case-fold-search))
+     :help "Toggle case sensitivity of searches for RE Builder target buffer"]
+    "---"
+    ["Quit" reb-quit
+     :help "Quit the RE Builder mode"]))
+
 (define-derived-mode reb-mode nil "RE Builder"
   "Major mode for interactively building Regular Expressions."
   (setq-local blink-matching-paren nil)
@@ -368,7 +361,6 @@ matching parts of the target buffer will be highlighted."
 (defun reb-change-target-buffer (buf)
   "Change the target buffer and display it in the target window."
   (interactive "bSet target buffer to: ")
-
   (let ((buffer (get-buffer buf)))
     (if (not buffer)
         (error "No such buffer")
@@ -381,7 +373,6 @@ matching parts of the target buffer will be highlighted."
 (defun reb-force-update ()
   "Force an update in the RE Builder target window without a match limit."
   (interactive)
-
   (let ((reb-auto-match-limit nil))
     (reb-update-overlays
      (if reb-subexp-mode reb-subexp-displayed nil))))
@@ -389,7 +380,6 @@ matching parts of the target buffer will be highlighted."
 (defun reb-quit ()
   "Quit the RE Builder mode."
   (interactive)
-
   (setq reb-subexp-mode nil
        reb-subexp-displayed nil)
   (reb-delete-overlays)
@@ -399,7 +389,6 @@ matching parts of the target buffer will be highlighted."
 (defun reb-next-match ()
   "Go to next match in the RE Builder target window."
   (interactive)
-
   (reb-assert-buffer-in-window)
   (with-selected-window reb-target-window
     (if (not (re-search-forward reb-regexp (point-max) t))
@@ -411,7 +400,6 @@ matching parts of the target buffer will be highlighted."
 (defun reb-prev-match ()
   "Go to previous match in the RE Builder target window."
   (interactive)
-
   (reb-assert-buffer-in-window)
   (with-selected-window reb-target-window
     (let ((p (point)))
@@ -426,7 +414,6 @@ matching parts of the target buffer will be highlighted."
 (defun reb-toggle-case ()
   "Toggle case sensitivity of searches for RE Builder target buffer."
   (interactive)
-
   (with-current-buffer reb-target-buffer
     (setq case-fold-search (not case-fold-search)))
   (reb-update-modestring)
@@ -435,7 +422,6 @@ matching parts of the target buffer will be highlighted."
 (defun reb-copy ()
   "Copy current RE into the kill ring for later insertion."
   (interactive)
-
   (reb-update-regexp)
   (let ((re (with-output-to-string
              (print (reb-target-binding reb-regexp)))))
@@ -503,7 +489,6 @@ Optional argument SYNTAX must be specified if called 
non-interactively."
 (defun reb-do-update (&optional subexp)
   "Update matches in the RE Builder target window.
 If SUBEXP is non-nil mark only the corresponding sub-expressions."
-
   (reb-assert-buffer-in-window)
   (reb-update-regexp)
   (reb-update-overlays subexp))
@@ -541,7 +526,6 @@ optional fourth argument FORCE is non-nil."
 
 (defun reb-assert-buffer-in-window ()
   "Assert that `reb-target-buffer' is displayed in `reb-target-window'."
-
   (if (not (eq reb-target-buffer (window-buffer reb-target-window)))
       (set-window-buffer reb-target-window reb-target-buffer)))
 
@@ -560,7 +544,6 @@ optional fourth argument FORCE is non-nil."
 (defun reb-display-subexp (&optional subexp)
   "Highlight only subexpression SUBEXP in the RE Builder."
   (interactive)
-
   (setq reb-subexp-displayed
        (or subexp (string-to-number (format "%c" last-command-event))))
   (reb-update-modestring)
@@ -568,7 +551,6 @@ optional fourth argument FORCE is non-nil."
 
 (defun reb-kill-buffer ()
   "When the RE Builder buffer is killed make sure no overlays stay around."
-
   (when (reb-mode-buffer-p)
     (reb-delete-overlays)))
 
@@ -600,7 +582,6 @@ optional fourth argument FORCE is non-nil."
 
 (defun reb-insert-regexp ()
   "Insert current RE."
-
   (let ((re (or (reb-target-binding reb-regexp)
                (reb-empty-regexp))))
   (cond ((eq reb-re-syntax 'read)
@@ -636,7 +617,6 @@ Return t if the (cooked) expression changed."
 ;; And now the real core of the whole thing
 (defun reb-count-subexps (re)
   "Return number of sub-expressions in the regexp RE."
-
   (let ((i 0) (beg 0))
     (while (string-match "\\\\(" re beg)
       (setq i (1+ i)
diff --git a/lisp/emacs-lisp/rx.el b/lisp/emacs-lisp/rx.el
index b29b870..56e588e 100644
--- a/lisp/emacs-lisp/rx.el
+++ b/lisp/emacs-lisp/rx.el
@@ -890,7 +890,7 @@ Return (REGEXP . PRECEDENCE)."
                                (* (or (seq "[:" (+ (any "a-z")) ":]")
                                       (not (any "]"))))
                                "]")
-                          anything
+                          (not (any "*+?^$[\\"))
                           (seq "\\"
                                (or anything
                                    (seq (any "sScC_") anything)
@@ -1418,6 +1418,12 @@ into a plain rx-expression, collecting names into 
`rx--pcase-vars'."
      (cons head (mapcar #'rx--pcase-transform rest)))
     (_ rx)))
 
+(defun rx--reduce-right (f l)
+  "Right-reduction on L by F.  L must be non-empty."
+  (if (cdr l)
+      (funcall f (car l) (rx--reduce-right f (cdr l)))
+    (car l)))
+
 ;;;###autoload
 (pcase-defmacro rx (&rest regexps)
   "A pattern that matches strings against `rx' REGEXPS in sexp form.
@@ -1436,13 +1442,28 @@ following constructs:
                    introduced by a previous (let REF ...)
                    construct."
   (let* ((rx--pcase-vars nil)
-         (regexp (rx--to-expr (rx--pcase-transform (cons 'seq regexps)))))
-    `(and (pred (string-match ,regexp))
-          ,@(let ((i 0))
-              (mapcar (lambda (name)
-                        (setq i (1+ i))
-                        `(app (match-string ,i) ,name))
-                      (reverse rx--pcase-vars))))))
+         (regexp (rx--to-expr (rx--pcase-transform (cons 'seq regexps))))
+         (nvars (length rx--pcase-vars)))
+    `(and (pred stringp)
+          ,(if (zerop nvars)
+               ;; No variables bound: a single predicate suffices.
+               `(pred (string-match ,regexp))
+             ;; Pack the submatches into a dotted list which is then
+             ;; immediately destructured into individual variables again.
+             ;; This is of course slightly inefficient when NVARS > 1.
+             ;; A dotted list is used to reduce the number of conses
+             ;; to create and take apart.
+             `(app (lambda (s)
+                     (and (string-match ,regexp s)
+                          ,(rx--reduce-right
+                            (lambda (a b) `(cons ,a ,b))
+                            (mapcar (lambda (i) `(match-string ,i s))
+                                    (number-sequence 1 nvars)))))
+                   ,(list '\`
+                          (rx--reduce-right
+                           #'cons
+                           (mapcar (lambda (name) (list '\, name))
+                                   (reverse rx--pcase-vars)))))))))
 
 ;; Obsolete internal symbol, used in old versions of the `flycheck' package.
 (define-obsolete-function-alias 'rx-submatch-n 'rx-to-string "27.1")
diff --git a/lisp/emacs-lisp/seq.el b/lisp/emacs-lisp/seq.el
index 31c15fe..2b8807f 100644
--- a/lisp/emacs-lisp/seq.el
+++ b/lisp/emacs-lisp/seq.el
@@ -134,9 +134,10 @@ Unlike `seq-map', FUNCTION takes two arguments: the 
element of
 the sequence, and its index within the sequence."
   (let ((index 0))
     (seq-do (lambda (elt)
-               (funcall function elt index)
-               (setq index (1+ index)))
-             sequence)))
+              (funcall function elt index)
+              (setq index (1+ index)))
+            sequence))
+  nil)
 
 (cl-defgeneric seqp (object)
   "Return non-nil if OBJECT is a sequence, nil otherwise."
@@ -393,9 +394,9 @@ found or not."
     count))
 
 (cl-defgeneric seq-contains (sequence elt &optional testfn)
-  (declare (obsolete seq-contains-p "27.1"))
   "Return the first element in SEQUENCE that is equal to ELT.
 Equality is defined by TESTFN if non-nil or by `equal' if nil."
+  (declare (obsolete seq-contains-p "27.1"))
   (seq-some (lambda (e)
               (when (funcall (or testfn #'equal) elt e)
                 e))
@@ -455,6 +456,7 @@ negative integer or 0, nil is returned."
         (setq sequence (seq-drop sequence n)))
       (nreverse result))))
 
+;;;###autoload
 (cl-defgeneric seq-intersection (sequence1 sequence2 &optional testfn)
   "Return a list of the elements that appear in both SEQUENCE1 and SEQUENCE2.
 Equality is defined by TESTFN if non-nil or by `equal' if nil."
diff --git a/lisp/emacs-lisp/shortdoc.el b/lisp/emacs-lisp/shortdoc.el
index 39e69f5..86d5130 100644
--- a/lisp/emacs-lisp/shortdoc.el
+++ b/lisp/emacs-lisp/shortdoc.el
@@ -40,6 +40,11 @@
     (t :height 0.1 :inverse-video t :extend t))
   "Face used to separate sections.")
 
+(defface shortdoc-heading
+  '((t :inherit variable-pitch :height 1.3 :weight bold))
+  "Face used for a heading."
+  :version "28.1")
+
 (defface shortdoc-section
   '((t :inherit variable-pitch))
   "Face used for a section.")
@@ -163,15 +168,12 @@ There can be any number of :example/:result elements."
   (replace-regexp-in-string
    :eval (replace-regexp-in-string "[a-z]+" "_" "*foo*"))
   (string-trim
-   :no-manual t
    :args (string)
    :doc "Trim STRING of leading and trailing white space."
    :eval (string-trim " foo "))
   (string-trim-left
-   :no-manual t
    :eval (string-trim-left "oofoo" "o+"))
   (string-trim-right
-   :no-manual t
    :eval (string-trim-right "barkss" "s+"))
   (string-truncate-left
    :no-manual t
@@ -1107,7 +1109,7 @@ There can be any number of :example/:result elements."
            (insert "\n"))
          (insert (propertize
                   (concat (substitute-command-keys data) "\n\n")
-                  'face '(variable-pitch (:height 1.3 :weight bold))
+                  'face 'shortdoc-heading
                   'shortdoc-section t)))
         ;; There may be functions not yet defined in the data.
         ((fboundp (car data))
@@ -1175,7 +1177,7 @@ function's documentation in the Info manual")))
                     (prin1 value (current-buffer)))
                   (insert "\n    " single-arrow " "
                           (propertize "[it depends]"
-                                      'face 'variable-pitch)
+                                      'face 'shortdoc-section)
                           "\n"))
                  (:no-value
                   (if (stringp value)
diff --git a/lisp/emacs-lisp/smie.el b/lisp/emacs-lisp/smie.el
index 44be9af..9944330 100644
--- a/lisp/emacs-lisp/smie.el
+++ b/lisp/emacs-lisp/smie.el
@@ -63,7 +63,7 @@
 ;; building the 2D precedence tables and then computing the precedence levels
 ;; from it) can be found in pages 187-194 of "Parsing techniques" by Dick Grune
 ;; and Ceriel Jacobs (BookBody.pdf available at
-;; http://dickgrune.com/Books/PTAPG_1st_Edition/).
+;; https://dickgrune.com/Books/PTAPG_1st_Edition/).
 ;;
 ;; OTOH we had to kill many chickens, read many coffee grounds, and practice
 ;; untold numbers of black magic spells, to come up with the indentation code.
diff --git a/lisp/emacs-lisp/subr-x.el b/lisp/emacs-lisp/subr-x.el
index a451445..9c8c967 100644
--- a/lisp/emacs-lisp/subr-x.el
+++ b/lisp/emacs-lisp/subr-x.el
@@ -215,28 +215,6 @@ The variable list SPEC is the same as in `if-let'."
 
 (define-obsolete-function-alias 'string-reverse 'reverse "25.1")
 
-(defsubst string-trim-left (string &optional regexp)
-  "Trim STRING of leading string matching REGEXP.
-
-REGEXP defaults to \"[ \\t\\n\\r]+\"."
-  (if (string-match (concat "\\`\\(?:" (or regexp "[ \t\n\r]+") "\\)") string)
-      (substring string (match-end 0))
-    string))
-
-(defsubst string-trim-right (string &optional regexp)
-  "Trim STRING of trailing string matching REGEXP.
-
-REGEXP defaults to  \"[ \\t\\n\\r]+\"."
-  (let ((i (string-match-p (concat "\\(?:" (or regexp "[ \t\n\r]+") "\\)\\'")
-                           string)))
-    (if i (substring string 0 i) string)))
-
-(defsubst string-trim (string &optional trim-left trim-right)
-  "Trim STRING of leading and trailing strings matching TRIM-LEFT and 
TRIM-RIGHT.
-
-TRIM-LEFT and TRIM-RIGHT default to \"[ \\t\\n\\r]+\"."
-  (string-trim-left (string-trim-right string trim-right) trim-left))
-
 ;;;###autoload
 (defun string-truncate-left (string length)
   "Truncate STRING to LENGTH, replacing initial surplus with \"...\"."
diff --git a/lisp/emacs-lisp/syntax.el b/lisp/emacs-lisp/syntax.el
index bee2f96..6d5b04b 100644
--- a/lisp/emacs-lisp/syntax.el
+++ b/lisp/emacs-lisp/syntax.el
@@ -290,12 +290,13 @@ all RULES in total."
                                     ',(string-to-syntax (nth 1 action)))
                                    ,@(nthcdr 2 action))
                                `((let ((mb (match-beginning ,gn))
-                                       (me (match-end ,gn))
-                                       (syntax ,(nth 1 action)))
-                                   (if syntax
-                                       (put-text-property
-                                        mb me 'syntax-table syntax))
-                                   ,@(nthcdr 2 action)))))
+                                       (me (match-end ,gn)))
+                                   ,(macroexp-let2 nil syntax (nth 1 action)
+                                      `(progn
+                                         (if ,syntax
+                                             (put-text-property
+                                              mb me 'syntax-table ,syntax))
+                                         ,@(nthcdr 2 action)))))))
                             (t
                              `((let ((mb (match-beginning ,gn))
                                      (me (match-end ,gn))
diff --git a/lisp/emacs-lisp/tcover-ses.el b/lisp/emacs-lisp/tcover-ses.el
index 12b0dcf..d9db1d3 100644
--- a/lisp/emacs-lisp/tcover-ses.el
+++ b/lisp/emacs-lisp/tcover-ses.el
@@ -32,8 +32,8 @@
 
 ;;;Here are some macros that exercise SES.  Set `pause' to t if you want the
 ;;;macros to pause after each step.
-(let* ((pause nil)
-       (x (if pause "\^Xq" ""))
+(let* (;; (pause nil)
+       (x (if nil "\^Xq" "")) ;; pause
        (y "\^X\^Fses-test.ses\r\^[<"))
   ;;Fiddle with the existing spreadsheet
   (fset 'ses-exercise-example
diff --git a/lisp/emacs-lisp/trace.el b/lisp/emacs-lisp/trace.el
index fa07d62..9354687 100644
--- a/lisp/emacs-lisp/trace.el
+++ b/lisp/emacs-lisp/trace.el
@@ -161,7 +161,7 @@
   "Helper function to get internal values.
 You can call this function to add internal values in the trace buffer."
   (unless inhibit-trace
-    (with-current-buffer trace-buffer
+    (with-current-buffer (get-buffer-create trace-buffer)
       (goto-char (point-max))
       (insert
        (trace-entry-message
@@ -174,7 +174,7 @@ and CONTEXT is a string describing the dynamic context 
(e.g. values of
 some global variables)."
   (let ((print-circle t))
     (format "%s%s%d -> %S%s\n"
-            (mapconcat 'char-to-string (make-string (1- level) ?|) " ")
+            (mapconcat 'char-to-string (make-string (max 0 (1- level)) ?|) " ")
             (if (> level 1) " " "")
             level
             ;; FIXME: Make it so we can click the function name to jump to its
diff --git a/lisp/emulation/cua-base.el b/lisp/emulation/cua-base.el
index a64274b..54f881b 100644
--- a/lisp/emulation/cua-base.el
+++ b/lisp/emulation/cua-base.el
@@ -1,4 +1,4 @@
-;;; cua-base.el --- emulate CUA key bindings
+;;; cua-base.el --- emulate CUA key bindings  -*- lexical-binding: t; -*-
 
 ;; Copyright (C) 1997-2021 Free Software Foundation, Inc.
 
@@ -272,19 +272,16 @@ a shifted movement key.  If the value is nil, these keys 
are never
 enabled."
   :type '(choice (const :tag "Disabled" nil)
                 (const :tag "Shift region only" shift)
-                (other :tag "Enabled" t))
-  :group 'cua)
+                (other :tag "Enabled" t)))
 
 (defcustom cua-remap-control-v t
   "If non-nil, C-v binding is used for paste (yank).
 Also, M-v is mapped to `delete-selection-repeat-replace-region'."
-  :type 'boolean
-  :group 'cua)
+  :type 'boolean)
 
 (defcustom cua-remap-control-z t
   "If non-nil, C-z binding is used for undo."
-  :type 'boolean
-  :group 'cua)
+  :type 'boolean)
 
 (defcustom cua-highlight-region-shift-only nil
   "If non-nil, only highlight region if marked with S-<move>.
@@ -292,8 +289,7 @@ When this is non-nil, CUA toggles `transient-mark-mode' on 
when the region
 is marked using shifted movement keys, and off when the mark is cleared.
 But when the mark was set using \\[cua-set-mark], Transient Mark mode
 is not turned on."
-  :type 'boolean
-  :group 'cua)
+  :type 'boolean)
 (make-obsolete-variable 'cua-highlight-region-shift-only
                         'transient-mark-mode "24.4")
 
@@ -307,33 +303,28 @@ first prefix key is discarded, so typing a prefix key 
twice in quick
 succession will also inhibit overriding the prefix key.
 If the value is nil, use a shifted prefix key to inhibit the override."
   :type '(choice (number :tag "Inhibit delay")
-                (const :tag "No delay" nil))
-  :group 'cua)
+                (const :tag "No delay" nil)))
 
 (defcustom cua-delete-selection t
   "If non-nil, typed text replaces text in the active selection."
   :type '(choice (const :tag "Disabled" nil)
-                (other :tag "Enabled" t))
-  :group 'cua)
+                (other :tag "Enabled" t)))
 
 (defcustom cua-keep-region-after-copy nil
   "If non-nil, don't deselect the region after copying."
-  :type 'boolean
-  :group 'cua)
+  :type 'boolean)
 
 (defcustom cua-toggle-set-mark t
   "If non-nil, the `cua-set-mark' command toggles the mark."
   :type '(choice (const :tag "Disabled" nil)
-                (other :tag "Enabled" t))
-  :group 'cua)
+                (other :tag "Enabled" t)))
 
 (defcustom cua-auto-mark-last-change nil
   "If non-nil, set implicit mark at position of last buffer change.
 This means that \\[universal-argument] \\[cua-set-mark] will jump to the 
position
 of the last buffer change before jumping to the explicit marks on the mark 
ring.
 See `cua-set-mark' for details."
-  :type 'boolean
-  :group 'cua)
+  :type 'boolean)
 
 (defcustom cua-enable-register-prefix 'not-ctrl-u
   "If non-nil, registers are supported via numeric prefix arg.
@@ -346,32 +337,27 @@ interpreted as a register number."
   :type '(choice (const :tag "Disabled" nil)
                 (const :tag "Enabled, but C-u arg is not a register" 
not-ctrl-u)
                 (const :tag "Enabled, but only for C-u arg" ctrl-u-only)
-                (other :tag "Enabled" t))
-  :group 'cua)
+                (other :tag "Enabled" t)))
 
 (defcustom cua-delete-copy-to-register-0 t
   ;; FIXME: Obey delete-selection-save-to-register rather than hardcoding
   ;; register 0.
   "If non-nil, save last deleted region or rectangle to register 0."
-  :type 'boolean
-  :group 'cua)
+  :type 'boolean)
 
 (defcustom cua-enable-region-auto-help nil
   "If non-nil, automatically show help for active region."
-  :type 'boolean
-  :group 'cua)
+  :type 'boolean)
 
 (defcustom cua-enable-modeline-indications nil
   "If non-nil, use minor-mode hook to show status in mode line."
-  :type 'boolean
-  :group 'cua)
+  :type 'boolean)
 
 (defcustom cua-check-pending-input t
   "If non-nil, don't override prefix key if input pending.
 It is rumored that `input-pending-p' is unreliable under some window
 managers, so try setting this to nil, if prefix override doesn't work."
-  :type 'boolean
-  :group 'cua)
+  :type 'boolean)
 
 (defcustom cua-paste-pop-rotate-temporarily nil
   "If non-nil, \\[cua-paste-pop] only rotates the kill-ring temporarily.
@@ -380,8 +366,7 @@ insert the most recently killed text.  Each immediately 
following \\[cua-paste-p
 replaces the previous text with the next older element on the `kill-ring'.
 With prefix arg, \\[universal-argument] \\[yank-pop] inserts the same text as 
the
 most recent \\[yank-pop] (or \\[yank]) command."
-  :type 'boolean
-  :group 'cua)
+  :type 'boolean)
 
 ;;; Rectangle Customization
 
@@ -390,8 +375,7 @@ most recent \\[yank-pop] (or \\[yank]) command."
 Note that although rectangles are always DISPLAYED with straight edges, the
 buffer is NOT modified, until you execute a command that actually modifies it.
 M-p toggles this feature when a rectangle is active."
-  :type 'boolean
-  :group 'cua)
+  :type 'boolean)
 
 (defcustom cua-auto-tabify-rectangles 1000
   "If non-nil, automatically tabify after rectangle commands.
@@ -403,11 +387,12 @@ present.  The number specifies then number of characters 
before
 and after the region marked by the rectangle to search."
   :type '(choice (number :tag "Auto detect (limit)")
                 (const :tag "Disabled" nil)
-                (other :tag "Enabled" t))
-  :group 'cua)
+                (other :tag "Enabled" t)))
 
 (defvar cua-global-keymap)             ; forward
 (defvar cua--region-keymap)            ; forward
+(declare-function cua-clear-rectangle-mark "cua-rect" ())
+(declare-function cua-mouse-set-rectangle-mark "cua-rect" (event))
 
 (defcustom cua-rectangle-mark-key [(control return)]
   "Global key used to toggle the cua rectangle mark."
@@ -416,14 +401,13 @@ and after the region marked by the rectangle to search."
           (when (and (boundp 'cua--keymaps-initialized)
                      cua--keymaps-initialized)
             (define-key cua-global-keymap value
-              'cua-set-rectangle-mark)
+              #'cua-set-rectangle-mark)
             (when (boundp 'cua--rectangle-keymap)
               (define-key cua--rectangle-keymap value
-                'cua-clear-rectangle-mark)
+                #'cua-clear-rectangle-mark)
               (define-key cua--region-keymap value
-                'cua-toggle-rectangle-mark))))
-  :type 'key-sequence
-  :group 'cua)
+                #'cua-toggle-rectangle-mark))))
+  :type 'key-sequence)
 
 (defcustom cua-rectangle-modifier-key 'meta
   "Modifier key used for rectangle commands bindings.
@@ -432,8 +416,7 @@ Must be set prior to enabling CUA."
   :type '(choice (const :tag "Meta key" meta)
                 (const :tag "Alt key" alt)
                 (const :tag "Hyper key" hyper)
-                (const :tag "Super key" super))
-  :group 'cua)
+                (const :tag "Super key" super)))
 
 (defcustom cua-rectangle-terminal-modifier-key 'meta
   "Modifier key used for rectangle commands bindings in terminals.
@@ -442,54 +425,46 @@ Must be set prior to enabling CUA."
                 (const :tag "Alt key" alt)
                 (const :tag "Hyper key" hyper)
                 (const :tag "Super key" super))
-  :group 'cua
   :version "27.1")
 
 (defcustom cua-enable-rectangle-auto-help t
   "If non-nil, automatically show help for region, rectangle and global mark."
-  :type 'boolean
-  :group 'cua)
+  :type 'boolean)
 
 (defface cua-rectangle
   '((default :inherit region)
     (((class color)) :foreground "white" :background "maroon"))
-  "Font used by CUA for highlighting the rectangle."
-  :group 'cua)
+  "Font used by CUA for highlighting the rectangle.")
 
 (defface cua-rectangle-noselect
   '((default :inherit region)
     (((class color)) :foreground "white" :background "dimgray"))
-  "Font used by CUA for highlighting the non-selected rectangle lines."
-  :group 'cua)
+  "Font used by CUA for highlighting the non-selected rectangle lines.")
 
 
 ;;; Global Mark Customization
 
 (defcustom cua-global-mark-keep-visible t
   "If non-nil, always keep global mark visible in other window."
-  :type 'boolean
-  :group 'cua)
+  :type 'boolean)
 
 (defface cua-global-mark
   '((((min-colors 88)(class color)) :foreground "black" :background "yellow1")
     (((class color)) :foreground "black" :background "yellow")
     (t :weight bold))
-  "Font used by CUA for highlighting the global mark."
-  :group 'cua)
+  "Font used by CUA for highlighting the global mark.")
 
 (defcustom cua-global-mark-blink-cursor-interval 0.20
   "Blink cursor at this interval when global mark is active."
   :type '(choice (number :tag "Blink interval")
-                (const :tag "No blink" nil))
-  :group 'cua)
+                (const :tag "No blink" nil)))
 
 
 ;;; Cursor Indication Customization
 
 (defcustom cua-enable-cursor-indications nil
   "If non-nil, use different cursor colors for indications."
-  :type 'boolean
-  :group 'cua)
+  :type 'boolean)
 
 (defcustom cua-normal-cursor-color (or (and (boundp 'initial-cursor-color) 
initial-cursor-color)
                                       (and (boundp 'initial-frame-alist)
@@ -507,7 +482,7 @@ If the value is a COLOR name, then only the `cursor-color' 
attribute will be
 affected.  If the value is a cursor TYPE (one of: box, hollow, bar, or hbar),
 then only the `cursor-type' property will be affected.  If the value is
 a cons (TYPE . COLOR), then both properties are affected."
-  :initialize 'custom-initialize-default
+  :initialize #'custom-initialize-default
   :type '(choice
          (color :tag "Color")
          (choice :tag "Type"
@@ -521,8 +496,7 @@ a cons (TYPE . COLOR), then both properties are affected."
                        (const :tag "Vertical bar" bar)
                        (const :tag "Horizontal bar" hbar)
                        (const :tag "Hollow box" hollow))
-               (color :tag "Color")))
-  :group 'cua)
+               (color :tag "Color"))))
 
 (defcustom cua-read-only-cursor-color "darkgreen"
   "Cursor color used in read-only buffers, if non-nil.
@@ -545,8 +519,7 @@ a cons (TYPE . COLOR), then both properties are affected."
                        (const :tag "Vertical bar" bar)
                        (const :tag "Horizontal bar" hbar)
                        (const :tag "Hollow box" hollow))
-               (color :tag "Color")))
-  :group 'cua)
+               (color :tag "Color"))))
 
 (defcustom cua-overwrite-cursor-color "yellow"
   "Cursor color used when overwrite mode is set, if non-nil.
@@ -569,8 +542,7 @@ a cons (TYPE . COLOR), then both properties are affected."
                        (const :tag "Vertical bar" bar)
                        (const :tag "Horizontal bar" hbar)
                        (const :tag "Hollow box" hollow))
-               (color :tag "Color")))
-  :group 'cua)
+               (color :tag "Color"))))
 
 (defcustom cua-global-mark-cursor-color "cyan"
   "Indication for active global mark.
@@ -594,8 +566,7 @@ a cons (TYPE . COLOR), then both properties are affected."
                        (const :tag "Vertical bar" bar)
                        (const :tag "Horizontal bar" hbar)
                        (const :tag "Hollow box" hollow))
-               (color :tag "Color")))
-  :group 'cua)
+               (color :tag "Color"))))
 
 
 ;;; Rectangle support is in cua-rect.el
@@ -710,7 +681,7 @@ a cons (TYPE . COLOR), then both properties are affected."
           (<= cua-prefix-override-inhibit-delay 0)
           ;; In state [1], start [T] and change to state [2]
           (run-with-timer cua-prefix-override-inhibit-delay nil
-                          'cua--prefix-override-timeout)))
+                          #'cua--prefix-override-timeout)))
     ;; Don't record this command
     (setq this-command last-command)
     ;; Restore the prefix arg
@@ -1243,6 +1214,8 @@ If ARG is the atom `-', scroll upward by nearly full 
screen."
   (interactive)
   (cua--shift-control-prefix ?\C-x))
 
+(declare-function delete-selection-repeat-replace-region "delsel" (arg))
+
 (defun cua--init-keymaps ()
   ;; Cache actual rectangle modifier key.
   (setq cua--rectangle-modifier-key
@@ -1250,68 +1223,84 @@ If ARG is the atom `-', scroll upward by nearly full 
screen."
            cua-rectangle-terminal-modifier-key
          cua-rectangle-modifier-key))
   ;; C-return always toggles rectangle mark
-  (define-key cua-global-keymap cua-rectangle-mark-key 'cua-set-rectangle-mark)
+  (define-key cua-global-keymap cua-rectangle-mark-key 
#'cua-set-rectangle-mark)
   (unless (eq cua--rectangle-modifier-key 'meta)
-    (cua--M/H-key cua-global-keymap ?\s                        
'cua-set-rectangle-mark)
+    (cua--M/H-key cua-global-keymap ?\s                       
#'cua-set-rectangle-mark)
     (define-key cua-global-keymap
-      (vector (list cua--rectangle-modifier-key 'mouse-1)) 
'cua-mouse-set-rectangle-mark))
+      (vector (list cua--rectangle-modifier-key 'mouse-1))
+      #'cua-mouse-set-rectangle-mark))
 
-  (define-key cua-global-keymap [(shift control ?\s)]  'cua-toggle-global-mark)
+  (define-key cua-global-keymap [(shift control ?\s)]  
#'cua-toggle-global-mark)
 
   ;; replace region with rectangle or element on kill ring
-  (define-key cua-global-keymap [remap yank]           'cua-paste)
-  (define-key cua-global-keymap [remap clipboard-yank] 'cua-paste)
-  (define-key cua-global-keymap [remap x-clipboard-yank] 'cua-paste)
+  (define-key cua-global-keymap [remap yank]            #'cua-paste)
+  (define-key cua-global-keymap [remap clipboard-yank]  #'cua-paste)
+  (define-key cua-global-keymap [remap x-clipboard-yank] #'cua-paste)
   ;; replace current yank with previous kill ring element
-  (define-key cua-global-keymap [remap yank-pop]               'cua-paste-pop)
+  (define-key cua-global-keymap [remap yank-pop]              #'cua-paste-pop)
   ;; set mark
-  (define-key cua-global-keymap [remap set-mark-command]       'cua-set-mark)
-  (define-key cua-global-keymap [remap exchange-point-and-mark] 
'cua-exchange-point-and-mark)
+  (define-key cua-global-keymap [remap set-mark-command]       #'cua-set-mark)
+  (define-key cua-global-keymap [remap exchange-point-and-mark]
+    #'cua-exchange-point-and-mark)
 
   ;; scrolling
-  (define-key cua-global-keymap [remap scroll-up]      'cua-scroll-up)
-  (define-key cua-global-keymap [remap scroll-down]    'cua-scroll-down)
-  (define-key cua-global-keymap [remap scroll-up-command]   'cua-scroll-up)
-  (define-key cua-global-keymap [remap scroll-down-command] 'cua-scroll-down)
+  (define-key cua-global-keymap [remap scroll-up]      #'cua-scroll-up)
+  (define-key cua-global-keymap [remap scroll-down]    #'cua-scroll-down)
+  (define-key cua-global-keymap [remap scroll-up-command]   #'cua-scroll-up)
+  (define-key cua-global-keymap [remap scroll-down-command] #'cua-scroll-down)
 
-  (define-key cua--cua-keys-keymap [(control x) timeout] 'kill-region)
-  (define-key cua--cua-keys-keymap [(control c) timeout] 'copy-region-as-kill)
+  (define-key cua--cua-keys-keymap [(control x) timeout] #'kill-region)
+  (define-key cua--cua-keys-keymap [(control c) timeout] #'copy-region-as-kill)
   (when cua-remap-control-z
-    (define-key cua--cua-keys-keymap [(control z)] 'undo))
+    (define-key cua--cua-keys-keymap [(control z)] #'undo))
   (when cua-remap-control-v
-    (define-key cua--cua-keys-keymap [(control v)] 'yank)
+    (define-key cua--cua-keys-keymap [(control v)] #'yank)
     (define-key cua--cua-keys-keymap [(meta v)]
-      'delete-selection-repeat-replace-region))
+      #'delete-selection-repeat-replace-region))
 
-  (define-key cua--prefix-override-keymap [(control x)] 
'cua--prefix-override-handler)
-  (define-key cua--prefix-override-keymap [(control c)] 
'cua--prefix-override-handler)
+  (define-key cua--prefix-override-keymap [(control x)]
+    #'cua--prefix-override-handler)
+  (define-key cua--prefix-override-keymap [(control c)]
+    #'cua--prefix-override-handler)
 
-  (define-key cua--prefix-repeat-keymap [(control x) (control x)] 
'cua--prefix-repeat-handler)
-  (define-key cua--prefix-repeat-keymap [(control c) (control c)] 
'cua--prefix-repeat-handler)
+  (define-key cua--prefix-repeat-keymap [(control x) (control x)]
+    #'cua--prefix-repeat-handler)
+  (define-key cua--prefix-repeat-keymap [(control c) (control c)]
+    #'cua--prefix-repeat-handler)
   (dolist (key '(up down left right home end next prior))
-    (define-key cua--prefix-repeat-keymap (vector '(control x) key) 
'cua--prefix-cut-handler)
-    (define-key cua--prefix-repeat-keymap (vector '(control c) key) 
'cua--prefix-copy-handler))
+    (define-key cua--prefix-repeat-keymap (vector '(control x) key)
+      #'cua--prefix-cut-handler)
+    (define-key cua--prefix-repeat-keymap (vector '(control c) key)
+      #'cua--prefix-copy-handler))
 
   ;; Enable shifted fallbacks for C-x and C-c when region is active
-  (define-key cua--region-keymap [(shift control x)] 
'cua--shift-control-x-prefix)
-  (define-key cua--region-keymap [(shift control c)] 
'cua--shift-control-c-prefix)
+  (define-key cua--region-keymap [(shift control x)]
+    #'cua--shift-control-x-prefix)
+  (define-key cua--region-keymap [(shift control c)]
+    #'cua--shift-control-c-prefix)
 
   ;; delete current region
-  (define-key cua--region-keymap [remap delete-backward-char]  
'cua-delete-region)
-  (define-key cua--region-keymap [remap backward-delete-char]  
'cua-delete-region)
-  (define-key cua--region-keymap [remap backward-delete-char-untabify] 
'cua-delete-region)
-  (define-key cua--region-keymap [remap delete-char]           
'cua-delete-region)
-  (define-key cua--region-keymap [remap delete-forward-char]    
'cua-delete-region)
+  (define-key cua--region-keymap [remap delete-backward-char]
+    #'cua-delete-region)
+  (define-key cua--region-keymap [remap backward-delete-char]
+    #'cua-delete-region)
+  (define-key cua--region-keymap [remap backward-delete-char-untabify]
+    #'cua-delete-region)
+  (define-key cua--region-keymap [remap delete-char]
+    #'cua-delete-region)
+  (define-key cua--region-keymap [remap delete-forward-char]
+    #'cua-delete-region)
   ;; kill region
-  (define-key cua--region-keymap [remap kill-region]           'cua-cut-region)
-  (define-key cua--region-keymap [remap clipboard-kill-region] 'cua-cut-region)
+  (define-key cua--region-keymap [remap kill-region]          #'cua-cut-region)
+  (define-key cua--region-keymap [remap clipboard-kill-region] 
#'cua-cut-region)
   ;; copy region
-  (define-key cua--region-keymap [remap copy-region-as-kill]   
'cua-copy-region)
-  (define-key cua--region-keymap [remap kill-ring-save]                
'cua-copy-region)
-  (define-key cua--region-keymap [remap clipboard-kill-ring-save] 
'cua-copy-region)
+  (define-key cua--region-keymap [remap copy-region-as-kill]  
#'cua-copy-region)
+  (define-key cua--region-keymap [remap kill-ring-save]              
#'cua-copy-region)
+  (define-key cua--region-keymap [remap clipboard-kill-ring-save]
+    #'cua-copy-region)
   ;; cancel current region/rectangle
-  (define-key cua--region-keymap [remap keyboard-escape-quit]  'cua-cancel)
-  (define-key cua--region-keymap [remap keyboard-quit]         'cua-cancel)
+  (define-key cua--region-keymap [remap keyboard-escape-quit]  #'cua-cancel)
+  (define-key cua--region-keymap [remap keyboard-quit]         #'cua-cancel)
   )
 
 
@@ -1344,11 +1333,9 @@ You can customize `cua-enable-cua-keys' to completely 
disable the
 CUA bindings, or `cua-prefix-override-inhibit-delay' to change
 the prefix fallback behavior."
   :global t
-  :group 'cua
   :set-after '(cua-enable-modeline-indications
               cua-remap-control-v cua-remap-control-z
               cua-rectangle-mark-key cua-rectangle-modifier-key)
-  :require 'cua-base
   :link '(emacs-commentary-link "cua-base.el")
   (setq mark-even-if-inactive t)
   (setq highlight-nonselected-windows nil)
@@ -1359,15 +1346,15 @@ the prefix fallback behavior."
 
   (if cua-mode
       (progn
-       (add-hook 'pre-command-hook 'cua--pre-command-handler)
-       (add-hook 'post-command-hook 'cua--post-command-handler)
+       (add-hook 'pre-command-hook #'cua--pre-command-handler)
+       (add-hook 'post-command-hook #'cua--post-command-handler)
        (if (and cua-enable-modeline-indications (not (assoc 'cua-mode 
minor-mode-alist)))
            (setq minor-mode-alist (cons '(cua-mode cua--status-string) 
minor-mode-alist)))
        (if cua-enable-cursor-indications
            (cua--update-indications)))
 
-    (remove-hook 'pre-command-hook 'cua--pre-command-handler)
-    (remove-hook 'post-command-hook 'cua--post-command-handler))
+    (remove-hook 'pre-command-hook #'cua--pre-command-handler)
+    (remove-hook 'post-command-hook #'cua--post-command-handler))
 
   (if (not cua-mode)
       (setq emulation-mode-map-alists
diff --git a/lisp/emulation/cua-gmrk.el b/lisp/emulation/cua-gmrk.el
index 6f6b9fc..7014330 100644
--- a/lisp/emulation/cua-gmrk.el
+++ b/lisp/emulation/cua-gmrk.el
@@ -1,4 +1,4 @@
-;;; cua-gmrk.el --- CUA unified global mark support
+;;; cua-gmrk.el --- CUA unified global mark support  -*- lexical-binding: t; 
-*-
 
 ;; Copyright (C) 1997-2021 Free Software Foundation, Inc.
 
@@ -186,7 +186,7 @@ With prefix argument, don't jump to global mark when 
canceling it."
 (defun cua--copy-rectangle-to-global-mark (as-text)
   ;; Copy rectangle to global mark buffer/position.
   (if (cua--global-mark-active)
-      (let ((src-buf (current-buffer))
+      (let (;; (src-buf (current-buffer))
            (text (cua--extract-rectangle)))
        (with-current-buffer (marker-buffer cua--global-mark-marker)
          (goto-char (marker-position cua--global-mark-marker))
@@ -351,29 +351,44 @@ With prefix argument, don't jump to global mark when 
canceling it."
 ;;; Initialization
 
 (defun cua--init-global-mark ()
-  (define-key cua--global-mark-keymap [remap copy-region-as-kill]      
'cua-copy-to-global-mark)
-  (define-key cua--global-mark-keymap [remap kill-ring-save]           
'cua-copy-to-global-mark)
-  (define-key cua--global-mark-keymap [remap kill-region]              
'cua-cut-to-global-mark)
-  (define-key cua--global-mark-keymap [remap yank]                     
'cua-copy-next-to-global-mark)
-
-  (define-key cua--global-mark-keymap [remap keyboard-escape-quit]     
'cua-cancel-global-mark)
-  (define-key cua--global-mark-keymap [remap keyboard-quit]            
'cua-cancel-global-mark)
-
-  (define-key cua--global-mark-keymap [(control ?d)]                   
'cua-cut-next-to-global-mark)
-  (define-key cua--global-mark-keymap [remap delete-backward-char]     
'cua-delete-backward-char-at-global-mark)
-  (define-key cua--global-mark-keymap [remap backward-delete-char]     
'cua-delete-backward-char-at-global-mark)
-  (define-key cua--global-mark-keymap [remap backward-delete-char-untabify] 
'cua-delete-backward-char-at-global-mark)
-  (define-key cua--global-mark-keymap [remap self-insert-command]      
'cua-insert-char-at-global-mark)
+  (define-key cua--global-mark-keymap [remap copy-region-as-kill]
+    #'cua-copy-to-global-mark)
+  (define-key cua--global-mark-keymap [remap kill-ring-save]
+    #'cua-copy-to-global-mark)
+  (define-key cua--global-mark-keymap [remap kill-region]
+    #'cua-cut-to-global-mark)
+  (define-key cua--global-mark-keymap [remap yank]
+    #'cua-copy-next-to-global-mark)
+
+  (define-key cua--global-mark-keymap [remap keyboard-escape-quit]
+    #'cua-cancel-global-mark)
+  (define-key cua--global-mark-keymap [remap keyboard-quit]
+    #'cua-cancel-global-mark)
+
+  (define-key cua--global-mark-keymap [(control ?d)]
+    #'cua-cut-next-to-global-mark)
+  (define-key cua--global-mark-keymap [remap delete-backward-char]
+    #'cua-delete-backward-char-at-global-mark)
+  (define-key cua--global-mark-keymap [remap backward-delete-char]
+    #'cua-delete-backward-char-at-global-mark)
+  (define-key cua--global-mark-keymap [remap backward-delete-char-untabify]
+    #'cua-delete-backward-char-at-global-mark)
+  (define-key cua--global-mark-keymap [remap self-insert-command]
+    #'cua-insert-char-at-global-mark)
 
   ;; Catch self-inserting characters which are "stolen" by other modes
   (define-key cua--global-mark-keymap [t]
     '(menu-item "sic" cua-insert-char-at-global-mark :filter 
cua--self-insert-char-p))
 
-  (define-key cua--global-mark-keymap [remap newline]                  
'cua-insert-newline-at-global-mark)
-  (define-key cua--global-mark-keymap [remap newline-and-indent]       
'cua-insert-newline-at-global-mark)
-  (define-key cua--global-mark-keymap "\r"                             
'cua-insert-newline-at-global-mark)
+  (define-key cua--global-mark-keymap [remap newline]
+    #'cua-insert-newline-at-global-mark)
+  (define-key cua--global-mark-keymap [remap newline-and-indent]
+    #'cua-insert-newline-at-global-mark)
+  (define-key cua--global-mark-keymap "\r"
+    #'cua-insert-newline-at-global-mark)
 
-  (define-key cua--global-mark-keymap "\t"                             
'cua-indent-to-global-mark-column)
+  (define-key cua--global-mark-keymap "\t"
+    #'cua-indent-to-global-mark-column)
 
   (setq cua--global-mark-initialized t))
 
diff --git a/lisp/emulation/cua-rect.el b/lisp/emulation/cua-rect.el
index be2d7c0..0039092 100644
--- a/lisp/emulation/cua-rect.el
+++ b/lisp/emulation/cua-rect.el
@@ -1,4 +1,4 @@
-;;; cua-rect.el --- CUA unified rectangle support
+;;; cua-rect.el --- CUA unified rectangle support  -*- lexical-binding: t; -*-
 
 ;; Copyright (C) 1997-2021 Free Software Foundation, Inc.
 
@@ -46,7 +46,7 @@ A cua-rectangle definition is a vector used for all actions in
 
 TOP is the upper-left corner point.
 
-BOTTOM is the point at the end of line after the the lower-right
+BOTTOM is the point at the end of line after the lower-right
 corner point.
 
 LEFT and RIGHT are column numbers.
@@ -90,7 +90,7 @@ See `cua--rectangle'.")
 
 (defvar cua--overlay-keymap
   (let ((map (make-sparse-keymap)))
-    (define-key map "\r" 'cua-rotate-rectangle)))
+    (define-key map "\r" #'cua-rotate-rectangle)))
 
 (defvar cua--virtual-edges-debug nil)
 
@@ -104,7 +104,7 @@ See `cua--rectangle'.")
          (e (cua--rect-end-position)))
       (undo-boundary)
       (push (list 'apply 0 s e
-                 'cua--rect-undo-handler
+                 #'cua--rect-undo-handler
                  (copy-sequence cua--rectangle) t s e)
             buffer-undo-list))))
 
@@ -114,7 +114,7 @@ See `cua--rectangle'.")
     (setq cua--restored-rectangle (copy-sequence rect))
     (setq cua--buffer-and-point-before-command nil))
   (push (list 'apply 0 s (if on e s)
-             'cua--rect-undo-handler rect on s e)
+             #'cua--rect-undo-handler rect on s e)
        buffer-undo-list))
 
 ;;;###autoload
@@ -575,6 +575,7 @@ Set undo boundary if UNDO is non-nil.
 Rectangle is padded if PAD = t or numeric and (cua--rectangle-virtual-edges)
 Perform auto-tabify after operation if TABIFY is non-nil.
 Mark is kept if keep-clear is 'keep and cleared if keep-clear is 'clear."
+  (declare (indent 4))
   (let* ((inhibit-field-text-motion t)
         (start (cua--rectangle-top))
          (end   (cua--rectangle-bot))
@@ -645,8 +646,6 @@ Mark is kept if keep-clear is 'keep and cleared if 
keep-clear is 'clear."
       (cua--keep-active)))
     (setq cua--buffer-and-point-before-command nil)))
 
-(put 'cua--rectangle-operation 'lisp-indent-function 4)
-
 (defun cua--delete-rectangle ()
   (let ((lines 0))
     (if (not (cua--rectangle-virtual-edges))
@@ -1220,6 +1219,7 @@ The numbers are formatted according to the FORMAT string."
 ;;; Replace/rearrange text in current rectangle
 
 (defun cua--rectangle-aux-replace (width adjust keep replace pad format-fct 
&optional setup-fct)
+  (declare (indent 4))
   ;; Process text inserted by calling SETUP-FCT or current rectangle if nil.
   ;; Then call FORMAT-FCT on text (if non-nil); takes two args: start and end.
   ;; Fill to WIDTH characters if > 0 or fill to current width if == 0.
@@ -1279,8 +1279,6 @@ The numbers are formatted according to the FORMAT string."
       (if keep
           (cua--rectangle-resized)))))
 
-(put 'cua--rectangle-aux-replace 'lisp-indent-function 4)
-
 (defun cua--left-fill-rectangle (_start _end)
   (beginning-of-line)
   (while (< (point) (point-max))
@@ -1485,79 +1483,79 @@ With prefix arg, indent to that column."
   (cua--M/H-key cua--rectangle-keymap key cmd))
 
 (defun cua--init-rectangles ()
-  (define-key cua--rectangle-keymap cua-rectangle-mark-key 
'cua-clear-rectangle-mark)
-  (define-key cua--region-keymap    cua-rectangle-mark-key 
'cua-toggle-rectangle-mark)
+  (define-key cua--rectangle-keymap cua-rectangle-mark-key 
#'cua-clear-rectangle-mark)
+  (define-key cua--region-keymap    cua-rectangle-mark-key 
#'cua-toggle-rectangle-mark)
   (unless (eq cua--rectangle-modifier-key 'meta)
-    (cua--rect-M/H-key ?\s                            
'cua-clear-rectangle-mark)
-    (cua--M/H-key cua--region-keymap ?\s              
'cua-toggle-rectangle-mark))
-
-  (define-key cua--rectangle-keymap [remap set-mark-command]    
'cua-toggle-rectangle-mark)
-
-  (define-key cua--rectangle-keymap [remap forward-char]        
'cua-resize-rectangle-right)
-  (define-key cua--rectangle-keymap [remap right-char]          
'cua-resize-rectangle-right)
-  (define-key cua--rectangle-keymap [remap backward-char]       
'cua-resize-rectangle-left)
-  (define-key cua--rectangle-keymap [remap left-char]           
'cua-resize-rectangle-left)
-  (define-key cua--rectangle-keymap [remap next-line]           
'cua-resize-rectangle-down)
-  (define-key cua--rectangle-keymap [remap previous-line]       
'cua-resize-rectangle-up)
-  (define-key cua--rectangle-keymap [remap end-of-line]         
'cua-resize-rectangle-eol)
-  (define-key cua--rectangle-keymap [remap beginning-of-line]   
'cua-resize-rectangle-bol)
-  (define-key cua--rectangle-keymap [remap end-of-buffer]       
'cua-resize-rectangle-bot)
-  (define-key cua--rectangle-keymap [remap beginning-of-buffer] 
'cua-resize-rectangle-top)
-  (define-key cua--rectangle-keymap [remap scroll-down]         
'cua-resize-rectangle-page-up)
-  (define-key cua--rectangle-keymap [remap scroll-up]           
'cua-resize-rectangle-page-down)
-  (define-key cua--rectangle-keymap [remap scroll-down-command] 
'cua-resize-rectangle-page-up)
-  (define-key cua--rectangle-keymap [remap scroll-up-command]   
'cua-resize-rectangle-page-down)
-
-  (define-key cua--rectangle-keymap [remap delete-backward-char] 
'cua-delete-char-rectangle)
-  (define-key cua--rectangle-keymap [remap backward-delete-char] 
'cua-delete-char-rectangle)
-  (define-key cua--rectangle-keymap [remap backward-delete-char-untabify] 
'cua-delete-char-rectangle)
-  (define-key cua--rectangle-keymap [remap self-insert-command]         
'cua-insert-char-rectangle)
+    (cua--rect-M/H-key ?\s                            
#'cua-clear-rectangle-mark)
+    (cua--M/H-key cua--region-keymap ?\s              
#'cua-toggle-rectangle-mark))
+
+  (define-key cua--rectangle-keymap [remap set-mark-command]    
#'cua-toggle-rectangle-mark)
+
+  (define-key cua--rectangle-keymap [remap forward-char]        
#'cua-resize-rectangle-right)
+  (define-key cua--rectangle-keymap [remap right-char]          
#'cua-resize-rectangle-right)
+  (define-key cua--rectangle-keymap [remap backward-char]       
#'cua-resize-rectangle-left)
+  (define-key cua--rectangle-keymap [remap left-char]           
#'cua-resize-rectangle-left)
+  (define-key cua--rectangle-keymap [remap next-line]           
#'cua-resize-rectangle-down)
+  (define-key cua--rectangle-keymap [remap previous-line]       
#'cua-resize-rectangle-up)
+  (define-key cua--rectangle-keymap [remap end-of-line]         
#'cua-resize-rectangle-eol)
+  (define-key cua--rectangle-keymap [remap beginning-of-line]   
#'cua-resize-rectangle-bol)
+  (define-key cua--rectangle-keymap [remap end-of-buffer]       
#'cua-resize-rectangle-bot)
+  (define-key cua--rectangle-keymap [remap beginning-of-buffer] 
#'cua-resize-rectangle-top)
+  (define-key cua--rectangle-keymap [remap scroll-down]         
#'cua-resize-rectangle-page-up)
+  (define-key cua--rectangle-keymap [remap scroll-up]           
#'cua-resize-rectangle-page-down)
+  (define-key cua--rectangle-keymap [remap scroll-down-command] 
#'cua-resize-rectangle-page-up)
+  (define-key cua--rectangle-keymap [remap scroll-up-command]   
#'cua-resize-rectangle-page-down)
+
+  (define-key cua--rectangle-keymap [remap delete-backward-char] 
#'cua-delete-char-rectangle)
+  (define-key cua--rectangle-keymap [remap backward-delete-char] 
#'cua-delete-char-rectangle)
+  (define-key cua--rectangle-keymap [remap backward-delete-char-untabify] 
#'cua-delete-char-rectangle)
+  (define-key cua--rectangle-keymap [remap self-insert-command]         
#'cua-insert-char-rectangle)
 
   ;; Catch self-inserting characters which are "stolen" by other modes
   (define-key cua--rectangle-keymap [t]
     '(menu-item "sic" cua-insert-char-rectangle :filter 
cua--self-insert-char-p))
 
-  (define-key cua--rectangle-keymap "\r"     'cua-rotate-rectangle)
-  (define-key cua--rectangle-keymap "\t"     'cua-indent-rectangle)
-
-  (define-key cua--rectangle-keymap [(control ??)] 'cua-help-for-rectangle)
-
-  (define-key cua--rectangle-keymap [mouse-1]     
'cua-mouse-set-rectangle-mark)
-  (define-key cua--rectangle-keymap [down-mouse-1] 'cua--mouse-ignore)
-  (define-key cua--rectangle-keymap [drag-mouse-1] 'cua--mouse-ignore)
-  (define-key cua--rectangle-keymap [mouse-3]     
'cua-mouse-save-then-kill-rectangle)
-  (define-key cua--rectangle-keymap [down-mouse-3] 'cua--mouse-ignore)
-  (define-key cua--rectangle-keymap [drag-mouse-3] 'cua--mouse-ignore)
-
-  (cua--rect-M/H-key 'up    'cua-move-rectangle-up)
-  (cua--rect-M/H-key 'down  'cua-move-rectangle-down)
-  (cua--rect-M/H-key 'left  'cua-move-rectangle-left)
-  (cua--rect-M/H-key 'right 'cua-move-rectangle-right)
-
-  (cua--rect-M/H-key '(control up)   'cua-scroll-rectangle-up)
-  (cua--rect-M/H-key '(control down) 'cua-scroll-rectangle-down)
-
-  (cua--rect-M/H-key ?a        'cua-align-rectangle)
-  (cua--rect-M/H-key ?b        'cua-blank-rectangle)
-  (cua--rect-M/H-key ?c        'cua-close-rectangle)
-  (cua--rect-M/H-key ?f        'cua-fill-char-rectangle)
-  (cua--rect-M/H-key ?i        'cua-incr-rectangle)
-  (cua--rect-M/H-key ?k        'cua-cut-rectangle-as-text)
-  (cua--rect-M/H-key ?l        'cua-downcase-rectangle)
-  (cua--rect-M/H-key ?m        'cua-copy-rectangle-as-text)
-  (cua--rect-M/H-key ?n        'cua-sequence-rectangle)
-  (cua--rect-M/H-key ?o        'cua-open-rectangle)
-  (cua--rect-M/H-key ?p        'cua-toggle-rectangle-virtual-edges)
-  (cua--rect-M/H-key ?P        'cua-do-rectangle-padding)
-  (cua--rect-M/H-key ?q        'cua-refill-rectangle)
-  (cua--rect-M/H-key ?r        'cua-replace-in-rectangle)
-  (cua--rect-M/H-key ?R        'cua-reverse-rectangle)
-  (cua--rect-M/H-key ?s        'cua-string-rectangle)
-  (cua--rect-M/H-key ?t        'cua-text-fill-rectangle)
-  (cua--rect-M/H-key ?u        'cua-upcase-rectangle)
-  (cua--rect-M/H-key ?|        'cua-shell-command-on-rectangle)
-  (cua--rect-M/H-key ?'        'cua-restrict-prefix-rectangle)
-  (cua--rect-M/H-key ?/        'cua-restrict-regexp-rectangle)
+  (define-key cua--rectangle-keymap "\r"     #'cua-rotate-rectangle)
+  (define-key cua--rectangle-keymap "\t"     #'cua-indent-rectangle)
+
+  (define-key cua--rectangle-keymap [(control ??)] #'cua-help-for-rectangle)
+
+  (define-key cua--rectangle-keymap [mouse-1]     
#'cua-mouse-set-rectangle-mark)
+  (define-key cua--rectangle-keymap [down-mouse-1] #'cua--mouse-ignore)
+  (define-key cua--rectangle-keymap [drag-mouse-1] #'cua--mouse-ignore)
+  (define-key cua--rectangle-keymap [mouse-3]     
#'cua-mouse-save-then-kill-rectangle)
+  (define-key cua--rectangle-keymap [down-mouse-3] #'cua--mouse-ignore)
+  (define-key cua--rectangle-keymap [drag-mouse-3] #'cua--mouse-ignore)
+
+  (cua--rect-M/H-key 'up    #'cua-move-rectangle-up)
+  (cua--rect-M/H-key 'down  #'cua-move-rectangle-down)
+  (cua--rect-M/H-key 'left  #'cua-move-rectangle-left)
+  (cua--rect-M/H-key 'right #'cua-move-rectangle-right)
+
+  (cua--rect-M/H-key '(control up)   #'cua-scroll-rectangle-up)
+  (cua--rect-M/H-key '(control down) #'cua-scroll-rectangle-down)
+
+  (cua--rect-M/H-key ?a        #'cua-align-rectangle)
+  (cua--rect-M/H-key ?b        #'cua-blank-rectangle)
+  (cua--rect-M/H-key ?c        #'cua-close-rectangle)
+  (cua--rect-M/H-key ?f        #'cua-fill-char-rectangle)
+  (cua--rect-M/H-key ?i        #'cua-incr-rectangle)
+  (cua--rect-M/H-key ?k        #'cua-cut-rectangle-as-text)
+  (cua--rect-M/H-key ?l        #'cua-downcase-rectangle)
+  (cua--rect-M/H-key ?m        #'cua-copy-rectangle-as-text)
+  (cua--rect-M/H-key ?n        #'cua-sequence-rectangle)
+  (cua--rect-M/H-key ?o        #'cua-open-rectangle)
+  (cua--rect-M/H-key ?p        #'cua-toggle-rectangle-virtual-edges)
+  (cua--rect-M/H-key ?P        #'cua-do-rectangle-padding)
+  (cua--rect-M/H-key ?q        #'cua-refill-rectangle)
+  (cua--rect-M/H-key ?r        #'cua-replace-in-rectangle)
+  (cua--rect-M/H-key ?R        #'cua-reverse-rectangle)
+  (cua--rect-M/H-key ?s        #'cua-string-rectangle)
+  (cua--rect-M/H-key ?t        #'cua-text-fill-rectangle)
+  (cua--rect-M/H-key ?u        #'cua-upcase-rectangle)
+  (cua--rect-M/H-key ?|        #'cua-shell-command-on-rectangle)
+  (cua--rect-M/H-key ?'        #'cua-restrict-prefix-rectangle)
+  (cua--rect-M/H-key ?/        #'cua-restrict-regexp-rectangle)
 
   (setq cua--rectangle-initialized t))
 
diff --git a/lisp/emulation/edt-mapper.el b/lisp/emulation/edt-mapper.el
index 98085c6..0b15278 100644
--- a/lisp/emulation/edt-mapper.el
+++ b/lisp/emulation/edt-mapper.el
@@ -1,4 +1,4 @@
-;;; edt-mapper.el --- create an EDT LK-201 map file for X-Windows Emacs
+;;; edt-mapper.el --- create an EDT LK-201 map file for X-Windows Emacs  -*- 
lexical-binding: t; -*-
 
 ;; Copyright (C) 1994-1995, 2000-2021 Free Software Foundation, Inc.
 
@@ -101,6 +101,8 @@
 (define-obsolete-variable-alias 'edt-window-system 'window-system "27.1")
 
 (defconst edt-xserver (when (eq window-system 'x)
+                        (declare-function x-server-vendor "xfns.c"
+                                          (&optional terminal))
                        ;; The Cygwin window manager has a `/' in its
                        ;; name, which breaks the generated file name of
                        ;; the custom key map file.  Replace `/' with a
@@ -176,7 +178,7 @@
   (mapc
    (lambda (function-key)
      (if (not (lookup-key (current-global-map) function-key))
-        (define-key (current-global-map) function-key 'forward-char)))
+        (define-key (current-global-map) function-key #'forward-char)))
    '([kp-0] [kp-1] [kp-2] [kp-3] [kp-4]
      [kp-5] [kp-6] [kp-7] [kp-8] [kp-9]
      [kp-space]
diff --git a/lisp/emulation/edt.el b/lisp/emulation/edt.el
index 7760a7f..50979c4 100644
--- a/lisp/emulation/edt.el
+++ b/lisp/emulation/edt.el
@@ -1,4 +1,4 @@
-;;; edt.el --- enhanced EDT keypad mode emulation for GNU Emacs
+;;; edt.el --- enhanced EDT keypad mode emulation for GNU Emacs  -*- 
lexical-binding: t; -*-
 
 ;; Copyright (C) 1986, 1992-1995, 2000-2021 Free Software Foundation,
 ;; Inc.
@@ -192,8 +192,7 @@ Emulation.  If set to nil (the default), the 
`page-delimiter' variable
 is set to \"\\f\" when edt-emulation-on is first invoked.  This
 setting replicates EDT's page delimiter behavior.  The original value
 is restored when edt-emulation-off is called."
-  :type 'boolean
-  :group 'edt)
+  :type 'boolean)
 
 (defcustom edt-use-EDT-control-key-bindings nil
   "Emacs MUST be restarted for a change in value to take effect!
@@ -201,8 +200,7 @@ Non-nil causes the control key bindings to be replaced with 
EDT
 bindings.  If set to nil (the default), EDT control key bindings are
 not used and the current Emacs control key bindings are retained for
 use within the EDT emulation."
-  :type 'boolean
-  :group 'edt)
+  :type 'boolean)
 
 (defcustom edt-word-entities '(?\t)
   "Specifies the list of EDT word entity characters.
@@ -226,22 +224,19 @@ representations, which you can also use:
 
 In EDT Emulation movement-by-word commands, each character in the list
 will be treated as if it were a separate word."
-  :type '(repeat integer)
-  :group 'edt)
+  :type '(repeat integer))
 
 (defcustom edt-top-scroll-margin 10
   "Scroll margin at the top of the screen.
 Interpreted as a percent of the current window size with a default
 setting of 10%.  If set to 0, top scroll margin is disabled."
-  :type 'integer
-  :group 'edt)
+  :type 'integer)
 
 (defcustom edt-bottom-scroll-margin 15
   "Scroll margin at the bottom of the screen.
 Interpreted as a percent of the current window size with a default
 setting of 15%.  If set to 0, bottom scroll margin is disabled."
-  :type 'integer
-  :group 'edt)
+  :type 'integer)
 
 ;;;
 ;;; Internal Variables
@@ -304,6 +299,8 @@ This means that an edt-user.el file was found in the user's 
`load-path'.")
 ;;;     o edt-emulation-on      o edt-load-keys
 ;;;
 (defconst edt-xserver (when (eq window-system 'x)
+                        (declare-function x-server-vendor "xfns.c"
+                                          (&optional terminal))
                        ;; The Cygwin window manager has a `/' in its
                        ;; name, which breaks the generated file name of
                        ;; the custom key map file.  Replace `/' with a
@@ -323,31 +320,31 @@ This means that an edt-user.el file was found in the 
user's `load-path'.")
 ;;;; EDT Emulation Commands
 ;;;;
 
-;;; Almost all of EDT's keypad mode commands have equivalent Emacs
-;;; function counterparts.  But many of these counterparts behave
-;;; somewhat differently in Emacs.
-;;;
-;;; So, the following Emacs functions emulate, where practical, the
-;;; exact behavior of the corresponding EDT keypad mode commands.  In
-;;; a few cases, the emulation is not exact, but it should be close
-;;; enough for most EDT die-hards.
-;;;
+;; Almost all of EDT's keypad mode commands have equivalent Emacs
+;; function counterparts.  But many of these counterparts behave
+;; somewhat differently in Emacs.
+;;
+;; So, the following Emacs functions emulate, where practical, the
+;; exact behavior of the corresponding EDT keypad mode commands.  In
+;; a few cases, the emulation is not exact, but it should be close
+;; enough for most EDT die-hards.
+;;
 
 ;;;
 ;;; PAGE
 ;;;
-;;; Emacs uses the regexp assigned to page-delimiter to determine what
-;;; marks a page break.  This is normally "^\f", which causes the
-;;; edt-page command to ignore form feeds not located at the beginning
-;;; of a line.  To emulate the EDT PAGE command exactly,
-;;; page-delimiter is set to "\f" when EDT emulation is turned on, and
-;;; restored to its original value when EDT emulation is turned off.
-;;; But this can be overridden if the EDT definition is not desired by
-;;; placing
-;;;
-;;;         (setq edt-keep-current-page-delimiter t)
-;;;
-;;; in your init file.
+;; Emacs uses the regexp assigned to page-delimiter to determine what
+;; marks a page break.  This is normally "^\f", which causes the
+;; edt-page command to ignore form feeds not located at the beginning
+;; of a line.  To emulate the EDT PAGE command exactly,
+;; page-delimiter is set to "\f" when EDT emulation is turned on, and
+;; restored to its original value when EDT emulation is turned off.
+;; But this can be overridden if the EDT definition is not desired by
+;; placing
+;;
+;;         (setq edt-keep-current-page-delimiter t)
+;;
+;; in your init file.
 
 (defun edt-page-forward (num)
   "Move forward to just after next page delimiter.
@@ -384,12 +381,12 @@ Argument NUM is the number of page delimiters to move."
 ;;;
 ;;; SECT
 ;;;
-;;; EDT defaults a section size to be 16 lines of its one and only
-;;; 24-line window.  That's two-thirds of the window at a time.  The
-;;; EDT SECT commands moves the cursor, not the window.
-;;;
-;;; This emulation of EDT's SECT moves the cursor approximately
-;;; two-thirds of the current window at a time.
+;; EDT defaults a section size to be 16 lines of its one and only
+;; 24-line window.  That's two-thirds of the window at a time.  The
+;; EDT SECT commands moves the cursor, not the window.
+;;
+;; This emulation of EDT's SECT moves the cursor approximately
+;; two-thirds of the current window at a time.
 
 (defun edt-sect-forward (num)
   "Move cursor forward two-thirds of a window's number of lines.
@@ -417,8 +414,8 @@ Argument NUM is the number of sections to move."
 ;;;
 ;;; BEGINNING OF LINE
 ;;;
-;;; EDT's beginning-of-line command is not affected by current
-;;; direction, for some unknown reason.
+;; EDT's beginning-of-line command is not affected by current
+;; direction, for some unknown reason.
 
 (defun edt-beginning-of-line (num)
   "Move backward to next beginning of line mark.
@@ -470,13 +467,13 @@ Argument NUM is the number of EOL marks to move."
 ;;;
 ;;; WORD
 ;;;
-;;; This one is a tad messy.  To emulate EDT's behavior everywhere in
-;;; the file (beginning of file, end of file, beginning of line, end
-;;; of line, etc.) it takes a bit of special handling.
-;;;
-;;; The variable edt-word-entities contains a list of characters which
-;;; are to be viewed as distinct words wherever they appear in the
-;;; buffer.  This emulates the EDT line mode command SET ENTITY WORD.
+;; This one is a tad messy.  To emulate EDT's behavior everywhere in
+;; the file (beginning of file, end of file, beginning of line, end
+;; of line, etc.) it takes a bit of special handling.
+;;
+;; The variable edt-word-entities contains a list of characters which
+;; are to be viewed as distinct words wherever they appear in the
+;; buffer.  This emulates the EDT line mode command SET ENTITY WORD.
 
 
 (defun edt-one-word-forward ()
@@ -567,9 +564,9 @@ Argument NUM is the number of characters to move."
 ;;;
 ;;; LINE
 ;;;
-;;; When direction is set to BACKUP, LINE behaves just like BEGINNING
-;;; OF LINE in EDT.  So edt-line-backward is not really needed as a
-;;; separate function.
+;; When direction is set to BACKUP, LINE behaves just like BEGINNING
+;; OF LINE in EDT.  So edt-line-backward is not really needed as a
+;; separate function.
 
 (defun edt-line-backward (num)
   "Move backward to next beginning of line mark.
@@ -640,8 +637,7 @@ Argument NUM is the number of lines to move."
 
 (defmacro edt-with-position (&rest body)
   "Execute BODY with some position-related variables bound."
-  `(let* ((left nil)
-          (beg (edt-current-line))
+  `(let* ((beg (edt-current-line))
           (height (window-height))
           (top-percent
            (if (zerop edt-top-scroll-margin) 10 edt-top-scroll-margin))
@@ -655,6 +651,7 @@ Argument NUM is the number of lines to move."
           (far (save-excursion
                  (goto-char bottom)
                  (point-at-bol (1- height)))))
+     (ignore top far)
      ,@body))
 
 ;;;
@@ -672,9 +669,10 @@ Optional argument FIND is t is this function is called 
from `edt-find'."
      (search-backward edt-find-last-text)
      (edt-set-match)
      (if (> (point) far)
-         (if (zerop (setq left (save-excursion (forward-line height))))
-             (recenter top-margin)
-           (recenter (- left bottom-up-margin)))
+         (let ((left (save-excursion (forward-line height))))
+           (recenter (if (zerop left)
+                         top-margin
+                       (- left bottom-up-margin))))
        (and (> (point) bottom) (recenter bottom-margin))))))
 
 (defun edt-find-backward (&optional find)
@@ -711,9 +709,9 @@ Optional argument FIND is t if this function is called from 
`edt-find'."
          (search-backward edt-find-last-text)
          (edt-set-match)
          (if (> (point) far)
-             (if (zerop (setq left (save-excursion (forward-line height))))
-                 (recenter top-margin)
-               (recenter (- left bottom-up-margin)))
+             (let ((left (save-excursion (forward-line height))))
+               (recenter (if (zerop left) top-margin
+                           (- left bottom-up-margin))))
            (and (> (point) bottom) (recenter bottom-margin))))
      (backward-char 1)
      (error "Search failed: \"%s\"" edt-find-last-text))))
@@ -1203,9 +1201,9 @@ Argument BOTTOM is the bottom margin in number of lines 
or percent of window."
 ;;;;
 
 ;;;
-;;; Several enhancements and additions to EDT keypad mode commands are
-;;; provided here.  Some of these have been motivated by similar
-;;; TPU/EVE and EVE-Plus commands.  Others are new.
+;; Several enhancements and additions to EDT keypad mode commands are
+;; provided here.  Some of these have been motivated by similar
+;; TPU/EVE and EVE-Plus commands.  Others are new.
 
 ;;;
 ;;; CHANGE DIRECTION
@@ -1245,9 +1243,8 @@ Argument NUM is the positive number of sentences to move."
      (forward-word 1)
      (backward-sentence))
    (if (> (point) far)
-       (if (zerop (setq left (save-excursion (forward-line height))))
-           (recenter top-margin)
-         (recenter (- left bottom-up-margin)))
+       (let ((left (save-excursion (forward-line height))))
+         (recenter (if (zerop left) top-margin (- left bottom-up-margin))))
      (and (> (point) bottom) (recenter bottom-margin)))))
 
 (defun edt-sentence-backward (num)
@@ -1286,9 +1283,8 @@ Argument NUM is the positive number of paragraphs to 
move."
          (forward-line 1))
      (setq num (1- num)))
    (if (> (point) far)
-       (if (zerop (setq left (save-excursion (forward-line height))))
-           (recenter top-margin)
-         (recenter (- left bottom-up-margin)))
+       (let ((left (save-excursion (forward-line height))))
+         (recenter (if (zerop left) top-margin (- left bottom-up-margin))))
      (and (> (point) bottom) (recenter bottom-margin)))))
 
 (defun edt-paragraph-backward (num)
@@ -1378,8 +1374,8 @@ Definition is stored in 
`edt-last-replaced-key-definition'."
 ;;;
 ;;; SCROLL WINDOW
 ;;;
-;;; Scroll a window (less one line) at a time.  Leave cursor in center of
-;;; window.
+;; Scroll a window (less one line) at a time.  Leave cursor in center of
+;; window.
 
 (defun edt-scroll-window-forward (num)
   "Scroll forward one window in buffer, less one line.
@@ -2051,7 +2047,7 @@ Optional argument USER-SETUP non-nil means  called from 
function
       (fset 'edt-emulation-on (symbol-function 'edt-select-default-global-map))
       (edt-select-default-global-map)))
   ;; Keep the menu bar Buffers menu up-to-date in edt-default-global-map.
-  (add-hook 'menu-bar-update-hook 'edt-default-menu-bar-update-buffers))
+  (add-hook 'menu-bar-update-hook #'edt-default-menu-bar-update-buffers))
 
 (defun edt-user-emulation-setup ()
   "Setup user custom emulation of DEC's EDT editor."
@@ -2072,7 +2068,7 @@ Optional argument USER-SETUP non-nil means  called from 
function
       (edt-setup-user-bindings))
   (edt-select-user-global-map)
   ;; Keep the menu bar Buffers menu up-to-date in edt-user-global-map.
-  (add-hook 'menu-bar-update-hook 'edt-user-menu-bar-update-buffers))
+  (add-hook 'menu-bar-update-hook #'edt-user-menu-bar-update-buffers))
 
 (defun edt-select-default-global-map()
   "Select default EDT emulation key bindings."
@@ -2490,7 +2486,7 @@ G-C-\\: Split Window                     |  FNDNXT  |   
Yank   |   CUT    |
                   (and b
                        (with-current-buffer b
                          (set-buffer-modified-p t)))
-                  (fset 'help-print-return-message 'ignore)
+                  (fset 'help-print-return-message #'ignore)
                   (call-interactively fun)
                   (and (get-buffer name)
                        (get-buffer-window (get-buffer name))
diff --git a/lisp/emulation/keypad.el b/lisp/emulation/keypad.el
index e4f3c4d..56202c7 100644
--- a/lisp/emulation/keypad.el
+++ b/lisp/emulation/keypad.el
@@ -1,4 +1,4 @@
-;;; keypad.el --- simplified keypad bindings
+;;; keypad.el --- simplified keypad bindings  -*- lexical-binding: t; -*-
 
 ;; Copyright (C) 2002-2021 Free Software Foundation, Inc.
 
@@ -101,10 +101,10 @@
   "Specifies the keypad setup for unshifted keypad keys when NumLock is off.
 When selecting the plain numeric keypad setup, the character returned by the
 decimal key must be specified."
-  :set (lambda (symbol value)
+  :set (lambda (_symbol value)
         (if value
             (keypad-setup value nil nil value)))
-  :initialize 'custom-initialize-default
+  :initialize #'custom-initialize-default
   :link '(emacs-commentary-link "keypad.el")
   :version "22.1"
   :type '(choice (const :tag "Plain numeric keypad" numeric)
@@ -124,10 +124,10 @@ decimal key must be specified."
   "Specifies the keypad setup for unshifted keypad keys when NumLock is on.
 When selecting the plain numeric keypad setup, the character returned by the
 decimal key must be specified."
-  :set (lambda (symbol value)
+  :set (lambda (_symbol value)
         (if value
             (keypad-setup value t nil value)))
-  :initialize 'custom-initialize-default
+  :initialize #'custom-initialize-default
   :link '(emacs-commentary-link "keypad.el")
   :version "22.1"
   :type '(choice (const :tag "Plain numeric keypad" numeric)
@@ -147,10 +147,10 @@ decimal key must be specified."
   "Specifies the keypad setup for shifted keypad keys when NumLock is off.
 When selecting the plain numeric keypad setup, the character returned by the
 decimal key must be specified."
-  :set (lambda (symbol value)
+  :set (lambda (_symbol value)
         (if value
             (keypad-setup value nil t value)))
-  :initialize 'custom-initialize-default
+  :initialize #'custom-initialize-default
   :link '(emacs-commentary-link "keypad.el")
   :version "22.1"
   :type '(choice (const :tag "Plain numeric keypad" numeric)
@@ -170,10 +170,10 @@ decimal key must be specified."
   "Specifies the keypad setup for shifted keypad keys when NumLock is off.
 When selecting the plain numeric keypad setup, the character returned by the
 decimal key must be specified."
-  :set (lambda (symbol value)
+  :set (lambda (_symbol value)
         (if value
             (keypad-setup value t t value)))
-  :initialize 'custom-initialize-default
+  :initialize #'custom-initialize-default
   :link '(emacs-commentary-link "keypad.el")
   :version "22.1"
   :type '(choice (const :tag "Plain numeric keypad" numeric)
diff --git a/lisp/emulation/viper-cmd.el b/lisp/emulation/viper-cmd.el
index f38be90..728f790 100644
--- a/lisp/emulation/viper-cmd.el
+++ b/lisp/emulation/viper-cmd.el
@@ -24,8 +24,6 @@
 
 ;;; Code:
 
-(provide 'viper-cmd)
-
 ;; Compiler pacifier
 (defvar viper-minibuffer-current-face)
 (defvar viper-minibuffer-insert-face)
@@ -293,15 +291,15 @@
   ;; desirable that viper-pre-command-sentinel is the last hook and
   ;; viper-post-command-sentinel is the first hook.
 
-  (remove-hook 'post-command-hook 'viper-post-command-sentinel)
-  (add-hook 'post-command-hook 'viper-post-command-sentinel)
-  (remove-hook 'pre-command-hook 'viper-pre-command-sentinel)
-  (add-hook 'pre-command-hook 'viper-pre-command-sentinel t)
+  (remove-hook 'post-command-hook #'viper-post-command-sentinel)
+  (add-hook 'post-command-hook #'viper-post-command-sentinel)
+  (remove-hook 'pre-command-hook #'viper-pre-command-sentinel)
+  (add-hook 'pre-command-hook #'viper-pre-command-sentinel t)
   ;; These hooks will be added back if switching to insert/replace mode
   (remove-hook 'viper-post-command-hooks
-              'viper-insert-state-post-command-sentinel 'local)
+              #'viper-insert-state-post-command-sentinel 'local)
   (remove-hook 'viper-pre-command-hooks
-              'viper-insert-state-pre-command-sentinel 'local)
+              #'viper-insert-state-pre-command-sentinel 'local)
   (setq viper-intermediate-command nil)
   (cond ((eq new-state 'vi-state)
         (cond ((member viper-current-state '(insert-state replace-state))
@@ -344,9 +342,9 @@
         (viper-move-marker-locally
          'viper-last-posn-while-in-insert-state (point))
         (add-hook 'viper-post-command-hooks
-                  'viper-insert-state-post-command-sentinel t 'local)
+                  #'viper-insert-state-post-command-sentinel t 'local)
         (add-hook 'viper-pre-command-hooks
-                  'viper-insert-state-pre-command-sentinel t 'local))
+                  #'viper-insert-state-pre-command-sentinel t 'local))
        ) ; outermost cond
 
   ;; Nothing needs to be done to switch to emacs mode! Just set some
@@ -378,12 +376,12 @@
   (cond ((memq state '(insert-state replace-state))
         (if viper-auto-indent
             (progn
-              (define-key viper-insert-basic-map "\C-m" 'viper-autoindent)
+              (define-key viper-insert-basic-map "\C-m" #'viper-autoindent)
               (if viper-want-emacs-keys-in-insert
                   ;; expert
                   (define-key viper-insert-basic-map "\C-j" nil)
                 ;; novice
-                (define-key viper-insert-basic-map "\C-j" 'viper-autoindent)))
+                (define-key viper-insert-basic-map "\C-j" #'viper-autoindent)))
           (define-key viper-insert-basic-map "\C-m" nil)
           (define-key viper-insert-basic-map "\C-j" nil))
 
@@ -392,25 +390,24 @@
 
         (if viper-want-ctl-h-help
             (progn
-              (define-key viper-insert-basic-map "\C-h" 'help-command)
-              (define-key viper-replace-map "\C-h" 'help-command))
+              (define-key viper-insert-basic-map "\C-h" #'help-command)
+              (define-key viper-replace-map "\C-h" #'help-command))
           (define-key viper-insert-basic-map
-            "\C-h" 'viper-del-backward-char-in-insert)
+            "\C-h" #'viper-del-backward-char-in-insert)
           (define-key viper-replace-map
-            "\C-h" 'viper-del-backward-char-in-replace))
+            "\C-h" #'viper-del-backward-char-in-replace))
         ;; In XEmacs, C-h overrides backspace, so we make sure it doesn't.
         (define-key viper-insert-basic-map
-          [backspace] 'viper-del-backward-char-in-insert)
+          [backspace] #'viper-del-backward-char-in-insert)
         (define-key viper-replace-map
-          [backspace] 'viper-del-backward-char-in-replace)
+          [backspace] #'viper-del-backward-char-in-replace)
         ) ; end insert/replace case
        (t ; Vi state
         (setq viper-vi-diehard-minor-mode (not viper-want-emacs-keys-in-vi))
-        (if viper-want-ctl-h-help
-            (define-key viper-vi-basic-map "\C-h" 'help-command)
-          (define-key viper-vi-basic-map "\C-h" 'viper-backward-char))
+        (define-key viper-vi-basic-map "\C-h"
+          (if viper-want-ctl-h-help #'help-command #'viper-backward-char))
         ;; In XEmacs, C-h overrides backspace, so we make sure it doesn't.
-        (define-key viper-vi-basic-map [backspace] 'viper-backward-char))
+        (define-key viper-vi-basic-map [backspace] #'viper-backward-char))
        ))
 
 
@@ -831,7 +828,7 @@ Vi's prefix argument will be used.  Otherwise, the prefix 
argument passed to
 
     (condition-case nil
        (let (viper-vi-kbd-minor-mode) ; execute without kbd macros
-         (setq result (eval form)))
+         (setq result (eval form t)))
       (error
        (signal 'quit nil)))
 
@@ -847,7 +844,7 @@ Similar to `viper-escape-to-emacs', but accepts forms 
rather than keystrokes."
   (let ((buff (current-buffer))
        result)
     (viper-set-mode-vars-for 'emacs-state)
-    (setq result (eval form))
+    (setq result (eval form t))
     (if (not (equal buff (current-buffer))) ; cmd switched buffer
        (with-current-buffer buff
          (viper-set-mode-vars-for viper-current-state)))
@@ -1411,17 +1408,17 @@ as a Meta key and any number of multiple escapes are 
allowed."
 ;; without affecting other functions.  Buffer search can now be bound
 ;; to any character.
 
-(aset viper-exec-array ?c 'viper-exec-change)
-(aset viper-exec-array ?C 'viper-exec-Change)
-(aset viper-exec-array ?d 'viper-exec-delete)
-(aset viper-exec-array ?D 'viper-exec-Delete)
-(aset viper-exec-array ?y 'viper-exec-yank)
-(aset viper-exec-array ?Y 'viper-exec-Yank)
-(aset viper-exec-array ?r 'viper-exec-dummy)
-(aset viper-exec-array ?! 'viper-exec-bang)
-(aset viper-exec-array ?< 'viper-exec-shift)
-(aset viper-exec-array ?> 'viper-exec-shift)
-(aset viper-exec-array ?= 'viper-exec-equals)
+(aset viper-exec-array ?c #'viper-exec-change)
+(aset viper-exec-array ?C #'viper-exec-Change)
+(aset viper-exec-array ?d #'viper-exec-delete)
+(aset viper-exec-array ?D #'viper-exec-Delete)
+(aset viper-exec-array ?y #'viper-exec-yank)
+(aset viper-exec-array ?Y #'viper-exec-Yank)
+(aset viper-exec-array ?r #'viper-exec-dummy)
+(aset viper-exec-array ?! #'viper-exec-bang)
+(aset viper-exec-array ?< #'viper-exec-shift)
+(aset viper-exec-array ?> #'viper-exec-shift)
+(aset viper-exec-array ?= #'viper-exec-equals)
 
 
 
@@ -1560,7 +1557,7 @@ invokes the command before that, etc."
 (defun viper-undo-sentinel (beg end length)
   (run-hook-with-args 'viper-undo-functions beg end length))
 
-(add-hook 'after-change-functions 'viper-undo-sentinel)
+(add-hook 'after-change-functions #'viper-undo-sentinel)
 
 ;; Hook used in viper-undo
 (defun viper-after-change-undo-hook (beg end _len)
@@ -1570,7 +1567,7 @@ invokes the command before that, etc."
     ;; some other hooks may be changing various text properties in
     ;; the buffer in response to 'undo'; so remove this hook to avoid
     ;; its repeated invocation
-    (remove-hook 'viper-undo-functions 'viper-after-change-undo-hook 'local)
+    (remove-hook 'viper-undo-functions #'viper-after-change-undo-hook 'local)
   ))
 
 (defun viper-undo ()
@@ -1581,7 +1578,7 @@ invokes the command before that, etc."
        undo-beg-posn undo-end-posn)
 
     ;; the viper-after-change-undo-hook removes itself after the 1st invocation
-    (add-hook 'viper-undo-functions 'viper-after-change-undo-hook nil 'local)
+    (add-hook 'viper-undo-functions #'viper-after-change-undo-hook nil 'local)
 
     (undo-start)
     (undo-more 2)
@@ -1789,7 +1786,7 @@ Undo previous insertion and inserts new."
        (do-not-change-default t))
     (setq quote-str
          (viper-read-string-with-history
-          "Quote string: "
+          "Quote string"
           nil
           'viper-quote-region-history
            ;; FIXME: Use comment-region.
@@ -1853,8 +1850,8 @@ Undo previous insertion and inserts new."
 ;;; Minibuffer business
 
 (defsubst viper-set-minibuffer-style ()
-  (add-hook 'minibuffer-setup-hook 'viper-minibuffer-setup-sentinel)
-  (add-hook 'post-command-hook 'viper-minibuffer-post-command-hook))
+  (add-hook 'minibuffer-setup-hook #'viper-minibuffer-setup-sentinel)
+  (add-hook 'post-command-hook #'viper-minibuffer-post-command-hook))
 
 
 (defun viper-minibuffer-setup-sentinel ()
@@ -1998,30 +1995,24 @@ problems."
            #'viper-minibuffer-standard-hook
            (if (or (not (listp old)) (eq (car old) 'lambda))
                (list old) old))))
-       (val "")
-       (padding "")
-       temp-msg)
+       (val ""))
 
     (setq keymap (or keymap minibuffer-local-map)
          initial (or initial "")
-         viper-initial initial
-         temp-msg (if default
-                      (format "(default %s) " default)
-                    ""))
+         viper-initial initial)
 
     (setq viper-incomplete-ex-cmd nil)
-    (setq val (read-from-minibuffer prompt
-                                   (concat temp-msg initial val padding)
-                                   keymap nil history-var))
-    (setq minibuffer-setup-hook nil
-         padding (viper-array-to-string (this-command-keys))
-         temp-msg "")
+    (setq val (read-from-minibuffer (format-prompt prompt default)
+                                   nil
+                                   keymap nil history-var default))
+    (setq minibuffer-setup-hook nil)
     ;; the following tries to be smart about what to put in history
-    (if (not (string= val (car (eval history-var))))
-       (set history-var (cons val (eval history-var))))
-    (if (or (string= (nth 0 (eval history-var)) (nth 1 (eval history-var)))
-           (string= (nth 0 (eval history-var)) ""))
-       (set history-var (cdr (eval history-var))))
+    (if (not (string= val (car (symbol-value history-var))))
+       (push val (symbol-value history-var)))
+    (if (or (string= (nth 0 (symbol-value history-var))
+                    (nth 1 (symbol-value history-var)))
+           (string= (nth 0 (symbol-value history-var)) ""))
+       (pop (symbol-value history-var)))
     ;; If the user enters nothing but the prev cmd wasn't viper-ex,
     ;; viper-command-argument, or `! shell-command', this probably means
     ;; that the user typed something then erased.  Return "" in this case, not
@@ -2192,22 +2183,22 @@ problems."
        viper-sitting-in-replace t
        viper-replace-chars-to-delete 0)
   (add-hook
-   'viper-after-change-functions 'viper-replace-mode-spy-after t 'local)
+   'viper-after-change-functions #'viper-replace-mode-spy-after t 'local)
   (add-hook
-   'viper-before-change-functions 'viper-replace-mode-spy-before t 'local)
+   'viper-before-change-functions #'viper-replace-mode-spy-before t 'local)
   ;; this will get added repeatedly, but no harm
-  (add-hook 'after-change-functions 'viper-after-change-sentinel t)
-  (add-hook 'before-change-functions 'viper-before-change-sentinel t)
+  (add-hook 'after-change-functions #'viper-after-change-sentinel t)
+  (add-hook 'before-change-functions #'viper-before-change-sentinel t)
   (viper-move-marker-locally
    'viper-last-posn-in-replace-region (viper-replace-start))
   (add-hook
-   'viper-post-command-hooks 'viper-replace-state-post-command-sentinel
+   'viper-post-command-hooks #'viper-replace-state-post-command-sentinel
    t 'local)
   (add-hook
-   'viper-pre-command-hooks 'viper-replace-state-pre-command-sentinel t 'local)
+   'viper-pre-command-hooks #'viper-replace-state-pre-command-sentinel t 
'local)
   ;; guard against a smarty who switched from R-replace to normal replace
   (remove-hook
-   'viper-post-command-hooks 'viper-R-state-post-command-sentinel 'local)
+   'viper-post-command-hooks #'viper-R-state-post-command-sentinel 'local)
   (if overwrite-mode (overwrite-mode -1))
   )
 
@@ -2281,13 +2272,13 @@ problems."
 ;; Don't delete anything if current point is past the end of the overlay.
 (defun viper-finish-change ()
   (remove-hook
-   'viper-after-change-functions 'viper-replace-mode-spy-after 'local)
+   'viper-after-change-functions #'viper-replace-mode-spy-after 'local)
   (remove-hook
-   'viper-before-change-functions 'viper-replace-mode-spy-before 'local)
+   'viper-before-change-functions #'viper-replace-mode-spy-before 'local)
   (remove-hook
-   'viper-post-command-hooks 'viper-replace-state-post-command-sentinel 'local)
+   'viper-post-command-hooks #'viper-replace-state-post-command-sentinel 
'local)
   (remove-hook
-   'viper-pre-command-hooks 'viper-replace-state-pre-command-sentinel 'local)
+   'viper-pre-command-hooks #'viper-replace-state-pre-command-sentinel 'local)
   (viper-restore-cursor-color 'after-replace-mode)
   (setq viper-sitting-in-replace nil) ; just in case we'll need to know it
   (save-excursion
@@ -2317,21 +2308,21 @@ problems."
 
 (defun viper-finish-R-mode ()
   (remove-hook
-   'viper-post-command-hooks 'viper-R-state-post-command-sentinel 'local)
+   'viper-post-command-hooks #'viper-R-state-post-command-sentinel 'local)
   (remove-hook
-   'viper-pre-command-hooks 'viper-replace-state-pre-command-sentinel 'local)
+   'viper-pre-command-hooks #'viper-replace-state-pre-command-sentinel 'local)
   (viper-downgrade-to-insert))
 
 (defun viper-start-R-mode ()
   ;; Leave arg as 1, not t: XEmacs insists that it must be a pos number
   (overwrite-mode 1)
   (add-hook
-   'viper-post-command-hooks 'viper-R-state-post-command-sentinel t 'local)
+   'viper-post-command-hooks #'viper-R-state-post-command-sentinel t 'local)
   (add-hook
-   'viper-pre-command-hooks 'viper-replace-state-pre-command-sentinel t 'local)
+   'viper-pre-command-hooks #'viper-replace-state-pre-command-sentinel t 
'local)
   ;; guard against a smarty who switched from R-replace to normal replace
   (remove-hook
-   'viper-post-command-hooks 'viper-replace-state-post-command-sentinel 'local)
+   'viper-post-command-hooks #'viper-replace-state-post-command-sentinel 
'local)
   )
 
 
@@ -3467,7 +3458,8 @@ controlled by the sign of prefix numeric value."
            '(viper-command-argument viper-digit-argument viper-repeat))
       (setq viper-this-command-keys (this-command-keys)))
   (let* ((keymap (let ((keymap (copy-keymap minibuffer-local-map)))
-                   (define-key keymap [(control ?s)] 
'viper-insert-isearch-string)
+                   (define-key keymap [(control ?s)]
+                     #'viper-insert-isearch-string)
                    keymap))
          (s (viper-read-string-with-history
            prompt
@@ -3776,8 +3768,8 @@ Null string will repeat previous search."
           (char-to-string viper-buffer-search-char))
          (t (error "viper-buffer-search-char: wrong value type, %S"
                    viper-buffer-search-char)))
-    'viper-command-argument)
-  (aset viper-exec-array viper-buffer-search-char 'viper-exec-buffer-search)
+    #'viper-command-argument)
+  (aset viper-exec-array viper-buffer-search-char #'viper-exec-buffer-search)
   (setq viper-prefix-commands
        (cons viper-buffer-search-char viper-prefix-commands)))
 
@@ -3826,7 +3818,7 @@ Null string will repeat previous search."
   (let (buffer buffer-name)
     (setq buffer-name
          (funcall viper-read-buffer-function
-                  (format "Kill buffer (%s): "
+                  (format-prompt "Kill buffer"
                           (buffer-name (current-buffer)))))
     (setq buffer
          (if (null buffer-name)
@@ -4172,8 +4164,8 @@ and regexp replace."
   (interactive)
   (let (str)
     (setq str (viper-read-string-with-history
-              (if viper-re-query-replace "Query replace regexp: "
-                "Query replace: ")
+              (if viper-re-query-replace "Query replace regexp"
+                "Query replace")
               nil  ; no initial
               'viper-replace1-history
               (car viper-replace1-history) ; default
@@ -4188,7 +4180,7 @@ and regexp replace."
          (query-replace-regexp
           str
           (viper-read-string-with-history
-           (format-message "Query replace regexp `%s' with: " str)
+           (format-message "Query replace regexp `%s' with" str)
            nil  ; no initial
            'viper-replace1-history
            (car viper-replace1-history) ; default
@@ -4196,7 +4188,7 @@ and regexp replace."
        (query-replace
         str
         (viper-read-string-with-history
-         (format-message "Query replace `%s' with: " str)
+         (format-message "Query replace `%s' with" str)
          nil  ; no initial
          'viper-replace1-history
          (car viper-replace1-history) ; default
@@ -4368,7 +4360,7 @@ One can use \\=`\\=` and \\='\\=' to temporarily jump 1 
step back."
 
 ;; Input Mode Indentation
 
-(define-obsolete-function-alias 'viper-looking-back 'looking-back "24.4")
+(define-obsolete-function-alias 'viper-looking-back #'looking-back "24.4")
 
 
 (defun viper-forward-indent ()
@@ -4511,8 +4503,8 @@ One can use \\=`\\=` and \\='\\=' to temporarily jump 1 
step back."
 ;; standard value.  Otherwise, get the value saved in the alist STORAGE.  If
 ;; STORAGE is nil, use viper-saved-user-settings.
 (defun viper-standard-value (symbol &optional storage)
-  (or (eval (car (get symbol 'customized-value)))
-      (eval (car (get symbol 'saved-value)))
+  (or (eval (car (get symbol 'customized-value)) t)
+      (eval (car (get symbol 'saved-value)) t)
       (nth 1 (assoc symbol (or storage viper-saved-user-settings)))))
 
 
@@ -4849,7 +4841,5 @@ Mail anyway (y or n)? ")
           nil 'delete-other-windows
           salutation)))
 
-
-
-
+(provide 'viper-cmd)
 ;;; viper-cmd.el ends here
diff --git a/lisp/emulation/viper-ex.el b/lisp/emulation/viper-ex.el
index 238faed..5b2fa04 100644
--- a/lisp/emulation/viper-ex.el
+++ b/lisp/emulation/viper-ex.el
@@ -1,4 +1,4 @@
-;;; viper-ex.el --- functions implementing the Ex commands for Viper
+;;; viper-ex.el --- functions implementing the Ex commands for Viper  -*- 
lexical-binding: t; -*-
 
 ;; Copyright (C) 1994-1998, 2000-2021 Free Software Foundation, Inc.
 
@@ -24,8 +24,6 @@
 
 ;;; Code:
 
-(provide 'viper-ex)
-
 ;; Compiler pacifier
 (defvar read-file-name-map)
 (defvar viper-use-register)
@@ -190,7 +188,7 @@
 
 ;; Executes the function associated with the command
 (defun ex-cmd-execute (cmd)
-  (eval (cadr cmd)))
+  (eval (cadr cmd) t))
 
 ;; If this is a one-letter magic command, splice in args.
 (defun ex-splice-args-in-1-letr-cmd (key list)
@@ -299,8 +297,7 @@
           "\\)")
          shell-file-name)))
   "Is the user using a unix-type shell under a non-OS?"
-  :type 'boolean
-  :group 'viper-ex)
+  :type 'boolean)
 
 (defcustom ex-unix-type-shell-options
   (let ((case-fold-search t))
@@ -312,13 +309,11 @@
              )))
   "Options to pass to the Unix-style shell.
 Don't put `-c' here, as it is added automatically."
-  :type '(choice (const nil) string)
-  :group 'viper-ex)
+  :type '(choice (const nil) string))
 
 (defcustom ex-compile-command "make"
   "The command to run when the user types :make."
-  :type 'string
-  :group 'viper-ex)
+  :type 'string)
 
 (defcustom viper-glob-function
   (cond (ex-unix-type-shell 'viper-glob-unix-files)
@@ -331,8 +326,7 @@ The default tries to set this variable to work with Unix or 
MS Windows.
 However, if it doesn't work right for some types of Unix shells or some OS,
 the user should supply the appropriate function and set this variable to the
 corresponding function symbol."
-  :type 'symbol
-  :group 'viper-ex)
+  :type 'symbol)
 
 
 ;; Remembers the previous Ex tag.
@@ -363,13 +357,11 @@ corresponding function symbol."
   "If t, :n and :b cycles through files and buffers in other window.
 Then :N and :B cycles in the current window.  If nil, this behavior is
 reversed."
-  :type 'boolean
-  :group 'viper-ex)
+  :type 'boolean)
 
 (defcustom ex-cycle-through-non-files nil
   "Cycle through *scratch* and other buffers that don't visit any file."
-  :type 'boolean
-  :group 'viper-ex)
+  :type 'boolean)
 
 ;; Last shell command executed with :! command.
 (defvar viper-ex-last-shell-com nil)
@@ -1314,7 +1306,7 @@ reversed."
   (let ((nonstandard-filename-chars "[^-a-zA-Z0-9_./,~$\\]"))
     (cond ((file-exists-p filespec) (find-file filespec))
          ((string-match nonstandard-filename-chars  filespec)
-          (mapcar 'find-file (funcall viper-glob-function filespec)))
+          (mapcar #'find-file (funcall viper-glob-function filespec)))
          (t (find-file filespec)))
     ))
 
@@ -1639,7 +1631,7 @@ reversed."
 ;; this function fixes ex-history for some commands like ex-read, ex-edit
 (defun ex-fixup-history (&rest args)
   (setq viper-ex-history
-       (cons (mapconcat 'identity args " ") (cdr viper-ex-history))))
+       (cons (mapconcat #'identity args " ") (cdr viper-ex-history))))
 
 
 ;; Ex recover from emacs \#file\#
@@ -1672,8 +1664,8 @@ reversed."
        (cursor-in-echo-area t)
        str batch)
     (define-key
-      minibuffer-local-completion-map " " 'minibuffer-complete-and-exit)
-    (define-key minibuffer-local-completion-map "=" 'exit-minibuffer)
+      minibuffer-local-completion-map " " #'minibuffer-complete-and-exit)
+    (define-key minibuffer-local-completion-map "=" #'exit-minibuffer)
     (if (viper-set-unread-command-events
         (ex-get-inline-cmd-args "[ \t]*[a-zA-Z]*[ \t]*" nil "\C-m"))
        (progn
@@ -1837,7 +1829,7 @@ reversed."
                     (format "%S" val)
                   val)))
     (if actual-lisp-cmd
-       (eval (car (read-from-string actual-lisp-cmd))))
+       (eval (car (read-from-string actual-lisp-cmd)) t))
     (if (string= var "fill-column")
        (if (> val2 0)
            (auto-fill-mode 1)
@@ -2319,4 +2311,5 @@ Type `mak ' (including the space) to run make with no 
args."
       (with-output-to-temp-buffer " *viper-info*"
        (princ lines))))))
 
+(provide 'viper-ex)
 ;;; viper-ex.el ends here
diff --git a/lisp/emulation/viper-init.el b/lisp/emulation/viper-init.el
index c05cf6a..8188971 100644
--- a/lisp/emulation/viper-init.el
+++ b/lisp/emulation/viper-init.el
@@ -1,4 +1,4 @@
-;;; viper-init.el --- some common definitions for Viper
+;;; viper-init.el --- some common definitions for Viper  -*- lexical-binding: 
t; -*-
 
 ;; Copyright (C) 1997-2021 Free Software Foundation, Inc.
 
@@ -46,7 +46,7 @@
 
 ;; Tell whether we are running as a window application or on a TTY
 
-(define-obsolete-function-alias 'viper-device-type 'window-system "27.1")
+(define-obsolete-function-alias 'viper-device-type #'window-system "27.1")
 
 (defun viper-color-display-p ()
   (condition-case nil
@@ -141,7 +141,7 @@ docstring.  The variable becomes buffer-local whenever set."
   (append (vconcat string) nil))
 
 (defsubst viper-charlist-to-string (list)
-  (mapconcat 'char-to-string list ""))
+  (mapconcat #'char-to-string list ""))
 
 ;; like char-after/before, but saves typing
 (defun viper-char-at-pos (direction &optional offset)
diff --git a/lisp/emulation/viper-keym.el b/lisp/emulation/viper-keym.el
index 1d80c9c..4a9070e 100644
--- a/lisp/emulation/viper-keym.el
+++ b/lisp/emulation/viper-keym.el
@@ -155,29 +155,26 @@ In insert mode, this key also functions as Meta."
         (let ((old-value (if (boundp 'viper-toggle-key)
                              viper-toggle-key
                            [(control ?z)])))
-          (mapc
-           (lambda (buf)
-             (with-current-buffer buf
-               (when (and (boundp 'viper-insert-basic-map)
-                          (keymapp viper-insert-basic-map))
-                 (when old-value
-                   (define-key viper-insert-basic-map old-value nil))
-                 (define-key viper-insert-basic-map value 'viper-escape-to-vi))
-               (when (and (boundp 'viper-vi-intercept-map)
-                          (keymapp viper-vi-intercept-map))
-                 (when old-value
-                   (define-key viper-vi-intercept-map old-value nil))
-                 (define-key
-                   viper-vi-intercept-map value 'viper-toggle-key-action))
-               (when (and (boundp 'viper-emacs-intercept-map)
-                          (keymapp viper-emacs-intercept-map))
-                 (define-key viper-emacs-intercept-map old-value nil)
-                 (define-key
-                   viper-emacs-intercept-map value 'viper-change-state-to-vi))
-               ))
-           (buffer-list))
-          (set-default symbol value)
-           )))
+          (dolist (buf (buffer-list))
+            (with-current-buffer buf
+              (when (and (boundp 'viper-insert-basic-map)
+                         (keymapp viper-insert-basic-map))
+                (when old-value
+                  (define-key viper-insert-basic-map old-value nil))
+                (define-key viper-insert-basic-map value 'viper-escape-to-vi))
+              (when (and (boundp 'viper-vi-intercept-map)
+                         (keymapp viper-vi-intercept-map))
+                (when old-value
+                  (define-key viper-vi-intercept-map old-value nil))
+                (define-key
+                  viper-vi-intercept-map value 'viper-toggle-key-action))
+              (when (and (boundp 'viper-emacs-intercept-map)
+                         (keymapp viper-emacs-intercept-map))
+                (define-key viper-emacs-intercept-map old-value nil)
+                (define-key
+                  viper-emacs-intercept-map value 'viper-change-state-to-vi))
+              ))
+          (set-default symbol value))))
 
 (defcustom viper-quoted-insert-key "\C-v"
   "The key used to quote special characters when inserting them in Insert 
state."
@@ -257,7 +254,7 @@ In insert mode, this key also functions as Meta."
 
 (let ((i ?\ ))
   (while (<= i ?~)
-    (define-key viper-insert-diehard-map (make-string 1 i) 
'self-insert-command)
+    (define-key viper-insert-diehard-map (string i) #'self-insert-command)
     (setq i (1+ i))))
 
 ;; Insert mode map when user wants emacs style
@@ -490,7 +487,7 @@ Useful in some modes, such as Gnus, MH, etc.")
 The effect is seen in the current buffer only.
 Useful for customizing  mailer buffers, gnus, etc.
 STATE is `vi-state', `insert-state', or `emacs-state'.
-ALIST is of the form ((key . func) (key . func) ...)
+ALIST is of the form ((KEY . FUNC) (KEY . FUNC) ...)
 Normally, this would be called from a hook to a major mode or
 on a per buffer basis.
 Usage:
@@ -548,14 +545,11 @@ The above needs not to be done for major modes that come 
up in Vi or Insert
 state by default.
 
 Arguments: (major-mode viper-state keymap)"
-  (let ((alist
-        (cond ((eq state 'vi-state) 'viper-vi-state-modifier-alist)
-              ((eq state 'insert-state) 'viper-insert-state-modifier-alist)
-              ((eq state 'emacs-state) 'viper-emacs-state-modifier-alist)))
-       elt)
-    (if (setq elt (assoc mode (eval alist)))
-       (set alist (delq elt (eval alist))))
-    (set alist (cons (cons mode keymap) (eval alist)))
+  (let* ((alist
+         (cond ((eq state 'vi-state) 'viper-vi-state-modifier-alist)
+               ((eq state 'insert-state) 'viper-insert-state-modifier-alist)
+               ((eq state 'emacs-state) 'viper-emacs-state-modifier-alist))))
+    (setf (alist-get mode (symbol-value alist)) keymap)
 
     ;; Normalization usually doesn't help here, since one needs to
     ;; normalize in the actual buffer where changes to the keymap are
@@ -646,9 +640,9 @@ Arguments: (major-mode viper-state keymap)"
        (cdr mapsrc)))
 
 (defun viper-modify-keymap (map alist)
-   "Modifies MAP with bindings specified in the ALIST.  The alist has the
-form ((key . function) (key . function) ... )."
-   (mapcar (lambda (p) (define-key map (eval (car p)) (cdr p)))
+   "Modifies MAP with bindings specified in the ALIST.
+The ALIST has the form ((KEY . FUNCTION) (KEY . FUNCTION) ... )."
+   (mapcar (lambda (p) (define-key map (eval (car p) t) (cdr p)))
           alist))
 
 
diff --git a/lisp/emulation/viper-macs.el b/lisp/emulation/viper-macs.el
index 039ddab..94ab817 100644
--- a/lisp/emulation/viper-macs.el
+++ b/lisp/emulation/viper-macs.el
@@ -24,8 +24,6 @@
 
 ;;; Code:
 
-(provide 'viper-macs)
-
 ;; compiler pacifier
 (defvar viper-ex-work-buf)
 (defvar viper-custom-file-name)
@@ -37,7 +35,7 @@
 
 (require 'viper-util)
 (require 'viper-keym)
-
+(require 'seq)
 
 ;;; Variables
 
@@ -102,9 +100,11 @@ a key is a symbol, e.g., `a', `\\1', `f2', etc., or a 
list, e.g.,
       ;; if defining macro for insert, switch there for authentic WYSIWYG
       (if ins (viper-change-state-to-insert))
       (start-kbd-macro nil)
-      (define-key viper-vi-intercept-map "\C-x)" 'viper-end-mapping-kbd-macro)
-      (define-key viper-insert-intercept-map "\C-x)" 
'viper-end-mapping-kbd-macro)
-      (define-key viper-emacs-intercept-map "\C-x)" 
'viper-end-mapping-kbd-macro)
+      (define-key viper-vi-intercept-map "\C-x)" #'viper-end-mapping-kbd-macro)
+      (define-key viper-insert-intercept-map "\C-x)"
+        #'viper-end-mapping-kbd-macro)
+      (define-key viper-emacs-intercept-map "\C-x)"
+        #'viper-end-mapping-kbd-macro)
       (message "Mapping %S in %s state.  Type macro definition followed by 
`C-x )'"
               (viper-display-macro macro-name)
               (if ins "Insert" "Vi")))
@@ -442,7 +442,7 @@ If SCOPE is nil, the user is asked to specify the scope."
                       (list nil (list (cons scope nil)) (cons t nil)))
                      ((stringp scope)
                       (list (list (cons scope nil)) nil (cons t nil))))))
-    (setq old-elt (assoc macro-name (eval macro-alist-var)))
+    (setq old-elt (assoc macro-name (symbol-value macro-alist-var)))
 
     (if (null old-elt)
        (progn
@@ -450,8 +450,8 @@ If SCOPE is nil, the user is asked to specify the scope."
          (define-key
            keymap
            (vector (viper-key-to-emacs-key (aref macro-name 0)))
-           'viper-exec-mapped-kbd-macro)
-         (setq lis (eval macro-alist-var))
+           #'viper-exec-mapped-kbd-macro)
+         (setq lis (symbol-value macro-alist-var))
          (while (and lis (string< (viper-array-to-string (car (car lis)))
                                   (viper-array-to-string macro-name)))
            (setq lis2 (cons (car lis) lis2))
@@ -514,7 +514,7 @@ mistakes in macro names to be passed to this function is to 
use
     (if (viper-char-array-p macro-name)
        (setq macro-name (viper-char-array-to-macro macro-name)))
 
-    (setq macro-entry (assoc macro-name (eval macro-alist-var)))
+    (setq macro-entry (assoc macro-name (symbol-value macro-alist-var)))
     (if (= (length macro-name) 0)
        (error "Can't unmap an empty macro name"))
     (if (null macro-entry)
@@ -557,9 +557,10 @@ mistakes in macro names to be passed to this function is 
to use
        (cdr mode-mapping)
        (cdr global-mapping)
        (progn
-         (set macro-alist-var (delq macro-entry (eval macro-alist-var)))
+         (set macro-alist-var (delq macro-entry
+                                    (symbol-value macro-alist-var)))
          (if (viper-can-release-key (aref macro-name 0)
-                                    (eval macro-alist-var))
+                                    (symbol-value macro-alist-var))
              (define-key
                keymap
                (vector (viper-key-to-emacs-key (aref macro-name 0)))
@@ -649,11 +650,11 @@ mistakes in macro names to be passed to this function is 
to use
   (interactive)
   (with-output-to-temp-buffer " *viper-info*"
     (princ "Macros in Vi state:\n===================\n")
-    (mapc 'viper-describe-one-macro viper-vi-kbd-macro-alist)
+    (mapc #'viper-describe-one-macro viper-vi-kbd-macro-alist)
     (princ "\n\nMacros in Insert and Replace 
states:\n====================================\n")
-    (mapc 'viper-describe-one-macro viper-insert-kbd-macro-alist)
+    (mapc #'viper-describe-one-macro viper-insert-kbd-macro-alist)
     (princ "\n\nMacros in Emacs state:\n======================\n")
-    (mapcar 'viper-describe-one-macro viper-emacs-kbd-macro-alist)
+    (mapc #'viper-describe-one-macro viper-emacs-kbd-macro-alist)
     ))
 
 (defun viper-describe-one-macro (macro)
@@ -661,11 +662,11 @@ mistakes in macro names to be passed to this function is 
to use
                 (viper-display-macro (car macro))))
   (princ "   ** Buffer-specific:")
   (if (viper-kbd-buf-alist macro)
-      (mapc 'viper-describe-one-macro-elt (viper-kbd-buf-alist macro))
+      (mapc #'viper-describe-one-macro-elt (viper-kbd-buf-alist macro))
     (princ "  none\n"))
   (princ "\n   ** Mode-specific:")
   (if (viper-kbd-mode-alist macro)
-      (mapc 'viper-describe-one-macro-elt (viper-kbd-mode-alist macro))
+      (mapc #'viper-describe-one-macro-elt (viper-kbd-mode-alist macro))
     (princ "  none\n"))
   (princ "\n   ** Global:")
   (if (viper-kbd-global-definition macro)
@@ -683,10 +684,9 @@ mistakes in macro names to be passed to this function is 
to use
 ;; check if SEQ is a prefix of some car of an element in ALIST
 (defun viper-keyseq-is-a-possible-macro (seq alist)
   (let ((converted-seq (viper-events-to-macro seq)))
-    (eval (cons 'or
-               (mapcar
-                (lambda (elt) (viper-prefix-subseq-p converted-seq elt))
-                (viper-this-buffer-macros alist))))))
+    (seq-some
+     (lambda (elt) (viper-prefix-subseq-p converted-seq elt))
+     (viper-this-buffer-macros alist))))
 
 ;; whether SEQ1 is a prefix of SEQ2
 (defun viper-prefix-subseq-p (seq1 seq2)
@@ -704,11 +704,10 @@ mistakes in macro names to be passed to this function is 
to use
         len)
     (if (= (length seqs) 0)
        (setq len 0)
-      (setq len (apply 'min (mapcar 'length seqs))))
+      (setq len (apply #'min (mapcar #'length seqs))))
     (while (< idx len)
-      (if (eval (cons 'and
-                     (mapcar (lambda (s) (equal (elt first idx) (elt s idx)))
-                             rest)))
+      (if (seq-every-p (lambda (s) (equal (elt first idx) (elt s idx)))
+                      rest)
          (setq pref (vconcat pref (vector (elt first idx)))))
       (setq idx (1+ idx)))
     pref))
@@ -720,7 +719,7 @@ mistakes in macro names to be passed to this function is to 
use
 
 (defun viper-do-sequence-completion (seq alist compl-message)
   (let* ((matches (viper-extract-matching-alist-members seq alist))
-        (new-seq (apply 'viper-common-seq-prefix matches))
+        (new-seq (apply #'viper-common-seq-prefix matches))
         )
     (cond ((and (equal seq new-seq) (= (length matches) 1))
           (message "%s (Sole completion)" compl-message)
@@ -741,8 +740,8 @@ mistakes in macro names to be passed to this function is to 
use
 (defun viper-display-vector-completions (list)
   (with-output-to-temp-buffer "*Completions*"
     (display-completion-list
-     (mapcar 'prin1-to-string
-            (mapcar 'viper-display-macro list)))))
+     (mapcar #'prin1-to-string
+            (mapcar #'viper-display-macro list)))))
 
 
 
@@ -793,9 +792,9 @@ mistakes in macro names to be passed to this function is to 
use
 ;; string--do so.  Otherwise, do nothing.
 (defun viper-display-macro (macro-name-or-body)
   (cond ((viper-char-symbol-sequence-p macro-name-or-body)
-        (mapconcat 'symbol-name macro-name-or-body ""))
+        (mapconcat #'symbol-name macro-name-or-body ""))
        ((viper-char-array-p macro-name-or-body)
-        (mapconcat 'char-to-string macro-name-or-body ""))
+        (mapconcat #'char-to-string macro-name-or-body ""))
        (t macro-name-or-body)))
 
 ;; convert sequence of events (that came presumably from emacs kbd macro) into
@@ -815,7 +814,7 @@ mistakes in macro names to be passed to this function is to 
use
 
 ;; convert strings or arrays of characters to Viper macro form
 (defun viper-char-array-to-macro (array)
-  (vconcat (mapcar 'viper-event-key (vconcat array))))
+  (vconcat (mapcar #'viper-event-key (vconcat array))))
 
 ;; For macros bodies and names, goes over MACRO and checks if all members are
 ;; names of keys (actually, it only checks if they are symbols or lists
@@ -850,7 +849,7 @@ mistakes in macro names to be passed to this function is to 
use
        macro)))
 
 (defun viper-macro-to-events (macro-body)
-  (vconcat (mapcar 'viper-key-to-emacs-key macro-body)))
+  (vconcat (mapcar #'viper-key-to-emacs-key macro-body)))
 
 
 
@@ -929,5 +928,5 @@ mistakes in macro names to be passed to this function is to 
use
     (beginning-of-line)
     (call-last-kbd-macro)))
 
-
+(provide 'viper-macs)
 ;;; viper-macs.el ends here
diff --git a/lisp/emulation/viper-mous.el b/lisp/emulation/viper-mous.el
index 71e40ee..83fc5af 100644
--- a/lisp/emulation/viper-mous.el
+++ b/lisp/emulation/viper-mous.el
@@ -1,4 +1,4 @@
-;;; viper-mous.el --- mouse support for Viper
+;;; viper-mous.el --- mouse support for Viper  -*- lexical-binding: t; -*-
 
 ;; Copyright (C) 1994-1997, 2001-2021 Free Software Foundation, Inc.
 
@@ -24,8 +24,6 @@
 
 ;;; Code:
 
-(provide 'viper-mous)
-
 ;; compiler pacifier
 (defvar double-click-time)
 (defvar mouse-track-multi-click-time)
@@ -60,8 +58,7 @@
 Takes two parameters: a COUNT, indicating how many words to return,
 and CLICK-COUNT, telling whether this is the first click, a double-click,
 or a triple-click."
-  :type 'symbol
-  :group 'viper-mouse)
+  :type 'symbol)
 
 ;; time interval in millisecond within which successive clicks are
 ;; considered related
@@ -70,8 +67,7 @@ or a triple-click."
                                    500)
   "Time interval in millisecond within which successive mouse clicks are
 considered related."
-  :type 'integer
-  :group 'viper-mouse)
+  :type 'integer)
 
 ;; Local variable used to toggle wraparound search on click.
 (defvar-local viper-mouse-click-search-noerror t)
@@ -292,7 +288,7 @@ See `viper-surrounding-word' for the definition of a word 
in this case."
                    (prin1-to-string (viper-event-key event)))))
 
 (define-obsolete-function-alias 'viper-event-click-count
-  'event-click-count "28.1")
+  #'event-click-count "28.1")
 
 (declare-function viper-forward-word "viper-cmd" (arg))
 (declare-function viper-adjust-window "viper-cmd" ())
@@ -407,7 +403,7 @@ this command.
          (setq arg (1- arg)))
        ))))
 
-(defun viper-mouse-catch-frame-switch (event arg)
+(defun viper-mouse-catch-frame-switch (_event arg)
   "Catch the event of switching frame.
 Usually is bound to a `down-mouse' event to work properly.  See sample
 bindings in the Viper manual."
@@ -436,8 +432,9 @@ bindings in the Viper manual."
 ;; until you do something other than viper-mouse-click-* command.
 ;; In XEmacs, you have to manually select frame B (with the mouse click) in
 ;; order to shift focus to frame B.
-(defsubst viper-remember-current-frame (frame)
-  (setq last-command 'handle-switch-frame
+(defun viper-remember-current-frame (&rest _)
+  "Remember the selected frame before the switch-frame event."
+  (setq last-command #'handle-switch-frame
        viper-current-frame-saved (selected-frame)))
 
 
@@ -446,8 +443,8 @@ bindings in the Viper manual."
 ;; Emacs.  EVENT-TYPE is either `up' or `down'.  Up returns button-up key; down
 ;; returns button-down key.
 (defun viper-parse-mouse-key (key-var event-type)
-  (let ((key (eval key-var))
-       button-spec meta-spec shift-spec control-spec key-spec)
+  (let ((key (symbol-value key-var))
+       button-spec meta-spec shift-spec control-spec)
     (if (null key)
        ;; just return nil
        ()
@@ -470,10 +467,9 @@ bindings in the Viper manual."
            control-spec
            (if (memq 'control key) "C-" ""))
 
-      (setq key-spec
-           (vector
-            (intern (concat control-spec meta-spec
-                             shift-spec button-spec)))))))
+      (vector
+       (intern (concat control-spec meta-spec
+                       shift-spec button-spec))))))
 
 (defun viper-unbind-mouse-search-key ()
   (if viper-mouse-up-search-key-parsed
@@ -497,8 +493,8 @@ bindings in the Viper manual."
        (viper-parse-mouse-key 'viper-mouse-search-key 'up)
        viper-mouse-down-search-key-parsed
        (viper-parse-mouse-key 'viper-mouse-search-key 'down))
-  (cond ((or (null viper-mouse-up-search-key-parsed)
-            (null viper-mouse-down-search-key-parsed))
+  (cond ((not (and viper-mouse-up-search-key-parsed
+                  viper-mouse-down-search-key-parsed))
         nil) ; just quit
        ((and (null force)
              (key-binding viper-mouse-up-search-key-parsed)
@@ -516,9 +512,9 @@ bindings in the Viper manual."
          viper-mouse-down-search-key-parsed))
        (t
         (global-set-key viper-mouse-up-search-key-parsed
-                        'viper-mouse-click-search-word)
+                        #'viper-mouse-click-search-word)
         (global-set-key viper-mouse-down-search-key-parsed
-                        'viper-mouse-catch-frame-switch))))
+                        #'viper-mouse-catch-frame-switch))))
 
 ;; If FORCE, bind even if this mouse action is already bound to something else
 (defun viper-bind-mouse-insert-key (&optional force)
@@ -526,8 +522,8 @@ bindings in the Viper manual."
        (viper-parse-mouse-key 'viper-mouse-insert-key 'up)
        viper-mouse-down-insert-key-parsed
        (viper-parse-mouse-key 'viper-mouse-insert-key 'down))
-  (cond ((or (null viper-mouse-up-insert-key-parsed)
-            (null viper-mouse-down-insert-key-parsed))
+  (cond ((not (and viper-mouse-up-insert-key-parsed
+                  viper-mouse-down-insert-key-parsed))
         nil) ; just quit
        ((and (null force)
              (key-binding viper-mouse-up-insert-key-parsed)
@@ -545,9 +541,9 @@ bindings in the Viper manual."
          viper-mouse-down-insert-key-parsed))
        (t
         (global-set-key viper-mouse-up-insert-key-parsed
-                        'viper-mouse-click-insert-word)
+                        #'viper-mouse-click-insert-word)
         (global-set-key viper-mouse-down-insert-key-parsed
-                        'viper-mouse-catch-frame-switch))))
+                        #'viper-mouse-catch-frame-switch))))
 
 (defun viper-reset-mouse-search-key (symb val)
   (viper-unbind-mouse-search-key)
@@ -573,8 +569,7 @@ This buffer may be different from the one where the click 
occurred."
                     (const :format "%v " shift)
                     (const control))
               (integer :tag "Button"))
-  :set 'viper-reset-mouse-search-key
-  :group 'viper-mouse)
+  :set #'viper-reset-mouse-search-key)
 
 (defcustom viper-mouse-insert-key '(meta shift 2)
   "Key used to click-insert in Viper.
@@ -589,7 +584,7 @@ This buffer may be different from the one where the click 
occurred."
                     (const :format "%v " shift)
                     (const control))
               (integer :tag "Button"))
-  :set 'viper-reset-mouse-insert-key
-  :group 'viper-mouse)
+  :set #'viper-reset-mouse-insert-key)
 
+(provide 'viper-mous)
 ;;; viper-mous.el ends here
diff --git a/lisp/emulation/viper-util.el b/lisp/emulation/viper-util.el
index 1bdb155..51f7406 100644
--- a/lisp/emulation/viper-util.el
+++ b/lisp/emulation/viper-util.el
@@ -24,8 +24,7 @@
 
 ;;; Code:
 
-(provide 'viper-util)
-
+(require 'seq)
 
 ;; Compiler pacifier
 (defvar viper-minibuffer-current-face)
@@ -47,22 +46,22 @@
 
 
 
-(define-obsolete-function-alias 'viper-overlay-p 'overlayp "27.1")
-(define-obsolete-function-alias 'viper-make-overlay 'make-overlay "27.1")
-(define-obsolete-function-alias 'viper-overlay-live-p 'overlayp "27.1")
-(define-obsolete-function-alias 'viper-move-overlay 'move-overlay "27.1")
-(define-obsolete-function-alias 'viper-overlay-start 'overlay-start "27.1")
-(define-obsolete-function-alias 'viper-overlay-end 'overlay-end "27.1")
-(define-obsolete-function-alias 'viper-overlay-get 'overlay-get "27.1")
-(define-obsolete-function-alias 'viper-overlay-put 'overlay-put "27.1")
-(define-obsolete-function-alias 'viper-read-event 'read-event "27.1")
-(define-obsolete-function-alias 'viper-characterp 'integerp "27.1")
-(define-obsolete-function-alias 'viper-int-to-char 'identity "27.1")
-(define-obsolete-function-alias 'viper-get-face 'facep "27.1")
+(define-obsolete-function-alias 'viper-overlay-p #'overlayp "27.1")
+(define-obsolete-function-alias 'viper-make-overlay #'make-overlay "27.1")
+(define-obsolete-function-alias 'viper-overlay-live-p #'overlayp "27.1")
+(define-obsolete-function-alias 'viper-move-overlay #'move-overlay "27.1")
+(define-obsolete-function-alias 'viper-overlay-start #'overlay-start "27.1")
+(define-obsolete-function-alias 'viper-overlay-end #'overlay-end "27.1")
+(define-obsolete-function-alias 'viper-overlay-get #'overlay-get "27.1")
+(define-obsolete-function-alias 'viper-overlay-put #'overlay-put "27.1")
+(define-obsolete-function-alias 'viper-read-event #'read-event "27.1")
+(define-obsolete-function-alias 'viper-characterp #'integerp "27.1")
+(define-obsolete-function-alias 'viper-int-to-char #'identity "27.1")
+(define-obsolete-function-alias 'viper-get-face #'facep "27.1")
 (define-obsolete-function-alias 'viper-color-defined-p
-  'x-color-defined-p "27.1")
+  #'x-color-defined-p "27.1")
 (define-obsolete-function-alias 'viper-iconify
-  'iconify-or-deiconify-frame "27.1")
+  #'iconify-or-deiconify-frame "27.1")
 
 
 ;; CHAR is supposed to be a char or an integer (positive or negative)
@@ -269,10 +268,10 @@ Otherwise return the normal value."
 ;; Then, each time this var is used in `viper-move-marker-locally' in a new
 ;; buffer, a new marker will be created.
 (defun viper-move-marker-locally (var pos &optional buffer)
-  (if (markerp (eval var))
+  (if (markerp (symbol-value var))
       ()
     (set var (make-marker)))
-  (move-marker (eval var) pos buffer))
+  (move-marker (symbol-value var) pos buffer))
 
 
 ;; Print CONDITIONS as a message.
@@ -280,7 +279,7 @@ Otherwise return the normal value."
   (let ((case (car conditions)) (msg (cdr conditions)))
     (if (null msg)
        (message "%s" case)
-      (message "%s: %s" case (mapconcat 'prin1-to-string msg " ")))
+      (message "%s: %s" case (mapconcat #'prin1-to-string msg " ")))
     (beep 1)))
 
 
@@ -453,7 +452,7 @@ Otherwise return the normal value."
                                  "$"))
                         tmp2))
        (setq tmp (cdr tmp)))
-      (reverse (apply 'append tmp2)))))
+      (reverse (apply #'append tmp2)))))
 
 
 ;;; Insertion ring
@@ -488,11 +487,11 @@ Otherwise return the normal value."
 
 ;; Push item onto ring.  The second argument is a ring-variable, not value.
 (defun viper-push-onto-ring (item ring-var)
-  (or (ring-p (eval ring-var))
-      (set ring-var (make-ring (eval (intern (format "%S-size" ring-var))))))
+  (or (ring-p (symbol-value ring-var))
+      (set ring-var (make-ring (symbol-value (intern (format "%S-size" 
ring-var))))))
   (or (null item) ; don't push nil
       (and (stringp item) (string= item "")) ; or empty strings
-      (equal item (viper-current-ring-item (eval ring-var))) ; or old stuff
+      (equal item (viper-current-ring-item (symbol-value ring-var))) ; or old 
stuff
       ;; Since viper-set-destructive-command checks if we are inside
       ;; viper-repeat, we don't check whether this-command-keys is a `.'.  The
       ;; cmd viper-repeat makes a call to the current function only if `.' is
@@ -505,7 +504,7 @@ Otherwise return the normal value."
       (and (eq ring-var 'viper-command-ring)
           (string-match "\\([0-9]*\e\\|^[ \t]*$\\|escape\\)"
                         (viper-array-to-string (this-command-keys))))
-      (viper-ring-insert (eval ring-var) item))
+      (viper-ring-insert (symbol-value ring-var) item))
   )
 
 
@@ -595,7 +594,7 @@ Otherwise return the normal value."
 ;; Arguments: var message file &optional erase-message
 (defun viper-save-setting (var message file &optional erase-msg)
   (let* ((var-name (symbol-name var))
-        (var-val (if (boundp var) (eval var)))
+        (var-val (if (boundp var) (symbol-value var)))
         (regexp (format "^[^;]*%s[ \t\n]*[a-zA-Z0-9---_']*[ \t\n)]" var-name))
         (buf (find-file-noselect (substitute-in-file-name file)))
        )
@@ -795,7 +794,7 @@ Otherwise return the normal value."
 ;;; XEmacs compatibility
 
 (define-obsolete-function-alias 'viper-abbreviate-file-name
-  'abbreviate-file-name "27.1")
+  #'abbreviate-file-name "27.1")
 
 (defsubst viper-sit-for-short (val &optional nodisp)
   (declare (obsolete nil "28.1"))
@@ -815,7 +814,7 @@ Otherwise return the normal value."
        (with-current-buffer buf
          (and (<= pos (point-max)) (<= (point-min) pos))))))
 
-(define-obsolete-function-alias 'viper-mark-marker 'mark-marker "27.1")
+(define-obsolete-function-alias 'viper-mark-marker #'mark-marker "27.1")
 
 (defvar viper-saved-mark nil
   "Where viper saves mark.  This mark is resurrected by m^.")
@@ -831,9 +830,9 @@ Otherwise return the normal value."
 ;; highlighted due to Viper's pushing marks.  So, we deactivate marks,
 ;; unless the user explicitly wants highlighting, e.g., by hitting ''
 ;; or ``
-(define-obsolete-function-alias 'viper-deactivate-mark 'deactivate-mark "27.1")
+(define-obsolete-function-alias 'viper-deactivate-mark #'deactivate-mark 
"27.1")
 
-(define-obsolete-function-alias 'viper-leave-region-active 'ignore "27.1")
+(define-obsolete-function-alias 'viper-leave-region-active #'ignore "27.1")
 
 ;; Check if arg is a valid character for register
 ;; TYPE is a list that can contain `letter', `Letter', and `digit'.
@@ -852,7 +851,7 @@ Otherwise return the normal value."
 
 
 
-(define-obsolete-function-alias 'viper-copy-event 'identity "27.1")
+(define-obsolete-function-alias 'viper-copy-event #'identity "27.1")
 
 ;; Uses different timeouts for ESC-sequences and others
 (defun viper-fast-keysequence-p ()
@@ -862,7 +861,7 @@ Otherwise return the normal value."
                t)))
 
 (define-obsolete-function-alias 'viper-read-event-convert-to-char
-  'read-event "27.1")
+  #'read-event "27.1")
 
 
 ;; Emacs has a bug in eventp, which causes (eventp nil) to return (nil)
@@ -941,20 +940,20 @@ Otherwise return the normal value."
                     (car (read-from-string
                           (concat
                            "?\\"
-                           (mapconcat 'identity mod-char-list "-\\")
+                           (mapconcat #'identity mod-char-list "-\\")
                            "-"
                            base-key-name))))
             (setq key-name
                   (intern
                    (concat
-                    (mapconcat 'identity mod-char-list "-")
+                    (mapconcat #'identity mod-char-list "-")
                     "-"
                     base-key-name))))))
     ))
 
 
 ;; LIS is assumed to be a list of events of characters
-(define-obsolete-function-alias 'viper-eventify-list-xemacs 'ignore "27.1")
+(define-obsolete-function-alias 'viper-eventify-list-xemacs #'ignore "27.1")
 
 
 ;; Arg is a character, an event, a list of events or a sequence of
@@ -985,22 +984,20 @@ Otherwise return the normal value."
 ;; XEmacs only
 (defun viper-event-vector-p (vec)
   (and (vectorp vec)
-       (eval (cons 'and (mapcar (lambda (elt) (if (eventp elt) t)) vec)))))
+       (seq-every-p (lambda (elt) (if (eventp elt) t)) vec)))
 
 
 ;; check if vec is a vector of character symbols
 (defun viper-char-symbol-sequence-p (vec)
   (and
    (sequencep vec)
-   (eval
-    (cons 'and
-         (mapcar (lambda (elt)
-                   (and (symbolp elt) (= (length (symbol-name elt)) 1)))
-                 vec)))))
+   (seq-every-p (lambda (elt)
+                 (and (symbolp elt) (= (length (symbol-name elt)) 1)))
+               vec)))
 
 
 (defun viper-char-array-p (array)
-  (eval (cons 'and (mapcar 'characterp array))))
+  (seq-every-p #'characterp array))
 
 
 ;; Args can be a sequence of events, a string, or a Viper macro.  Will try to
@@ -1012,19 +1009,19 @@ Otherwise return the normal value."
   (let (temp temp2)
     (cond ((stringp event-seq) event-seq)
          ((viper-event-vector-p event-seq)
-           (setq temp (mapcar 'viper-event-key event-seq))
+           (setq temp (mapcar #'viper-event-key event-seq))
            (cond ((viper-char-symbol-sequence-p temp)
-                  (mapconcat 'symbol-name temp ""))
+                  (mapconcat #'symbol-name temp ""))
                  ((and (viper-char-array-p
-                        (setq temp2 (mapcar 'viper-key-to-character temp))))
-                  (mapconcat 'char-to-string temp2 ""))
+                        (setq temp2 (mapcar #'viper-key-to-character temp))))
+                  (mapconcat #'char-to-string temp2 ""))
                  (t (prin1-to-string (vconcat temp)))))
          ((viper-char-symbol-sequence-p event-seq)
-          (mapconcat 'symbol-name event-seq ""))
+          (mapconcat #'symbol-name event-seq ""))
          ((and (vectorp event-seq)
                (viper-char-array-p
-                (setq temp (mapcar 'viper-key-to-character event-seq))))
-          (mapconcat 'char-to-string temp ""))
+                (setq temp (mapcar #'viper-key-to-character event-seq))))
+          (mapconcat #'char-to-string temp ""))
          (t (prin1-to-string event-seq)))))
 
 (defun viper-key-press-events-to-chars (events)
@@ -1172,7 +1169,7 @@ syntax tables.
 This option is appropriate if you like Emacs-style words."
   :type '(radio (const strict-vi) (const reformed-vi)
                 (const extended) (const emacs))
-  :set 'viper-set-syntax-preference
+  :set #'viper-set-syntax-preference
   :group 'viper)
 (make-variable-buffer-local 'viper-syntax-preference)
 
@@ -1375,4 +1372,5 @@ This option is appropriate if you like Emacs-style words."
                 (setq i (1+ i) start (1+ start)))
               res))))))
 
+(provide 'viper-util)
 ;;; viper-util.el ends here
diff --git a/lisp/emulation/viper.el b/lisp/emulation/viper.el
index df5a083..cce5117 100644
--- a/lisp/emulation/viper.el
+++ b/lisp/emulation/viper.el
@@ -1061,9 +1061,7 @@ This may be needed if the previous `:map' command 
terminated abnormally."
   (if (viper-window-display-p)
       (viper--advice-add
        'handle-switch-frame :before
-       (lambda (&rest _)
-        "Remember the selected frame before the switch-frame event."
-        (viper-remember-current-frame (selected-frame)))))
+       #'viper-remember-current-frame))
 
   ) ; end viper-non-hook-settings
 
@@ -1191,7 +1189,7 @@ These two lines must come in the order given."))
 
 ;; The default viper-toggle-key is \C-z; for the novice, it suspends or
 ;; iconifies Emacs
-(define-key viper-vi-intercept-map viper-toggle-key 'viper-toggle-key-action)
+(define-key viper-vi-intercept-map viper-toggle-key #'viper-toggle-key-action)
 (define-key
   viper-emacs-intercept-map viper-toggle-key #'viper-change-state-to-vi)
 
diff --git a/lisp/epa.el b/lisp/epa.el
index 572c947..bbfa2c1 100644
--- a/lisp/epa.el
+++ b/lisp/epa.el
@@ -183,8 +183,7 @@ You should bind this variable with `let', but do not set it 
globally.")
 (defvar epa-last-coding-system-specified nil)
 
 (defvar epa-key-list-mode-map
-  (let ((keymap (make-sparse-keymap))
-       (menu-map (make-sparse-keymap)))
+  (let ((keymap (make-sparse-keymap)))
     (define-key keymap "\C-m" 'epa-show-key)
     (define-key keymap [?\t] 'forward-button)
     (define-key keymap [backtab] 'backward-button)
@@ -204,38 +203,32 @@ You should bind this variable with `let', but do not set 
it globally.")
     (define-key keymap [?\S-\ ] 'scroll-down-command)
     (define-key keymap [delete] 'scroll-down-command)
     (define-key keymap "q" 'epa-exit-buffer)
-    (define-key keymap [menu-bar epa-key-list-mode] (cons "Keys" menu-map))
-    (define-key menu-map [epa-key-list-unmark-key]
-      '(menu-item "Unmark Key" epa-unmark-key
-                 :help "Unmark a key"))
-    (define-key menu-map [epa-key-list-mark-key]
-      '(menu-item "Mark Key" epa-mark-key
-                 :help "Mark a key"))
-    (define-key menu-map [separator-epa-file] '(menu-item "--"))
-    (define-key menu-map [epa-verify-file]
-      '(menu-item "Verify File..." epa-verify-file
-                 :help "Verify FILE"))
-    (define-key menu-map [epa-sign-file]
-      '(menu-item "Sign File..." epa-sign-file
-                 :help "Sign FILE by SIGNERS keys selected"))
-    (define-key menu-map [epa-decrypt-file]
-      '(menu-item "Decrypt File..." epa-decrypt-file
-                 :help "Decrypt FILE"))
-    (define-key menu-map [epa-encrypt-file]
-      '(menu-item "Encrypt File..." epa-encrypt-file
-                 :help "Encrypt FILE for RECIPIENTS"))
-    (define-key menu-map [separator-epa-key-list] '(menu-item "--"))
-    (define-key menu-map [epa-key-list-delete-keys]
-      '(menu-item "Delete Keys" epa-delete-keys
-                 :help "Delete Marked Keys"))
-    (define-key menu-map [epa-key-list-import-keys]
-      '(menu-item "Import Keys" epa-import-keys
-                 :help "Import keys from a file"))
-    (define-key menu-map [epa-key-list-export-keys]
-      '(menu-item "Export Keys" epa-export-keys
-                 :help "Export marked keys to a file"))
     keymap))
 
+(easy-menu-define epa-key-list-mode-menu epa-key-list-mode-map
+  "Menu for `epa-key-list-mode'."
+  '("Keys"
+    ["Export Keys" epa-export-keys
+     :help "Export marked keys to a file"]
+    ["Import Keys" epa-import-keys
+     :help "Import keys from a file"]
+    ["Delete Keys" epa-delete-keys
+     :help "Delete Marked Keys"]
+    "---"
+    ["Encrypt File..." epa-encrypt-file
+     :help "Encrypt file for recipients"]
+    ["Decrypt File..." epa-decrypt-file
+     :help "Decrypt file"]
+    ["Sign File..." epa-sign-file
+     :help "Sign file by signers keys selected"]
+    ["Verify File..." epa-verify-file
+     :help "Verify file"]
+    "---"
+    ["Mark Key" epa-mark-key
+     :help "Mark a key"]
+    ["Unmark Key" epa-unmark-key
+     :help "Unmark a key"]))
+
 (defvar epa-key-mode-map
   (let ((keymap (make-sparse-keymap)))
     (define-key keymap "q" 'epa-exit-buffer)
diff --git a/lisp/erc/erc-autoaway.el b/lisp/erc/erc-autoaway.el
index a008566..1a13aa9 100644
--- a/lisp/erc/erc-autoaway.el
+++ b/lisp/erc/erc-autoaway.el
@@ -1,4 +1,4 @@
-;;; erc-autoaway.el --- Provides autoaway for ERC
+;;; erc-autoaway.el --- Provides autoaway for ERC  -*- lexical-binding: t; -*-
 
 ;; Copyright (C) 2002-2004, 2006-2021 Free Software Foundation, Inc.
 
@@ -58,7 +58,7 @@ function each time you change `erc-autoaway-idle-seconds'."
   (setq erc-autoaway-idletimer
        (run-with-idle-timer erc-autoaway-idle-seconds
                             t
-                            'erc-autoaway-set-away
+                            #'erc-autoaway-set-away
                             erc-autoaway-idle-seconds)))
 
 (defun erc-autoaway-some-server-buffer ()
@@ -66,21 +66,21 @@ function each time you change `erc-autoaway-idle-seconds'."
 If none is found, return nil."
   (car (erc-buffer-list #'erc-open-server-buffer-p)))
 
-(defun erc-autoaway-insinuate-maybe (&optional server &rest ignored)
+(defun erc-autoaway-insinuate-maybe (&optional server &rest _ignored)
   "Add autoaway reset function to `post-command-hook' if at least one
 ERC process is alive.
 
 This is used when `erc-autoaway-idle-method' is `user'."
   (when (or server (erc-autoaway-some-server-buffer))
-    (add-hook 'post-command-hook 'erc-autoaway-reset-idle-user)))
+    (add-hook 'post-command-hook #'erc-autoaway-reset-idle-user)))
 
-(defun erc-autoaway-remove-maybe (&rest ignored)
+(defun erc-autoaway-remove-maybe (&rest _ignored)
   "Remove the autoaway reset function from `post-command-hook' if
 no ERC process is alive.
 
 This is used when `erc-autoaway-idle-method' is `user'."
   (unless (erc-autoaway-some-server-buffer)
-    (remove-hook 'post-command-hook 'erc-autoaway-reset-idle-user)))
+    (remove-hook 'post-command-hook #'erc-autoaway-reset-idle-user)))
 
 ;;;###autoload(autoload 'erc-autoaway-mode "erc-autoaway")
 (define-erc-module autoaway nil
@@ -107,36 +107,36 @@ set you no longer away.
 Related variables: `erc-public-away-p' and `erc-away-nickname'."
   ;; Enable:
   ((when (boundp 'erc-autoaway-idle-method)
-     (add-hook 'erc-connect-pre-hook 'erc-autoaway-reset-indicators)
+     (add-hook 'erc-connect-pre-hook #'erc-autoaway-reset-indicators)
      (setq erc-autoaway-last-sent-time (erc-current-time))
      (cond
       ((eq erc-autoaway-idle-method 'irc)
-       (add-hook 'erc-send-completed-hook 'erc-autoaway-reset-idle-irc)
-       (add-hook 'erc-server-001-functions 'erc-autoaway-reset-idle-irc))
+       (add-hook 'erc-send-completed-hook #'erc-autoaway-reset-idle-irc)
+       (add-hook 'erc-server-001-functions #'erc-autoaway-reset-idle-irc))
       ((eq erc-autoaway-idle-method 'user)
-       (add-hook 'erc-after-connect 'erc-autoaway-insinuate-maybe)
-       (add-hook 'erc-disconnected-hook 'erc-autoaway-remove-maybe)
+       (add-hook 'erc-after-connect #'erc-autoaway-insinuate-maybe)
+       (add-hook 'erc-disconnected-hook #'erc-autoaway-remove-maybe)
        (erc-autoaway-insinuate-maybe))
       ((eq erc-autoaway-idle-method 'emacs)
        (erc-autoaway-reestablish-idletimer)))
-     (add-hook 'erc-timer-hook 'erc-autoaway-possibly-set-away)
-     (add-hook 'erc-server-305-functions 'erc-autoaway-reset-indicators)))
+     (add-hook 'erc-timer-hook #'erc-autoaway-possibly-set-away)
+     (add-hook 'erc-server-305-functions #'erc-autoaway-reset-indicators)))
   ;; Disable:
   ((when (boundp 'erc-autoaway-idle-method)
-     (remove-hook 'erc-connect-pre-hook 'erc-autoaway-reset-indicators)
+     (remove-hook 'erc-connect-pre-hook #'erc-autoaway-reset-indicators)
      (cond
       ((eq erc-autoaway-idle-method 'irc)
-       (remove-hook 'erc-send-completed-hook 'erc-autoaway-reset-idle-irc)
-       (remove-hook 'erc-server-001-functions 'erc-autoaway-reset-idle-irc))
+       (remove-hook 'erc-send-completed-hook #'erc-autoaway-reset-idle-irc)
+       (remove-hook 'erc-server-001-functions #'erc-autoaway-reset-idle-irc))
       ((eq erc-autoaway-idle-method 'user)
-       (remove-hook 'post-command-hook 'erc-autoaway-reset-idle-user)
-       (remove-hook 'erc-after-connect 'erc-autoaway-insinuate-maybe)
-       (remove-hook 'erc-disconnected-hook 'erc-autoaway-remove-maybe))
+       (remove-hook 'post-command-hook #'erc-autoaway-reset-idle-user)
+       (remove-hook 'erc-after-connect #'erc-autoaway-insinuate-maybe)
+       (remove-hook 'erc-disconnected-hook #'erc-autoaway-remove-maybe))
       ((eq erc-autoaway-idle-method 'emacs)
        (cancel-timer erc-autoaway-idletimer)
        (setq erc-autoaway-idletimer nil)))
-     (remove-hook 'erc-timer-hook 'erc-autoaway-possibly-set-away)
-     (remove-hook 'erc-server-305-functions 'erc-autoaway-reset-indicators))))
+     (remove-hook 'erc-timer-hook #'erc-autoaway-possibly-set-away)
+     (remove-hook 'erc-server-305-functions #'erc-autoaway-reset-indicators))))
 
 (defcustom erc-autoaway-idle-method 'user
   "The method used to determine how long you have been idle.
@@ -148,7 +148,6 @@ The time itself is specified by `erc-autoaway-idle-seconds'.
 
 See `erc-autoaway-mode' for more information on the various
 definitions of being idle."
-  :group 'erc-autoaway
   :type '(choice (const :tag "User idle time" user)
                 (const :tag "Emacs idle time" emacs)
                 (const :tag "Last IRC action" irc))
@@ -166,7 +165,6 @@ ERC autoaway mode can set you away when you idle, and set 
you no
 longer away when you type something.  This variable controls whether
 you will be set away when you idle.  See `erc-auto-discard-away' for
 the other half."
-  :group 'erc-autoaway
   :type 'boolean)
 
 (defcustom erc-auto-discard-away t
@@ -176,20 +174,17 @@ longer away when you type something.  This variable 
controls whether
 you will be set no longer away when you type something.  See
 `erc-auto-set-away' for the other half.
 See also `erc-autoaway-no-auto-discard-regexp'."
-  :group 'erc-autoaway
   :type 'boolean)
 
 (defcustom erc-autoaway-no-auto-discard-regexp "^/g?away.*$"
   "Input that matches this will not automatically discard away status.
 See `erc-auto-discard-away'."
-  :group 'erc-autoaway
   :type 'regexp)
 
 (defcustom erc-autoaway-idle-seconds 1800
   "Number of seconds after which ERC will set you automatically away.
 If you are changing this variable using lisp instead of customizing it,
 you have to run `erc-autoaway-reestablish-idletimer' afterwards."
-  :group 'erc-autoaway
   :set (lambda (sym val)
         (set-default sym val)
         (when (eq erc-autoaway-idle-method 'emacs)
@@ -201,10 +196,9 @@ you have to run `erc-autoaway-reestablish-idletimer' 
afterwards."
   "Message ERC will use when setting you automatically away.
 It is used as a `format' string with the argument of the idletime
 in seconds."
-  :group 'erc-autoaway
   :type 'string)
 
-(defun erc-autoaway-reset-idle-user (&rest stuff)
+(defun erc-autoaway-reset-idle-user (&rest _stuff)
   "Reset the stored user idle time.
 This is one global variable since a user talking on one net can
 talk on another net too."
@@ -212,7 +206,7 @@ talk on another net too."
     (erc-autoaway-set-back #'erc-autoaway-remove-maybe))
   (setq erc-autoaway-last-sent-time (erc-current-time)))
 
-(defun erc-autoaway-reset-idle-irc (line &rest stuff)
+(defun erc-autoaway-reset-idle-irc (line &rest _stuff)
   "Reset the stored IRC idle time.
 This is one global variable since a user talking on one net can
 talk on another net too."
@@ -272,7 +266,7 @@ active server buffer available."
     (setq erc-autoaway-caused-away t)
     (erc-cmd-GAWAY (format-message erc-autoaway-message idle-time))))
 
-(defun erc-autoaway-reset-indicators (&rest stuff)
+(defun erc-autoaway-reset-indicators (&rest _stuff)
   "Reset indicators used by the erc-autoaway module."
   (setq erc-autoaway-last-sent-time (erc-current-time))
   (setq erc-autoaway-caused-away nil))
diff --git a/lisp/erc/erc-backend.el b/lisp/erc/erc-backend.el
index 4cabd42..b1f97ae 100644
--- a/lisp/erc/erc-backend.el
+++ b/lisp/erc/erc-backend.el
@@ -6,7 +6,7 @@
 ;; Author: Lawrence Mitchell <wence@gmx.li>
 ;; Maintainer: Amin Bandali <bandali@gnu.org>
 ;; Created: 2004-05-7
-;; Keywords: IRC chat client internet
+;; Keywords: comm, IRC, chat, client, internet
 
 ;; This file is part of GNU Emacs.
 
@@ -268,7 +268,6 @@ protection algorithm.")
   "Non-nil means that ERC will attempt to reestablish broken connections.
 
 Reconnection will happen automatically for any unexpected disconnection."
-  :group 'erc-server
   :type 'boolean)
 
 (defcustom erc-server-reconnect-attempts 2
@@ -276,7 +275,6 @@ Reconnection will happen automatically for any unexpected 
disconnection."
 broken connection, or t to always attempt to reconnect.
 
 This only has an effect if `erc-server-auto-reconnect' is non-nil."
-  :group 'erc-server
   :type '(choice (const :tag "Always reconnect" t)
                  integer))
 
@@ -285,7 +283,6 @@ This only has an effect if `erc-server-auto-reconnect' is 
non-nil."
 successive reconnect attempts.
 
 If a key is pressed while ERC is waiting, it will stop waiting."
-  :group 'erc-server
   :type 'number)
 
 (defcustom erc-split-line-length 440
@@ -299,14 +296,12 @@ And a typical message looks like this:
 
 You can limit here the maximum length of the \"Hello!\" part.
 Good luck."
-  :type 'integer
-  :group 'erc-server)
+  :type 'integer)
 
 (defcustom erc-coding-system-precedence '(utf-8 undecided)
   "List of coding systems to be preferred when receiving a string from the 
server.
 This will only be consulted if the coding system in
 `erc-server-coding-system' is `undecided'."
-  :group 'erc-server
   :version "24.1"
   :type '(repeat coding-system))
 
@@ -331,7 +326,6 @@ If you need to send non-ASCII text to people not using a 
client that
 does decoding on its own, you must tell ERC what encoding to use.
 Emacs cannot guess it, since it does not know what the people on the
 other end of the line are using."
-  :group 'erc-server
   :type '(choice (const :tag "None" nil)
                  coding-system
                  (cons (coding-system :tag "encoding" :value utf-8)
@@ -346,37 +340,32 @@ current target as returned by `erc-default-target'.
 Example: If you know that the channel #linux-ru uses the coding-system
 `cyrillic-koi8', then add (\"#linux-ru\" . cyrillic-koi8) to the
 alist."
-  :group 'erc-server
   :type '(repeat (cons (regexp :tag "Target")
                        coding-system)))
 
 (defcustom erc-server-connect-function #'erc-open-network-stream
   "Function used to initiate a connection.
 It should take same arguments as `open-network-stream' does."
-  :group 'erc-server
   :type 'function)
 
 (defcustom erc-server-prevent-duplicates '("301")
   "Either nil or a list of strings.
 Each string is a IRC message type, like PRIVMSG or NOTICE.
 All Message types in that list of subjected to duplicate prevention."
-  :type '(choice (const nil) (list string))
-  :group 'erc-server)
+  :type '(choice (const nil) (list string)))
 
 (defcustom erc-server-duplicate-timeout 60
   "The time allowed in seconds between duplicate messages.
 
 If two identical messages arrive within this value of one another, the second
 isn't displayed."
-  :type 'integer
-  :group 'erc-server)
+  :type 'integer)
 
 (defcustom erc-server-timestamp-format "%Y-%m-%d %T"
   "Timestamp format used with server response messages.
 This string is processed using `format-time-string'."
   :version "24.3"
-  :type 'string
-  :group 'erc-server)
+  :type 'string)
 
 ;;; Flood-related
 
@@ -395,22 +384,19 @@ detailed in RFC 2813, section 5.8 \"Flood control of 
clients\".
     time, send a message, and increase
     `erc-server-flood-last-message' by
     `erc-server-flood-penalty' for each message."
-  :type 'integer
-  :group 'erc-server)
+  :type 'integer)
 
 (defcustom erc-server-flood-penalty 3
   "How much we penalize a message.
 See `erc-server-flood-margin' for an explanation of the flood
 protection algorithm."
-  :type 'integer
-  :group 'erc-server)
+  :type 'integer)
 
 ;; Ping handling
 
 (defcustom erc-server-send-ping-interval 30
   "Interval of sending pings to the server, in seconds.
 If this is set to nil, pinging the server is disabled."
-  :group 'erc-server
   :type '(choice (const :tag "Disabled" nil)
                  (integer :tag "Seconds")))
 
@@ -422,7 +408,6 @@ This must be greater than or equal to the value for
 `erc-server-send-ping-interval'.
 
 If this is set to nil, never try to reconnect."
-  :group 'erc-server
   :type '(choice (const :tag "Disabled" nil)
                  (integer :tag "Seconds")))
 
@@ -1079,14 +1064,9 @@ Finds hooks by looking in the `erc-server-responses' 
hash table."
     (erc-display-message parsed 'notice proc line)))
 
 
-(put 'define-erc-response-handler 'edebug-form-spec
-     '(&define :name erc-response-handler
-               (name &rest name)
-               &optional sexp sexp def-body))
-
 (cl-defmacro define-erc-response-handler ((name &rest aliases)
-                                        &optional extra-fn-doc extra-var-doc
-                                        &rest fn-body)
+                                          &optional extra-fn-doc extra-var-doc
+                                          &rest fn-body)
   "Define an ERC handler hook/function pair.
 NAME is the response name as sent by the server (see the IRC RFC for
 meanings).
@@ -1166,6 +1146,9 @@ Would expand to:
   See also `erc-server-311'.\"))
 
 \(fn (NAME &rest ALIASES) &optional EXTRA-FN-DOC EXTRA-VAR-DOC &rest FN-BODY)"
+  (declare (debug (&define [&name "erc-response-handler@"
+                                  (symbolp &rest symbolp)]
+                           &optional sexp sexp def-body)))
   (if (numberp name) (setq name (intern (format "%03i" name))))
   (setq aliases (mapcar (lambda (a)
                           (if (numberp a)
@@ -1228,8 +1211,8 @@ add things to `%s' instead."
        ,@(cl-loop for fn in fn-alternates
                   for var in var-alternates
                   for a in aliases
-                  nconc (list `(defalias ',fn ',fn-name)
-                              `(defvar ,var ',fn-name ,(format hook-doc a))
+                  nconc (list `(defalias ',fn #',fn-name)
+                              `(defvar ,var #',fn-name ,(format hook-doc a))
                               `(put ',var 'definition-name ',hook-name))))))
 
 (define-erc-response-handler (ERROR)
diff --git a/lisp/erc/erc-button.el b/lisp/erc/erc-button.el
index 71ff408..044776c 100644
--- a/lisp/erc/erc-button.el
+++ b/lisp/erc/erc-button.el
@@ -4,7 +4,7 @@
 
 ;; Author: Mario Lang <mlang@delysid.org>
 ;; Maintainer: Amin Bandali <bandali@gnu.org>
-;; Keywords: irc, button, url, regexp
+;; Keywords: comm, irc, button, url, regexp
 ;; URL: https://www.emacswiki.org/emacs/ErcButton
 
 ;; This file is part of GNU Emacs.
@@ -52,14 +52,14 @@
 ;;;###autoload(autoload 'erc-button-mode "erc-button" nil t)
 (define-erc-module button nil
   "This mode buttonizes all messages according to `erc-button-alist'."
-  ((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-complete-functions 'erc-button-next-function)
-   (add-hook 'erc-mode-hook 'erc-button-setup))
-  ((remove-hook 'erc-insert-modify-hook 'erc-button-add-buttons)
-   (remove-hook 'erc-send-modify-hook 'erc-button-add-buttons)
-   (remove-hook 'erc-complete-functions 'erc-button-next-function)
-   (remove-hook 'erc-mode-hook 'erc-button-setup)))
+  ((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-complete-functions #'erc-button-next-function)
+   (add-hook 'erc-mode-hook #'erc-button-setup))
+  ((remove-hook 'erc-insert-modify-hook #'erc-button-add-buttons)
+   (remove-hook 'erc-send-modify-hook #'erc-button-add-buttons)
+   (remove-hook 'erc-complete-functions #'erc-button-next-function)
+   (remove-hook 'erc-mode-hook #'erc-button-setup)))
 
 ;;; Variables
 
@@ -91,7 +91,6 @@ above them."
 (defcustom erc-button-url-regexp browse-url-button-regexp
   "Regular expression that matches URLs."
   :version "27.1"
-  :group 'erc-button
   :type 'regexp)
 
 (defcustom erc-button-wrap-long-urls nil
@@ -100,28 +99,25 @@ above them."
 If this variable is a number, consider URLs longer than its value to
 be \"long\".  If t, URLs will be considered \"long\" if they are
 longer than `erc-fill-column'."
-  :group 'erc-button
   :type '(choice integer boolean))
 
 (defcustom erc-button-buttonize-nicks t
   "Flag indicating whether nicks should be buttonized or not."
-  :group 'erc-button
   :type 'boolean)
 
-(defcustom erc-button-rfc-url "http://www.faqs.org/rfcs/rfc%s.html";
-  "URL used to browse rfc references.
+(defcustom erc-button-rfc-url "https://tools.ietf.org/html/rfc%s";
+  "URL used to browse RFC references.
 %s is replaced by the number."
-  :group 'erc-button
-  :type 'string)
+  :type 'string
+  :version "28.1")
 
 (define-obsolete-variable-alias 'erc-button-google-url
   'erc-button-search-url "27.1")
 
-(defcustom erc-button-search-url "http://duckduckgo.com/?q=%s";
+(defcustom erc-button-search-url "https://duckduckgo.com/?q=%s";
   "URL used to search for a term.
 %s is replaced by the search string."
-  :version "27.1"
-  :group 'erc-button
+  :version "28.1"
   :type 'string)
 
 (defcustom erc-button-alist
@@ -179,7 +175,6 @@ PAR is a number of a regexp grouping whose text will be 
passed to
   CALLBACK.  There can be several PAR arguments.  If REGEXP is
   \\='nicknames, these are ignored, and CALLBACK will be called with
   the nickname matched as the argument."
-  :group 'erc-button
   :version "24.1"                       ; remove finger (bug#4443)
   :type '(repeat
           (list :tag "Button"
@@ -200,20 +195,18 @@ PAR is a number of a regexp grouping whose text will be 
passed to
 
 (defcustom erc-emacswiki-url "https://www.emacswiki.org/cgi-bin/wiki.pl?";
   "URL of the EmacsWiki Homepage."
-  :group 'erc-button
   :type 'string)
 
 (defcustom erc-emacswiki-lisp-url "https://www.emacswiki.org/elisp/";
   "URL of the EmacsWiki ELisp area."
-  :group 'erc-button
   :type 'string)
 
 (defvar erc-button-keymap
   (let ((map (make-sparse-keymap)))
-    (define-key map (kbd "RET") 'erc-button-press-button)
-    (define-key map (kbd "<mouse-2>") 'erc-button-click-button)
-    (define-key map (kbd "TAB") 'erc-button-next)
-    (define-key map (kbd "<backtab>") 'erc-button-previous)
+    (define-key map (kbd "RET") #'erc-button-press-button)
+    (define-key map (kbd "<mouse-2>") #'erc-button-click-button)
+    (define-key map (kbd "TAB") #'erc-button-next)
+    (define-key map (kbd "<backtab>") #'erc-button-previous)
     (define-key map [follow-link] 'mouse-face)
     (set-keymap-parent map erc-mode-map)
     map)
@@ -244,7 +237,7 @@ global-level ERC button keys yet.")
   "Add ERC mode-level button movement keys.  This is only done once."
   ;; Add keys.
   (unless erc-button-keys-added
-    (define-key erc-mode-map (kbd "<backtab>") 'erc-button-previous)
+    (define-key erc-mode-map (kbd "<backtab>") #'erc-button-previous)
     (setq erc-button-keys-added t)))
 
 (defun erc-button-add-buttons ()
@@ -287,7 +280,7 @@ specified by `erc-button-alist'."
         (fun (nth 3 entry))
         bounds word)
     (when (or (eq t form)
-              (eval form))
+              (eval form t))
       (goto-char (point-min))
       (while (erc-forward-word)
         (when (setq bounds (erc-bounds-of-word-at-point))
@@ -306,9 +299,9 @@ specified by `erc-button-alist'."
           (end (match-end (nth 1 entry)))
           (form (nth 2 entry))
           (fun (nth 3 entry))
-          (data (mapcar 'match-string (nthcdr 4 entry))))
+          (data (mapcar #'match-string (nthcdr 4 entry))))
       (when (or (eq t form)
-                (eval form))
+                (eval form t))
         (erc-button-add-button start end fun nil data regexp)))))
 
 (defun erc-button-remove-old-buttons ()
@@ -483,7 +476,6 @@ Examples:
    (format
     \"ldapsearch -x -P 2 -h db.debian.org -b dc=debian,dc=org ircnick=%s\"
     nick)))"
-  :group 'erc-button
   :type '(repeat (cons (string :tag "Op")
                        sexp)))
 
diff --git a/lisp/erc/erc-capab.el b/lisp/erc/erc-capab.el
index 4e4d012..19bc2db 100644
--- a/lisp/erc/erc-capab.el
+++ b/lisp/erc/erc-capab.el
@@ -1,4 +1,4 @@
-;;; erc-capab.el --- support for dancer-ircd and hyperion's CAPAB
+;;; erc-capab.el --- support for dancer-ircd and hyperion's CAPAB  -*- 
lexical-binding: t; -*-
 
 ;; Copyright (C) 2006-2021 Free Software Foundation, Inc.
 
@@ -40,8 +40,8 @@
 ;; disable this module, it will continue removing message flags, but the
 ;; unidentified nickname prefix will not be added to messages.
 
-;; Visit <http://freenode.net/faq.shtml#spoofing> and
-;; <http://freenode.net/faq.shtml#registering> to find further
+;; Visit <https://freenode.net/kb/answer/cloaks> and
+;; <https://freenode.net/kb/answer/registration> to find further
 ;; explanations of this capability.
 
 ;; From freenode.net's web site (not there anymore) on how to mark
@@ -80,12 +80,10 @@
 
 If you change this from the default \"*\", be sure to use a
 character not found in IRC nicknames to avoid confusion."
-  :group 'erc-capab
   :type '(choice string (const nil)))
 
 (defface erc-capab-identify-unidentified '((t)) ; same as `erc-default-face'
   "Face to use for `erc-capab-identify-prefix'."
-  :group 'erc-capab
   :group 'erc-faces)
 
 ;;; Define module:
@@ -94,22 +92,22 @@ character not found in IRC nicknames to avoid confusion."
 (define-erc-module capab-identify nil
   "Handle dancer-ircd's CAPAB IDENTIFY-MSG and IDENTIFY-CTCP."
   ;; append so that `erc-server-parameters' is already set by `erc-server-005'
-  ((add-hook 'erc-server-005-functions 'erc-capab-identify-setup t)
-   (add-hook 'erc-server-290-functions 'erc-capab-identify-activate)
+  ((add-hook 'erc-server-005-functions #'erc-capab-identify-setup t)
+   (add-hook 'erc-server-290-functions #'erc-capab-identify-activate)
    (add-hook 'erc-server-PRIVMSG-functions
-             'erc-capab-identify-remove/set-identified-flag)
+             #'erc-capab-identify-remove/set-identified-flag)
    (add-hook 'erc-server-NOTICE-functions
-             'erc-capab-identify-remove/set-identified-flag)
-   (add-hook 'erc-insert-modify-hook 'erc-capab-identify-add-prefix t)
+             #'erc-capab-identify-remove/set-identified-flag)
+   (add-hook 'erc-insert-modify-hook #'erc-capab-identify-add-prefix t)
    (mapc (lambda (buffer)
            (when buffer
              (with-current-buffer buffer (erc-capab-identify-setup))))
-         (erc-buffer-list 'erc-open-server-buffer-p)))
-  ((remove-hook 'erc-server-005-functions 'erc-capab-identify-setup)
-   (remove-hook 'erc-server-290-functions 'erc-capab-identify-activate)
+         (erc-buffer-list #'erc-open-server-buffer-p)))
+  ((remove-hook 'erc-server-005-functions #'erc-capab-identify-setup)
+   (remove-hook 'erc-server-290-functions #'erc-capab-identify-activate)
    ;; we don't remove the `erc-capab-identify-remove/set-identified-flag' hooks
    ;; because there doesn't seem to be a way to tell the server to turn it off
-   (remove-hook 'erc-insert-modify-hook 'erc-capab-identify-add-prefix)))
+   (remove-hook 'erc-insert-modify-hook #'erc-capab-identify-add-prefix)))
 
 ;;; Variables:
 
@@ -121,7 +119,7 @@ character not found in IRC nicknames to avoid confusion."
 
 ;;; Functions:
 
-(defun erc-capab-identify-setup (&optional proc parsed)
+(defun erc-capab-identify-setup (&optional _proc _parsed)
   "Set up CAPAB IDENTIFY on the current server.
 
 Optional argument PROC is the current server's process.
@@ -146,19 +144,19 @@ These arguments are sent to this function when called as 
a hook in
     (setq erc-capab-identify-sent t)))
 
 
-(defun erc-capab-identify-activate (proc parsed)
+(defun erc-capab-identify-activate (_proc parsed)
   "Set `erc-capab-identify-activated' and display an activation message.
 
 PROC is the current server's process.
 PARSED is an `erc-parsed' response struct."
-  (when (or (string= "IDENTIFY-MSG" (erc-response.contents parsed))
-            (string= "IDENTIFY-CTCP" (erc-response.contents parsed)))
+  (when (member (erc-response.contents parsed)
+                '("IDENTIFY-MSG" "IDENTIFY-CTCP"))
     (setq erc-capab-identify-activated t)
     (erc-display-message
      parsed 'notice 'active (format "%s activated"
                                     (erc-response.contents parsed)))))
 
-(defun erc-capab-identify-remove/set-identified-flag (proc parsed)
+(defun erc-capab-identify-remove/set-identified-flag (_proc parsed)
   "Remove PARSED message's id flag and add the `erc-identified' text property.
 
 PROC is the current server's process.
diff --git a/lisp/erc/erc-dcc.el b/lisp/erc/erc-dcc.el
index 9dedd3c..234b4b5 100644
--- a/lisp/erc/erc-dcc.el
+++ b/lisp/erc/erc-dcc.el
@@ -1,4 +1,4 @@
-;;; erc-dcc.el --- CTCP DCC module for ERC
+;;; erc-dcc.el --- CTCP DCC module for ERC  -*- lexical-binding: t; -*-
 
 ;; Copyright (C) 1993-1995, 1998, 2002-2004, 2006-2021 Free Software
 ;; Foundation, Inc.
@@ -7,7 +7,7 @@
 ;;         Noah Friedman <friedman@prep.ai.mit.edu>
 ;;         Per Persson <pp@sno.pp.se>
 ;; Maintainer: Amin Bandali <bandali@gnu.org>
-;; Keywords: comm, processes
+;; Keywords: comm
 ;; Created: 1994-01-23
 
 ;; This file is part of GNU Emacs.
@@ -55,12 +55,6 @@
 ;; Require at run-time too to silence compiler.
 (require 'pcomplete)
 
-;;;###autoload(autoload 'erc-dcc-mode "erc-dcc")
-(define-erc-module dcc nil
-  "Provide Direct Client-to-Client support for ERC."
-  ((add-hook 'erc-server-401-functions 'erc-dcc-no-such-nick))
-  ((remove-hook 'erc-server-401-functions 'erc-dcc-no-such-nick)))
-
 (defgroup erc-dcc nil
   "DCC stands for Direct Client Communication, where you and your
 friend's client programs connect directly to each other,
@@ -71,9 +65,14 @@ Using DCC get and send, you can transfer files directly from 
and to other
 IRC users."
   :group 'erc)
 
+;;;###autoload(autoload 'erc-dcc-mode "erc-dcc")
+(define-erc-module dcc nil
+  "Provide Direct Client-to-Client support for ERC."
+  ((add-hook 'erc-server-401-functions #'erc-dcc-no-such-nick))
+  ((remove-hook 'erc-server-401-functions #'erc-dcc-no-such-nick)))
+
 (defcustom erc-dcc-verbose nil
   "If non-nil, be verbose about DCC activity reporting."
-  :group 'erc-dcc
   :type 'boolean)
 
 (defconst erc-dcc-connection-types
@@ -120,7 +119,8 @@ All values of the list must be uppercase strings.")
 ;; more: the entry data from erc-dcc-list for this particular process.
 (defvar erc-dcc-connect-function 'erc-dcc-open-network-stream)
 
-(defun erc-dcc-open-network-stream (procname buffer addr port entry)
+(defun erc-dcc-open-network-stream (procname buffer addr port _entry)
+  ;; FIXME: Time to try activating this again!?
   (if nil;  (fboundp 'open-network-stream-nowait)  ;; this currently crashes
                                                    ;; cvs emacs
       (open-network-stream-nowait procname buffer addr port)
@@ -286,7 +286,6 @@ The result is also a string."
   "IP address to listen on when offering files.
 Should be set to a string or nil.  If nil, automatic detection of
 the host interface to use will be attempted."
-  :group 'erc-dcc
   :type (list 'choice (list 'const :tag "Auto-detect" nil)
               (list 'string :tag "IP-address"
                     :valid-regexp erc-dcc-ipv4-regexp)))
@@ -295,7 +294,6 @@ the host interface to use will be attempted."
   "IP address to use for outgoing DCC offers.
 Should be set to a string or nil.  If nil, use the value of
 `erc-dcc-listen-host'."
-  :group 'erc-dcc
   :type (list 'choice (list 'const :tag "Same as erc-dcc-listen-host" nil)
               (list 'string :tag "IP-address"
                     :valid-regexp erc-dcc-ipv4-regexp)))
@@ -306,7 +304,6 @@ Should be set to a string or nil.  If nil, use the value of
         You might want to set `erc-dcc-auto-masks' for this.
 `auto' - Automatically accept the request and begin downloading the file
 `ignore' - Ignore incoming DCC Send requests completely."
-  :group 'erc-dcc
   :type '(choice (const ask) (const auto) (const ignore)))
 
 (defun erc-dcc-get-host (proc)
@@ -323,7 +320,6 @@ If variable `erc-dcc-host' is non-nil, use it.  Otherwise 
call
 (defcustom erc-dcc-port-range nil
   "If nil, any available user port is used for outgoing DCC connections.
 If set to a cons, it specifies a range of ports to use in the form (min . max)"
-  :group 'erc-dcc
   :type '(choice
           (const :tag "Any port" nil)
           (cons :tag "Port range"
@@ -335,7 +331,6 @@ If set to a cons, it specifies a range of ports to use in 
the form (min . max)"
 accepted automatically.  A user identifier has the form \"nick!login@host\".
 For instance, to accept all incoming DCC send offers automatically, add the
 string \".*!.*@.*\" to this list."
-  :group 'erc-dcc
   :type '(repeat regexp))
 
 (defun erc-dcc-server (name filter sentinel)
@@ -391,7 +386,6 @@ the accepted connection."
 (defcustom erc-dcc-get-default-directory nil
   "Default directory for incoming DCC file transfers.
 If this is nil, then the current value of `default-directory' is used."
-  :group 'erc-dcc
   :type '(choice (const nil :tag "Default directory") directory))
 
 ;;;###autoload
@@ -468,7 +462,7 @@ where FOO is one of CLOSE, GET, SEND, LIST, CHAT, etc."
          'dcc-chat-offer ?n nick)
         t))))
 
-(defun erc-dcc-do-CLOSE-command (proc &optional type nick)
+(defun erc-dcc-do-CLOSE-command (_proc &optional type nick)
   "Close a connection.  Usage: /dcc close type nick.
 At least one of TYPE and NICK must be provided."
   ;; disambiguate type and nick if only one is provided
@@ -540,7 +534,7 @@ PROC is the server process."
 
 (defvar-local erc-dcc-byte-count nil)
 
-(defun erc-dcc-do-LIST-command (proc)
+(defun erc-dcc-do-LIST-command (_proc)
   "This is the handler for the /dcc list command.
 It lists the current state of `erc-dcc-list' in an easy to read manner."
   (let ((alist erc-dcc-list)
@@ -703,7 +697,6 @@ the matching regexp, or nil if none found."
 `ask' - Report the Chat request, and wait for the user to manually accept it
 `auto' - Automatically accept the request and open a new chat window
 `ignore' - Ignore incoming DCC chat requests completely."
-  :group 'erc-dcc
   :type '(choice (const ask) (const auto) (const ignore)))
 
 (defun erc-dcc-handle-ctcp-chat (proc query nick login host to)
@@ -757,13 +750,11 @@ the matching regexp, or nil if none found."
 
 (defcustom erc-dcc-block-size 1024
   "Block size to use for DCC SEND sessions."
-  :group 'erc-dcc
   :type 'integer)
 
 (defcustom erc-dcc-pump-bytes nil
   "If set to an integer, keep sending until that number of bytes are
 unconfirmed."
-  :group 'erc-dcc
   :type '(choice (const nil) integer))
 
 (define-inline erc-dcc-get-parent (proc)
@@ -837,7 +828,6 @@ bytes sent."
   '(erc-dcc-display-send erc-dcc-send-block)
   "Hook run whenever the remote end of a DCC SEND offer connected to your
 listening port."
-  :group 'erc-dcc
   :type 'hook)
 
 (defun erc-dcc-nick (plist)
@@ -900,7 +890,6 @@ other client."
 
 (defcustom erc-dcc-receive-cache (* 1024 512)
   "Number of bytes to let the receive buffer grow before flushing it."
-  :group 'erc-dcc
   :type 'integer)
 
 (defvar-local erc-dcc-file-name nil)
@@ -942,12 +931,12 @@ and making the connection."
       (set-process-coding-system proc 'binary 'binary)
       (set-buffer-file-coding-system 'binary t)
 
-      (set-process-filter proc 'erc-dcc-get-filter)
-      (set-process-sentinel proc 'erc-dcc-get-sentinel)
+      (set-process-filter proc #'erc-dcc-get-filter)
+      (set-process-sentinel proc #'erc-dcc-get-sentinel)
       (setq entry (plist-put entry :start-time (erc-current-time)))
       (setq entry (plist-put entry :peer proc)))))
 
-(defun erc-dcc-append-contents (buffer file)
+(defun erc-dcc-append-contents (buffer _file)
   "Append the contents of BUFFER to FILE.
 The contents of the BUFFER will then be erased."
   (with-current-buffer buffer
@@ -1000,7 +989,7 @@ rather than every 1024 byte block, but nobody seems to 
care."
          proc (erc-pack-int received-bytes)))))))
 
 
-(defun erc-dcc-get-sentinel (proc event)
+(defun erc-dcc-get-sentinel (proc _event)
   "This is the process sentinel for CTCP DCC SEND connections.
 It shuts down the connection and notifies the user that the
 transfer is complete."
@@ -1025,25 +1014,21 @@ transfer is complete."
 
 (defcustom erc-dcc-chat-buffer-name-format "DCC-CHAT-%s"
   "Format to use for DCC Chat buffer names."
-  :group 'erc-dcc
   :type 'string)
 
 (defcustom erc-dcc-chat-mode-hook nil
   "Hook calls when `erc-dcc-chat-mode' finished setting up the buffer."
-  :group 'erc-dcc
   :type 'hook)
 
 (defcustom erc-dcc-chat-connect-hook nil
   ""
-  :group 'erc-dcc
   :type 'hook)
 
 (defcustom erc-dcc-chat-exit-hook nil
   ""
-  :group 'erc-dcc
   :type 'hook)
 
-(defun erc-cmd-CREQ (line &optional force)
+(defun erc-cmd-CREQ (line &optional _force)
   "Set or get the DCC chat request flag.
 Possible values are: ask, auto, ignore."
   (when (string-match "^\\s-*\\(auto\\|ask\\|ignore\\)?$" line)
@@ -1058,7 +1043,7 @@ Possible values are: ask, auto, ignore."
                                      erc-dcc-chat-request)))
       t)))
 
-(defun erc-cmd-SREQ (line &optional force)
+(defun erc-cmd-SREQ (line &optional _force)
   "Set or get the DCC send request flag.
 Possible values are: ask, auto, ignore."
   (when (string-match "^\\s-*\\(auto\\|ask\\|ignore\\)?$" line)
@@ -1075,7 +1060,7 @@ Possible values are: ask, auto, ignore."
 
 (defun pcomplete/erc-mode/CREQ ()
   (pcomplete-here '("auto" "ask" "ignore")))
-(defalias 'pcomplete/erc-mode/SREQ 'pcomplete/erc-mode/CREQ)
+(defalias 'pcomplete/erc-mode/SREQ #'pcomplete/erc-mode/CREQ)
 
 (define-obsolete-variable-alias 'erc-dcc-chat-filter-hook
   'erc-dcc-chat-filter-functions "24.3")
@@ -1087,19 +1072,19 @@ the unprocessed output.")
 
 (defvar erc-dcc-chat-mode-map
   (let ((map (make-sparse-keymap)))
-    (define-key map (kbd "RET") 'erc-send-current-line)
-    (define-key map "\t" 'completion-at-point)
+    (define-key map (kbd "RET") #'erc-send-current-line)
+    (define-key map "\t" #'completion-at-point)
     map)
   "Keymap for `erc-dcc-mode'.")
 
 (define-derived-mode erc-dcc-chat-mode fundamental-mode "DCC-Chat"
   "Major mode for wasting time via DCC chat."
   (setq mode-line-process '(":%s")
-        erc-send-input-line-function 'erc-dcc-chat-send-input-line
+        erc-send-input-line-function #'erc-dcc-chat-send-input-line
         erc-default-recipients '(dcc))
-  (add-hook 'completion-at-point-functions 'erc-complete-word-at-point nil t))
+  (add-hook 'completion-at-point-functions #'erc-complete-word-at-point nil t))
 
-(defun erc-dcc-chat-send-input-line (recipient line &optional force)
+(defun erc-dcc-chat-send-input-line (recipient line &optional _force)
   "Send LINE to the remote end.
 Argument RECIPIENT should always be the symbol dcc, and force
 is ignored."
@@ -1150,14 +1135,14 @@ other client."
     (setq erc-input-marker (make-marker))
     (erc-display-prompt buffer (point-max))
     (set-process-buffer proc buffer)
-    (add-hook 'kill-buffer-hook 'erc-dcc-chat-buffer-killed nil t)
+    (add-hook 'kill-buffer-hook #'erc-dcc-chat-buffer-killed nil t)
     (run-hook-with-args 'erc-dcc-chat-connect-hook proc)
     buffer))
 
 (defun erc-dcc-chat-accept (entry parent-proc)
   "Accept an incoming DCC connection and open a DCC window."
-  (let* ((nick (erc-extract-nick (plist-get entry :nick)))
-         buffer proc)
+  (let* (;; (nick (erc-extract-nick (plist-get entry :nick)))
+         proc) ;; buffer
     (setq proc
           (funcall erc-dcc-connect-function
                    "dcc-chat" nil
@@ -1167,9 +1152,10 @@ other client."
     ;; XXX: connected, should we kill the ip/port properties?
     (setq entry (plist-put entry :peer proc))
     (setq entry (plist-put entry :parent parent-proc))
-    (set-process-filter proc 'erc-dcc-chat-filter)
-    (set-process-sentinel proc 'erc-dcc-chat-sentinel)
-    (setq buffer (erc-dcc-chat-setup entry))))
+    (set-process-filter proc #'erc-dcc-chat-filter)
+    (set-process-sentinel proc #'erc-dcc-chat-sentinel)
+    ;; (setq buffer
+    (erc-dcc-chat-setup entry))) ;; )
 
 (defun erc-dcc-chat-filter (proc str)
   (let ((orig-buffer (current-buffer)))
diff --git a/lisp/erc/erc-desktop-notifications.el 
b/lisp/erc/erc-desktop-notifications.el
index 056fb23..990f013 100644
--- a/lisp/erc/erc-desktop-notifications.el
+++ b/lisp/erc/erc-desktop-notifications.el
@@ -45,13 +45,11 @@
 
 (defcustom erc-notifications-icon nil
   "Icon to use for notification."
-  :group 'erc-notifications
   :type '(choice (const :tag "No icon" nil) file))
 
 (defcustom erc-notifications-bus :session
   "D-Bus bus to use for notification."
   :version "25.1"
-  :group 'erc-notifications
   :type '(choice (const :tag "Session bus" :session) string))
 
 (defvar dbus-debug) ; used in the macroexpansion of dbus-ignore-errors
@@ -99,11 +97,11 @@ This will replace the last notification sent with this 
function."
 (define-erc-module notifications nil
   "Send notifications on private message reception and mentions."
   ;; Enable
-  ((add-hook 'erc-server-PRIVMSG-functions 'erc-notifications-PRIVMSG)
-   (add-hook 'erc-text-matched-hook 'erc-notifications-notify-on-match))
+  ((add-hook 'erc-server-PRIVMSG-functions #'erc-notifications-PRIVMSG)
+   (add-hook 'erc-text-matched-hook #'erc-notifications-notify-on-match))
   ;; Disable
-  ((remove-hook 'erc-server-PRIVMSG-functions 'erc-notifications-PRIVMSG)
-   (remove-hook 'erc-text-matched-hook 'erc-notifications-notify-on-match)))
+  ((remove-hook 'erc-server-PRIVMSG-functions #'erc-notifications-PRIVMSG)
+   (remove-hook 'erc-text-matched-hook #'erc-notifications-notify-on-match)))
 
 (provide 'erc-desktop-notifications)
 
diff --git a/lisp/erc/erc-ezbounce.el b/lisp/erc/erc-ezbounce.el
index 8378ff5..331d29a 100644
--- a/lisp/erc/erc-ezbounce.el
+++ b/lisp/erc/erc-ezbounce.el
@@ -1,4 +1,4 @@
-;;; erc-ezbounce.el ---  Handle EZBounce bouncer commands
+;;; erc-ezbounce.el ---  Handle EZBounce bouncer commands  -*- 
lexical-binding: t; -*-
 
 ;; Copyright (C) 2002, 2004, 2006-2021 Free Software Foundation, Inc.
 
@@ -33,7 +33,6 @@
 
 (defcustom erc-ezb-regexp "^ezbounce!srv$"
   "Regexp used by the EZBouncer to identify itself to the user."
-  :group 'erc-ezbounce
   :type 'regexp)
 
 (defcustom erc-ezb-login-alist '()
@@ -44,7 +43,6 @@ The alist's format is as follows:
  (((server . port) . (username . password))
   ((server . port) . (username . password))
   ...)"
-  :group 'erc-ezbounce
   :type '(repeat
          (cons (cons :tag "Server"
                     string
@@ -68,7 +66,7 @@ The alist's format is as follows:
   "Indicate whether current notices are expected to be EZB session listings.")
 
 ;;;###autoload
-(defun erc-cmd-ezb (line &optional force)
+(defun erc-cmd-ezb (line &optional _force)
   "Send EZB commands to the EZBouncer verbatim."
   (erc-server-send (concat "EZB " line)))
 (put 'erc-cmd-EZB 'do-not-parse-args t)
@@ -102,7 +100,7 @@ in the alist is nil, prompt for the appropriate values."
     found))
 
 ;;;###autoload
-(defun erc-ezb-notice-autodetect (proc parsed)
+(defun erc-ezb-notice-autodetect (_proc parsed)
   "React on an EZBounce NOTICE request."
   (let* ((sender (erc-response.sender parsed))
         (message (erc-response.contents parsed))
@@ -113,7 +111,7 @@ in the alist is nil, prompt for the appropriate values."
   nil)
 
 ;;;###autoload
-(defun erc-ezb-identify (message)
+(defun erc-ezb-identify (_message)
   "Identify to the EZBouncer server."
   (let ((login (erc-ezb-get-login erc-session-server (erc-port-to-string 
erc-session-port))))
     (unless (null login)
@@ -122,13 +120,13 @@ in the alist is nil, prompt for the appropriate values."
        (erc-server-send (concat "LOGIN " username " " pass))))))
 
 ;;;###autoload
-(defun erc-ezb-init-session-list (message)
+(defun erc-ezb-init-session-list (_message)
   "Reset the EZBounce session list to nil."
   (setq erc-ezb-session-list nil)
   (setq erc-ezb-inside-session-listing t))
 
 ;;;###autoload
-(defun erc-ezb-end-of-session-list (message)
+(defun erc-ezb-end-of-session-list (_message)
   "Indicate the end of the EZBounce session listing."
   (setq erc-ezb-inside-session-listing nil))
 
@@ -143,7 +141,7 @@ in the alist is nil, prompt for the appropriate values."
       (add-to-list 'erc-ezb-session-list (list id nick to)))))
 
 ;;;###autoload
-(defun erc-ezb-select (message)
+(defun erc-ezb-select (_message)
   "Select an IRC server to use by EZBounce, in ERC style."
   (unless (and erc-ezb-session-list
               (erc-ezb-select-session))
@@ -169,7 +167,7 @@ in the alist is nil, prompt for the appropriate values."
 ;;;###autoload
 (defun erc-ezb-initialize ()
   "Add EZBouncer convenience functions to ERC."
-  (add-hook 'erc-server-NOTICE-functions 'erc-ezb-notice-autodetect))
+  (add-hook 'erc-server-NOTICE-functions #'erc-ezb-notice-autodetect))
 
 (provide 'erc-ezbounce)
 
diff --git a/lisp/erc/erc-fill.el b/lisp/erc/erc-fill.el
index 83ef5f9..0312d22 100644
--- a/lisp/erc/erc-fill.el
+++ b/lisp/erc/erc-fill.el
@@ -1,4 +1,4 @@
-;;; erc-fill.el --- Filling IRC messages in various ways
+;;; erc-fill.el --- Filling IRC messages in various ways  -*- lexical-binding: 
t; -*-
 
 ;; Copyright (C) 2001-2004, 2006-2021 Free Software Foundation, Inc.
 
@@ -47,7 +47,7 @@ the mode if ARG is omitted or nil.
 ERC fill mode is a global minor mode.  When enabled, messages in
 the channel buffers are filled."
   nil nil nil
-  :global t :group 'erc-fill
+  :global t
   (if erc-fill-mode
       (erc-fill-enable)
     (erc-fill-disable)))
@@ -55,19 +55,18 @@ the channel buffers are filled."
 (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-insert-modify-hook #'erc-fill)
+  (add-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))
+  (remove-hook 'erc-insert-modify-hook #'erc-fill)
+  (remove-hook 'erc-send-modify-hook #'erc-fill))
 
 (defcustom erc-fill-prefix nil
   "Values used as `fill-prefix' for `erc-fill-variable'.
 nil means fill with space, a string means fill with this string."
-  :group 'erc-fill
   :type '(choice (const nil) string))
 
 (defcustom erc-fill-function 'erc-fill-variable
@@ -94,7 +93,6 @@ These two styles are implemented using `erc-fill-variable' and
 `erc-fill-static'.  You can, of course, define your own filling
 function.  Narrowing to the region in question is in effect while your
 function is called."
-  :group 'erc-fill
   :type '(choice (const :tag "Variable Filling" erc-fill-variable)
                  (const :tag "Static Filling" erc-fill-static)
                  function))
@@ -104,18 +102,15 @@ function is called."
 centered.  This column denotes the point where the ` ' character
 between <nickname> and the entered text will be put, thus aligning
 nick names right and text left."
-  :group 'erc-fill
   :type 'integer)
 
 (defcustom erc-fill-variable-maximum-indentation 17
   "If we indent a line after a long nick, don't indent more then this
 characters.  Set to nil to disable."
-  :group 'erc-fill
   :type 'integer)
 
 (defcustom erc-fill-column 78
   "The column at which a filled paragraph is broken."
-  :group 'erc-fill
   :type 'integer)
 
 ;;;###autoload
diff --git a/lisp/erc/erc-goodies.el b/lisp/erc/erc-goodies.el
index aef6881..1143faa 100644
--- a/lisp/erc/erc-goodies.el
+++ b/lisp/erc/erc-goodies.el
@@ -1,4 +1,4 @@
-;; erc-goodies.el --- Collection of ERC modules
+;; erc-goodies.el --- Collection of ERC modules  -*- lexical-binding: t; -*-
 
 ;; Copyright (C) 2001-2021 Free Software Foundation, Inc.
 
@@ -37,7 +37,7 @@
   "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)
+(add-hook 'erc-mode-hook #'erc-imenu-setup)
 (autoload 'erc-create-imenu-index "erc-imenu" "Imenu index creation function")
 
 ;;; Automatically scroll to bottom
@@ -53,16 +53,16 @@ argument to `recenter'."
 
 (define-erc-module scrolltobottom nil
   "This mode causes the prompt to stay at the end of the window."
-  ((add-hook 'erc-mode-hook 'erc-add-scroll-to-bottom)
-   (add-hook 'erc-insert-done-hook 'erc-possibly-scroll-to-bottom)
+  ((add-hook 'erc-mode-hook #'erc-add-scroll-to-bottom)
+   (add-hook 'erc-insert-done-hook #'erc-possibly-scroll-to-bottom)
    (dolist (buffer (erc-buffer-list))
      (with-current-buffer buffer
        (erc-add-scroll-to-bottom))))
-  ((remove-hook 'erc-mode-hook 'erc-add-scroll-to-bottom)
-   (remove-hook 'erc-insert-done-hook 'erc-possibly-scroll-to-bottom)
+  ((remove-hook 'erc-mode-hook #'erc-add-scroll-to-bottom)
+   (remove-hook 'erc-insert-done-hook #'erc-possibly-scroll-to-bottom)
    (dolist (buffer (erc-buffer-list))
      (with-current-buffer buffer
-       (remove-hook 'post-command-hook 'erc-scroll-to-bottom t)))))
+       (remove-hook 'post-command-hook #'erc-scroll-to-bottom t)))))
 
 (defun erc-possibly-scroll-to-bottom ()
   "Like `erc-add-scroll-to-bottom', but only if window is selected."
@@ -77,7 +77,7 @@ the value of `erc-input-line-position'.
 
 This works whenever scrolling happens, so it's added to
 `window-scroll-functions' rather than `erc-insert-post-hook'."
-  (add-hook 'post-command-hook 'erc-scroll-to-bottom nil t))
+  (add-hook 'post-command-hook #'erc-scroll-to-bottom nil t))
 
 (defun erc-scroll-to-bottom ()
   "Recenter WINDOW so that `point' is on the last line.
@@ -104,10 +104,10 @@ variable `erc-input-line-position'."
 ;;; Make read only
 (define-erc-module readonly nil
   "This mode causes all inserted text to be read-only."
-  ((add-hook 'erc-insert-post-hook 'erc-make-read-only)
-   (add-hook 'erc-send-post-hook 'erc-make-read-only))
-  ((remove-hook 'erc-insert-post-hook 'erc-make-read-only)
-   (remove-hook 'erc-send-post-hook 'erc-make-read-only)))
+  ((add-hook 'erc-insert-post-hook #'erc-make-read-only)
+   (add-hook 'erc-send-post-hook #'erc-make-read-only))
+  ((remove-hook 'erc-insert-post-hook #'erc-make-read-only)
+   (remove-hook 'erc-send-post-hook #'erc-make-read-only)))
 
 (defun erc-make-read-only ()
   "Make all the text in the current buffer read-only.
@@ -119,14 +119,14 @@ Put this function on `erc-insert-post-hook' and/or 
`erc-send-post-hook'."
 ;;; Move to prompt when typing text
 (define-erc-module move-to-prompt nil
   "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)
    (dolist (buffer (erc-buffer-list))
      (with-current-buffer buffer
        (erc-move-to-prompt-setup))))
-  ((remove-hook 'erc-mode-hook 'erc-move-to-prompt-setup)
+  ((remove-hook 'erc-mode-hook #'erc-move-to-prompt-setup)
    (dolist (buffer (erc-buffer-list))
      (with-current-buffer buffer
-       (remove-hook 'pre-command-hook 'erc-move-to-prompt t)))))
+       (remove-hook 'pre-command-hook #'erc-move-to-prompt t)))))
 
 (defun erc-move-to-prompt ()
   "Move the point to the ERC prompt if this is a self-inserting command."
@@ -138,15 +138,15 @@ Put this function on `erc-insert-post-hook' and/or 
`erc-send-post-hook'."
 
 (defun erc-move-to-prompt-setup ()
   "Initialize the move-to-prompt module for XEmacs."
-  (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
 (define-erc-module keep-place nil
   "Leave point above un-viewed text in other channels."
-  ((add-hook 'erc-insert-pre-hook  'erc-keep-place))
-  ((remove-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)))
 
-(defun erc-keep-place (ignored)
+(defun erc-keep-place (_ignored)
   "Move point away from the last line in a non-selected ERC buffer."
   (when (and (not (eq (window-buffer (selected-window))
                       (current-buffer)))
@@ -183,8 +183,8 @@ does not appear in the ERC buffer after the user presses 
ENTER.")
   "This mode distinguishes non-commands.
 Commands listed in `erc-insert-this' know how to display
 themselves."
-  ((add-hook 'erc-pre-send-functions 'erc-send-distinguish-noncommands))
-  ((remove-hook 'erc-pre-send-functions 'erc-send-distinguish-noncommands)))
+  ((add-hook 'erc-pre-send-functions #'erc-send-distinguish-noncommands))
+  ((remove-hook 'erc-pre-send-functions #'erc-send-distinguish-noncommands)))
 
 (defun erc-send-distinguish-noncommands (state)
   "If STR is an ERC non-command, set `insertp' in STATE to nil."
@@ -211,20 +211,17 @@ highlighting effects.  When this variable is non-nil, it 
can cause Emacs to run
 slowly on systems lacking sufficient CPU speed.  In chatty channels, or in an
 emergency (message flood) it can be turned off to save processing time.  See
 `erc-toggle-interpret-controls'."
-  :group 'erc-control-characters
   :type '(choice (const :tag "Highlight control characters" t)
                  (const :tag "Remove control characters" remove)
                  (const :tag "Display raw control characters" nil)))
 
 (defcustom erc-interpret-mirc-color nil
   "If non-nil, ERC will interpret mIRC color codes."
-  :group 'erc-control-characters
   :type 'boolean)
 
 (defcustom erc-beep-p nil
   "Beep if C-g is in the server message.
 The value `erc-interpret-controls-p' must also be t for this to work."
-  :group 'erc-control-characters
   :type 'boolean)
 
 (defface erc-bold-face '((t :weight bold))
@@ -372,10 +369,10 @@ The value `erc-interpret-controls-p' must also be t for 
this to work."
 
 (define-erc-module irccontrols nil
   "This mode enables the interpretation of IRC control chars."
-  ((add-hook 'erc-insert-modify-hook 'erc-controls-highlight)
-   (add-hook 'erc-send-modify-hook 'erc-controls-highlight))
-  ((remove-hook 'erc-insert-modify-hook 'erc-controls-highlight)
-   (remove-hook 'erc-send-modify-hook 'erc-controls-highlight)))
+  ((add-hook 'erc-insert-modify-hook #'erc-controls-highlight)
+   (add-hook 'erc-send-modify-hook #'erc-controls-highlight))
+  ((remove-hook 'erc-insert-modify-hook #'erc-controls-highlight)
+   (remove-hook 'erc-send-modify-hook #'erc-controls-highlight)))
 
 (defun erc-controls-interpret (str)
    "Return a copy of STR after dealing with IRC control characters.
@@ -546,10 +543,10 @@ Else interpretation is turned off."
   "This mode translates text-smileys such as :-) into pictures.
 This requires the function `smiley-region', which is defined in
 smiley.el, which is part of Gnus."
-  ((add-hook 'erc-insert-modify-hook 'erc-smiley)
-   (add-hook 'erc-send-modify-hook 'erc-smiley))
-  ((remove-hook 'erc-insert-modify-hook 'erc-smiley)
-   (remove-hook 'erc-send-modify-hook 'erc-smiley)))
+  ((add-hook 'erc-insert-modify-hook #'erc-smiley)
+   (add-hook 'erc-send-modify-hook #'erc-smiley))
+  ((remove-hook 'erc-insert-modify-hook #'erc-smiley)
+   (remove-hook 'erc-send-modify-hook #'erc-smiley)))
 
 (defun erc-smiley ()
   "Smilify a region.
@@ -560,8 +557,8 @@ This function should be used with `erc-insert-modify-hook'."
 ;; Unmorse
 (define-erc-module unmorse nil
   "This mode causes morse code in the current channel to be unmorsed."
-  ((add-hook 'erc-insert-modify-hook 'erc-unmorse))
-  ((remove-hook 'erc-insert-modify-hook 'erc-unmorse)))
+  ((add-hook 'erc-insert-modify-hook #'erc-unmorse))
+  ((remove-hook 'erc-insert-modify-hook #'erc-unmorse)))
 
 (defun erc-unmorse ()
   "Unmorse some text.
diff --git a/lisp/erc/erc-ibuffer.el b/lisp/erc/erc-ibuffer.el
index 5a002cc..22336ed 100644
--- a/lisp/erc/erc-ibuffer.el
+++ b/lisp/erc/erc-ibuffer.el
@@ -1,4 +1,4 @@
-;;; erc-ibuffer.el --- ibuffer integration with ERC
+;;; erc-ibuffer.el --- ibuffer integration with ERC  -*- lexical-binding: t; 
-*-
 
 ;; Copyright (C) 2002, 2004, 2006-2021 Free Software Foundation, Inc.
 
@@ -39,20 +39,16 @@
 
 (defcustom erc-ibuffer-keyword-char ?k
   "Char used to indicate a channel which had keyword traffic lately (hidden)."
-  :group 'erc-ibuffer
   :type 'character)
 (defcustom erc-ibuffer-pal-char ?p
   "Char used to indicate a channel which had pal traffic lately (hidden)."
-  :group 'erc-ibuffer
   :type 'character)
 (defcustom erc-ibuffer-fool-char ?f
   "Char used to indicate a channel which had fool traffic lately (hidden)."
-  :group 'erc-ibuffer
   :type 'character)
 (defcustom erc-ibuffer-dangerous-host-char ?d
   "Char used to indicate a channel which had dangerous-host traffic lately
 \(hidden)."
-  :group 'erc-ibuffer
   :type 'character)
 
 (define-ibuffer-filter erc-server
@@ -153,7 +149,7 @@
   (if (and (eq major-mode 'erc-mode)
           (or (> (length erc-channel-modes) 0)
               erc-channel-user-limit))
-      (concat (apply 'concat
+      (concat (apply #'concat
                     "(+" erc-channel-modes)
              (if erc-channel-user-limit
                  (format "l %d" erc-channel-user-limit)
@@ -181,6 +177,7 @@
 (defvar erc-ibuffer-limit-map nil
   "Prefix keymap to use for ERC related limiting.")
 (define-prefix-command 'erc-ibuffer-limit-map)
+;; FIXME: Where is `ibuffer-limit-by-erc-server' defined?
 (define-key 'erc-ibuffer-limit-map (kbd "s") 'ibuffer-limit-by-erc-server)
 (define-key ibuffer-mode-map (kbd "/ \C-e") 'erc-ibuffer-limit-map)
 
diff --git a/lisp/erc/erc-identd.el b/lisp/erc/erc-identd.el
index 5f1aab1..3821e29 100644
--- a/lisp/erc/erc-identd.el
+++ b/lisp/erc/erc-identd.el
@@ -1,10 +1,10 @@
-;;; erc-identd.el --- RFC1413 (identd authentication protocol) server
+;;; erc-identd.el --- RFC1413 (identd authentication protocol) server  -*- 
lexical-binding: t; -*-
 
 ;; Copyright (C) 2003, 2006-2021 Free Software Foundation, Inc.
 
 ;; Author: John Wiegley <johnw@gnu.org>
 ;; Maintainer: Amin Bandali <bandali@gnu.org>
-;; Keywords: comm, processes
+;; Keywords: comm
 
 ;; This file is part of GNU Emacs.
 
@@ -50,7 +50,6 @@
 `erc-identd-start'.
 
 This can be either a string or a number."
-  :group 'erc-identd
   :type '(choice (const :tag "None" nil)
                 (integer :tag "Port number")
                 (string :tag "Port string")))
@@ -58,10 +57,10 @@ This can be either a string or a number."
 ;;;###autoload(autoload 'erc-identd-mode "erc-identd")
 (define-erc-module identd nil
   "This mode launches an identd server on port 8113."
-  ((add-hook 'erc-connect-pre-hook 'erc-identd-quickstart)
-   (add-hook 'erc-disconnected-hook 'erc-identd-stop))
-  ((remove-hook 'erc-connect-pre-hook 'erc-identd-quickstart)
-   (remove-hook 'erc-disconnected-hook 'erc-identd-stop)))
+  ((add-hook 'erc-connect-pre-hook #'erc-identd-quickstart)
+   (add-hook 'erc-disconnected-hook #'erc-identd-stop))
+  ((remove-hook 'erc-connect-pre-hook #'erc-identd-quickstart)
+   (remove-hook 'erc-disconnected-hook #'erc-identd-stop)))
 
 (defun erc-identd-filter (proc string)
   "This filter implements RFC1413 (identd authentication protocol)."
@@ -95,16 +94,16 @@ system."
                              :buffer nil
                              :host 'local :service port
                              :server t :noquery t :nowait t
-                             :filter 'erc-identd-filter))
+                             :filter #'erc-identd-filter))
   (set-process-query-on-exit-flag erc-identd-process nil))
 
-(defun erc-identd-quickstart (&rest ignored)
+(defun erc-identd-quickstart (&rest _ignored)
   "Start the identd server with the default port.
 The default port is specified by `erc-identd-port'."
   (erc-identd-start))
 
 ;;;###autoload
-(defun erc-identd-stop (&rest ignore)
+(defun erc-identd-stop (&rest _ignore)
   (interactive)
   (when erc-identd-process
     (delete-process erc-identd-process)
diff --git a/lisp/erc/erc-imenu.el b/lisp/erc/erc-imenu.el
index 1a2d8e2..b2a2dc5 100644
--- a/lisp/erc/erc-imenu.el
+++ b/lisp/erc/erc-imenu.el
@@ -1,4 +1,4 @@
-;;; erc-imenu.el -- Imenu support for ERC
+;;; erc-imenu.el -- Imenu support for ERC  -*- lexical-binding: t; -*-
 
 ;; Copyright (C) 2001-2002, 2004, 2006-2021 Free Software Foundation,
 ;; Inc.
@@ -71,15 +71,13 @@ Don't rely on this function, read it first!"
        (message-alist '())
        (mode-change-alist '())
        (topic-change-alist '())
-       prev-pos)
+       ) ;; prev-pos
     (goto-char (point-max))
-    (imenu-progress-message prev-pos 0)
     (while (if (bolp)
               (> (forward-line -1)
                  -1)
             (progn (forward-line 0)
                    t))
-      (imenu-progress-message prev-pos nil t)
       (save-match-data
        (when (looking-at (concat (regexp-quote erc-notice-prefix)
                                  "\\(.+\\)$"))
@@ -108,7 +106,8 @@ Don't rely on this function, read it first!"
                    "^\\(\\S-+\\) (.+) has set the topic for \\S-+: \\(.*\\)$"
                    notice-text)
               (push (cons (concat (match-string 1 notice-text) ": "
-                                  (match-string 2 notice-text)) pos)
+                                  (match-string 2 notice-text))
+                          pos)
                     topic-change-alist)))))
        (when (looking-at "<\\(\\S-+\\)> \\(.+\\)$")
          (let ((from (match-string 1))
diff --git a/lisp/erc/erc-join.el b/lisp/erc/erc-join.el
index e6e5070..2ad9c8b 100644
--- a/lisp/erc/erc-join.el
+++ b/lisp/erc/erc-join.el
@@ -1,10 +1,10 @@
-;;; erc-join.el --- autojoin channels on connect and reconnects
+;;; erc-join.el --- autojoin channels on connect and reconnects  -*- 
lexical-binding: t; -*-
 
 ;; Copyright (C) 2002-2004, 2006-2021 Free Software Foundation, Inc.
 
 ;; Author: Alex Schroeder <alex@gnu.org>
 ;; Maintainer: Amin Bandali <bandali@gnu.org>
-;; Keywords: irc
+;; Keywords: comm, irc
 ;; URL: https://www.emacswiki.org/emacs/ErcAutoJoin
 
 ;; This file is part of GNU Emacs.
@@ -42,14 +42,14 @@
 ;;;###autoload(autoload 'erc-autojoin-mode "erc-join" nil t)
 (define-erc-module autojoin nil
   "Makes ERC autojoin on connects and reconnects."
-  ((add-hook 'erc-after-connect 'erc-autojoin-channels)
-   (add-hook 'erc-nickserv-identified-hook 'erc-autojoin-after-ident)
-   (add-hook 'erc-server-JOIN-functions 'erc-autojoin-add)
-   (add-hook 'erc-server-PART-functions 'erc-autojoin-remove))
-  ((remove-hook 'erc-after-connect 'erc-autojoin-channels)
-   (remove-hook 'erc-nickserv-identified-hook 'erc-autojoin-after-ident)
-   (remove-hook 'erc-server-JOIN-functions 'erc-autojoin-add)
-   (remove-hook 'erc-server-PART-functions 'erc-autojoin-remove)))
+  ((add-hook 'erc-after-connect #'erc-autojoin-channels)
+   (add-hook 'erc-nickserv-identified-hook #'erc-autojoin-after-ident)
+   (add-hook 'erc-server-JOIN-functions #'erc-autojoin-add)
+   (add-hook 'erc-server-PART-functions #'erc-autojoin-remove))
+  ((remove-hook 'erc-after-connect #'erc-autojoin-channels)
+   (remove-hook 'erc-nickserv-identified-hook #'erc-autojoin-after-ident)
+   (remove-hook 'erc-server-JOIN-functions #'erc-autojoin-add)
+   (remove-hook 'erc-server-PART-functions #'erc-autojoin-remove)))
 
 (defcustom erc-autojoin-channels-alist nil
   "Alist of channels to autojoin on IRC networks.
@@ -70,7 +70,6 @@ keeps track of what channels you are on, and will join them
 again when you get disconnected.  When you restart Emacs, however,
 those changes are lost, and the customization you saved the last
 time is used again."
-  :group 'erc-autojoin
   :type '(repeat (cons :tag "Server"
                       (regexp :tag "Name")
                       (repeat :tag "Channels"
@@ -82,7 +81,6 @@ If the value is `connect', autojoin immediately on connecting.
 If the value is `ident', autojoin after successful NickServ
 identification, or after `erc-autojoin-delay' seconds.
 Any other value means the same as `connect'."
-  :group 'erc-autojoin
   :version "24.1"
   :type  '(choice (const :tag "On Connection" connect)
                  (const :tag "When Identified" ident)))
@@ -92,7 +90,6 @@ Any other value means the same as `connect'."
 This only takes effect if `erc-autojoin-timing' is `ident'.
 If NickServ identification occurs before this delay expires, ERC
 autojoins immediately at that time."
-  :group 'erc-autojoin
   :version "24.1"
   :type  'integer)
 
@@ -102,7 +99,6 @@ If non-nil, and a channel on the server a.b.c is joined, then
 only b.c is used as the server for `erc-autojoin-channels-alist'.
 This is important for networks that redirect you to other
 servers, presumably in the same domain."
-  :group 'erc-autojoin
   :type 'boolean)
 
 (defvar-local erc--autojoin-timer nil)
@@ -121,7 +117,7 @@ This is called from a timer set up by 
`erc-autojoin-channels'."
       (erc-log "Delayed autojoin started (no ident success detected yet)")
       (erc-autojoin-channels server nick))))
 
-(defun erc-autojoin-after-ident (network nick)
+(defun erc-autojoin-after-ident (_network _nick)
   "Autojoin channels in `erc-autojoin-channels-alist'.
 This function is run from `erc-nickserv-identified-hook'."
   (if erc--autojoin-timer
@@ -149,7 +145,7 @@ This function is run from `erc-nickserv-identified-hook'."
       (when (> erc-autojoin-delay 0)
        (setq erc--autojoin-timer
              (run-with-timer erc-autojoin-delay nil
-                             'erc-autojoin-channels-delayed
+                             #'erc-autojoin-channels-delayed
                              server nick (current-buffer))))
     ;; `erc-autojoin-timing' is `connect':
     (let ((server (or erc-session-server erc-server-announced-name)))
diff --git a/lisp/erc/erc-lang.el b/lisp/erc/erc-lang.el
index b86a8d0..136131c 100644
--- a/lisp/erc/erc-lang.el
+++ b/lisp/erc/erc-lang.el
@@ -1,4 +1,4 @@
-;;; erc-lang.el --- provide the LANG command to ERC
+;;; erc-lang.el --- provide the LANG command to ERC  -*- lexical-binding: t; 
-*-
 
 ;; Copyright (C) 2002, 2004, 2006-2021 Free Software Foundation, Inc.
 
@@ -6,7 +6,7 @@
 ;; Maintainer: Amin Bandali <bandali@gnu.org>
 ;; Old-Version: 1.0.0
 ;; URL: https://www.emacswiki.org/emacs/ErcLang
-;; Keywords: comm languages processes
+;; Keywords: comm
 
 ;; This file is part of GNU Emacs.
 
diff --git a/lisp/erc/erc-list.el b/lisp/erc/erc-list.el
index cf150e7..31693a7 100644
--- a/lisp/erc/erc-list.el
+++ b/lisp/erc/erc-list.el
@@ -59,13 +59,13 @@
 ;;;###autoload(autoload 'erc-list-mode "erc-list")
 (define-erc-module list nil
   "List channels nicely in a separate buffer."
-  ((remove-hook 'erc-server-321-functions 'erc-server-321-message)
-   (remove-hook 'erc-server-322-functions 'erc-server-322-message))
+  ((remove-hook 'erc-server-321-functions #'erc-server-321-message)
+   (remove-hook 'erc-server-322-functions #'erc-server-322-message))
   ((erc-with-all-buffers-of-server nil
      #'erc-open-server-buffer-p
-     (remove-hook 'erc-server-322-functions 'erc-list-handle-322 t))
-   (add-hook 'erc-server-321-functions 'erc-server-321-message t)
-   (add-hook 'erc-server-322-functions 'erc-server-322-message t)))
+     (remove-hook 'erc-server-322-functions #'erc-list-handle-322 t))
+   (add-hook 'erc-server-321-functions #'erc-server-321-message t)
+   (add-hook 'erc-server-322-functions #'erc-server-322-message t)))
 
 ;; Format a record for display.
 (defun erc-list-make-string (channel users topic)
@@ -126,17 +126,17 @@
 (defvar erc-list-menu-mode-map
   (let ((map (make-keymap)))
     (set-keymap-parent map special-mode-map)
-    (define-key map "k" 'erc-list-kill)
-    (define-key map "j" 'erc-list-join)
-    (define-key map "g" 'erc-list-revert)
-    (define-key map "n" 'next-line)
-    (define-key map "p" 'previous-line)
+    (define-key map "k" #'erc-list-kill)
+    (define-key map "j" #'erc-list-join)
+    (define-key map "g" #'erc-list-revert)
+    (define-key map "n" #'next-line)
+    (define-key map "p" #'previous-line)
     map)
   "Local keymap for `erc-list-mode' buffers.")
 
 (defvar erc-list-menu-sort-button-map
   (let ((map (make-sparse-keymap)))
-    (define-key map [header-line mouse-1] 'erc-list-menu-sort-by-column)
+    (define-key map [header-line mouse-1] #'erc-list-menu-sort-by-column)
     (define-key map [follow-link] 'mouse-face)
     map)
   "Local keymap for ERC list menu mode sorting buttons.")
@@ -181,12 +181,12 @@
 (defun erc-list-install-322-handler (server-buffer)
   (with-current-buffer server-buffer
     ;; Arrange for 322 responses to insert into our buffer.
-    (add-hook 'erc-server-322-functions 'erc-list-handle-322 t t)
+    (add-hook 'erc-server-322-functions #'erc-list-handle-322 t t)
     ;; Arrange for 323 (end of list) to end this.
     (erc-once-with-server-event
      323
      (lambda (_proc _parsed)
-       (remove-hook 'erc-server-322-functions 'erc-list-handle-322 t)))
+       (remove-hook 'erc-server-322-functions #'erc-list-handle-322 t)))
     ;; Find the list buffer, empty it, and display it.
     (setq-local erc-list-buffer
                 (get-buffer-create (concat "*Channels of "
diff --git a/lisp/erc/erc-log.el b/lisp/erc/erc-log.el
index 4540ec6..ddd00af 100644
--- a/lisp/erc/erc-log.el
+++ b/lisp/erc/erc-log.el
@@ -1,11 +1,11 @@
-;;; erc-log.el --- Logging facilities for ERC.
+;;; erc-log.el --- Logging facilities for ERC.  -*- lexical-binding: t; -*-
 
 ;; Copyright (C) 2003-2021 Free Software Foundation, Inc.
 
 ;; Author: Lawrence Mitchell <wence@gmx.li>
 ;; Maintainer: Amin Bandali <bandali@gnu.org>
 ;; URL: https://www.emacswiki.org/emacs/ErcLogging
-;; Keywords: IRC, chat, client, Internet, logging
+;; Keywords: comm, IRC, chat, client, Internet, logging
 
 ;; Created 2003-04-26
 ;; Logging code taken from erc.el and modified to use markers.
@@ -112,7 +112,6 @@ SERVER and PORT are the parameters that were used to 
connect to BUFFERs
 If you want to write logs into different directories, make a
 custom function which returns the directory part and set
 `erc-log-channels-directory' to its name."
-  :group 'erc-log
   :type '(choice (const :tag "#channel!nick@server:port.txt"
                        erc-generate-log-file-name-long)
                 (const :tag "#channel!nick@network.txt"
@@ -124,7 +123,6 @@ custom function which returns the directory part and set
 
 (defcustom erc-truncate-buffer-on-save nil
   "Erase the contents of any ERC (channel, query, server) buffer when it is 
saved."
-  :group 'erc-log
   :type 'boolean)
 
 (defcustom erc-enable-logging t
@@ -138,7 +136,6 @@ This variable is buffer local.  Setting it via 
\\[customize] sets the
 default value.
 
 Log files are stored in `erc-log-channels-directory'."
-  :group 'erc-log
   :type '(choice boolean
                 function))
 (make-variable-buffer-local 'erc-enable-logging)
@@ -153,14 +150,12 @@ If this is the name of a function, the function will be 
called
 with the buffer, target, nick, server, and port arguments.  See
 `erc-generate-log-file-name-function' for a description of these
 arguments."
-  :group 'erc-log
   :type '(choice directory
                 (function "Function")
                 (const :tag "Disable logging" nil)))
 
 (defcustom erc-log-insert-log-on-open nil
   "Insert log file contents into the buffer if a log file exists."
-  :group 'erc-log
   :type 'boolean)
 
 (defcustom erc-save-buffer-on-part t
@@ -168,7 +163,6 @@ arguments."
 
 If you set this to nil, you may want to enable both
 `erc-log-write-after-send' and `erc-log-write-after-insert'."
-  :group 'erc-log
   :type 'boolean)
 
 (defcustom erc-save-queries-on-quit t
@@ -176,7 +170,6 @@ If you set this to nil, you may want to enable both
 
 If you set this to nil, you may want to enable both
 `erc-log-write-after-send' and `erc-log-write-after-insert'."
-  :group 'erc-log
   :type 'boolean)
 
 (defcustom erc-log-write-after-send nil
@@ -184,7 +177,6 @@ If you set this to nil, you may want to enable both
 
 If you set this to nil, you may want to enable both
 `erc-save-buffer-on-part' and `erc-save-queries-on-quit'."
-  :group 'erc-log
   :type 'boolean)
 
 (defcustom erc-log-write-after-insert nil
@@ -193,7 +185,6 @@ logged ERC buffer.
 
 If you set this to nil, you may want to enable both
 `erc-save-buffer-on-part' and `erc-save-queries-on-quit'."
-  :group 'erc-log
   :type 'boolean)
 
 (defcustom erc-log-file-coding-system 'emacs-mule
@@ -201,15 +192,13 @@ If you set this to nil, you may want to enable both
 
 This should ideally, be a \"catch-all\" coding system, like
 `emacs-mule', or `iso-2022-7bit'."
-  :type 'coding-system
-  :group 'erc-log)
+  :type 'coding-system)
 
 (defcustom erc-log-filter-function nil
   "If non-nil, pass text through the given function before writing it to
 a log file.
 
 The function should take one argument, which is the text to filter."
-  :group 'erc-log
   :type '(choice (function "Function")
                 (const :tag "No filtering" nil)))
 
@@ -232,31 +221,31 @@ also be a predicate function.  To only log when you are 
not set away, use:
          (null (erc-away-time)))))"
   ;; enable
   ((when erc-log-write-after-insert
-     (add-hook 'erc-insert-post-hook 'erc-save-buffer-in-logs))
+     (add-hook 'erc-insert-post-hook #'erc-save-buffer-in-logs))
    (when erc-log-write-after-send
-     (add-hook 'erc-send-post-hook 'erc-save-buffer-in-logs))
-   (add-hook 'erc-kill-buffer-hook 'erc-save-buffer-in-logs)
-   (add-hook 'erc-kill-channel-hook 'erc-save-buffer-in-logs)
-   (add-hook 'kill-emacs-hook 'erc-log-save-all-buffers)
-   (add-hook 'erc-quit-hook 'erc-conditional-save-queries)
-   (add-hook 'erc-part-hook 'erc-conditional-save-buffer)
+     (add-hook 'erc-send-post-hook #'erc-save-buffer-in-logs))
+   (add-hook 'erc-kill-buffer-hook #'erc-save-buffer-in-logs)
+   (add-hook 'erc-kill-channel-hook #'erc-save-buffer-in-logs)
+   (add-hook 'kill-emacs-hook #'erc-log-save-all-buffers)
+   (add-hook 'erc-quit-hook #'erc-conditional-save-queries)
+   (add-hook 'erc-part-hook #'erc-conditional-save-buffer)
    ;; append, so that 'erc-initialize-log-marker runs first
-   (add-hook 'erc-connect-pre-hook 'erc-log-setup-logging 'append)
+   (add-hook 'erc-connect-pre-hook #'erc-log-setup-logging 'append)
    (dolist (buffer (erc-buffer-list))
      (erc-log-setup-logging buffer)))
   ;; disable
-  ((remove-hook 'erc-insert-post-hook 'erc-save-buffer-in-logs)
-   (remove-hook 'erc-send-post-hook 'erc-save-buffer-in-logs)
-   (remove-hook 'erc-kill-buffer-hook 'erc-save-buffer-in-logs)
-   (remove-hook 'erc-kill-channel-hook 'erc-save-buffer-in-logs)
-   (remove-hook 'kill-emacs-hook 'erc-log-save-all-buffers)
-   (remove-hook 'erc-quit-hook 'erc-conditional-save-queries)
-   (remove-hook 'erc-part-hook 'erc-conditional-save-buffer)
-   (remove-hook 'erc-connect-pre-hook 'erc-log-setup-logging)
+  ((remove-hook 'erc-insert-post-hook #'erc-save-buffer-in-logs)
+   (remove-hook 'erc-send-post-hook #'erc-save-buffer-in-logs)
+   (remove-hook 'erc-kill-buffer-hook #'erc-save-buffer-in-logs)
+   (remove-hook 'erc-kill-channel-hook #'erc-save-buffer-in-logs)
+   (remove-hook 'kill-emacs-hook #'erc-log-save-all-buffers)
+   (remove-hook 'erc-quit-hook #'erc-conditional-save-queries)
+   (remove-hook 'erc-part-hook #'erc-conditional-save-buffer)
+   (remove-hook 'erc-connect-pre-hook #'erc-log-setup-logging)
    (dolist (buffer (erc-buffer-list))
      (erc-log-disable-logging buffer))))
 
-(define-key erc-mode-map "\C-c\C-l" 'erc-save-buffer-in-logs)
+(define-key erc-mode-map "\C-c\C-l" #'erc-save-buffer-in-logs)
 
 ;;; functionality referenced from erc.el
 (defun erc-log-setup-logging (buffer)
@@ -357,13 +346,13 @@ The result is converted to lowercase, as IRC is 
case-insensitive."
                    buffer target nick server port)
         erc-log-channels-directory)))))
 
-(defun erc-generate-log-file-name-with-date (buffer &rest ignore)
+(defun erc-generate-log-file-name-with-date (buffer &rest _ignore)
   "This function computes a short log file name.
 The name of the log file is composed of BUFFER and the current date.
 This function is a possible value for `erc-generate-log-file-name-function'."
   (concat (buffer-name buffer) "-" (format-time-string "%Y-%m-%d") ".txt"))
 
-(defun erc-generate-log-file-name-short (buffer &rest ignore)
+(defun erc-generate-log-file-name-short (buffer &rest _ignore)
   "This function computes a short log file name.
 In fact, it only uses the buffer name of the BUFFER argument, so
 you can affect that using `rename-buffer' and the-like.  This
@@ -371,7 +360,7 @@ function is a possible value for
 `erc-generate-log-file-name-function'."
   (concat (buffer-name buffer) ".txt"))
 
-(defun erc-generate-log-file-name-long (buffer target nick server port)
+(defun erc-generate-log-file-name-long (_buffer target nick server port)
   "Generates a log-file name in the way ERC always did it.
 This results in a file name of the form #channel!nick@server:port.txt.
 This function is a possible value for `erc-generate-log-file-name-function'."
@@ -385,7 +374,7 @@ This function is a possible value for 
`erc-generate-log-file-name-function'."
 
 (declare-function erc-network-name "erc-networks" ())
 
-(defun erc-generate-log-file-name-network (buffer target nick server port)
+(defun erc-generate-log-file-name-network (buffer target nick server _port)
   "Generates a log-file name using the network name rather than server name.
 This results in a file name of the form #channel!nick@network.txt.
 This function is a possible value for `erc-generate-log-file-name-function'."
diff --git a/lisp/erc/erc-match.el b/lisp/erc/erc-match.el
index 153742a..43fbca3 100644
--- a/lisp/erc/erc-match.el
+++ b/lisp/erc/erc-match.el
@@ -1,10 +1,10 @@
-;;; erc-match.el --- Highlight messages matching certain regexps
+;;; erc-match.el --- Highlight messages matching certain regexps  -*- 
lexical-binding: t; -*-
 
 ;; Copyright (C) 2002-2021 Free Software Foundation, Inc.
 
 ;; Author: Andreas Fuchs <asf@void.at>
 ;; Maintainer: Amin Bandali <bandali@gnu.org>
-;; Keywords: comm, faces
+;; Keywords: comm
 ;; URL: https://www.emacswiki.org/emacs/ErcMatch
 
 ;; This file is part of GNU Emacs.
@@ -52,19 +52,17 @@ they are hidden or highlighted.  This is controlled via the 
variables
 `erc-current-nick-highlight-type'.  For all these highlighting types,
 you can decide whether the entire message or only the sending nick is
 highlighted."
-  ((add-hook 'erc-insert-modify-hook 'erc-match-message 'append))
-  ((remove-hook 'erc-insert-modify-hook 'erc-match-message)))
+  ((add-hook 'erc-insert-modify-hook #'erc-match-message 'append))
+  ((remove-hook 'erc-insert-modify-hook #'erc-match-message)))
 
 ;; Remaining customizations
 
 (defcustom erc-pals nil
   "List of pals on IRC."
-  :group 'erc-match
   :type '(repeat regexp))
 
 (defcustom erc-fools nil
   "List of fools on IRC."
-  :group 'erc-match
   :type '(repeat regexp))
 
 (defcustom erc-keywords nil
@@ -72,14 +70,12 @@ highlighted."
 Each entry in the list is either a regexp, or a cons cell with the
 regexp in the car and the face to use in the cdr.  If no face is
 specified, `erc-keyword-face' is used."
-  :group 'erc-match
   :type '(repeat (choice regexp
                         (list regexp face))))
 
 (defcustom erc-dangerous-hosts nil
   "List of regexps for hosts to highlight.
 Useful to mark nicks from dangerous hosts."
-  :group 'erc-match
   :type '(repeat regexp))
 
 (defcustom erc-current-nick-highlight-type 'keyword
@@ -99,7 +95,6 @@ The following values are allowed:
                      current nickname occurs
 
 Any other value disables highlighting of current nickname altogether."
-  :group 'erc-match
   :type '(choice (const nil)
                 (const nick)
                 (const keyword)
@@ -120,7 +115,6 @@ The following values are allowed:
                 from pal
 
 Any other value disables pal highlighting altogether."
-  :group 'erc-match
   :type '(choice (const nil)
                 (const nick)
                  (const message)
@@ -139,7 +133,6 @@ The following values are allowed:
                 from fool
 
 Any other value disables fool highlighting altogether."
-  :group 'erc-match
   :type '(choice (const nil)
                 (const nick)
                  (const message)
@@ -157,7 +150,6 @@ The following values are allowed:
                 containing keyword
 
 Any other value disables keyword highlighting altogether."
-  :group 'erc-match
   :type '(choice (const nil)
                 (const keyword)
                  (const message)
@@ -175,7 +167,6 @@ The following values are allowed:
                 from dangerous-host
 
 Any other value disables dangerous-host highlighting altogether."
-  :group 'erc-match
   :type '(choice (const nil)
                 (const nick)
                  (const message)
@@ -193,7 +184,6 @@ Valid match type keys are:
 
 The other element of each cons pair in this list is the buffer name to
 use for the logged message."
-  :group 'erc-match
   :type '(repeat (cons (choice :tag "Key"
                               (const keyword)
                               (const pal)
@@ -207,7 +197,6 @@ use for the logged message."
 When nil, don't log any matched messages.
 When t, log messages.
 When `away', log messages only when away."
-  :group 'erc-match
   :type '(choice (const nil)
                 (const away)
                 (const t)))
@@ -222,14 +211,12 @@ will be formatted.  The various format specs are:
 %u Nickname!user@host of sender
 %c Channel in which this was received
 %m Message"
-  :group 'erc-match
   :type 'string)
 
 (defcustom erc-beep-match-types '(current-nick)
   "Types of matches to beep for when a match occurs.
 The function `erc-beep-on-match' needs to be added to `erc-text-matched-hook'
 for beeping to work."
-  :group 'erc-match
   :type '(choice (repeat :tag "Beep on match" (choice
                                               (const current-nick)
                                               (const keyword)
@@ -244,14 +231,12 @@ Functions in this hook are passed as arguments:
 \(match-type nick!user@host message) where MATCH-TYPE is a symbol of:
 current-nick, keyword, pal, dangerous-host, fool."
   :options '(erc-log-matches erc-hide-fools erc-beep-on-match)
-  :group 'erc-match
   :type 'hook)
 
 (defcustom erc-match-exclude-server-buffer nil
   "If true, don't perform match on the server buffer; this is
 useful for excluding all the things like MOTDs from the server
 and other miscellaneous functions."
-  :group 'erc-match
   :version "24.3"
   :type 'boolean)
 
@@ -390,7 +375,7 @@ car is the string."
   (interactive)
   (erc-remove-entry-from-list 'erc-dangerous-hosts "Delete dangerous-host: "))
 
-(defun erc-match-current-nick-p (nickuserhost msg)
+(defun erc-match-current-nick-p (_nickuserhost msg)
   "Check whether the current nickname is in MSG.
 NICKUSERHOST will be ignored."
   (with-syntax-table erc-match-syntax-table
@@ -400,7 +385,7 @@ NICKUSERHOST will be ignored."
                               "\\b")
                       msg))))
 
-(defun erc-match-pal-p (nickuserhost msg)
+(defun erc-match-pal-p (nickuserhost _msg)
   "Check whether NICKUSERHOST is in `erc-pals'.
 MSG will be ignored."
   (and nickuserhost
@@ -412,7 +397,7 @@ MSG will be ignored."
        (or (erc-list-match erc-fools nickuserhost)
           (erc-match-directed-at-fool-p msg))))
 
-(defun erc-match-keyword-p (nickuserhost msg)
+(defun erc-match-keyword-p (_nickuserhost msg)
   "Check whether any keyword of `erc-keywords' matches for MSG.
 NICKUSERHOST will be ignored."
   (and msg
@@ -424,7 +409,7 @@ NICKUSERHOST will be ignored."
                erc-keywords)
        msg)))
 
-(defun erc-match-dangerous-host-p (nickuserhost msg)
+(defun erc-match-dangerous-host-p (nickuserhost _msg)
   "Check whether NICKUSERHOST is in `erc-dangerous-hosts'.
 MSG will be ignored."
   (and nickuserhost
@@ -457,7 +442,7 @@ Use this defun with `erc-insert-modify-hook'."
         (nickuserhost (erc-get-parsed-vector-nick vector))
         (nickname (and nickuserhost
                        (nth 0 (erc-parse-user nickuserhost))))
-        (old-pt (point))
+        ;; (old-pt (point))
         (nick-beg (and nickname
                        (re-search-forward (regexp-quote nickname)
                                           (point-max) t)
@@ -484,11 +469,12 @@ Use this defun with `erc-insert-modify-hook'."
         (goto-char (point-min))
         (let* ((match-prefix (concat "erc-" match-type))
                (match-pred (intern (concat "erc-match-" match-type "-p")))
-               (match-htype (eval (intern (concat match-prefix
-                                                  "-highlight-type"))))
+               (match-htype (symbol-value (intern (concat match-prefix
+                                                          "-highlight-type"))))
                (match-regex (if (string= match-type "current-nick")
                                 (regexp-quote (erc-current-nick))
-                              (eval (intern (concat match-prefix "s")))))
+                              (symbol-value
+                               (intern (concat match-prefix "s")))))
                (match-face (intern (concat match-prefix "-face"))))
           (when (funcall match-pred nickuserhost message)
             (cond
@@ -601,7 +587,7 @@ See `erc-log-match-format'."
                                 (kill-buffer buffer)))))
       buffer)))
 
-(defun erc-log-matches-come-back (proc parsed)
+(defun erc-log-matches-come-back (_proc _parsed)
   "Display a notice that messages were logged while away."
   (when (and (erc-away-time)
             (eq erc-log-matches-flag 'away))
@@ -629,7 +615,7 @@ See `erc-log-match-format'."
   nil)
 
 ; This handler must be run _before_ erc-process-away is.
-(add-hook 'erc-server-305-functions 'erc-log-matches-come-back nil)
+(add-hook 'erc-server-305-functions #'erc-log-matches-come-back nil)
 
 (defun erc-go-to-log-matches-buffer ()
   "Interactively open an erc-log-matches buffer."
@@ -642,9 +628,9 @@ See `erc-log-match-format'."
                                        (get-buffer (car buffer-cons))))))
     (switch-to-buffer buffer-name)))
 
-(define-key erc-mode-map "\C-c\C-k" 'erc-go-to-log-matches-buffer)
+(define-key erc-mode-map "\C-c\C-k" #'erc-go-to-log-matches-buffer)
 
-(defun erc-hide-fools (match-type nickuserhost message)
+(defun erc-hide-fools (match-type _nickuserhost _message)
  "Hide foolish comments.
 This function should be called from `erc-text-matched-hook'."
  (when (eq match-type 'fool)
@@ -652,7 +638,7 @@ This function should be called from 
`erc-text-matched-hook'."
                            '(invisible intangible)
                            (current-buffer))))
 
-(defun erc-beep-on-match (match-type nickuserhost message)
+(defun erc-beep-on-match (match-type _nickuserhost _message)
   "Beep when text matches.
 This function is meant to be called from `erc-text-matched-hook'."
   (when (member match-type erc-beep-match-types)
diff --git a/lisp/erc/erc-menu.el b/lisp/erc/erc-menu.el
index 4c092c8..0dc819f 100644
--- a/lisp/erc/erc-menu.el
+++ b/lisp/erc/erc-menu.el
@@ -1,10 +1,10 @@
-;; erc-menu.el -- Menu-bar definitions for ERC
+;; erc-menu.el -- Menu-bar definitions for ERC  -*- lexical-binding: t; -*-
 
 ;; Copyright (C) 2001-2002, 2004-2021 Free Software Foundation, Inc.
 
 ;; Author: Mario Lang <mlang@delysid.org>
 ;; Maintainer: Amin Bandali <bandali@gnu.org>
-;; Keywords: comm, processes, menu
+;; Keywords: comm, menu
 
 ;; This file is part of GNU Emacs.
 
@@ -28,7 +28,6 @@
 ;;; Code:
 
 (require 'erc)
-(require 'easymenu)
 
 (defgroup erc-menu nil
   "ERC menu support."
@@ -111,11 +110,11 @@ ERC menu yet.")
 (define-erc-module menu nil
   "Enable a menu in ERC buffers."
   ((unless erc-menu-defined
-     ;; make sure the menu only gets defined once, since Emacs 22
+     ;; make sure the menu only gets defined once, since Emacs
      ;; activates it immediately
      (easy-menu-define erc-menu erc-mode-map "ERC menu" erc-menu-definition)
      (setq erc-menu-defined t)))
-  (;; `easy-menu-remove' is a no-op in Emacs 22
+  (;; `easy-menu-remove' is a no-op in Emacs
    (message "You might have to restart Emacs to remove the ERC menu")))
 
 (defun erc-menu-add ()
diff --git a/lisp/erc/erc-netsplit.el b/lisp/erc/erc-netsplit.el
index 37fc4cf..9cfb947 100644
--- a/lisp/erc/erc-netsplit.el
+++ b/lisp/erc/erc-netsplit.el
@@ -1,4 +1,4 @@
-;;; erc-netsplit.el --- Reduce JOIN/QUIT messages on netsplits
+;;; erc-netsplit.el --- Reduce JOIN/QUIT messages on netsplits  -*- 
lexical-binding: t; -*-
 
 ;; Copyright (C) 2002-2004, 2006-2021 Free Software Foundation, Inc.
 
@@ -42,30 +42,27 @@ netsplits, so that it can filter the JOIN messages on a 
netjoin too."
 (define-erc-module netsplit nil
   "This mode hides quit/join messages if a netsplit occurs."
   ((erc-netsplit-install-message-catalogs)
-   (add-hook 'erc-server-JOIN-functions 'erc-netsplit-JOIN)
-   (add-hook 'erc-server-MODE-functions 'erc-netsplit-MODE)
-   (add-hook 'erc-server-QUIT-functions 'erc-netsplit-QUIT)
-   (add-hook 'erc-timer-hook 'erc-netsplit-timer))
-  ((remove-hook 'erc-server-JOIN-functions 'erc-netsplit-JOIN)
-   (remove-hook 'erc-server-MODE-functions 'erc-netsplit-MODE)
-   (remove-hook 'erc-server-QUIT-functions 'erc-netsplit-QUIT)
-   (remove-hook 'erc-timer-hook 'erc-netsplit-timer)))
+   (add-hook 'erc-server-JOIN-functions #'erc-netsplit-JOIN)
+   (add-hook 'erc-server-MODE-functions #'erc-netsplit-MODE)
+   (add-hook 'erc-server-QUIT-functions #'erc-netsplit-QUIT)
+   (add-hook 'erc-timer-hook #'erc-netsplit-timer))
+  ((remove-hook 'erc-server-JOIN-functions #'erc-netsplit-JOIN)
+   (remove-hook 'erc-server-MODE-functions #'erc-netsplit-MODE)
+   (remove-hook 'erc-server-QUIT-functions #'erc-netsplit-QUIT)
+   (remove-hook 'erc-timer-hook #'erc-netsplit-timer)))
 
 (defcustom erc-netsplit-show-server-mode-changes-flag nil
   "Set to t to enable display of server mode changes."
-  :group 'erc-netsplit
   :type 'boolean)
 
 (defcustom erc-netsplit-debug nil
   "If non-nil, debug messages will be shown in the sever buffer."
-  :group 'erc-netsplit
   :type 'boolean)
 
 (defcustom erc-netsplit-regexp
   "^[^ @!\"\n]+\\.[^ @!\n]+ [^ @!\n]+\\.[^ @!\"\n]+$"
   "This regular expression should match quit reasons produced
 by netsplits."
-  :group 'erc-netsplit
   :type 'regexp)
 
 (defcustom erc-netsplit-hook nil
@@ -190,13 +187,13 @@ join from that split has been detected or not.")
        (erc-display-message
         nil 'notice 'active
         'netsplit-wholeft ?s (car elt)
-        ?n (mapconcat 'erc-extract-nick (nthcdr 3 elt) " ")
+        ?n (mapconcat #'erc-extract-nick (nthcdr 3 elt) " ")
         ?t (if (nth 2 elt)
                "(joining)"
              "")))))
   t)
 
-(defalias 'erc-cmd-WL 'erc-cmd-WHOLEFT)
+(defalias 'erc-cmd-WL #'erc-cmd-WHOLEFT)
 
 (provide 'erc-netsplit)
 
diff --git a/lisp/erc/erc-networks.el b/lisp/erc/erc-networks.el
index 9926255..aed02a9 100644
--- a/lisp/erc/erc-networks.el
+++ b/lisp/erc/erc-networks.el
@@ -1,4 +1,4 @@
-;;; erc-networks.el --- IRC networks
+;;; erc-networks.el --- IRC networks  -*- lexical-binding: t; -*-
 
 ;; Copyright (C) 2002, 2004-2021 Free Software Foundation, Inc.
 
@@ -443,7 +443,6 @@ NET is a symbol indicating to which network from 
`erc-networks-alist'
   this server corresponds,
 HOST is the servers hostname and
 PORTS is either a number, a list of numbers, or a list of port ranges."
-  :group 'erc-networks
   :type '(alist :key-type (string :tag "Name")
                :value-type
                (group symbol (string :tag "Hostname")
@@ -714,7 +713,6 @@ MATCHER is used to find a corresponding network to a server 
while
   connected to it.  If it is regexp, it's used to match against
   `erc-server-announced-name'.  It can also be a function (predicate).
   Then it is executed with the server buffer as current-buffer."
-  :group 'erc-networks
   :type '(repeat
          (list :tag "Network"
                (symbol :tag "Network name")
@@ -762,25 +760,25 @@ Return the name of this server's network as a symbol."
   "Return the name of the current network as a string."
   (erc-with-server-buffer (symbol-name erc-network)))
 
-(defun erc-set-network-name (proc parsed)
+(defun erc-set-network-name (_proc _parsed)
   "Set `erc-network' to the value returned by `erc-determine-network'."
   (unless erc-server-connected
     (setq erc-network (erc-determine-network)))
   nil)
 
-(defun erc-unset-network-name (nick ip reason)
+(defun erc-unset-network-name (_nick _ip _reason)
   "Set `erc-network' to nil."
   (setq erc-network nil)
   nil)
 
 (define-erc-module networks nil
   "Provide data about IRC networks."
-  ((add-hook 'erc-server-375-functions 'erc-set-network-name)
-   (add-hook 'erc-server-422-functions 'erc-set-network-name)
-   (add-hook 'erc-disconnected-hook 'erc-unset-network-name))
-  ((remove-hook 'erc-server-375-functions 'erc-set-network-name)
-   (remove-hook 'erc-server-422-functions 'erc-set-network-name)
-   (remove-hook 'erc-disconnected-hook 'erc-unset-network-name)))
+  ((add-hook 'erc-server-375-functions #'erc-set-network-name)
+   (add-hook 'erc-server-422-functions #'erc-set-network-name)
+   (add-hook 'erc-disconnected-hook #'erc-unset-network-name))
+  ((remove-hook 'erc-server-375-functions #'erc-set-network-name)
+   (remove-hook 'erc-server-422-functions #'erc-set-network-name)
+   (remove-hook 'erc-disconnected-hook #'erc-unset-network-name)))
 
 (defun erc-ports-list (ports)
   "Return a list of PORTS.
diff --git a/lisp/erc/erc-notify.el b/lisp/erc/erc-notify.el
index e133e05..1ed056c 100644
--- a/lisp/erc/erc-notify.el
+++ b/lisp/erc/erc-notify.el
@@ -42,20 +42,17 @@
 (defcustom erc-notify-list nil
   "List of nicknames you want to be notified about online/offline
 status change."
-  :group 'erc-notify
   :type '(repeat string))
 
 (defcustom erc-notify-interval 60
   "Time interval (in seconds) for checking online status of notified
 people."
-  :group 'erc-notify
   :type 'integer)
 
 (defcustom erc-notify-signon-hook nil
   "Hook run after someone on `erc-notify-list' has signed on.
 Two arguments are passed to the function, SERVER and NICK, both
 strings."
-  :group 'erc-notify
   :type 'hook
   :options '(erc-notify-signon))
 
@@ -63,7 +60,6 @@ strings."
   "Hook run after someone on `erc-notify-list' has signed off.
 Two arguments are passed to the function, SERVER and NICK, both
 strings."
-  :group 'erc-notify
   :type 'hook
   :options '(erc-notify-signoff))
 
@@ -95,14 +91,14 @@ strings."
 (define-erc-module notify nil
   "Periodically check for the online status of certain users and report
 changes."
-  ((add-hook 'erc-timer-hook 'erc-notify-timer)
-   (add-hook 'erc-server-JOIN-functions 'erc-notify-JOIN)
-   (add-hook 'erc-server-NICK-functions 'erc-notify-NICK)
-   (add-hook 'erc-server-QUIT-functions 'erc-notify-QUIT))
-  ((remove-hook 'erc-timer-hook 'erc-notify-timer)
-   (remove-hook 'erc-server-JOIN-functions 'erc-notify-JOIN)
-   (remove-hook 'erc-server-NICK-functions 'erc-notify-NICK)
-   (remove-hook 'erc-server-QUIT-functions 'erc-notify-QUIT)))
+  ((add-hook 'erc-timer-hook #'erc-notify-timer)
+   (add-hook 'erc-server-JOIN-functions #'erc-notify-JOIN)
+   (add-hook 'erc-server-NICK-functions #'erc-notify-NICK)
+   (add-hook 'erc-server-QUIT-functions #'erc-notify-QUIT))
+  ((remove-hook 'erc-timer-hook #'erc-notify-timer)
+   (remove-hook 'erc-server-JOIN-functions #'erc-notify-JOIN)
+   (remove-hook 'erc-server-NICK-functions #'erc-notify-NICK)
+   (remove-hook 'erc-server-QUIT-functions #'erc-notify-QUIT)))
 
 ;;;; Timer handler
 
@@ -137,7 +133,7 @@ changes."
         (setq erc-last-ison ison-list)
         t)))
     (erc-server-send
-     (concat "ISON " (mapconcat 'identity erc-notify-list " ")))
+     (concat "ISON " (mapconcat #'identity erc-notify-list " ")))
     (setq erc-last-ison-time now)))
 
 (defun erc-notify-JOIN (proc parsed)
@@ -211,7 +207,7 @@ with args, toggle notify status of people."
         'notify_current ?l ison))))
    ((string= (car args) "-l")
     (erc-display-message nil 'notice 'active
-                        'notify_list ?l (mapconcat 'identity erc-notify-list
+                        'notify_list ?l (mapconcat #'identity erc-notify-list
                                                    " ")))
    (t
     (while args
@@ -231,7 +227,7 @@ with args, toggle notify status of people."
       (setq args (cdr args)))
     (erc-display-message
      nil 'notice 'active
-     'notify_list ?l (mapconcat 'identity erc-notify-list " "))))
+     'notify_list ?l (mapconcat #'identity erc-notify-list " "))))
   t)
 
 (autoload 'pcomplete-erc-all-nicks "erc-pcomplete")
diff --git a/lisp/erc/erc-page.el b/lisp/erc/erc-page.el
index 0cb60f5..4c244b7 100644
--- a/lisp/erc/erc-page.el
+++ b/lisp/erc/erc-page.el
@@ -1,4 +1,4 @@
-;; erc-page.el - CTCP PAGE support for ERC
+;; erc-page.el - CTCP PAGE support for ERC  -*- lexical-binding: t; -*-
 
 ;; Copyright (C) 2002, 2004, 2006-2021 Free Software Foundation, Inc.
 
@@ -30,6 +30,10 @@
 
 (require 'erc)
 
+(defgroup erc-page nil
+  "React to CTCP PAGE messages."
+  :group 'erc)
+
 ;;;###autoload(autoload 'erc-page-mode "erc-page")
 (define-erc-module page ctcp-page
   "Process CTCP PAGE requests from IRC."
@@ -37,10 +41,6 @@
 
 (erc-define-catalog-entry 'english 'CTCP-PAGE "Page from %n (%u@%h): %m")
 
-(defgroup erc-page nil
-  "React to CTCP PAGE messages."
-  :group 'erc)
-
 (defcustom erc-page-function nil
   "A function to process a \"page\" request.
 If nil, this prints the page message in the minibuffer and calls
@@ -53,20 +53,18 @@ Example for your init file:
       (lambda (sender msg)
        (play-sound-file \"/home/alex/elisp/erc/sounds/ni.wav\")
        (message \"IRC Page from %s: %s\" sender msg)))"
-  :group 'erc-page
   :type '(choice (const nil)
                 (function)))
 
-(defcustom erc-ctcp-query-PAGE-hook '(erc-ctcp-query-PAGE)
+(defcustom erc-ctcp-query-PAGE-hook (list #'erc-ctcp-query-PAGE)
   "List of functions to be called when a CTCP PAGE is received.
 This is called from `erc-process-ctcp-query'.  The functions are called
 with six arguments: PROC NICK LOGIN HOST TO MSG.  Note that you can
 also set `erc-page-function' to a function, which only gets two arguments,
 SENDER and MSG, so that might be easier to use."
-  :group 'erc-page
   :type '(repeat function))
 
-(defun erc-ctcp-query-PAGE (proc nick login host to msg)
+(defun erc-ctcp-query-PAGE (_proc nick login host _to msg)
   "Deal with an CTCP PAGE query, if `erc-page-mode' is non-nil.
 This will call `erc-page-function', if defined, or it will just print
 a message and `beep'.  In addition to that, the page message is also
@@ -91,7 +89,7 @@ inserted into the server buffer."
        nil 'notice nil text)))
   nil)
 
-(defun erc-cmd-PAGE (line &optional force)
+(defun erc-cmd-PAGE (line &optional _force)
   "Send a CTCP page to the user given as the first word in LINE.
 The rest of LINE is the message to send.  Note that you will only
 receive pages if `erc-page-mode' is on."
diff --git a/lisp/erc/erc-pcomplete.el b/lisp/erc/erc-pcomplete.el
index ddaf787..8ea37c7 100644
--- a/lisp/erc/erc-pcomplete.el
+++ b/lisp/erc/erc-pcomplete.el
@@ -1,10 +1,10 @@
-;;; erc-pcomplete.el --- Provides programmable completion for ERC
+;;; erc-pcomplete.el --- Provides programmable completion for ERC  -*- 
lexical-binding: t; -*-
 
 ;; Copyright (C) 2002-2004, 2006-2021 Free Software Foundation, Inc.
 
 ;; Author: Sacha Chua <sacha@free.net.ph>
 ;; Maintainer: Amin Bandali <bandali@gnu.org>
-;; Keywords: comm, convenience
+;; Keywords: comm
 ;; URL: https://www.emacswiki.org/emacs/ErcCompletion
 
 ;; This file is part of GNU Emacs.
@@ -50,23 +50,21 @@
 (defcustom erc-pcomplete-nick-postfix ":"
   "When `pcomplete' is used in the first word after the prompt,
 add this string to nicks completed."
-  :group 'erc-pcomplete
   :type 'string)
 
 (defcustom erc-pcomplete-order-nickname-completions t
   "If t, channel nickname completions will be ordered such that
 the most recent speakers are listed first."
-  :group 'erc-pcomplete
   :type 'boolean)
 
 ;;;###autoload(autoload 'erc-completion-mode "erc-pcomplete" nil t)
 (define-erc-module pcomplete Completion
   "In ERC Completion mode, the TAB key does completion whenever possible."
-  ((add-hook 'erc-mode-hook 'pcomplete-erc-setup)
-   (add-hook 'erc-complete-functions 'erc-pcompletions-at-point)
+  ((add-hook 'erc-mode-hook #'pcomplete-erc-setup)
+   (add-hook 'erc-complete-functions #'erc-pcompletions-at-point)
    (erc-buffer-list #'pcomplete-erc-setup))
-  ((remove-hook 'erc-mode-hook 'pcomplete-erc-setup)
-   (remove-hook 'erc-complete-functions 'erc-pcompletions-at-point)))
+  ((remove-hook 'erc-mode-hook #'pcomplete-erc-setup)
+   (remove-hook 'erc-complete-functions #'erc-pcompletions-at-point)))
 
 (defun erc-pcompletions-at-point ()
   "ERC completion data from pcomplete.
@@ -154,7 +152,7 @@ for use on `completion-at-point-function'."
 (defun pcomplete/erc-mode/NAMES ()
   (while (pcomplete-here (pcomplete-erc-channels))))
 
-(defalias 'pcomplete/erc-mode/NOTICE 'pcomplete/erc-mode/MSG)
+(defalias 'pcomplete/erc-mode/NOTICE #'pcomplete/erc-mode/MSG)
 
 (defun pcomplete/erc-mode/OP ()
   (while (pcomplete-here (pcomplete-erc-not-ops))))
@@ -162,7 +160,7 @@ for use on `completion-at-point-function'."
 (defun pcomplete/erc-mode/PART ()
   (pcomplete-here (pcomplete-erc-channels)))
 
-(defalias 'pcomplete/erc-mode/LEAVE 'pcomplete/erc-mode/PART)
+(defalias 'pcomplete/erc-mode/LEAVE #'pcomplete/erc-mode/PART)
 
 (defun pcomplete/erc-mode/QUERY ()
   (pcomplete-here (append (pcomplete-erc-all-nicks)
diff --git a/lisp/erc/erc-replace.el b/lisp/erc/erc-replace.el
index 91fafbb..d08d985 100644
--- a/lisp/erc/erc-replace.el
+++ b/lisp/erc/erc-replace.el
@@ -1,4 +1,4 @@
-;; erc-replace.el -- wash and massage messages inserted into the buffer
+;; erc-replace.el -- wash and massage messages inserted into the buffer  -*- 
lexical-binding: t; -*-
 
 ;; Copyright (C) 2001-2002, 2004, 2006-2021 Free Software Foundation,
 ;; Inc.
@@ -6,7 +6,7 @@
 ;; Author: Andreas Fuchs <asf@void.at>
 ;; Maintainer: Amin Bandali <bandali@gnu.org>
 ;; URL: https://www.emacswiki.org/emacs/ErcReplace
-;; Keywords: IRC, client, Internet
+;; Keywords: comm, IRC, client, Internet
 
 ;; This file is part of GNU Emacs.
 
@@ -49,7 +49,6 @@ expression or a variable, or any sexp, TO can be a string or a
 function to call, or any sexp.  If a function, it will be called with
 one argument, the string to be replaced, and it should return a
 replacement string."
-  :group 'erc-replace
   :type '(repeat (cons :tag "Search & Replace"
                       (choice :tag "From"
                               regexp
@@ -68,23 +67,23 @@ It replaces text according to `erc-replace-alist'."
            (let ((from (car elt))
                  (to (cdr elt)))
              (unless (stringp from)
-               (setq from (eval from)))
+               (setq from (eval from t)))
              (while (re-search-forward from nil t)
                (cond ((stringp to)
                       (replace-match to))
-                     ((and (symbolp to) (fboundp to))
+                     ((functionp to)
                       (replace-match (funcall to (match-string 0))))
                      (t
-                      (eval to))))))
+                      (eval to t))))))
          erc-replace-alist))
 
 ;;;###autoload(autoload 'erc-replace-mode "erc-replace")
 (define-erc-module replace nil
   "This mode replaces incoming text according to `erc-replace-alist'."
   ((add-hook 'erc-insert-modify-hook
-            'erc-replace-insert))
+            #'erc-replace-insert))
   ((remove-hook 'erc-insert-modify-hook
-               'erc-replace-insert)))
+               #'erc-replace-insert)))
 
 (provide 'erc-replace)
 
diff --git a/lisp/erc/erc-ring.el b/lisp/erc/erc-ring.el
index 71a9f8e..28299ae 100644
--- a/lisp/erc/erc-ring.el
+++ b/lisp/erc/erc-ring.el
@@ -1,4 +1,4 @@
-;; erc-ring.el -- Command history handling for erc using ring.el
+;; erc-ring.el -- Command history handling for erc using ring.el  -*- 
lexical-binding: t; -*-
 
 ;; Copyright (C) 2001-2004, 2006-2021 Free Software Foundation, Inc.
 
@@ -46,12 +46,12 @@
 (define-erc-module ring nil
   "Stores input in a ring so that previous commands and messages can
 be recalled using M-p and M-n."
-  ((add-hook 'erc-pre-send-functions 'erc-add-to-input-ring)
-   (define-key erc-mode-map "\M-p" 'erc-previous-command)
-   (define-key erc-mode-map "\M-n" 'erc-next-command))
-  ((remove-hook 'erc-pre-send-functions 'erc-add-to-input-ring)
-   (define-key erc-mode-map "\M-p" 'undefined)
-   (define-key erc-mode-map "\M-n" 'undefined)))
+  ((add-hook 'erc-pre-send-functions #'erc-add-to-input-ring)
+   (define-key erc-mode-map "\M-p" #'erc-previous-command)
+   (define-key erc-mode-map "\M-n" #'erc-next-command))
+  ((remove-hook 'erc-pre-send-functions #'erc-add-to-input-ring)
+   (define-key erc-mode-map "\M-p" #'undefined)
+   (define-key erc-mode-map "\M-n" #'undefined)))
 
 (defvar-local erc-input-ring nil "Input ring for erc.")
 
@@ -69,10 +69,13 @@ Call this function when setting up the mode."
     (setq erc-input-ring (make-ring comint-input-ring-size)))
   (setq erc-input-ring-index nil))
 
-(defun erc-add-to-input-ring (state)
-  "Add string S to the input ring and reset history position."
+(defun erc-add-to-input-ring (state-or-string)
+  "Add STATE-OR-STRING to input ring and reset history position.
+STATE-OR-STRING should be a string or an erc-input object."
   (unless erc-input-ring (erc-input-ring-setup))
-  (ring-insert erc-input-ring (erc-input-string state))
+  (ring-insert erc-input-ring (if (erc-input-p state-or-string)
+                                  (erc-input-string state-or-string)
+                                state-or-string)) ; string
   (setq erc-input-ring-index nil))
 
 (defun erc-clear-input-ring ()
@@ -101,11 +104,10 @@ containing a password."
       ;; area, push it on the history ring before moving back through
       ;; the input history, so it will be there when we return to the
       ;; front.
-      (if (null erc-input-ring-index)
-          (when (> (point-max) erc-input-marker)
-            (erc-add-to-input-ring (buffer-substring erc-input-marker
-                                                     (point-max)))
-            (setq erc-input-ring-index 0)))
+      (when (and (null erc-input-ring-index)
+                 (> (point-max) erc-input-marker))
+        (erc-add-to-input-ring (erc-user-input))
+        (setq erc-input-ring-index 0))
 
       (setq erc-input-ring-index (if erc-input-ring-index
                                      (ring-plus1 erc-input-ring-index
diff --git a/lisp/erc/erc-services.el b/lisp/erc/erc-services.el
index 9ef8b7f..09d1f7a 100644
--- a/lisp/erc/erc-services.el
+++ b/lisp/erc/erc-services.el
@@ -91,7 +91,6 @@ Possible settings are:.
 nil           - Disables automatic Nickserv identification.
 
 You can also use \\[erc-nickserv-identify-mode] to change modes."
-  :group 'erc-services
   :type '(choice (const autodetect)
                 (const nick-change)
                 (const both)
@@ -107,13 +106,13 @@ You can also use \\[erc-nickserv-identify-mode] to change 
modes."
   "This mode automates communication with services."
   ((erc-nickserv-identify-mode erc-nickserv-identify-mode))
   ((remove-hook 'erc-server-NOTICE-functions
-               'erc-nickserv-identify-autodetect)
+               #'erc-nickserv-identify-autodetect)
    (remove-hook 'erc-after-connect
-               'erc-nickserv-identify-on-connect)
+               #'erc-nickserv-identify-on-connect)
    (remove-hook 'erc-nick-changed-functions
-               'erc-nickserv-identify-on-nick-change)
+               #'erc-nickserv-identify-on-nick-change)
    (remove-hook 'erc-server-NOTICE-functions
-               'erc-nickserv-identification-autodetect)))
+               #'erc-nickserv-identification-autodetect)))
 
 ;;;###autoload
 (defun erc-nickserv-identify-mode (mode)
@@ -123,7 +122,7 @@ You can also use \\[erc-nickserv-identify-mode] to change 
modes."
                  "Choose Nickserv identify mode (RET to disable): "
                  '(("autodetect") ("nick-change") ("both")) nil t))))
   (add-hook 'erc-server-NOTICE-functions
-           'erc-nickserv-identification-autodetect)
+           #'erc-nickserv-identification-autodetect)
   (unless erc-networks-mode
     ;; Force-enable networks module, because we need it to set
     ;; erc-network for us.
@@ -131,41 +130,40 @@ You can also use \\[erc-nickserv-identify-mode] to change 
modes."
   (cond ((eq mode 'autodetect)
         (setq erc-nickserv-identify-mode 'autodetect)
         (add-hook 'erc-server-NOTICE-functions
-                  'erc-nickserv-identify-autodetect)
+                  #'erc-nickserv-identify-autodetect)
         (remove-hook 'erc-nick-changed-functions
-                     'erc-nickserv-identify-on-nick-change)
+                     #'erc-nickserv-identify-on-nick-change)
         (remove-hook 'erc-after-connect
-                     'erc-nickserv-identify-on-connect))
+                     #'erc-nickserv-identify-on-connect))
        ((eq mode 'nick-change)
         (setq erc-nickserv-identify-mode 'nick-change)
         (add-hook 'erc-after-connect
-                  'erc-nickserv-identify-on-connect)
+                  #'erc-nickserv-identify-on-connect)
         (add-hook 'erc-nick-changed-functions
-                  'erc-nickserv-identify-on-nick-change)
+                  #'erc-nickserv-identify-on-nick-change)
         (remove-hook 'erc-server-NOTICE-functions
-                     'erc-nickserv-identify-autodetect))
+                     #'erc-nickserv-identify-autodetect))
        ((eq mode 'both)
         (setq erc-nickserv-identify-mode 'both)
         (add-hook 'erc-server-NOTICE-functions
-                  'erc-nickserv-identify-autodetect)
+                  #'erc-nickserv-identify-autodetect)
         (add-hook 'erc-after-connect
-                  'erc-nickserv-identify-on-connect)
+                  #'erc-nickserv-identify-on-connect)
         (add-hook 'erc-nick-changed-functions
-                  'erc-nickserv-identify-on-nick-change))
+                  #'erc-nickserv-identify-on-nick-change))
        (t
         (setq erc-nickserv-identify-mode nil)
         (remove-hook 'erc-server-NOTICE-functions
-                     'erc-nickserv-identify-autodetect)
+                     #'erc-nickserv-identify-autodetect)
         (remove-hook 'erc-after-connect
-                     'erc-nickserv-identify-on-connect)
+                     #'erc-nickserv-identify-on-connect)
         (remove-hook 'erc-nick-changed-functions
-                     'erc-nickserv-identify-on-nick-change)
+                     #'erc-nickserv-identify-on-nick-change)
         (remove-hook 'erc-server-NOTICE-functions
-                     'erc-nickserv-identification-autodetect))))
+                     #'erc-nickserv-identification-autodetect))))
 
 (defcustom erc-prompt-for-nickserv-password t
   "Ask for the password when identifying to NickServ."
-  :group 'erc-services
   :type 'boolean)
 
 (defcustom erc-use-auth-source-for-nickserv-password nil
@@ -174,7 +172,6 @@ This option has an no effect if 
`erc-prompt-for-nickserv-password'
 is non-nil, and passwords from `erc-nickserv-passwords' take
 precedence."
   :version "28.1"
-  :group 'erc-services
   :type 'boolean)
 
 (defcustom erc-nickserv-passwords nil
@@ -187,7 +184,6 @@ Example of use:
         \\='((freenode ((\"nick-one\" . \"password\")
                      (\"nick-two\" . \"password\")))
           (DALnet ((\"nick\" . \"password\")))))"
-  :group 'erc-services
   :type '(repeat
          (list :tag "Network"
                (choice :tag "Network name"
@@ -305,7 +301,6 @@ ANSWER is the command to use for the answer.  The default 
is `privmsg'.
 SUCCESS-REGEXP is a regular expression matching the message nickserv
   sends when you've successfully identified.
 The last two elements are optional."
-   :group 'erc-services
    :type '(repeat
           (list :tag "Nickserv data"
                 (symbol :tag "Network name")
@@ -357,7 +352,6 @@ The last two elements are optional."
 (defcustom erc-nickserv-identified-hook nil
   "Run this hook when NickServ acknowledged successful identification.
 Hooks are called with arguments (NETWORK NICK)."
-  :group 'erc-services
   :type 'hook)
 
 (defun erc-nickserv-identification-autodetect (_proc parsed)
diff --git a/lisp/erc/erc-sound.el b/lisp/erc/erc-sound.el
index edde973..92759d2 100644
--- a/lisp/erc/erc-sound.el
+++ b/lisp/erc/erc-sound.el
@@ -1,4 +1,4 @@
-;;; erc-sound.el --- CTCP SOUND support for ERC
+;;; erc-sound.el --- CTCP SOUND support for ERC  -*- lexical-binding: t -*-
 
 ;; Copyright (C) 2002-2003, 2006-2021 Free Software Foundation, Inc.
 
@@ -52,11 +52,11 @@
   "In ERC sound mode, the client will respond to CTCP SOUND requests
 and play sound files as requested."
   ;; Enable:
-  ((add-hook 'erc-ctcp-query-SOUND-hook 'erc-ctcp-query-SOUND)
-   (define-key erc-mode-map "\C-c\C-s" 'erc-toggle-sound))
+  ((add-hook 'erc-ctcp-query-SOUND-hook #'erc-ctcp-query-SOUND)
+   (define-key erc-mode-map "\C-c\C-s" #'erc-toggle-sound))
   ;; Disable:
-  ((remove-hook 'erc-ctcp-query-SOUND-hook 'erc-ctcp-query-SOUND)
-   (define-key erc-mode-map "\C-c\C-s" 'undefined)))
+  ((remove-hook 'erc-ctcp-query-SOUND-hook #'erc-ctcp-query-SOUND)
+   (define-key erc-mode-map "\C-c\C-s" #'undefined)))
 
 (erc-define-catalog-entry 'english 'CTCP-SOUND "%n (%u@%h) plays %s:%m")
 
@@ -66,18 +66,15 @@ and play sound files as requested."
 
 (defcustom erc-play-sound t
   "Play sounds when you receive CTCP SOUND requests."
-  :group 'erc-sound
   :type 'boolean)
 
 (defcustom erc-sound-path nil
   "List of directories that contain sound samples to play on SOUND events."
-  :group 'erc-sound
   :type '(repeat directory))
 
 (defcustom erc-default-sound nil
   "Play this sound if the requested file was not found.
 If this is set to nil or the file doesn't exist a beep will sound."
-  :group 'erc-sound
   :type '(choice (const nil)
                 file))
 
@@ -108,7 +105,7 @@ LINE is the text entered, including the command."
       t))
    (t nil)))
 
-(defun erc-ctcp-query-SOUND (proc nick login host to msg)
+(defun erc-ctcp-query-SOUND (_proc nick login host _to msg)
   "Display a CTCP SOUND message and play sound if `erc-play-sound' is non-nil."
   (when (string-match 
"^SOUND\\s-+\\(\\S-+\\)\\(\\(\\s-+.*\\)\\|\\(\\s-*\\)\\)$" msg)
     (let ((sound (match-string 1 msg))
diff --git a/lisp/erc/erc-speedbar.el b/lisp/erc/erc-speedbar.el
index c2be239..bb85844 100644
--- a/lisp/erc/erc-speedbar.el
+++ b/lisp/erc/erc-speedbar.el
@@ -1,4 +1,4 @@
-;;; erc-speedbar.el --- Speedbar support for ERC
+;;; erc-speedbar.el --- Speedbar support for ERC  -*- lexical-binding: t; -*-
 
 ;; Copyright (C) 2001-2004, 2006-2021 Free Software Foundation, Inc.
 
@@ -52,7 +52,6 @@
 `activity'     - Sort users by channel activity
 `alphabetical' - Sort users alphabetically
 nil            - Do not sort users"
-  :group 'erc-speedbar
   :type '(choice (const :tag "Sort users by channel activity" activity)
                 (const :tag "Sort users alphabetically" alphabetical)
                 (const :tag "Do not sort users" nil)))
@@ -67,11 +66,11 @@ nil            - Do not sort users"
     (setq erc-speedbar-key-map (speedbar-make-specialized-keymap))
 
     ;; Basic tree features
-    (define-key erc-speedbar-key-map "e" 'speedbar-edit-line)
-    (define-key erc-speedbar-key-map "\C-m" 'speedbar-edit-line)
-    (define-key erc-speedbar-key-map "+" 'speedbar-expand-line)
-    (define-key erc-speedbar-key-map "=" 'speedbar-expand-line)
-    (define-key erc-speedbar-key-map "-" 'speedbar-contract-line))
+    (define-key erc-speedbar-key-map "e" #'speedbar-edit-line)
+    (define-key erc-speedbar-key-map "\C-m" #'speedbar-edit-line)
+    (define-key erc-speedbar-key-map "+" #'speedbar-expand-line)
+    (define-key erc-speedbar-key-map "=" #'speedbar-expand-line)
+    (define-key erc-speedbar-key-map "-" #'speedbar-contract-line))
 
   (speedbar-add-expansion-list '("ERC" erc-speedbar-menu-items
                                 erc-speedbar-key-map
@@ -124,7 +123,7 @@ This will add a speedbar major display mode."
           (erc-speedbar-insert-target buffer 0))
          (t (ignore)))))
 
-(defun erc-speedbar-server-buttons (directory depth)
+(defun erc-speedbar-server-buttons (_directory depth)
   "Insert the initial list of servers you are connected to."
   (let ((servers (erc-buffer-list
                  (lambda ()
@@ -154,7 +153,7 @@ This will add a speedbar major display mode."
        (t (error "Ooops... not sure what to do")))
   (speedbar-center-buffer-smartly))
 
-(defun erc-speedbar-channel-buttons (directory depth server-buffer)
+(defun erc-speedbar-channel-buttons (_directory depth server-buffer)
   (when (get-buffer server-buffer)
     (let* ((proc (with-current-buffer server-buffer erc-server-process))
           (targets (erc-buffer-list
@@ -191,7 +190,7 @@ INDENT is the current indentation level."
      (save-excursion
        (end-of-line) (forward-char 1)
        (let ((modes (with-current-buffer channel
-                     (concat (apply 'concat
+                     (concat (apply #'concat
                                     erc-channel-modes)
                              (cond
                               ((and erc-channel-user-limit
@@ -314,7 +313,7 @@ The update is only done when the channel is actually 
expanded already."
        (t (error "Ooops... not sure what to do")))
   (speedbar-center-buffer-smartly))
 
-(defun erc-speedbar-goto-buffer (text buffer indent)
+(defun erc-speedbar-goto-buffer (_text buffer _indent)
   "When user clicks on TEXT, goto an ERC buffer.
 The INDENT level is ignored."
   (if (featurep 'dframe)
diff --git a/lisp/erc/erc-spelling.el b/lisp/erc/erc-spelling.el
index 44a3e35..950a821 100644
--- a/lisp/erc/erc-spelling.el
+++ b/lisp/erc/erc-spelling.el
@@ -1,10 +1,10 @@
-;;; erc-spelling.el --- use flyspell in ERC
+;;; erc-spelling.el --- use flyspell in ERC  -*- lexical-binding: t; -*-
 
 ;; Copyright (C) 2005-2021 Free Software Foundation, Inc.
 
 ;; Author: Jorgen Schaefer <forcer@forcix.cx>
 ;; Maintainer: Amin Bandali <bandali@gnu.org>
-;; Keywords: irc
+;; Keywords: comm, irc
 ;; URL: https://www.emacswiki.org/emacs/ErcSpelling
 
 ;; This file is part of GNU Emacs.
@@ -38,10 +38,10 @@
   "Enable flyspell mode in ERC buffers."
   ;; Use erc-connect-pre-hook instead of erc-mode-hook as pre-hook is
   ;; called AFTER the server buffer is initialized.
-  ((add-hook 'erc-connect-pre-hook 'erc-spelling-init)
+  ((add-hook 'erc-connect-pre-hook #'erc-spelling-init)
    (dolist (buffer (erc-buffer-list))
      (erc-spelling-init buffer)))
-  ((remove-hook 'erc-connect-pre-hook 'erc-spelling-init)
+  ((remove-hook 'erc-connect-pre-hook #'erc-spelling-init)
    (dolist (buffer (erc-buffer-list))
      (with-current-buffer buffer (flyspell-mode 0)))))
 
@@ -104,7 +104,7 @@ The cadr is the beginning and the caddr is the end."
 
 (put 'erc-mode
      'flyspell-mode-predicate
-     'erc-spelling-flyspell-verify)
+     #'erc-spelling-flyspell-verify)
 
 (provide 'erc-spelling)
 
diff --git a/lisp/erc/erc-stamp.el b/lisp/erc/erc-stamp.el
index 2c42a18..31de9e8 100644
--- a/lisp/erc/erc-stamp.el
+++ b/lisp/erc/erc-stamp.el
@@ -4,7 +4,7 @@
 
 ;; Author: Mario Lang <mlang@delysid.org>
 ;; Maintainer: Amin Bandali <bandali@gnu.org>
-;; Keywords: comm, processes, timestamp
+;; Keywords: comm, timestamp
 ;; URL: https://www.emacswiki.org/emacs/ErcStamp
 
 ;; This file is part of GNU Emacs.
@@ -52,7 +52,6 @@ This string is processed using `format-time-string'.
 Good examples are \"%T\" and \"%H:%M\".
 
 If nil, timestamping is turned off."
-  :group 'erc-stamp
   :type '(choice (const nil)
                 (string)))
 
@@ -66,7 +65,6 @@ screen when `erc-insert-timestamp-function' is set to
 `erc-insert-timestamp-left-and-right'.
 
 If nil, timestamping is turned off."
-  :group 'erc-stamp
   :type '(choice (const nil)
                 (string)))
 
@@ -80,7 +78,6 @@ screen when `erc-insert-timestamp-function' is set to
 `erc-insert-timestamp-left-and-right'.
 
 If nil, timestamping is turned off."
-  :group 'erc-stamp
   :type '(choice (const nil)
                 (string)))
 
@@ -95,7 +92,6 @@ operate on.
 
 You will probably want to set
 `erc-insert-away-timestamp-function' to the same value."
-  :group 'erc-stamp
   :type '(choice (const :tag "Both sides" erc-insert-timestamp-left-and-right)
                 (const :tag "Right" erc-insert-timestamp-right)
                 (const :tag "Left" erc-insert-timestamp-left)
@@ -108,7 +104,6 @@ If nil, timestamping is turned off when away unless 
`erc-timestamp-format'
 is set.
 
 If `erc-timestamp-format' is set, this will not be used."
-  :group 'erc-stamp
   :type '(choice (const nil)
                 (string)))
 
@@ -117,7 +112,6 @@ If `erc-timestamp-format' is set, this will not be used."
   "Function to use to insert the away timestamp.
 
 See `erc-insert-timestamp-function' for details."
-  :group 'erc-stamp
   :type '(choice (const :tag "Both sides" erc-insert-timestamp-left-and-right)
                 (const :tag "Right" erc-insert-timestamp-right)
                 (const :tag "Left" erc-insert-timestamp-left)
@@ -128,7 +122,6 @@ See `erc-insert-timestamp-function' for details."
 
 This is useful for logging, because, although timestamps will be
 hidden, they will still be present in the logs."
-  :group 'erc-stamp
   :type 'boolean)
 
 (defcustom erc-echo-timestamps nil
@@ -136,20 +129,17 @@ hidden, they will still be present in the logs."
 Using this variable, you can turn off normal timestamping,
 and simply move point to an irc message to see its timestamp
 printed in the minibuffer."
-  :group 'erc-stamp
   :type 'boolean)
 
 (defcustom erc-echo-timestamp-format "Timestamped %A, %H:%M:%S"
   "Format string to be used when `erc-echo-timestamps' is non-nil.
 This string specifies the format of the timestamp being echoed in
 the minibuffer."
-  :group 'erc-stamp
   :type 'string)
 
 (defcustom erc-timestamp-intangible nil
   "Whether the timestamps should be intangible, i.e. prevent the point
 from entering them and instead jump over them."
-  :group 'erc-stamp
   :version "24.5"
   :type 'boolean)
 
@@ -211,7 +201,6 @@ string of spaces which is the same size as the timestamp is 
added to
 the beginning of the line in its place.  If you use
 `erc-insert-timestamp-right', nothing gets inserted in place of the
 timestamp."
-  :group 'erc-stamp
   :type 'boolean)
 
 (defcustom erc-timestamp-right-column nil
@@ -219,7 +208,6 @@ timestamp."
 if the timestamp is to be printed to the right.  If nil,
 `erc-insert-timestamp-right' will use other means to determine
 the correct column."
-  :group 'erc-stamp
   :type '(choice
          (integer :tag "Column number")
          (const :tag "Unspecified" nil)))
@@ -231,7 +219,6 @@ Asian language characters and math symbols) precede a 
timestamp.
 
 A side effect of enabling this is that there will only be one
 space before a right timestamp in any saved logs."
-  :group 'erc-stamp
   :type 'boolean)
 
 (defun erc-insert-timestamp-left (string)
diff --git a/lisp/erc/erc-status-sidebar.el b/lisp/erc/erc-status-sidebar.el
index ff51026..a75a74b 100644
--- a/lisp/erc/erc-status-sidebar.el
+++ b/lisp/erc/erc-status-sidebar.el
@@ -1,4 +1,4 @@
-;;; erc-status-sidebar.el --- HexChat-like activity overview for ERC
+;;; erc-status-sidebar.el --- HexChat-like activity overview for ERC  -*- 
lexical-binding: t; -*-
 
 ;; Copyright (C) 2017, 2020-2021 Free Software Foundation, Inc.
 
@@ -58,36 +58,30 @@
 
 (defcustom erc-status-sidebar-buffer-name "*ERC Status*"
   "Name of the sidebar buffer."
-  :type 'string
-  :group 'erc-status-sidebar)
+  :type 'string)
 
 (defcustom erc-status-sidebar-mode-line-format "ERC Status"
   "Mode line format for the status sidebar."
-  :type 'string
-  :group 'erc-status-sidebar)
+  :type 'string)
 
 (defcustom erc-status-sidebar-header-line-format nil
   "Header line format for the status sidebar."
   :type '(choice (const :tag "No header line" nil)
-                 string)
-  :group 'erc-status-sidebar)
+                 string))
 
 (defcustom erc-status-sidebar-width 15
   "Default width of the sidebar (in columns)."
-  :type 'number
-  :group 'erc-status-sidebar)
+  :type 'number)
 
 (defcustom erc-status-sidebar-channel-sort
   'erc-status-sidebar-default-chansort
   "Sorting function used to determine order of channels in the sidebar."
-  :type 'function
-  :group 'erc-status-sidebar)
+  :type 'function)
 
 (defcustom erc-status-sidebar-channel-format
   'erc-status-sidebar-default-chan-format
   "Function used to format channel names for display in the sidebar."
-  :type 'function
-  :group 'erc-status-sidebar)
+  :type 'function)
 
 (defun erc-status-sidebar-display-window ()
   "Display the status buffer in a side window.  Return the new window."
@@ -152,7 +146,8 @@ containing it on the current frame is closed.  See
   (save-excursion
     (let ((sidebar-exists (erc-status-sidebar-buffer-exists-p))
           (sidebar-buffer (erc-status-sidebar-get-buffer))
-          (sidebar-window (erc-status-sidebar-get-window)))
+          ;; (sidebar-window (erc-status-sidebar-get-window))
+          )
       (unless sidebar-exists
         (with-current-buffer sidebar-buffer
           (erc-status-sidebar-mode)
@@ -253,7 +248,7 @@ name stand out."
     erc-disconnected-hook
     erc-quit-hook))
 
-(defun erc-status-sidebar--post-refresh (&rest ignore)
+(defun erc-status-sidebar--post-refresh (&rest _ignore)
   "Schedule sidebar refresh for execution after command stack is cleared.
 
 Ignore arguments in IGNORE, allowing this function to be added to
@@ -276,7 +271,7 @@ to the `window-configuration-change-hook'."
   (when (and (eq (selected-window) (erc-status-sidebar-get-window))
              (fboundp 'window-preserve-size))
     (unless (eq (window-total-width) (window-min-size nil t))
-      (apply 'window-preserve-size (selected-window) t t nil))))
+      (apply #'window-preserve-size (selected-window) t t nil))))
 
 (define-derived-mode erc-status-sidebar-mode special-mode "ERC Sidebar"
   "Major mode for ERC status sidebar"
@@ -298,8 +293,7 @@ to the `window-configuration-change-hook'."
   ;; erc-status-sidebar-mode initialization code, so it won't undo the
   ;; add-hook's we did in the previous expressions.
   (add-hook 'change-major-mode-hook #'erc-status-sidebar-mode--unhook nil t)
-  (add-hook 'kill-buffer-hook #'erc-status-sidebar-mode--unhook nil t)
-  :group 'erc-status-sidebar)
+  (add-hook 'kill-buffer-hook #'erc-status-sidebar-mode--unhook nil t))
 
 (provide 'erc-status-sidebar)
 ;;; erc-status-sidebar.el ends here
diff --git a/lisp/erc/erc-track.el b/lisp/erc/erc-track.el
index d6ad847..8be5555 100644
--- a/lisp/erc/erc-track.el
+++ b/lisp/erc/erc-track.el
@@ -4,7 +4,7 @@
 
 ;; Author: Mario Lang <mlang@delysid.org>
 ;; Maintainer: Amin Bandali <bandali@gnu.org>
-;; Keywords: comm, faces
+;; Keywords: comm
 ;; URL: https://www.emacswiki.org/emacs/ErcChannelTracking
 
 ;; This file is part of GNU Emacs.
@@ -60,7 +60,6 @@ The reason for using this default value is to both (1) adhere 
to
 the Emacs development guidelines which say not to touch keys of
 the form C-c C-<something> and also (2) to meet the expectations
 of long-time ERC users, many of whom rely on these keybindings."
-  :group 'erc-track
   :type '(choice (const :tag "Ask, if used already" ask)
                 (const :tag "Enable" t)
                 (const :tag "Disable" nil)))
@@ -80,7 +79,6 @@ nil              - only the selected frame
 selected-visible - only the selected frame if it is visible
 
 Activity means that there was no user input in the last 10 seconds."
-  :group 'erc-track
   :type  '(choice (const :tag "All frames" t)
                  (const :tag "All visible frames" visible)
                  (const :tag "Only the selected frame" nil)
@@ -89,13 +87,11 @@ Activity means that there was no user input in the last 10 
seconds."
 
 (defcustom erc-track-exclude nil
   "A list targets (channel names or query targets) which should not be 
tracked."
-  :group 'erc-track
   :type '(repeat string))
 
 (defcustom erc-track-remove-disconnected-buffers nil
   "If true, remove buffers associated with a server that is
 disconnected from `erc-modified-channels-alist'."
-  :group 'erc-track
   :type 'boolean)
 
 (defcustom erc-track-exclude-types '("NICK" "333" "353")
@@ -105,25 +101,21 @@ This list could look like (\"JOIN\" \"PART\").
 By default, exclude changes of nicknames (NICK), display of who
 set the channel topic (333), and listing of users on the current
 channel (353)."
-  :group 'erc-track
   :type 'erc-message-type)
 
 (defcustom erc-track-exclude-server-buffer nil
   "If true, don't perform tracking on the server buffer; this is
 useful for excluding all the things like MOTDs from the server and
 other miscellaneous functions."
-  :group 'erc-track
   :type 'boolean)
 
 (defcustom erc-track-shorten-start 1
   "This number specifies the minimum number of characters a channel name in
 the mode-line should be reduced to."
-  :group 'erc-track
   :type 'number)
 
 (defcustom erc-track-shorten-cutoff 4
   "All channel names longer than this value will be shortened."
-  :group 'erc-track
   :type 'number)
 
 (defcustom erc-track-shorten-aggressively nil
@@ -144,7 +136,6 @@ not compared to #electronica -- only to #vi, therefore it 
can be shortened
 even more and the result is #e and #v.
 
 This setting is used by `erc-track-shorten-names'."
-  :group 'erc-track
   :type '(choice (const :tag "No" nil)
                 (const :tag "Yes" t)
                 (const :tag "Max" max)))
@@ -154,7 +145,6 @@ This setting is used by `erc-track-shorten-names'."
 It takes one argument, CHANNEL-NAMES which is a list of strings.
 It should return a list of strings of the same number of elements.
 If nil instead of a function, shortening is disabled."
-  :group 'erc-track
   :type '(choice (const :tag "Disabled")
                 function))
 
@@ -165,14 +155,12 @@ If nil instead of a function, shortening is disabled."
 This is useful for people that don't use the default mode-line
 notification but instead use a separate mechanism to provide
 notification of channel activity."
-  :group 'erc-track
   :type 'hook)
 
 (defcustom erc-track-use-faces t
   "Use faces in the mode-line.
 The faces used are the same as used for text in the buffers.
 \(e.g. `erc-pal-face' is used if a pal sent a message to that channel.)"
-  :group 'erc-track
   :type 'boolean)
 
 (defcustom erc-track-faces-priority-list
@@ -199,7 +187,6 @@ The faces used are the same as used for text in the buffers.
   "A list of faces used to highlight active buffer names in the mode line.
 If a message contains one of the faces in this list, the buffer name will
 be highlighted using that face.  The first matching face is used."
-  :group 'erc-track
   :type '(repeat (choice face
                         (repeat :tag "Combination" face))))
 
@@ -214,7 +201,6 @@ this feature.
 
 Note: If you have a lot of faces listed in `erc-track-faces-priority-list',
 setting this variable might not be very useful."
-  :group 'erc-track
   :type '(choice (const nil)
                 (repeat string)
                 (const all)))
@@ -237,21 +223,17 @@ message.  This gives a rough indication that active 
conversations
 are occurring in these channels.
 
 The effect may be disabled by setting this variable to nil."
-  :group 'erc-track
   :type '(repeat (choice face
                         (repeat :tag "Combination" face))))
 
 (defcustom erc-track-position-in-mode-line 'before-modes
   "Where to show modified channel information in the mode-line.
 
-Setting this variable only has effect in GNU Emacs versions above 21.3.
-
 Choices are:
 `before-modes' - add to the beginning of `mode-line-modes',
 `after-modes'  - add to the end of `mode-line-modes',
 t              - add to the end of `global-mode-string',
 nil            - don't add to mode line."
-  :group 'erc-track
   :type '(choice (const :tag "Just before mode information" before-modes)
                 (const :tag "Just after mode information" after-modes)
                 (const :tag "After all other information" t)
@@ -268,7 +250,7 @@ nil            - don't add to mode line."
   (if strings
       (concat (if (eq erc-track-position-in-mode-line 'after-modes)
                  "[" " [")
-             (mapconcat 'identity (nreverse strings) ",")
+             (mapconcat #'identity (nreverse strings) ",")
              (if (eq erc-track-position-in-mode-line 'before-modes)
                  "] " "]"))
     ""))
@@ -291,20 +273,17 @@ while the buffer was not visible.")
 
 (defcustom erc-track-showcount nil
   "If non-nil, count of unseen messages will be shown for each channel."
-  :type 'boolean
-  :group 'erc-track)
+  :type 'boolean)
 
 (defcustom erc-track-showcount-string ":"
   "The string to display between buffer name and the count in the mode line.
 The default is a colon, resulting in \"#emacs:9\"."
-  :type 'string
-  :group 'erc-track)
+  :type 'string)
 
 (defcustom erc-track-switch-from-erc t
   "If non-nil, `erc-track-switch-buffer' will return to the last non-erc buffer
 when there are no more active channels."
-  :type 'boolean
-  :group 'erc-track)
+  :type 'boolean)
 
 (defcustom erc-track-switch-direction 'oldest
   "Direction `erc-track-switch-buffer' should switch.
@@ -318,7 +297,6 @@ when there are no more active channels."
 If set to `importance', the importance is determined by position
 in `erc-track-faces-priority-list', where first is most
 important."
-  :group 'erc-track
   :type '(choice (const importance)
                 (const oldest)
                 (const newest)
@@ -474,9 +452,9 @@ START is the minimum length of the name used."
 (defvar erc-track-minor-mode-map (make-sparse-keymap)
   "Keymap for rcirc track minor mode.")
 
-(define-key erc-track-minor-mode-map (kbd "C-c C-@") 'erc-track-switch-buffer)
+(define-key erc-track-minor-mode-map (kbd "C-c C-@") #'erc-track-switch-buffer)
 (define-key erc-track-minor-mode-map (kbd "C-c C-SPC")
-  'erc-track-switch-buffer)
+  #'erc-track-switch-buffer)
 
 ;;;###autoload
 (define-minor-mode erc-track-minor-mode
@@ -489,8 +467,7 @@ keybindings will not do anything useful."
   :init-value nil
   :lighter ""
   :keymap erc-track-minor-mode-map
-  :global t
-  :group 'erc-track)
+  :global t)
 
 (defun erc-track-minor-mode-maybe (&optional buffer)
   "Enable `erc-track-minor-mode', depending on `erc-track-enable-keybindings'."
@@ -532,17 +509,17 @@ keybindings will not do anything useful."
   ((when (boundp 'erc-track-when-inactive)
      (if erc-track-when-inactive
         (progn
-          (add-hook 'window-configuration-change-hook 'erc-user-is-active)
-          (add-hook 'erc-send-completed-hook 'erc-user-is-active)
-          (add-hook 'erc-server-001-functions 'erc-user-is-active))
+          (add-hook 'window-configuration-change-hook #'erc-user-is-active)
+          (add-hook 'erc-send-completed-hook #'erc-user-is-active)
+          (add-hook 'erc-server-001-functions #'erc-user-is-active))
        (erc-track-add-to-mode-line erc-track-position-in-mode-line)
        (erc-update-mode-line)
        (add-hook 'window-configuration-change-hook
-                'erc-window-configuration-change)
-       (add-hook 'erc-insert-post-hook 'erc-track-modified-channels)
-       (add-hook 'erc-disconnected-hook 'erc-modified-channels-update))
+                #'erc-window-configuration-change)
+       (add-hook 'erc-insert-post-hook #'erc-track-modified-channels)
+       (add-hook 'erc-disconnected-hook #'erc-modified-channels-update))
      ;; enable the tracking keybindings
-     (add-hook 'erc-connect-pre-hook 'erc-track-minor-mode-maybe)
+     (add-hook 'erc-connect-pre-hook #'erc-track-minor-mode-maybe)
      (erc-track-minor-mode-maybe)))
   ;; Disable:
   ((when (boundp 'erc-track-when-inactive)
@@ -550,23 +527,22 @@ keybindings will not do anything useful."
      (if erc-track-when-inactive
         (progn
           (remove-hook 'window-configuration-change-hook
-                       'erc-user-is-active)
-          (remove-hook 'erc-send-completed-hook 'erc-user-is-active)
-          (remove-hook 'erc-server-001-functions 'erc-user-is-active)
-          (remove-hook 'erc-timer-hook 'erc-user-is-active))
+                       #'erc-user-is-active)
+          (remove-hook 'erc-send-completed-hook #'erc-user-is-active)
+          (remove-hook 'erc-server-001-functions #'erc-user-is-active)
+          (remove-hook 'erc-timer-hook #'erc-user-is-active))
        (remove-hook 'window-configuration-change-hook
-                   'erc-window-configuration-change)
-       (remove-hook 'erc-disconnected-hook 'erc-modified-channels-update)
-       (remove-hook 'erc-insert-post-hook 'erc-track-modified-channels))
+                   #'erc-window-configuration-change)
+       (remove-hook 'erc-disconnected-hook #'erc-modified-channels-update)
+       (remove-hook 'erc-insert-post-hook #'erc-track-modified-channels))
      ;; disable the tracking keybindings
-     (remove-hook 'erc-connect-pre-hook 'erc-track-minor-mode-maybe)
+     (remove-hook 'erc-connect-pre-hook #'erc-track-minor-mode-maybe)
      (when erc-track-minor-mode
        (erc-track-minor-mode -1)))))
 
 (defcustom erc-track-when-inactive nil
   "Enable channel tracking even for visible buffers, if you are
 inactive."
-  :group 'erc-track
   :type 'boolean
   :set (lambda (sym val)
         (if erc-track-mode
@@ -707,9 +683,9 @@ Use `erc-make-mode-line-buffer-name' to create buttons."
              ;; four lists we use to create a new
              ;; `erc-modified-channels-object' using
              ;; `erc-make-mode-line-buffer-name'.
-             (let* ((buffers (mapcar 'car erc-modified-channels-alist))
-                    (counts (mapcar 'cadr erc-modified-channels-alist))
-                    (faces (mapcar 'cddr erc-modified-channels-alist))
+             (let* ((buffers (mapcar #'car erc-modified-channels-alist))
+                    (counts (mapcar #'cadr erc-modified-channels-alist))
+                    (faces (mapcar #'cddr erc-modified-channels-alist))
                     (long-names (mapcar #'(lambda (buf)
                                             (or (buffer-name buf)
                                                 ""))
diff --git a/lisp/erc/erc-truncate.el b/lisp/erc/erc-truncate.el
index f4514ca..ff33fbc 100644
--- a/lisp/erc/erc-truncate.el
+++ b/lisp/erc/erc-truncate.el
@@ -1,4 +1,4 @@
-;;; erc-truncate.el --- Functions for truncating ERC buffers
+;;; erc-truncate.el --- Functions for truncating ERC buffers  -*- 
lexical-binding: t; -*-
 
 ;; Copyright (C) 2003-2004, 2006-2021 Free Software Foundation, Inc.
 
@@ -41,7 +41,6 @@
   "Maximum size in chars of each ERC buffer.
 Used only when auto-truncation is enabled.
 \(see `erc-truncate-buffer' and `erc-insert-post-hook')."
-  :group 'erc-truncate
   :type 'integer)
 
 ;;;###autoload(autoload 'erc-truncate-mode "erc-truncate" nil t)
@@ -51,9 +50,9 @@ This prevents the query buffer from getting too large, which 
can
 bring any grown Emacs to its knees after a few days worth of
 tracking heavy-traffic channels."
   ;;enable
-  ((add-hook 'erc-insert-post-hook 'erc-truncate-buffer))
+  ((add-hook 'erc-insert-post-hook #'erc-truncate-buffer))
   ;; disable
-  ((remove-hook 'erc-insert-post-hook 'erc-truncate-buffer)))
+  ((remove-hook 'erc-insert-post-hook #'erc-truncate-buffer)))
 
 ;;;###autoload
 (defun erc-truncate-buffer-to-size (size &optional buffer)
diff --git a/lisp/erc/erc-xdcc.el b/lisp/erc/erc-xdcc.el
index 6808f24..e1b9f0d 100644
--- a/lisp/erc/erc-xdcc.el
+++ b/lisp/erc/erc-xdcc.el
@@ -1,10 +1,10 @@
-;;; erc-xdcc.el --- XDCC file-server support for ERC
+;;; erc-xdcc.el --- XDCC file-server support for ERC  -*- lexical-binding: t; 
-*-
 
 ;; Copyright (C) 2003-2004, 2006-2021 Free Software Foundation, Inc.
 
 ;; Author: Mario Lang <mlang@delysid.org>
 ;; Maintainer: Amin Bandali <bandali@gnu.org>
-;; Keywords: comm, processes
+;; Keywords: comm
 
 ;; This file is part of GNU Emacs.
 
@@ -51,7 +51,7 @@ Your friends should issue \"/ctcp yournick XDCC list\" to see 
this."
 (defcustom erc-xdcc-help-text
   '(("Hey " nick ", wondering how this works?  Pretty easy.")
     ("Available commands: XDCC ["
-     (mapconcat 'car erc-xdcc-handler-alist "|") "]")
+     (mapconcat #'car erc-xdcc-handler-alist "|") "]")
     ("Type \"/ctcp " (erc-current-nick)
      " XDCC list\" to see the list of offered files, then type \"/ctcp "
      (erc-current-nick) " XDCC send #\" to get a particular file number."))
@@ -82,7 +82,7 @@ being evaluated and should return strings."
 (defvar erc-ctcp-query-XDCC-hook '(erc-xdcc)
   "Hook called whenever a CTCP XDCC message is received.")
 
-(defun erc-xdcc (proc nick login host to query)
+(defun erc-xdcc (proc nick login host _to query)
   "Handle incoming CTCP XDCC queries."
   (when erc-xdcc-verbose-flag
     (erc-display-message nil 'notice proc
@@ -96,15 +96,15 @@ being evaluated and should return strings."
        (format "Unknown XDCC sub-command, try \"/ctcp %s XDCC help\""
               (erc-current-nick))))))
 
-(defun erc-xdcc-help (proc nick login host args)
+(defun erc-xdcc-help (proc nick _login _host _args)
   "Send basic help information to NICK."
   (mapc
    (lambda (msg)
      (erc-xdcc-reply proc nick
-      (mapconcat (lambda (elt) (if (stringp elt) elt (eval elt))) msg "")))
+      (mapconcat (lambda (elt) (if (stringp elt) elt (eval elt t))) msg "")))
    erc-xdcc-help-text))
 
-(defun erc-xdcc-list (proc nick login host args)
+(defun erc-xdcc-list (proc nick _login _host _args)
   "Show the contents of `erc-xdcc-files' via privmsg to NICK."
   (if (null erc-xdcc-files)
       (erc-xdcc-reply proc nick "No files offered, sorry")
@@ -117,7 +117,7 @@ being evaluated and should return strings."
                 (setq n (1+ n))
                 (erc-dcc-file-to-name file)))))))
 
-(defun erc-xdcc-send (proc nick login host args)
+(defun erc-xdcc-send (proc nick _login _host args)
   "Send a file to NICK."
   (let ((n (string-to-number (car args)))
        (len (length erc-xdcc-files)))
diff --git a/lisp/erc/erc.el b/lisp/erc/erc.el
index dd7f50f..b6dea95 100644
--- a/lisp/erc/erc.el
+++ b/lisp/erc/erc.el
@@ -1,4 +1,4 @@
-;; erc.el --- An Emacs Internet Relay Chat client  -*- lexical-binding:t -*-
+;;; erc.el --- An Emacs Internet Relay Chat client  -*- lexical-binding:t -*-
 
 ;; Copyright (C) 1997-2021 Free Software Foundation, Inc.
 
@@ -114,17 +114,6 @@
   "Running scripts at startup and with /LOAD"
   :group 'erc)
 
-;; compatibility with older ERC releases
-
-(define-obsolete-variable-alias 'erc-announced-server-name
-  'erc-server-announced-name "ERC 5.1")
-(define-obsolete-variable-alias 'erc-process 'erc-server-process "ERC 5.1")
-(define-obsolete-variable-alias 'erc-default-coding-system
-  'erc-server-coding-system "ERC 5.1")
-
-(define-obsolete-function-alias 'erc-send-command
-  'erc-server-send "ERC 5.1")
-
 (require 'erc-backend)
 
 ;; tunable connection and authentication parameters
@@ -1144,31 +1133,31 @@ which the local user typed."
 
 (defvar erc-mode-map
   (let ((map (make-sparse-keymap)))
-    (define-key map "\C-m" 'erc-send-current-line)
-    (define-key map "\C-a" 'erc-bol)
-    (define-key map [home] 'erc-bol)
-    (define-key map "\C-c\C-a" 'erc-bol)
-    (define-key map "\C-c\C-b" 'erc-switch-to-buffer)
-    (define-key map "\C-c\C-c" 'erc-toggle-interpret-controls)
-    (define-key map "\C-c\C-d" 'erc-input-action)
-    (define-key map "\C-c\C-e" 'erc-toggle-ctcp-autoresponse)
-    (define-key map "\C-c\C-f" 'erc-toggle-flood-control)
-    (define-key map "\C-c\C-i" 'erc-invite-only-mode)
-    (define-key map "\C-c\C-j" 'erc-join-channel)
-    (define-key map "\C-c\C-n" 'erc-channel-names)
-    (define-key map "\C-c\C-o" 'erc-get-channel-mode-from-keypress)
-    (define-key map "\C-c\C-p" 'erc-part-from-channel)
-    (define-key map "\C-c\C-q" 'erc-quit-server)
-    (define-key map "\C-c\C-r" 'erc-remove-text-properties-region)
-    (define-key map "\C-c\C-t" 'erc-set-topic)
-    (define-key map "\C-c\C-u" 'erc-kill-input)
-    (define-key map "\C-c\C-x" 'erc-quit-server)
-    (define-key map "\M-\t" 'ispell-complete-word)
-    (define-key map "\t" 'completion-at-point)
+    (define-key map "\C-m" #'erc-send-current-line)
+    (define-key map "\C-a" #'erc-bol)
+    (define-key map [home] #'erc-bol)
+    (define-key map "\C-c\C-a" #'erc-bol)
+    (define-key map "\C-c\C-b" #'erc-switch-to-buffer)
+    (define-key map "\C-c\C-c" #'erc-toggle-interpret-controls)
+    (define-key map "\C-c\C-d" #'erc-input-action)
+    (define-key map "\C-c\C-e" #'erc-toggle-ctcp-autoresponse)
+    (define-key map "\C-c\C-f" #'erc-toggle-flood-control)
+    (define-key map "\C-c\C-i" #'erc-invite-only-mode)
+    (define-key map "\C-c\C-j" #'erc-join-channel)
+    (define-key map "\C-c\C-n" #'erc-channel-names)
+    (define-key map "\C-c\C-o" #'erc-get-channel-mode-from-keypress)
+    (define-key map "\C-c\C-p" #'erc-part-from-channel)
+    (define-key map "\C-c\C-q" #'erc-quit-server)
+    (define-key map "\C-c\C-r" #'erc-remove-text-properties-region)
+    (define-key map "\C-c\C-t" #'erc-set-topic)
+    (define-key map "\C-c\C-u" #'erc-kill-input)
+    (define-key map "\C-c\C-x" #'erc-quit-server)
+    (define-key map "\M-\t" #'ispell-complete-word)
+    (define-key map "\t" #'completion-at-point)
 
     ;; Suppress `font-lock-fontify-block' key binding since it
     ;; destroys face properties.
-    (define-key map [remap font-lock-fontify-block] 'undefined)
+    (define-key map [remap font-lock-fontify-block] #'undefined)
 
     map)
   "ERC keymap.")
@@ -1304,6 +1293,9 @@ and disable it otherwise.  If called from Lisp, enable 
the mode
 if ARG is omitted or nil.
 %s" name name doc)
         nil nil nil
+        ;; FIXME: We don't know if this group exists, so this `:group' may
+        ;; actually just silence a valid warning about the fact that the var
+        ;; is not associated with any group.
         :global ,(not local-p) :group (quote ,group)
         (if ,mode
             (,enable)
@@ -1324,12 +1316,10 @@ if ARG is omitted or nil.
          ,@disable-body)
        ,(when (and alias (not (eq name alias)))
           `(defalias
-             (quote
-              ,(intern
+             ',(intern
                 (format "erc-%s-mode"
-                        (downcase (symbol-name alias)))))
-             (quote
-              ,mode)))
+                        (downcase (symbol-name alias))))
+             #',mode))
        ;; For find-function and find-variable.
        (put ',mode    'definition-name ',name)
        (put ',enable  'definition-name ',name)
@@ -1756,7 +1746,7 @@ nil."
        (ignore res)
        res)))
 
-(define-obsolete-function-alias 'erc-iswitchb 'erc-switch-to-buffer "25.1")
+(define-obsolete-function-alias 'erc-iswitchb #'erc-switch-to-buffer "25.1")
 (defun erc--switch-to-buffer (&optional arg)
   (read-buffer "Switch to ERC buffer: "
               (when (boundp 'erc-modified-channels-alist)
@@ -1865,7 +1855,7 @@ removed from the list will be disabled."
   :get (lambda (sym)
          ;; replace outdated names with their newer equivalents
          (erc-migrate-modules (symbol-value sym)))
-  :initialize 'custom-initialize-default
+  :initialize #'custom-initialize-default
   :set (lambda (sym val)
          ;; disable modules which have just been removed
          (when (and (boundp 'erc-modules) erc-modules val)
@@ -2136,33 +2126,34 @@ If no buffer matches, return nil."
           (erc-current-nick-p nick)))))
 
 (defcustom erc-before-connect nil
-  "Hook called before connecting to a server.
-This hook gets executed before `erc' actually invokes `erc-mode'
-with your input data.  The functions in here get called with three
-parameters, SERVER, PORT and NICK."
+  "Functions called before connecting to a server.
+The functions in this variable gets executed before `erc'
+actually invokes `erc-mode' with your input data.  The functions
+in here get called with three parameters, SERVER, PORT and NICK."
   :group 'erc-hooks
-  :type 'hook)
+  :type '(repeat function))
 
 (defcustom erc-after-connect nil
-  "Hook called after connecting to a server.
-This hook gets executed when an end of MOTD has been received.  All
-functions in here get called with the parameters SERVER and NICK."
+  "Functions called after connecting to a server.
+This functions in this variable gets executed when an end of MOTD
+has been received.  All functions in here get called with the
+parameters SERVER and NICK."
   :group 'erc-hooks
-  :type 'hook)
+  :type '(repeat function))
 
 ;;;###autoload
 (defun erc-select-read-args ()
   "Prompt the user for values of nick, server, port, and password."
   (let (user-input server port nick passwd)
-    (setq user-input (read-from-minibuffer
+    (setq user-input (read-string
                       "IRC server: "
-                      (erc-compute-server) nil nil 'erc-server-history-list))
+                      (erc-compute-server) 'erc-server-history-list))
 
     (if (string-match "\\(.*\\):\\(.*\\)\\'" user-input)
         (setq port (erc-string-to-port (match-string 2 user-input))
               user-input (match-string 1 user-input))
       (setq port
-            (erc-string-to-port (read-from-minibuffer
+            (erc-string-to-port (read-string
                                  "IRC port: " (erc-port-to-string
                                                (erc-compute-port))))))
 
@@ -2171,13 +2162,12 @@ functions in here get called with the parameters SERVER 
and NICK."
               user-input (match-string 2 user-input))
       (setq nick
             (if (erc-already-logged-in server port nick)
-                (read-from-minibuffer
+                (read-string
                  (erc-format-message 'nick-in-use ?n nick)
-                 nick
-                 nil nil 'erc-nick-history-list)
-              (read-from-minibuffer
+                 nick 'erc-nick-history-list)
+              (read-string
                "Nickname: " (erc-compute-nick nick)
-               nil nil 'erc-nick-history-list))))
+               'erc-nick-history-list))))
 
     (setq server user-input)
 
@@ -2196,10 +2186,9 @@ functions in here get called with the parameters SERVER 
and NICK."
       ;; bnc with the same nick. actually it would be nice to have
       ;; bncs transparent, so that erc-compute-buffer-name displays
       ;; the server one is connected to.
-      (setq nick (read-from-minibuffer
+      (setq nick (read-string
                   (erc-format-message 'nick-in-use ?n nick)
-                  nick
-                  nil nil 'erc-nick-history-list)))
+                  nick 'erc-nick-history-list)))
     (list :server server :port port :nick nick :password passwd)))
 
 ;;;###autoload
@@ -2231,8 +2220,8 @@ be invoked for the values of the other parameters."
   (erc-open server port nick full-name t password))
 
 ;;;###autoload
-(defalias 'erc-select 'erc)
-(defalias 'erc-ssl 'erc-tls)
+(defalias 'erc-select #'erc)
+(defalias 'erc-ssl #'erc-tls)
 
 ;;;###autoload
 (defun erc-tls (&rest r)
@@ -2853,14 +2842,14 @@ VALUE is computed by evaluating the rest of LINE in 
Lisp."
           (val (read (match-string 2 line))))
       (if (boundp var)
           (progn
-            (set var (eval val))
+            (set var (eval val t))
             (erc-display-message
              nil nil 'active (format "Set %S to %S" var val))
             t)
         (setq var (read (match-string 1 line)))
         (if (boundp var)
             (progn
-              (set var (eval val))
+              (set var (eval val t))
               (erc-display-message
                nil nil 'active (format "Set %S to %S" var val))
               t)
@@ -2882,8 +2871,8 @@ VALUE is computed by evaluating the rest of LINE in Lisp."
      (current-buffer))
     t)
    (t nil)))
-(defalias 'erc-cmd-VAR 'erc-cmd-SET)
-(defalias 'erc-cmd-VARIABLE 'erc-cmd-SET)
+(defalias 'erc-cmd-VAR #'erc-cmd-SET)
+(defalias 'erc-cmd-VARIABLE #'erc-cmd-SET)
 (put 'erc-cmd-SET 'do-not-parse-args t)
 (put 'erc-cmd-SET 'process-not-needed t)
 
@@ -3011,7 +3000,7 @@ If no USER argument is specified, list the contents of 
`erc-ignore-list'."
                                           (car user-data))
                                          ops)))))
                  erc-channel-users))
-    (setq ops (sort ops 'string-lessp))
+    (setq ops (sort ops #'string-lessp))
     (if ops
         (erc-display-message
          nil 'notice (current-buffer) 'ops
@@ -3110,7 +3099,7 @@ For a list of user commands (/join /part, ...):
     (message "Type C-h m to get additional information about keybindings.")
     t))
 
-(defalias 'erc-cmd-H 'erc-cmd-HELP)
+(defalias 'erc-cmd-H #'erc-cmd-HELP)
 (put 'erc-cmd-HELP 'process-not-needed t)
 
 (defun erc-server-join-channel (server channel &optional secret)
@@ -3156,8 +3145,8 @@ were most recently invited.  See also `invitation'."
          (erc-server-join-channel server chnl key)))))
   t)
 
-(defalias 'erc-cmd-CHANNEL 'erc-cmd-JOIN)
-(defalias 'erc-cmd-J 'erc-cmd-JOIN)
+(defalias 'erc-cmd-CHANNEL #'erc-cmd-JOIN)
+(defalias 'erc-cmd-J #'erc-cmd-JOIN)
 
 (defvar-local erc-channel-new-member-names nil
   "If non-nil, a names list is currently being received.
@@ -3181,7 +3170,7 @@ command."
           (erc-server-send (concat "NAMES " tgt)))
       (erc-display-message nil 'error (current-buffer) 'no-default-channel)))
   t)
-(defalias 'erc-cmd-N 'erc-cmd-NAMES)
+(defalias 'erc-cmd-N #'erc-cmd-NAMES)
 
 (defun erc-cmd-KICK (target &optional reason-or-nick &rest reasonwords)
   "Kick the user indicated in LINE from the current channel.
@@ -3251,7 +3240,7 @@ If SERVER is non-nil, use that, rather than the current 
server."
     (erc-log (format "cmd: %s" send))
     (erc-server-send send)
     t))
-(defalias 'erc-cmd-WI 'erc-cmd-WHOIS)
+(defalias 'erc-cmd-WI #'erc-cmd-WHOIS)
 
 (defun erc-cmd-WHOAMI ()
   "Display whois information about yourself."
@@ -3400,7 +3389,7 @@ to send.
 If only one word is given, display the mode of that target.
 
 A list of valid mode strings for Freenode may be found at
-URL `http://freenode.net/using_the_network.shtml'."
+URL `https://freenode.net/kb/all'."
   (cond
    ((string-match "^\\s-\\(.*\\)$" line)
     (let ((s (match-string 1 line)))
@@ -3422,7 +3411,7 @@ The rest is the message to send."
 The rest of LINE is the message to send."
   (erc-message "PRIVMSG" line))
 
-(defalias 'erc-cmd-M 'erc-cmd-MSG)
+(defalias 'erc-cmd-M #'erc-cmd-MSG)
 (put 'erc-cmd-MSG 'do-not-parse-args t)
 
 (defun erc-cmd-SQUERY (line)
@@ -3477,7 +3466,7 @@ Otherwise leave the channel indicated by LINE."
    (t nil)))
 (put 'erc-cmd-PART 'do-not-parse-args t)
 
-(defalias 'erc-cmd-LEAVE 'erc-cmd-PART)
+(defalias 'erc-cmd-LEAVE #'erc-cmd-PART)
 
 (defun erc-cmd-PING (recipient)
   "Ping RECIPIENT."
@@ -3521,7 +3510,7 @@ The type of query window/frame/etc will depend on the 
value of
 If USER is omitted, close the current query buffer if one exists
 - except this is broken now ;-)"
   (interactive
-   (list (read-from-minibuffer "Start a query with: " nil)))
+   (list (read-string "Start a query with: ")))
   (let ((session-buffer (erc-server-buffer))
         (erc-join-buffer erc-query-display))
     (if user
@@ -3529,7 +3518,7 @@ If USER is omitted, close the current query buffer if one 
exists
       ;; currently broken, evil hack to display help anyway
                                         ;(erc-delete-query))))
       (signal 'wrong-number-of-arguments ""))))
-(defalias 'erc-cmd-Q 'erc-cmd-QUERY)
+(defalias 'erc-cmd-Q #'erc-cmd-QUERY)
 
 (defun erc-quit/part-reason-default ()
   "Default quit/part message."
@@ -3624,9 +3613,9 @@ the message given by REASON."
     t)
    (t nil)))
 
-(defalias 'erc-cmd-BYE 'erc-cmd-QUIT)
-(defalias 'erc-cmd-EXIT 'erc-cmd-QUIT)
-(defalias 'erc-cmd-SIGNOFF 'erc-cmd-QUIT)
+(defalias 'erc-cmd-BYE #'erc-cmd-QUIT)
+(defalias 'erc-cmd-EXIT #'erc-cmd-QUIT)
+(defalias 'erc-cmd-SIGNOFF #'erc-cmd-QUIT)
 (put 'erc-cmd-QUIT 'do-not-parse-args t)
 (put 'erc-cmd-QUIT 'process-not-needed t)
 
@@ -3645,7 +3634,7 @@ the message given by REASON."
          (kill-buffer buffer)))))
   t)
 
-(defalias 'erc-cmd-GQ 'erc-cmd-GQUIT)
+(defalias 'erc-cmd-GQ #'erc-cmd-GQUIT)
 (put 'erc-cmd-GQUIT 'do-not-parse-args t)
 (put 'erc-cmd-GQUIT 'process-not-needed t)
 
@@ -3743,7 +3732,7 @@ the message given by REASON."
       (erc-server-send (concat "TIME " args)))
     t)
    (t (erc-server-send "TIME"))))
-(defalias 'erc-cmd-DATE 'erc-cmd-TIME)
+(defalias 'erc-cmd-DATE #'erc-cmd-TIME)
 
 (defun erc-cmd-TOPIC (topic)
   "Set or request the topic for a channel.
@@ -3784,7 +3773,7 @@ be displayed."
         (erc-display-message nil 'error (current-buffer) 'no-target)))
     t)
    (t nil)))
-(defalias 'erc-cmd-T 'erc-cmd-TOPIC)
+(defalias 'erc-cmd-T #'erc-cmd-TOPIC)
 (put 'erc-cmd-TOPIC 'do-not-parse-args t)
 
 (defun erc-cmd-APPENDTOPIC (topic)
@@ -3796,7 +3785,7 @@ be displayed."
     ;; strip trailing ^O
     (when (string-match "\\(.*\\)\C-o" oldtopic)
       (erc-cmd-TOPIC (concat (match-string 1 oldtopic) topic)))))
-(defalias 'erc-cmd-AT 'erc-cmd-APPENDTOPIC)
+(defalias 'erc-cmd-AT #'erc-cmd-APPENDTOPIC)
 (put 'erc-cmd-APPENDTOPIC 'do-not-parse-args t)
 
 (defun erc-cmd-CLEARTOPIC (&optional channel)
@@ -3820,6 +3809,8 @@ The property `received-from-server' indicates whether
 or not the ban list has been requested from the server.")
 (put 'erc-channel-banlist 'received-from-server nil)
 
+(defvar erc-fill-column)
+
 (defun erc-cmd-BANLIST ()
   "Pretty-print the contents of `erc-channel-banlist'.
 
@@ -3890,7 +3881,7 @@ The ban list is fetched from the server if necessary."
         (put 'erc-channel-banlist 'received-from-server nil)))))
   t)
 
-(defalias 'erc-cmd-BL 'erc-cmd-BANLIST)
+(defalias 'erc-cmd-BL #'erc-cmd-BANLIST)
 
 (defun erc-cmd-MASSUNBAN ()
   "Mass Unban.
@@ -3932,7 +3923,7 @@ Unban all currently banned users in the current channel."
              (erc-group-list bans 3))))
         t))))
 
-(defalias 'erc-cmd-MUB 'erc-cmd-MASSUNBAN)
+(defalias 'erc-cmd-MUB #'erc-cmd-MASSUNBAN)
 
 ;;;; End of IRC commands
 
@@ -4033,8 +4024,7 @@ If FACE is non-nil, it will be used to propertize the 
prompt.  If it is nil,
   "Interactively input a user action and send it to IRC."
   (interactive "")
   (erc-set-active-buffer (current-buffer))
-  (let ((action (read-from-minibuffer
-                 "Action: " nil nil nil 'erc-action-history-list)))
+  (let ((action (read-string "Action: " nil 'erc-action-history-list)))
     (if (not (string-match "^\\s-*$" action))
         (erc-send-action (erc-default-target) action))))
 
@@ -4051,24 +4041,25 @@ If `point' is at the beginning of a channel name, use 
that as default."
       (completing-read (format-prompt "Join channel" chnl)
                        table nil nil nil nil chnl))
     (when (or current-prefix-arg erc-prompt-for-channel-key)
-      (read-from-minibuffer "Channel key (RET for none): " nil))))
+      (read-string "Channel key (RET for none): "))))
   (erc-cmd-JOIN channel (when (>= (length key) 1) key)))
 
 (defun erc-part-from-channel (reason)
   "Part from the current channel and prompt for a REASON."
   (interactive
+    ;; FIXME: Has this ever worked?  We're in the interactive-spec, so the
+    ;; argument `reason' can't be in scope yet!
+    ;;(if (and (boundp 'reason) (stringp reason) (not (string= reason "")))
+    ;;    reason
    (list
-    (if (and (boundp 'reason) (stringp reason) (not (string= reason "")))
-        reason
-      (read-from-minibuffer (concat "Reason for leaving " (erc-default-target)
-                                    ": ")))))
+    (read-string (concat "Reason for leaving " (erc-default-target) ": "))))
   (erc-cmd-PART (concat (erc-default-target)" " reason)))
 
 (defun erc-set-topic (topic)
   "Prompt for a TOPIC for the current channel."
   (interactive
    (list
-    (read-from-minibuffer
+    (read-string
      (concat "Set topic of " (erc-default-target) ": ")
      (when erc-channel-topic
        (let ((ss (split-string erc-channel-topic "\C-o")))
@@ -4080,7 +4071,7 @@ If `point' is at the beginning of a channel name, use 
that as default."
 (defun erc-set-channel-limit (&optional limit)
   "Set a LIMIT for the current channel.  Remove limit if nil.
 Prompt for one if called interactively."
-  (interactive (list (read-from-minibuffer
+  (interactive (list (read-string
                       (format "Limit for %s (RET to remove limit): "
                               (erc-default-target)))))
   (let ((tgt (erc-default-target)))
@@ -4091,7 +4082,7 @@ Prompt for one if called interactively."
 (defun erc-set-channel-key (&optional key)
   "Set a KEY for the current channel.  Remove key if nil.
 Prompt for one if called interactively."
-  (interactive (list (read-from-minibuffer
+  (interactive (list (read-string
                       (format "Key for %s (RET to remove key): "
                               (erc-default-target)))))
   (let ((tgt (erc-default-target)))
@@ -4102,7 +4093,7 @@ Prompt for one if called interactively."
 (defun erc-quit-server (reason)
   "Disconnect from current server after prompting for REASON.
 `erc-quit-reason' works with this just like with `erc-cmd-QUIT'."
-  (interactive (list (read-from-minibuffer
+  (interactive (list (read-string
                       (format "Reason for quitting %s: "
                               (or erc-server-announced-name
                                   erc-session-server)))))
@@ -4133,7 +4124,7 @@ This places `point' just after the prompt, or at the 
beginning of the line."
 (defun erc-complete-word-at-point ()
   (run-hook-with-args-until-success 'erc-complete-functions))
 
-(define-obsolete-function-alias 'erc-complete-word 'completion-at-point "24.1")
+(define-obsolete-function-alias 'erc-complete-word #'completion-at-point 
"24.1")
 
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;;
@@ -5181,7 +5172,7 @@ TOPIC string to the current topic."
   "Sort LIST-OF-STRINGS in lexicographic order.
 
 Side-effect free."
-  (sort (copy-sequence list-of-strings) 'string<))
+  (sort (copy-sequence list-of-strings) #'string<))
 
 (defun erc-parse-modes (mode-string)
   "Parse MODE-STRING into a list.
@@ -6118,11 +6109,11 @@ non-nil value is found.
 
 ;; time routines
 
-(define-obsolete-function-alias 'erc-string-to-emacs-time 'string-to-number
+(define-obsolete-function-alias 'erc-string-to-emacs-time #'string-to-number
   "27.1")
 
-(defalias 'erc-emacs-time-to-erc-time 'float-time)
-(defalias 'erc-current-time 'float-time)
+(defalias 'erc-emacs-time-to-erc-time #'float-time)
+(defalias 'erc-current-time #'float-time)
 
 (defun erc-time-diff (t1 t2)
   "Return the absolute value of the difference in seconds between T1 and T2."
@@ -6289,7 +6280,6 @@ The following characters are replaced:
 
 (defcustom erc-header-line-format "%n on %t (%m,%l) %o"
   "A string to be formatted and shown in the header-line in `erc-mode'.
-Only used starting in Emacs 21.
 
 Set this to nil if you do not want the header line to be
 displayed.
@@ -6905,7 +6895,3 @@ Otherwise, connect to HOST:PORT as USER and /join 
CHANNEL."
 (require 'erc-goodies)
 
 ;;; erc.el ends here
-;;
-;; Local Variables:
-;; outline-regexp: ";;+"
-;; End:
diff --git a/lisp/eshell/em-ls.el b/lisp/eshell/em-ls.el
index e942ae2..3d7c43b 100644
--- a/lisp/eshell/em-ls.el
+++ b/lisp/eshell/em-ls.el
@@ -680,12 +680,12 @@ Each member of FILES is either a string or a cons cell of 
the form
     (let ((f files)
          last-f
          display-files
-         ignore)
+         ) ;; ignore
       (while f
        (if (cdar f)
            (setq last-f f
                  f (cdr f))
-         (unless ignore
+         (unless nil ;; ignore
            (funcall error-func
                     (format "%s: No such file or directory\n" (caar f))))
          (if (eq f files)
@@ -698,7 +698,7 @@ Each member of FILES is either a string or a cons cell of 
the form
              (setcar f (cadr f))
              (setcdr f (cddr f))))))
       (if (not show-size)
-         (setq display-files (mapcar 'eshell-ls-annotate files))
+         (setq display-files (mapcar #'eshell-ls-annotate files))
        (dolist (file files)
          (let* ((str (eshell-ls-printable-size (file-attribute-size (cdr 
file)) t))
                 (len (length str)))
diff --git a/lisp/eshell/esh-mode.el b/lisp/eshell/esh-mode.el
index d29b010..f9dbce9 100644
--- a/lisp/eshell/esh-mode.el
+++ b/lisp/eshell/esh-mode.el
@@ -458,7 +458,7 @@ and the hook `eshell-exit-hook'."
   (let ((inhibit-read-only t)
        (no-default (eobp))
        (find-tag-default-function 'ignore))
-    (setq tagname (car (find-tag-interactive "Find tag: " no-default)))
+    (setq tagname (car (find-tag-interactive "Find tag" no-default)))
     (with-suppressed-warnings ((obsolete find-tag))
       (find-tag tagname next-p regexp-p))))
 
diff --git a/lisp/eshell/esh-opt.el b/lisp/eshell/esh-opt.el
index c1db484..7d31845 100644
--- a/lisp/eshell/esh-opt.el
+++ b/lisp/eshell/esh-opt.el
@@ -23,14 +23,6 @@
 
 ;;; Code:
 
-
-;; Unused.
-;; (defgroup eshell-opt nil
-;;   "The options processing code handles command argument parsing for
-;; Eshell commands implemented in Lisp."
-;;   :tag "Command options processing"
-;;   :group 'eshell)
-
 ;;; User Functions:
 
 ;; Macro expansion of eshell-eval-using-options refers to eshell-stringify-list
diff --git a/lisp/eshell/esh-var.el b/lisp/eshell/esh-var.el
index a09c47c..9fccc6b 100644
--- a/lisp/eshell/esh-var.el
+++ b/lisp/eshell/esh-var.el
@@ -355,7 +355,7 @@ This function is explicit for adding to 
`eshell-parse-argument-hook'."
 (defun pcomplete/eshell-mode/setq ()
   "Completion function for Eshell's `setq'."
   (while (and (pcomplete-here (all-completions pcomplete-stub
-                                              obarray 'boundp))
+                                              obarray #'boundp))
              (pcomplete-here))))
 
 ;; FIXME the real "env" command does more than this, it runs a program
diff --git a/lisp/expand.el b/lisp/expand.el
index 9df8d9f..d11ae7c 100644
--- a/lisp/expand.el
+++ b/lisp/expand.el
@@ -1,4 +1,4 @@
-;;; expand.el --- make abbreviations more usable
+;;; expand.el --- make abbreviations more usable  -*- lexical-binding: t -*-
 
 ;; Copyright (C) 1995-1996, 2001-2021 Free Software Foundation, Inc.
 
@@ -74,20 +74,17 @@
 
 (defcustom expand-load-hook nil
   "Hooks run when `expand.el' is loaded."
-  :type 'hook
-  :group 'expand)
+  :type 'hook)
 (make-obsolete-variable 'expand-load-hook
                         "use `with-eval-after-load' instead." "28.1")
 
 (defcustom expand-expand-hook nil
   "Hooks run when an abbrev made by `expand-add-abbrevs' is expanded."
-  :type 'hook
-  :group 'expand)
+  :type 'hook)
 
 (defcustom expand-jump-hook nil
   "Hooks run by `expand-jump-to-previous-slot' and `expand-jump-to-next-slot'."
-  :type 'hook
-  :group 'expand)
+  :type 'hook)
 
 ;;; Samples:
 
@@ -319,8 +316,7 @@ If ARG is omitted, point is placed at the end of the 
expanded text."
                nil)
              (if (and (symbolp expansion) (fboundp expansion))
                  expansion
-               nil)
-             )
+                nil))
       'expand-abbrev-hook)))
 
 (put 'expand-abbrev-hook 'no-self-insert t)
@@ -368,13 +364,12 @@ See `expand-add-abbrevs'.  Value is non-nil if expansion 
was done."
           (insert text)
           (setq expand-point (point))))
     (if jump-args
-       (funcall 'expand-build-list (car jump-args) (cdr jump-args)))
+        (funcall #'expand-build-list (car jump-args) (cdr jump-args)))
     (if position
        (backward-char position))
     (if hook
        (funcall hook))
-    t)
-  )
+    t))
 
 (defun expand-abbrev-from-expand (word)
   "Test if an abbrev has a hook."
@@ -428,8 +423,7 @@ This is used only in conjunction with `expand-add-abbrevs'."
        (lenlist (length expand-list)))
     (while (< i lenlist)
       (aset expand-list i (- len (1- (aref expand-list i))))
-      (setq i (1+ i))))
-  )
+      (setq i (1+ i)))))
 
 (defun expand-build-marks (p)
   "Transform the offsets vector into a marker vector."
diff --git a/lisp/facemenu.el b/lisp/facemenu.el
index dc5f8f4..2d06658 100644
--- a/lisp/facemenu.el
+++ b/lisp/facemenu.el
@@ -85,10 +85,6 @@
 
 ;;; Code:
 
-;; Global bindings:
-(define-key global-map [C-down-mouse-2] 'facemenu-menu)
-(define-key global-map "\M-o" 'facemenu-keymap)
-
 (defgroup facemenu nil
   "Create a face menu for interactively adding fonts to text."
   :group 'faces
@@ -173,6 +169,14 @@ it will remove any faces not explicitly in the list."
 (defalias 'facemenu-background-menu facemenu-background-menu)
 (put 'facemenu-background-menu 'menu-enable '(facemenu-enable-faces-p))
 
+(defcustom facemenu-add-face-function nil
+  "Function called at beginning of text to change or nil.
+This function is passed the FACE to set and END of text to change, and must
+return a string which is inserted.  It may set `facemenu-end-add-face'."
+  :type '(choice (const :tag "None" nil)
+                function)
+  :group 'facemenu)
+
 ;;; Condition for enabling menu items that set faces.
 (defun facemenu-enable-faces-p ()
   ;; Enable the facemenu if facemenu-add-face-function is defined
@@ -264,14 +268,6 @@ requested in `facemenu-keybindings'.")
 (defalias 'facemenu-keymap facemenu-keymap)
 
 
-(defcustom facemenu-add-face-function nil
-  "Function called at beginning of text to change or nil.
-This function is passed the FACE to set and END of text to change, and must
-return a string which is inserted.  It may set `facemenu-end-add-face'."
-  :type '(choice (const :tag "None" nil)
-                function)
-  :group 'facemenu)
-
 (defcustom facemenu-end-add-face nil
   "String to insert or function called at end of text to change or nil.
 This function is passed the FACE to set, and must return a string which is
@@ -295,6 +291,7 @@ May also be t meaning to use `facemenu-add-face-function'."
 (defvar facemenu-color-alist nil
   "Alist of colors, used for completion.
 If this is nil, then the value of (defined-colors) is used.")
+(make-obsolete-variable 'facemenu-color-alist nil "28.1")
 
 (defun facemenu-update ()
   "Add or update the \"Face\" menu in the menu bar.
diff --git a/lisp/faces.el b/lisp/faces.el
index 90f11bb..42f4cdd 100644
--- a/lisp/faces.el
+++ b/lisp/faces.el
@@ -503,7 +503,8 @@ If INHERIT is t, and FACE doesn't define a foreground 
color, then any
   foreground color that FACE inherits through its `:inherit' attribute
   is considered as well; however the return value may still be nil.
 If INHERIT is a face or a list of faces, then it is used to try to
-  resolve an unspecified foreground color.
+  resolve an unspecified foreground color, in addition to using any
+inherited color.
 
 To ensure that a valid color is always returned, use a value of
 `default' for INHERIT; this will resolve any unspecified values by
@@ -523,7 +524,8 @@ If INHERIT is t, and FACE doesn't define a background 
color, then any
   background color that FACE inherits through its `:inherit' attribute
   is considered as well; however the return value may still be nil.
 If INHERIT is a face or a list of faces, then it is used to try to
-  resolve an unspecified background color.
+  resolve an unspecified background color, in addition to using any
+inherited color.
 
 To ensure that a valid color is always returned, use a value of
 `default' for INHERIT; this will resolve any unspecified values by
@@ -1259,7 +1261,15 @@ of a global face.  Value is the new attribute value."
                   (or (car (rassoc old-value valid))
                       (format "%s" old-value))))
             (setq new-value
-                  (face-read-string face default attribute-name valid))
+                   (if (memq attribute '(:foreground :background))
+                       (let ((color
+                              (read-color
+                               (format-prompt "%s for face `%s'"
+                                              default attribute-name face))))
+                         (if (equal (string-trim color) "")
+                             default
+                           color))
+                    (face-read-string face default attribute-name valid)))
             (if (equal new-value default)
                 ;; Nothing changed, so don't bother with all the stuff
                 ;; below.  In particular, this avoids a non-tty color
@@ -1917,12 +1927,11 @@ Interactively, or with optional arg MSG non-nil, print 
the
 resulting color name in the echo area."
   (interactive "i\np\ni\np")    ; Always convert to RGB interactively.
   (let* ((completion-ignore-case t)
-        (colors (or facemenu-color-alist
-                    (append '("foreground at point" "background at point")
-                            (if allow-empty-name '(""))
-                             (if (display-color-p)
-                                 (defined-colors-with-face-attributes)
-                               (defined-colors)))))
+        (colors (append '("foreground at point" "background at point")
+                        (if allow-empty-name '(""))
+                         (if (display-color-p)
+                             (defined-colors-with-face-attributes)
+                           (defined-colors))))
         (color (completing-read
                 (or prompt "Color (name or #RGB triplet): ")
                 ;; Completing function for reading colors, accepting
@@ -2815,6 +2824,30 @@ Note: Other faces cannot inherit from the cursor face."
   "Face to highlight argument names in *Help* buffers."
   :group 'help)
 
+(defface help-key-binding
+  '((((class color) (min-colors 88) (background light))
+     :background "grey96" :foreground "DarkBlue"
+     ;; We use negative thickness of the horizontal box border line to
+     ;; avoid enlarging the height of the echo-area display, which
+     ;; would then move the mode line a few pixels up.
+     :box (:line-width (1 . -1) :color "grey80"))
+    (((class color) (min-colors 88) (background dark))
+     :background "grey19" :foreground "LightBlue"
+     :box (:line-width (1 . -1) :color "grey35"))
+    (((class color grayscale) (background light)) :background "grey90")
+    (((class color grayscale) (background dark)) :background "grey25")
+    (t :background "grey90"))
+  "Face for keybindings in *Help* buffers.
+
+This face is added by `substitute-command-keys', which see.
+
+Note that this face will also be used for key bindings in
+tooltips.  This means that, for example, changing the :height of
+this face will increase the height of any tooltip containing key
+bindings.  See also the face `tooltip'."
+  :version "28.1"
+  :group 'help)
+
 (defface glyphless-char
   '((((type tty)) :inherit underline)
     (((type pc)) :inherit escape-glyph)
diff --git a/lisp/filenotify.el b/lisp/filenotify.el
index 7857177..07871bb 100644
--- a/lisp/filenotify.el
+++ b/lisp/filenotify.el
@@ -100,6 +100,7 @@ If it is registered in `file-notify-descriptors', a 
`stopped' event is sent."
   "Handle a file system monitoring event, coming from backends.
 If OBJECT is a filewatch event, call its callback.
 Otherwise, signal a `file-notify-error'."
+  (declare (completion ignore))
   (interactive "e")
   (when file-notify-debug
     (message "file-notify-handle-event %S" object))
diff --git a/lisp/files-x.el b/lisp/files-x.el
index 526a128..23e4562 100644
--- a/lisp/files-x.el
+++ b/lisp/files-x.el
@@ -699,13 +699,14 @@ will not be changed."
         (copy-tree connection-local-variables-alist)))
    (hack-local-variables-apply)))
 
-(defsubst connection-local-criteria-for-default-directory ()
-  "Return a connection-local criteria, which represents `default-directory'."
+(defsubst connection-local-criteria-for-default-directory (&optional 
application)
+  "Return a connection-local criteria, which represents `default-directory'.
+If APPLICATION is nil, the symbol `tramp' is used."
   (when (file-remote-p default-directory)
-    `(:application tramp
-       :protocol ,(file-remote-p default-directory 'method)
-       :user     ,(file-remote-p default-directory 'user)
-       :machine  ,(file-remote-p default-directory 'host))))
+    `(:application ,(or application 'tramp)
+       :protocol   ,(file-remote-p default-directory 'method)
+       :user       ,(file-remote-p default-directory 'user)
+       :machine    ,(file-remote-p default-directory 'host))))
 
 ;;;###autoload
 (defmacro with-connection-local-variables (&rest body)
diff --git a/lisp/files.el b/lisp/files.el
index dada69c..60d6034 100644
--- a/lisp/files.el
+++ b/lisp/files.el
@@ -823,7 +823,9 @@ The path separator is colon in GNU and GNU-like systems."
          (expand-file-name dir))
     (locate-file dir cd-path nil
                  (lambda (f) (and (file-directory-p f) 'dir-ok)))
-    (error "No such directory found via CDPATH environment variable"))))
+    (if (getenv "CDPATH")
+        (error "No such directory found via CDPATH environment variable: %s" 
dir)
+      (error "No such directory: %s" dir)))))
 
 (defun directory-files-recursively (dir regexp
                                         &optional include-directories predicate
@@ -1639,7 +1641,7 @@ called additional times).
 
 This macro actually adds an auxiliary function that calls FUN,
 rather than FUN itself, to `minibuffer-setup-hook'."
-  (declare (indent 1) (debug t))
+  (declare (indent 1) (debug ([&or (":append" form) [&or symbolp form]] body)))
   (let ((hook (make-symbol "setup-hook"))
         (funsym (make-symbol "fun"))
         (append nil))
@@ -2530,13 +2532,11 @@ unless NOMODES is non-nil."
           (msg
            (cond
             ((not warn) nil)
-            ((and error (file-attributes buffer-file-name))
+            ((and error (file-exists-p buffer-file-name))
              (setq buffer-read-only t)
-             (if (and (file-symlink-p buffer-file-name)
-                      (not (file-exists-p
-                            (file-chase-links buffer-file-name))))
-                 "Symbolic link that points to nonexistent file"
-               "File exists, but cannot be read"))
+             "File exists, but cannot be read")
+            ((and error (file-symlink-p buffer-file-name))
+             "Symbolic link that points to nonexistent file")
             ((not buffer-read-only)
              (if (and warn
                       ;; No need to warn if buffer is auto-saved
@@ -2553,13 +2553,12 @@ unless NOMODES is non-nil."
             ((not error)
              (setq not-serious t)
              "Note: file is write protected")
-            ((file-attributes (directory-file-name default-directory))
+            ((file-accessible-directory-p default-directory)
              "File not found and directory write-protected")
-            ((file-exists-p (file-name-directory buffer-file-name))
-             (setq buffer-read-only nil))
             (t
              (setq buffer-read-only nil)
-             "Use M-x make-directory RET RET to create the directory and its 
parents"))))
+             (unless (file-directory-p default-directory)
+               "Use M-x make-directory RET RET to create the directory and its 
parents")))))
       (when msg
        (message "%s" msg)
        (or not-serious (sit-for 1 t))))
@@ -2726,6 +2725,7 @@ since only a single case-insensitive search through the 
alist is made."
      ("\\.scm\\.[0-9]*\\'" . scheme-mode)
      ("\\.[ckz]?sh\\'\\|\\.shar\\'\\|/\\.z?profile\\'" . sh-mode)
      ("\\.bash\\'" . sh-mode)
+     ("/PKGBUILD\\'" . sh-mode)
      
("\\(/\\|\\`\\)\\.\\(bash_\\(profile\\|history\\|log\\(in\\|out\\)\\)\\|z?log\\(in\\|out\\)\\)\\'"
 . sh-mode)
      
("\\(/\\|\\`\\)\\.\\(shrc\\|zshrc\\|m?kshrc\\|bashrc\\|t?cshrc\\|esrc\\)\\'" . 
sh-mode)
      ("\\(/\\|\\`\\)\\.\\([kz]shenv\\|xinitrc\\|startxrc\\|xsession\\)\\'" . 
sh-mode)
@@ -6237,11 +6237,6 @@ an auto-save file."
              "Cannot revert unreadable file %s")
            file-name))
    (t
-    ;; Bind buffer-file-name to nil
-    ;; so that we don't try to lock the file.
-    (let ((buffer-file-name nil))
-      (or auto-save-p
-          (unlock-buffer)))
     (widen)
     (let ((coding-system-for-read
            ;; Auto-saved file should be read by Emacs's
@@ -7863,9 +7858,22 @@ Otherwise, trash FILENAME using the freedesktop.org 
conventions,
 
               ;; Make a .trashinfo file.  Use O_EXCL, as per trash-spec 1.0.
               (let* ((files-base (file-name-nondirectory fn))
-                     (info-fn (expand-file-name
+                      (overwrite nil)
+                      info-fn)
+                 ;; We're checking further down whether the info file
+                 ;; exists, but the file name may exist in the trash
+                 ;; directory even if there is no info file for it.
+                 (when (file-exists-p
+                        (expand-file-name files-base trash-files-dir))
+                   (setq overwrite t
+                         files-base (file-name-nondirectory
+                                     (make-temp-file
+                                      (expand-file-name
+                                       files-base trash-files-dir)))))
+                (setq info-fn (expand-file-name
                                (concat files-base ".trashinfo")
-                               trash-info-dir)))
+                               trash-info-dir))
+                 ;; Re-check the existence (sort of).
                 (condition-case nil
                     (write-region nil nil info-fn nil 'quiet info-fn 'excl)
                   (file-already-exists
@@ -7881,7 +7889,7 @@ Otherwise, trash FILENAME using the freedesktop.org 
conventions,
                 ;; Finally, try to move the file to the trashcan.
                 (let ((delete-by-moving-to-trash nil)
                       (new-fn (expand-file-name files-base trash-files-dir)))
-                  (rename-file fn new-fn)))))))))
+                  (rename-file fn new-fn overwrite)))))))))
 
 (defsubst file-attribute-type (attributes)
   "The type field in ATTRIBUTES returned by `file-attributes'.
diff --git a/lisp/filesets.el b/lisp/filesets.el
index 2ef13ae..8e9fae8 100644
--- a/lisp/filesets.el
+++ b/lisp/filesets.el
@@ -90,7 +90,6 @@
 
 (require 'cl-lib)
 (require 'seq)
-(require 'easymenu)
 
 ;;; Some variables
 
@@ -1184,7 +1183,7 @@ Return full path if FULL-FLAG is non-nil."
      (constraint-flag
       (message "Obsolete :constraint-flag %S, use :constraintp instead"
                (cadr constraint-flag))
-      (eval (cadr constraint-flag)))
+      (eval (cadr constraint-flag) t))
      (t
       t))))
 
@@ -1558,18 +1557,20 @@ Replace <file-name> or <<file-name>> with filename."
                    (completing-read "Select fileset: " filesets-data nil t))))
     (when (and cmd-name name)
       (let* ((event (if (equal cmd-name "Grep <<selection>>")
-                      'on-grep
+                       'on-grep
                      'on-cmd))
             (files (if (and fileset
-                            (or (equal mode ':ingroup)
-                                (equal mode ':tree)))
+                            (or (equal mode :ingroup)
+                                (equal mode :tree)))
                        (filesets-get-filelist fileset mode event)
-                    (filesets-get-filelist
-                     (filesets-get-fileset-from-name name)
-                     mode event))))
+                     (filesets-get-filelist
+                      (filesets-get-fileset-from-name name)
+                      mode event))))
        (when files
          (let ((fn   (filesets-cmd-get-fn cmd-name))
-               (args (filesets-cmd-get-args cmd-name)))
+               (args
+                (dlet ((filesets--files files))
+                  (filesets-cmd-get-args cmd-name))))
            (if (memq fn '(multi-isearch-files multi-isearch-files-regexp))
                (apply fn args)
              (dolist (this files nil)
@@ -1578,28 +1579,27 @@ Replace <file-name> or <<file-name>> with filename."
                    (let ((buffer (filesets-find-file this)))
                      (when buffer
                        (goto-char (point-min))
-                       (progn
-                         (cond
-                          ((stringp fn)
-                           (let* ((args
-                                   (mapconcat
-                                    (lambda (this)
-                                      (filesets-run-cmd--repl-fn
-                                                      this
-                                                      (lambda (this)
-                                                        (format "%s" this))))
-                                    args
-                                    " "))
-                                  (cmd (concat fn " " args)))
-                             (filesets-cmd-show-result
-                              cmd (shell-command-to-string cmd))))
-                          ((symbolp fn)
-                           (apply fn
-                                  (mapcan (lambda (this)
-                                            (filesets-run-cmd--repl-fn
-                                             this
-                                             'list))
-                                          args)))))))))))))))))
+                       (cond
+                        ((stringp fn)
+                         (let* ((args
+                                 (mapconcat
+                                  (lambda (this)
+                                    (filesets-run-cmd--repl-fn
+                                     this
+                                     (lambda (this)
+                                       (format "%s" this))))
+                                  args
+                                  " "))
+                                (cmd (concat fn " " args)))
+                           (filesets-cmd-show-result
+                            cmd (shell-command-to-string cmd))))
+                        ((symbolp fn)
+                         (apply fn
+                                (mapcan (lambda (this)
+                                          (filesets-run-cmd--repl-fn
+                                           this
+                                           'list))
+                                        args))))))))))))))))
 
 (defun filesets-get-cmd-menu ()
   "Create filesets command menu."
@@ -1625,7 +1625,7 @@ Replace <file-name> or <<file-name>> with filename."
 
 (defun filesets-cmd-isearch-getargs ()
   "Get arguments for `multi-isearch-files' and `multi-isearch-files-regexp'."
-  (and (boundp 'files) (list files)))
+  (and (boundp 'filesets--files) (list filesets--files)))
 
 (defun filesets-cmd-shell-command-getargs ()
   "Get arguments for `filesets-cmd-shell-command'."
diff --git a/lisp/finder.el b/lisp/finder.el
index 15c3fcb..c2d5806 100644
--- a/lisp/finder.el
+++ b/lisp/finder.el
@@ -1,11 +1,10 @@
-;;; finder.el --- topic & keyword-based code finder
+;;; finder.el --- topic & keyword-based code finder  -*- lexical-binding: t -*-
 
 ;; Copyright (C) 1992, 1997-1999, 2001-2021 Free Software Foundation,
 ;; Inc.
 
 ;; Author: Eric S. Raymond <esr@snark.thyrsus.com>
 ;; Created: 16 Jun 1992
-;; Version: 1.0
 ;; Keywords: help
 
 ;; This file is part of GNU Emacs.
@@ -78,8 +77,7 @@
 Each element has the form (KEYWORD . DESCRIPTION).")
 
 (defvar finder-mode-map
-  (let ((map (make-sparse-keymap))
-       (menu-map (make-sparse-keymap "Finder")))
+  (let ((map (make-sparse-keymap)))
     (define-key map " "        'finder-select)
     (define-key map "f"        'finder-select)
     (define-key map [follow-link] 'mouse-face)
@@ -90,24 +88,21 @@ Each element has the form (KEYWORD . DESCRIPTION).")
     (define-key map "p" 'previous-line)
     (define-key map "q"        'finder-exit)
     (define-key map "d"        'finder-list-keywords)
-
-    (define-key map [menu-bar finder-mode]
-      (cons "Finder" menu-map))
-    (define-key menu-map [finder-exit]
-      '(menu-item "Quit" finder-exit
-                 :help "Exit Finder mode"))
-    (define-key menu-map [finder-summary]
-      '(menu-item "Summary" finder-summary
-                 :help "Summary item on current line in a finder buffer"))
-    (define-key menu-map [finder-list-keywords]
-      '(menu-item "List keywords" finder-list-keywords
-                 :help "Display descriptions of the keywords in the Finder 
buffer"))
-    (define-key menu-map [finder-select]
-      '(menu-item "Select" finder-select
-                 :help "Select item on current line in a finder buffer"))
     map)
   "Keymap used in `finder-mode'.")
 
+(easy-menu-define finder-mode-menu finder-mode-map
+  "Menu for `finder-mode'."
+  '("Finder"
+    ["Select" finder-select
+     :help "Select item on current line in a finder buffer"]
+    ["List keywords" finder-list-keywords
+     :help "Display descriptions of the keywords in the Finder buffer"]
+    ["Summary" finder-summary
+     :help "Summary item on current line in a finder buffer"]
+    ["Quit" finder-exit
+     :help "Exit Finder mode"]))
+
 (defvar finder-mode-syntax-table
   (let ((st (make-syntax-table emacs-lisp-mode-syntax-table)))
     (modify-syntax-entry ?\; ".   " st)
@@ -202,8 +197,7 @@ from; the default is `load-path'."
          (progress (make-progress-reporter
                     (byte-compile-info "Scanning files for finder")
                     0 (length files)))
-        package-override base-name ; processed
-        summary keywords package version entry desc)
+        base-name summary keywords package version entry desc)
     (dolist (elem files)
       (let* ((d (car elem))
              (f (cdr elem))
@@ -233,7 +227,7 @@ from; the default is `load-path'."
           ;;       (push base-name processed)
          (with-temp-buffer
            (insert-file-contents (expand-file-name f d))
-           (setq keywords (mapcar 'intern (lm-keywords-list))
+           (setq keywords (mapcar #'intern (lm-keywords-list))
                  package  (or package-override
                               (let ((str (lm-header "package")))
                                 (if str (intern str)))
@@ -293,7 +287,7 @@ from; the default is `load-path'."
 
 (defun finder-compile-keywords-make-dist ()
   "Regenerate `finder-inf.el' for the Emacs distribution."
-  (apply 'finder-compile-keywords command-line-args-left)
+  (apply #'finder-compile-keywords command-line-args-left)
   (kill-emacs))
 
 ;;; Now the retrieval code
@@ -302,7 +296,7 @@ from; the default is `load-path'."
   "Insert, at column COLUMN, other args STRINGS."
   (if (>= (current-column) column) (insert "\n"))
   (move-to-column column t)
-  (apply 'insert strings))
+  (apply #'insert strings))
 
 (defvar finder-help-echo nil)
 
@@ -319,7 +313,7 @@ from; the default is `load-path'."
                   (keys (nconc (where-is-internal
                                 'finder-mouse-select finder-mode-map)
                                keys1)))
-             (concat (mapconcat 'key-description keys ", ")
+             (concat (mapconcat #'key-description keys ", ")
                      ": select item"))))
     (add-text-properties
      (line-beginning-position) (line-end-position)
@@ -371,7 +365,7 @@ not `finder-known-keywords'."
 (define-button-type 'finder-xref 'action #'finder-goto-xref)
 
 (defun finder-goto-xref (button)
-  "Jump to a lisp file for the BUTTON at point."
+  "Jump to a Lisp file for the BUTTON at point."
   (let* ((file (button-get button 'xref))
          (lib (locate-library file)))
     (if lib (finder-commentary lib)
@@ -421,7 +415,7 @@ FILE should be in a form suitable for passing to 
`locate-library'."
 
 (defun finder-select ()
   "Select item on current line in a Finder buffer."
-  (interactive)
+  (interactive nil finder-mode)
   (let ((key (finder-current-item)))
       (if (string-match "\\.el$" key)
          (finder-commentary key)
@@ -437,6 +431,7 @@ FILE should be in a form suitable for passing to 
`locate-library'."
 ;;;###autoload
 (defun finder-by-keyword ()
   "Find packages matching a given keyword."
+  ;; FIXME: Why does this function exist?  Should it just be an alias?
   (interactive)
   (finder-list-keywords))
 
@@ -446,13 +441,14 @@ FILE should be in a form suitable for passing to 
`locate-library'."
 \\[finder-select]      more help for the item on the current line
 \\[finder-exit]        exit Finder mode and kill the Finder buffer."
   :syntax-table finder-mode-syntax-table
+  :interactive nil
   (setq buffer-read-only t
        buffer-undo-list t)
   (setq-local finder-headmark nil))
 
 (defun finder-summary ()
   "Summarize basic Finder commands."
-  (interactive)
+  (interactive nil finder-mode)
   (message "%s"
    (substitute-command-keys
     "\\<finder-mode-map>\\[finder-select] = select, \
@@ -462,7 +458,7 @@ finder directory, \\[finder-exit] = quit, 
\\[finder-summary] = help")))
 (defun finder-exit ()
   "Exit Finder mode.
 Quit the window and kill all Finder-related buffers."
-  (interactive)
+  (interactive nil finder-mode)
   (quit-window t)
   (dolist (buf (list finder-buffer "*Finder-package*"))
     (and (get-buffer buf) (kill-buffer buf))))
diff --git a/lisp/follow.el b/lisp/follow.el
index 0697587..56f06b1 100644
--- a/lisp/follow.el
+++ b/lisp/follow.el
@@ -25,7 +25,7 @@
 
 ;;; Commentary:
 
-;; `Follow mode' is a minor mode that combines windows into one tall
+;; `follow-mode' is a minor mode that combines windows into one tall
 ;; virtual window.
 ;;
 ;; The feeling of a "virtual window" has been accomplished by the use
@@ -81,7 +81,7 @@
 ;;   text.  Enter long lines spanning several lines, or several
 ;;   windows.
 ;;
-;; * Should you find `Follow' mode annoying, just type
+;; * Should you find Follow mode annoying, just type
 ;;     M-x follow-mode <RETURN>
 ;;   to turn it off.
 
@@ -93,25 +93,24 @@
 ;; key map.  To do so, add the following lines (replacing `[f7]' and
 ;; `[f8]' with your favorite keys) to the init file:
 ;;
-;; (global-set-key [f8] 'follow-mode)
-;; (global-set-key [f7] 'follow-delete-other-windows-and-split)
+;; (global-set-key [f8] #'follow-mode)
+;; (global-set-key [f7] #'follow-delete-other-windows-and-split)
 
 
 ;; There exist two system variables that control the appearance of
 ;; lines wider than the window containing them.  The default is to
 ;; truncate long lines whenever a window isn't as wide as the frame.
 ;;
-;; To make sure lines are never truncated, please place the following
-;; lines in your init file:
+;; To make sure lines are never truncated, place the following lines
+;; in your Init file:
 ;;
 ;; (setq truncate-lines nil)
 ;; (setq truncate-partial-width-windows nil)
 
 
-;; The correct way to configure Follow mode, or any other mode for
-;; that matter, is to create one or more functions that do
-;; whatever you would like to do.  These functions are then added to
-;; a hook.
+;; One way to configure Follow mode is to create one or more functions
+;; that do whatever you would like to do.  These functions are then
+;; added to a hook.
 ;;
 ;; The keymap `follow-mode-map' contains key bindings activated by
 ;; `follow-mode'.
@@ -120,8 +119,8 @@
 ;; (add-hook 'follow-mode-hook 'my-follow-mode-hook)
 ;;
 ;; (defun my-follow-mode-hook ()
-;;    (define-key follow-mode-map "\C-ca" 'your-favorite-function)
-;;    (define-key follow-mode-map "\C-cb" 'another-function))
+;;    (define-key follow-mode-map "\C-ca" #'your-favorite-function)
+;;    (define-key follow-mode-map "\C-cb" #'another-function))
 
 
 ;; Usage:
@@ -129,60 +128,60 @@
 ;; To activate, issue the command "M-x follow-mode"
 ;; and press Return.  To deactivate, do it again.
 ;;
-;; The following is a list of commands useful when follow-mode is active.
+;; The following is a list of commands useful when `follow-mode' is active.
 ;;
-;;     follow-scroll-up                         C-c . C-v
+;;     `follow-scroll-up'                       C-c . C-v
 ;;             Scroll text in a Follow mode window chain up.
 ;;
-;;     follow-scroll-down                       C-c . v
+;;     `follow-scroll-down'                     C-c . v
 ;;             Like `follow-scroll-up', but in the other direction.
 ;;
-;;     follow-delete-other-windows-and-split    C-c . 1
+;;     `follow-delete-other-windows-and-split'  C-c . 1
 ;;             Maximize the visible area of the current buffer,
-;;             and enter Follow mode.  This is a very convenient
+;;             and enter Follow mode.          This is a very convenient
 ;;             way to start Follow mode, hence we recommend that
 ;;             this command be added to the global keymap.
 ;;
-;;     follow-recenter                          C-c . C-l
+;;     `follow-recenter'                                C-c . C-l
 ;;             Place point in the center of the middle window,
 ;;             or a specified number of lines from either top or bottom.
 ;;
-;;     follow-switch-to-buffer                  C-c . b
+;;     `follow-switch-to-buffer'                        C-c . b
 ;;             Switch buffer in all windows displaying the current buffer
 ;;             in this frame.
 ;;
-;;     follow-switch-to-buffer-all              C-c . C-b
+;;     `follow-switch-to-buffer-all'            C-c . C-b
 ;;             Switch buffer in all windows in the selected frame.
 ;;
-;;     follow-switch-to-current-buffer-all
+;;     `follow-switch-to-current-buffer-all'
 ;;             Show the current buffer in all windows on the current
 ;;             frame and turn on `follow-mode'.
 ;;
-;;     follow-first-window                      C-c . <
+;;     `follow-first-window'                    C-c . <
 ;;             Select the first window in the frame showing the same buffer.
 ;;
-;;     follow-last-window                       C-c . >
+;;     `follow-last-window'                     C-c . >
 ;;             Select the last window in the frame showing the same buffer.
 ;;
-;;     follow-next-window                       C-c . n
+;;     `follow-next-window'                     C-c . n
 ;;             Select the next window in the frame showing the same buffer.
 ;;
-;;     follow-previous-window                   C-c . p
+;;     `follow-previous-window'                         C-c . p
 ;;             Select the previous window showing the same buffer.
 
 
 ;; Well, it seems ok, but what if I really want to look at two different
-;; positions in the text? Here are two simple methods to use:
+;; positions in the text?  Here are two simple methods to use:
 ;;
 ;; 1) Use multiple frames; `follow' mode only affects windows displayed
-;;    in the same frame. (My apologies to you who can't use frames.)
+;;    in the same frame.  (My apologies to you who can't use frames.)
 ;;
 ;; 2) Bind `follow-mode' to key so you can turn it off whenever
-;;    you want to view two locations.  Of course, `follow' mode can
+;;    you want to view two locations.  Of course, `follow-mode' can
 ;;    be reactivated by hitting the same key again.
 ;;
 ;;    Example from my ~/.emacs:
-;;     (global-set-key [f8] 'follow-mode)
+;;     (global-set-key [f8] #'follow-mode)
 
 ;; Implementation:
 ;;
@@ -201,7 +200,6 @@
 
 ;;; Code:
 
-(require 'easymenu)
 (eval-when-compile (require 'cl-lib))
 
 ;;; Variables
@@ -343,7 +341,7 @@ property `follow-mode-use-cache' to non-nil.")
 ;; Internal variables:
 
 (defvar follow-internal-force-redisplay nil
-  "True when Follow mode should redisplay the windows.")
+  "Non-nil when Follow mode should redisplay the windows.")
 
 (defvar follow-active-menu nil
   "The menu visible when Follow mode is active.")
@@ -1020,8 +1018,8 @@ returned by `follow-windows-start-end'."
       (setq win-start-end (cdr win-start-end)))
     result))
 
-;; Check if point is visible in all windows. (So that
-;; no one will be recentered.)
+;; Check if point is visible in all windows.
+;; (So that no one will be recentered.)
 
 (defun follow-point-visible-all-windows-p (win-start-end)
   "Non-nil when the `window-point' is visible in all windows."
@@ -1070,11 +1068,11 @@ Return the selected window."
     win))
 
 ;; Lets select a window showing the end. Make sure we only select it if
-;; it wasn't just moved here. (I.e. M-> shall not unconditionally place
+;; it wasn't just moved here.  (I.e. M-> shall not unconditionally place
 ;; point in the selected window.)
 ;;
 ;; (Compatibility kludge: in Emacs `window-end' is equal to `point-max';
-;; in XEmacs, it is equal to `point-max + 1'. Should I really bother
+;; in XEmacs, it is equal to `point-max + 1'.  Should I really bother
 ;; checking `window-end' now when I check `end-of-buffer' explicitly?)
 
 (defun follow-select-if-end-visible (win-start-end)
@@ -1098,7 +1096,7 @@ Return the selected window."
 
 
 ;; Select a window that will display point if the windows would
-;; be redisplayed with the first window fixed. This is useful for
+;; be redisplayed with the first window fixed.  This is useful for
 ;; example when the user has pressed return at the bottom of a window
 ;; as point is not visible in any window.
 
@@ -1203,7 +1201,7 @@ should be a member of WINDOWS, starts at position START."
       (goto-char guess)
       (while (not done)
        (if (not (= (vertical-motion 1 (car windows)) 1))
-           ;; Hit bottom! (Can we really do this?)
+            ;; Hit bottom!  (Can we really do this?)
            ;; We'll keep it, since it ensures termination.
            (progn
              (setq done t)
@@ -1284,7 +1282,7 @@ non-first windows in Follow mode."
 
 (defvar follow-prev-buffer nil
   "The buffer current at the last call to `follow-adjust-window' or nil.
-follow-mode is not necessarily enabled in this buffer.")
+`follow-mode' is not necessarily enabled in this buffer.")
 
 ;; This function is added to `pre-display-function' and is thus called
 ;; before each redisplay operation.  It supersedes (2018-09) the
@@ -1332,7 +1330,7 @@ follow-mode is not necessarily enabled in this buffer.")
 ;; .
 
 (defun follow-adjust-window (win)
-  ;; Adjust the window WIN and its followers.
+  "Adjust the window WIN and its followers."
   (cl-assert (eq (window-buffer win) (current-buffer)))
 
   ;; Have we moved out of or into a follow-mode window group?
@@ -1647,17 +1645,17 @@ This is updated by redisplay or by calling
 
 (defun follow-window-end (&optional window update)
   "Return position at which display currently ends in the Follow
-  Mode group of windows which includes WINDOW.
+Mode group of windows which includes WINDOW.
 
-  WINDOW must be a live window and defaults to the selected one.
-  This is updated by redisplay, when it runs to completion.
-  Simply changing the buffer text or setting `window-start' does
-  not update this value.
-
-  Return nil if there is no recorded value.  (This can happen if
-  the last redisplay of WINDOW was preempted, and did not
-  finish.)  If UPDATE is non-nil, compute the up-to-date position
-  if it isn't already recorded."
+WINDOW must be a live window and defaults to the selected one.
+This is updated by redisplay, when it runs to completion.
+Simply changing the buffer text or setting `window-start' does
+not update this value.
+
+Return nil if there is no recorded value.  (This can happen if
+the last redisplay of WINDOW was preempted, and did not
+finish.)  If UPDATE is non-nil, compute the up-to-date position
+if it isn't already recorded."
   (let* ((windows (follow-all-followers window))
          (last (car (last windows))))
     (when (and update follow-start-end-invalid)
@@ -1677,7 +1675,7 @@ overriding motion of point in order to display at this 
exact start."
 
 (defun follow-pos-visible-in-window-p (&optional pos window partially)
   "Return non-nil if position POS is currently on the frame in one of
-  the windows in the Follow Mode group which includes WINDOW.
+the windows in the Follow Mode group which includes WINDOW.
 
 WINDOW must be a live window and defaults to the selected one.
 
diff --git a/lisp/font-lock.el b/lisp/font-lock.el
index c344a61..82915d8 100644
--- a/lisp/font-lock.el
+++ b/lisp/font-lock.el
@@ -1120,6 +1120,18 @@ portion of the buffer."
     (funcall font-lock-ensure-function
              (or beg (point-min)) (or end (point-max)))))
 
+(defun font-lock-update (&optional arg)
+  "Updates the syntax highlighting in this buffer.
+Refontify the accessible portion of this buffer, or enable Font Lock mode
+in this buffer if it is currently disabled.  With prefix ARG, toggle Font
+Lock mode."
+  (interactive "P")
+  (save-excursion
+    (if (and (not arg) font-lock-mode)
+        (font-lock-fontify-region (point-min) (point-max))
+      (font-lock-unfontify-region (point-min) (point-max))
+      (font-lock-mode 'toggle))))
+
 (defun font-lock-default-fontify-buffer ()
   "Fontify the whole buffer using `font-lock-fontify-region-function'."
   (let ((verbose (if (numberp font-lock-verbose)
diff --git a/lisp/format.el b/lisp/format.el
index 4209fc6..3e2d92f 100644
--- a/lisp/format.el
+++ b/lisp/format.el
@@ -747,13 +747,17 @@ to write these unknown annotations back into the file."
 
            (if (numberp val)   ; add to ambient value if numeric
                (format-property-increment-region from to prop val 0)
-             (put-text-property
-              from to prop
-              (cond ((get prop 'format-list-valued) ; value gets consed onto
-                                                    ; list-valued properties
-                     (let ((prev (get-text-property from prop)))
-                       (cons val (if (listp prev) prev (list prev)))))
-                    (t val))))) ; normally, just set to val.
+              ;; Kludge alert: ignore items with reversed order of
+              ;; FROM and TO.  They seem to be redundant anyway, and
+              ;; in one case I've seen them refer to EOB.
+              (when (<= from to)
+               (put-text-property
+                from to prop
+                (cond ((get prop 'format-list-valued) ; value gets consed onto
+                                                      ; list-valued properties
+                       (let ((prev (get-text-property from prop)))
+                         (cons val (if (listp prev) prev (list prev)))))
+                      (t val)))))) ; normally, just set to val.
          (setq todo (cdr todo)))
 
        (if unknown-ans
diff --git a/lisp/frame.el b/lisp/frame.el
index ce4de83..2b6e4a6 100644
--- a/lisp/frame.el
+++ b/lisp/frame.el
@@ -367,6 +367,7 @@ there (in decreasing order of priority)."
       ;; by the lines added in x-create-frame for the tab-bar and
       ;; switch `tab-bar-mode' off.
       (when (display-graphic-p)
+        (declare-function tab-bar-height "xdisp.c" (&optional frame pixelwise))
        (let* ((init-lines
                (assq 'tab-bar-lines initial-frame-alist))
               (other-lines
@@ -708,9 +709,11 @@ Return nil if we don't know how to interpret DISPLAY."
 (defun make-frame-on-display (display &optional parameters)
   "Make a frame on display DISPLAY.
 The optional argument PARAMETERS specifies additional frame parameters."
-  (interactive (list (completing-read
-                      (format "Make frame on display: ")
-                      (x-display-list))))
+  (interactive (if (fboundp 'x-display-list)
+                   (list (completing-read
+                          (format "Make frame on display: ")
+                          (x-display-list)))
+                 (user-error "This Emacs build does not support X displays")))
   (make-frame (cons (cons 'display display) parameters)))
 
 (defun make-frame-on-current-monitor (&optional parameters)
@@ -1370,7 +1373,7 @@ FRAME defaults to the selected frame."
 FRAME defaults to the selected frame."
   (setq frame (window-normalize-frame frame))
   (- (frame-native-height frame)
-     (tab-bar-height frame t)
+     (if (fboundp 'tab-bar-height) (tab-bar-height frame t) 0)
      (* 2 (frame-internal-border-width frame))))
 
 (defun frame-outer-width (&optional frame)
@@ -2733,6 +2736,14 @@ See also `toggle-frame-maximized'."
 (make-obsolete-variable
  'window-system-version "it does not give useful information." "24.3")
 
+(defun set-frame-property--interactive (prompt number)
+  "Get a value for `set-frame-width' or `set-frame-height', prompting with 
PROMPT.
+Offer NUMBER as default value, if it is a natural number."
+  (if (and current-prefix-arg (not (consp current-prefix-arg)))
+      (list (selected-frame) (prefix-numeric-value current-prefix-arg))
+    (let ((default (and (natnump number) number)))
+      (list (selected-frame) (read-number prompt default)))))
+
 ;; Variables whose change of value should trigger redisplay of the
 ;; current buffer.
 ;; To test whether a given variable needs to be added to this list,
diff --git a/lisp/gnus/.dir-locals.el b/lisp/gnus/.dir-locals.el
deleted file mode 100644
index fb968e1..0000000
--- a/lisp/gnus/.dir-locals.el
+++ /dev/null
@@ -1,4 +0,0 @@
-((emacs-lisp-mode . ((show-trailing-whitespace . t))))
-;; Local Variables:
-;; no-byte-compile: t
-;; End:
diff --git a/lisp/gnus/deuglify.el b/lisp/gnus/deuglify.el
index 08beef7..e6c4630 100644
--- a/lisp/gnus/deuglify.el
+++ b/lisp/gnus/deuglify.el
@@ -310,7 +310,7 @@ You can control what lines will be unwrapped by frobbing
 `gnus-outlook-deuglify-unwrap-min' and `gnus-outlook-deuglify-unwrap-max',
 indicating the minimum and maximum length of an unwrapped citation line.  If
 NODISPLAY is non-nil, don't redisplay the article buffer."
-  (interactive "P")
+  (interactive "P" gnus-article-mode gnus-summary-mode)
   (let ((case-fold-search nil)
        (inhibit-read-only t)
        (cite-marks gnus-outlook-deuglify-cite-marks)
@@ -430,7 +430,7 @@ NODISPLAY is non-nil, don't redisplay the article buffer."
 (defun gnus-article-outlook-repair-attribution (&optional nodisplay)
   "Repair a broken attribution line.
 If NODISPLAY is non-nil, don't redisplay the article buffer."
-  (interactive "P")
+  (interactive "P" gnus-article-mode gnus-summary-mode)
   (let ((attrib-start
         (or
          (gnus-outlook-repair-attribution-other)
@@ -442,7 +442,7 @@ If NODISPLAY is non-nil, don't redisplay the article 
buffer."
 (defun gnus-article-outlook-rearrange-citation (&optional nodisplay)
   "Repair broken citations.
 If NODISPLAY is non-nil, don't redisplay the article buffer."
-  (interactive "P")
+  (interactive "P" gnus-article-mode gnus-summary-mode)
   (let ((attrib-start (gnus-article-outlook-repair-attribution 'nodisplay)))
     ;; rearrange citations if an attribution line has been recognized
     (if attrib-start
@@ -455,7 +455,7 @@ If NODISPLAY is non-nil, don't redisplay the article 
buffer."
 Treat \"smartquotes\", unwrap lines, repair attribution and
 rearrange citation.  If NODISPLAY is non-nil, don't redisplay the
 article buffer."
-  (interactive "P")
+  (interactive "P" gnus-article-mode gnus-summary-mode)
   ;; apply treatment of dumb quotes
   (gnus-article-treat-smartquotes)
   ;; repair wrapped cited lines
@@ -467,7 +467,7 @@ article buffer."
 ;;;###autoload
 (defun gnus-article-outlook-deuglify-article ()
   "Deuglify broken Outlook (Express) articles and redisplay."
-  (interactive)
+  (interactive nil gnus-article-mode gnus-summary-mode)
   (gnus-outlook-deuglify-article nil))
 
 (provide 'deuglify)
diff --git a/lisp/gnus/gnus-art.el b/lisp/gnus/gnus-art.el
index c9afa3a..c1071c1 100644
--- a/lisp/gnus/gnus-art.el
+++ b/lisp/gnus/gnus-art.el
@@ -728,9 +728,6 @@ Each element is a regular expression."
   :type '(repeat regexp)
   :group 'gnus-article-various)
 
-(make-obsolete-variable 'gnus-article-hide-pgp-hook nil
-                       "Gnus 5.10 (Emacs 22.1)")
-
 (defface gnus-button
   '((t (:weight bold)))
   "Face used for highlighting a button in the article buffer."
@@ -974,7 +971,7 @@ see http://www.cs.indiana.edu/picons/ftp/index.html";
   :version "22.1"
   :type '(repeat directory)
   :link '(url-link :tag "download"
-                  "http://www.cs.indiana.edu/picons/ftp/index.html";)
+                   "http://www.cs.indiana.edu/picons/ftp/index.html";)
   :link '(custom-manual "(gnus)Picons")
   :group 'gnus-picon)
 
@@ -1264,9 +1261,6 @@ Any symbol is used to look up a regular expression to 
match the
 banner in `gnus-list-identifiers'.  A string is used as a regular
 expression to match the identifier directly.")
 
-(make-obsolete-variable 'gnus-treat-strip-pgp nil
-                       "Gnus 5.10 (Emacs 22.1)")
-
 (defcustom gnus-treat-strip-pem nil
   "Strip PEM signatures.
 Valid values are nil, t, `head', `first', `last', an integer or a
@@ -1396,9 +1390,6 @@ predicate.  See Info node `(gnus)Customizing Articles'."
   :link '(custom-manual "(gnus)Customizing Articles")
   :type gnus-article-treat-custom)
 
-(make-obsolete-variable 'gnus-treat-display-xface
-                       'gnus-treat-display-x-face "Emacs 22.1")
-
 (defcustom gnus-treat-display-x-face
   (and (not noninteractive)
        (gnus-image-type-available-p 'xbm)
@@ -1423,17 +1414,7 @@ See Info node `(gnus)Customizing Articles' and Info node
          symbol
          (cond ((or (boundp symbol) (get symbol 'saved-value))
                 value)
-               ((boundp 'gnus-treat-display-xface)
-                (message "\
-** gnus-treat-display-xface is an obsolete variable;\
- use gnus-treat-display-x-face instead")
-                (default-value 'gnus-treat-display-xface))
-               ((get 'gnus-treat-display-xface 'saved-value)
-                (message "\
-** gnus-treat-display-xface is an obsolete variable;\
- use gnus-treat-display-x-face instead")
-                (eval (car (get 'gnus-treat-display-xface 'saved-value)) t))
-               (t
+                (t
                 value)))))
 (put 'gnus-treat-display-x-face 'highlight t)
 
@@ -1823,7 +1804,7 @@ Initialized from `text-mode-syntax-table'.")
 
 (defun article-hide-headers (&optional _arg _delete)
   "Hide unwanted headers and possibly sort them as well."
-  (interactive)
+  (interactive nil gnus-article-mode)
   ;; This function might be inhibited.
   (unless gnus-inhibit-hiding
     (let ((inhibit-read-only t)
@@ -1891,7 +1872,7 @@ Initialized from `text-mode-syntax-table'.")
   "Toggle hiding of headers that aren't very interesting.
 If given a negative prefix, always show; if given a positive prefix,
 always hide."
-  (interactive (gnus-article-hidden-arg))
+  (interactive (gnus-article-hidden-arg) gnus-article-mode)
   (when (and (not (gnus-article-check-hidden-text 'boring-headers arg))
             (not gnus-show-all-headers))
     (save-excursion
@@ -2050,7 +2031,7 @@ always hide."
 
 (defun article-normalize-headers ()
   "Make all header lines 40 characters long."
-  (interactive)
+  (interactive nil gnus-article-mode)
   (let ((inhibit-read-only t)
        column)
     (save-excursion
@@ -2086,7 +2067,7 @@ iso-8859-1 character map in an attempt to provide more 
quoting
 characters.  If you see something like \\222 or \\264 where
 you're expecting some kind of apostrophe or quotation mark, then
 try this wash."
-  (interactive)
+  (interactive nil gnus-article-mode)
   (article-translate-strings gnus-article-smartquotes-map))
 (define-obsolete-function-alias 'article-treat-dumbquotes
   #'article-treat-smartquotes "27.1")
@@ -2095,7 +2076,7 @@ try this wash."
 
 (defun article-treat-non-ascii ()
   "Translate many Unicode characters into their ASCII equivalents."
-  (interactive)
+  (interactive nil gnus-article-mode)
   (require 'org-entities)
   (let ((table (make-char-table nil)))
     (dolist (elem org-entities)
@@ -2138,7 +2119,7 @@ MAP is an alist where the elements are on the form 
(\"from\" \"to\")."
 
 (defun article-treat-overstrike ()
   "Translate overstrikes into bold text."
-  (interactive)
+  (interactive nil gnus-article-mode)
   (save-excursion
     (when (article-goto-body)
       (let ((inhibit-read-only t))
@@ -2166,7 +2147,7 @@ MAP is an alist where the elements are on the form 
(\"from\" \"to\")."
 
 (defun article-treat-ansi-sequences ()
   "Translate ANSI SGR control sequences into overlays or extents."
-  (interactive)
+  (interactive nil gnus-article-mode)
   (save-excursion
     (when (article-goto-body)
       (require 'ansi-color)
@@ -2178,7 +2159,7 @@ MAP is an alist where the elements are on the form 
(\"from\" \"to\")."
   "Unfold folded message headers.
 Only the headers that fit into the current window width will be
 unfolded."
-  (interactive)
+  (interactive nil gnus-article-mode gnus-summary-mode)
   (gnus-with-article-headers
     (let (length)
       (while (not (eobp))
@@ -2204,7 +2185,7 @@ unfolded."
 
 (defun gnus-article-treat-fold-headers ()
   "Fold message headers."
-  (interactive)
+  (interactive nil gnus-article-mode gnus-summary-mode)
   (gnus-with-article-headers
     (while (not (eobp))
       (save-restriction
@@ -2214,7 +2195,7 @@ unfolded."
 
 (defun gnus-treat-smiley ()
   "Toggle display of textual emoticons (\"smileys\") as small graphical icons."
-  (interactive)
+  (interactive nil gnus-article-mode gnus-summary-mode)
   (gnus-with-article-buffer
     (if (memq 'smiley gnus-article-wash-types)
        (gnus-delete-images 'smiley)
@@ -2227,7 +2208,7 @@ unfolded."
 
 (defun gnus-article-remove-images ()
   "Remove all images from the article buffer."
-  (interactive)
+  (interactive nil gnus-article-mode gnus-summary-mode)
   (gnus-with-article-buffer
     (save-restriction
       (widen)
@@ -2239,7 +2220,7 @@ unfolded."
 (defun gnus-article-show-images ()
   "Show any images that are in the HTML-rendered article buffer.
 This only works if the article in question is HTML."
-  (interactive)
+  (interactive nil gnus-article-mode gnus-summary-mode)
   (gnus-with-article-buffer
     (save-restriction
       (widen)
@@ -2255,7 +2236,7 @@ This only works if the article in question is HTML."
 
 (defun gnus-article-treat-fold-newsgroups ()
   "Fold the Newsgroups and Followup-To message headers."
-  (interactive)
+  (interactive nil gnus-article-mode gnus-summary-mode)
   (gnus-with-article-headers
     (while (gnus-article-goto-header "newsgroups\\|followup-to")
       (save-restriction
@@ -2279,7 +2260,7 @@ predicate.  See Info node `(gnus)Customizing Articles'."
 If ARG is non-nil and not a number, toggle
 `gnus-article-truncate-lines' too.  If ARG is a number, truncate
 long lines if and only if arg is positive."
-  (interactive "P")
+  (interactive "P" gnus-article-mode gnus-summary-mode)
   (cond
    ((and (numberp arg) (> arg 0))
     (setq gnus-article-truncate-lines t))
@@ -2298,7 +2279,7 @@ long lines if and only if arg is positive."
 
 (defun gnus-article-treat-body-boundary ()
   "Place a boundary line at the end of the headers."
-  (interactive)
+  (interactive nil gnus-article-mode gnus-summary-mode)
   (when (and gnus-body-boundary-delimiter
             (> (length gnus-body-boundary-delimiter) 0))
     (gnus-with-article-headers
@@ -2317,7 +2298,7 @@ long lines if and only if arg is positive."
   "Fill lines that are wider than the window width or `fill-column'.
 If WIDTH (interactively, the numeric prefix), use that as the
 fill width."
-  (interactive "P")
+  (interactive "P" gnus-article-mode)
   (save-excursion
     (let* ((inhibit-read-only t)
           (window-width (window-width (get-buffer-window (current-buffer))))
@@ -2341,7 +2322,7 @@ fill width."
 
 (defun article-capitalize-sentences ()
   "Capitalize the first word in each sentence."
-  (interactive)
+  (interactive nil gnus-article-mode)
   (save-excursion
     (let ((inhibit-read-only t)
          (paragraph-start "^[\n\^L]"))
@@ -2352,7 +2333,7 @@ fill width."
 
 (defun article-remove-cr ()
   "Remove trailing CRs and then translate remaining CRs into LFs."
-  (interactive)
+  (interactive nil gnus-article-mode)
   (save-excursion
     (let ((inhibit-read-only t))
       (goto-char (point-min))
@@ -2364,7 +2345,7 @@ fill width."
 
 (defun article-remove-trailing-blank-lines ()
   "Remove all trailing blank lines from the article."
-  (interactive)
+  (interactive nil gnus-article-mode)
   (save-excursion
     (let ((inhibit-read-only t))
       (goto-char (point-max))
@@ -2383,7 +2364,7 @@ fill width."
 
 (defun article-display-face (&optional force)
   "Display any Face headers in the header."
-  (interactive (list 'force))
+  (interactive (list 'force) gnus-article-mode gnus-summary-mode)
   (let ((wash-face-p buffer-read-only))
     (gnus-with-article-headers
       ;; When displaying parts, this function can be called several times on
@@ -2431,7 +2412,7 @@ fill width."
 
 (defun article-display-x-face (&optional force)
   "Look for an X-Face header and display it if present."
-  (interactive (list 'force))
+  (interactive (list 'force) gnus-article-mode gnus-summary-mode)
   (let ((wash-face-p buffer-read-only))        ;; When type `W f'
     (gnus-with-article-headers
       ;; Delete the old process, if any.
@@ -2493,7 +2474,7 @@ fill width."
 
 (defun article-decode-mime-words ()
   "Decode all MIME-encoded words in the article."
-  (interactive)
+  (interactive nil gnus-article-mode gnus-summary-mode)
   (gnus-with-article-buffer
     (let ((inhibit-point-motion-hooks t)
          (mail-parse-charset gnus-newsgroup-charset)
@@ -2505,7 +2486,7 @@ fill width."
 (defun article-decode-charset (&optional prompt)
   "Decode charset-encoded text in the article.
 If PROMPT (the prefix), prompt for a coding system to use."
-  (interactive "P")
+  (interactive "P" gnus-article-mode)
   (let ((inhibit-point-motion-hooks t) (case-fold-search t)
        (inhibit-read-only t)
        (mail-parse-charset gnus-newsgroup-charset)
@@ -2627,7 +2608,7 @@ Mail-Reply-To: and Mail-Followup-To:."
 If FORCE, decode the article whether it is marked as quoted-printable
 or not.
 If READ-CHARSET, ask for a coding system."
-  (interactive (list 'force current-prefix-arg))
+  (interactive (list 'force current-prefix-arg) gnus-article-mode)
   (save-excursion
     (let ((inhibit-read-only t) type charset)
       (if (gnus-buffer-live-p gnus-original-article-buffer)
@@ -2655,7 +2636,7 @@ If READ-CHARSET, ask for a coding system."
   "Translate a base64 article.
 If FORCE, decode the article whether it is marked as base64 not.
 If READ-CHARSET, ask for a coding system."
-  (interactive (list 'force current-prefix-arg))
+  (interactive (list 'force current-prefix-arg) gnus-article-mode)
   (save-excursion
     (let ((inhibit-read-only t) type charset)
       (if (gnus-buffer-live-p gnus-original-article-buffer)
@@ -2687,7 +2668,7 @@ If READ-CHARSET, ask for a coding system."
 
 (defun article-decode-HZ ()
   "Translate a HZ-encoded article."
-  (interactive)
+  (interactive nil gnus-article-mode)
   (require 'rfc1843)
   (save-excursion
     (let ((inhibit-read-only t))
@@ -2695,7 +2676,7 @@ If READ-CHARSET, ask for a coding system."
 
 (defun article-unsplit-urls ()
   "Remove the newlines that some other mailers insert into URLs."
-  (interactive)
+  (interactive nil gnus-article-mode)
   (save-excursion
     (let ((inhibit-read-only t))
       (goto-char (point-min))
@@ -2707,7 +2688,7 @@ If READ-CHARSET, ask for a coding system."
 
 (defun article-wash-html ()
   "Format an HTML article."
-  (interactive)
+  (interactive nil gnus-article-mode)
   (let ((handles nil)
        (inhibit-read-only t))
     (when (gnus-buffer-live-p gnus-original-article-buffer)
@@ -3041,7 +3022,7 @@ This command creates temporary files to pass HTML 
contents including
 images if any to the browser, and deletes them when exiting the group
 \(if you want)."
   ;; Cf. `mm-w3m-safe-url-regexp'
-  (interactive "P")
+  (interactive "P" gnus-article-mode)
   (if arg
       (gnus-summary-show-article)
     (let ((gnus-visible-headers
@@ -3078,7 +3059,7 @@ images if any to the browser, and deletes them when 
exiting the group
 (defun article-hide-list-identifiers ()
   "Remove list identifiers from the Subject header.
 The `gnus-list-identifiers' variable specifies what to do."
-  (interactive)
+  (interactive nil gnus-article-mode)
   (let ((inhibit-point-motion-hooks t)
         (regexp (gnus-group-get-list-identifiers gnus-newsgroup-name))
         (inhibit-read-only t))
@@ -3100,7 +3081,7 @@ The `gnus-list-identifiers' variable specifies what to 
do."
   "Toggle hiding of any PEM headers and signatures in the current article.
 If given a negative prefix, always show; if given a positive prefix,
 always hide."
-  (interactive (gnus-article-hidden-arg))
+  (interactive (gnus-article-hidden-arg) gnus-article-mode)
   (unless (gnus-article-check-hidden-text 'pem arg)
     (save-excursion
       (let ((inhibit-read-only t) end)
@@ -3126,7 +3107,7 @@ always hide."
 (defun article-strip-banner ()
   "Strip the banners specified by the `banner' group parameter and by
 `gnus-article-address-banner-alist'."
-  (interactive)
+  (interactive nil gnus-article-mode)
   (save-excursion
     (save-restriction
       (let ((inhibit-point-motion-hooks t))
@@ -3175,7 +3156,7 @@ always hide."
 
 (defun article-babel ()
   "Translate article using an online translation service."
-  (interactive)
+  (interactive nil gnus-article-mode gnus-summary-mode)
   (require 'babel)
   (gnus-with-article-buffer
     (when (article-goto-body)
@@ -3192,7 +3173,7 @@ always hide."
   "Hide the signature in the current article.
 If given a negative prefix, always show; if given a positive prefix,
 always hide."
-  (interactive (gnus-article-hidden-arg))
+  (interactive (gnus-article-hidden-arg) gnus-article-mode)
   (unless (gnus-article-check-hidden-text 'signature arg)
     (save-excursion
       (save-restriction
@@ -3204,7 +3185,7 @@ always hide."
 
 (defun article-strip-headers-in-body ()
   "Strip offensive headers from bodies."
-  (interactive)
+  (interactive nil gnus-article-mode)
   (save-excursion
     (article-goto-body)
     (let ((case-fold-search t))
@@ -3213,7 +3194,7 @@ always hide."
 
 (defun article-strip-leading-blank-lines ()
   "Remove all blank lines from the beginning of the article."
-  (interactive)
+  (interactive nil gnus-article-mode)
   (save-excursion
     (let ((inhibit-point-motion-hooks t)
          (inhibit-read-only t))
@@ -3255,7 +3236,7 @@ Point is left at the beginning of the narrowed-to region."
 
 (defun article-strip-multiple-blank-lines ()
   "Replace consecutive blank lines with one empty line."
-  (interactive)
+  (interactive nil gnus-article-mode)
   (save-excursion
     (let ((inhibit-point-motion-hooks t)
          (inhibit-read-only t))
@@ -3274,7 +3255,7 @@ Point is left at the beginning of the narrowed-to region."
 
 (defun article-strip-leading-space ()
   "Remove all white space from the beginning of the lines in the article."
-  (interactive)
+  (interactive nil gnus-article-mode)
   (save-excursion
     (let ((inhibit-point-motion-hooks t)
          (inhibit-read-only t))
@@ -3284,7 +3265,7 @@ Point is left at the beginning of the narrowed-to region."
 
 (defun article-strip-trailing-space ()
   "Remove all white space from the end of the lines in the article."
-  (interactive)
+  (interactive nil gnus-article-mode)
   (save-excursion
     (let ((inhibit-point-motion-hooks t)
          (inhibit-read-only t))
@@ -3294,14 +3275,14 @@ Point is left at the beginning of the narrowed-to 
region."
 
 (defun article-strip-blank-lines ()
   "Strip leading, trailing and multiple blank lines."
-  (interactive)
+  (interactive nil gnus-article-mode)
   (article-strip-leading-blank-lines)
   (article-remove-trailing-blank-lines)
   (article-strip-multiple-blank-lines))
 
 (defun article-strip-all-blank-lines ()
   "Strip all blank lines."
-  (interactive)
+  (interactive nil gnus-article-mode)
   (save-excursion
     (let ((inhibit-point-motion-hooks t)
          (inhibit-read-only t))
@@ -3433,7 +3414,7 @@ lines forward."
   "Convert DATE date to TYPE in the current article.
 The default type is `ut'.  See `gnus-article-date-headers' for
 possible values."
-  (interactive (list 'ut t))
+  (interactive (list 'ut t) gnus-article-mode)
   (let* ((case-fold-search t)
         (inhibit-read-only t)
         (inhibit-point-motion-hooks t)
@@ -3677,29 +3658,29 @@ possible values."
 
 (defun article-date-local (&optional highlight)
   "Convert the current article date to the local timezone."
-  (interactive (list t))
+  (interactive (list t) gnus-article-mode)
   (article-date-ut 'local highlight))
 
 (defun article-date-english (&optional highlight)
   "Convert the current article date to something that is proper English."
-  (interactive (list t))
+  (interactive (list t) gnus-article-mode)
   (article-date-ut 'english highlight))
 
 (defun article-date-original (&optional highlight)
   "Convert the current article date to what it was originally.
 This is only useful if you have used some other date conversion
 function and want to see what the date was before converting."
-  (interactive (list t))
+  (interactive (list t) gnus-article-mode)
   (article-date-ut 'original highlight))
 
 (defun article-date-lapsed (&optional highlight)
   "Convert the current article date to time lapsed since it was sent."
-  (interactive (list t))
+  (interactive (list t) gnus-article-mode)
   (article-date-ut 'lapsed highlight))
 
 (defun article-date-combined-lapsed (&optional highlight)
   "Convert the current article date to time lapsed since it was sent."
-  (interactive (list t))
+  (interactive (list t) gnus-article-mode)
   (article-date-ut 'combined-lapsed highlight))
 
 (defun article-update-date-lapsed ()
@@ -3748,7 +3729,7 @@ function and want to see what the date was before 
converting."
   "Start a timer to update the Date headers in the article buffers.
 The numerical prefix says how frequently (in seconds) the function
 is to run."
-  (interactive "p")
+  (interactive "p" gnus-article-mode)
   (unless n
     (setq n 1))
   (gnus-stop-date-timer)
@@ -3757,7 +3738,7 @@ is to run."
 
 (defun gnus-stop-date-timer ()
   "Stop the Date timer."
-  (interactive)
+  (interactive nil gnus-article-mode)
   (when article-lapsed-timer
     (cancel-timer article-lapsed-timer)
     (setq article-lapsed-timer nil)))
@@ -3765,12 +3746,12 @@ is to run."
 (defun article-date-user (&optional highlight)
   "Convert the current article date to the user-defined format.
 This format is defined by the `gnus-article-time-format' variable."
-  (interactive (list t))
+  (interactive (list t) gnus-article-mode)
   (article-date-ut 'user-defined highlight))
 
 (defun article-date-iso8601 (&optional highlight)
   "Convert the current article date to ISO8601."
-  (interactive (list t))
+  (interactive (list t) gnus-article-mode)
   (article-date-ut 'iso8601 highlight))
 
 (defmacro gnus-article-save-original-date (&rest forms)
@@ -3803,7 +3784,7 @@ This format is defined by the `gnus-article-time-format' 
variable."
 
 (defun article-remove-leading-whitespace ()
   "Remove excessive whitespace from all headers."
-  (interactive)
+  (interactive nil gnus-article-mode)
   (save-excursion
     (save-restriction
       (let ((inhibit-read-only t))
@@ -3814,7 +3795,7 @@ This format is defined by the `gnus-article-time-format' 
variable."
 
 (defun article-emphasize (&optional arg)
   "Emphasize text according to `gnus-emphasis-alist'."
-  (interactive (gnus-article-hidden-arg))
+  (interactive (gnus-article-hidden-arg) gnus-article-mode)
   (unless (gnus-article-check-hidden-text 'emphasis arg)
     (save-excursion
       (let ((alist (or
@@ -4247,7 +4228,7 @@ If variable `gnus-use-long-file-name' is non-nil, it is
 (defun article-verify-x-pgp-sig ()
   "Verify X-PGP-Sig."
   ;; <https://ftp.isc.org/pub/pgpcontrol/FORMAT>
-  (interactive)
+  (interactive nil gnus-article-mode)
   (if (gnus-buffer-live-p gnus-original-article-buffer)
       (let ((sig (with-current-buffer gnus-original-article-buffer
                   (gnus-fetch-field "X-PGP-Sig")))
@@ -4321,7 +4302,7 @@ If variable `gnus-use-long-file-name' is non-nil, it is
 
 (defun article-verify-cancel-lock ()
   "Verify Cancel-Lock header."
-  (interactive)
+  (interactive nil gnus-article-mode)
   (if (gnus-buffer-live-p gnus-original-article-buffer)
       (canlock-verify gnus-original-article-buffer)))
 
@@ -4330,7 +4311,7 @@ If variable `gnus-use-long-file-name' is non-nil, it is
            `(defun ,(intern (format "gnus-%s" func))
                 (&optional interactive &rest args)
               ,(format "Run `%s' in the article buffer." func)
-              (interactive (list t))
+              (interactive (list t) gnus-article-mode gnus-summary-mode)
               (with-current-buffer gnus-article-buffer
                 (if interactive
                     (call-interactively #',func)
@@ -4752,7 +4733,7 @@ If ALL-HEADERS is non-nil, no headers are hidden."
 (defun gnus-sticky-article (arg)
   "Make the current article sticky.
 If a prefix ARG is given, ask for a name for this sticky article buffer."
-  (interactive "P")
+  (interactive "P" gnus-article-mode gnus-summary-mode)
   (gnus-summary-show-thread)
   (gnus-summary-select-article nil nil 'pseudo)
   (let (new-art-buf-name)
@@ -4796,7 +4777,7 @@ If a prefix ARG is given, ask for a name for this sticky 
article buffer."
   "Kill the given sticky article BUFFER.
 If none is given, assume the current buffer and kill it if it has
 `gnus-sticky-article-mode'."
-  (interactive)
+  (interactive nil gnus-article-mode)
   (unless buffer
     (setq buffer (current-buffer)))
   (with-current-buffer buffer
@@ -4806,7 +4787,7 @@ If none is given, assume the current buffer and kill it 
if it has
 (defun gnus-kill-sticky-article-buffers (arg)
   "Kill all sticky article buffers.
 If a prefix ARG is given, ask for confirmation."
-  (interactive "P")
+  (interactive "P" gnus-article-mode)
   (dolist (buf (gnus-buffers))
     (with-current-buffer buf
       (and (derived-mode-p 'gnus-sticky-article-mode)
@@ -4948,7 +4929,7 @@ General format specifiers can also be used.  See Info node
 
 (defun gnus-mime-view-all-parts (&optional handles)
   "View all the MIME parts."
-  (interactive)
+  (interactive nil gnus-article-mode)
   (with-current-buffer gnus-article-buffer
     (let ((handles (or handles gnus-article-mime-handles))
          (mail-parse-charset gnus-newsgroup-charset)
@@ -4965,7 +4946,7 @@ General format specifiers can also be used.  See Info node
 
 (defun gnus-article-jump-to-part (n)
   "Jump to MIME part N."
-  (interactive "P")
+  (interactive "P" gnus-article-mode)
   (let ((parts (with-current-buffer gnus-article-buffer
                 (length gnus-article-mime-handle-alist))))
     (when (zerop parts)
@@ -5061,11 +5042,11 @@ and `gnus-mime-delete-part', and not provided at 
run-time normally."
 (defun gnus-mime-replace-part (file)
   "Replace MIME part under point with an external body."
   ;; Useful if file has already been saved to disk
-  (interactive
-   (list
-    (read-file-name "Replace MIME part with file: "
-                    (or mm-default-directory default-directory)
-                    nil t)))
+  (interactive (list
+               (read-file-name "Replace MIME part with file: "
+                               (or mm-default-directory default-directory)
+                               nil t))
+              gnus-article-mode)
   (unless (file-regular-p (file-truename file))
     (error "Can't replace part with %s, which isn't a regular file"
           file))
@@ -5074,7 +5055,7 @@ and `gnus-mime-delete-part', and not provided at run-time 
normally."
 (defun gnus-mime-save-part-and-strip (&optional file event)
   "Save the MIME part under point then replace it with an external body.
 If FILE is given, use it for the external part."
-  (interactive (list nil last-nonmenu-event))
+  (interactive (list nil last-nonmenu-event) gnus-article-mode)
   (save-excursion
     (mouse-set-point event)
     (gnus-article-check-buffer)
@@ -5116,7 +5097,7 @@ The current article has a complicated MIME structure, 
giving up..."))
 (defun gnus-mime-delete-part (&optional event)
   "Delete the MIME part under point.
 Replace it with some information about the removed part."
-  (interactive (list last-nonmenu-event))
+  (interactive (list last-nonmenu-event) gnus-article-mode)
   (mouse-set-point event)
   (gnus-article-check-buffer)
   (when (gnus-group-read-only-p)
@@ -5165,7 +5146,7 @@ Deleting parts may malfunction or destroy the article; 
continue? "))
 
 (defun gnus-mime-save-part (&optional event)
   "Save the MIME part under point."
-  (interactive (list last-nonmenu-event))
+  (interactive (list last-nonmenu-event) gnus-article-mode)
   (mouse-set-point event)
   (gnus-article-check-buffer)
   (let ((data (get-text-property (point) 'gnus-data)))
@@ -5175,7 +5156,7 @@ Deleting parts may malfunction or destroy the article; 
continue? "))
 (defun gnus-mime-pipe-part (&optional cmd event)
   "Pipe the MIME part under point to a process.
 Use CMD as the process."
-  (interactive (list nil last-nonmenu-event))
+  (interactive (list nil last-nonmenu-event) gnus-article-mode)
   (mouse-set-point event)
   (gnus-article-check-buffer)
   (let ((data (get-text-property (point) 'gnus-data)))
@@ -5184,7 +5165,7 @@ Use CMD as the process."
 
 (defun gnus-mime-view-part (&optional event)
   "Interactively choose a viewing method for the MIME part under point."
-  (interactive (list last-nonmenu-event))
+  (interactive (list last-nonmenu-event) gnus-article-mode)
   (save-excursion
     (mouse-set-point event)
     (gnus-article-check-buffer)
@@ -5214,7 +5195,7 @@ Use CMD as the process."
   "Choose a MIME media type, and view the part as such.
 If non-nil, PRED is a predicate to use during completion to limit the
 available media-types."
-  (interactive (list nil nil last-nonmenu-event))
+  (interactive (list nil nil last-nonmenu-event) gnus-article-mode)
   (save-excursion
     (if event (mouse-set-point event))
     (unless mime-type
@@ -5253,7 +5234,8 @@ available media-types."
   "Put the MIME part under point into a new buffer.
 If `auto-compression-mode' is enabled, compressed files like .gz and .bz2
 are decompressed."
-  (interactive (list nil current-prefix-arg last-nonmenu-event))
+  (interactive (list nil current-prefix-arg last-nonmenu-event)
+              gnus-article-mode)
   (mouse-set-point event)
   (gnus-article-check-buffer)
   (unless handle
@@ -5309,7 +5291,8 @@ are decompressed."
 (defun gnus-mime-print-part (&optional handle filename event)
   "Print the MIME part under point."
   (interactive
-   (list nil (ps-print-preprint current-prefix-arg) last-nonmenu-event))
+   (list nil (ps-print-preprint current-prefix-arg) last-nonmenu-event)
+   gnus-article-mode)
   (save-excursion
     (mouse-set-point event)
     (gnus-article-check-buffer)
@@ -5337,7 +5320,8 @@ are decompressed."
 (defun gnus-mime-inline-part (&optional handle arg event)
   "Insert the MIME part under point into the current buffer.
 Compressed files like .gz and .bz2 are decompressed."
-  (interactive (list nil current-prefix-arg last-nonmenu-event))
+  (interactive (list nil current-prefix-arg last-nonmenu-event)
+              gnus-article-mode)
   (if event (mouse-set-point event))
   (gnus-article-check-buffer)
   (let* ((inhibit-read-only t)
@@ -5435,7 +5419,8 @@ CHARSET may either be a string or a symbol."
 (defun gnus-mime-view-part-as-charset (&optional handle arg event)
   "Insert the MIME part under point into the current buffer using the
 specified charset."
-  (interactive (list nil current-prefix-arg last-nonmenu-event))
+  (interactive (list nil current-prefix-arg last-nonmenu-event)
+              gnus-article-mode)
   (save-excursion
     (mouse-set-point event)
     (gnus-article-check-buffer)
@@ -5475,7 +5460,7 @@ specified charset."
 
 (defun gnus-mime-view-part-externally (&optional handle event)
   "View the MIME part under point with an external viewer."
-  (interactive (list nil last-nonmenu-event))
+  (interactive (list nil last-nonmenu-event) gnus-article-mode)
   (save-excursion
     (mouse-set-point event)
     (gnus-article-check-buffer)
@@ -5497,7 +5482,7 @@ specified charset."
 (defun gnus-mime-view-part-internally (&optional handle event)
   "View the MIME part under point with an internal viewer.
 If no internal viewer is available, use an external viewer."
-  (interactive (list nil last-nonmenu-event))
+  (interactive (list nil last-nonmenu-event) gnus-article-mode)
   (save-excursion
     (mouse-set-point event)
     (gnus-article-check-buffer)
@@ -5518,7 +5503,9 @@ If no internal viewer is available, use an external 
viewer."
 (defun gnus-mime-action-on-part (&optional action)
   "Do something with the MIME attachment at (point)."
   (interactive
-   (list (gnus-completing-read "Action" (mapcar #'car gnus-mime-action-alist) 
t)))
+   (list (gnus-completing-read
+         "Action" (mapcar #'car gnus-mime-action-alist) t))
+   gnus-article-mode)
   (gnus-article-check-buffer)
   (let ((action-pair (assoc action gnus-mime-action-alist)))
     (if action-pair
@@ -5611,62 +5598,62 @@ If INTERACTIVE, call FUNCTION interactively."
 
 (defun gnus-article-pipe-part (n)
   "Pipe MIME part N, which is the numerical prefix."
-  (interactive "P")
+  (interactive "P" gnus-article-mode)
   (gnus-article-part-wrapper n 'mm-pipe-part))
 
 (defun gnus-article-save-part (n)
   "Save MIME part N, which is the numerical prefix."
-  (interactive "P")
+  (interactive "P" gnus-article-mode)
   (gnus-article-part-wrapper n 'mm-save-part))
 
 (defun gnus-article-interactively-view-part (n)
   "View MIME part N interactively, which is the numerical prefix."
-  (interactive "P")
+  (interactive "P" gnus-article-mode)
   (gnus-article-part-wrapper n 'mm-interactively-view-part))
 
 (defun gnus-article-copy-part (n)
   "Copy MIME part N, which is the numerical prefix."
-  (interactive "P")
+  (interactive "P" gnus-article-mode)
   (gnus-article-part-wrapper n 'gnus-mime-copy-part))
 
 (defun gnus-article-view-part-as-charset (n)
   "View MIME part N using a specified charset.
 N is the numerical prefix."
-  (interactive "P")
+  (interactive "P" gnus-article-mode)
   (gnus-article-part-wrapper n 'gnus-mime-view-part-as-charset))
 
 (defun gnus-article-view-part-externally (n)
   "View MIME part N externally, which is the numerical prefix."
-  (interactive "P")
+  (interactive "P" gnus-article-mode)
   (gnus-article-part-wrapper n 'gnus-mime-view-part-externally))
 
 (defun gnus-article-inline-part (n)
   "Inline MIME part N, which is the numerical prefix."
-  (interactive "P")
+  (interactive "P" gnus-article-mode)
   (gnus-article-part-wrapper n 'gnus-mime-inline-part))
 
 (defun gnus-article-save-part-and-strip (n)
   "Save MIME part N and replace it with an external body.
 N is the numerical prefix."
-  (interactive "P")
+  (interactive "P" gnus-article-mode)
   (gnus-article-part-wrapper n 'gnus-mime-save-part-and-strip t))
 
 (defun gnus-article-replace-part (n)
   "Replace MIME part N with an external body.
 N is the numerical prefix."
-  (interactive "P")
+  (interactive "P" gnus-article-mode)
   (gnus-article-part-wrapper n 'gnus-mime-replace-part t t))
 
 (defun gnus-article-delete-part (n)
   "Delete MIME part N and add some information about the removed part.
 N is the numerical prefix."
-  (interactive "P")
+  (interactive "P" gnus-article-mode)
   (gnus-article-part-wrapper n 'gnus-mime-delete-part t))
 
 (defun gnus-article-view-part-as-type (n)
   "Choose a MIME media type, and view part N as such.
 N is the numerical prefix."
-  (interactive "P")
+  (interactive "P" gnus-article-mode)
   (gnus-article-part-wrapper n 'gnus-mime-view-part-as-type t))
 
 (defun gnus-article-mime-match-handle-first (condition)
@@ -5693,7 +5680,7 @@ N is the numerical prefix."
   "View MIME part N, which is the numerical prefix.
 If the part is already shown, hide the part.  If N is nil, view
 all parts."
-  (interactive "P")
+  (interactive "P" gnus-article-mode gnus-summary-mode)
   (with-current-buffer gnus-article-buffer
     (or (numberp n) (setq n (gnus-article-mime-match-handle-first
                             gnus-article-mime-match-handle-function)))
@@ -6383,7 +6370,7 @@ Provided for backwards compatibility."
 This function toggles the display when called interactively.  Note that
 buttons to be added to the header are only the ones that aren't inlined
 in the body.  Use `gnus-header-face-alist' to highlight buttons."
-  (interactive (list t))
+  (interactive (list t) gnus-article-mode gnus-summary-mode)
   (gnus-with-article-buffer
     (let ((case-fold-search t) buttons st)
       (save-excursion
@@ -6488,7 +6475,7 @@ the coding cookie."
 (defun gnus-narrow-to-page (&optional arg)
   "Narrow the article buffer to a page.
 If given a numerical ARG, move forward ARG pages."
-  (interactive "P")
+  (interactive "P" gnus-article-mode)
   (setq arg (if arg (prefix-numeric-value arg) 0))
   (with-current-buffer gnus-article-buffer
     (widen)
@@ -6541,7 +6528,7 @@ If given a numerical ARG, move forward ARG pages."
 
 (defun gnus-article-goto-next-page ()
   "Show the next page of the article."
-  (interactive)
+  (interactive nil gnus-article-mode)
   (when (gnus-article-next-page)
     (goto-char (point-min))
     (gnus-article-read-summary-keys nil ?n)))
@@ -6549,7 +6536,7 @@ If given a numerical ARG, move forward ARG pages."
 
 (defun gnus-article-goto-prev-page ()
   "Show the previous page of the article."
-  (interactive)
+  (interactive nil gnus-article-mode)
   (if (save-restriction (widen) (bobp)) ;; Real beginning-of-buffer?
       (gnus-article-read-summary-keys nil ?p)
     (gnus-article-prev-page nil)))
@@ -6572,7 +6559,7 @@ If given a numerical ARG, move forward ARG pages."
   "Show the next page of the current article.
 If end of article, return non-nil.  Otherwise return nil.
 Argument LINES specifies lines to be scrolled up."
-  (interactive "p")
+  (interactive "p" gnus-article-mode)
   (move-to-window-line (- -1 scroll-margin))
   (if (and (not (and gnus-article-over-scroll
                     (> (count-lines (window-start) (point-max))
@@ -6628,7 +6615,7 @@ specifies."
 (defun gnus-article-prev-page (&optional lines)
   "Show previous page of current article.
 Argument LINES specifies lines to be scrolled down."
-  (interactive "p")
+  (interactive "p" gnus-article-mode)
   (move-to-window-line 0)
   (if (and gnus-page-broken
           (bobp)
@@ -6669,7 +6656,7 @@ not have a face in `gnus-article-boring-faces'."
 
 (defun gnus-article-refer-article ()
   "Read article specified by message-id around point."
-  (interactive)
+  (interactive nil gnus-article-mode)
   (save-excursion
     (re-search-backward "[ \t]\\|^" (point-at-bol) t)
     (re-search-forward "<?news:<?\\|<" (point-at-eol) t)
@@ -6681,7 +6668,7 @@ not have a face in `gnus-article-boring-faces'."
 
 (defun gnus-article-show-summary ()
   "Reconfigure windows to show summary buffer."
-  (interactive)
+  (interactive nil gnus-article-mode)
   (if (not (gnus-buffer-live-p gnus-summary-buffer))
       (error "There is no summary buffer for this article buffer")
     (gnus-article-set-globals)
@@ -6691,7 +6678,7 @@ not have a face in `gnus-article-boring-faces'."
 
 (defun gnus-article-describe-briefly ()
   "Describe article mode commands briefly."
-  (interactive)
+  (interactive nil gnus-article-mode)
   (gnus-message 6 "%s" (substitute-command-keys 
"\\<gnus-article-mode-map>\\[gnus-article-goto-next-page]:Next page     
\\[gnus-article-goto-prev-page]:Prev page  \\[gnus-article-show-summary]:Show 
summary  \\[gnus-info-find-node]:Run Info  
\\[gnus-article-describe-briefly]:This help")))
 
 (defun gnus-article-check-buffer ()
@@ -6703,7 +6690,7 @@ not have a face in `gnus-article-boring-faces'."
 
 (defun gnus-article-read-summary-keys (&optional _arg key not-restore-window)
   "Read a summary buffer key sequence and execute it from the article buffer."
-  (interactive "P")
+  (interactive "P" gnus-article-mode)
   (gnus-article-check-buffer)
   (let ((nosaves
         '("q" "Q" "r" "m"  "a" "f" "WDD" "WDW"
@@ -6814,7 +6801,7 @@ not have a face in `gnus-article-boring-faces'."
            (ding))))))))
 
 (defun gnus-article-read-summary-send-keys ()
-  (interactive)
+  (interactive nil gnus-article-mode)
   (let ((unread-command-events (list ?S)))
     (gnus-article-read-summary-keys)))
 
@@ -6822,7 +6809,8 @@ not have a face in `gnus-article-boring-faces'."
   "Display documentation of the function invoked by KEY.
 KEY is a string or a vector."
   (interactive (list (let ((cursor-in-echo-area t))
-                      (read-key-sequence "Describe key: "))))
+                      (read-key-sequence "Describe key: ")))
+              gnus-article-mode)
   (gnus-article-check-buffer)
   (if (memq (key-binding key t) '(gnus-article-read-summary-keys
                                  gnus-article-read-summary-send-keys))
@@ -6844,7 +6832,8 @@ KEY is a string or a vector."
 KEY is a string or a vector."
   (interactive (list (let ((cursor-in-echo-area t))
                       (read-key-sequence "Describe key: "))
-                    current-prefix-arg))
+                    current-prefix-arg)
+              gnus-article-mode)
   (gnus-article-check-buffer)
   (if (memq (key-binding key t) '(gnus-article-read-summary-keys
                                  gnus-article-read-summary-send-keys))
@@ -6871,7 +6860,7 @@ KEY is a string or a vector."
   "Show a list of all defined keys, and their definitions.
 The optional argument PREFIX, if non-nil, should be a key sequence;
 then we display only bindings that start with that prefix."
-  (interactive)
+  (interactive nil gnus-article-mode)
   (gnus-article-check-buffer)
   (let ((keymap (copy-keymap gnus-article-mode-map))
        (map (copy-keymap gnus-article-send-map))
@@ -6930,7 +6919,7 @@ then we display only bindings that start with that 
prefix."
   "Start composing a reply mail to the current message.
 The text in the region will be yanked.  If the region isn't active,
 the entire article will be yanked."
-  (interactive)
+  (interactive nil gnus-article-mode)
   (let ((article (cdr gnus-article-current))
        contents)
     (if (not (and transient-mark-mode mark-active))
@@ -6948,14 +6937,14 @@ the entire article will be yanked."
   "Start composing a wide reply mail to the current message.
 The text in the region will be yanked.  If the region isn't active,
 the entire article will be yanked."
-  (interactive)
+  (interactive nil gnus-article-mode)
   (gnus-article-reply-with-original t))
 
 (defun gnus-article-followup-with-original ()
   "Compose a followup to the current article.
 The text in the region will be yanked.  If the region isn't active,
 the entire article will be yanked."
-  (interactive)
+  (interactive nil gnus-article-mode)
   (let ((article (cdr gnus-article-current))
        contents)
       (if (not (and transient-mark-mode mark-active))
@@ -6974,7 +6963,8 @@ the entire article will be yanked."
 This means that signatures, cited text and (some) headers will be
 hidden.
 If given a prefix, show the hidden text instead."
-  (interactive (append (gnus-article-hidden-arg) (list 'force)))
+  (interactive (append (gnus-article-hidden-arg) (list 'force))
+              gnus-article-mode gnus-summary-mode)
   (gnus-with-article-buffer
     (article-hide-headers arg)
     (article-hide-list-identifiers)
@@ -7269,7 +7259,7 @@ This is an extended text-mode.
 This will have permanent effect only in mail groups.
 If FORCE is non-nil, allow editing of articles even in read-only
 groups."
-  (interactive "P")
+  (interactive "P" gnus-article-mode gnus-summary-mode)
   (when (and (not force)
             (gnus-group-read-only-p))
     (error "The current newsgroup does not support article editing"))
@@ -7302,7 +7292,7 @@ groups."
 
 (defun gnus-article-edit-done (&optional arg)
   "Update the article edits and exit."
-  (interactive "P")
+  (interactive "P" gnus-article-mode)
   (let ((func gnus-article-edit-done-function)
        (buf (current-buffer))
        (start (window-start))
@@ -7336,7 +7326,7 @@ groups."
 
 (defun gnus-article-edit-exit ()
   "Exit the article editing without updating."
-  (interactive)
+  (interactive nil gnus-article-mode)
   (when (or (not (buffer-modified-p))
            (yes-or-no-p "Article modified; kill anyway? "))
     (let ((curbuf (current-buffer))
@@ -7357,7 +7347,7 @@ groups."
 
 (defun gnus-article-edit-full-stops ()
   "Interactively repair spacing at end of sentences."
-  (interactive)
+  (interactive nil gnus-article-mode)
   (save-excursion
     (goto-char (point-min))
     (search-forward-regexp "^$" nil t)
@@ -7875,7 +7865,7 @@ HEADER is a regexp to match a header.  For a fuller 
explanation, see
   "Check text under the mouse pointer for a callback function.
 If the text under the mouse pointer has a `gnus-callback' property,
 call it with the value of the `gnus-data' text property."
-  (interactive "e")
+  (interactive "e" gnus-article-mode)
   (set-buffer (window-buffer (posn-window (event-start event))))
   (let* ((pos (posn-point (event-start event)))
         (data (get-text-property pos 'gnus-data))
@@ -7888,7 +7878,7 @@ call it with the value of the `gnus-data' text property."
   "Check text at point for a callback function.
 If the text at point has a `gnus-callback' property,
 call it with the value of the `gnus-data' text property."
-  (interactive (list last-nonmenu-event))
+  (interactive (list last-nonmenu-event) gnus-article-mode)
   (save-excursion
     (when event
       (mouse-set-point event))
@@ -7902,7 +7892,7 @@ This function calls `gnus-article-highlight-headers',
 `gnus-article-highlight-citation',
 `gnus-article-highlight-signature', and `gnus-article-add-buttons' to
 do the highlighting.  See the documentation for those functions."
-  (interactive (list 'force))
+  (interactive (list 'force) gnus-article-mode)
   (gnus-article-highlight-headers)
   (gnus-article-highlight-citation force)
   (gnus-article-highlight-signature)
@@ -7914,14 +7904,14 @@ do the highlighting.  See the documentation for those 
functions."
 This function calls `gnus-article-highlight-headers',
 `gnus-article-highlight-signature', and `gnus-article-add-buttons' to
 do the highlighting.  See the documentation for those functions."
-  (interactive (list 'force))
+  (interactive (list 'force) gnus-article-mode)
   (gnus-article-highlight-headers)
   (gnus-article-highlight-signature)
   (gnus-article-add-buttons))
 
 (defun gnus-article-highlight-headers ()
   "Highlight article headers as specified by `gnus-header-face-alist'."
-  (interactive)
+  (interactive nil gnus-article-mode gnus-summary-mode)
   (gnus-with-article-headers
     (let (regexp header-face field-face from hpoints fpoints)
       (dolist (entry gnus-header-face-alist)
@@ -7955,7 +7945,7 @@ do the highlighting.  See the documentation for those 
functions."
   "Highlight the signature in an article.
 It does this by highlighting everything after
 `gnus-signature-separator' using the face `gnus-signature'."
-  (interactive)
+  (interactive nil gnus-article-mode gnus-summary-mode)
   (gnus-with-article-buffer
     (let ((inhibit-point-motion-hooks t))
       (save-restriction
@@ -7978,7 +7968,7 @@ It does this by highlighting everything after
   "Find external references in the article and make buttons of them.
 \"External references\" are things like Message-IDs and URLs, as
 specified by `gnus-button-alist'."
-  (interactive)
+  (interactive nil gnus-article-mode gnus-summary-mode)
   (gnus-with-article-buffer
     (let ((inhibit-point-motion-hooks t)
          (case-fold-search t)
@@ -8072,7 +8062,7 @@ url is put as the `gnus-button-url' overlay property on 
the button."
 ;; Add buttons to the head of an article.
 (defun gnus-article-add-buttons-to-head ()
   "Add buttons to the head of the article."
-  (interactive)
+  (interactive nil gnus-article-mode gnus-summary-mode)
   (gnus-with-article-headers
     (let (beg end)
       (dolist (entry gnus-header-button-alist)
@@ -8120,7 +8110,7 @@ url is put as the `gnus-button-url' overlay property on 
the button."
 
 (defun gnus-article-copy-string ()
   "Copy the string in the button to the kill ring."
-  (interactive)
+  (interactive nil gnus-article-mode)
   (gnus-article-check-buffer)
   (let ((data (get-text-property (point) 'gnus-string)))
     (when data
@@ -8236,7 +8226,7 @@ url is put as the `gnus-button-url' overlay property on 
the button."
 
 (defun gnus-button-patch (library line)
   "Visit an Emacs Lisp library LIBRARY on line LINE."
-  (interactive)
+  (interactive nil gnus-article-mode)
   (let ((file (locate-library (file-name-nondirectory library))))
     (unless file
       (error "Couldn't find library %s" library))
@@ -8428,7 +8418,7 @@ url is put as the `gnus-button-url' overlay property on 
the button."
 
 (defun gnus-button-next-page (&optional _args _more-args)
   "Go to the next page."
-  (interactive)
+  (interactive nil gnus-article-mode)
   (let ((win (selected-window)))
     (select-window (gnus-get-buffer-window gnus-article-buffer t))
     (gnus-article-next-page)
@@ -8436,7 +8426,7 @@ url is put as the `gnus-button-url' overlay property on 
the button."
 
 (defun gnus-button-prev-page (&optional _args _more-args)
   "Go to the prev page."
-  (interactive)
+  (interactive nil gnus-article-mode)
   (let ((win (selected-window)))
     (select-window (gnus-get-buffer-window gnus-article-buffer t))
     (gnus-article-prev-page)
@@ -8460,7 +8450,7 @@ url is put as the `gnus-button-url' overlay property on 
the button."
 
 (defun gnus-article-button-next-page (_arg)
   "Go to the next page."
-  (interactive "P")
+  (interactive "P" gnus-article-mode)
   (let ((win (selected-window)))
     (select-window (gnus-get-buffer-window gnus-article-buffer t))
     (gnus-article-next-page)
@@ -8468,7 +8458,7 @@ url is put as the `gnus-button-url' overlay property on 
the button."
 
 (defun gnus-article-button-prev-page (_arg)
   "Go to the prev page."
-  (interactive "P")
+  (interactive "P" gnus-article-mode)
   (let ((win (selected-window)))
     (select-window (gnus-get-buffer-window gnus-article-buffer t))
     (gnus-article-prev-page)
@@ -8602,9 +8592,10 @@ For example:
    (list
     (or gnus-article-encrypt-protocol
        (gnus-completing-read "Encrypt protocol"
-                              (mapcar #'car 
gnus-article-encrypt-protocol-alist)
-                              t))
-    current-prefix-arg))
+                             (mapcar #'car gnus-article-encrypt-protocol-alist)
+                             t))
+    current-prefix-arg)
+   gnus-article-mode)
   ;; User might hit `K E' instead of `K e', so prompt once.
   (when (and gnus-article-encrypt-protocol
             gnus-novice-user)
@@ -8728,7 +8719,7 @@ For example:
 
 (defun gnus-mime-security-button-menu (event prefix)
   "Construct a context-sensitive menu of security commands."
-  (interactive "e\nP")
+  (interactive "e\nP" gnus-article-mode)
   (save-window-excursion
     (let ((pos (event-start event)))
       (select-window (posn-window pos))
@@ -8885,12 +8876,12 @@ For example:
 
 (defun gnus-mime-security-save-part ()
   "Save the security part under point."
-  (interactive)
+  (interactive nil gnus-article-mode)
   (gnus-mime-security-run-function 'mm-save-part))
 
 (defun gnus-mime-security-pipe-part ()
   "Pipe the security part under point to a process."
-  (interactive)
+  (interactive nil gnus-article-mode)
   (gnus-mime-security-run-function 'mm-pipe-part))
 
 (provide 'gnus-art)
diff --git a/lisp/gnus/gnus-bookmark.el b/lisp/gnus/gnus-bookmark.el
index bc41d5b..8c2a928 100644
--- a/lisp/gnus/gnus-bookmark.el
+++ b/lisp/gnus/gnus-bookmark.el
@@ -168,7 +168,7 @@ So the cdr of each bookmark is an alist too.")
 ;;;###autoload
 (defun gnus-bookmark-set ()
   "Set a bookmark for this article."
-  (interactive)
+  (interactive nil gnus-article-mode gnus-summary-mode)
   (gnus-bookmark-maybe-load-default-file)
   (if (or (not (derived-mode-p 'gnus-summary-mode))
          (not gnus-article-current))
@@ -483,7 +483,7 @@ Gnus bookmarks names preceded by a \"*\" have annotations.
 (defun gnus-bookmark-bmenu-toggle-infos (&optional show)
   "Toggle whether details are shown in the Gnus bookmark list.
 Optional argument SHOW means show them unconditionally."
-  (interactive)
+  (interactive nil gnus-bookmark-bmenu-mode)
   (cond
    (show
     (setq gnus-bookmark-bmenu-toggle-infos nil)
@@ -649,14 +649,14 @@ reposition and try again, else return nil."
 
 (defun gnus-bookmark-bmenu-show-details ()
   "Show the annotation for the current bookmark in another window."
-  (interactive)
+  (interactive nil gnus-bookmark-bmenu-mode)
   (let ((bookmark (gnus-bookmark-bmenu-bookmark)))
     (if (gnus-bookmark-bmenu-check-position)
        (gnus-bookmark-show-details bookmark))))
 
 (defun gnus-bookmark-bmenu-mark ()
   "Mark bookmark on this line to be displayed by 
\\<gnus-bookmark-bmenu-mode-map>\\[gnus-bookmark-bmenu-select]."
-  (interactive)
+  (interactive nil gnus-bookmark-bmenu-mode)
   (beginning-of-line)
   (if (gnus-bookmark-bmenu-check-position)
       (let ((inhibit-read-only t))
@@ -668,7 +668,7 @@ reposition and try again, else return nil."
 (defun gnus-bookmark-bmenu-unmark (&optional backup)
   "Cancel all requested operations on bookmark on this line and move down.
 Optional BACKUP means move up."
-  (interactive "P")
+  (interactive "P" gnus-bookmark-bmenu-mode)
   (beginning-of-line)
   (if (gnus-bookmark-bmenu-check-position)
       (progn
@@ -683,7 +683,7 @@ Optional BACKUP means move up."
 
 (defun gnus-bookmark-bmenu-backup-unmark ()
   "Move up and cancel all requested operations on bookmark on line above."
-  (interactive)
+  (interactive nil gnus-bookmark-bmenu-mode)
   (forward-line -1)
   (if (gnus-bookmark-bmenu-check-position)
       (progn
@@ -695,7 +695,7 @@ Optional BACKUP means move up."
   "Mark Gnus bookmark on this line to be deleted.
 To carry out the deletions that you've marked, use
 \\<gnus-bookmark-bmenu-mode-map>\\[gnus-bookmark-bmenu-execute-deletions]."
-  (interactive)
+  (interactive nil gnus-bookmark-bmenu-mode)
   (beginning-of-line)
   (if (gnus-bookmark-bmenu-check-position)
       (let ((inhibit-read-only t))
@@ -708,7 +708,7 @@ To carry out the deletions that you've marked, use
   "Mark bookmark on this line to be deleted, then move up one line.
 To carry out the deletions that you've marked, use
 \\<gnus-bookmark-bmenu-mode-map>\\[gnus-bookmark-bmenu-execute-deletions]."
-  (interactive)
+  (interactive nil gnus-bookmark-bmenu-mode)
   (gnus-bookmark-bmenu-delete)
   (forward-line -2)
   (if (gnus-bookmark-bmenu-check-position)
@@ -720,7 +720,7 @@ To carry out the deletions that you've marked, use
 You can mark bookmarks with the
 \\<gnus-bookmark-bmenu-mode-map>\\[gnus-bookmark-bmenu-mark]
 command."
-  (interactive)
+  (interactive nil gnus-bookmark-bmenu-mode)
   (if (gnus-bookmark-bmenu-check-position)
       (let ((bmrk (gnus-bookmark-bmenu-bookmark))
             (menu (current-buffer)))
@@ -730,13 +730,13 @@ command."
         (bury-buffer menu))))
 
 (defun gnus-bookmark-bmenu-select-by-mouse (event)
-  (interactive "e")
+  (interactive "e" gnus-bookmark-bmenu-mode)
   (mouse-set-point event)
   (gnus-bookmark-bmenu-select))
 
 (defun gnus-bookmark-bmenu-load ()
   "Load the Gnus bookmark file and rebuild the bookmark menu-buffer."
-  (interactive)
+  (interactive nil gnus-bookmark-bmenu-mode)
   (if (gnus-bookmark-bmenu-check-position)
       (save-excursion
         (save-window-excursion
@@ -745,7 +745,7 @@ command."
 
 (defun gnus-bookmark-bmenu-execute-deletions ()
   "Delete Gnus bookmarks marked with 
\\<Buffer-menu-mode-map>\\[Buffer-menu-delete] commands."
-  (interactive)
+  (interactive nil gnus-bookmark-bmenu-mode)
   (message "Deleting Gnus bookmarks...")
   (let ((hide-em gnus-bookmark-bmenu-toggle-infos)
         (o-point  (point))
diff --git a/lisp/gnus/gnus-cache.el b/lisp/gnus/gnus-cache.el
index 5ed7319..34dba54 100644
--- a/lisp/gnus/gnus-cache.el
+++ b/lisp/gnus/gnus-cache.el
@@ -342,7 +342,7 @@ it's not cached."
   "Enter the next N articles into the cache.
 If not given a prefix, use the process marked articles instead.
 Returns the list of articles entered."
-  (interactive "P")
+  (interactive "P" gnus-summary-mode)
   (let (out)
     (dolist (article (gnus-summary-work-articles n))
       (gnus-summary-remove-process-mark article)
@@ -363,7 +363,7 @@ Returns the list of articles entered."
   "Remove the next N articles from the cache.
 If not given a prefix, use the process marked articles instead.
 Returns the list of articles removed."
-  (interactive "P")
+  (interactive "P" gnus-summary-mode)
   (gnus-cache-change-buffer gnus-newsgroup-name)
   (let (out)
     (dolist (article (gnus-summary-work-articles n))
@@ -388,7 +388,7 @@ Returns the list of articles removed."
 
 (defun gnus-summary-insert-cached-articles ()
   "Insert all the articles cached for this group into the current buffer."
-  (interactive)
+  (interactive nil gnus-summary-mode)
   (let ((gnus-verbose (max 6 gnus-verbose)))
     (cond
      ((not gnus-newsgroup-cached)
@@ -401,7 +401,7 @@ Returns the list of articles removed."
 
 (defun gnus-summary-limit-include-cached ()
   "Limit the summary buffer to articles that are cached."
-  (interactive)
+  (interactive nil gnus-summary-mode)
   (let ((gnus-verbose (max 6 gnus-verbose)))
     (if gnus-newsgroup-cached
        (progn
diff --git a/lisp/gnus/gnus-cite.el b/lisp/gnus/gnus-cite.el
index 96f1a7d..1f564f1 100644
--- a/lisp/gnus/gnus-cite.el
+++ b/lisp/gnus/gnus-cite.el
@@ -335,7 +335,7 @@ lines matches `message-cite-prefix-regexp' with the same 
prefix.
 
 Lines matching `gnus-cite-attribution-suffix' and perhaps
 `gnus-cite-attribution-prefix' are considered attribution lines."
-  (interactive (list 'force))
+  (interactive (list 'force) gnus-article-mode gnus-summary-mode)
   (with-current-buffer (if same-buffer (current-buffer) gnus-article-buffer)
     (gnus-cite-parse-maybe force)
     (let ((buffer-read-only nil)
@@ -459,7 +459,7 @@ frame width.
 
 Sections that are heuristically interpreted as not being
 text (i.e., computer code and the like) will not be folded."
-  (interactive "P")
+  (interactive "P" gnus-article-mode gnus-summary-mode)
   (with-current-buffer gnus-article-buffer
     (let ((buffer-read-only nil)
          (inhibit-point-motion-hooks t)
@@ -529,7 +529,8 @@ text (i.e., computer code and the like) will not be folded."
 See the documentation for `gnus-article-highlight-citation'.
 If given a negative prefix, always show; if given a positive prefix,
 always hide."
-  (interactive (append (gnus-article-hidden-arg) (list 'force)))
+  (interactive (append (gnus-article-hidden-arg) (list 'force))
+              gnus-article-mode gnus-summary-mode)
   (gnus-set-format 'cited-opened-text-button t)
   (gnus-set-format 'cited-closed-text-button t)
   (with-current-buffer gnus-article-buffer
@@ -661,7 +662,8 @@ percent and at least `gnus-cite-hide-absolute' lines of the 
body is
 cited text with attributions.  When called interactively, these two
 variables are ignored.
 See also the documentation for `gnus-article-highlight-citation'."
-  (interactive (append (gnus-article-hidden-arg) '(force)))
+  (interactive (append (gnus-article-hidden-arg) '(force))
+              gnus-article-mode gnus-summary-mode)
   (with-current-buffer gnus-article-buffer
     (gnus-delete-wash-type 'cite)
     (unless (gnus-article-check-hidden-text 'cite arg)
@@ -689,7 +691,7 @@ See also the documentation for 
`gnus-article-highlight-citation'."
 
 (defun gnus-article-hide-citation-in-followups ()
   "Hide cited text in non-root articles."
-  (interactive)
+  (interactive nil gnus-article-mode gnus-summary-mode)
   (with-current-buffer gnus-article-buffer
     (let ((article (cdr gnus-article-current)))
       (unless (with-current-buffer gnus-summary-buffer
diff --git a/lisp/gnus/gnus-cus.el b/lisp/gnus/gnus-cus.el
index d8f48b1..0852f8e 100644
--- a/lisp/gnus/gnus-cus.el
+++ b/lisp/gnus/gnus-cus.el
@@ -337,7 +337,8 @@ category."))
 
 (defun gnus-group-customize (group &optional topic)
   "Edit the group or topic on the current line."
-  (interactive (list (gnus-group-group-name) (gnus-group-topic-name)))
+  (interactive (list (gnus-group-group-name) (gnus-group-topic-name))
+              gnus-group-mode)
   (let (info
        (types (mapcar (lambda (entry)
                         `(cons :format "%v%h\n"
@@ -485,7 +486,7 @@ form, but who cares?"
 
 (defun gnus-group-customize-done (&rest _ignore)
   "Apply changes and bury the buffer."
-  (interactive)
+  (interactive nil gnus-custom-mode)
   (let ((params (widget-value gnus-custom-params)))
     (if gnus-custom-topic
        (gnus-topic-set-parameters gnus-custom-topic params)
@@ -829,7 +830,7 @@ eh?")))
   "Customize score file FILE.
 When called interactively, FILE defaults to the current score file.
 This can be changed using the `\\[gnus-score-change-score-file]' command."
-  (interactive (list gnus-current-score-file))
+  (interactive (list gnus-current-score-file) gnus-summary-mode)
   (unless file
     (error "No score file for %s" gnus-newsgroup-name))
   (let ((scores (gnus-score-load file))
@@ -1000,7 +1001,7 @@ articles in the thread.
 
 (defun gnus-agent-customize-category (category)
   "Edit the CATEGORY."
-  (interactive (list (gnus-category-name)))
+  (interactive (list (gnus-category-name)) gnus-custom-mode)
   (let ((info (assq category gnus-category-alist))
         (defaults (list nil '(agent-predicate . false)
                         (cons 'agent-enable-expiration
diff --git a/lisp/gnus/gnus-delay.el b/lisp/gnus/gnus-delay.el
index 0cee01b..944fd97 100644
--- a/lisp/gnus/gnus-delay.el
+++ b/lisp/gnus/gnus-delay.el
@@ -76,10 +76,10 @@ DELAY is a string, giving the length of the time.  Possible 
values are:
 The value of `message-draft-headers' determines which headers are
 generated when the article is delayed.  Remaining headers are
 generated when the article is sent."
-  (interactive
-   (list (read-string
-         "Target date (YYYY-MM-DD), time (hh:mm), or length of delay (units in 
[mhdwMY]): "
-         gnus-delay-default-delay)))
+  (interactive (list (read-string
+                     "Target date (YYYY-MM-DD), time (hh:mm), or length of 
delay (units in [mhdwMY]): "
+                     gnus-delay-default-delay))
+              message-mode)
   ;; Allow spell checking etc.
   (run-hooks 'message-send-hook)
   (let (num unit year month day hour minute deadline) ;; days
diff --git a/lisp/gnus/gnus-diary.el b/lisp/gnus/gnus-diary.el
index 5270564..64eb639 100644
--- a/lisp/gnus/gnus-diary.el
+++ b/lisp/gnus/gnus-diary.el
@@ -214,7 +214,7 @@ There are currently two built-in format functions:
 (defun gnus-summary-sort-by-schedule (&optional reverse)
   "Sort nndiary summary buffers by schedule of appointments.
 Optional prefix (or REVERSE argument) means sort in reverse order."
-  (interactive "P")
+  (interactive "P" gnus-summary-mode)
   (gnus-summary-sort 'schedule reverse))
 
 (defvar gnus-summary-misc-menu) ;; Avoid byte compiler warning.
@@ -322,7 +322,7 @@ This function checks that all NNDiary required headers are 
present and
 valid, and prompts for values / correction otherwise.
 
 If ARG (or prefix) is non-nil, force prompting for all fields."
-  (interactive "P")
+  (interactive "P" gnus-summary-mode)
   (save-excursion
     (mapcar
      (lambda (head)
diff --git a/lisp/gnus/gnus-dired.el b/lisp/gnus/gnus-dired.el
index ca2d57d..af0b782 100644
--- a/lisp/gnus/gnus-dired.el
+++ b/lisp/gnus/gnus-dired.el
@@ -124,7 +124,8 @@ filenames."
          (mapcar
           ;; don't attach directories
           (lambda (f) (if (file-directory-p f) nil f))
-          (nreverse (dired-map-over-marks (dired-get-filename) nil))))))
+          (nreverse (dired-map-over-marks (dired-get-filename) nil)))))
+   dired-mode)
   (let ((destination nil)
        (files-str nil)
        (bufs nil))
@@ -178,7 +179,8 @@ filenames."
 If ARG is non-nil, open it in a new buffer."
   (interactive (list
                (file-name-sans-versions (dired-get-filename) t)
-               current-prefix-arg))
+               current-prefix-arg)
+              dired-mode)
   (mailcap-parse-mailcaps)
   (if (file-exists-p file-name)
       (let (mime-type method)
@@ -216,7 +218,8 @@ that name.  If PRINT-TO is a number, prompt the user for 
the name
 of the file to save in."
   (interactive (list
                (file-name-sans-versions (dired-get-filename) t)
-               (ps-print-preprint current-prefix-arg)))
+               (ps-print-preprint current-prefix-arg))
+              dired-mode)
   (mailcap-parse-mailcaps)
   (cond
    ((file-directory-p file-name)
diff --git a/lisp/gnus/gnus-draft.el b/lisp/gnus/gnus-draft.el
index f68e9d6..9a0f213 100644
--- a/lisp/gnus/gnus-draft.el
+++ b/lisp/gnus/gnus-draft.el
@@ -71,7 +71,7 @@
 
 (defun gnus-draft-toggle-sending (article)
   "Toggle whether to send an article or not."
-  (interactive (list (gnus-summary-article-number)))
+  (interactive (list (gnus-summary-article-number)) gnus-summary-mode)
   (if (gnus-draft-article-sendable-p article)
       (progn
        (push article gnus-newsgroup-unsendable)
@@ -83,7 +83,7 @@
 
 (defun gnus-draft-edit-message ()
   "Enter a mail/post buffer to edit and send the draft."
-  (interactive)
+  (interactive nil gnus-summary-mode)
   (let ((article (gnus-summary-article-number))
        (group gnus-newsgroup-name))
     (gnus-draft-check-draft-articles (list article))
@@ -109,7 +109,7 @@
 (defun gnus-draft-send-message (&optional n)
   "Send the current draft(s).
 Obeys the standard process/prefix convention."
-  (interactive "P")
+  (interactive "P" gnus-summary-mode)
   (let* ((articles (gnus-summary-work-articles n))
         (total (length articles))
         article)
diff --git a/lisp/gnus/gnus-eform.el b/lisp/gnus/gnus-eform.el
index 265edf4..3fd8bf5 100644
--- a/lisp/gnus/gnus-eform.el
+++ b/lisp/gnus/gnus-eform.el
@@ -104,7 +104,7 @@ The optional LAYOUT overrides the `edit-form' window 
layout."
 
 (defun gnus-edit-form-done ()
   "Update changes and kill the current buffer."
-  (interactive)
+  (interactive nil gnus-edit-form-mode)
   (goto-char (point-min))
   (let ((form (condition-case nil
                  (read (current-buffer))
@@ -115,7 +115,7 @@ The optional LAYOUT overrides the `edit-form' window 
layout."
 
 (defun gnus-edit-form-exit ()
   "Kill the current buffer."
-  (interactive)
+  (interactive nil gnus-edit-form-mode)
   (let ((winconf gnus-prev-winconf))
     (kill-buffer (current-buffer))
     (set-window-configuration winconf)))
diff --git a/lisp/gnus/gnus-fun.el b/lisp/gnus/gnus-fun.el
index f69c2ed..c2e72ab 100644
--- a/lisp/gnus/gnus-fun.el
+++ b/lisp/gnus/gnus-fun.el
@@ -132,11 +132,12 @@ For instance, to insert an X-Face use 
`gnus-random-x-face' as FUN
 
 Files matching `gnus-x-face-omit-files' are not considered."
   (interactive)
-  (gnus--random-face-with-type gnus-x-face-directory "\\.pbm$" 
gnus-x-face-omit-files
-                         (lambda (file)
-                           (gnus-shell-command-to-string
-                            (format gnus-convert-pbm-to-x-face-command
-                                    (shell-quote-argument file))))))
+  (gnus--random-face-with-type
+   gnus-x-face-directory "\\.pbm$" gnus-x-face-omit-files
+   (lambda (file)
+     (gnus-shell-command-to-string
+      (format gnus-convert-pbm-to-x-face-command
+             (shell-quote-argument file))))))
 
 ;;;###autoload
 (defun gnus-insert-random-x-face-header ()
@@ -231,8 +232,8 @@ FILE should be a PNG file that's 48x48 and smaller than or 
equal to
 Files matching `gnus-face-omit-files' are not considered."
   (interactive)
   (gnus--random-face-with-type gnus-face-directory "\\.png$"
-                         gnus-face-omit-files
-                         'gnus-convert-png-to-face))
+                               gnus-face-omit-files
+                               'gnus-convert-png-to-face))
 
 ;;;###autoload
 (defun gnus-insert-random-face-header ()
@@ -277,7 +278,6 @@ colors of the displayed X-Faces."
 
 (defun gnus-grab-cam-x-face ()
   "Grab a picture off the camera and make it into an X-Face."
-  (interactive)
   (shell-command "xawtv-remote snap ppm")
   (let ((file nil))
     (while (null (setq file (directory-files "/tftpboot/sparky/tmp"
@@ -289,13 +289,11 @@ colors of the displayed X-Faces."
        (format "pnmcut -left 110 -top 30 -width 144 -height 144 '%s' | ppmnorm 
2>%s | pnmscale -width 48 | ppmtopgm | pgmtopbm -threshold -value 0.92 | 
pbmtoxbm | compface"
               file null-device)
        (current-buffer))
-      ;;(sleep-for 3)
       (delete-file file)
       (buffer-string))))
 
 (defun gnus-grab-cam-face ()
   "Grab a picture off the camera and make it into an X-Face."
-  (interactive)
   (shell-command "xawtv-remote snap ppm")
   (let ((file nil)
        (tempfile (make-temp-file "gnus-face-" nil ".ppm"))
@@ -312,7 +310,6 @@ colors of the displayed X-Faces."
                   (gnus-fun-ppm-change-string))))
       (setq result (gnus-face-from-file tempfile)))
     (delete-file file)
-    ;;(delete-file tempfile)    ; FIXME why are we not deleting it?!
     result))
 
 (defun gnus-fun-ppm-change-string ()
diff --git a/lisp/gnus/gnus-gravatar.el b/lisp/gnus/gnus-gravatar.el
index 9ea9e10..be57774 100644
--- a/lisp/gnus/gnus-gravatar.el
+++ b/lisp/gnus/gnus-gravatar.el
@@ -125,7 +125,7 @@ callback for `gravatar-retrieve'."
 (defun gnus-treat-from-gravatar (&optional force)
   "Display gravatar in the From header.
 If gravatar is already displayed, remove it."
-  (interactive "p")
+  (interactive "p" gnus-article-mode gnus-summary-mode)
   (gnus-with-article-buffer
     (if (memq 'from-gravatar gnus-article-wash-types)
        (gnus-delete-images 'from-gravatar)
@@ -135,7 +135,7 @@ If gravatar is already displayed, remove it."
 (defun gnus-treat-mail-gravatar (&optional force)
   "Display gravatars in the Cc and To headers.
 If gravatars are already displayed, remove them."
-  (interactive "p")
+  (interactive "p" gnus-article-mode gnus-summary-mode)
   (gnus-with-article-buffer
     (if (memq 'mail-gravatar gnus-article-wash-types)
         (gnus-delete-images 'mail-gravatar)
diff --git a/lisp/gnus/gnus-group.el b/lisp/gnus/gnus-group.el
index e8b62a4..909391b 100644
--- a/lisp/gnus/gnus-group.el
+++ b/lisp/gnus/gnus-group.el
@@ -1160,7 +1160,7 @@ The following commands are available:
 
 (defun gnus-mouse-pick-group (e)
   "Enter the group under the mouse pointer."
-  (interactive "e")
+  (interactive "e" gnus-group-mode)
   (mouse-set-point e)
   (gnus-group-read-group nil))
 
@@ -1241,7 +1241,8 @@ Also see the `gnus-group-use-permanent-levels' variable."
           (or
            (gnus-group-default-level nil t)
            (gnus-group-default-list-level)
-           gnus-level-subscribed))))
+           gnus-level-subscribed)))
+   gnus-group-mode)
   (unless level
     (setq level (car gnus-group-list-mode)
          unread (cdr gnus-group-list-mode)))
@@ -1292,7 +1293,7 @@ Also see the `gnus-group-use-permanent-levels' variable."
 (defun gnus-group-list-level (level &optional all)
   "List groups on LEVEL.
 If ALL (the prefix), also list groups that have no unread articles."
-  (interactive "nList groups on level: \nP")
+  (interactive "nList groups on level: \nP" gnus-group-mode)
   (gnus-group-list-groups level all level))
 
 (defun gnus-group-prepare-logic (group test)
@@ -1866,7 +1867,7 @@ If FIRST-TOO, the current line is also eligible as a 
target."
 
 (defun gnus-group-mark-group (n &optional unmark no-advance)
   "Mark the current group."
-  (interactive "p")
+  (interactive "p" gnus-group-mode)
   (let ((buffer-read-only nil)
        group)
     (while (and (> n 0)
@@ -1891,13 +1892,13 @@ If FIRST-TOO, the current line is also eligible as a 
target."
 
 (defun gnus-group-unmark-group (n)
   "Remove the mark from the current group."
-  (interactive "p")
+  (interactive "p" gnus-group-mode)
   (gnus-group-mark-group n 'unmark)
   (gnus-group-position-point))
 
 (defun gnus-group-unmark-all-groups ()
   "Unmark all groups."
-  (interactive)
+  (interactive nil gnus-group-mode)
   (save-excursion
     (mapc #'gnus-group-remove-mark gnus-group-marked))
   (gnus-group-position-point))
@@ -1905,7 +1906,7 @@ If FIRST-TOO, the current line is also eligible as a 
target."
 (defun gnus-group-mark-region (unmark beg end)
   "Mark all groups between point and mark.
 If UNMARK, remove the mark instead."
-  (interactive "P\nr")
+  (interactive "P\nr" gnus-group-mode)
   (let ((num (count-lines beg end)))
     (save-excursion
       (goto-char beg)
@@ -1914,12 +1915,12 @@ If UNMARK, remove the mark instead."
 (defun gnus-group-mark-buffer (&optional unmark)
   "Mark all groups in the buffer.
 If UNMARK, remove the mark instead."
-  (interactive "P")
+  (interactive "P" gnus-group-mode)
   (gnus-group-mark-region unmark (point-min) (point-max)))
 
 (defun gnus-group-mark-regexp (regexp)
   "Mark all groups that match some regexp."
-  (interactive "sMark (regexp): ")
+  (interactive "sMark (regexp): " gnus-group-mode)
   (let ((alist (cdr gnus-newsrc-alist))
        group)
     (save-excursion
@@ -2028,7 +2029,7 @@ number of the earliest articles in the group.
 If the optional argument NO-ARTICLE is non-nil, no article will
 be auto-selected upon group entry.  If GROUP is non-nil, fetch
 that group."
-  (interactive "P")
+  (interactive "P" gnus-group-mode)
   (let ((no-display (eq all 0))
        (group (or group (gnus-group-group-name)))
        number active marked entry)
@@ -2062,7 +2063,7 @@ If ALL is a positive number, fetch this number of the 
latest
 articles in the group.
 If ALL is a negative number, fetch this number of the earliest
 articles in the group."
-  (interactive "P")
+  (interactive "P" gnus-group-mode)
   (when (and (eobp) (not (gnus-group-group-name)))
     (forward-line -1))
   (gnus-group-read-group all t))
@@ -2081,7 +2082,7 @@ buffer.  If GROUP is nil, use current group.
 
 This might be useful if you want to toggle threading
 before entering the group."
-  (interactive "P")
+  (interactive "P" gnus-group-mode)
   (require 'gnus-score)
   (let (gnus-visual
        gnus-score-find-score-files-function
@@ -2092,7 +2093,7 @@ before entering the group."
 
 (defun gnus-group-visible-select-group (&optional all)
   "Select the current group without hiding any articles."
-  (interactive "P")
+  (interactive "P" gnus-group-mode)
   (let ((gnus-inhibit-limiting t))
     (gnus-group-read-group all t)))
 
@@ -2101,7 +2102,7 @@ before entering the group."
 You will actually be entered into a group that's a copy of
 the current group; no changes you make while in this group will
 be permanent."
-  (interactive)
+  (interactive nil gnus-group-mode)
   (require 'gnus-score)
   (let* (gnus-visual
         gnus-score-find-score-files-function gnus-apply-kill-hook
@@ -2333,7 +2334,8 @@ specified by `gnus-gmane-group-download-format'."
    (list
     (gnus-group-completing-read "Gmane group")
     (read-number "Start article number: ")
-    (read-number "How many articles: ")))
+    (read-number "How many articles: "))
+   gnus-group-mode)
   (unless range (setq range 500))
   (when (< range 1)
     (error "Invalid range: %s" range))
@@ -2367,8 +2369,7 @@ Valid input formats include:
   ;; - The URLs should be added to `gnus-button-alist'.  Probably we should
   ;;   prompt the user to decide: "View via `browse-url' or in Gnus? "
   ;;   (`gnus-read-ephemeral-gmane-group-url')
-  (interactive
-   (list (gnus-group-completing-read "Gmane URL")))
+  (interactive (list (gnus-group-completing-read "Gmane URL")) gnus-group-mode)
   (let (group start range)
     (cond
      ;; URLs providing `group', `start' and `range':
@@ -2543,7 +2544,8 @@ If PROMPT (the prefix) is a number, use the prompt 
specified in
             (or (and (stringp gnus-group-jump-to-group-prompt)
                      gnus-group-jump-to-group-prompt)
                 (let ((p (cdr (assq 0 gnus-group-jump-to-group-prompt))))
-                  (and (stringp p) p)))))))
+                  (and (stringp p) p))))))
+   gnus-group-mode)
 
   (when (equal group "")
     (error "Empty group name"))
@@ -2612,7 +2614,7 @@ Return nil if GROUP is not found."
 If N is negative, search backward instead.
 Returns the difference between N and the number of skips actually
 done."
-  (interactive "p")
+  (interactive "p" gnus-group-mode)
   (gnus-group-next-unread-group n t nil silent))
 
 (defun gnus-group-next-unread-group (n &optional all level silent)
@@ -2624,7 +2626,7 @@ such group can be found, the next group with a level 
higher than
 LEVEL.
 Returns the difference between N and the number of skips actually
 made."
-  (interactive "p")
+  (interactive "p" gnus-group-mode)
   (let ((backward (< n 0))
        (n (abs n)))
     (while (and (> n 0)
@@ -2641,14 +2643,14 @@ made."
   "Go to previous N'th newsgroup.
 Returns the difference between N and the number of skips actually
 done."
-  (interactive "p")
+  (interactive "p" gnus-group-mode)
   (gnus-group-next-unread-group (- n) t))
 
 (defun gnus-group-prev-unread-group (n)
   "Go to previous N'th unread newsgroup.
 Returns the difference between N and the number of skips actually
 done."
-  (interactive "p")
+  (interactive "p" gnus-group-mode)
   (gnus-group-next-unread-group (- n)))
 
 (defun gnus-group-next-unread-group-same-level (n)
@@ -2656,7 +2658,7 @@ done."
 If N is negative, search backward instead.
 Returns the difference between N and the number of skips actually
 done."
-  (interactive "p")
+  (interactive "p" gnus-group-mode)
   (gnus-group-next-unread-group n t (gnus-group-group-level))
   (gnus-group-position-point))
 
@@ -2664,14 +2666,14 @@ done."
   "Go to next N'th unread newsgroup on the same level.
 Returns the difference between N and the number of skips actually
 done."
-  (interactive "p")
+  (interactive "p" gnus-group-mode)
   (gnus-group-next-unread-group (- n) t (gnus-group-group-level))
   (gnus-group-position-point))
 
 (defun gnus-group-best-unread-group (&optional exclude-group)
   "Go to the group with the highest level.
 If EXCLUDE-GROUP, do not go to that group."
-  (interactive)
+  (interactive nil gnus-group-mode)
   (goto-char (point-min))
   (let ((best 100000)
        unread best-point)
@@ -2711,7 +2713,7 @@ If EXCLUDE-GROUP, do not go to that group."
 
 (defun gnus-group-first-unread-group ()
   "Go to the first group with unread articles."
-  (interactive)
+  (interactive nil gnus-group-mode)
   (prog1
       (let ((opoint (point))
            unread)
@@ -2727,13 +2729,13 @@ If EXCLUDE-GROUP, do not go to that group."
 
 (defun gnus-group-enter-server-mode ()
   "Jump to the server buffer."
-  (interactive)
+  (interactive nil gnus-group-mode)
   (gnus-enter-server-buffer))
 
 (defun gnus-group-make-group-simple (&optional group)
   "Add a new newsgroup.
 The user will be prompted for GROUP."
-  (interactive (list (gnus-group-completing-read)))
+  (interactive (list (gnus-group-completing-read)) gnus-group-mode)
   (gnus-group-make-group (gnus-group-real-name group)
                         (gnus-group-server group)
                         nil nil))
@@ -2749,7 +2751,8 @@ server."
   (interactive
    (list
     (gnus-read-group "Group name: ")
-    (gnus-read-method "Select method for new group (use tab for completion)")))
+    (gnus-read-method "Select method for new group (use tab for completion)"))
+   gnus-group-mode)
 
   (when (stringp method)
     (setq method (or (gnus-server-to-method method) method)))
@@ -2794,7 +2797,7 @@ server."
 
 (defun gnus-group-delete-groups (&optional arg)
   "Delete the current group.  Only meaningful with editable groups."
-  (interactive "P")
+  (interactive "P" gnus-group-mode)
   (let ((n (length (gnus-group-process-prefix arg))))
     (when (gnus-yes-or-no-p
           (if (= n 1)
@@ -2809,8 +2812,8 @@ server."
 If OLDP (the prefix), only delete articles that are \"old\",
 according to the expiry settings.  Note that this will delete old
 not-expirable articles, too."
-  (interactive (list (gnus-group-group-name)
-                    current-prefix-arg))
+  (interactive (list (gnus-group-group-name) current-prefix-arg)
+              gnus-group-mode)
   (let ((articles (gnus-uncompress-range (gnus-active group))))
     (when (gnus-yes-or-no-p
           (format "Do you really want to delete these %d articles forever? "
@@ -2829,9 +2832,8 @@ doing the deletion.
 
 Note that you also have to specify FORCE if you want the group to
 be removed from the server, even when it's empty."
-  (interactive
-   (list (gnus-group-group-name)
-        current-prefix-arg))
+  (interactive (list (gnus-group-group-name) current-prefix-arg)
+              gnus-group-mode)
   (unless group
     (error "No group to delete"))
   (unless (gnus-check-backend-function 'request-delete-group group)
@@ -2865,7 +2867,8 @@ and NEW-NAME will be prompted for."
                     "Rename group to: "
                     (gnus-group-real-name group))
           method (gnus-info-method (gnus-get-info group)))
-     (list group (gnus-group-prefixed-name new-name method))))
+     (list group (gnus-group-prefixed-name new-name method)))
+   gnus-group-mode)
 
   (unless (gnus-check-backend-function 'request-rename-group group)
     (error "This back end does not support renaming groups"))
@@ -2911,7 +2914,7 @@ and NEW-NAME will be prompted for."
 
 (defun gnus-group-edit-group (group &optional part)
   "Edit the group on the current line."
-  (interactive (list (gnus-group-group-name)))
+  (interactive (list (gnus-group-group-name)) gnus-group-mode)
   (let ((part (or part 'info))
        info)
     (unless group
@@ -2950,12 +2953,12 @@ and NEW-NAME will be prompted for."
 
 (defun gnus-group-edit-group-method (group)
   "Edit the select method of GROUP."
-  (interactive (list (gnus-group-group-name)))
+  (interactive (list (gnus-group-group-name)) gnus-group-mode)
   (gnus-group-edit-group group 'method))
 
 (defun gnus-group-edit-group-parameters (group)
   "Edit the group parameters of GROUP."
-  (interactive (list (gnus-group-group-name)))
+  (interactive (list (gnus-group-group-name)) gnus-group-mode)
   (gnus-group-edit-group group 'params))
 
 (defun gnus-group-edit-group-done (part group form)
@@ -2993,14 +2996,16 @@ and NEW-NAME will be prompted for."
 (defun gnus-group-make-useful-group (group method)
   "Create one of the groups described in `gnus-useful-groups'."
   (interactive
-   (let ((entry (assoc (gnus-completing-read "Create group"
-                                             (mapcar #'car gnus-useful-groups)
-                                             t)
+   (let ((entry (assoc (gnus-completing-read
+                       "Create group"
+                       (mapcar #'car gnus-useful-groups)
+                       t)
                       gnus-useful-groups)))
      (list (cadr entry)
-          ;; Don't use `caddr' here since macros within the `interactive'
-          ;; form won't be expanded.
-          (car (cddr entry)))))
+          ;; Don't use `caddr' here since macros within the
+          ;; `interactive' form won't be expanded.
+          (car (cddr entry))))
+   gnus-group-mode)
   (setq method (copy-tree method))
   (let (entry)
     (while (setq entry (memq (assq 'eval method) method))
@@ -3014,7 +3019,7 @@ group already exists:
 - if not given, and error is signaled,
 - if t, stay silent,
 - if anything else, just print a message."
-  (interactive)
+  (interactive nil gnus-group-mode)
   (let ((name (gnus-group-prefixed-name "gnus-help" '(nndoc "gnus-help")))
        (file (nnheader-find-etc-directory "gnus-tut.txt" t)))
     (if (gnus-group-entry name)
@@ -3040,9 +3045,9 @@ group already exists:
   "Create a group that uses a single file as the source.
 
 If called with a prefix argument, ask for the file type."
-  (interactive
-   (list (read-file-name "File name: ")
-        (and current-prefix-arg 'ask)))
+  (interactive (list (read-file-name "File name: ")
+                    (and current-prefix-arg 'ask))
+              gnus-group-mode)
   (when (eq type 'ask)
     (let ((err "")
          char found)
@@ -3077,7 +3082,7 @@ If called with a prefix argument, ask for the file type."
 (defun gnus-group-make-web-group (&optional solid)
   "Create an ephemeral nnweb group.
 If SOLID (the prefix), create a solid group."
-  (interactive "P")
+  (interactive "P" gnus-group-mode)
   (require 'nnweb)
   (let* ((group
          (if solid (gnus-read-group "Group name: ")
@@ -3117,7 +3122,7 @@ If SOLID (the prefix), create a solid group."
 (defun gnus-group-make-rss-group (&optional url)
   "Given a URL, discover if there is an RSS feed.
 If there is, use Gnus to create an nnrss group"
-  (interactive)
+  (interactive nil gnus-group-mode)
   (require 'nnrss)
   (if (not url)
       (setq url (read-from-minibuffer "URL to Search for RSS: ")))
@@ -3158,8 +3163,8 @@ If there is, use Gnus to create an nnrss group"
 The user will be prompted for a directory.  The contents of this
 directory will be used as a newsgroup.  The directory should contain
 mail messages or news articles in files that have numeric names."
-  (interactive
-   (list (read-directory-name "Create group from directory: ")))
+  (interactive (list (read-directory-name "Create group from directory: "))
+              gnus-group-mode)
   (unless (file-exists-p dir)
     (error "No such directory"))
   (unless (file-directory-p dir)
@@ -3192,7 +3197,7 @@ prefix arg NO-PARSE means that Gnus should not parse the 
search
 query before passing it to the underlying search engine.  A
 non-nil SPECS arg must be an alist with `search-query-spec' and
 `search-group-spec' keys, and skips all prompting."
-  (interactive "P")
+  (interactive "P" gnus-group-mode)
   (let ((name (gnus-read-group "Group name: ")))
     (with-current-buffer gnus-group-buffer
       (let* ((group-spec
@@ -3246,7 +3251,7 @@ prefix arg NO-PARSE means that Gnus should not parse the 
search
 query before passing it to the underlying search engine.  A
 non-nil SPECS arg must be an alist with `search-query-spec' and
 `search-group-spec' keys, and skips all prompting."
-  (interactive "P")
+  (interactive "P" gnus-group-mode)
   (let* ((group-spec
          (or (cdr (assq 'search-group-spec specs))
              (cdr (assq 'nnir-group-spec specs))
@@ -3286,10 +3291,10 @@ non-nil SPECS arg must be an alist with 
`search-query-spec' and
 
 (defun gnus-group-add-to-virtual (n vgroup)
   "Add the current group to a virtual group."
-  (interactive
-   (list current-prefix-arg
-        (gnus-group-completing-read "Add to virtual group"
-                                     nil t "nnvirtual:")))
+  (interactive (list current-prefix-arg
+                    (gnus-group-completing-read "Add to virtual group"
+                                                nil t "nnvirtual:"))
+              gnus-group-mode)
   (unless (eq (car (gnus-find-method-for-group vgroup)) 'nnvirtual)
     (error "%s is not an nnvirtual group" vgroup))
   (gnus-close-group vgroup)
@@ -3307,7 +3312,7 @@ non-nil SPECS arg must be an alist with 
`search-query-spec' and
 
 (defun gnus-group-make-empty-virtual (group)
   "Create a new, fresh, empty virtual group."
-  (interactive "sCreate new, empty virtual group: ")
+  (interactive "sCreate new, empty virtual group: " gnus-group-mode)
   (let* ((method (list 'nnvirtual "^$"))
         (pgroup (gnus-group-prefixed-name group method)))
     ;; Check whether it exists already.
@@ -3321,7 +3326,7 @@ non-nil SPECS arg must be an alist with 
`search-query-spec' and
 
 (defun gnus-group-enter-directory (dir)
   "Enter an ephemeral nneething group."
-  (interactive "DDirectory to read: ")
+  (interactive "DDirectory to read: " gnus-group-mode)
   (let* ((method (list 'nneething dir '(nneething-read-only t)))
         (leaf (gnus-group-prefixed-name
                (file-name-nondirectory (directory-file-name dir))
@@ -3336,7 +3341,7 @@ non-nil SPECS arg must be an alist with 
`search-query-spec' and
 
 (defun gnus-group-expunge-group (group)
   "Expunge deleted articles in current nnimap GROUP."
-  (interactive (list (gnus-group-group-name)))
+  (interactive (list (gnus-group-group-name)) gnus-group-mode)
   (let ((method (gnus-find-method-for-group group)))
     (if (not (gnus-check-backend-function
              'request-expunge-group (car method)))
@@ -3348,7 +3353,7 @@ non-nil SPECS arg must be an alist with 
`search-query-spec' and
 
 (defun gnus-group-nnimap-edit-acl (group)
   "Edit the Access Control List of current nnimap GROUP."
-  (interactive (list (gnus-group-group-name)))
+  (interactive (list (gnus-group-group-name)) gnus-group-mode)
   (let ((mailbox (gnus-group-real-name group)) method acl)
     (unless group
       (error "No group on current line"))
@@ -3395,7 +3400,8 @@ Editing the access control list for `%s'.
 When used interactively, the sorting function used will be
 determined by the `gnus-group-sort-function' variable.
 If REVERSE (the prefix), reverse the sorting order."
-  (interactive (list gnus-group-sort-function current-prefix-arg))
+  (interactive (list gnus-group-sort-function current-prefix-arg)
+              gnus-group-mode)
   (funcall gnus-group-sort-alist-function
           (gnus-make-sort-function func) reverse)
   (gnus-group-unmark-all-groups)
@@ -3428,56 +3434,57 @@ value is disregarded."
 (defun gnus-group-sort-groups-by-alphabet (&optional reverse)
   "Sort the group buffer alphabetically by group name.
 If REVERSE, sort in reverse order."
-  (interactive "P")
+  (interactive "P" gnus-group-mode)
   (gnus-group-sort-groups 'gnus-group-sort-by-alphabet reverse))
 
 (defun gnus-group-sort-groups-by-real-name (&optional reverse)
   "Sort the group buffer alphabetically by real (unprefixed) group name.
 If REVERSE, sort in reverse order."
-  (interactive "P")
+  (interactive "P" gnus-group-mode)
   (gnus-group-sort-groups 'gnus-group-sort-by-real-name reverse))
 
 (defun gnus-group-sort-groups-by-unread (&optional reverse)
   "Sort the group buffer by number of unread articles.
 If REVERSE, sort in reverse order."
-  (interactive "P")
+  (interactive "P" gnus-group-mode)
   (gnus-group-sort-groups 'gnus-group-sort-by-unread reverse))
 
 (defun gnus-group-sort-groups-by-level (&optional reverse)
   "Sort the group buffer by group level.
 If REVERSE, sort in reverse order."
-  (interactive "P")
+  (interactive "P" gnus-group-mode)
   (gnus-group-sort-groups 'gnus-group-sort-by-level reverse))
 
 (defun gnus-group-sort-groups-by-score (&optional reverse)
   "Sort the group buffer by group score.
 If REVERSE, sort in reverse order."
-  (interactive "P")
+  (interactive "P" gnus-group-mode)
   (gnus-group-sort-groups 'gnus-group-sort-by-score reverse))
 
 (defun gnus-group-sort-groups-by-rank (&optional reverse)
   "Sort the group buffer by group rank.
 If REVERSE, sort in reverse order."
-  (interactive "P")
+  (interactive "P" gnus-group-mode)
   (gnus-group-sort-groups 'gnus-group-sort-by-rank reverse))
 
 (defun gnus-group-sort-groups-by-method (&optional reverse)
   "Sort the group buffer alphabetically by back end name.
 If REVERSE, sort in reverse order."
-  (interactive "P")
+  (interactive "P" gnus-group-mode)
   (gnus-group-sort-groups 'gnus-group-sort-by-method reverse))
 
 (defun gnus-group-sort-groups-by-server (&optional reverse)
   "Sort the group buffer alphabetically by server name.
 If REVERSE, sort in reverse order."
-  (interactive "P")
+  (interactive "P" gnus-group-mode)
   (gnus-group-sort-groups 'gnus-group-sort-by-server reverse))
 
 ;;; Selected group sorting.
 
 (defun gnus-group-sort-selected-groups (n func &optional reverse)
   "Sort the process/prefixed groups."
-  (interactive (list current-prefix-arg gnus-group-sort-function))
+  (interactive (list current-prefix-arg gnus-group-sort-function)
+              gnus-group-mode)
   (let ((groups (gnus-group-process-prefix n)))
     (funcall gnus-group-sort-selected-function
             groups (gnus-make-sort-function func) reverse)
@@ -3509,49 +3516,49 @@ If REVERSE is non-nil, reverse the sorting."
   "Sort the group buffer alphabetically by group name.
 Obeys the process/prefix convention.  If REVERSE (the symbolic prefix),
 sort in reverse order."
-  (interactive (gnus-interactive "P\ny"))
+  (interactive (gnus-interactive "P\ny") gnus-group-mode)
   (gnus-group-sort-selected-groups n 'gnus-group-sort-by-alphabet reverse))
 
 (defun gnus-group-sort-selected-groups-by-real-name (&optional n reverse)
   "Sort the group buffer alphabetically by real group name.
 Obeys the process/prefix convention.  If REVERSE (the symbolic prefix),
 sort in reverse order."
-  (interactive (gnus-interactive "P\ny"))
+  (interactive (gnus-interactive "P\ny") gnus-group-mode)
   (gnus-group-sort-selected-groups n 'gnus-group-sort-by-real-name reverse))
 
 (defun gnus-group-sort-selected-groups-by-unread (&optional n reverse)
   "Sort the group buffer by number of unread articles.
 Obeys the process/prefix convention.  If REVERSE (the symbolic prefix),
 sort in reverse order."
-  (interactive (gnus-interactive "P\ny"))
+  (interactive (gnus-interactive "P\ny") gnus-group-mode)
   (gnus-group-sort-selected-groups n 'gnus-group-sort-by-unread reverse))
 
 (defun gnus-group-sort-selected-groups-by-level (&optional n reverse)
   "Sort the group buffer by group level.
 Obeys the process/prefix convention.  If REVERSE (the symbolic prefix),
 sort in reverse order."
-  (interactive (gnus-interactive "P\ny"))
+  (interactive (gnus-interactive "P\ny") gnus-group-mode)
   (gnus-group-sort-selected-groups n 'gnus-group-sort-by-level reverse))
 
 (defun gnus-group-sort-selected-groups-by-score (&optional n reverse)
   "Sort the group buffer by group score.
 Obeys the process/prefix convention.  If REVERSE (the symbolic prefix),
 sort in reverse order."
-  (interactive (gnus-interactive "P\ny"))
+  (interactive (gnus-interactive "P\ny") gnus-group-mode)
   (gnus-group-sort-selected-groups n 'gnus-group-sort-by-score reverse))
 
 (defun gnus-group-sort-selected-groups-by-rank (&optional n reverse)
   "Sort the group buffer by group rank.
 Obeys the process/prefix convention.  If REVERSE (the symbolic prefix),
 sort in reverse order."
-  (interactive (gnus-interactive "P\ny"))
+  (interactive (gnus-interactive "P\ny") gnus-group-mode)
   (gnus-group-sort-selected-groups n 'gnus-group-sort-by-rank reverse))
 
 (defun gnus-group-sort-selected-groups-by-method (&optional n reverse)
   "Sort the group buffer alphabetically by back end name.
 Obeys the process/prefix convention.  If REVERSE (the symbolic prefix),
 sort in reverse order."
-  (interactive (gnus-interactive "P\ny"))
+  (interactive (gnus-interactive "P\ny") gnus-group-mode)
   (gnus-group-sort-selected-groups n 'gnus-group-sort-by-method reverse))
 
 ;;; Sorting predicates.
@@ -3609,7 +3616,7 @@ sort in reverse order."
 (defun gnus-group-clear-data (&optional arg)
   "Clear all marks and read ranges from the current group.
 Obeys the process/prefix convention."
-  (interactive "P")
+  (interactive "P" gnus-group-mode)
   (when (gnus-y-or-n-p "Really clear data? ")
     (gnus-group-iterate arg
       (lambda (group)
@@ -3621,7 +3628,7 @@ Obeys the process/prefix convention."
 
 (defun gnus-group-clear-data-on-native-groups ()
   "Clear all marks and read ranges from all native groups."
-  (interactive)
+  (interactive nil gnus-group-mode)
   (when (gnus-yes-or-no-p "Really clear all data from almost all groups? ")
     (let ((alist (cdr gnus-newsrc-alist))
          info)
@@ -3665,7 +3672,7 @@ caught up.  If ALL is non-nil, marked articles will also 
be marked as
 read.  Cross references (Xref: header) of articles are ignored.
 The number of newsgroups that this function was unable to catch
 up is returned."
-  (interactive "P")
+  (interactive "P" gnus-group-mode)
   (let ((groups (gnus-group-process-prefix n))
        (ret 0)
        group)
@@ -3704,7 +3711,7 @@ up is returned."
 (defun gnus-group-catchup-current-all (&optional n)
   "Mark all articles in current newsgroup as read.
 Cross references (Xref: header) of articles are ignored."
-  (interactive "P")
+  (interactive "P" gnus-group-mode)
   (gnus-group-catchup-current n 'all))
 
 (declare-function gnus-sequence-of-unread-articles "gnus-sum" (group))
@@ -3751,7 +3758,7 @@ or nil if no action could be taken."
 (defun gnus-group-expire-articles (&optional n)
   "Expire all expirable articles in the current newsgroup.
 Uses the process/prefix convention."
-  (interactive "P")
+  (interactive "P" gnus-group-mode)
   (let ((groups (gnus-group-process-prefix n))
        group)
     (unless groups
@@ -3797,7 +3804,7 @@ Uses the process/prefix convention."
 
 (defun gnus-group-expire-all-groups ()
   "Expire all expirable articles in all newsgroups."
-  (interactive)
+  (interactive nil gnus-group-mode)
   (save-excursion
     (gnus-message 5 "Expiring...")
     (let ((gnus-group-marked (mapcar (lambda (info) (gnus-info-group info))
@@ -3821,7 +3828,8 @@ Uses the process/prefix convention."
         (if (string-match "^\\s-*$" s)
             (int-to-string (or (gnus-group-group-level)
                                gnus-level-default-subscribed))
-          s))))))
+          s)))))
+   gnus-group-mode)
   (unless (and (>= level 1) (<= level gnus-level-killed))
     (error "Invalid level: %d" level))
   (dolist (group (gnus-group-process-prefix n))
@@ -3837,18 +3845,18 @@ Uses the process/prefix convention."
 
 (defun gnus-group-unsubscribe (&optional n)
   "Unsubscribe the current group."
-  (interactive "P")
+  (interactive "P" gnus-group-mode)
   (gnus-group-unsubscribe-current-group n 'unsubscribe))
 
 (defun gnus-group-subscribe (&optional n)
   "Subscribe the current group."
-  (interactive "P")
+  (interactive "P" gnus-group-mode)
   (gnus-group-unsubscribe-current-group n 'subscribe))
 
 (defun gnus-group-unsubscribe-current-group (&optional n do-sub)
   "Toggle subscription of the current group.
 If given numerical prefix, toggle the N next groups."
-  (interactive "P")
+  (interactive "P" gnus-group-mode)
   (dolist (group (gnus-group-process-prefix n))
     (gnus-group-remove-mark group)
     (gnus-group-unsubscribe-group
@@ -3871,7 +3879,8 @@ If given numerical prefix, toggle the N next groups."
 Killed newsgroups are subscribed.  If SILENT, don't try to update the
 group line."
   (interactive (list (gnus-group-completing-read
-                     nil nil (gnus-read-active-file-p))))
+                     nil nil (gnus-read-active-file-p)))
+              gnus-group-mode)
   (let ((newsrc (gnus-group-entry group)))
     (cond
      ((string-match "\\`[ \t]*\\'" group)
@@ -3905,7 +3914,7 @@ group line."
   "Move the current newsgroup up N places.
 If given a negative prefix, move down instead.  The difference between
 N and the number of steps taken is returned."
-  (interactive "p")
+  (interactive "p" gnus-group-mode)
   (unless (gnus-group-group-name)
     (error "No group on current line"))
   (gnus-group-kill-group 1)
@@ -3917,7 +3926,8 @@ N and the number of steps taken is returned."
 (defun gnus-group-kill-all-zombies (&optional dummy)
   "Kill all zombie newsgroups.
 The optional DUMMY should always be nil."
-  (interactive (list (not (gnus-yes-or-no-p "Really kill all zombies? "))))
+  (interactive (list (not (gnus-yes-or-no-p "Really kill all zombies? ")))
+              gnus-group-mode)
   (unless dummy
     (setq gnus-killed-list (nconc gnus-zombie-list gnus-killed-list))
     (setq gnus-zombie-list nil)
@@ -3927,7 +3937,7 @@ The optional DUMMY should always be nil."
 (defun gnus-group-kill-region (begin end)
   "Kill newsgroups in current region (excluding current point).
 The killed newsgroups can be yanked by using \\[gnus-group-yank-group]."
-  (interactive "r")
+  (interactive "r" gnus-group-mode)
   (let ((lines
         ;; Count lines.
         (save-excursion
@@ -3949,7 +3959,7 @@ However, only groups that were alive can be yanked; 
already killed
 groups or zombie groups can't be yanked.
 The return value is the name of the group that was killed, or a list
 of groups killed."
-  (interactive "P")
+  (interactive "P" gnus-group-mode)
   (let ((buffer-read-only nil)
        (groups (gnus-group-process-prefix n))
        group entry level out)
@@ -4009,7 +4019,7 @@ of groups killed."
 The numeric ARG specifies how many newsgroups are to be yanked.  The
 name of the newsgroup yanked is returned, or (if several groups are
 yanked) a list of yanked groups is returned."
-  (interactive "p")
+  (interactive "p" gnus-group-mode)
   (setq arg (or arg 1))
   (let (info group prev out)
     (while (>= (cl-decf arg) 0)
@@ -4034,7 +4044,7 @@ yanked) a list of yanked groups is returned."
 
 (defun gnus-group-kill-level (level)
   "Kill all groups that is on a certain LEVEL."
-  (interactive "nKill all groups on level: ")
+  (interactive "nKill all groups on level: " gnus-group-mode)
   (cond
    ((= level gnus-level-zombie)
     (setq gnus-killed-list
@@ -4065,7 +4075,7 @@ yanked) a list of yanked groups is returned."
   "List all newsgroups with level ARG or lower.
 Default is `gnus-level-unsubscribed', which lists all subscribed and most
 unsubscribed groups."
-  (interactive "P")
+  (interactive "P" gnus-group-mode)
   (gnus-group-list-groups (or arg gnus-level-unsubscribed) t))
 
 ;; Redefine this to list ALL killed groups if prefix arg used.
@@ -4074,7 +4084,7 @@ unsubscribed groups."
   "List all killed newsgroups in the group buffer.
 If ARG is non-nil, list ALL killed groups known to Gnus.  This may
 entail asking the server for the groups."
-  (interactive "P")
+  (interactive "P" gnus-group-mode)
   ;; Find all possible killed newsgroups if arg.
   (when arg
     (gnus-get-killed-groups))
@@ -4088,7 +4098,7 @@ entail asking the server for the groups."
 
 (defun gnus-group-list-zombies ()
   "List all zombie newsgroups in the group buffer."
-  (interactive)
+  (interactive nil gnus-group-mode)
   (if (not gnus-zombie-list)
       (gnus-message 6 "No zombie groups")
     (let (gnus-group-list-mode)
@@ -4099,7 +4109,7 @@ entail asking the server for the groups."
 
 (defun gnus-group-list-active ()
   "List all groups that are available from the server(s)."
-  (interactive)
+  (interactive nil gnus-group-mode)
   ;; First we make sure that we have really read the active file.
   (unless (gnus-read-active-file-p)
     (let ((gnus-read-active-file t)
@@ -4121,7 +4131,7 @@ entail asking the server for the groups."
 
 (defun gnus-activate-all-groups (level)
   "Activate absolutely all groups."
-  (interactive (list gnus-level-unsubscribed))
+  (interactive (list gnus-level-unsubscribed) gnus-group-mode)
   (let ((gnus-activate-level level)
        (gnus-activate-foreign-newsgroups level))
     (gnus-group-get-new-news)))
@@ -4133,7 +4143,7 @@ re-scanning.  If ARG is non-nil and not a number, this 
will force
 \"hard\" re-reading of the active files from all servers.
 If ONE-LEVEL is not nil, then re-scan only the specified level,
 otherwise all levels below ARG will be scanned too."
-  (interactive "P")
+  (interactive "P" gnus-group-mode)
   (require 'nnmail)
   (let ((gnus-inhibit-demon t)
        ;; Binding this variable will inhibit multiple fetchings
@@ -4163,7 +4173,7 @@ otherwise all levels below ARG will be scanned too."
 The difference between N and the number of newsgroup checked is returned.
 If N is negative, this group and the N-1 previous groups will be checked.
 If DONT-SCAN is non-nil, scan non-activated groups as well."
-  (interactive "P")
+  (interactive "P" gnus-group-mode)
   (let* ((groups (gnus-group-process-prefix n))
         (ret (if (numberp n) (- n (length groups)) 0))
         (beg (unless n
@@ -4208,7 +4218,8 @@ If DONT-SCAN is non-nil, scan non-activated groups as 
well."
 
 (defun gnus-group-describe-group (force &optional group)
   "Display a description of the current newsgroup."
-  (interactive (list current-prefix-arg (gnus-group-group-name)))
+  (interactive (list current-prefix-arg (gnus-group-group-name))
+              gnus-group-mode)
   (let* ((method (gnus-find-method-for-group group))
         (mname (gnus-group-prefixed-name "" method))
         desc)
@@ -4230,7 +4241,7 @@ If DONT-SCAN is non-nil, scan non-activated groups as 
well."
 ;; Suggested by Per Abrahamsen <amanda@iesd.auc.dk>.
 (defun gnus-group-describe-all-groups (&optional force)
   "Pop up a buffer with descriptions of all newsgroups."
-  (interactive "P")
+  (interactive "P" gnus-group-mode)
   (when force
     (setq gnus-description-hashtb nil))
   (when (not (or gnus-description-hashtb
@@ -4255,7 +4266,7 @@ If DONT-SCAN is non-nil, scan non-activated groups as 
well."
 ;; Suggested by Daniel Quinlan <quinlan@best.com>.
 (defun gnus-group-apropos (regexp &optional search-description)
   "List all newsgroups that have names that match a regexp."
-  (interactive "sGnus apropos (regexp): ")
+  (interactive "sGnus apropos (regexp): " gnus-group-mode)
   (let ((prev "")
        (obuf (current-buffer))
        groups des)
@@ -4294,7 +4305,7 @@ If DONT-SCAN is non-nil, scan non-activated groups as 
well."
 
 (defun gnus-group-description-apropos (regexp)
   "List all newsgroups that have names or descriptions that match REGEXP."
-  (interactive "sGnus description apropos (regexp): ")
+  (interactive "sGnus description apropos (regexp): " gnus-group-mode)
   (when (not (or gnus-description-hashtb
                 (gnus-read-all-descriptions-files)))
     (error "Couldn't request descriptions file"))
@@ -4309,7 +4320,7 @@ If ALL, also list groups with no unread articles.
 If LOWEST, don't list groups with level lower than LOWEST.
 
 This command may read the active file."
-  (interactive "P\nsList newsgroups matching: ")
+  (interactive "P\nsList newsgroups matching: " gnus-group-mode)
   ;; First make sure active file has been read.
   (when (and level
             (> (prefix-numeric-value level) gnus-level-killed))
@@ -4324,7 +4335,7 @@ This command may read the active file."
 If the prefix LEVEL is non-nil, it should be a number that says which
 level to cut off listing groups.
 If LOWEST, don't list groups with level lower than LOWEST."
-  (interactive "P\nsList newsgroups matching: ")
+  (interactive "P\nsList newsgroups matching: " gnus-group-mode)
   (when level
     (setq level (prefix-numeric-value level)))
   (gnus-group-list-matching (or level gnus-level-killed) regexp t lowest))
@@ -4333,12 +4344,12 @@ If LOWEST, don't list groups with level lower than 
LOWEST."
 (defun gnus-group-save-newsrc (&optional force)
   "Save the Gnus startup files.
 If FORCE, force saving whether it is necessary or not."
-  (interactive "P")
+  (interactive "P" gnus-group-mode)
   (gnus-save-newsrc-file force))
 
 (defun gnus-group-restart (&optional _arg)
   "Force Gnus to read the .newsrc file."
-  (interactive)
+  (interactive nil gnus-group-mode)
   (when (gnus-yes-or-no-p
         (format "Are you sure you want to restart Gnus? "))
     (gnus-save-newsrc-file)
@@ -4347,7 +4358,7 @@ If FORCE, force saving whether it is necessary or not."
 
 (defun gnus-group-read-init-file ()
   "Read the Gnus elisp init file."
-  (interactive)
+  (interactive nil gnus-group-mode)
   (gnus-read-init-file)
   (gnus-message 5 "Read %s" gnus-init-file))
 
@@ -4355,7 +4366,7 @@ If FORCE, force saving whether it is necessary or not."
   "Check bogus newsgroups.
 If given a prefix, don't ask for confirmation before removing a bogus
 group."
-  (interactive "P")
+  (interactive "P" gnus-group-mode)
   (gnus-check-bogus-newsgroups (and (not silent) (not gnus-expert-user)))
   (gnus-group-list-groups))
 
@@ -4366,7 +4377,7 @@ With 1 C-u, use the `ask-server' method to query the 
server for new
 groups.
 With 2 C-u's, use most complete method possible to query the server
 for new groups, and subscribe the new groups as zombies."
-  (interactive "p")
+  (interactive "p" gnus-group-mode)
   (let ((new-groups (gnus-find-new-newsgroups (or arg 1)))
        current-group)
     (gnus-group-list-groups)
@@ -4379,7 +4390,7 @@ for new groups, and subscribe the new groups as zombies."
 (defun gnus-group-edit-global-kill (&optional article group)
   "Edit the global kill file.
 If GROUP, edit that local kill file instead."
-  (interactive "P")
+  (interactive "P" gnus-group-mode)
   (setq gnus-current-kill-article article)
   (gnus-kill-file-edit-file group)
   (gnus-message 6 "Editing a %s kill file (Type %s to exit)"
@@ -4388,12 +4399,12 @@ If GROUP, edit that local kill file instead."
 
 (defun gnus-group-edit-local-kill (article group)
   "Edit a local kill file."
-  (interactive (list nil (gnus-group-group-name)))
+  (interactive (list nil (gnus-group-group-name)) gnus-group-mode)
   (gnus-group-edit-global-kill article group))
 
 (defun gnus-group-force-update ()
   "Update `.newsrc' file."
-  (interactive)
+  (interactive nil gnus-group-mode)
   (gnus-save-newsrc-file))
 
 (defvar gnus-backlog-articles)
@@ -4402,7 +4413,7 @@ If GROUP, edit that local kill file instead."
   "Suspend the current Gnus session.
 In fact, cleanup buffers except for group mode buffer.
 The hook `gnus-suspend-gnus-hook' is called before actually suspending."
-  (interactive)
+  (interactive nil gnus-group-mode)
   (gnus-run-hooks 'gnus-suspend-gnus-hook)
   (gnus-offer-save-summaries)
   ;; Kill Gnus buffers except for group mode buffer.
@@ -4425,14 +4436,14 @@ The hook `gnus-suspend-gnus-hook' is called before 
actually suspending."
 
 (defun gnus-group-clear-dribble ()
   "Clear all information from the dribble buffer."
-  (interactive)
+  (interactive nil gnus-group-mode)
   (gnus-dribble-clear)
   (gnus-message 7 "Cleared dribble buffer"))
 
 (defun gnus-group-exit ()
   "Quit reading news after updating .newsrc.eld and .newsrc.
 The hook `gnus-exit-gnus-hook' is called before actually exiting."
-  (interactive)
+  (interactive nil gnus-group-mode)
   (when
       (or noninteractive               ;For gnus-batch-kill
          (not gnus-interactive-exit)   ;Without confirmation
@@ -4466,7 +4477,7 @@ The hook `gnus-exit-gnus-hook' is called before actually 
exiting."
 (defun gnus-group-quit ()
   "Quit reading news without updating .newsrc.eld or .newsrc.
 The hook `gnus-exit-gnus-hook' is called before actually exiting."
-  (interactive)
+  (interactive nil gnus-group-mode)
   (when (or noninteractive             ;For gnus-batch-kill
            (zerop (buffer-size))
            (not (gnus-server-opened gnus-select-method))
@@ -4491,7 +4502,7 @@ The hook `gnus-exit-gnus-hook' is called before actually 
exiting."
 
 (defun gnus-group-describe-briefly ()
   "Give a one line description of the group mode commands."
-  (interactive)
+  (interactive nil gnus-group-mode)
   (gnus-message 7 "%s" (substitute-command-keys 
"\\<gnus-group-mode-map>\\[gnus-group-read-group]:Select  
\\[gnus-group-next-unread-group]:Forward  
\\[gnus-group-prev-unread-group]:Backward  \\[gnus-group-exit]:Exit  
\\[gnus-info-find-node]:Run Info  \\[gnus-group-describe-briefly]:This help")))
 
 (defun gnus-group-browse-foreign-server (method)
@@ -4504,7 +4515,7 @@ and the second element is the address."
    (list (let ((how (gnus-completing-read
                     "Which back end"
                     (mapcar #'car (append gnus-valid-select-methods
-                                         gnus-server-alist))
+                                          gnus-server-alist))
                     t (cons "nntp" 0) 'gnus-method-history)))
           ;; We either got a back end name or a virtual server name.
           ;; If the first, we also need an address.
@@ -4520,7 +4531,8 @@ and the second element is the address."
                          gnus-secondary-servers
                        (cdr gnus-select-method))))
             ;; We got a server name.
-            how))))
+            how)))
+   gnus-group-mode)
   (gnus-browse-foreign-server method))
 
 (defun gnus-group-set-info (info &optional method-only-group part)
@@ -4678,7 +4690,7 @@ level to cut off listing groups.
 If LOWEST, don't list groups with level lower than LOWEST.
 
 This command may read the active file."
-  (interactive "P")
+  (interactive "P" gnus-group-mode)
   (when level
     (setq level (prefix-numeric-value level)))
   (when (or (not level) (>= level gnus-level-zombie))
@@ -4709,7 +4721,7 @@ level to cut off listing groups.
 If LOWEST, don't list groups with level lower than LOWEST.
 
 This command may read the active file."
-  (interactive "P")
+  (interactive "P" gnus-group-mode)
   (when level
     (setq level (prefix-numeric-value level)))
   (when (or (not level) (>= level gnus-level-zombie))
@@ -4731,7 +4743,7 @@ level to cut off listing groups.
 If LOWEST, don't list groups with level lower than LOWEST.
 
 This command may read the active file."
-  (interactive "P")
+  (interactive "P" gnus-group-mode)
   (when level
     (setq level (prefix-numeric-value level)))
   (when (or (not level) (>= level gnus-level-zombie))
@@ -4759,7 +4771,7 @@ This command may read the active file."
 
 (defun gnus-group-list-plus (&optional _args)
   "List groups plus the current selection."
-  (interactive)
+  (interactive nil gnus-group-mode)
   (let ((gnus-group-listed-groups (gnus-group-listed-groups))
        (gnus-group-list-mode gnus-group-list-mode) ;; Save it.
        func)
@@ -4775,7 +4787,7 @@ This command may read the active file."
 
 (defun gnus-group-list-flush (&optional args)
   "Flush groups from the current selection."
-  (interactive "P")
+  (interactive "P" gnus-group-mode)
   (let ((gnus-group-list-option 'flush))
     (gnus-group-list-plus args)))
 
@@ -4786,7 +4798,7 @@ with this command.  If you've first limited to groups with
 dormant articles with `A ?', you can then further limit with
 `A / c', which will then limit to groups with cached articles, giving
 you the groups that have both dormant articles and cached articles."
-  (interactive "P")
+  (interactive "P" gnus-group-mode)
   (let ((gnus-group-list-option 'limit))
     (gnus-group-list-plus args)))
 
@@ -4839,7 +4851,7 @@ operation is only meaningful for back ends using one file 
per article
 \(e.g. nnml).
 
 Note: currently only implemented in nnml."
-  (interactive (list (gnus-group-group-name)))
+  (interactive (list (gnus-group-group-name)) gnus-group-mode)
   (unless group
     (error "No group to compact"))
   (unless (gnus-check-backend-function 'request-compact-group group)
diff --git a/lisp/gnus/gnus-icalendar.el b/lisp/gnus/gnus-icalendar.el
index 9811e8b..1b2743c 100644
--- a/lisp/gnus/gnus-icalendar.el
+++ b/lisp/gnus/gnus-icalendar.el
@@ -970,7 +970,7 @@ These will be used to retrieve the RSVP information from 
ical events."
 
 (defun gnus-icalendar-save-event ()
   "Save the Calendar event in the text/calendar part under point."
-  (interactive)
+  (interactive nil gnus-article-mode gnus-summary-mode)
   (gnus-article-check-buffer)
   (let ((data (get-text-property (point) 'gnus-data)))
     (when data
@@ -978,28 +978,28 @@ These will be used to retrieve the RSVP information from 
ical events."
 
 (defun gnus-icalendar-reply-accept ()
   "Accept invitation in the current article."
-  (interactive)
+  (interactive nil gnus-article-mode gnus-summary-mode)
   (with-current-buffer gnus-article-buffer
     (gnus-icalendar-reply (list gnus-icalendar-handle 'accepted 
gnus-icalendar-event))
     (setq-local gnus-icalendar-reply-status 'accepted)))
 
 (defun gnus-icalendar-reply-tentative ()
   "Send tentative response to invitation in the current article."
-  (interactive)
+  (interactive nil gnus-article-mode gnus-summary-mode)
   (with-current-buffer gnus-article-buffer
     (gnus-icalendar-reply (list gnus-icalendar-handle 'tentative 
gnus-icalendar-event))
     (setq-local gnus-icalendar-reply-status 'tentative)))
 
 (defun gnus-icalendar-reply-decline ()
   "Decline invitation in the current article."
-  (interactive)
+  (interactive nil gnus-article-mode gnus-summary-mode)
   (with-current-buffer gnus-article-buffer
     (gnus-icalendar-reply (list gnus-icalendar-handle 'declined 
gnus-icalendar-event))
     (setq-local gnus-icalendar-reply-status 'declined)))
 
 (defun gnus-icalendar-event-export ()
   "Export calendar event to `org-mode', or update existing agenda entry."
-  (interactive)
+  (interactive nil gnus-article-mode gnus-summary-mode)
   (with-current-buffer gnus-article-buffer
     (gnus-icalendar-sync-event-to-org gnus-icalendar-event))
   ;; refresh article buffer in case the reply had been sent before initial org
@@ -1009,14 +1009,14 @@ These will be used to retrieve the RSVP information 
from ical events."
 
 (defun gnus-icalendar-event-show ()
   "Display `org-mode' agenda entry related to the calendar event."
-  (interactive)
+  (interactive nil gnus-article-mode gnus-summary-mode)
   (gnus-icalendar--show-org-event
    (with-current-buffer gnus-article-buffer
      gnus-icalendar-event)))
 
 (defun gnus-icalendar-event-check-agenda ()
   "Display `org-mode' agenda for days between event start and end dates."
-  (interactive)
+  (interactive nil gnus-article-mode gnus-summary-mode)
   (gnus-icalendar-show-org-agenda
    (with-current-buffer gnus-article-buffer gnus-icalendar-event)))
 
diff --git a/lisp/gnus/gnus-int.el b/lisp/gnus/gnus-int.el
index 6492862..0105379 100644
--- a/lisp/gnus/gnus-int.el
+++ b/lisp/gnus/gnus-int.el
@@ -662,7 +662,7 @@ This is the string that Gnus uses to identify the group."
   "Look up the current article in the group where it originated.
 This command only makes sense for groups shows articles gathered
 from other groups -- for instance, search results and the like."
-  (interactive)
+  (interactive nil gnus-summary-mode)
   (let ((gnus-command-method
          (gnus-find-method-for-group gnus-newsgroup-name)))
     (or
diff --git a/lisp/gnus/gnus-kill.el b/lisp/gnus/gnus-kill.el
index b0e6cb5..f73627a 100644
--- a/lisp/gnus/gnus-kill.el
+++ b/lisp/gnus/gnus-kill.el
@@ -337,7 +337,7 @@ Returns the number of articles marked as read."
                           (gnus-newsgroup-kill-file gnus-newsgroup-name)))
         (unreads (length gnus-newsgroup-unreads))
         (gnus-summary-inhibit-highlight t)
-        beg)
+        ) ;; beg
     (setq gnus-newsgroup-kill-headers nil)
     ;; If there are any previously scored articles, we remove these
     ;; from the `gnus-newsgroup-headers' list that the score functions
@@ -381,7 +381,7 @@ Returns the number of articles marked as read."
 
       (gnus-set-mode-line 'summary)
 
-      (if beg
+      (if nil ;; beg
          (let ((nunreads (- unreads (length gnus-newsgroup-unreads))))
            (or (eq nunreads 0)
                (gnus-message 6 "Marked %d articles as read" nunreads))
diff --git a/lisp/gnus/gnus-mh.el b/lisp/gnus/gnus-mh.el
index fc8d9be..df076c1 100644
--- a/lisp/gnus/gnus-mh.el
+++ b/lisp/gnus/gnus-mh.el
@@ -53,7 +53,7 @@ If N is a positive number, save the N next articles.
 If N is a negative number, save the N previous articles.
 If N is nil and any articles have been marked with the process mark,
 save those articles instead."
-  (interactive "P")
+  (interactive "P" gnus-summary-mode)
   (require 'gnus-art)
   (let ((gnus-default-article-saver 'gnus-summary-save-in-folder))
     (gnus-summary-save-article arg)))
diff --git a/lisp/gnus/gnus-msg.el b/lisp/gnus/gnus-msg.el
index 45e665b..f1181d4 100644
--- a/lisp/gnus/gnus-msg.el
+++ b/lisp/gnus/gnus-msg.el
@@ -143,9 +143,6 @@ See Info node `(gnus)Posting Styles'."
   :group 'gnus-message
   :type 'boolean)
 
-(make-obsolete-variable 'gnus-inews-mark-gcc-as-read
-                       'gnus-gcc-mark-as-read "Emacs 22.1")
-
 (defcustom gnus-gcc-externalize-attachments nil
   "Should local-file attachments be included as external parts in Gcc copies?
 If it is `all', attach files as external parts;
@@ -609,8 +606,6 @@ instead."
 If ARG, use the group under the point to find a posting style.
 If ARG is 1, prompt for a group name to find the posting style."
   (interactive "P")
-  ;; We can't `let' gnus-newsgroup-name here, since that leads
-  ;; to local variables leaking.
   (let* (;;(group gnus-newsgroup-name)
         ;; make sure last viewed article doesn't affect posting styles:
         (gnus-article-copy)
@@ -634,8 +629,6 @@ This function prepares a news even when using mail groups.  
This is useful
 for posting messages to mail groups without actually sending them over the
 network.  The corresponding back end must have a `request-post' method."
   (interactive "P")
-  ;; We can't `let' gnus-newsgroup-name here, since that leads
-  ;; to local variables leaking.
   (let* (;;(group gnus-newsgroup-name)
         ;; make sure last viewed article doesn't affect posting styles:
         (gnus-article-copy)
@@ -657,7 +650,7 @@ network.  The corresponding back end must have a 
`request-post' method."
 If ARG, post to group under point.  If ARG is 1, prompt for group name.
 Depending on the selected group, the message might be either a mail or
 a news."
-  (interactive "P")
+  (interactive "P" gnus-group-mode)
   ;; Bind this variable here to make message mode hooks work ok.
   (let ((gnus-newsgroup-name
         (if arg
@@ -676,9 +669,7 @@ a news."
 Use the posting of the current group by default.
 If ARG, don't do that.  If ARG is 1, prompt for group name to find the
 posting style."
-  (interactive "P")
-  ;; We can't `let' gnus-newsgroup-name here, since that leads
-  ;; to local variables leaking.
+  (interactive "P" gnus-summary-mode)
   (let* (;;(group gnus-newsgroup-name)
         ;; make sure last viewed article doesn't affect posting styles:
         (gnus-article-copy)
@@ -701,9 +692,7 @@ If ARG, don't do that.  If ARG is 1, prompt for group name 
to post to.
 This function prepares a news even when using mail groups.  This is useful
 for posting messages to mail groups without actually sending them over the
 network.  The corresponding back end must have a `request-post' method."
-  (interactive "P")
-  ;; We can't `let' gnus-newsgroup-name here, since that leads
-  ;; to local variables leaking.
+  (interactive "P" gnus-summary-mode)
   (let* (;;(group gnus-newsgroup-name)
         ;; make sure last viewed article doesn't affect posting styles:
         (gnus-article-copy)
@@ -730,7 +719,7 @@ network.  The corresponding back end must have a 
`request-post' method."
 If ARG, don't do that.  If ARG is 1, prompt for a group name to post to.
 Depending on the selected group, the message might be either a mail or
 a news."
-  (interactive "P")
+  (interactive "P" gnus-summary-mode)
   ;; Bind this variable here to make message mode hooks work ok.
   (let ((gnus-newsgroup-name
         (if arg
@@ -750,9 +739,9 @@ If prefix argument YANK is non-nil, the original article is 
yanked
 automatically.
 YANK is a list of elements, where the car of each element is the
 article number, and the cdr is the string to be yanked."
-  (interactive
-   (list (and current-prefix-arg
-             (gnus-summary-work-articles 1))))
+  (interactive (list (and current-prefix-arg
+                         (gnus-summary-work-articles 1)))
+              gnus-summary-mode)
   (when yank
     (gnus-summary-goto-subject
      (if (listp (car yank))
@@ -772,19 +761,19 @@ article number, and the cdr is the string to be yanked."
   "Compose a followup to an article and include the original article.
 The text in the region will be yanked.  If the region isn't
 active, the entire article will be yanked."
-  (interactive "P")
+  (interactive "P" gnus-summary-mode)
   (gnus-summary-followup (gnus-summary-work-articles n) force-news))
 
 (defun gnus-summary-followup-to-mail (&optional arg)
   "Followup to the current mail message via news."
-  (interactive
-   (list (and current-prefix-arg
-             (gnus-summary-work-articles 1))))
+  (interactive (list (and current-prefix-arg
+                         (gnus-summary-work-articles 1)))
+              gnus-summary-mode)
   (gnus-summary-followup arg t))
 
 (defun gnus-summary-followup-to-mail-with-original (&optional arg)
   "Followup to the current mail message via news."
-  (interactive "P")
+  (interactive "P" gnus-summary-mode)
   (gnus-summary-followup (gnus-summary-work-articles arg) t))
 
 (defun gnus-inews-yank-articles (articles)
@@ -819,7 +808,7 @@ active, the entire article will be yanked."
 Uses the process-prefix convention.  If given the symbolic
 prefix `a', cancel using the standard posting method; if not
 post using the current select method."
-  (interactive (gnus-interactive "P\ny"))
+  (interactive (gnus-interactive "P\ny") gnus-summary-mode)
   (let ((message-post-method
         (let ((gn gnus-newsgroup-name))
           (lambda (_arg) (gnus-post-method (eq symp 'a) gn))))
@@ -849,7 +838,7 @@ post using the current select method."
   "Compose an article that will supersede a previous article.
 This is done simply by taking the old article and adding a Supersedes
 header line with the old Message-ID."
-  (interactive)
+  (interactive nil gnus-summary-mode)
   (let ((article (gnus-summary-article-number))
        (mail-parse-charset gnus-newsgroup-charset))
     (gnus-setup-message 'reply-yank
@@ -1088,7 +1077,6 @@ If SILENT, don't prompt the user."
 (defun gnus-extended-version ()
   "Stringified Gnus version and Emacs version.
 See the variable `gnus-user-agent'."
-  (interactive)
   (if (stringp gnus-user-agent)
       gnus-user-agent
     ;; `gnus-user-agent' is a list:
@@ -1117,9 +1105,9 @@ If prefix argument YANK is non-nil, the original article 
is yanked
 automatically.
 If WIDE, make a wide reply.
 If VERY-WIDE, make a very wide reply."
-  (interactive
-   (list (and current-prefix-arg
-             (gnus-summary-work-articles 1))))
+  (interactive (list (and current-prefix-arg
+                         (gnus-summary-work-articles 1)))
+              gnus-summary-mode)
   ;; Allow user to require confirmation before replying by mail to the
   ;; author of a news article (or mail message).
   (when (or (not (or (gnus-news-group-p gnus-newsgroup-name)
@@ -1187,14 +1175,14 @@ If VERY-WIDE, make a very wide reply."
 (defun gnus-summary-reply-with-original (n &optional wide)
   "Start composing a reply mail to the current message.
 The original article will be yanked."
-  (interactive "P")
+  (interactive "P" gnus-summary-mode)
   (gnus-summary-reply (gnus-summary-work-articles n) wide))
 
 (defun gnus-summary-reply-to-list-with-original (n &optional wide)
   "Start composing a reply mail to the current message.
 The reply goes only to the mailing list.
 The original article will be yanked."
-  (interactive "P")
+  (interactive "P" gnus-summary-mode)
   (let ((message-reply-to-function
         (lambda nil
           `((To . ,(gnus-mailing-list-followup-to))))))
@@ -1206,32 +1194,32 @@ If prefix argument YANK is non-nil, the original 
article is yanked
 automatically.
 If WIDE, make a wide reply.
 If VERY-WIDE, make a very wide reply."
-  (interactive
-   (list (and current-prefix-arg
-             (gnus-summary-work-articles 1))))
+  (interactive (list (and current-prefix-arg
+                         (gnus-summary-work-articles 1)))
+              gnus-summary-mode)
   (let ((gnus-msg-force-broken-reply-to t))
     (gnus-summary-reply yank wide very-wide)))
 
 (defun gnus-summary-reply-broken-reply-to-with-original (n &optional wide)
   "Like `gnus-summary-reply-with-original' except removing reply-to field.
 The original article will be yanked."
-  (interactive "P")
+  (interactive "P" gnus-summary-mode)
   (gnus-summary-reply-broken-reply-to (gnus-summary-work-articles n) wide))
 
 (defun gnus-summary-wide-reply (&optional yank)
   "Start composing a wide reply mail to the current message.
 If prefix argument YANK is non-nil, the original article is yanked
 automatically."
-  (interactive
-   (list (and current-prefix-arg
-             (gnus-summary-work-articles 1))))
+  (interactive (list (and current-prefix-arg
+                         (gnus-summary-work-articles 1)))
+              gnus-summary-mode)
   (gnus-summary-reply yank t))
 
 (defun gnus-summary-wide-reply-with-original (n)
   "Start composing a wide reply mail to the current message.
 The original article(s) will be yanked.
 Uses the process/prefix convention."
-  (interactive "P")
+  (interactive "P" gnus-summary-mode)
   (gnus-summary-reply-with-original n t))
 
 (defun gnus-summary-very-wide-reply (&optional yank)
@@ -1244,9 +1232,9 @@ messages as the To/Cc headers.
 
 If prefix argument YANK is non-nil, the original article(s) will
 be yanked automatically."
-  (interactive
-   (list (and current-prefix-arg
-             (gnus-summary-work-articles 1))))
+  (interactive (list (and current-prefix-arg
+                         (gnus-summary-work-articles 1)))
+              gnus-summary-mode)
   (gnus-summary-reply yank t (gnus-summary-work-articles yank)))
 
 (defun gnus-summary-very-wide-reply-with-original (n)
@@ -1258,7 +1246,7 @@ The reply will include all From/Cc headers from the 
original
 messages as the To/Cc headers.
 
 The original article(s) will be yanked."
-  (interactive "P")
+  (interactive "P" gnus-summary-mode)
   (gnus-summary-reply
    (gnus-summary-work-articles n) t (gnus-summary-work-articles n)))
 
@@ -1274,7 +1262,7 @@ otherwise, use flipped `message-forward-as-mime'.
 If POST, post instead of mail.
 For the \"inline\" alternatives, also see the variable
 `message-forward-ignored-headers'."
-  (interactive "P")
+  (interactive "P" gnus-summary-mode)
   (if (cdr (gnus-summary-work-articles nil))
       ;; Process marks are given.
       (gnus-uu-digest-mail-forward nil post)
@@ -1363,7 +1351,8 @@ the message before resending."
            ;; initial-contents.
            (with-current-buffer gnus-original-article-buffer
              (nnmail-fetch-field "to"))))
-        current-prefix-arg))
+        current-prefix-arg)
+   gnus-summary-mode)
   (let ((message-header-setup-hook (copy-sequence message-header-setup-hook))
        (message-sent-hook (copy-sequence message-sent-hook))
        ;; Honor posting-style for `name' and `address' in Resent-From header.
@@ -1416,7 +1405,7 @@ the message before resending."
 A new buffer will be created to allow the user to modify body and
 contents of the message, and then, everything will happen as when
 composing a new message."
-  (interactive)
+  (interactive nil gnus-summary-mode)
   (let ((mail-parse-charset gnus-newsgroup-charset))
     (gnus-setup-message 'reply-yank
       (gnus-summary-select-article t)
@@ -1444,12 +1433,12 @@ composing a new message."
 (defun gnus-summary-post-forward (&optional arg)
   "Forward the current article to a newsgroup.
 See `gnus-summary-mail-forward' for ARG."
-  (interactive "P")
+  (interactive "P" gnus-summary-mode)
   (gnus-summary-mail-forward arg t))
 
 (defun gnus-summary-mail-crosspost-complaint (n)
   "Send a complaint about crossposting to the current article(s)."
-  (interactive "P")
+  (interactive "P" gnus-summary-mode)
   (dolist (article (gnus-summary-work-articles n))
     (set-buffer gnus-summary-buffer)
     (gnus-summary-goto-subject article)
@@ -1517,9 +1506,9 @@ Already submitted bugs can be found in the Emacs bug 
tracker:
 
 (defun gnus-summary-yank-message (buffer n)
   "Yank the current article into a composed message."
-  (interactive
-   (list (gnus-completing-read "Buffer" (message-buffers) t)
-        current-prefix-arg))
+  (interactive (list (gnus-completing-read "Buffer" (message-buffers) t)
+                    current-prefix-arg)
+              gnus-summary-mode)
   (gnus-summary-iterate n
     (let ((gnus-inhibit-treatment t))
       (gnus-summary-select-article))
@@ -1536,7 +1525,7 @@ contains some mail you have written which has been 
bounced back to
 you.
 If FETCH, try to fetch the article that this is a reply to, if indeed
 this is a reply."
-  (interactive "P")
+  (interactive "P" gnus-summary-mode)
   (gnus-summary-select-article t)
   (let (summary-buffer parent)
     (if fetch
@@ -1579,7 +1568,6 @@ this is a reply."
 
 ;; Do Gcc handling, which copied the message over to some group.
 (defun gnus-inews-do-gcc (&optional gcc)
-  (interactive)
   (save-excursion
     (save-restriction
       (message-narrow-to-headers)
@@ -1668,9 +1656,7 @@ this is a reply."
                         ;; FIXME: Should gcc-mark-as-read work when
                         ;; Gnus is not running?
                         (gnus-alive-p))
-               (if (or gnus-gcc-mark-as-read
-                       (and (boundp 'gnus-inews-mark-gcc-as-read)
-                            (symbol-value 'gnus-inews-mark-gcc-as-read)))
+                (if gnus-gcc-mark-as-read
                    (gnus-group-mark-article-read group (cdr group-art))
                  (with-current-buffer gnus-group-buffer
                    (let ((gnus-group-marked (list group))
@@ -1972,7 +1958,7 @@ created.
 
 This command uses the process/prefix convention, so if you
 process-mark several articles, they will all be attached."
-  (interactive "P")
+  (interactive "P" gnus-summary-mode)
   (let ((buffers (message-buffers))
        destination)
     ;; Set up the destination mail composition buffer.
diff --git a/lisp/gnus/gnus-picon.el b/lisp/gnus/gnus-picon.el
index 7927b88..fd4d3b8 100644
--- a/lisp/gnus/gnus-picon.el
+++ b/lisp/gnus/gnus-picon.el
@@ -244,7 +244,7 @@ replacement is added."
                     (gnus-picon-insert-glyph (pop spec) category))))))))))
 
 (defun gnus-picon-transform-newsgroups (header)
-  (interactive)
+  (interactive nil gnus-article-mode gnus-summary-mode)
   (gnus-with-article-headers
    (gnus-article-goto-header header)
    (mail-header-narrow-to-field)
@@ -283,7 +283,7 @@ replacement is added."
 (defun gnus-treat-from-picon ()
   "Display picons in the From header.
 If picons are already displayed, remove them."
-  (interactive)
+  (interactive nil gnus-article-mode gnus-summary-mode)
   (let ((wash-picon-p buffer-read-only))
     (gnus-with-article-buffer
      (if (and wash-picon-p (memq 'from-picon gnus-article-wash-types))
@@ -294,7 +294,7 @@ If picons are already displayed, remove them."
 (defun gnus-treat-mail-picon ()
   "Display picons in the Cc and To headers.
 If picons are already displayed, remove them."
-  (interactive)
+  (interactive nil gnus-article-mode gnus-summary-mode)
   (let ((wash-picon-p buffer-read-only))
     (gnus-with-article-buffer
      (if (and wash-picon-p (memq 'mail-picon gnus-article-wash-types))
@@ -306,7 +306,7 @@ If picons are already displayed, remove them."
 (defun gnus-treat-newsgroups-picon ()
   "Display picons in the Newsgroups and Followup-To headers.
 If picons are already displayed, remove them."
-  (interactive)
+  (interactive nil gnus-article-mode gnus-summary-mode)
   (let ((wash-picon-p buffer-read-only))
     (gnus-with-article-buffer
      (if (and wash-picon-p (memq 'newsgroups-picon gnus-article-wash-types))
diff --git a/lisp/gnus/gnus-registry.el b/lisp/gnus/gnus-registry.el
index 147550d..e3b9c19 100644
--- a/lisp/gnus/gnus-registry.el
+++ b/lisp/gnus/gnus-registry.el
@@ -88,7 +88,6 @@
 (require 'gnus-art)
 (require 'gnus-util)
 (require 'nnmail)
-(require 'easymenu)
 (require 'registry)
 
 (defvar gnus-adaptive-word-syntax-table)
@@ -813,7 +812,7 @@ Consults `gnus-registry-ignored-groups' and
 (defun gnus-registry-wash-for-keywords (&optional force)
   "Get the keywords of the current article.
 Overrides existing keywords with FORCE set non-nil."
-  (interactive)
+  (interactive nil gnus-article-mode gnus-summary-mode)
   (let ((id (gnus-registry-fetch-message-id-fast gnus-current-article))
         word words)
     (if (or (not (gnus-registry-get-id-key id 'keyword))
@@ -1039,13 +1038,15 @@ Uses `gnus-registry-marks' to find what shortcuts to 
install."
 
 (defun gnus-registry-set-article-mark (&rest articles)
   "Apply a mark to process-marked ARTICLES."
-  (interactive (gnus-summary-work-articles current-prefix-arg))
+  (interactive (gnus-summary-work-articles current-prefix-arg)
+              gnus-article-mode gnus-summary-mode)
   (gnus-registry-set-article-mark-internal (gnus-registry-read-mark)
                                            articles nil t))
 
 (defun gnus-registry-remove-article-mark (&rest articles)
   "Remove a mark from process-marked ARTICLES."
-  (interactive (gnus-summary-work-articles current-prefix-arg))
+  (interactive (gnus-summary-work-articles current-prefix-arg)
+              gnus-article-mode gnus-summary-mode)
   (gnus-registry-set-article-mark-internal (gnus-registry-read-mark)
                                            articles t t))
 
@@ -1069,7 +1070,8 @@ Uses `gnus-registry-marks' to find what shortcuts to 
install."
   "Get the Gnus registry marks for ARTICLES and show them if interactive.
 Uses process/prefix conventions.  For multiple articles,
 only the last one's marks are returned."
-  (interactive (gnus-summary-work-articles 1))
+  (interactive (gnus-summary-work-articles 1)
+              gnus-article-mode gnus-summary-mode)
   (let* ((article (last articles))
          (id (gnus-registry-fetch-message-id-fast article))
          (marks (when id (gnus-registry-get-id-key id 'mark))))
diff --git a/lisp/gnus/gnus-salt.el b/lisp/gnus/gnus-salt.el
index e222d24..5b746a8 100644
--- a/lisp/gnus/gnus-salt.el
+++ b/lisp/gnus/gnus-salt.el
@@ -137,6 +137,8 @@ It accepts the same format specs that 
`gnus-summary-line-format' does."
   "Start reading the picked articles.
 If given a prefix, mark all unpicked articles as read."
   (interactive "P")
+  (declare (completion (lambda (s b)
+                        (completion-minor-mode-active-p s b 'gnus-pick-mode))))
   (if gnus-newsgroup-processable
       (progn
        (gnus-summary-limit-to-articles nil)
@@ -462,7 +464,7 @@ Two predefined functions are available:
 
 (defun gnus-tree-read-summary-keys (&optional arg)
   "Read a summary buffer key sequence and execute it."
-  (interactive "P")
+  (interactive "P" gnus-tree-mode)
   (unless gnus-tree-inhibit
     (let ((buf (current-buffer))
          (gnus-tree-inhibit t)
@@ -477,7 +479,7 @@ Two predefined functions are available:
 
 (defun gnus-tree-show-summary ()
   "Reconfigure windows to show summary buffer."
-  (interactive)
+  (interactive nil gnus-tree-mode)
   (if (not (gnus-buffer-live-p gnus-summary-buffer))
       (error "There is no summary buffer for this tree buffer")
     (gnus-configure-windows 'article)
@@ -485,7 +487,7 @@ Two predefined functions are available:
 
 (defun gnus-tree-select-article (article)
   "Select the article under point, if any."
-  (interactive (list (gnus-tree-article-number)))
+  (interactive (list (gnus-tree-article-number)) gnus-tree-mode)
   (let ((buf (current-buffer)))
     (when article
       (with-current-buffer gnus-summary-buffer
@@ -494,7 +496,7 @@ Two predefined functions are available:
 
 (defun gnus-tree-pick-article (e)
   "Select the article under the mouse pointer."
-  (interactive "e")
+  (interactive "e" gnus-tree-mode)
   (mouse-set-point e)
   (gnus-tree-select-article (gnus-tree-article-number)))
 
diff --git a/lisp/gnus/gnus-score.el b/lisp/gnus/gnus-score.el
index ade0897..ce64dce 100644
--- a/lisp/gnus/gnus-score.el
+++ b/lisp/gnus/gnus-score.el
@@ -528,7 +528,8 @@ permanence, and the string to be used.  The numerical 
prefix will
 be used as SCORE.  A symbolic prefix of `a' (the SYMP parameter)
 says to use the `all.SCORE' file for the command instead of the
 current score file."
-  (interactive (gnus-interactive "P\ny"))
+  (interactive (gnus-interactive "P\ny")
+              gnus-article-mode gnus-summary-mode)
   (gnus-summary-increase-score (- (gnus-score-delta-default score)) symp))
 
 (defun gnus-score-kill-help-buffer ()
@@ -544,7 +545,8 @@ permanence, and the string to be used.  The numerical 
prefix will
 be used as SCORE.  A symbolic prefix of `a' (the SYMP parameter)
 says to use the `all.SCORE' file for the command instead of the
 current score file."
-  (interactive (gnus-interactive "P\ny"))
+  (interactive (gnus-interactive "P\ny")
+              gnus-article-mode gnus-summary-mode)
   (let* ((nscore (gnus-score-delta-default score))
         (prefix (if (< nscore 0) ?L ?I))
         (increase (> nscore 0))
@@ -931,15 +933,16 @@ TYPE is the score type.
 SCORE is the score to add.
 EXTRA is the possible non-standard header."
   (interactive (list (gnus-completing-read "Header"
-                                           (mapcar
+                                          (mapcar
                                             #'car
                                             (seq-filter
                                              (lambda (x) (fboundp (nth 2 x)))
                                              gnus-header-index))
-                                           t)
+                                          t)
                     (read-string "Match: ")
                     (if (y-or-n-p "Use regexp match? ") 'r 's)
-                    (string-to-number (read-string "Score: "))))
+                    (string-to-number (read-string "Score: ")))
+              gnus-article-mode gnus-summary-mode)
   (save-excursion
     (unless (and (stringp match) (> (length match) 0))
       (error "No match"))
@@ -974,7 +977,8 @@ EXTRA is the possible non-standard header."
   "Automatically mark articles with score below SCORE as read."
   (interactive
    (list (or (and current-prefix-arg (prefix-numeric-value current-prefix-arg))
-            (string-to-number (read-string "Mark below: ")))))
+            (string-to-number (read-string "Mark below: "))))
+   gnus-article-mode gnus-summary-mode)
   (setq score (or score gnus-summary-default-score 0))
   (gnus-score-set 'mark (list score))
   (gnus-score-set 'touched '(t))
@@ -1008,14 +1012,15 @@ EXTRA is the possible non-standard header."
   "Automatically expunge articles with score below SCORE."
   (interactive
    (list (or (and current-prefix-arg (prefix-numeric-value current-prefix-arg))
-            (string-to-number (read-string "Set expunge below: ")))))
+            (string-to-number (read-string "Set expunge below: "))))
+   gnus-article-mode gnus-summary-mode)
   (setq score (or score gnus-summary-default-score 0))
   (gnus-score-set 'expunge (list score))
   (gnus-score-set 'touched '(t)))
 
 (defun gnus-score-followup-article (&optional score)
   "Add SCORE to all followups to the article in the current buffer."
-  (interactive "P")
+  (interactive "P" gnus-article-mode gnus-summary-mode)
   (setq score (gnus-score-delta-default score))
   (when (gnus-buffer-live-p gnus-summary-buffer)
     (save-excursion
@@ -1030,7 +1035,7 @@ EXTRA is the possible non-standard header."
 
 (defun gnus-score-followup-thread (&optional score)
   "Add SCORE to all later articles in the thread the current buffer is part 
of."
-  (interactive "P")
+  (interactive "P" gnus-article-mode gnus-summary-mode)
   (setq score (gnus-score-delta-default score))
   (when (gnus-buffer-live-p gnus-summary-buffer)
     (save-excursion
@@ -1064,13 +1069,13 @@ EXTRA is the possible non-standard header."
 
 (defun gnus-summary-raise-score (n)
   "Raise the score of the current article by N."
-  (interactive "p")
+  (interactive "p" gnus-article-mode gnus-summary-mode)
   (gnus-summary-set-score (+ (gnus-summary-article-score)
                             (or n gnus-score-interactive-default-score ))))
 
 (defun gnus-summary-set-score (n)
   "Set the score of the current article to N."
-  (interactive "p")
+  (interactive "p" gnus-article-mode gnus-summary-mode)
   (save-excursion
     (gnus-summary-show-thread)
     (let ((buffer-read-only nil))
@@ -1089,7 +1094,7 @@ EXTRA is the possible non-standard header."
 (defun gnus-summary-current-score (arg)
   "Return the score of the current article.
   With prefix ARG, return the total score of the current (sub)thread."
-  (interactive "P")
+  (interactive "P" gnus-article-mode gnus-summary-mode)
   (message "%s" (if arg
                    (gnus-thread-total-score
                     (gnus-id-to-thread
@@ -1099,14 +1104,16 @@ EXTRA is the possible non-standard header."
 (defun gnus-score-change-score-file (file)
   "Change current score alist."
   (interactive
-   (list (read-file-name "Change to score file: " gnus-kill-files-directory)))
+   (list (read-file-name "Change to score file: " gnus-kill-files-directory))
+   gnus-article-mode gnus-summary-mode)
   (gnus-score-load-file file)
   (gnus-set-mode-line 'summary))
 
 (defvar gnus-score-edit-exit-function)
 (defun gnus-score-edit-current-scores (file)
   "Edit the current score alist."
-  (interactive (list gnus-current-score-file))
+  (interactive (list gnus-current-score-file)
+              gnus-article-mode gnus-summary-mode)
   (if (not gnus-current-score-file)
       (error "No current score file")
     (let ((winconf (current-window-configuration)))
@@ -2496,7 +2503,7 @@ score in `gnus-newsgroup-scored' by SCORE."
 
 (defun gnus-score-find-trace ()
   "Find all score rules that applies to the current article."
-  (interactive)
+  (interactive nil gnus-article-mode gnus-summary-mode)
   (let ((old-scored gnus-newsgroup-scored))
     (let ((gnus-newsgroup-headers
           (list (gnus-summary-article-header)))
@@ -2611,7 +2618,7 @@ the score file and its full name, including the 
directory.")
 
 (defun gnus-summary-rescore ()
   "Redo the entire scoring process in the current summary."
-  (interactive)
+  (interactive nil gnus-article-mode gnus-summary-mode)
   (gnus-score-save)
   (setq gnus-score-cache nil)
   (setq gnus-newsgroup-scored nil)
@@ -2642,7 +2649,7 @@ the score file and its full name, including the 
directory.")
 
 (defun gnus-summary-raise-same-subject-and-select (score)
   "Raise articles which has the same subject with SCORE and select the next."
-  (interactive "p")
+  (interactive "p" gnus-article-mode gnus-summary-mode)
   (let ((subject (gnus-summary-article-subject)))
     (gnus-summary-raise-score score)
     (while (gnus-summary-find-subject subject)
@@ -2651,7 +2658,7 @@ the score file and its full name, including the 
directory.")
 
 (defun gnus-summary-raise-same-subject (score)
   "Raise articles which has the same subject with SCORE."
-  (interactive "p")
+  (interactive "p" gnus-article-mode gnus-summary-mode)
   (let ((subject (gnus-summary-article-subject)))
     (gnus-summary-raise-score score)
     (while (gnus-summary-find-subject subject)
@@ -2664,7 +2671,7 @@ the score file and its full name, including the 
directory.")
 
 (defun gnus-summary-raise-thread (&optional score)
   "Raise the score of the articles in the current thread with SCORE."
-  (interactive "P")
+  (interactive "P" gnus-article-mode gnus-summary-mode)
   (setq score (gnus-score-delta-default score))
   (let (e)
     (save-excursion
@@ -2683,17 +2690,17 @@ the score file and its full name, including the 
directory.")
 
 (defun gnus-summary-lower-same-subject-and-select (score)
   "Raise articles which has the same subject with SCORE and select the next."
-  (interactive "p")
+  (interactive "p" gnus-article-mode gnus-summary-mode)
   (gnus-summary-raise-same-subject-and-select (- score)))
 
 (defun gnus-summary-lower-same-subject (score)
   "Raise articles which has the same subject with SCORE."
-  (interactive "p")
+  (interactive "p" gnus-article-mode gnus-summary-mode)
   (gnus-summary-raise-same-subject (- score)))
 
 (defun gnus-summary-lower-thread (&optional score)
   "Lower score of articles in the current thread with SCORE."
-  (interactive "P")
+  (interactive "P" gnus-article-mode gnus-summary-mode)
   (gnus-summary-raise-thread (- (gnus-score-delta-default score))))
 
 ;;; Finding score files.
diff --git a/lisp/gnus/gnus-search.el b/lisp/gnus/gnus-search.el
index d7b1c06..61a1d67 100644
--- a/lisp/gnus/gnus-search.el
+++ b/lisp/gnus/gnus-search.el
@@ -365,7 +365,7 @@ This variable can also be set per-server."
   "A list of strings representing expandable search keys.
 \"Expandable\" simply means the key can be abbreviated while
 typing in search queries, ie \"subject\" could be entered as
-\"subj\" or even \"su\", though \"s\" is ambigous between
+\"subj\" or even \"su\", though \"s\" is ambiguous between
 \"subject\" and \"since\".
 
 Ambiguous abbreviations will raise an error."
@@ -402,7 +402,7 @@ The search \"language\" is essentially a series of key:value
 expressions.  Key is most often a mail header, but there are
 other keys.  Value is a string, quoted if it contains spaces.
 Key and value are separated by a colon, no space.  Expressions
-are implictly ANDed; the \"or\" keyword can be used to
+are implicitly ANDed; the \"or\" keyword can be used to
 OR. \"not\" will negate the following expression, or keys can be
 prefixed with a \"-\".  The \"near\" operator will work for
 engines that understand it; other engines will convert it to
@@ -448,7 +448,7 @@ auto-completion of contact names and addresses for keys like
 Date values (any key in `gnus-search-date-keys') can be provided
 in any format that `parse-time-string' can parse (note that this
 can produce weird results).  Dates with missing bits will be
-interpreted as the most recent occurance thereof (ie \"march 03\"
+interpreted as the most recent occurence thereof (ie \"march 03\"
 is the most recent March 3rd).  Lastly, relative specifications
 such as 1d (one day ago) are understood.  This also accepts w, m,
 and y.  m is assumed to be 30 days.
@@ -549,7 +549,7 @@ structure.
 
 In the simplest case, they are simply consed together.  String
 KEY is converted to a symbol."
-  (let (return)
+  (let () ;; return
     (cond
      ((member key gnus-search-date-keys)
       (when (string= "after" key)
@@ -559,7 +559,7 @@ KEY is converted to a symbol."
       (setq value (gnus-search-query-parse-mark value)))
      ((string= "message-id" key)
       (setq key "id")))
-    (or return
+    (or nil ;; return
        (cons (intern key) value))))
 
 (defun gnus-search-query-parse-date (value &optional rel-date)
@@ -646,7 +646,7 @@ gnus-*-mark marks, and return an appropriate string."
   "Return a string from the current buffer.
 If DELIMITED is non-nil, assume the next character is a delimiter
 character, and return everything between point and the next
-occurance of the delimiter, including the delimiters themselves.
+occurence of the delimiter, including the delimiters themselves.
 If TRIM is non-nil, do not return the delimiters. Otherwise,
 return one word."
   ;; This function cannot handle nested delimiters, as it's not a
@@ -789,7 +789,7 @@ the files in ARTLIST by that search key.")
    (raw-queries-p
     :initform (symbol-value 'gnus-search-imap-raw-queries-p)))
     :documentation
-  "The base IMAP search engine, using an IMAP server's search capabilites.
+  "The base IMAP search engine, using an IMAP server's search capabilities.
 This backend may be subclassed to handle particular IMAP servers'
 quirks.")
 
@@ -1082,7 +1082,7 @@ Responsible for handling and, or, and parenthetical 
expressions.")
 (cl-defmethod gnus-search-imap-search-command ((engine gnus-search-imap)
                                               (query string))
   "Create the IMAP search command for QUERY.
-Currenly takes into account support for the LITERAL+ capability.
+Currently takes into account support for the LITERAL+ capability.
 Other capabilities could be tested here."
   (with-slots (literal-plus) engine
     (when literal-plus
@@ -1672,8 +1672,8 @@ and \"-\" before marks."
 (cl-defmethod gnus-search-transform-expression ((engine gnus-search-mairix)
                                                (expr (head or)))
   "Handle Mairix \"or\" statement.
-Mairix only accepts \"or\" expressions on homogenous keys.  We
-cast \"or\" expressions on heterogenous keys as \"and\", which
+Mairix only accepts \"or\" expressions on homogeneous keys.  We
+cast \"or\" expressions on heterogeneous keys as \"and\", which
 isn't quite right, but it's the best we can do.  For date keys,
 only keep one of the terms."
   (let ((term1 (caadr expr))
diff --git a/lisp/gnus/gnus-sieve.el b/lisp/gnus/gnus-sieve.el
index 5dcd079..eeedf7f 100644
--- a/lisp/gnus/gnus-sieve.el
+++ b/lisp/gnus/gnus-sieve.el
@@ -113,7 +113,7 @@ Return nil if no rule could be guessed."
 
 ;;;###autoload
 (defun gnus-sieve-article-add-rule ()
-  (interactive)
+  (interactive nil gnus-article-mode gnus-summary-mode)
   (gnus-summary-select-article nil 'force)
   (with-current-buffer gnus-original-article-buffer
     (let ((rule (gnus-sieve-guess-rule-for-article))
diff --git a/lisp/gnus/gnus-srvr.el b/lisp/gnus/gnus-srvr.el
index a305e34..f66f842 100644
--- a/lisp/gnus/gnus-srvr.el
+++ b/lisp/gnus/gnus-srvr.el
@@ -409,7 +409,7 @@ The following commands are available:
 
 (defun gnus-server-kill-server (server)
   "Kill the server on the current line."
-  (interactive (list (gnus-server-server-name)))
+  (interactive (list (gnus-server-server-name)) gnus-server-mode)
   (unless (gnus-server-goto-server server)
     (if server (error "No such server: %s" server)
       (error "No server on the current line")))
@@ -438,7 +438,7 @@ The following commands are available:
 
 (defun gnus-server-yank-server ()
   "Yank the previously killed server."
-  (interactive)
+  (interactive nil gnus-server-mode)
   (unless gnus-server-killed-servers
     (error "No killed servers to be yanked"))
   (let ((alist gnus-server-alist)
@@ -460,14 +460,14 @@ The following commands are available:
 
 (defun gnus-server-exit ()
   "Return to the group buffer."
-  (interactive)
+  (interactive nil gnus-server-mode)
   (gnus-run-hooks 'gnus-server-exit-hook)
   (gnus-kill-buffer (current-buffer))
   (gnus-configure-windows 'group t))
 
 (defun gnus-server-list-servers ()
   "List all available servers."
-  (interactive)
+  (interactive nil gnus-server-mode)
   (let ((cur (gnus-server-server-name)))
     (gnus-server-prepare)
     (if cur (gnus-server-goto-server cur)
@@ -489,7 +489,7 @@ The following commands are available:
 
 (defun gnus-server-open-server (server)
   "Force an open of SERVER."
-  (interactive (list (gnus-server-server-name)))
+  (interactive (list (gnus-server-server-name)) gnus-server-mode)
   (let ((method (gnus-server-to-method server)))
     (unless method
       (error "No such server: %s" server))
@@ -501,13 +501,13 @@ The following commands are available:
 
 (defun gnus-server-open-all-servers ()
   "Open all servers."
-  (interactive)
+  (interactive nil gnus-server-mode)
   (dolist (server gnus-inserted-opened-servers)
     (gnus-server-open-server (car server))))
 
 (defun gnus-server-close-server (server)
   "Close SERVER."
-  (interactive (list (gnus-server-server-name)))
+  (interactive (list (gnus-server-server-name)) gnus-server-mode)
   (let ((method (gnus-server-to-method server)))
     (unless method
       (error "No such server: %s" server))
@@ -519,7 +519,7 @@ The following commands are available:
 
 (defun gnus-server-offline-server (server)
   "Set SERVER to offline."
-  (interactive (list (gnus-server-server-name)))
+  (interactive (list (gnus-server-server-name)) gnus-server-mode)
   (let ((method (gnus-server-to-method server)))
     (unless method
       (error "No such server: %s" server))
@@ -531,7 +531,7 @@ The following commands are available:
 
 (defun gnus-server-close-all-servers ()
   "Close all servers."
-  (interactive)
+  (interactive nil gnus-server-mode)
   (dolist (server gnus-inserted-opened-servers)
     (gnus-server-close-server (car server)))
   (dolist (server gnus-server-alist)
@@ -539,7 +539,7 @@ The following commands are available:
 
 (defun gnus-server-deny-server (server)
   "Make sure SERVER will never be attempted opened."
-  (interactive (list (gnus-server-server-name)))
+  (interactive (list (gnus-server-server-name)) gnus-server-mode)
   (let ((method (gnus-server-to-method server)))
     (unless method
       (error "No such server: %s" server))
@@ -550,7 +550,7 @@ The following commands are available:
 
 (defun gnus-server-remove-denials ()
   "Make all denied servers into closed servers."
-  (interactive)
+  (interactive nil gnus-server-mode)
   (dolist (server gnus-opened-servers)
     (when (eq (nth 1 server) 'denied)
       (setcar (nthcdr 1 server) 'closed)))
@@ -558,11 +558,11 @@ The following commands are available:
 
 (defun gnus-server-copy-server (from to)
   "Copy a server definition to a new name."
-  (interactive
-   (list
-    (or (gnus-server-server-name)
-       (error "No server on the current line"))
-    (read-string "Copy to: ")))
+  (interactive (list
+               (or (gnus-server-server-name)
+                   (error "No server on the current line"))
+               (read-string "Copy to: "))
+              gnus-server-mode)
   (unless from
     (error "No server on current line"))
   (unless (and to (not (string= to "")))
@@ -583,7 +583,8 @@ The following commands are available:
    (list (intern (gnus-completing-read "Server method"
                                        (mapcar #'car gnus-valid-select-methods)
                                        t))
-        (read-string "Server name: ")))
+        (read-string "Server name: "))
+   gnus-server-mode)
   (when (assq where gnus-server-alist)
     (error "Server with that name already defined"))
   (push (list where how where) gnus-server-killed-servers)
@@ -593,7 +594,8 @@ The following commands are available:
   "Jump to a server line."
   (interactive
    (list (gnus-completing-read "Goto server"
-                               (mapcar #'car gnus-server-alist) t)))
+                               (mapcar #'car gnus-server-alist) t))
+   gnus-server-mode)
   (let ((to (text-property-any (point-min) (point-max)
                               'gnus-server (intern server))))
     (when to
@@ -602,7 +604,7 @@ The following commands are available:
 
 (defun gnus-server-edit-server (server)
   "Edit the server on the current line."
-  (interactive (list (gnus-server-server-name)))
+  (interactive (list (gnus-server-server-name)) gnus-server-mode)
   (unless server
     (error "No server on current line"))
   (unless (assoc server gnus-server-alist)
@@ -620,7 +622,7 @@ The following commands are available:
 
 (defun gnus-server-show-server (server)
   "Show the definition of the server on the current line."
-  (interactive (list (gnus-server-server-name)))
+  (interactive (list (gnus-server-server-name)) gnus-server-mode)
   (unless server
     (error "No server on current line"))
   (let ((info (gnus-server-to-method server)))
@@ -632,7 +634,7 @@ The following commands are available:
 
 (defun gnus-server-scan-server (server)
   "Request a scan from the current server."
-  (interactive (list (gnus-server-server-name)))
+  (interactive (list (gnus-server-server-name)) gnus-server-mode)
   (let ((method (gnus-server-to-method server)))
     (if (not (gnus-get-function method 'request-scan))
        (error "Server %s can't scan" (car method))
@@ -897,7 +899,7 @@ buffer.
 (defun gnus-browse-read-group (&optional no-article number)
   "Enter the group at the current line.
 If NUMBER, fetch this number of articles."
-  (interactive "P")
+  (interactive "P" gnus-browse-mode)
   (let* ((full-name (gnus-browse-group-name))
         (group (if (gnus-native-method-p
                     (gnus-find-method-for-group full-name))
@@ -916,26 +918,26 @@ If NUMBER, fetch this number of articles."
 (defun gnus-browse-select-group (&optional number)
   "Select the current group.
 If NUMBER, fetch this number of articles."
-  (interactive "P")
+  (interactive "P" gnus-browse-mode)
   (gnus-browse-read-group 'no number))
 
 (defun gnus-browse-next-group (n)
   "Go to the next group."
-  (interactive "p")
+  (interactive "p" gnus-browse-mode)
   (prog1
       (forward-line n)
     (gnus-group-position-point)))
 
 (defun gnus-browse-prev-group (n)
   "Go to the next group."
-  (interactive "p")
+  (interactive "p" gnus-browse-mode)
   (gnus-browse-next-group (- n)))
 
 (defun gnus-browse-unsubscribe-current-group (arg)
   "(Un)subscribe to the next ARG groups.
 The variable `gnus-browse-subscribe-newsgroup-method' determines
 how new groups will be entered into the group buffer."
-  (interactive "p")
+  (interactive "p" gnus-browse-mode)
   (when (eobp)
     (error "No group at current line"))
   (let ((ward (if (< arg 0) -1 1))
@@ -961,7 +963,7 @@ how new groups will be entered into the group buffer."
 
 (defun gnus-browse-describe-group (group)
   "Describe the current group."
-  (interactive (list (gnus-browse-group-name)))
+  (interactive (list (gnus-browse-group-name)) gnus-browse-mode)
   (gnus-group-describe-group nil group))
 
 (defun gnus-browse-delete-group (group force)
@@ -970,8 +972,8 @@ If FORCE (the prefix) is non-nil, all the articles in the 
group will
 be deleted.  This is \"deleted\" as in \"removed forever from the face
 of the Earth\".  There is no undo.  The user will be prompted before
 doing the deletion."
-  (interactive (list (gnus-browse-group-name)
-                    current-prefix-arg))
+  (interactive (list (gnus-browse-group-name) current-prefix-arg)
+              gnus-browse-mode)
   (gnus-group-delete-group group force))
 
 (defun gnus-browse-unsubscribe-group ()
@@ -1020,7 +1022,7 @@ doing the deletion."
 
 (defun gnus-browse-exit ()
   "Quit browsing and return to the group buffer."
-  (interactive)
+  (interactive nil gnus-browse-mode)
   (when (derived-mode-p 'gnus-browse-mode)
     (gnus-kill-buffer (current-buffer)))
   ;; Insert the newly subscribed groups in the group buffer.
@@ -1032,7 +1034,7 @@ doing the deletion."
 
 (defun gnus-browse-describe-briefly ()
   "Give a one line description of the group mode commands."
-  (interactive)
+  (interactive nil gnus-browse-mode)
   (gnus-message 6 "%s"
                (substitute-command-keys 
"\\<gnus-browse-mode-map>\\[gnus-group-next-group]:Forward  
\\[gnus-group-prev-group]:Backward  \\[gnus-browse-exit]:Exit  
\\[gnus-info-find-node]:Run Info  \\[gnus-browse-describe-briefly]:This help")))
 
@@ -1089,7 +1091,7 @@ Requesting compaction of %s... (this may take a long 
time)"
 
 (defun gnus-server-toggle-cloud-server ()
   "Toggle whether the server under point is replicated in the Emacs Cloud."
-  (interactive)
+  (interactive nil gnus-server-mode)
   (let ((server (gnus-server-server-name)))
     (unless server
       (error "No server on the current line"))
@@ -1110,7 +1112,7 @@ Requesting compaction of %s... (this may take a long 
time)"
 
 (defun gnus-server-set-cloud-method-server ()
   "Set the server under point to host the Emacs Cloud."
-  (interactive)
+  (interactive nil gnus-server-mode)
   (let ((server (gnus-server-server-name)))
     (unless server
       (error "No server on the current line"))
diff --git a/lisp/gnus/gnus-start.el b/lisp/gnus/gnus-start.el
index 1554635..44e97d5 100644
--- a/lisp/gnus/gnus-start.el
+++ b/lisp/gnus/gnus-start.el
@@ -663,7 +663,6 @@ the first newsgroup."
 (defvar mail-sources)
 (defvar nnmail-scan-directory-mail-source-once)
 (defvar nnmail-split-history)
-(defvar nnmail-spool-file)
 
 (defun gnus-close-all-servers ()
   "Close all servers."
@@ -1070,7 +1069,7 @@ With 1 C-u, use the `ask-server' method to query the 
server for new
 groups.
 With 2 C-u's, use most complete method possible to query the server
 for new groups, and subscribe the new groups as zombies."
-  (interactive "p")
+  (interactive "p" gnus-group-mode)
   (let* ((gnus-subscribe-newsgroup-method
          gnus-subscribe-newsgroup-method)
         (check (cond
@@ -1173,7 +1172,7 @@ for new groups, and subscribe the new groups as zombies."
                               gnus-check-new-newsgroups)
                          gnus-secondary-select-methods))))
         (groups 0)
-        group new-newsgroups got-new method hashtb
+        new-newsgroups got-new method hashtb ;; group
         gnus-override-subscribe-method)
     (unless gnus-killed-hashtb
       (gnus-make-hashtable-from-killed))
@@ -1204,14 +1203,14 @@ for new groups, and subscribe the new groups as 
zombies."
               (cond
                ((eq do-sub 'subscribe)
                 (cl-incf groups)
-                (puthash g-name group gnus-killed-hashtb)
+                (puthash g-name nil gnus-killed-hashtb) ;; group
                 (gnus-call-subscribe-functions
                  gnus-subscribe-options-newsgroup-method g-name))
                ((eq do-sub 'ignore)
                 nil)
                (t
                 (cl-incf groups)
-                (puthash g-name group gnus-killed-hashtb)
+                (puthash g-name nil gnus-killed-hashtb) ;; group
                 (if gnus-subscribe-hierarchical-interactive
                     (push g-name new-newsgroups)
                   (gnus-call-subscribe-functions
@@ -1405,7 +1404,7 @@ newsgroup."
 
 (defun gnus-check-duplicate-killed-groups ()
   "Remove duplicates from the list of killed groups."
-  (interactive)
+  (interactive nil gnus-group-mode)
   (let ((killed gnus-killed-list))
     (while killed
       (gnus-message 9 "%d" (length killed))
@@ -2379,6 +2378,11 @@ If FORCE is non-nil, the .newsrc file is read."
             (unless (gnus-yes-or-no-p (concat errmsg "; continue? "))
               (error "%s" errmsg)))))))))
 
+;; IIUC these 3 vars were used in older .newsrc files.
+(defvar gnus-killed-assoc)
+(defvar gnus-marked-assoc)
+(defvar gnus-newsrc-assoc)
+
 (defun gnus-read-newsrc-el-file (file)
   (let ((ding-file (concat file "d")))
     (when (file-exists-p ding-file)
diff --git a/lisp/gnus/gnus-sum.el b/lisp/gnus/gnus-sum.el
index 456e7b0..c30f9a5 100644
--- a/lisp/gnus/gnus-sum.el
+++ b/lisp/gnus/gnus-sum.el
@@ -73,18 +73,10 @@
 (eval-when-compile
   (require 'subr-x))
 
-(autoload 'gnus-summary-limit-include-cached "gnus-cache" nil t)
+(autoload 'gnus-summary-limit-include-cached "gnus-cache" nil
+  '(gnus-summary-mode))
 (autoload 'gnus-cache-write-active "gnus-cache")
-(autoload 'gnus-mailing-list-insinuate "gnus-ml" nil t)
-(autoload 'turn-on-gnus-mailing-list-mode "gnus-ml" nil t)
 (autoload 'gnus-pick-line-number "gnus-salt" nil t)
-(autoload 'mm-uu-dissect "mm-uu")
-(autoload 'gnus-article-outlook-deuglify-article "deuglify"
-  "Deuglify broken Outlook (Express) articles and redisplay."
-  t)
-(autoload 'gnus-article-outlook-unwrap-lines "deuglify" nil t)
-(autoload 'gnus-article-outlook-repair-attribution "deuglify" nil t)
-(autoload 'gnus-article-outlook-rearrange-citation "deuglify" nil t)
 (autoload 'nnselect-article-rsv "nnselect" nil nil)
 (autoload 'nnselect-article-group "nnselect" nil nil)
 (autoload 'gnus-nnselect-group-p "nnselect" nil nil)
@@ -2525,6 +2517,7 @@ gnus-summary-show-article-from-menu-as-charset-%s" cs))))
                               (let ((gnus-summary-show-article-charset-alist
                                      `((1 . ,cs))))
                                 (gnus-summary-show-article 1))))
+                       (function-put command 'completion-predicate #'ignore)
                       `[,(symbol-name cs) ,command t]))
                   (sort (coding-system-list) #'string<)))))
             ("Washing"
@@ -3149,6 +3142,7 @@ buffer; read the Info manual for more information 
(`\\[gnus-info-find-node]').
 The following commands are available:
 
 \\{gnus-summary-mode-map}"
+  :interactive nil
   (let ((gnus-summary-local-variables gnus-newsgroup-variables))
     (gnus-summary-make-local-variables))
   (gnus-summary-make-local-variables)
@@ -3479,7 +3473,7 @@ marks of articles."
 ;; Various summary mode internalish functions.
 
 (defun gnus-mouse-pick-article (e)
-  (interactive "e")
+  (interactive "e" gnus-summary-mode)
   (mouse-set-point e)
   (gnus-summary-next-page nil t))
 
@@ -4219,7 +4213,7 @@ If SELECT-ARTICLES, only select those articles from 
GROUP."
 
 (defun gnus-summary-prepare ()
   "Generate the summary buffer."
-  (interactive)
+  (interactive nil gnus-summary-mode)
   (let ((inhibit-read-only t))
     (erase-buffer)
     (setq gnus-newsgroup-data nil
@@ -4268,7 +4262,7 @@ If SELECT-ARTICLES, only select those articles from 
GROUP."
 
 (defun gnus-summary-simplify-subject-query ()
   "Query where the respool algorithm would put this article."
-  (interactive)
+  (interactive nil gnus-summary-mode)
   (gnus-summary-select-article)
   (message "%s" (gnus-general-simplify-subject 
(gnus-summary-article-subject))))
 
@@ -5983,14 +5977,15 @@ If SELECT-ARTICLES, only select those articles from 
GROUP."
                         (input
                          (read-string
                           (if only-read-p
-                              (format
-                               "How many articles from %s (available %d, 
default %d): "
-                               (gnus-group-real-name gnus-newsgroup-name)
-                               number default)
-                            (format
-                             "How many articles from %s (%d default): "
-                             (gnus-group-real-name gnus-newsgroup-name)
-                             default))
+                              (format-prompt
+                                   "How many articles from %s (available %d)"
+                                   default
+                                   (gnus-group-real-name gnus-newsgroup-name)
+                                   number)
+                            (format-prompt
+                             "How many articles from %s"
+                             default
+                             (gnus-group-real-name gnus-newsgroup-name)))
                           nil
                           nil
                           (number-to-string default))))
@@ -6360,9 +6355,9 @@ The resulting hash table is returned, or nil if no Xrefs 
were found."
       ;; First peel off all invalid article numbers.
       (when active
        (let ((ids articles)
-             id first)
+             id) ;; first
          (while (setq id (pop ids))
-           (when (and first (> id (cdr active)))
+           (when nil ;; (and first (> id (cdr active)))
              ;; We'll end up in this situation in one particular
              ;; obscure situation.  If you re-scan a group and get
              ;; a new article that is cross-posted to a different
@@ -6671,19 +6666,19 @@ executed with point over the summary line of the 
articles."
 
 (defun gnus-summary-save-process-mark ()
   "Push the current set of process marked articles on the stack."
-  (interactive)
+  (interactive nil gnus-summary-mode)
   (push (copy-sequence gnus-newsgroup-processable)
        gnus-newsgroup-process-stack))
 
 (defun gnus-summary-kill-process-mark ()
   "Push the current set of process marked articles on the stack and unmark."
-  (interactive)
+  (interactive nil gnus-summary-mode)
   (gnus-summary-save-process-mark)
   (gnus-summary-unmark-all-processable))
 
 (defun gnus-summary-yank-process-mark ()
   "Pop the last process mark state off the stack and restore it."
-  (interactive)
+  (interactive nil gnus-summary-mode)
   (unless gnus-newsgroup-process-stack
     (error "Empty mark stack"))
   (gnus-summary-process-mark-set (pop gnus-newsgroup-process-stack)))
@@ -6818,7 +6813,7 @@ articles with that subject.  If BACKWARD, search backward 
instead."
 (defun gnus-recenter (&optional n)
   "Center point in window and redisplay frame.
 Also do horizontal recentering."
-  (interactive "P")
+  (interactive "P" gnus-summary-mode)
   (when (and gnus-auto-center-summary
             (not (eq gnus-auto-center-summary 'vertical)))
     (gnus-horizontal-recenter))
@@ -6852,7 +6847,7 @@ If `gnus-auto-center-summary' is nil, or the article 
buffer isn't
 displayed, no centering will be performed."
   ;; Suggested by earle@mahendo.JPL.NASA.GOV (Greg Earle).
   ;; Recenter only when requested.  Suggested by popovich@park.cs.columbia.edu.
-  (interactive)
+  (interactive nil gnus-summary-mode)
   ;; The user has to want it.
   (when gnus-auto-center-summary
     (let* ((top (cond ((< (window-height) 4) 0)
@@ -7029,7 +7024,7 @@ displayed, no centering will be performed."
   "Reconfigure windows to show the article buffer.
 If `gnus-widen-article-window' is set, show only the article
 buffer."
-  (interactive)
+  (interactive nil gnus-summary-mode)
   (if (not (gnus-buffer-live-p gnus-article-buffer))
       (error "There is no article buffer for this summary buffer")
     (or (get-buffer-window gnus-article-buffer)
@@ -7052,7 +7047,7 @@ buffer."
 
 (defun gnus-summary-universal-argument (arg)
   "Perform any operation on all articles that are process/prefixed."
-  (interactive "P")
+  (interactive "P" gnus-summary-mode)
   (let ((articles (gnus-summary-work-articles arg))
        func article)
     (if (eq
@@ -7073,7 +7068,7 @@ buffer."
   (gnus-summary-position-point))
 
 (define-obsolete-function-alias
-    'gnus-summary-toggle-truncation #'toggle-truncate-lines "26.1")
+  'gnus-summary-toggle-truncation #'toggle-truncate-lines "26.1")
 
 (defun gnus-summary-find-for-reselect ()
   "Return the number of an article to stay on across a reselect.
@@ -7095,7 +7090,7 @@ insertion from another group.  If there's no such then 
return a dummy 0."
 (defun gnus-summary-reselect-current-group (&optional all rescan)
   "Exit and then reselect the current newsgroup.
 The prefix argument ALL means to select all articles."
-  (interactive "P")
+  (interactive "P" gnus-summary-mode)
   (when (gnus-ephemeral-group-p gnus-newsgroup-name)
     (error "Ephemeral groups can't be reselected"))
   (let ((current-subject (gnus-summary-find-for-reselect))
@@ -7113,7 +7108,7 @@ The prefix argument ALL means to select all articles."
 
 (defun gnus-summary-rescan-group (&optional all)
   "Exit the newsgroup, ask for new articles, and select the newsgroup."
-  (interactive "P")
+  (interactive "P" gnus-summary-mode)
   (let ((config gnus-current-window-configuration))
     (gnus-summary-reselect-current-group all t)
     (gnus-configure-windows config)
@@ -7168,7 +7163,7 @@ The prefix argument ALL means to select all articles."
 
 (defun gnus-summary-make-group-from-search ()
   "Make a persistent group from the current ephemeral search group."
-  (interactive)
+  (interactive nil gnus-summary-mode)
   (if (not (gnus-nnselect-group-p gnus-newsgroup-name))
       (gnus-message 3 "%s is not a search group" gnus-newsgroup-name)
     (let ((name (gnus-read-group "Group name: ")))
@@ -7185,7 +7180,7 @@ The prefix argument ALL means to select all articles."
   "Save the current number of read/marked articles in the dribble buffer.
 The dribble buffer will then be saved.
 If FORCE (the prefix), also save the .newsrc file(s)."
-  (interactive "P")
+  (interactive "P" gnus-summary-mode)
   (gnus-summary-update-info t)
   (if force
       (gnus-save-newsrc-file)
@@ -7197,7 +7192,7 @@ If FORCE (the prefix), also save the .newsrc file(s)."
 (defun gnus-summary-exit (&optional temporary leave-hidden)
   "Exit reading current newsgroup, and then return to group selection mode.
 `gnus-exit-group-hook' is called with no arguments if that value is non-nil."
-  (interactive)
+  (interactive nil gnus-summary-mode)
   (gnus-set-global-variables)
   (when (gnus-buffer-live-p gnus-article-buffer)
     (with-current-buffer gnus-article-buffer
@@ -7303,7 +7298,7 @@ If FORCE (the prefix), also save the .newsrc file(s)."
 (defalias 'gnus-summary-quit 'gnus-summary-exit-no-update)
 (defun gnus-summary-exit-no-update (&optional no-questions)
   "Quit reading current newsgroup without updating read article info."
-  (interactive)
+  (interactive nil gnus-summary-mode)
   (let* ((group gnus-newsgroup-name)
         (gnus-group-is-exiting-p t)
         (gnus-group-is-exiting-without-update-p t)
@@ -7457,7 +7452,7 @@ The state which existed when entering the ephemeral is 
reset."
 
 (defun gnus-summary-wake-up-the-dead (&rest _)
   "Wake up the dead summary buffer."
-  (interactive)
+  (interactive nil gnus-summary-mode)
   (gnus-dead-summary-mode -1)
   (let ((name (buffer-name)))
     (when (string-match "Dead " name)
@@ -7470,12 +7465,12 @@ The state which existed when entering the ephemeral is 
reset."
 ;; Suggested by Per Abrahamsen <amanda@iesd.auc.dk>.
 (defun gnus-summary-describe-group (&optional force)
   "Describe the current newsgroup."
-  (interactive "P")
+  (interactive "P" gnus-summary-mode)
   (gnus-group-describe-group force gnus-newsgroup-name))
 
 (defun gnus-summary-describe-briefly ()
   "Describe summary mode commands briefly."
-  (interactive)
+  (interactive nil gnus-summary-mode)
   (gnus-message 6 "%s" (substitute-command-keys 
"\\<gnus-summary-mode-map>\\[gnus-summary-next-page]:Select  
\\[gnus-summary-next-unread-article]:Forward  
\\[gnus-summary-prev-unread-article]:Backward  \\[gnus-summary-exit]:Exit  
\\[gnus-info-find-node]:Run Info  \\[gnus-summary-describe-briefly]:This 
help")))
 
 ;; Walking around group mode buffer from summary mode.
@@ -7485,7 +7480,7 @@ The state which existed when entering the ephemeral is 
reset."
 If prefix argument NO-ARTICLE is non-nil, no article is selected
 initially.  If TARGET-GROUP, go to this group.  If BACKWARD, go to
 previous group instead."
-  (interactive "P")
+  (interactive "P" gnus-summary-mode)
   ;; Stop pre-fetching.
   (gnus-async-halt-prefetch)
   (let ((current-group gnus-newsgroup-name)
@@ -7531,7 +7526,7 @@ previous group instead."
 (defun gnus-summary-prev-group (&optional no-article)
   "Exit current newsgroup and then select previous unread newsgroup.
 If prefix argument NO-ARTICLE is non-nil, no article is selected initially."
-  (interactive "P")
+  (interactive "P" gnus-summary-mode)
   (gnus-summary-next-group no-article nil t))
 
 ;; Walking around summary lines.
@@ -7542,7 +7537,7 @@ If UNREAD is non-nil, the article should be unread.
 If UNDOWNLOADED is non-nil, the article should be undownloaded.
 If UNSEEN is non-nil, the article should be unseen as well as unread.
 Returns the article selected or nil if there are no matching articles."
-  (interactive "P")
+  (interactive "P" gnus-summary-mode)
   (cond
    ;; Empty summary.
    ((null gnus-newsgroup-data)
@@ -7594,7 +7589,7 @@ If N is negative, go to the previous N'th subject line.
 If UNREAD is non-nil, only unread articles are selected.
 The difference between N and the actual number of steps taken is
 returned."
-  (interactive "p")
+  (interactive "p" gnus-summary-mode)
   (let ((backward (< n 0))
        (n (abs n)))
     (while (and (> n 0)
@@ -7613,18 +7608,18 @@ returned."
 
 (defun gnus-summary-next-unread-subject (n)
   "Go to next N'th unread summary line."
-  (interactive "p")
+  (interactive "p" gnus-summary-mode)
   (gnus-summary-next-subject n t))
 
 (defun gnus-summary-prev-subject (n &optional unread)
   "Go to previous N'th summary line.
 If optional argument UNREAD is non-nil, only unread article is selected."
-  (interactive "p")
+  (interactive "p" gnus-summary-mode)
   (gnus-summary-next-subject (- n) unread))
 
 (defun gnus-summary-prev-unread-subject (n)
   "Go to previous N'th unread summary line."
-  (interactive "p")
+  (interactive "p" gnus-summary-mode)
   (gnus-summary-next-subject (- n) t))
 
 (defun gnus-summary-goto-subjects (articles)
@@ -7638,7 +7633,7 @@ If optional argument UNREAD is non-nil, only unread 
article is selected."
 (defun gnus-summary-goto-subject (article &optional force silent)
   "Go to the subject line of ARTICLE.
 If FORCE, also allow jumping to articles not currently shown."
-  (interactive "nArticle number: ")
+  (interactive "nArticle number: " gnus-summary-mode)
   (unless (numberp article)
     (error "Article %s is not a number" article))
   (let ((b (point))
@@ -7668,7 +7663,7 @@ If FORCE, also allow jumping to articles not currently 
shown."
 (defun gnus-summary-expand-window (&optional arg)
   "Make the summary buffer take up the entire Emacs frame.
 Given a prefix, will force an `article' buffer configuration."
-  (interactive "P")
+  (interactive "P" gnus-summary-mode)
   (if arg
       (gnus-configure-windows 'article 'force)
     (gnus-configure-windows 'summary 'force)))
@@ -7751,7 +7746,7 @@ be displayed."
 
 (defun gnus-summary-force-verify-and-decrypt ()
   "Display buttons for signed/encrypted parts and verify/decrypt them."
-  (interactive)
+  (interactive nil gnus-summary-mode)
   (let ((mm-verify-option 'known)
        (mm-decrypt-option 'known)
        (gnus-article-emulate-mime t)
@@ -7765,7 +7760,7 @@ be displayed."
 If UNREAD, only unread articles are selected.
 If SUBJECT, only articles with SUBJECT are selected.
 If BACKWARD, the previous article is selected instead of the next."
-  (interactive "P")
+  (interactive "P" gnus-summary-mode)
   ;; Make sure we are in the summary buffer.
   (unless (derived-mode-p 'gnus-summary-mode)
     (set-buffer gnus-summary-buffer))
@@ -7877,7 +7872,7 @@ If BACKWARD, the previous article is selected instead of 
the next."
 
 (defun gnus-summary-next-unread-article ()
   "Select unread article after current one."
-  (interactive)
+  (interactive nil gnus-summary-mode)
   (gnus-summary-next-article
    (or (not (eq gnus-summary-goto-unread 'never))
        (gnus-summary-last-article-p (gnus-summary-article-number)))
@@ -7887,12 +7882,12 @@ If BACKWARD, the previous article is selected instead 
of the next."
 (defun gnus-summary-prev-article (&optional unread subject)
   "Select the article before the current one.
 If UNREAD is non-nil, only unread articles are selected."
-  (interactive "P")
+  (interactive "P" gnus-summary-mode)
   (gnus-summary-next-article unread subject t))
 
 (defun gnus-summary-prev-unread-article ()
   "Select unread article before current one."
-  (interactive)
+  (interactive nil gnus-summary-mode)
   (gnus-summary-prev-article
    (or (not (eq gnus-summary-goto-unread 'never))
        (gnus-summary-first-article-p (gnus-summary-article-number)))
@@ -7913,7 +7908,7 @@ article.
 If STOP is non-nil, just stop when reaching the end of the message.
 
 Also see the variable `gnus-article-skip-boring'."
-  (interactive "P")
+  (interactive "P" gnus-summary-mode)
   (gnus-set-global-variables)
   (let ((article (gnus-summary-article-number))
        (article-window (get-buffer-window gnus-article-buffer t))
@@ -7958,7 +7953,7 @@ Also see the variable `gnus-article-skip-boring'."
 Argument LINES specifies lines to be scrolled down.
 If MOVE, move to the previous unread article if point is at
 the beginning of the buffer."
-  (interactive "P")
+  (interactive "P" gnus-summary-mode)
   (let ((article (gnus-summary-article-number))
        (article-window (get-buffer-window gnus-article-buffer t))
        endp)
@@ -7988,14 +7983,14 @@ the beginning of the buffer."
   "Show previous page of selected article.
 Argument LINES specifies lines to be scrolled down.
 If at the beginning of the article, go to the next article."
-  (interactive "P")
+  (interactive "P" gnus-summary-mode)
   (gnus-summary-prev-page lines t))
 
 (defun gnus-summary-scroll-up (lines)
   "Scroll up (or down) one line current article.
 Argument LINES specifies lines to be scrolled up (or down if negative).
 If no article is selected, then the current article will be selected first."
-  (interactive "p")
+  (interactive "p" gnus-summary-mode)
   (gnus-configure-windows 'article)
   (gnus-summary-show-thread)
   (when (eq (gnus-summary-select-article nil nil 'pseudo) 'old)
@@ -8012,33 +8007,33 @@ If no article is selected, then the current article 
will be selected first."
   "Scroll down (or up) one line current article.
 Argument LINES specifies lines to be scrolled down (or up if negative).
 If no article is selected, then the current article will be selected first."
-  (interactive "p")
+  (interactive "p" gnus-summary-mode)
   (gnus-summary-scroll-up (- lines)))
 
 (defun gnus-summary-next-same-subject ()
   "Select next article which has the same subject as current one."
-  (interactive)
+  (interactive nil gnus-summary-mode)
   (gnus-summary-next-article nil (gnus-summary-article-subject)))
 
 (defun gnus-summary-prev-same-subject ()
   "Select previous article which has the same subject as current one."
-  (interactive)
+  (interactive nil gnus-summary-mode)
   (gnus-summary-prev-article nil (gnus-summary-article-subject)))
 
 (defun gnus-summary-next-unread-same-subject ()
   "Select next unread article which has the same subject as current one."
-  (interactive)
+  (interactive nil gnus-summary-mode)
   (gnus-summary-next-article t (gnus-summary-article-subject)))
 
 (defun gnus-summary-prev-unread-same-subject ()
   "Select previous unread article which has the same subject as current one."
-  (interactive)
+  (interactive nil gnus-summary-mode)
   (gnus-summary-prev-article t (gnus-summary-article-subject)))
 
 (defun gnus-summary-first-unread-article ()
   "Select the first unread article.
 Return nil if there are no unread articles."
-  (interactive)
+  (interactive nil gnus-summary-mode)
   (prog1
       (when (gnus-summary-first-subject t)
        (gnus-summary-show-thread)
@@ -8049,7 +8044,7 @@ Return nil if there are no unread articles."
 (defun gnus-summary-first-unread-subject ()
   "Place the point on the subject line of the first unread article.
 Return nil if there are no unread articles."
-  (interactive)
+  (interactive nil gnus-summary-mode)
   (prog1
       (when (gnus-summary-first-subject t)
        (gnus-summary-show-thread)
@@ -8058,7 +8053,7 @@ Return nil if there are no unread articles."
 
 (defun gnus-summary-next-unseen-article (&optional backward)
   "Select the next unseen article."
-  (interactive)
+  (interactive nil gnus-summary-mode)
   (let* ((article (gnus-summary-article-number))
         (articles (gnus-data-find-list article (gnus-data-list backward))))
     (when (or (not gnus-summary-check-current)
@@ -8079,13 +8074,13 @@ Return nil if there are no unread articles."
 
 (defun gnus-summary-prev-unseen-article ()
   "Select the previous unseen article."
-  (interactive)
+  (interactive nil gnus-summary-mode)
   (gnus-summary-next-unseen-article t))
 
 (defun gnus-summary-first-unseen-subject ()
   "Place the point on the subject line of the first unseen article.
 Return nil if there are no unseen articles."
-  (interactive)
+  (interactive nil gnus-summary-mode)
   (prog1
       (when (gnus-summary-first-subject nil nil t)
        (gnus-summary-show-thread)
@@ -8096,7 +8091,7 @@ Return nil if there are no unseen articles."
   "Place the point on the subject line of the first unseen and unread article.
 If all article have been seen, on the subject line of the first unread
 article."
-  (interactive)
+  (interactive nil gnus-summary-mode)
   (prog1
       (unless (when (gnus-summary-first-subject nil nil t)
                (gnus-summary-show-thread)
@@ -8109,7 +8104,7 @@ article."
 (defun gnus-summary-first-article ()
   "Select the first article.
 Return nil if there are no articles."
-  (interactive)
+  (interactive nil gnus-summary-mode)
   (prog1
       (when (gnus-summary-first-subject)
        (gnus-summary-show-thread)
@@ -8121,7 +8116,7 @@ Return nil if there are no articles."
   "Select the unread article with the highest score.
 If given a prefix argument, select the next unread article that has a
 score higher than the default score."
-  (interactive "P")
+  (interactive "P" gnus-summary-mode)
   (let ((article (if arg
                     (gnus-summary-better-unread-subject)
                   (gnus-summary-best-unread-subject))))
@@ -8131,7 +8126,7 @@ score higher than the default score."
 
 (defun gnus-summary-best-unread-subject ()
   "Select the unread subject with the highest score."
-  (interactive)
+  (interactive nil gnus-summary-mode)
   (let ((best -1000000)
        (data gnus-newsgroup-data)
        article score)
@@ -8150,7 +8145,7 @@ score higher than the default score."
 
 (defun gnus-summary-better-unread-subject ()
   "Select the first unread subject that has a score over the default score."
-  (interactive)
+  (interactive nil gnus-summary-mode)
   (let ((data gnus-newsgroup-data)
        article)
     (while (and (setq article (gnus-data-number (car data)))
@@ -8176,11 +8171,10 @@ If FORCE, go to the article even if it isn't displayed. 
 If FORCE
 is a number, it is the line the article is to be displayed on."
   (interactive
    (list
-    (gnus-completing-read
-     "Article number or Message-ID"
-     (mapcar #'int-to-string gnus-newsgroup-limit))
-    current-prefix-arg
-    t))
+    (gnus-completing-read "Article number or Message-ID"
+                         (mapcar #'int-to-string gnus-newsgroup-limit))
+    current-prefix-arg t)
+   gnus-summary-mode)
   (prog1
       (if (and (stringp article)
               (string-match "@\\|%40" article))
@@ -8194,7 +8188,7 @@ is a number, it is the line the article is to be 
displayed on."
 
 (defun gnus-summary-goto-last-article ()
   "Go to the previously read article."
-  (interactive)
+  (interactive nil gnus-summary-mode)
   (prog1
       (when gnus-last-article
        (gnus-summary-goto-article gnus-last-article nil t))
@@ -8203,7 +8197,7 @@ is a number, it is the line the article is to be 
displayed on."
 (defun gnus-summary-pop-article (number)
   "Pop one article off the history and go to the previous.
 NUMBER articles will be popped off."
-  (interactive "p")
+  (interactive "p" gnus-summary-mode)
   (let (to)
     (setq gnus-newsgroup-history
          (cdr (setq to (nthcdr number gnus-newsgroup-history))))
@@ -8217,7 +8211,7 @@ NUMBER articles will be popped off."
 (defun gnus-summary-limit-to-articles (n)
   "Limit the summary buffer to the next N articles.
 If not given a prefix, use the process marked articles instead."
-  (interactive "P")
+  (interactive "P" gnus-summary-mode)
   (prog1
       (let ((articles (gnus-summary-work-articles n)))
        (setq gnus-newsgroup-processable nil)
@@ -8227,7 +8221,7 @@ If not given a prefix, use the process marked articles 
instead."
 (defun gnus-summary-pop-limit (&optional total)
   "Restore the previous limit.
 If given a prefix, remove all limits."
-  (interactive "P")
+  (interactive "P" gnus-summary-mode)
   (when total
     (setq gnus-newsgroup-limits
          (list (mapcar #'mail-header-number gnus-newsgroup-headers))))
@@ -8241,10 +8235,11 @@ If given a prefix, remove all limits."
   "Limit the summary buffer to articles that have subjects that match a regexp.
 If NOT-MATCHING, excluding articles that have subjects that match a regexp."
   (interactive
-   (list (read-string (if current-prefix-arg
-                         "Exclude subject (regexp): "
-                       "Limit to subject (regexp): "))
-        nil current-prefix-arg))
+   (list
+    (read-string
+     (if current-prefix-arg "Exclude subject (regexp): " "Limit to subject 
(regexp): "))
+    nil current-prefix-arg)
+   gnus-summary-mode)
   (unless header
     (setq header "subject"))
   (when (not (equal "" subject))
@@ -8261,18 +8256,25 @@ If NOT-MATCHING, excluding articles that have subjects 
that match a regexp."
   "Limit the summary buffer to articles that have authors that match a regexp.
 If NOT-MATCHING, excluding articles that have authors that match a regexp."
   (interactive
-   (list (let* ((header (gnus-summary-article-header))
-               (default (and header (car (mail-header-parse-address
-                                          (mail-header-from header))))))
-          (read-string (concat (if current-prefix-arg
-                                   "Exclude author (regexp"
-                                 "Limit to author (regexp")
-                               (if default
-                                   (concat ", default \"" default "\"): ")
-                                 "): "))
-                       nil nil
-                       default))
-        current-prefix-arg))
+   (list
+    (let*
+       ((header
+         (gnus-summary-article-header))
+        (default
+          (and header
+               (car
+                (mail-header-parse-address
+                 (mail-header-from header))))))
+      (read-string
+       (concat
+       (if current-prefix-arg
+           "Exclude author (regexp" "Limit to author (regexp")
+       (if default
+           (concat ", default \"" default "\"): ")
+         "): "))
+       nil nil default))
+    current-prefix-arg)
+   gnus-summary-mode)
   (gnus-summary-limit-to-subject from "from" not-matching))
 
 (defun gnus-summary-limit-to-recipient (recipient &optional not-matching)
@@ -8284,9 +8286,12 @@ To and Cc headers are checked.  You need to include them 
in
 `nnmail-extra-headers'."
   ;; Unlike `rmail-summary-by-recipients', doesn't include From.
   (interactive
-   (list (read-string (format "%s recipient (regexp): "
-                             (if current-prefix-arg "Exclude" "Limit to")))
-        current-prefix-arg))
+   (list
+    (read-string
+     (format "%s recipient (regexp): "
+            (if current-prefix-arg "Exclude" "Limit to")))
+    current-prefix-arg)
+   gnus-summary-mode)
   (when (not (equal "" recipient))
     (prog1 (let* ((to
                   (if (memq 'To nnmail-extra-headers)
@@ -8326,9 +8331,12 @@ If NOT-MATCHING, exclude ADDRESS.
 To, Cc and From headers are checked.  You need to include `To' and `Cc'
 in `nnmail-extra-headers'."
   (interactive
-   (list (read-string (format "%s address (regexp): "
-                             (if current-prefix-arg "Exclude" "Limit to")))
-        current-prefix-arg))
+   (list
+    (read-string
+     (format "%s address (regexp): "
+            (if current-prefix-arg "Exclude" "Limit to")))
+    current-prefix-arg)
+   gnus-summary-mode)
   (when (not (equal "" address))
     (prog1 (let* ((to
                   (if (memq 'To nnmail-extra-headers)
@@ -8415,7 +8423,8 @@ articles that are younger than AGE days."
               (setq days (* days -1))))
         (message "Please enter a number.")
         (sleep-for 1)))
-     (list days younger)))
+     (list days younger))
+   gnus-summary-mode)
   (prog1
       (let ((data gnus-newsgroup-data)
            (cutoff (days-to-time age))
@@ -8439,17 +8448,18 @@ articles that are younger than AGE days."
    (let ((header
          (intern
           (gnus-completing-read
-           (if current-prefix-arg
-               "Exclude extra header"
-             "Limit extra header")
+           (if current-prefix-arg "Exclude extra header" "Limit extra header")
            (mapcar #'symbol-name gnus-extra-headers)
            t nil nil
-            (symbol-name (car gnus-extra-headers))))))
+           (symbol-name
+            (car gnus-extra-headers))))))
      (list header
-          (read-string (format "%s header %s (regexp): "
-                               (if current-prefix-arg "Exclude" "Limit to")
-                               header))
-          current-prefix-arg)))
+          (read-string
+           (format "%s header %s (regexp): "
+                   (if current-prefix-arg "Exclude" "Limit to")
+                   header))
+          current-prefix-arg))
+   gnus-summary-mode)
   (when (not (equal "" regexp))
     (prog1
        (let ((articles (gnus-summary-find-matching
@@ -8462,7 +8472,7 @@ articles that are younger than AGE days."
 
 (defun gnus-summary-limit-to-display-predicate ()
   "Limit the summary buffer to the predicated in the `display' group 
parameter."
-  (interactive)
+  (interactive nil gnus-summary-mode)
   (unless gnus-newsgroup-display
     (error "There is no `display' group parameter"))
   (let (articles)
@@ -8475,7 +8485,7 @@ articles that are younger than AGE days."
 (defun gnus-summary-limit-to-unread (&optional all)
   "Limit the summary buffer to articles that are not marked as read.
 If ALL is non-nil, limit strictly to unread articles."
-  (interactive "P")
+  (interactive "P" gnus-summary-mode)
   (if all
       (gnus-summary-limit-to-marks (char-to-string gnus-unread-mark))
     (gnus-summary-limit-to-marks
@@ -8491,7 +8501,7 @@ If ALL is non-nil, limit strictly to unread articles."
 (defun gnus-summary-limit-to-headers (match &optional reverse)
   "Limit the summary buffer to articles that have headers that match MATCH.
 If REVERSE (the prefix), limit to articles that don't match."
-  (interactive "sMatch headers (regexp): \nP")
+  (interactive "sMatch headers (regexp): \nP" gnus-summary-mode)
   (gnus-summary-limit-to-bodies match reverse t))
 
 (declare-function article-goto-body "gnus-art" ())
@@ -8499,7 +8509,7 @@ If REVERSE (the prefix), limit to articles that don't 
match."
 (defun gnus-summary-limit-to-bodies (match &optional reverse headersp)
   "Limit the summary buffer to articles that have bodies that match MATCH.
 If REVERSE (the prefix), limit to articles that don't match."
-  (interactive "sMatch body (regexp): \nP")
+  (interactive "sMatch body (regexp): \nP" gnus-summary-mode)
   (let ((articles nil)
        (gnus-select-article-hook nil)  ;Disable hook.
        (gnus-article-prepare-hook nil)
@@ -8532,7 +8542,7 @@ If REVERSE (the prefix), limit to articles that don't 
match."
 (defun gnus-summary-limit-to-singletons (&optional threadsp)
   "Limit the summary buffer to articles that aren't part on any thread.
 If THREADSP (the prefix), limit to articles that are in threads."
-  (interactive "P")
+  (interactive "P" gnus-summary-mode)
   (let ((articles nil)
        thread-articles
        threads)
@@ -8556,7 +8566,7 @@ If THREADSP (the prefix), limit to articles that are in 
threads."
 (defun gnus-summary-limit-to-replied (&optional unreplied)
   "Limit the summary buffer to replied articles.
 If UNREPLIED (the prefix), limit to unreplied articles."
-  (interactive "P")
+  (interactive "P" gnus-summary-mode)
   (if unreplied
       (gnus-summary-limit
        (gnus-set-difference gnus-newsgroup-articles
@@ -8569,7 +8579,7 @@ If UNREPLIED (the prefix), limit to unreplied articles."
 If REVERSE, limit the summary buffer to articles that are marked
 with MARKS.  MARKS can either be a string of marks or a list of marks.
 Returns how many articles were removed."
-  (interactive "sMarks: ")
+  (interactive "sMarks: " gnus-summary-mode)
   (gnus-summary-limit-to-marks marks t))
 
 (defun gnus-summary-limit-to-marks (marks &optional reverse)
@@ -8578,7 +8588,7 @@ If REVERSE (the prefix), limit the summary buffer to 
articles that are
 not marked with MARKS.  MARKS can either be a string of marks or a
 list of marks.
 Returns how many articles were removed."
-  (interactive "sMarks: \nP")
+  (interactive "sMarks: \nP" gnus-summary-mode)
   (prog1
       (let ((data gnus-newsgroup-data)
            (marks (if (listp marks) marks
@@ -8597,10 +8607,13 @@ Returns how many articles were removed."
 
 With a prefix argument, limit to articles with score at or below
 SCORE."
-  (interactive (list (string-to-number
-                      (read-string
-                       (format "Limit to articles with score of at %s: "
-                               (if current-prefix-arg "most" "least"))))))
+  (interactive
+   (list
+    (string-to-number
+     (read-string
+      (format "Limit to articles with score of at %s: "
+             (if current-prefix-arg "most" "least")))))
+   gnus-summary-mode)
   (let ((data gnus-newsgroup-data)
         (compare (if (or below current-prefix-arg) #'<= #'>=))
         articles)
@@ -8616,7 +8629,7 @@ SCORE."
 
 (defun gnus-summary-limit-to-unseen ()
   "Limit to unseen articles."
-  (interactive)
+  (interactive nil gnus-summary-mode)
   (prog1
       (gnus-summary-limit gnus-newsgroup-unseen)
     (gnus-summary-position-point)))
@@ -8626,8 +8639,12 @@ SCORE."
 When called interactively, ID is the Message-ID of the current
 article.  If thread-only is non-nil limit the summary buffer to
 these articles."
-  (interactive (list (mail-header-id (gnus-summary-article-header))
-                    current-prefix-arg))
+  (interactive
+   (list
+    (mail-header-id
+     (gnus-summary-article-header))
+    current-prefix-arg)
+   gnus-summary-mode)
   (let ((articles (gnus-articles-in-thread
                   (gnus-id-to-thread (gnus-root-id id))))
        ;;we REALLY want the whole thread---this prevents cut-threads
@@ -8653,8 +8670,11 @@ these articles."
 
 (defun gnus-summary-limit-include-matching-articles (header regexp)
   "Display all the hidden articles that have HEADERs that match REGEXP."
-  (interactive (list (read-string "Match on header: ")
-                    (read-string "Regexp: ")))
+  (interactive
+   (list
+    (read-string "Match on header: ")
+    (read-string "Regexp: "))
+   gnus-summary-mode)
   (let ((articles (gnus-find-matching-articles header regexp)))
     (prog1
        (gnus-summary-limit (nconc articles gnus-newsgroup-limit))
@@ -8662,7 +8682,7 @@ these articles."
 
 (defun gnus-summary-insert-dormant-articles ()
   "Insert all the dormant articles for this group into the current buffer."
-  (interactive)
+  (interactive nil gnus-summary-mode)
   (let ((gnus-verbose (max 6 gnus-verbose)))
     (if (not gnus-newsgroup-dormant)
        (gnus-message 3 "No dormant articles for this group")
@@ -8670,7 +8690,7 @@ these articles."
 
 (defun gnus-summary-insert-ticked-articles ()
   "Insert ticked articles for this group into the current buffer."
-  (interactive)
+  (interactive nil gnus-summary-mode)
   (let ((gnus-verbose (max 6 gnus-verbose)))
     (if (not gnus-newsgroup-marked)
        (gnus-message 3 "No ticked articles for this group")
@@ -8680,7 +8700,7 @@ these articles."
   "Display all the hidden articles that are marked as dormant.
 Note that this command only works on a subset of the articles currently
 fetched for this group."
-  (interactive)
+  (interactive nil gnus-summary-mode)
   (unless gnus-newsgroup-dormant
     (error "There are no dormant articles in this group"))
   (prog1
@@ -8703,14 +8723,14 @@ fetched for this group."
 
 (defun gnus-summary-limit-exclude-dormant ()
   "Hide all dormant articles."
-  (interactive)
+  (interactive nil gnus-summary-mode)
   (prog1
       (gnus-summary-limit-to-marks (list gnus-dormant-mark) 'reverse)
     (gnus-summary-position-point)))
 
 (defun gnus-summary-limit-exclude-childless-dormant ()
   "Hide all dormant articles that have no children."
-  (interactive)
+  (interactive nil gnus-summary-mode)
   (let ((data (gnus-data-list t))
        articles d children)
     ;; Find all articles that are either not dormant or have
@@ -8735,7 +8755,7 @@ fetched for this group."
 (defun gnus-summary-limit-mark-excluded-as-read (&optional all)
   "Mark all unread excluded articles as read.
 If ALL, mark even excluded ticked and dormants as read."
-  (interactive "P")
+  (interactive "P" gnus-summary-mode)
   (setq gnus-newsgroup-limit (sort gnus-newsgroup-limit #'<))
   (let ((articles (gnus-sorted-ndifference
                   (sort
@@ -8974,7 +8994,7 @@ fetch-old-headers verbiage, and so on."
   "Refer parent article N times.
 If N is negative, go to ancestor -N instead.
 The difference between N and the number of articles fetched is returned."
-  (interactive "p")
+  (interactive "p" gnus-summary-mode)
   (let ((skip 1)
        error header ref)
     (when (not (natnump n))
@@ -9016,7 +9036,7 @@ The difference between N and the number of articles 
fetched is returned."
 (defun gnus-summary-refer-references ()
   "Fetch all articles mentioned in the References header.
 Return the number of articles fetched."
-  (interactive)
+  (interactive nil gnus-summary-mode)
   (let ((ref (mail-header-references (gnus-summary-article-header)))
        (current (gnus-summary-article-number))
        (n 0))
@@ -9059,7 +9079,7 @@ has the reverse meaning.  If no backend-specific 
`request-thread'
 function is available fetch LIMIT (the numerical prefix) old
 headers.  If LIMIT is non-numeric or nil fetch the number
 specified by the `gnus-refer-thread-limit' variable."
-  (interactive "P")
+  (interactive "P" gnus-summary-mode)
   (let* ((header (gnus-summary-article-header))
         (id (mail-header-id header))
         (gnus-inhibit-demon t)
@@ -9114,7 +9134,7 @@ specified by the `gnus-refer-thread-limit' variable."
 
 (defun gnus-summary-open-group-with-article (message-id)
   "Open a group containing the article with the given MESSAGE-ID."
-  (interactive "sMessage-ID: ")
+  (interactive "sMessage-ID: " gnus-summary-mode)
   (require 'nndoc)
   (with-temp-buffer
     ;; Prepare a dummy article
@@ -9149,7 +9169,7 @@ specified by the `gnus-refer-thread-limit' variable."
 
 (defun gnus-summary-refer-article (message-id)
   "Fetch an article specified by MESSAGE-ID."
-  (interactive "sMessage-ID: ")
+  (interactive "sMessage-ID: " gnus-summary-mode)
   (when (and (stringp message-id)
             (not (zerop (length message-id))))
     (setq message-id (replace-regexp-in-string " " "" message-id))
@@ -9222,12 +9242,12 @@ specified by the `gnus-refer-thread-limit' variable."
 
 (defun gnus-summary-edit-parameters ()
   "Edit the group parameters of the current group."
-  (interactive)
+  (interactive nil gnus-summary-mode)
   (gnus-group-edit-group gnus-newsgroup-name 'params))
 
 (defun gnus-summary-customize-parameters ()
   "Customize the group parameters of the current group."
-  (interactive)
+  (interactive nil gnus-summary-mode)
   (gnus-group-customize gnus-newsgroup-name))
 
 (defun gnus-summary-enter-digest-group (&optional force)
@@ -9237,7 +9257,7 @@ what the document format is.
 
 To control what happens when you exit the group, see the
 `gnus-auto-select-on-ephemeral-exit' variable."
-  (interactive "P")
+  (interactive "P" gnus-summary-mode)
   (let ((conf gnus-current-window-configuration))
     (save-window-excursion
       (save-excursion
@@ -9322,7 +9342,7 @@ To control what happens when you exit the group, see the
 This will allow you to read digests and other similar
 documents as newsgroups.
 Obeys the standard process/prefix convention."
-  (interactive "P")
+  (interactive "P" gnus-summary-mode)
   (let* ((ogroup gnus-newsgroup-name)
         (params (append (gnus-info-params (gnus-get-info ogroup))
                         (list (cons 'to-group ogroup))))
@@ -9371,7 +9391,7 @@ Obeys the standard process/prefix convention."
 (defun gnus-summary-button-forward (arg)
   "Move point to the next field or button in the article.
 With optional ARG, move across that many fields."
-  (interactive "p")
+  (interactive "p" gnus-summary-mode)
   (gnus-summary-select-article)
   (gnus-configure-windows 'article)
   (let ((win (or (gnus-get-buffer-window gnus-article-buffer t)
@@ -9385,7 +9405,7 @@ With optional ARG, move across that many fields."
 (defun gnus-summary-button-backward (arg)
   "Move point to the previous field or button in the article.
 With optional ARG, move across that many fields."
-  (interactive "p")
+  (interactive "p" gnus-summary-mode)
   (gnus-summary-select-article)
   (gnus-configure-windows 'article)
   (let ((win (or (gnus-get-buffer-window gnus-article-buffer t)
@@ -9442,7 +9462,7 @@ If only one link is found, browse that directly, 
otherwise use
 completion to select a link.  The first link marked in the
 article text with `gnus-collect-urls-primary-text' is the
 default."
-  (interactive "P")
+  (interactive "P" gnus-summary-mode)
   (let (urls target)
     (gnus-summary-select-article)
     (gnus-with-article-buffer
@@ -9467,7 +9487,7 @@ default."
 (defun gnus-summary-isearch-article (&optional regexp-p)
   "Do incremental search forward on the current article.
 If REGEXP-P (the prefix) is non-nil, do regexp isearch."
-  (interactive "P")
+  (interactive "P" gnus-summary-mode)
   (gnus-summary-select-article)
   (gnus-configure-windows 'article)
   (gnus-eval-in-buffer-window gnus-article-buffer
@@ -9477,14 +9497,14 @@ If REGEXP-P (the prefix) is non-nil, do regexp isearch."
 
 (defun gnus-summary-repeat-search-article-forward ()
   "Repeat the previous search forwards."
-  (interactive)
+  (interactive nil gnus-summary-mode)
   (unless gnus-last-search-regexp
     (error "No previous search"))
   (gnus-summary-search-article-forward gnus-last-search-regexp))
 
 (defun gnus-summary-repeat-search-article-backward ()
   "Repeat the previous search backwards."
-  (interactive)
+  (interactive nil gnus-summary-mode)
   (unless gnus-last-search-regexp
     (error "No previous search"))
   (gnus-summary-search-article-forward gnus-last-search-regexp t))
@@ -9493,13 +9513,13 @@ If REGEXP-P (the prefix) is non-nil, do regexp isearch."
   "Search for an article containing REGEXP forward.
 If BACKWARD, search backward instead."
   (interactive
-   (list (read-string
-         (format "Search article %s (regexp%s): "
-                 (if current-prefix-arg "backward" "forward")
-                 (if gnus-last-search-regexp
-                     (concat ", default " gnus-last-search-regexp)
-                   "")))
-        current-prefix-arg))
+   (list
+    (read-string
+     (format-prompt "Search article %s (regexp)"
+                    gnus-last-search-regexp
+                    (if current-prefix-arg "backward" "forward")))
+    current-prefix-arg)
+   gnus-summary-mode)
   (if (string-equal regexp "")
       (setq regexp (or gnus-last-search-regexp ""))
     (setq gnus-last-search-regexp regexp)
@@ -9514,11 +9534,11 @@ If BACKWARD, search backward instead."
 (defun gnus-summary-search-article-backward (regexp)
   "Search for an article containing REGEXP backward."
   (interactive
-   (list (read-string
-         (format "Search article backward (regexp%s): "
-                 (if gnus-last-search-regexp
-                     (concat ", default " gnus-last-search-regexp)
-                   "")))))
+   (list
+    (read-string
+     (format-prompt "Search article backward (regexp)"
+                    gnus-last-search-regexp)))
+   gnus-summary-mode)
   (gnus-summary-search-article-forward regexp 'backward))
 
 (defun gnus-summary-search-article (regexp &optional backward)
@@ -9653,18 +9673,20 @@ that not match REGEXP on HEADER."
 If HEADER is an empty string (or nil), the match is done on the entire
 article.  If BACKWARD (the prefix) is non-nil, search backward instead."
   (interactive
-   (list (let ((completion-ignore-case t))
-          (gnus-completing-read
-           "Header name"
-           (mapcar #'symbol-name
-                   (append
-                    '(Number Subject From Lines Date
-                      Message-ID Xref References Body)
-                    gnus-extra-headers))
-           'require-match))
-        (read-string "Regexp: ")
-        (read-key-sequence "Command: ")
-        current-prefix-arg))
+   (list
+    (let ((completion-ignore-case t))
+      (gnus-completing-read
+       "Header name"
+       (mapcar #'symbol-name
+              (append
+               '(Number Subject From Lines Date Message-ID
+                        Xref References Body)
+               gnus-extra-headers))
+       'require-match))
+    (read-string "Regexp: ")
+    (read-key-sequence "Command: ")
+    current-prefix-arg)
+   gnus-summary-mode)
   (when (equal header "Body")
     (setq header ""))
   ;; Hidden thread subtrees must be searched as well.
@@ -9688,7 +9710,7 @@ article.  If BACKWARD (the prefix) is non-nil, search 
backward instead."
 
 (defun gnus-summary-beginning-of-article ()
   "Scroll the article back to the beginning."
-  (interactive)
+  (interactive nil gnus-summary-mode)
   (gnus-summary-select-article)
   (gnus-configure-windows 'article)
   (gnus-eval-in-buffer-window gnus-article-buffer
@@ -9699,7 +9721,7 @@ article.  If BACKWARD (the prefix) is non-nil, search 
backward instead."
 
 (defun gnus-summary-end-of-article ()
   "Scroll to the end of the article."
-  (interactive)
+  (interactive nil gnus-summary-mode)
   (gnus-summary-select-article)
   (gnus-configure-windows 'article)
   (gnus-eval-in-buffer-window gnus-article-buffer
@@ -9732,7 +9754,9 @@ If the optional first argument FILENAME is nil, send the 
image to the
 printer.  If FILENAME is a string, save the PostScript image in a file with
 that name.  If FILENAME is a number, prompt the user for the name of the file
 to save in."
-  (interactive (list (ps-print-preprint current-prefix-arg)))
+  (interactive
+   (list (ps-print-preprint current-prefix-arg))
+   gnus-summary-mode)
   (dolist (article (gnus-summary-work-articles n))
     (gnus-summary-select-article nil nil 'pseudo article)
     (gnus-eval-in-buffer-window gnus-article-buffer
@@ -9772,7 +9796,7 @@ to save in."
   "Show a complete version of the current article.
 This is only useful if you're looking at a partial version of the
 article currently."
-  (interactive)
+  (interactive nil gnus-summary-mode)
   (let ((gnus-keep-backlog nil)
        (gnus-use-cache nil)
        (gnus-agent nil)
@@ -9799,7 +9823,7 @@ If ARG (the prefix) is non-nil and not a number, show the 
article,
 but without running any of the article treatment functions
 article.  Normally, the keystroke is `C-u g'.  When using `C-u
 C-u g', show the raw article."
-  (interactive "P")
+  (interactive "P" gnus-summary-mode)
   (cond
    ((numberp arg)
     (gnus-summary-show-article t)
@@ -9875,14 +9899,14 @@ C-u g', show the raw article."
 
 (defun gnus-summary-show-raw-article ()
   "Show the raw article without any article massaging functions being run."
-  (interactive)
+  (interactive nil gnus-summary-mode)
   (gnus-summary-show-article t))
 
 (defun gnus-summary-verbose-headers (&optional arg)
   "Toggle permanent full header display.
 If ARG is a positive number, turn header display on.
 If ARG is a negative number, turn header display off."
-  (interactive "P")
+  (interactive "P" gnus-summary-mode)
   (setq gnus-show-all-headers
        (cond ((or (not (numberp arg))
                   (zerop arg))
@@ -9901,7 +9925,7 @@ If ARG is a negative number, turn header display off."
   "Show the headers if they are hidden, or hide them if they are shown.
 If ARG is a positive number, show the entire header.
 If ARG is a negative number, hide the unwanted header lines."
-  (interactive "P")
+  (interactive "P" gnus-summary-mode)
   (let ((window (and (gnus-buffer-live-p gnus-article-buffer)
                     (get-buffer-window gnus-article-buffer t))))
     (with-current-buffer gnus-article-buffer
@@ -9947,14 +9971,14 @@ If ARG is a negative number, hide the unwanted header 
lines."
 
 (defun gnus-summary-show-all-headers ()
   "Make all header lines visible."
-  (interactive)
+  (interactive nil gnus-summary-mode)
   (gnus-summary-toggle-header 1))
 
 (defun gnus-summary-caesar-message (&optional arg)
   "Caesar rotate the current article by 13.
 With a non-numerical prefix, also rotate headers.  A numerical
 prefix specifies how many places to rotate each letter forward."
-  (interactive "P")
+  (interactive "P" gnus-summary-mode)
   (gnus-summary-select-article)
   (let ((mail-header-separator ""))
     (gnus-eval-in-buffer-window gnus-article-buffer
@@ -9977,7 +10001,7 @@ invalid IDNA string (`xn--bar' is invalid).
 
 You must have GNU Libidn (URL `https://www.gnu.org/software/libidn/')
 installed for this command to work."
-  (interactive)
+  (interactive nil gnus-summary-mode)
   (gnus-summary-select-article)
   (let ((mail-header-separator ""))
     (gnus-eval-in-buffer-window gnus-article-buffer
@@ -9991,7 +10015,7 @@ installed for this command to work."
 
 (defun gnus-summary-morse-message (&optional _arg)
   "Morse decode the current article."
-  (interactive)
+  (interactive nil gnus-summary-mode)
   (gnus-summary-select-article)
   (let ((mail-header-separator ""))
     (gnus-eval-in-buffer-window gnus-article-buffer
@@ -10012,7 +10036,7 @@ installed for this command to work."
 
 (defun gnus-summary-stop-page-breaking ()
   "Stop page breaking in the current article."
-  (interactive)
+  (interactive nil gnus-summary-mode)
   (gnus-summary-select-article)
   (gnus-eval-in-buffer-window gnus-article-buffer
     (widen)
@@ -10042,7 +10066,7 @@ newsgroup that you want to move to have to support the 
`request-move'
 and `request-accept' functions.
 
 ACTION can be either `move' (the default), `crosspost' or `copy'."
-  (interactive "P")
+  (interactive "P" gnus-summary-mode)
   (unless action
     (setq action 'move))
   ;; Check whether the source group supports the required functions.
@@ -10348,13 +10372,13 @@ ACTION can be either `move' (the default), 
`crosspost' or `copy'."
 (defun gnus-summary-copy-article (&optional n to-newsgroup select-method)
   "Copy the current article to some other group.
 Arguments have the same meanings as in `gnus-summary-move-article'."
-  (interactive "P")
+  (interactive "P" gnus-summary-mode)
   (gnus-summary-move-article n to-newsgroup select-method 'copy))
 
 (defun gnus-summary-crosspost-article (&optional n)
   "Crosspost the current article to some other group.
 Arguments have the same meanings as in `gnus-summary-move-article'."
-  (interactive "P")
+  (interactive "P" gnus-summary-mode)
   (gnus-summary-move-article n nil nil 'crosspost))
 
 (defcustom gnus-summary-respool-default-method nil
@@ -10398,7 +10422,8 @@ latter case, they will be copied into the relevant 
groups."
            (t
             (let ((ms-alist (mapcar (lambda (m) (cons (cadr m) m)) ms)))
               (cdr (assoc (gnus-completing-read "Server name" ms-alist t)
-                          ms-alist))))))))
+                          ms-alist)))))))
+   gnus-summary-mode)
   (unless method
     (error "No method given for respooling"))
   (if (assoc (symbol-name
@@ -10409,7 +10434,7 @@ latter case, they will be copied into the relevant 
groups."
 
 (defun gnus-summary-import-article (file &optional edit)
   "Import an arbitrary file into a mail newsgroup."
-  (interactive "fImport file: \nP")
+  (interactive "fImport file: \nP" gnus-summary-mode)
   (let ((group gnus-newsgroup-name)
        atts lines group-art)
     (unless (gnus-check-backend-function 'request-accept-article group)
@@ -10453,7 +10478,7 @@ latter case, they will be copied into the relevant 
groups."
 
 (defun gnus-summary-create-article ()
   "Create an article in a mail newsgroup."
-  (interactive)
+  (interactive nil gnus-summary-mode)
   (let ((group gnus-newsgroup-name)
        (now (current-time))
        group-art)
@@ -10477,7 +10502,7 @@ latter case, they will be copied into the relevant 
groups."
 (defun gnus-summary-article-posted-p ()
   "Say whether the current (mail) article is available from news as well.
 This will be the case if the article has both been mailed and posted."
-  (interactive)
+  (interactive nil gnus-summary-mode)
   (let ((id (mail-header-references (gnus-summary-article-header)))
        (gnus-override-method (car (gnus-refer-article-methods))))
     (if (gnus-request-head id "")
@@ -10489,7 +10514,7 @@ This will be the case if the article has both been 
mailed and posted."
 
 (defun gnus-summary-expire-articles (&optional now)
   "Expire all articles that are marked as expirable in the current group."
-  (interactive)
+  (interactive nil gnus-summary-mode)
   (when (and (not gnus-group-is-exiting-without-update-p)
             (gnus-check-backend-function
              'request-expire-articles gnus-newsgroup-name))
@@ -10558,7 +10583,7 @@ This will be the case if the article has both been 
mailed and posted."
   "Expunge all expirable articles in the current group.
 This means that *all* articles that are marked as expirable will be
 deleted forever, right now."
-  (interactive)
+  (interactive nil gnus-summary-mode)
   (or gnus-expert-user
       (gnus-yes-or-no-p
        "Are you really, really sure you want to delete all expirable messages? 
")
@@ -10578,7 +10603,7 @@ delete these instead.
 
 If `gnus-novice-user' is non-nil you will be asked for
 confirmation before the articles are deleted."
-  (interactive "P")
+  (interactive "P" gnus-summary-mode)
   (unless (gnus-check-backend-function 'request-expire-articles
                                       gnus-newsgroup-name)
     (error "The current newsgroup does not support article deletion"))
@@ -10628,7 +10653,7 @@ If ARG is 2, edit the raw articles even in read-only 
groups.
 If ARG is 3, edit the articles with the current handles.
 Otherwise, allow editing of articles even in read-only
 groups."
-  (interactive "P")
+  (interactive "P" gnus-summary-mode)
   (let (force raw current-handles)
     (cond
      ((null arg))
@@ -10708,7 +10733,7 @@ groups."
 (defun gnus-summary-edit-article-done (&optional references read-only buffer
                                                 no-highlight)
   "Make edits to the current article permanent."
-  (interactive)
+  (interactive nil gnus-summary-mode)
   (save-excursion
     ;; The buffer restriction contains the entire article if it exists.
     (when (article-goto-body)
@@ -10796,7 +10821,8 @@ groups."
    (list
     (progn
       (message "%s" (concat (this-command-keys) "- "))
-      (read-char))))
+      (read-char)))
+   gnus-summary-mode)
   (message "")
   (gnus-summary-edit-article)
   (execute-kbd-macro (concat (this-command-keys) key))
@@ -10809,7 +10835,7 @@ groups."
 
 (defun gnus-summary-respool-query (&optional silent trace)
   "Query where the respool algorithm would put this article."
-  (interactive)
+  (interactive nil gnus-summary-mode)
   (let (gnus-mark-article-hook)
     (gnus-summary-select-article)
     (with-current-buffer gnus-original-article-buffer
@@ -10839,7 +10865,7 @@ groups."
 (defun gnus-summary-respool-trace ()
   "Trace where the respool algorithm would put this article.
 Display a buffer showing all fancy splitting patterns which matched."
-  (interactive)
+  (interactive nil gnus-summary-mode)
   (gnus-summary-respool-query nil t))
 
 ;; Summary marking commands.
@@ -10848,7 +10874,7 @@ Display a buffer showing all fancy splitting patterns 
which matched."
   "Mark articles which has the same subject as read, and then select the next.
 If UNMARK is positive, remove any kind of mark.
 If UNMARK is negative, tick articles."
-  (interactive "P")
+  (interactive "P" gnus-summary-mode)
   (when unmark
     (setq unmark (prefix-numeric-value unmark)))
   (let ((count
@@ -10866,7 +10892,7 @@ If UNMARK is negative, tick articles."
   "Mark articles which has the same subject as read.
 If UNMARK is positive, remove any kind of mark.
 If UNMARK is negative, tick articles."
-  (interactive "P")
+  (interactive "P" gnus-summary-mode)
   (when unmark
     (setq unmark (prefix-numeric-value unmark)))
   (let ((count
@@ -10916,7 +10942,7 @@ If optional argument UNMARK is negative, mark articles 
as unread instead."
 If N is negative, mark backward instead.  If UNMARK is non-nil, remove
 the process mark instead.  The difference between N and the actual
 number of articles marked is returned."
-  (interactive "P")
+  (interactive "P" gnus-summary-mode)
   (if (and (null n) (and transient-mark-mode mark-active))
       (gnus-uu-mark-region (region-beginning) (region-end) unmark)
     (setq n (prefix-numeric-value n))
@@ -10940,12 +10966,12 @@ number of articles marked is returned."
   "Remove the process mark from the next N articles.
 If N is negative, unmark backward instead.  The difference between N and
 the actual number of articles unmarked is returned."
-  (interactive "P")
+  (interactive "P" gnus-summary-mode)
   (gnus-summary-mark-as-processable n t))
 
 (defun gnus-summary-unmark-all-processable ()
   "Remove the process mark from all articles."
-  (interactive)
+  (interactive nil gnus-summary-mode)
   (save-excursion
     (while gnus-newsgroup-processable
       (gnus-summary-remove-process-mark (car gnus-newsgroup-processable))))
@@ -10969,20 +10995,21 @@ the actual number of articles unmarked is returned."
   "Mark N articles forward as expirable.
 If N is negative, mark backward instead.  The difference between N and
 the actual number of articles marked is returned."
-  (interactive "p")
+  (interactive "p" gnus-summary-mode)
   (gnus-summary-mark-forward n gnus-expirable-mark))
 
 (defun gnus-summary-mark-as-spam (n)
   "Mark N articles forward as spam.
 If N is negative, mark backward instead.  The difference between N and
 the actual number of articles marked is returned."
-  (interactive "p")
+  (interactive "p" gnus-summary-mode)
   (gnus-summary-mark-forward n gnus-spam-mark))
 
 (defun gnus-summary-mark-article-as-replied (article)
   "Mark ARTICLE as replied to and update the summary line.
 ARTICLE can also be a list of articles."
-  (interactive (list (gnus-summary-article-number)))
+  (interactive (list (gnus-summary-article-number))
+              gnus-summary-mode)
   (let ((articles (if (listp article) article (list article))))
     (dolist (article articles)
       (unless (numberp article)
@@ -11004,7 +11031,8 @@ ARTICLE can also be a list of articles."
 
 (defun gnus-summary-set-bookmark (article)
   "Set a bookmark in current article."
-  (interactive (list (gnus-summary-article-number)))
+  (interactive (list (gnus-summary-article-number))
+              gnus-summary-mode)
   (when (or (not (get-buffer gnus-article-buffer))
            (not gnus-current-article)
            (not gnus-article-current)
@@ -11028,7 +11056,8 @@ ARTICLE can also be a list of articles."
 
 (defun gnus-summary-remove-bookmark (article)
   "Remove the bookmark from the current article."
-  (interactive (list (gnus-summary-article-number)))
+  (interactive (list (gnus-summary-article-number))
+              gnus-summary-mode)
   ;; Remove old bookmark, if one exists.
   (if (not (assq article gnus-newsgroup-bookmarks))
       (gnus-message 6 "No bookmark in current article.")
@@ -11040,7 +11069,7 @@ ARTICLE can also be a list of articles."
   "Mark N articles forward as dormant.
 If N is negative, mark backward instead.  The difference between N and
 the actual number of articles marked is returned."
-  (interactive "p")
+  (interactive "p" gnus-summary-mode)
   (gnus-summary-mark-forward n gnus-dormant-mark))
 
 (defun gnus-summary-set-process-mark (article)
@@ -11075,7 +11104,7 @@ If N is negative, mark backwards instead.  Mark with 
MARK, ?r by default.
 The difference between N and the actual number of articles marked is
 returned.
 If NO-EXPIRE, auto-expiry will be inhibited."
-  (interactive "p")
+  (interactive "p" gnus-summary-mode)
   (gnus-summary-show-thread)
   (let ((backward (< n 0))
        (gnus-summary-goto-unread
@@ -11339,20 +11368,20 @@ If NO-EXPIRE, auto-expiry will be inhibited."
   "Tick N articles forwards.
 If N is negative, tick backwards instead.
 The difference between N and the number of articles ticked is returned."
-  (interactive "p")
+  (interactive "p" gnus-summary-mode)
   (gnus-summary-mark-forward n gnus-ticked-mark))
 
 (defun gnus-summary-tick-article-backward (n)
   "Tick N articles backwards.
 The difference between N and the number of articles ticked is returned."
-  (interactive "p")
+  (interactive "p" gnus-summary-mode)
   (gnus-summary-mark-forward (- n) gnus-ticked-mark))
 
 (defun gnus-summary-tick-article (&optional article clear-mark)
   "Mark current article as unread.
 Optional 1st argument ARTICLE specifies article number to be marked as unread.
 Optional 2nd argument CLEAR-MARK remove any kinds of mark."
-  (interactive)
+  (interactive nil gnus-summary-mode)
   (gnus-summary-mark-article article (if clear-mark gnus-unread-mark
                                       gnus-ticked-mark)))
 
@@ -11361,14 +11390,14 @@ Optional 2nd argument CLEAR-MARK remove any kinds of 
mark."
 If N is negative, mark backwards instead.
 The difference between N and the actual number of articles marked is
 returned."
-  (interactive "p")
+  (interactive "p" gnus-summary-mode)
   (gnus-summary-mark-forward n gnus-del-mark gnus-inhibit-user-auto-expire))
 
 (defun gnus-summary-mark-as-read-backward (n)
   "Mark the N articles as read backwards.
 The difference between N and the actual number of articles marked is
 returned."
-  (interactive "p")
+  (interactive "p" gnus-summary-mode)
   (gnus-summary-mark-forward
    (- n) gnus-del-mark gnus-inhibit-user-auto-expire))
 
@@ -11382,13 +11411,13 @@ MARK specifies a string to be inserted at the 
beginning of the line."
   "Clear marks from N articles forward.
 If N is negative, clear backward instead.
 The difference between N and the number of marks cleared is returned."
-  (interactive "p")
+  (interactive "p" gnus-summary-mode)
   (gnus-summary-mark-forward n gnus-unread-mark))
 
 (defun gnus-summary-clear-mark-backward (n)
   "Clear marks from N articles backward.
 The difference between N and the number of marks cleared is returned."
-  (interactive "p")
+  (interactive "p" gnus-summary-mode)
   (gnus-summary-mark-forward (- n) gnus-unread-mark))
 
 (defun gnus-summary-mark-unread-as-read ()
@@ -11421,7 +11450,7 @@ The difference between N and the number of marks 
cleared is returned."
   "Mark all unread articles between point and mark as read.
 If given a prefix, mark all articles between point and mark as read,
 even ticked and dormant ones."
-  (interactive "r\nP")
+  (interactive "r\nP" gnus-summary-mode)
   (save-excursion
     (let (article)
       (goto-char point)
@@ -11438,7 +11467,7 @@ even ticked and dormant ones."
 
 (defun gnus-summary-mark-below (score mark)
   "Mark articles with score less than SCORE with MARK."
-  (interactive "P\ncMark: ")
+  (interactive "P\ncMark: " gnus-summary-mode)
   (setq score (if score
                  (prefix-numeric-value score)
                (or gnus-summary-default-score 0)))
@@ -11452,22 +11481,22 @@ even ticked and dormant ones."
 
 (defun gnus-summary-kill-below (&optional score)
   "Mark articles with score below SCORE as read."
-  (interactive "P")
+  (interactive "P" gnus-summary-mode)
   (gnus-summary-mark-below score gnus-killed-mark))
 
 (defun gnus-summary-clear-above (&optional score)
   "Clear all marks from articles with score above SCORE."
-  (interactive "P")
+  (interactive "P" gnus-summary-mode)
   (gnus-summary-mark-above score gnus-unread-mark))
 
 (defun gnus-summary-tick-above (&optional score)
   "Tick all articles with score above SCORE."
-  (interactive "P")
+  (interactive "P" gnus-summary-mode)
   (gnus-summary-mark-above score gnus-ticked-mark))
 
 (defun gnus-summary-mark-above (score mark)
   "Mark articles with score over SCORE with MARK."
-  (interactive "P\ncMark: ")
+  (interactive "P\ncMark: " gnus-summary-mode)
   (setq score (if score
                  (prefix-numeric-value score)
                (or gnus-summary-default-score 0)))
@@ -11483,7 +11512,7 @@ even ticked and dormant ones."
 (defalias 'gnus-summary-show-all-expunged 'gnus-summary-limit-include-expunged)
 (defun gnus-summary-limit-include-expunged (&optional no-error)
   "Display all the hidden articles that were expunged for low scores."
-  (interactive)
+  (interactive nil gnus-summary-mode)
   (let ((inhibit-read-only t))
     (let ((scored gnus-newsgroup-scored)
          headers h)
@@ -11520,7 +11549,7 @@ Note that this function will only catch up the unread 
article
 in the current summary buffer limitation.
 
 The number of articles marked as read is returned."
-  (interactive "P")
+  (interactive "P" gnus-summary-mode)
   (prog1
       (save-excursion
        (when (or quietly
@@ -11569,7 +11598,7 @@ The number of articles marked as read is returned."
 (defun gnus-summary-catchup-to-here (&optional all)
   "Mark all unticked articles before the current one as read.
 If ALL is non-nil, also mark ticked and dormant articles as read."
-  (interactive "P")
+  (interactive "P" gnus-summary-mode)
   (save-excursion
     (gnus-save-hidden-threads
       (let ((beg (point)))
@@ -11581,7 +11610,7 @@ If ALL is non-nil, also mark ticked and dormant 
articles as read."
 (defun gnus-summary-catchup-from-here (&optional all)
   "Mark all unticked articles after (and including) the current one as read.
 If ALL is non-nil, also mark ticked and dormant articles as read."
-  (interactive "P")
+  (interactive "P" gnus-summary-mode)
   (save-excursion
     (gnus-save-hidden-threads
       (let ((beg (point)))
@@ -11594,14 +11623,14 @@ If ALL is non-nil, also mark ticked and dormant 
articles as read."
   "Mark all articles in this newsgroup as read.
 This command is dangerous.  Normally, you want \\[gnus-summary-catchup]
 instead, which marks only unread articles as read."
-  (interactive "P")
+  (interactive "P" gnus-summary-mode)
   (gnus-summary-catchup t quietly))
 
 (defun gnus-summary-catchup-and-exit (&optional all quietly)
   "Mark all unread articles in this group as read, then exit.
 If prefix argument ALL is non-nil, all articles are marked as read.
 If QUIETLY is non-nil, no questions will be asked."
-  (interactive "P")
+  (interactive "P" gnus-summary-mode)
   (when (gnus-summary-catchup all quietly nil 'fast)
     ;; Select next newsgroup or exit.
     (if (and (not (gnus-group-quit-config gnus-newsgroup-name))
@@ -11613,14 +11642,14 @@ If QUIETLY is non-nil, no questions will be asked."
   "Mark all articles in this newsgroup as read, and then exit.
 This command is dangerous.  Normally, you want 
\\[gnus-summary-catchup-and-exit]
 instead, which marks only unread articles as read."
-  (interactive "P")
+  (interactive "P" gnus-summary-mode)
   (gnus-summary-catchup-and-exit t quietly))
 
 (defun gnus-summary-catchup-and-goto-next-group (&optional all)
   "Mark all articles in this group as read and select the next group.
 If given a prefix, mark all articles, unread as well as ticked, as
 read."
-  (interactive "P")
+  (interactive "P" gnus-summary-mode)
   (save-excursion
     (gnus-summary-catchup all))
   (gnus-summary-next-group))
@@ -11629,7 +11658,7 @@ read."
   "Mark all articles in this group as read and select the previous group.
 If given a prefix, mark all articles, unread as well as ticked, as
 read."
-  (interactive "P")
+  (interactive "P" gnus-summary-mode)
   (save-excursion
     (gnus-summary-catchup all))
   (gnus-summary-next-group nil nil t))
@@ -11705,7 +11734,7 @@ with that article."
 
 (defun gnus-summary-rethread-current ()
   "Rethread the thread the current article is part of."
-  (interactive)
+  (interactive nil gnus-summary-mode)
   (let* ((gnus-show-threads t)
         (article (gnus-summary-article-number))
         (id (mail-header-id (gnus-summary-article-header)))
@@ -11720,7 +11749,7 @@ with that article."
 
 Note that the re-threading will only work if `gnus-thread-ignore-subject'
 is non-nil or the Subject: of both articles are the same."
-  (interactive)
+  (interactive nil gnus-summary-mode)
   (unless (not (gnus-group-read-only-p))
     (error "The current newsgroup does not support article editing"))
   (unless (<= (length gnus-newsgroup-processable) 1)
@@ -11739,9 +11768,10 @@ is non-nil or the Subject: of both articles are the 
same."
   "Make PARENT the parent of CHILDREN.
 When called interactively, PARENT is the current article and CHILDREN
 are the process-marked articles."
-  (interactive
-   (list (gnus-summary-article-number)
-        (gnus-summary-work-articles nil)))
+  (interactive (list
+               (gnus-summary-article-number)
+               (gnus-summary-work-articles nil))
+              gnus-summary-mode)
   (dolist (child children)
     (save-window-excursion
       (let ((gnus-article-buffer " *reparent*"))
@@ -11774,7 +11804,7 @@ are the process-marked articles."
 (defun gnus-summary-toggle-threads (&optional arg)
   "Toggle showing conversation threads.
 If ARG is positive number, turn showing conversation threads on."
-  (interactive "P")
+  (interactive "P" gnus-summary-mode)
   (let ((current (or (gnus-summary-article-number) gnus-newsgroup-end)))
     (setq gnus-show-threads
          (if (null arg) (not gnus-show-threads)
@@ -11786,7 +11816,7 @@ If ARG is positive number, turn showing conversation 
threads on."
 
 (defun gnus-summary-show-all-threads ()
   "Show all threads."
-  (interactive)
+  (interactive nil gnus-summary-mode)
   (remove-overlays (point-min) (point-max) 'invisible 'gnus-sum)
   (gnus-summary-position-point))
 
@@ -11796,7 +11826,7 @@ If ARG is positive number, turn showing conversation 
threads on."
 (defun gnus-summary-show-thread ()
   "Show thread subtrees.
 Returns nil if no thread was there to be shown."
-  (interactive)
+  (interactive nil gnus-summary-mode)
   (let* ((orig (point))
         (end (point-at-eol))
          (end (or (gnus-summary--inv end) (gnus-summary--inv (1- end))))
@@ -11837,7 +11867,7 @@ Returns nil if no thread was there to be shown."
   "Hide all thread subtrees.
 If PREDICATE is supplied, threads that satisfy this predicate
 will not be hidden."
-  (interactive)
+  (interactive nil gnus-summary-mode)
   (save-excursion
     (goto-char (point-min))
     (let ((end nil)
@@ -11856,7 +11886,7 @@ will not be hidden."
 (defun gnus-summary-hide-thread ()
   "Hide thread subtrees.
 Returns nil if no threads were there to be hidden."
-  (interactive)
+  (interactive nil gnus-summary-mode)
   (beginning-of-line)
   (let ((start (point))
        (starteol (line-end-position))
@@ -11908,7 +11938,7 @@ Returns the difference between N and the number of 
skips actually
 done.
 
 If SILENT, don't output messages."
-  (interactive "p")
+  (interactive "p" gnus-summary-mode)
   (let ((backward (< n 0))
        (n (abs n)))
     (while (and (> n 0)
@@ -11924,7 +11954,7 @@ If SILENT, don't output messages."
   "Go to the same level previous N'th thread.
 Returns the difference between N and the number of skips actually
 done."
-  (interactive "p")
+  (interactive "p" gnus-summary-mode)
   (gnus-summary-next-thread (- n)))
 
 (defun gnus-summary-go-down-thread ()
@@ -11944,7 +11974,7 @@ done."
 If N is negative, go up instead.
 Returns the difference between N and how many steps down that were
 taken."
-  (interactive "p")
+  (interactive "p" gnus-summary-mode)
   (let ((up (< n 0))
        (n (abs n)))
     (while (and (> n 0)
@@ -11961,18 +11991,18 @@ taken."
 If N is negative, go down instead.
 Returns the difference between N and how many steps down that were
 taken."
-  (interactive "p")
+  (interactive "p" gnus-summary-mode)
   (gnus-summary-down-thread (- n)))
 
 (defun gnus-summary-top-thread ()
   "Go to the top of the thread."
-  (interactive)
+  (interactive nil gnus-summary-mode)
   (while (gnus-summary-go-up-thread))
   (gnus-summary-article-number))
 
 (defun gnus-summary-expire-thread ()
   "Mark articles under current thread as expired."
-  (interactive)
+  (interactive nil gnus-summary-mode)
   (gnus-summary-kill-thread 0))
 
 (defun gnus-summary-kill-thread (&optional unmark)
@@ -11980,7 +12010,7 @@ taken."
 If the prefix argument is positive, remove any kinds of marks.
 If the prefix argument is zero, mark thread as expired.
 If the prefix argument is negative, tick articles instead."
-  (interactive "P")
+  (interactive "P" gnus-summary-mode)
   (when unmark
     (setq unmark (prefix-numeric-value unmark)))
   (let ((articles (gnus-summary-articles-in-thread))
@@ -12015,82 +12045,82 @@ If the prefix argument is negative, tick articles 
instead."
 (defun gnus-summary-sort-by-number (&optional reverse)
   "Sort the summary buffer by article number.
 Argument REVERSE means reverse order."
-  (interactive "P")
+  (interactive "P" gnus-summary-mode)
   (gnus-summary-sort 'number reverse))
 
 (defun gnus-summary-sort-by-most-recent-number (&optional reverse)
   "Sort the summary buffer by most recent article number.
 Argument REVERSE means reverse order."
-  (interactive "P")
+  (interactive "P" gnus-summary-mode)
   (gnus-summary-sort 'most-recent-number reverse))
 
 (defun gnus-summary-sort-by-random (&optional reverse)
   "Randomize the order in the summary buffer.
 Argument REVERSE means to randomize in reverse order."
-  (interactive "P")
+  (interactive "P" gnus-summary-mode)
   (gnus-summary-sort 'random reverse))
 
 (defun gnus-summary-sort-by-author (&optional reverse)
   "Sort the summary buffer by author name alphabetically.
 If `case-fold-search' is non-nil, case of letters is ignored.
 Argument REVERSE means reverse order."
-  (interactive "P")
+  (interactive "P" gnus-summary-mode)
   (gnus-summary-sort 'author reverse))
 
 (defun gnus-summary-sort-by-recipient (&optional reverse)
   "Sort the summary buffer by recipient name alphabetically.
 If `case-fold-search' is non-nil, case of letters is ignored.
 Argument REVERSE means reverse order."
-  (interactive "P")
+  (interactive "P" gnus-summary-mode)
   (gnus-summary-sort 'recipient reverse))
 
 (defun gnus-summary-sort-by-subject (&optional reverse)
   "Sort the summary buffer by subject alphabetically.  `Re:'s are ignored.
 If `case-fold-search' is non-nil, case of letters is ignored.
 Argument REVERSE means reverse order."
-  (interactive "P")
+  (interactive "P" gnus-summary-mode)
   (gnus-summary-sort 'subject reverse))
 
 (defun gnus-summary-sort-by-date (&optional reverse)
   "Sort the summary buffer by date.
 Argument REVERSE means reverse order."
-  (interactive "P")
+  (interactive "P" gnus-summary-mode)
   (gnus-summary-sort 'date reverse))
 
 (defun gnus-summary-sort-by-most-recent-date (&optional reverse)
   "Sort the summary buffer by most recent date.
 Argument REVERSE means reverse order."
-  (interactive "P")
+  (interactive "P" gnus-summary-mode)
   (gnus-summary-sort 'most-recent-date reverse))
 
 (defun gnus-summary-sort-by-score (&optional reverse)
   "Sort the summary buffer by score.
 Argument REVERSE means reverse order."
-  (interactive "P")
+  (interactive "P" gnus-summary-mode)
   (gnus-summary-sort 'score reverse))
 
 (defun gnus-summary-sort-by-lines (&optional reverse)
   "Sort the summary buffer by the number of lines.
 Argument REVERSE means reverse order."
-  (interactive "P")
+  (interactive "P" gnus-summary-mode)
   (gnus-summary-sort 'lines reverse))
 
 (defun gnus-summary-sort-by-chars (&optional reverse)
   "Sort the summary buffer by article length.
 Argument REVERSE means reverse order."
-  (interactive "P")
+  (interactive "P" gnus-summary-mode)
   (gnus-summary-sort 'chars reverse))
 
 (defun gnus-summary-sort-by-marks (&optional reverse)
   "Sort the summary buffer by article marks.
 Argument REVERSE means reverse order."
-  (interactive "P")
+  (interactive "P" gnus-summary-mode)
   (gnus-summary-sort 'marks reverse))
 
 (defun gnus-summary-sort-by-original (&optional _reverse)
   "Sort the summary buffer using the default sorting method.
 Argument REVERSE means reverse order."
-  (interactive)
+  (interactive nil gnus-summary-mode)
   (let* ((inhibit-read-only t)
         (gnus-summary-prepare-hook nil))
     ;; We do the sorting by regenerating the threads.
@@ -12139,7 +12169,7 @@ will not be marked as saved.
 
 The `gnus-prompt-before-saving' variable says how prompting is
 performed."
-  (interactive "P")
+  (interactive "P" gnus-summary-mode)
   (require 'gnus-art)
   (let* ((articles (gnus-summary-work-articles n))
         (save-buffer (save-excursion
@@ -12208,7 +12238,7 @@ is neither omitted nor the symbol `r', force including 
all headers
 regardless of the `:headers' property.  If it is the symbol `r',
 articles that are not decoded and include all headers will be piped
 no matter what the properties `:decode' and `:headers' are."
-  (interactive (gnus-interactive "P\ny"))
+  (interactive (gnus-interactive "P\ny") gnus-summary-mode)
   (require 'gnus-art)
   (let* ((articles (gnus-summary-work-articles n))
         (result-buffer shell-command-buffer-name)
@@ -12260,7 +12290,7 @@ If N is a positive number, save the N next articles.
 If N is a negative number, save the N previous articles.
 If N is nil and any articles have been marked with the process mark,
 save those articles instead."
-  (interactive "P")
+  (interactive "P" gnus-summary-mode)
   (require 'gnus-art)
   (let ((gnus-default-article-saver 'gnus-summary-save-in-mail))
     (gnus-summary-save-article arg)))
@@ -12271,7 +12301,7 @@ If N is a positive number, save the N next articles.
 If N is a negative number, save the N previous articles.
 If N is nil and any articles have been marked with the process mark,
 save those articles instead."
-  (interactive "P")
+  (interactive "P" gnus-summary-mode)
   (require 'gnus-art)
   (let ((gnus-default-article-saver 'gnus-summary-save-in-rmail))
     (gnus-summary-save-article arg)))
@@ -12282,7 +12312,7 @@ If N is a positive number, save the N next articles.
 If N is a negative number, save the N previous articles.
 If N is nil and any articles have been marked with the process mark,
 save those articles instead."
-  (interactive "P")
+  (interactive "P" gnus-summary-mode)
   (require 'gnus-art)
   (let ((gnus-default-article-saver 'gnus-summary-save-in-file))
     (gnus-summary-save-article arg)))
@@ -12293,7 +12323,7 @@ If N is a positive number, save the N next articles.
 If N is a negative number, save the N previous articles.
 If N is nil and any articles have been marked with the process mark,
 save those articles instead."
-  (interactive "P")
+  (interactive "P" gnus-summary-mode)
   (require 'gnus-art)
   (let ((gnus-default-article-saver 'gnus-summary-write-to-file))
     (gnus-summary-save-article arg)))
@@ -12304,7 +12334,7 @@ If N is a positive number, save the N next articles.
 If N is a negative number, save the N previous articles.
 If N is nil and any articles have been marked with the process mark,
 save those articles instead."
-  (interactive "P")
+  (interactive "P" gnus-summary-mode)
   (require 'gnus-art)
   (let ((gnus-default-article-saver 'gnus-summary-save-body-in-file))
     (gnus-summary-save-article arg)))
@@ -12315,7 +12345,7 @@ If N is a positive number, save the N next articles.
 If N is a negative number, save the N previous articles.
 If N is nil and any articles have been marked with the process mark,
 save those articles instead."
-  (interactive "P")
+  (interactive "P" gnus-summary-mode)
   (require 'gnus-art)
   (let ((gnus-default-article-saver 'gnus-summary-write-body-to-file))
     (gnus-summary-save-article arg)))
@@ -12326,14 +12356,14 @@ If N is a positive number, save the N next articles.
 If N is a negative number, save the N previous articles.
 If N is nil and any articles have been marked with the process mark,
 save those articles instead."
-  (interactive "P")
+  (interactive "P" gnus-summary-mode)
   (require 'gnus-art)
   (let ((gnus-default-article-saver 'gnus-summary-pipe-to-muttprint))
     (gnus-summary-save-article arg t)))
 
 (defun gnus-summary-pipe-message (program)
   "Pipe the current article through PROGRAM."
-  (interactive "sProgram: ")
+  (interactive "sProgram: " gnus-summary-mode)
   (gnus-summary-select-article)
   (let ((mail-header-separator ""))
     (gnus-eval-in-buffer-window gnus-article-buffer
@@ -12451,7 +12481,8 @@ If REVERSE, save parts that do not match TYPE."
               (read-directory-name "Save to directory: "
                                     gnus-summary-save-parts-last-directory
                                     nil t))
-        current-prefix-arg))
+        current-prefix-arg)
+   gnus-summary-mode)
   (gnus-summary-iterate n
     (let ((gnus-display-mime-function nil)
          gnus-article-prepare-hook
@@ -12590,12 +12621,12 @@ If REVERSE, save parts that do not match TYPE."
 
 (defun gnus-summary-edit-global-kill (article)
   "Edit the \"global\" kill file."
-  (interactive (list (gnus-summary-article-number)))
+  (interactive (list (gnus-summary-article-number)) gnus-summary-mode)
   (gnus-group-edit-global-kill article))
 
 (defun gnus-summary-edit-local-kill ()
   "Edit a local kill file applied to the current newsgroup."
-  (interactive)
+  (interactive nil gnus-summary-mode)
   (setq gnus-current-headers (gnus-summary-article-header))
   (gnus-group-edit-local-kill
    (gnus-summary-article-number) gnus-newsgroup-name))
@@ -12707,7 +12738,7 @@ If REVERSE, save parts that do not match TYPE."
        ;; so we highlight the entire line instead.
        (when (= (+ to 2) from)
          (setq from beg)
-         (setq to end))
+         (setq to (1+ end)))
        (if gnus-newsgroup-selected-overlay
            ;; Move old overlay.
            (move-overlay
@@ -12762,7 +12793,7 @@ If REVERSE, save parts that do not match TYPE."
     (let ((face (funcall (gnus-summary-highlight-line-0))))
       (unless (eq face (gnus-get-text-property-excluding-characters-with-faces 
beg 'face))
        (gnus-put-text-property-excluding-characters-with-faces
-        beg (point-at-eol) 'face
+        beg (1+ (point-at-eol)) 'face
         (setq face (if (boundp face) (symbol-value face) face)))
        (when gnus-summary-highlight-line-function
          (funcall gnus-summary-highlight-line-function article face))))))
@@ -12893,7 +12924,7 @@ UNREAD is a sorted list."
   "Display the current article buffer fully MIME-buttonized.
 If SHOW-ALL-PARTS (the prefix) is non-nil, all multipart/* parts are
 treated as multipart/mixed."
-  (interactive "P")
+  (interactive "P" gnus-summary-mode)
   (require 'gnus-art)
   (let ((gnus-unbuttonized-mime-types nil)
        (gnus-mime-display-multipart-as-mixed show-all-parts))
@@ -12901,7 +12932,7 @@ treated as multipart/mixed."
 
 (defun gnus-summary-repair-multipart (article)
   "Add a Content-Type header to a multipart article without one."
-  (interactive (list (gnus-summary-article-number)))
+  (interactive (list (gnus-summary-article-number)) gnus-summary-mode)
   (gnus-with-article article
     (message-narrow-to-head)
     (message-remove-header "Mime-Version")
@@ -12921,7 +12952,7 @@ treated as multipart/mixed."
 
 (defun gnus-summary-toggle-display-buttonized ()
   "Toggle the buttonizing of the article buffer."
-  (interactive)
+  (interactive nil gnus-summary-mode)
   (require 'gnus-art)
   (if (setq gnus-inhibit-mime-unbuttonizing
            (not gnus-inhibit-mime-unbuttonizing))
@@ -12976,7 +13007,7 @@ If N is negative, move in reverse order.
 The difference between N and the actual number of articles marked is
 returned."
        name (cadr lway))
-     (interactive "p")
+     (interactive "p" gnus-summary-mode)
      (gnus-summary-generic-mark n ,mark ',(nth 2 lway) ,(nth 3 lway))))
 
 (defun gnus-summary-generic-mark (n mark move unread)
@@ -13059,7 +13090,7 @@ returned."
   "Insert all old articles in this group.
 If ALL is non-nil, already read articles become readable.
 If ALL is a number, fetch this number of articles."
-  (interactive "P")
+  (interactive "P" gnus-summary-mode)
   (prog1
       (let ((old (sort (mapcar #'gnus-data-number gnus-newsgroup-data) #'<))
            older len)
@@ -13133,7 +13164,7 @@ If ALL is a number, fetch this number of articles."
 
 (defun gnus-summary-insert-new-articles ()
   "Insert all new articles in this group."
-  (interactive)
+  (interactive nil gnus-summary-mode)
   (let ((old (sort (mapcar #'gnus-data-number gnus-newsgroup-data) #'<))
        (old-high gnus-newsgroup-highest)
        (nnmail-fetched-sources (list t))
diff --git a/lisp/gnus/gnus-topic.el b/lisp/gnus/gnus-topic.el
index 3253b78..b3d17bc 100644
--- a/lisp/gnus/gnus-topic.el
+++ b/lisp/gnus/gnus-topic.el
@@ -146,7 +146,8 @@ See Info node `(gnus)Formatting Variables'."
 (defun gnus-topic-jump-to-topic (topic)
   "Go to TOPIC."
   (interactive
-   (list (gnus-completing-read "Go to topic" (gnus-topic-list) t)))
+   (list (gnus-completing-read "Go to topic" (gnus-topic-list) t))
+   gnus-topic-mode)
   (let ((inhibit-read-only t))
     (dolist (topic (gnus-current-topics topic))
       (unless (gnus-topic-goto-topic topic)
@@ -235,12 +236,12 @@ If RECURSIVE is t, return groups in its subtopics too."
 
 (defun gnus-topic-goto-previous-topic (n)
   "Go to the N'th previous topic."
-  (interactive "p")
+  (interactive "p" gnus-topic-mode)
   (gnus-topic-goto-next-topic (- n)))
 
 (defun gnus-topic-goto-next-topic (n)
   "Go to the N'th next topic."
-  (interactive "p")
+  (interactive "p" gnus-topic-mode)
   (let ((backward (< n 0))
        (n (abs n))
        (topic (gnus-current-topic)))
@@ -661,7 +662,7 @@ articles in the topic and its subtopics."
 
 (defun gnus-topic-update-topics-containing-group (group)
   "Update all topics that have GROUP as a member."
-  (when (and (eq major-mode 'gnus-group-mode)
+  (when (and (eq major-mode 'gnus-topic-mode)
             gnus-topic-mode)
     (save-excursion
       (let ((alist gnus-topic-alist))
@@ -677,7 +678,7 @@ articles in the topic and its subtopics."
 
 (defun gnus-topic-update-topic ()
   "Update all parent topics to the current group."
-  (when (and (eq major-mode 'gnus-group-mode)
+  (when (and (eq major-mode 'gnus-topic-mode)
             gnus-topic-mode)
     (let ((group (gnus-group-group-name))
          (m (point-marker))
@@ -1122,7 +1123,9 @@ articles in the topic and its subtopics."
 
 (define-minor-mode gnus-topic-mode
   "Minor mode for topicsifying Gnus group buffers."
-  :lighter " Topic" :keymap gnus-topic-mode-map
+  :lighter " Topic"
+  :keymap gnus-topic-mode-map
+  :interactive (gnus-group-mode)
   (if (not (derived-mode-p 'gnus-group-mode))
       (setq gnus-topic-mode nil)
     ;; Infest Gnus with topics.
@@ -1172,7 +1175,7 @@ articles in the group.  If ALL is a negative number, 
fetch this
 number of the earliest articles in the group.
 
 If performed over a topic line, toggle folding the topic."
-  (interactive "P")
+  (interactive "P" gnus-topic-mode)
   (when (and (eobp) (not (gnus-group-group-name)))
     (forward-line -1))
   (if (gnus-group-topic-p)
@@ -1184,13 +1187,13 @@ If performed over a topic line, toggle folding the 
topic."
 
 (defun gnus-mouse-pick-topic (e)
   "Select the group or topic under the mouse pointer."
-  (interactive "e")
+  (interactive "e" gnus-topic-mode)
   (mouse-set-point e)
   (gnus-topic-read-group nil))
 
 (defun gnus-topic-expire-articles (topic)
   "Expire articles in this topic or group."
-  (interactive (list (gnus-group-topic-name)))
+  (interactive (list (gnus-group-topic-name)) gnus-topic-mode)
   (if (not topic)
       (call-interactively 'gnus-group-expire-articles)
     (save-excursion
@@ -1205,7 +1208,7 @@ If performed over a topic line, toggle folding the topic."
 (defun gnus-topic-catchup-articles (topic)
   "Catchup this topic or group.
 Also see `gnus-group-catchup'."
-  (interactive (list (gnus-group-topic-name)))
+  (interactive (list (gnus-group-topic-name)) gnus-topic-mode)
   (if (not topic)
       (call-interactively 'gnus-group-catchup-current)
     (save-excursion
@@ -1232,7 +1235,7 @@ be auto-selected upon group entry.  If GROUP is non-nil, 
fetch
 that group.
 
 If performed over a topic line, toggle folding the topic."
-  (interactive "P")
+  (interactive "P" gnus-topic-mode)
   (when (and (eobp) (not (gnus-group-group-name)))
     (forward-line -1))
   (if (gnus-group-topic-p)
@@ -1247,7 +1250,8 @@ When used interactively, PARENT will be the topic under 
point."
   (interactive
    (list
     (read-string "New topic: ")
-    (gnus-current-topic)))
+    (gnus-current-topic))
+   gnus-topic-mode)
   ;; Check whether this topic already exists.
   (when (gnus-topic-find-topology topic)
     (error "Topic already exists"))
@@ -1284,7 +1288,8 @@ If COPYP, copy the groups instead."
   (interactive
    (list current-prefix-arg
         (gnus-completing-read "Move to topic" (mapcar #'car gnus-topic-alist) t
-                              nil 'gnus-topic-history)))
+                              nil 'gnus-topic-history))
+   gnus-topic-mode)
   (let ((use-marked (and (not n) (not (and transient-mark-mode mark-active))
                         gnus-group-marked t))
        (groups (gnus-group-process-prefix n))
@@ -1309,7 +1314,7 @@ If COPYP, copy the groups instead."
 
 (defun gnus-topic-remove-group (&optional n)
   "Remove the current group from the topic."
-  (interactive "P")
+  (interactive "P" gnus-topic-mode)
   (let ((use-marked (and (not n) (not (and transient-mark-mode mark-active))
                         gnus-group-marked t))
        (groups (gnus-group-process-prefix n)))
@@ -1331,12 +1336,13 @@ If COPYP, copy the groups instead."
   (interactive
    (list current-prefix-arg
         (gnus-completing-read
-         "Copy to topic" (mapcar #'car gnus-topic-alist) t)))
+         "Copy to topic" (mapcar #'car gnus-topic-alist) t))
+   gnus-topic-mode)
   (gnus-topic-move-group n topic t))
 
 (defun gnus-topic-kill-group (&optional n discard)
   "Kill the next N groups."
-  (interactive "P")
+  (interactive "P" gnus-topic-mode)
   (if (gnus-group-topic-p)
       (let ((topic (gnus-group-topic-name)))
        (push (cons
@@ -1356,7 +1362,7 @@ If COPYP, copy the groups instead."
 
 (defun gnus-topic-yank-group (&optional arg)
   "Yank the last topic."
-  (interactive "p")
+  (interactive "p" gnus-topic-mode)
   (if gnus-topic-killed-topics
       (let* ((previous
              (or (gnus-group-topic-name)
@@ -1405,7 +1411,7 @@ If COPYP, copy the groups instead."
 (defun gnus-topic-hide-topic (&optional permanent)
   "Hide the current topic.
 If PERMANENT, make it stay hidden in subsequent sessions as well."
-  (interactive "P")
+  (interactive "P" gnus-topic-mode)
   (when (gnus-current-topic)
     (gnus-topic-goto-topic (gnus-current-topic))
     (if permanent
@@ -1418,7 +1424,7 @@ If PERMANENT, make it stay hidden in subsequent sessions 
as well."
 (defun gnus-topic-show-topic (&optional permanent)
   "Show the hidden topic.
 If PERMANENT, make it stay shown in subsequent sessions as well."
-  (interactive "P")
+  (interactive "P" gnus-topic-mode)
   (when (gnus-group-topic-p)
     (if (not permanent)
        (gnus-topic-remove-topic t nil)
@@ -1433,9 +1439,11 @@ If PERMANENT, make it stay shown in subsequent sessions 
as well."
 (defun gnus-topic-mark-topic (topic &optional unmark non-recursive)
   "Mark all groups in the TOPIC with the process mark.
 If NON-RECURSIVE (which is the prefix) is t, don't mark its subtopics."
-  (interactive (list (gnus-group-topic-name)
-                    nil
-                    (and current-prefix-arg t)))
+  (interactive
+   (list (gnus-group-topic-name)
+        nil
+        (and current-prefix-arg t))
+   gnus-topic-mode)
   (if (not topic)
       (call-interactively 'gnus-group-mark-group)
     (save-excursion
@@ -1450,14 +1458,15 @@ If NON-RECURSIVE (which is the prefix) is t, don't mark 
its subtopics."
 If NON-RECURSIVE (which is the prefix) is t, don't unmark its subtopics."
   (interactive (list (gnus-group-topic-name)
                     nil
-                    (and current-prefix-arg t)))
+                    (and current-prefix-arg t))
+              gnus-topic-mode)
   (if (not topic)
       (call-interactively 'gnus-group-unmark-group)
     (gnus-topic-mark-topic topic t non-recursive)))
 
 (defun gnus-topic-get-new-news-this-topic (&optional n)
   "Check for new news in the current topic."
-  (interactive "P")
+  (interactive "P" gnus-topic-mode)
   (if (not (gnus-group-topic-p))
       (gnus-group-get-new-news-this-group n)
     (let* ((topic (gnus-group-topic-name))
@@ -1475,7 +1484,8 @@ If NON-RECURSIVE (which is the prefix) is t, don't unmark 
its subtopics."
       (list
        (setq topic (gnus-completing-read "Move to topic"
                                          (mapcar #'car gnus-topic-alist) t))
-       (read-string (format "Move to %s (regexp): " topic))))))
+       (read-string (format "Move to %s (regexp): " topic)))))
+   gnus-topic-mode)
   (gnus-group-mark-regexp regexp)
   (gnus-topic-move-group nil topic copyp))
 
@@ -1486,12 +1496,13 @@ If NON-RECURSIVE (which is the prefix) is t, don't 
unmark its subtopics."
                                       (mapcar #'car gnus-topic-alist) t)))
      (nreverse
       (list topic
-            (read-string (format "Copy to %s (regexp): " topic))))))
+            (read-string (format "Copy to %s (regexp): " topic)))))
+   gnus-topic-mode)
   (gnus-topic-move-matching regexp topic t))
 
 (defun gnus-topic-delete (topic)
   "Delete a topic."
-  (interactive (list (gnus-group-topic-name)))
+  (interactive (list (gnus-group-topic-name)) gnus-topic-mode)
   (unless topic
     (error "No topic to be deleted"))
   (let ((entry (assoc topic gnus-topic-alist))
@@ -1512,7 +1523,8 @@ If NON-RECURSIVE (which is the prefix) is t, don't unmark 
its subtopics."
   (interactive
    (let ((topic (gnus-current-topic)))
      (list topic
-          (read-string (format "Rename %s to: " topic) topic))))
+          (read-string (format "Rename %s to: " topic) topic)))
+   gnus-topic-mode)
   ;; Check whether the new name exists.
   (when (gnus-topic-find-topology new-name)
     (error "Topic `%s' already exists" new-name))
@@ -1535,7 +1547,7 @@ If NON-RECURSIVE (which is the prefix) is t, don't unmark 
its subtopics."
 (defun gnus-topic-indent (&optional unindent)
   "Indent a topic -- make it a sub-topic of the previous topic.
 If UNINDENT, remove an indentation."
-  (interactive "P")
+  (interactive "P" gnus-topic-mode)
   (if unindent
       (gnus-topic-unindent)
     (let* ((topic (gnus-current-topic))
@@ -1555,7 +1567,7 @@ If UNINDENT, remove an indentation."
 
 (defun gnus-topic-unindent ()
   "Unindent a topic."
-  (interactive)
+  (interactive nil gnus-topic-mode)
   (let* ((topic (gnus-current-topic))
         (parent (gnus-topic-parent-topic topic))
         (grandparent (gnus-topic-parent-topic parent)))
@@ -1574,7 +1586,7 @@ If UNINDENT, remove an indentation."
 (defun gnus-topic-list-active (&optional force)
   "List all groups that Gnus knows about in a topicsified fashion.
 If FORCE, always re-read the active file."
-  (interactive "P")
+  (interactive "P" gnus-topic-mode)
   (when force
     (gnus-get-killed-groups))
   (gnus-topic-grok-active force)
@@ -1585,7 +1597,7 @@ If FORCE, always re-read the active file."
 
 (defun gnus-topic-toggle-display-empty-topics ()
   "Show/hide topics that have no unread articles."
-  (interactive)
+  (interactive nil gnus-topic-mode)
   (setq gnus-topic-display-empty-topics
        (not gnus-topic-display-empty-topics))
   (gnus-group-list-groups)
@@ -1598,7 +1610,7 @@ If FORCE, always re-read the active file."
 (defun gnus-topic-edit-parameters (group)
   "Edit the group parameters of GROUP.
 If performed on a topic, edit the topic parameters instead."
-  (interactive (list (gnus-group-group-name)))
+  (interactive (list (gnus-group-group-name)) gnus-topic-mode)
   (if group
       (gnus-group-edit-group-parameters group)
     (if (not (gnus-group-topic-p))
@@ -1642,7 +1654,8 @@ If performed on a topic, edit the topic parameters 
instead."
 (defun gnus-topic-sort-groups (func &optional reverse)
   "Sort the current topic according to FUNC.
 If REVERSE, reverse the sorting order."
-  (interactive (list gnus-group-sort-function current-prefix-arg))
+  (interactive (list gnus-group-sort-function current-prefix-arg)
+              gnus-topic-mode)
   (let ((topic (assoc (gnus-current-topic) gnus-topic-alist)))
     (gnus-topic-sort-topic
      topic (gnus-make-sort-function func) reverse)
@@ -1651,43 +1664,43 @@ If REVERSE, reverse the sorting order."
 (defun gnus-topic-sort-groups-by-alphabet (&optional reverse)
   "Sort the current topic alphabetically by group name.
 If REVERSE, sort in reverse order."
-  (interactive "P")
+  (interactive "P" gnus-topic-mode)
   (gnus-topic-sort-groups 'gnus-group-sort-by-alphabet reverse))
 
 (defun gnus-topic-sort-groups-by-unread (&optional reverse)
   "Sort the current topic by number of unread articles.
 If REVERSE, sort in reverse order."
-  (interactive "P")
+  (interactive "P" gnus-topic-mode)
   (gnus-topic-sort-groups 'gnus-group-sort-by-unread reverse))
 
 (defun gnus-topic-sort-groups-by-level (&optional reverse)
   "Sort the current topic by group level.
 If REVERSE, sort in reverse order."
-  (interactive "P")
+  (interactive "P" gnus-topic-mode)
   (gnus-topic-sort-groups 'gnus-group-sort-by-level reverse))
 
 (defun gnus-topic-sort-groups-by-score (&optional reverse)
   "Sort the current topic by group score.
 If REVERSE, sort in reverse order."
-  (interactive "P")
+  (interactive "P" gnus-topic-mode)
   (gnus-topic-sort-groups 'gnus-group-sort-by-score reverse))
 
 (defun gnus-topic-sort-groups-by-rank (&optional reverse)
   "Sort the current topic by group rank.
 If REVERSE, sort in reverse order."
-  (interactive "P")
+  (interactive "P" gnus-topic-mode)
   (gnus-topic-sort-groups 'gnus-group-sort-by-rank reverse))
 
 (defun gnus-topic-sort-groups-by-method (&optional reverse)
   "Sort the current topic alphabetically by backend name.
 If REVERSE, sort in reverse order."
-  (interactive "P")
+  (interactive "P" gnus-topic-mode)
   (gnus-topic-sort-groups 'gnus-group-sort-by-method reverse))
 
 (defun gnus-topic-sort-groups-by-server (&optional reverse)
   "Sort the current topic alphabetically by server name.
 If REVERSE, sort in reverse order."
-  (interactive "P")
+  (interactive "P" gnus-topic-mode)
   (gnus-topic-sort-groups 'gnus-group-sort-by-server reverse))
 
 (defun gnus-topic-sort-topics-1 (top reverse)
@@ -1708,7 +1721,8 @@ If REVERSE, reverse the sorting order."
    (list (gnus-completing-read "Sort topics in"
                                (mapcar #'car gnus-topic-alist) t
                                (gnus-current-topic))
-        current-prefix-arg))
+        current-prefix-arg)
+   gnus-topic-mode)
   (let ((topic-topology (or (and topic (cdr (gnus-topic-find-topology topic)))
                            gnus-topic-topology)))
     (gnus-topic-sort-topics-1 topic-topology reverse)
@@ -1721,7 +1735,8 @@ If REVERSE, reverse the sorting order."
   (interactive
    (list
     (gnus-group-topic-name)
-    (gnus-completing-read "Move to topic" (mapcar #'car gnus-topic-alist) t)))
+    (gnus-completing-read "Move to topic" (mapcar #'car gnus-topic-alist) t))
+   gnus-topic-mode)
   (unless (and current to)
     (error "Can't find topic"))
   (let ((current-top (cdr (gnus-topic-find-topology current)))
diff --git a/lisp/gnus/gnus-util.el b/lisp/gnus/gnus-util.el
index f80243c..e558f63 100644
--- a/lisp/gnus/gnus-util.el
+++ b/lisp/gnus/gnus-util.el
@@ -1612,8 +1612,8 @@ empty directories from OLD-PATH."
   "Rescale IMAGE to SIZE if possible.
 SIZE is in format (WIDTH . HEIGHT).  Return a new image.
 Sizes are in pixels."
-  (if (not (display-graphic-p))
-      image
+  (when (display-images-p)
+    (declare-function image-size "image.c" (spec &optional pixels frame))
     (let ((new-width (car size))
           (new-height (cdr size)))
       (when (> (cdr (image-size image t)) new-height)
@@ -1621,8 +1621,8 @@ Sizes are in pixels."
                                   :max-height new-height)))
       (when (> (car (image-size image t)) new-width)
        (setq image (create-image (plist-get (cdr image) :data) nil t
-                                  :max-width new-width)))
-      image)))
+                                  :max-width new-width)))))
+  image)
 
 (defun gnus-recursive-directory-files (dir)
   "Return all regular files below DIR.
diff --git a/lisp/gnus/gnus-uu.el b/lisp/gnus/gnus-uu.el
index 32a8785..bd9a1a3 100644
--- a/lisp/gnus/gnus-uu.el
+++ b/lisp/gnus/gnus-uu.el
@@ -355,7 +355,7 @@ didn't work, and overwrite existing files.  Otherwise, ask 
each time."
 
 (defun gnus-uu-decode-uu (&optional n)
   "Uudecodes the current article."
-  (interactive "P")
+  (interactive "P" gnus-article-mode gnus-summary-mode)
   (gnus-uu-decode-with-method #'gnus-uu-uustrip-article n))
 
 (defun gnus-uu-decode-uu-and-save (n dir)
@@ -364,13 +364,14 @@ didn't work, and overwrite existing files.  Otherwise, 
ask each time."
    (list current-prefix-arg
         (file-name-as-directory
          (read-directory-name "Uudecode and save in dir: "
-                         gnus-uu-default-dir
-                         gnus-uu-default-dir t))))
+                              gnus-uu-default-dir
+                              gnus-uu-default-dir t)))
+   gnus-article-mode gnus-summary-mode)
   (gnus-uu-decode-with-method #'gnus-uu-uustrip-article n dir nil nil t))
 
 (defun gnus-uu-decode-unshar (&optional n)
   "Unshars the current article."
-  (interactive "P")
+  (interactive "P" gnus-article-mode gnus-summary-mode)
   (gnus-uu-decode-with-method #'gnus-uu-unshar-article n nil nil 'scan t))
 
 (defun gnus-uu-decode-unshar-and-save (n dir)
@@ -379,8 +380,9 @@ didn't work, and overwrite existing files.  Otherwise, ask 
each time."
    (list current-prefix-arg
         (file-name-as-directory
          (read-directory-name "Unshar and save in dir: "
-                         gnus-uu-default-dir
-                         gnus-uu-default-dir t))))
+                              gnus-uu-default-dir
+                              gnus-uu-default-dir t)))
+   gnus-article-mode gnus-summary-mode)
   (gnus-uu-decode-with-method #'gnus-uu-unshar-article n dir nil 'scan t))
 
 (defun gnus-uu-decode-save (n file)
@@ -391,7 +393,8 @@ didn't work, and overwrite existing files.  Otherwise, ask 
each time."
             (read-directory-name
              "Save articles in dir: " gnus-uu-default-dir gnus-uu-default-dir)
           (read-file-name
-           "Save article in file: " gnus-uu-default-dir gnus-uu-default-dir))))
+           "Save article in file: " gnus-uu-default-dir gnus-uu-default-dir)))
+   gnus-article-mode gnus-summary-mode)
   (setq gnus-uu-saved-article-name file)
   (gnus-uu-decode-with-method #'gnus-uu-save-article n nil t))
 
@@ -401,8 +404,9 @@ didn't work, and overwrite existing files.  Otherwise, ask 
each time."
    (list current-prefix-arg
         (file-name-as-directory
          (read-directory-name "Unbinhex and save in dir: "
-                         gnus-uu-default-dir
-                         gnus-uu-default-dir))))
+                              gnus-uu-default-dir
+                              gnus-uu-default-dir)))
+   gnus-article-mode gnus-summary-mode)
   (gnus-uu-initialize)
   (setq gnus-uu-binhex-article-name
        (make-temp-file (expand-file-name "binhex" gnus-uu-work-dir)))
@@ -414,14 +418,15 @@ didn't work, and overwrite existing files.  Otherwise, 
ask each time."
    (list current-prefix-arg
         (file-name-as-directory
          (read-directory-name "yEnc decode and save in dir: "
-                         gnus-uu-default-dir
-                         gnus-uu-default-dir))))
+                              gnus-uu-default-dir
+                              gnus-uu-default-dir)))
+   gnus-article-mode gnus-summary-mode)
   (setq gnus-uu-yenc-article-name nil)
   (gnus-uu-decode-with-method #'gnus-uu-yenc-article n dir nil t))
 
 (defun gnus-uu-decode-uu-view (&optional n)
   "Uudecodes and views the current article."
-  (interactive "P")
+  (interactive "P" gnus-article-mode gnus-summary-mode)
   (let ((gnus-view-pseudos (or gnus-view-pseudos 'automatic)))
     (gnus-uu-decode-uu n)))
 
@@ -431,13 +436,14 @@ didn't work, and overwrite existing files.  Otherwise, 
ask each time."
    (list current-prefix-arg
         (read-file-name "Uudecode, view and save in dir: "
                         gnus-uu-default-dir
-                        gnus-uu-default-dir t)))
+                        gnus-uu-default-dir t))
+   gnus-article-mode gnus-summary-mode)
   (let ((gnus-view-pseudos (or gnus-view-pseudos 'automatic)))
     (gnus-uu-decode-uu-and-save n dir)))
 
 (defun gnus-uu-decode-unshar-view (&optional n)
   "Unshars and views the current article."
-  (interactive "P")
+  (interactive "P" gnus-article-mode gnus-summary-mode)
   (let ((gnus-view-pseudos (or gnus-view-pseudos 'automatic)))
     (gnus-uu-decode-unshar n)))
 
@@ -447,7 +453,8 @@ didn't work, and overwrite existing files.  Otherwise, ask 
each time."
    (list current-prefix-arg
         (read-file-name "Unshar, view and save in dir: "
                         gnus-uu-default-dir
-                        gnus-uu-default-dir t)))
+                        gnus-uu-default-dir t))
+   gnus-article-mode gnus-summary-mode)
   (let ((gnus-view-pseudos (or gnus-view-pseudos 'automatic)))
     (gnus-uu-decode-unshar-and-save n dir)))
 
@@ -459,7 +466,8 @@ didn't work, and overwrite existing files.  Otherwise, ask 
each time."
             (read-directory-name "Save articles in dir: "
                                  gnus-uu-default-dir gnus-uu-default-dir)
           (read-file-name "Save articles in file: "
-                          gnus-uu-default-dir gnus-uu-default-dir))))
+                          gnus-uu-default-dir gnus-uu-default-dir)))
+   gnus-article-mode gnus-summary-mode)
   (let ((gnus-view-pseudos (or gnus-view-pseudos 'automatic)))
     (gnus-uu-decode-save n file)))
 
@@ -468,7 +476,8 @@ didn't work, and overwrite existing files.  Otherwise, ask 
each time."
   (interactive
    (list current-prefix-arg
         (read-file-name "Unbinhex, view and save in dir: "
-                        gnus-uu-default-dir gnus-uu-default-dir)))
+                        gnus-uu-default-dir gnus-uu-default-dir))
+   gnus-article-mode gnus-summary-mode)
   (gnus-uu-initialize)
   (setq gnus-uu-binhex-article-name
        (make-temp-file (expand-file-name "binhex" gnus-uu-work-dir)))
@@ -480,7 +489,7 @@ didn't work, and overwrite existing files.  Otherwise, ask 
each time."
 
 (defun gnus-uu-digest-mail-forward (&optional n post)
   "Digests and forwards all articles in this series."
-  (interactive "P")
+  (interactive "P" gnus-article-mode gnus-summary-mode)
   (gnus-uu-initialize)
   (let ((gnus-uu-save-in-digest t)
        (file (make-temp-file (nnheader-concat gnus-uu-work-dir "forward")))
@@ -546,7 +555,7 @@ didn't work, and overwrite existing files.  Otherwise, ask 
each time."
 
 (defun gnus-uu-digest-post-forward (&optional n)
   "Digest and forward to a newsgroup."
-  (interactive "P")
+  (interactive "P" gnus-article-mode gnus-summary-mode)
   (gnus-uu-digest-mail-forward n t))
 
 ;; Process marking.
@@ -576,7 +585,7 @@ didn't work, and overwrite existing files.  Otherwise, ask 
each time."
   "Set the process mark on articles whose subjects match REGEXP.
 When called interactively, prompt for REGEXP.
 Optional UNMARK non-nil means unmark instead of mark."
-  (interactive "sMark (regexp): \nP")
+  (interactive "sMark (regexp): \nP" gnus-article-mode gnus-summary-mode)
   (save-excursion
     (let* ((articles (gnus-uu-find-articles-matching regexp))
           (new-marked (gnus-new-processable unmark articles)))
@@ -590,12 +599,12 @@ Optional UNMARK non-nil means unmark instead of mark."
 (defun gnus-uu-unmark-by-regexp (regexp)
   "Remove the process mark from articles whose subjects match REGEXP.
 When called interactively, prompt for REGEXP."
-  (interactive "sUnmark (regexp): ")
+  (interactive "sUnmark (regexp): " gnus-article-mode gnus-summary-mode)
   (gnus-uu-mark-by-regexp regexp t))
 
 (defun gnus-uu-mark-series (&optional silent)
   "Mark the current series with the process mark."
-  (interactive)
+  (interactive nil gnus-article-mode gnus-summary-mode)
   (let* ((articles (gnus-uu-find-articles-matching))
         (l (length articles)))
     (while articles
@@ -608,7 +617,7 @@ When called interactively, prompt for REGEXP."
 
 (defun gnus-uu-mark-region (beg end &optional unmark)
   "Set the process mark on all articles between point and mark."
-  (interactive "r")
+  (interactive "r" gnus-article-mode gnus-summary-mode)
   (save-excursion
     (goto-char beg)
     (while (< (point) end)
@@ -620,22 +629,22 @@ When called interactively, prompt for REGEXP."
 
 (defun gnus-uu-unmark-region (beg end)
   "Remove the process mark from all articles between point and mark."
-  (interactive "r")
+  (interactive "r" gnus-article-mode gnus-summary-mode)
   (gnus-uu-mark-region beg end t))
 
 (defun gnus-uu-mark-buffer ()
   "Set the process mark on all articles in the buffer."
-  (interactive)
+  (interactive nil gnus-article-mode gnus-summary-mode)
   (gnus-uu-mark-region (point-min) (point-max)))
 
 (defun gnus-uu-unmark-buffer ()
   "Remove the process mark on all articles in the buffer."
-  (interactive)
+  (interactive nil gnus-article-mode gnus-summary-mode)
   (gnus-uu-mark-region (point-min) (point-max) t))
 
 (defun gnus-uu-mark-thread ()
   "Marks all articles downwards in this thread."
-  (interactive)
+  (interactive nil gnus-article-mode gnus-summary-mode)
   (gnus-save-hidden-threads
     (let ((level (gnus-summary-thread-level)))
       (while (and (gnus-summary-set-process-mark (gnus-summary-article-number))
@@ -646,7 +655,7 @@ When called interactively, prompt for REGEXP."
 
 (defun gnus-uu-unmark-thread ()
   "Unmarks all articles downwards in this thread."
-  (interactive)
+  (interactive nil gnus-article-mode gnus-summary-mode)
   (let ((level (gnus-summary-thread-level)))
     (while (and (gnus-summary-remove-process-mark
                 (gnus-summary-article-number))
@@ -656,7 +665,7 @@ When called interactively, prompt for REGEXP."
 
 (defun gnus-uu-invert-processable ()
   "Invert the list of process-marked articles."
-  (interactive)
+  (interactive nil gnus-article-mode gnus-summary-mode)
   (let ((data gnus-newsgroup-data)
        number)
     (save-excursion
@@ -669,7 +678,7 @@ When called interactively, prompt for REGEXP."
 
 (defun gnus-uu-mark-over (&optional score)
   "Mark all articles with a score over SCORE (the prefix)."
-  (interactive "P")
+  (interactive "P" gnus-article-mode gnus-summary-mode)
   (let ((score (or score gnus-summary-default-score 0))
        (data gnus-newsgroup-data))
     (save-excursion
@@ -684,7 +693,7 @@ When called interactively, prompt for REGEXP."
 
 (defun gnus-uu-mark-sparse ()
   "Mark all series that have some articles marked."
-  (interactive)
+  (interactive nil gnus-article-mode gnus-summary-mode)
   (let ((marked (nreverse gnus-newsgroup-processable))
        subject articles total headers)
     (unless marked
@@ -708,7 +717,7 @@ When called interactively, prompt for REGEXP."
 
 (defun gnus-uu-mark-all ()
   "Mark all articles in \"series\" order."
-  (interactive)
+  (interactive nil gnus-article-mode gnus-summary-mode)
   (setq gnus-newsgroup-processable nil)
   (save-excursion
     (let ((data gnus-newsgroup-data)
@@ -728,33 +737,33 @@ When called interactively, prompt for REGEXP."
 
 (defun gnus-uu-decode-postscript (&optional n)
   "Gets PostScript of the current article."
-  (interactive "P")
+  (interactive "P" gnus-article-mode gnus-summary-mode)
   (gnus-uu-decode-with-method #'gnus-uu-decode-postscript-article n))
 
 (defun gnus-uu-decode-postscript-view (&optional n)
   "Gets and views the current article."
-  (interactive "P")
+  (interactive "P" gnus-article-mode gnus-summary-mode)
   (let ((gnus-view-pseudos (or gnus-view-pseudos 'automatic)))
     (gnus-uu-decode-postscript n)))
 
 (defun gnus-uu-decode-postscript-and-save (n dir)
   "Extracts PostScript and saves the current article."
-  (interactive
-   (list current-prefix-arg
-        (file-name-as-directory
-         (read-directory-name "Save in dir: "
-                         gnus-uu-default-dir
-                         gnus-uu-default-dir t))))
+  (interactive (list current-prefix-arg
+                    (file-name-as-directory
+                     (read-directory-name "Save in dir: "
+                                          gnus-uu-default-dir
+                                          gnus-uu-default-dir t)))
+              gnus-article-mode gnus-summary-mode)
   (gnus-uu-decode-with-method #'gnus-uu-decode-postscript-article
                              n dir nil nil t))
 
 (defun gnus-uu-decode-postscript-and-save-view (n dir)
   "Decodes, views and saves the resulting file."
-  (interactive
-   (list current-prefix-arg
-        (read-file-name "Where do you want to save the file(s)? "
-                        gnus-uu-default-dir
-                        gnus-uu-default-dir t)))
+  (interactive (list current-prefix-arg
+                    (read-file-name "Where do you want to save the file(s)? "
+                                    gnus-uu-default-dir
+                                    gnus-uu-default-dir t))
+              gnus-article-mode gnus-summary-mode)
   (let ((gnus-view-pseudos (or gnus-view-pseudos 'automatic)))
     (gnus-uu-decode-postscript-and-save n dir)))
 
diff --git a/lisp/gnus/gnus-vm.el b/lisp/gnus/gnus-vm.el
index b7e6b2a..ec36011 100644
--- a/lisp/gnus/gnus-vm.el
+++ b/lisp/gnus/gnus-vm.el
@@ -72,7 +72,7 @@ If N is a positive number, save the N next articles.
 If N is a negative number, save the N previous articles.
 If N is nil and any articles have been marked with the process mark,
 save those articles instead."
-  (interactive "P")
+  (interactive "P" gnus-article-mode gnus-summary-mode)
   (require 'gnus-art)
   (let ((gnus-default-article-saver 'gnus-summary-save-in-vm))
     (gnus-summary-save-article arg)))
@@ -80,7 +80,7 @@ save those articles instead."
 (declare-function vm-save-message "ext:vm-save" (folder &optional count))
 
 (defun gnus-summary-save-in-vm (&optional folder)
-  (interactive)
+  (interactive nil gnus-article-mode gnus-summary-mode)
   (require 'vm)
   (setq folder
        (gnus-read-save-file-name
diff --git a/lisp/gnus/gnus.el b/lisp/gnus/gnus.el
index 7b94c64..2f2b206 100644
--- a/lisp/gnus/gnus.el
+++ b/lisp/gnus/gnus.el
@@ -1138,7 +1138,7 @@ no need to set this variable."
   :group 'gnus-message
   :type '(choice (const :tag "default" nil)
                 string))
-(make-obsolete-variable 'gnus-local-domain nil "Emacs 24.1")
+(make-obsolete-variable 'gnus-local-domain nil "24.1")
 
 ;; Customization variables
 
@@ -2310,7 +2310,7 @@ automatically cache the article in the agent cache."
 ;; The carpal mode has been removed, but define the variable for
 ;; backwards compatibility.
 (defvar gnus-carpal nil)
-(make-obsolete-variable 'gnus-carpal nil "Emacs 24.1")
+(make-obsolete-variable 'gnus-carpal nil "24.1")
 
 (defvar gnus-agent-fetching nil
   "Whether Gnus agent is in fetching mode.")
@@ -2513,7 +2513,7 @@ are always t.")
    '(("info" :interactive t Info-goto-node)
      ("qp" quoted-printable-decode-region quoted-printable-decode-string)
      ("ps-print" ps-print-preprint)
-     ("message" :interactive t
+     ("message" :interactive (message-mode)
       message-send-and-exit message-yank-original)
      ("babel" babel-as-string)
      ("nnmail" nnmail-split-fancy nnmail-article-group)
@@ -2530,7 +2530,7 @@ are always t.")
      ("score-mode" :interactive t gnus-score-mode)
      ("gnus-mh" gnus-summary-save-article-folder
       gnus-Folder-save-name gnus-folder-save-name)
-     ("gnus-mh" :interactive t gnus-summary-save-in-folder)
+     ("gnus-mh" :interactive (gnus-summary-mode) gnus-summary-save-in-folder)
      ("gnus-demon" gnus-demon-add-scanmail
       gnus-demon-add-rescan gnus-demon-add-scan-timestamps
       gnus-demon-add-disconnection gnus-demon-add-handler
@@ -2545,7 +2545,7 @@ are always t.")
      ("gnus-srvr" gnus-enter-server-buffer gnus-server-set-info
       gnus-server-server-name)
      ("gnus-srvr" gnus-browse-foreign-server)
-     ("gnus-cite" :interactive t
+     ("gnus-cite" :interactive (gnus-article-mode gnus-summary-mode)
       gnus-article-highlight-citation gnus-article-hide-citation-maybe
       gnus-article-hide-citation gnus-article-fill-cited-article
       gnus-article-hide-citation-in-followups
@@ -2561,29 +2561,34 @@ are always t.")
       gnus-cache-enter-remove-article gnus-cached-article-p
       gnus-cache-open gnus-cache-close gnus-cache-update-article
       gnus-cache-articles-in-group)
-     ("gnus-cache" :interactive t gnus-jog-cache gnus-cache-enter-article
+     ("gnus-cache" :interactive (gnus-summary-mode)
+      gnus-summary-insert-cached-articles gnus-cache-enter-article
       gnus-cache-remove-article gnus-summary-insert-cached-articles)
+     ("gnus-cache" :interactive t gnus-jog-cache)
      ("gnus-score" :interactive t
+      gnus-score-flush-cache gnus-score-close)
+     ("gnus-score" :interactive (gnus-summary-mode)
       gnus-summary-increase-score gnus-summary-set-score
       gnus-summary-raise-thread gnus-summary-raise-same-subject
       gnus-summary-raise-score gnus-summary-raise-same-subject-and-select
       gnus-summary-lower-thread gnus-summary-lower-same-subject
       gnus-summary-lower-score gnus-summary-lower-same-subject-and-select
       gnus-summary-current-score gnus-score-delta-default
-      gnus-score-flush-cache gnus-score-close
       gnus-possibly-score-headers gnus-score-followup-article
       gnus-score-followup-thread)
      ("gnus-score"
       (gnus-summary-score-map keymap) gnus-score-save gnus-score-headers
       gnus-current-score-file-nondirectory gnus-score-adaptive
       gnus-score-find-trace gnus-score-file-name)
-     ("gnus-cus" :interactive t gnus-group-customize gnus-score-customize)
-     ("gnus-topic" :interactive t gnus-topic-mode)
+     ("gnus-cus" :interactive (gnus-group-mode) gnus-group-customize)
+     ("gnus-cus" :interactive (gnus-summary-mode) gnus-score-customize)
+     ("gnus-topic" :interactive (gnus-group-mode) gnus-topic-mode)
      ("gnus-topic" gnus-topic-remove-group gnus-topic-set-parameters
       gnus-subscribe-topics)
-     ("gnus-salt" :interactive t gnus-pick-mode gnus-binary-mode)
+     ("gnus-salt" :interactive (gnus-summary-mode)
+      gnus-pick-mode gnus-binary-mode)
      ("gnus-uu" (gnus-uu-extract-map keymap) (gnus-uu-mark-map keymap))
-     ("gnus-uu" :interactive t
+     ("gnus-uu" :interactive (gnus-article-mode gnus-summary-mode)
       gnus-uu-digest-mail-forward gnus-uu-digest-post-forward
       gnus-uu-mark-series gnus-uu-mark-region gnus-uu-mark-buffer
       gnus-uu-mark-by-regexp gnus-uu-mark-all
@@ -2598,12 +2603,13 @@ are always t.")
      ("gnus-uu" gnus-uu-delete-work-dir gnus-uu-unmark-thread)
      ("gnus-msg" (gnus-summary-send-map keymap)
       gnus-article-mail gnus-copy-article-buffer gnus-extended-version)
-     ("gnus-msg" :interactive t
-      gnus-group-post-news gnus-group-mail gnus-group-news
+     ("gnus-msg" :interactive (gnus-group-mode)
+      gnus-group-post-news gnus-group-mail gnus-group-news)
+     ("gnus-msg" :interactive (gnus-summary-mode)
       gnus-summary-post-news gnus-summary-news-other-window
       gnus-summary-followup gnus-summary-followup-with-original
       gnus-summary-cancel-article gnus-summary-supersede-article
-      gnus-post-news gnus-summary-reply gnus-summary-reply-with-original
+      gnus-summary-reply gnus-summary-reply-with-original
       gnus-summary-mail-forward gnus-summary-mail-other-window
       gnus-summary-resend-message gnus-summary-resend-bounced-mail
       gnus-summary-wide-reply gnus-summary-followup-to-mail
@@ -2611,7 +2617,9 @@ are always t.")
       gnus-summary-wide-reply-with-original
       gnus-summary-post-forward gnus-summary-wide-reply-with-original
       gnus-summary-post-forward)
-     ("gnus-picon" :interactive t gnus-treat-from-picon)
+     ("gnus-msg" gnus-post-news)
+     ("gnus-picon" :interactive (gnus-article-mode gnus-summary-mode)
+      gnus-treat-from-picon)
      ("smiley" :interactive t smiley-region)
      ("gnus-win" gnus-configure-windows gnus-add-configuration)
      ("gnus-sum" gnus-summary-insert-line gnus-summary-read-group
@@ -2634,7 +2642,7 @@ are always t.")
       gnus-request-article-this-buffer gnus-article-mode
       gnus-article-setup-buffer gnus-narrow-to-page
       gnus-article-delete-invisible-text gnus-treat-article)
-     ("gnus-art" :interactive t
+     ("gnus-art" :interactive (gnus-summary-mode gnus-article-mode)
       gnus-article-hide-headers gnus-article-hide-boring-headers
       gnus-article-treat-overstrike
       gnus-article-remove-cr gnus-article-remove-trailing-blank-lines
@@ -2646,7 +2654,6 @@ are always t.")
       gnus-article-hide-pem gnus-article-hide-signature
       gnus-article-strip-leading-blank-lines gnus-article-date-local
       gnus-article-date-original gnus-article-date-lapsed
-      ;;gnus-article-show-all-headers
       gnus-article-edit-mode gnus-article-edit-article
       gnus-article-edit-done gnus-article-decode-encoded-words
       gnus-start-date-timer gnus-stop-date-timer
@@ -2671,12 +2678,13 @@ are always t.")
       gnus-agent-store-article gnus-agent-group-covered-p)
      ("gnus-agent" :interactive t
       gnus-unplugged gnus-agentize gnus-agent-batch)
-     ("gnus-vm" :interactive t gnus-summary-save-in-vm
+     ("gnus-vm" :interactive (gnus-summary-mode) gnus-summary-save-in-vm
       gnus-summary-save-article-vm)
      ("compface" uncompface)
-     ("gnus-draft" :interactive t gnus-draft-mode gnus-group-send-queue)
+     ("gnus-draft" :interactive (gnus-summary-mode) gnus-draft-mode)
+     ("gnus-draft" :interactive t gnus-group-send-queue)
      ("gnus-mlspl" gnus-group-split gnus-group-split-fancy)
-     ("gnus-mlspl" :interactive t gnus-group-split-setup
+     ("gnus-mlspl" :interactive (gnus-group-mode) gnus-group-split-setup
       gnus-group-split-update)
      ("gnus-delay" gnus-delay-initialize))))
 
diff --git a/lisp/gnus/message.el b/lisp/gnus/message.el
index 5a5dbce..fad4ef3 100644
--- a/lisp/gnus/message.el
+++ b/lisp/gnus/message.el
@@ -382,7 +382,7 @@ Archives \(such as groups.google.com) respect this header."
   :group 'message-various)
 
 (defcustom message-archive-note
-  "X-No-Archive: Yes - save http://groups.google.com/";
+  "X-No-Archive: Yes - save https://groups.google.com/";
   "Note to insert why you wouldn't want this posting archived.
 If nil, don't insert any text in the body."
   :version "22.1"
@@ -2334,7 +2334,8 @@ Leading \"Re: \" is not stripped by this function.  Use 
the function
   "Ask for NEW-SUBJECT header, append (was: <Old Subject>)."
   (interactive
    (list
-    (read-from-minibuffer "New subject: ")))
+    (read-from-minibuffer "New subject: "))
+   message-mode)
   (cond ((and (not (or (null new-subject) ; new subject not empty
                       (zerop (string-width new-subject))
                       (string-match "^[ \t]*$" new-subject))))
@@ -2364,7 +2365,7 @@ Leading \"Re: \" is not stripped by this function.  Use 
the function
   "Mark some region in the current article with enclosing tags.
 See `message-mark-insert-begin' and `message-mark-insert-end'.
 If VERBATIM, use slrn style verbatim marks (\"#v+\" and \"#v-\")."
-  (interactive "r\nP")
+  (interactive "r\nP" message-mode)
   (save-excursion
     ;; add to the end of the region first, otherwise end would be invalid
     (goto-char end)
@@ -2376,7 +2377,7 @@ If VERBATIM, use slrn style verbatim marks (\"#v+\" and 
\"#v-\")."
   "Insert FILE at point, marking it with enclosing tags.
 See `message-mark-insert-begin' and `message-mark-insert-end'.
 If VERBATIM, use slrn style verbatim marks (\"#v+\" and \"#v-\")."
-  (interactive "fFile to insert: \nP")
+  (interactive "fFile to insert: \nP" message-mode)
     ;; reverse insertion to get correct result.
   (let ((p (point)))
     (insert (if verbatim "#v-\n" message-mark-insert-end))
@@ -2390,7 +2391,7 @@ If VERBATIM, use slrn style verbatim marks (\"#v+\" and 
\"#v-\")."
 The note can be customized using `message-archive-note'.  When called with a
 prefix argument, ask for a text to insert.  If you don't want the note in the
 body, set  `message-archive-note' to nil."
-  (interactive)
+  (interactive nil message-mode)
   (if current-prefix-arg
       (setq message-archive-note
            (read-from-minibuffer "Reason for No-Archive: "
@@ -2416,7 +2417,8 @@ With prefix-argument just set Follow-Up, don't 
cross-post."
                          gnus-newsrc-alist)
                      nil nil '("poster" . 0)
                      (if (boundp 'gnus-group-history)
-                         'gnus-group-history)))))
+                         'gnus-group-history))))
+   message-mode)
   (message-remove-header "Follow[Uu]p-[Tt]o" t)
   (message-goto-newsgroups)
   (beginning-of-line)
@@ -2493,7 +2495,8 @@ With prefix-argument just set Follow-Up, don't 
cross-post."
                          gnus-newsrc-alist)
                      nil nil '("poster" . 0)
                      (if (boundp 'gnus-group-history)
-                         'gnus-group-history)))))
+                         'gnus-group-history))))
+   message-mode)
   (when (fboundp 'gnus-group-real-name)
     (setq target-group (gnus-group-real-name target-group)))
   (cond ((not (or (null target-group) ; new subject not empty
@@ -2528,7 +2531,7 @@ With prefix-argument just set Follow-Up, don't 
cross-post."
 
 (defun message-reduce-to-to-cc ()
  "Replace contents of To: header with contents of Cc: or Bcc: header."
- (interactive)
+ (interactive nil message-mode)
  (let ((cc-content
        (save-restriction (message-narrow-to-headers)
                          (message-fetch-field "cc")))
@@ -2694,7 +2697,7 @@ Point is left at the beginning of the narrowed-to region."
 
 (defun message-sort-headers ()
   "Sort headers of the current message according to 
`message-header-format-alist'."
-  (interactive)
+  (interactive nil message-mode)
   (save-excursion
     (save-restriction
       (let ((max (1+ (length message-header-format-alist)))
@@ -2715,7 +2718,7 @@ Point is left at the beginning of the narrowed-to region."
 
 (defun message-kill-address ()
   "Kill the address under point."
-  (interactive)
+  (interactive nil message-mode)
   (let ((start (point)))
     (message-skip-to-next-address)
     (kill-region start (if (bolp) (1- (point)) (point)))))
@@ -3208,79 +3211,79 @@ Like `text-mode', but with these additional commands:
 
 (defun message-goto-to ()
   "Move point to the To header."
-  (interactive)
+  (interactive nil message-mode)
   (push-mark)
   (message-position-on-field "To"))
 
 (defun message-goto-from ()
   "Move point to the From header."
-  (interactive)
+  (interactive nil message-mode)
   (push-mark)
   (message-position-on-field "From"))
 
 (defun message-goto-subject ()
   "Move point to the Subject header."
-  (interactive)
+  (interactive nil message-mode)
   (push-mark)
   (message-position-on-field "Subject"))
 
 (defun message-goto-cc ()
   "Move point to the Cc header."
-  (interactive)
+  (interactive nil message-mode)
   (push-mark)
   (message-position-on-field "Cc" "To"))
 
 (defun message-goto-bcc ()
   "Move point to the Bcc  header."
-  (interactive)
+  (interactive nil message-mode)
   (push-mark)
   (message-position-on-field "Bcc" "Cc" "To"))
 
 (defun message-goto-fcc ()
   "Move point to the Fcc header."
-  (interactive)
+  (interactive nil message-mode)
   (push-mark)
   (message-position-on-field "Fcc" "To" "Newsgroups"))
 
 (defun message-goto-reply-to ()
   "Move point to the Reply-To header."
-  (interactive)
+  (interactive nil message-mode)
   (push-mark)
   (message-position-on-field "Reply-To" "Subject"))
 
 (defun message-goto-newsgroups ()
   "Move point to the Newsgroups header."
-  (interactive)
+  (interactive nil message-mode)
   (push-mark)
   (message-position-on-field "Newsgroups"))
 
 (defun message-goto-distribution ()
   "Move point to the Distribution header."
-  (interactive)
+  (interactive nil message-mode)
   (push-mark)
   (message-position-on-field "Distribution"))
 
 (defun message-goto-followup-to ()
   "Move point to the Followup-To header."
-  (interactive)
+  (interactive nil message-mode)
   (push-mark)
   (message-position-on-field "Followup-To" "Newsgroups"))
 
 (defun message-goto-mail-followup-to ()
   "Move point to the Mail-Followup-To header."
-  (interactive)
+  (interactive nil message-mode)
   (push-mark)
   (message-position-on-field "Mail-Followup-To" "To"))
 
 (defun message-goto-keywords ()
   "Move point to the Keywords header."
-  (interactive)
+  (interactive nil message-mode)
   (push-mark)
   (message-position-on-field "Keywords" "Subject"))
 
 (defun message-goto-summary ()
   "Move point to the Summary header."
-  (interactive)
+  (interactive nil message-mode)
   (push-mark)
   (message-position-on-field "Summary" "Subject"))
 
@@ -3288,7 +3291,7 @@ Like `text-mode', but with these additional commands:
 (defun message-goto-body (&optional interactive)
   "Move point to the beginning of the message body.
 Returns point."
-  (interactive "p")
+  (interactive "p" message-mode)
   (when interactive
     (when (looking-at "[ \t]*\n")
     (expand-abbrev))
@@ -3315,7 +3318,7 @@ Returns point."
 
 (defun message-goto-eoh (&optional interactive)
   "Move point to the end of the headers."
-  (interactive "p")
+  (interactive "p" message-mode)
   (message-goto-body interactive)
   (forward-line -1))
 
@@ -3323,7 +3326,7 @@ Returns point."
   "Move point to the beginning of the message signature.
 If there is no signature in the article, go to the end and
 return nil."
-  (interactive)
+  (interactive nil message-mode)
   (push-mark)
   (goto-char (point-min))
   (if (re-search-forward message-signature-separator nil t)
@@ -3342,7 +3345,7 @@ in the current mail buffer, and appends the current 
`user-mail-address'.
 If the optional argument INCLUDE-CC is non-nil, the addresses in the
 Cc: header are also put into the MFT."
 
-  (interactive "P")
+  (interactive "P" message-mode)
   (let* (cc tos)
     (save-restriction
       (message-narrow-to-headers)
@@ -3360,7 +3363,7 @@ Cc: header are also put into the MFT."
   "Insert a To header that points to the author of the article being replied 
to.
 If the original author requested not to be sent mail, don't insert unless the
 prefix FORCE is given."
-  (interactive "P")
+  (interactive "P" message-mode)
   (let* ((mct (message-fetch-reply-field "mail-copies-to"))
         (dont (and mct (or (equal (downcase mct) "never")
                            (equal (downcase mct) "nobody"))))
@@ -3379,7 +3382,7 @@ prefix FORCE is given."
 
 (defun message-insert-wide-reply ()
   "Insert To and Cc headers as if you were doing a wide reply."
-  (interactive)
+  (interactive nil message-mode)
   (let ((headers (message-with-reply-buffer
                   (message-get-reply-headers t))))
     (message-carefully-insert-headers headers)))
@@ -3424,7 +3427,7 @@ or in the synonym headers, defined by 
`message-header-synonyms'."
 
 (defun message-widen-reply ()
   "Widen the reply to include maximum recipients."
-  (interactive)
+  (interactive nil message-mode)
   (let ((follow-to
          (and (buffer-live-p message-reply-buffer)
              (with-current-buffer message-reply-buffer
@@ -3440,7 +3443,7 @@ or in the synonym headers, defined by 
`message-header-synonyms'."
 
 (defun message-insert-newsgroups ()
   "Insert the Newsgroups header from the article being replied to."
-  (interactive)
+  (interactive nil message-mode)
   (let ((old-newsgroups (mail-fetch-field "newsgroups"))
        (new-newsgroups (message-fetch-reply-field "newsgroups"))
        (first t)
@@ -3475,13 +3478,13 @@ or in the synonym headers, defined by 
`message-header-synonyms'."
 
 (defun message-widen-and-recenter ()
   "Widen the buffer and go to the start."
-  (interactive)
+  (interactive nil message-mode)
   (widen)
   (goto-char (point-min)))
 
 (defun message-delete-not-region (beg end)
   "Delete everything in the body of the current message outside of the region."
-  (interactive "r")
+  (interactive "r" message-mode)
   (let (citeprefix)
     (save-excursion
       (goto-char beg)
@@ -3508,7 +3511,7 @@ or in the synonym headers, defined by 
`message-header-synonyms'."
   "Kill all text up to the signature.
 If a numeric argument or prefix arg is given, leave that number
 of lines before the signature intact."
-  (interactive "P")
+  (interactive "P" message-mode)
   (save-excursion
     (save-restriction
       (let ((point (point)))
@@ -3526,7 +3529,7 @@ of lines before the signature intact."
 (defun message-newline-and-reformat (&optional arg not-break)
   "Insert four newlines, and then reformat if inside quoted text.
 Prefix arg means justify as well."
-  (interactive (list (if current-prefix-arg 'full)))
+  (interactive (list (if current-prefix-arg 'full)) message-mode)
   (unless (message-in-body-p)
     (error "This command only works in the body of the message"))
   (let (quoted point beg end leading-space bolp fill-paragraph-function)
@@ -3617,7 +3620,7 @@ Prefix arg means justify as well."
   "Message specific function to fill a paragraph.
 This function is used as the value of `fill-paragraph-function' in
 Message buffers and is not meant to be called directly."
-  (interactive (list (if current-prefix-arg 'full)))
+  (interactive (list (if current-prefix-arg 'full)) message-mode)
   (if (message-point-in-header-p)
       (message-fill-field)
     (message-newline-and-reformat arg t))
@@ -3648,7 +3651,7 @@ more information.
 If FORCE is 0 (or when called interactively), the global values
 of the signature variables will be consulted if the local ones
 are null."
-  (interactive (list 0))
+  (interactive (list 0) message-mode)
   (let ((message-signature message-signature)
        (message-signature-file message-signature-file))
     ;; If called interactively and there's no signature to insert,
@@ -3707,7 +3710,7 @@ are null."
 
 (defun message-insert-importance-high ()
   "Insert header to mark message as important."
-  (interactive)
+  (interactive nil message-mode)
   (save-excursion
     (save-restriction
       (message-narrow-to-headers)
@@ -3717,7 +3720,7 @@ are null."
 
 (defun message-insert-importance-low ()
   "Insert header to mark message as unimportant."
-  (interactive)
+  (interactive nil message-mode)
   (save-excursion
     (save-restriction
       (message-narrow-to-headers)
@@ -3729,7 +3732,7 @@ are null."
   "Insert a \"Importance: high\" header, or cycle through the header values.
 The three allowed values according to RFC 1327 are `high', `normal'
 and `low'."
-  (interactive)
+  (interactive nil message-mode)
   (save-excursion
     (let ((new "high")
          cur)
@@ -3749,7 +3752,7 @@ and `low'."
 (defun message-insert-disposition-notification-to ()
   "Request a disposition notification (return receipt) to this message.
 Note that this should not be used in newsgroups."
-  (interactive)
+  (interactive nil message-mode)
   (save-excursion
     (save-restriction
       (message-narrow-to-headers)
@@ -3764,7 +3767,7 @@ Note that this should not be used in newsgroups."
   "Elide the text in the region.
 An ellipsis (from `message-elide-ellipsis') will be inserted where the
 text was killed."
-  (interactive "r")
+  (interactive "r" message-mode)
   (let ((lines (count-lines b e))
         (chars (- e b)))
     (kill-region b e)
@@ -3781,7 +3784,8 @@ text was killed."
     (min (point) (or (mark t) (point)))
     (max (point) (or (mark t) (point)))
     (when current-prefix-arg
-      (prefix-numeric-value current-prefix-arg))))
+      (prefix-numeric-value current-prefix-arg)))
+   message-mode)
 
   (setq n (if (numberp n) (mod n 26) 13)) ;canonize N
   (unless (or (zerop n)                        ; no action needed for a rot of 0
@@ -3815,7 +3819,8 @@ With prefix arg, specifies the number of places to rotate 
each letter forward.
 Mail and USENET news headers are not rotated unless WIDE is non-nil."
   (interactive (if current-prefix-arg
                   (list (prefix-numeric-value current-prefix-arg))
-                (list nil)))
+                (list nil))
+              message-mode)
   (save-excursion
     (save-restriction
       (when (and (not wide) (message-goto-body))
@@ -3835,7 +3840,7 @@ Mail and USENET news headers are not rotated unless WIDE 
is non-nil."
   "Rename the *message* buffer to \"*message* RECIPIENT\".
 If the function is run with a prefix, it will ask for a new buffer
 name, rather than giving an automatic name."
-  (interactive "Pbuffer name: ")
+  (interactive "Pbuffer name: " message-mode)
   (save-excursion
     (save-restriction
       (goto-char (point-min))
@@ -3858,7 +3863,7 @@ name, rather than giving an automatic name."
 (defun message-fill-yanked-message (&optional justifyp)
   "Fill the paragraphs of a message yanked into this one.
 Numeric argument means justify as well."
-  (interactive "P")
+  (interactive "P" message-mode)
   (save-excursion
     (goto-char (point-min))
     (search-forward (concat "\n" mail-header-separator "\n") nil t)
@@ -3923,7 +3928,7 @@ If REMOVE is non-nil, remove newlines, too.
 
 To use this automatically, you may add this function to
 `gnus-message-setup-hook'."
-  (interactive "P")
+  (interactive "P" message-mode)
   (let ((citexp (concat "^\\("
                        (concat message-yank-cited-prefix "\\|")
                        message-yank-prefix
@@ -3988,7 +3993,7 @@ This function uses `message-cite-function' to do the 
actual citing.
 
 Just \\[universal-argument] as argument means don't indent, insert no
 prefix, and don't delete any headers."
-  (interactive "P")
+  (interactive "P" message-mode)
   ;; eval the let forms contained in message-cite-style
   (let ((bindings (if (symbolp message-cite-style)
                      (symbol-value message-cite-style)
@@ -3999,7 +4004,7 @@ prefix, and don't delete any headers."
 
 (defun message-yank-buffer (buffer)
   "Insert BUFFER into the current buffer and quote it."
-  (interactive "bYank buffer: ")
+  (interactive "bYank buffer: " message-mode)
   (let ((message-reply-buffer (get-buffer buffer)))
     (save-window-excursion
       (message-yank-original))))
@@ -4226,7 +4231,7 @@ This function strips off the signature from the original 
message."
   "Send message like `message-send', then, if no errors, exit from mail buffer.
 The usage of ARG is defined by the instance that called Message.
 It should typically alter the sending method in some way or other."
-  (interactive "P")
+  (interactive "P" message-mode)
   (let ((buf (current-buffer))
        (position (point-marker))
        (actions message-exit-actions))
@@ -4246,7 +4251,7 @@ It should typically alter the sending method in some way 
or other."
 (defun message-dont-send ()
   "Don't send the message you have been editing.
 Instead, just auto-save the buffer and then bury it."
-  (interactive)
+  (interactive nil message-mode)
   (set-buffer-modified-p t)
   (save-buffer)
   (let ((actions message-postpone-actions))
@@ -4255,7 +4260,7 @@ Instead, just auto-save the buffer and then bury it."
 
 (defun message-kill-buffer ()
   "Kill the current buffer."
-  (interactive)
+  (interactive nil message-mode)
   (when (or (not (buffer-modified-p))
            (not message-kill-buffer-query)
            (yes-or-no-p "Message modified; kill anyway? "))
@@ -4304,7 +4309,7 @@ Otherwise any failure is reported in a message back to 
the user from
 the mailer.
 The usage of ARG is defined by the instance that called Message.
 It should typically alter the sending method in some way or other."
-  (interactive "P")
+  (interactive "P" message-mode)
   ;; Make it possible to undo the coming changes.
   (undo-boundary)
   (let ((inhibit-read-only t))
@@ -4572,7 +4577,7 @@ An address might be bogus if there's a matching entry in
   "Warn before composing or sending a mail to an invalid address.
 
 This function could be useful in `message-setup-hook'."
-  (interactive)
+  (interactive nil message-mode)
   (save-restriction
     (message-narrow-to-headers)
     (dolist (hdr '("To" "Cc" "Bcc"))
@@ -5744,7 +5749,7 @@ If NOW, use that time instead."
 
 (defun message-insert-expires (days)
   "Insert the Expires header.  Expiry in DAYS days."
-  (interactive "NExpire article in how many days? ")
+  (interactive "NExpire article in how many days? " message-mode)
   (save-excursion
     (message-position-on-field "Expires" "X-Draft-From")
     (insert (message-make-expires-date days))))
@@ -6047,7 +6052,7 @@ give as trustworthy answer as possible."
 (defun message-to-list-only ()
   "Send a message to the list only.
 Remove all addresses but the list address from To and Cc headers."
-  (interactive)
+  (interactive nil message-mode)
   (let ((listaddr (message-make-mail-followup-to t)))
     (when listaddr
       (save-excursion
@@ -6133,7 +6138,7 @@ subscribed address (and not the additional To and Cc 
header contents)."
 (defun message-idna-to-ascii-rhs ()
   "Possibly IDNA encode non-ASCII domain names in From:, To: and Cc: headers.
 See `message-idna-encode'."
-  (interactive)
+  (interactive nil message-mode)
   (when message-use-idna
     (save-excursion
       (save-restriction
@@ -6351,7 +6356,7 @@ Headers already prepared in the buffer are not modified."
 (defun message-split-line ()
   "Split current line, moving portion beyond point vertically down.
 If the current line has `message-yank-prefix', insert it on the new line."
-  (interactive "*")
+  (interactive "*" message-mode)
   (split-line message-yank-prefix))
 
 (defun message-insert-header (header value)
@@ -6549,7 +6554,7 @@ When called without a prefix argument, header value 
spanning
 multiple lines is treated as a single line.  Otherwise, even if
 N is 1, when point is on a continuation header line, it will be
 moved to the beginning "
-  (interactive "^p")
+  (interactive "^p" message-mode)
   (cond
    ;; Go to beginning of header or beginning of line.
    ((and message-beginning-of-line (message-point-in-header-p))
@@ -6874,7 +6879,7 @@ are not included."
 
 (defun message-insert-headers ()
   "Generate the headers for the article."
-  (interactive)
+  (interactive nil message-mode)
   (save-excursion
     (save-restriction
       (message-narrow-to-headers)
@@ -8214,7 +8219,7 @@ If nil, the function bound in `text-mode-map' or 
`global-map' is executed."
 Execute function specified by `message-tab-body-function' when
 not in those headers.  If that variable is nil, indent with the
 regular text mode tabbing command."
-  (interactive)
+  (interactive nil message-mode)
   (cond
    ((let ((completion-fail-discreetly t))
       (completion-at-point))
@@ -8591,7 +8596,7 @@ From headers in the original article."
 
 (defun message-display-abbrev (&optional choose)
   "Display the next possible abbrev for the text before point."
-  (interactive (list t))
+  (interactive (list t) message-mode)
   (when (message--in-tocc-p)
     (let* ((end (point))
           (start (save-excursion
@@ -8678,7 +8683,7 @@ Unless FORCE, prompt before sending.
 
 The messages are separated by `message-form-letter-separator'.
 Header and body are separated by `mail-header-separator'."
-  (interactive "P")
+  (interactive "P" message-mode)
   (let ((sent 0) (skipped 0)
        start end text
        buff
@@ -8746,7 +8751,7 @@ Used in `message-simplify-recipients'."
 
 (make-obsolete 'message-simplify-recipients nil "27.1")
 (defun message-simplify-recipients ()
-  (interactive)
+  (interactive nil message-mode)
   (dolist (hdr '("Cc" "To"))
     (message-replace-header
      hdr
@@ -8769,7 +8774,8 @@ Used in `message-simplify-recipients'."
 
 (defun message-make-html-message-with-image-files (files)
   "Make a message containing the current dired-marked image files."
-  (interactive (list (dired-get-marked-files nil current-prefix-arg)))
+  (interactive (list (dired-get-marked-files nil current-prefix-arg))
+              dired-mode)
   (message-mail)
   (message-goto-body)
   (insert "<#part type=text/html>\n\n")
@@ -8780,7 +8786,7 @@ Used in `message-simplify-recipients'."
 
 (defun message-toggle-image-thumbnails ()
   "For any included image files, insert a thumbnail of that image."
-  (interactive)
+  (interactive nil message-mode)
   (let ((displayed nil))
     (save-excursion
       (goto-char (point-min))
@@ -8816,7 +8822,7 @@ starting the screenshotting process.
 
 The `message-screenshot-command' variable says what command is
 used to take the screenshot."
-  (interactive "p")
+  (interactive "p" message-mode)
   (unless (executable-find (car message-screenshot-command))
     (error "Can't find %s to take the screenshot"
           (car message-screenshot-command)))
@@ -8885,15 +8891,16 @@ used to take the screenshot."
     retval))
 
 ;;;###autoload
-(defun message-mailto ()
+(defun message-mailto (&optional url)
   "Command to parse command line mailto: links.
 This is meant to be used for MIME handlers: Setting the handler
 for \"x-scheme-handler/mailto;\" to \"emacs -f message-mailto %u\"
-will then start up Emacs ready to compose mail."
+will then start up Emacs ready to compose mail.  For emacsclient use
+  emacsclient -e '(message-mailto \"%u\")'"
   (interactive)
   ;; <a 
href="mailto:someone@example.com?subject=This%20is%20the%20subject&cc=someone_else@example.com&body=This%20is%20the%20body";>Send
 email</a>
   (message-mail)
-  (message-mailto-1 (pop command-line-args-left)))
+  (message-mailto-1 (or url (pop command-line-args-left))))
 
 (defun message-mailto-1 (url)
   (let ((args (message-parse-mailto-url url)))
diff --git a/lisp/gnus/mml-sec.el b/lisp/gnus/mml-sec.el
index d41c9dd..15157e6 100644
--- a/lisp/gnus/mml-sec.el
+++ b/lisp/gnus/mml-sec.el
@@ -140,7 +140,7 @@ by default identifies the used encryption keys, giving away 
the
 Bcc'ed identities.  Clearly, this contradicts the original goal of
 *blind* copies.
 For an academic paper explaining the problem, see URL
-`http://crypto.stanford.edu/portia/papers/bb-bcc.pdf'.
+`https://crypto.stanford.edu/portia/papers/bb-bcc.pdf'.
 Use this variable to specify e-mail addresses whose owners do not
 mind if they are identifiable as recipients.  This may be useful if
 you use Bcc headers to encrypt e-mails to yourself."
@@ -250,7 +250,7 @@ You can also customize or set `mml-signencrypt-style-alist' 
instead."
   "Add MML tags to sign this MML part.
 Use METHOD if given.  Else use `mml-secure-method' or
 `mml-default-sign-method'."
-  (interactive)
+  (interactive nil mml-mode)
   (mml-secure-part
    (or method mml-secure-method mml-default-sign-method)
    'sign))
@@ -259,43 +259,43 @@ Use METHOD if given.  Else use `mml-secure-method' or
   "Add MML tags to encrypt this MML part.
 Use METHOD if given.  Else use `mml-secure-method' or
 `mml-default-sign-method'."
-  (interactive)
+  (interactive nil mml-mode)
   (mml-secure-part
    (or method mml-secure-method mml-default-sign-method)))
 
 (defun mml-secure-sign-pgp ()
   "Add MML tags to PGP sign this MML part."
-  (interactive)
+  (interactive nil mml-mode)
   (mml-secure-part "pgp" 'sign))
 
 (defun mml-secure-sign-pgpauto ()
   "Add MML tags to PGP-auto sign this MML part."
-  (interactive)
+  (interactive nil mml-mode)
   (mml-secure-part "pgpauto" 'sign))
 
 (defun mml-secure-sign-pgpmime ()
   "Add MML tags to PGP/MIME sign this MML part."
-  (interactive)
+  (interactive nil mml-mode)
   (mml-secure-part "pgpmime" 'sign))
 
 (defun mml-secure-sign-smime ()
   "Add MML tags to S/MIME sign this MML part."
-  (interactive)
+  (interactive nil mml-mode)
   (mml-secure-part "smime" 'sign))
 
 (defun mml-secure-encrypt-pgp ()
   "Add MML tags to PGP encrypt this MML part."
-  (interactive)
+  (interactive nil mml-mode)
   (mml-secure-part "pgp"))
 
 (defun mml-secure-encrypt-pgpmime ()
   "Add MML tags to PGP/MIME encrypt this MML part."
-  (interactive)
+  (interactive nil mml-mode)
   (mml-secure-part "pgpmime"))
 
 (defun mml-secure-encrypt-smime ()
   "Add MML tags to S/MIME encrypt this MML part."
-  (interactive)
+  (interactive nil mml-mode)
   (mml-secure-part "smime"))
 
 (defun mml-secure-is-encrypted-p (&optional tag-present)
@@ -358,7 +358,7 @@ either an error is raised or not."
 
 (defun mml-unsecure-message ()
   "Remove security related MML tags from message."
-  (interactive)
+  (interactive nil mml-mode)
   (save-excursion
     (goto-char (point-max))
     (when (re-search-backward "^<#secure.*>\n" nil t)
@@ -369,7 +369,7 @@ either an error is raised or not."
   "Add MML tags to sign the entire message.
 Use METHOD if given.  Else use `mml-secure-method' or
 `mml-default-sign-method'."
-  (interactive)
+  (interactive nil mml-mode)
   (mml-secure-message
    (or method mml-secure-method mml-default-sign-method)
    'sign))
@@ -378,7 +378,7 @@ Use METHOD if given.  Else use `mml-secure-method' or
   "Add MML tag to sign and encrypt the entire message.
 Use METHOD if given.  Else use `mml-secure-method' or
 `mml-default-sign-method'."
-  (interactive)
+  (interactive nil mml-mode)
   (mml-secure-message
    (or method mml-secure-method mml-default-sign-method)
    'signencrypt))
@@ -387,53 +387,53 @@ Use METHOD if given.  Else use `mml-secure-method' or
   "Add MML tag to encrypt the entire message.
 Use METHOD if given.  Else use `mml-secure-method' or
 `mml-default-sign-method'."
-  (interactive)
+  (interactive nil mml-mode)
   (mml-secure-message
    (or method mml-secure-method mml-default-sign-method)
    'encrypt))
 
 (defun mml-secure-message-sign-smime ()
   "Add MML tag to encrypt/sign the entire message."
-  (interactive)
+  (interactive nil mml-mode)
   (mml-secure-message "smime" 'sign))
 
 (defun mml-secure-message-sign-pgp ()
   "Add MML tag to encrypt/sign the entire message."
-  (interactive)
+  (interactive nil mml-mode)
   (mml-secure-message "pgp" 'sign))
 
 (defun mml-secure-message-sign-pgpmime ()
   "Add MML tag to encrypt/sign the entire message."
-  (interactive)
+  (interactive nil mml-mode)
   (mml-secure-message "pgpmime" 'sign))
 
 (defun mml-secure-message-sign-pgpauto ()
   "Add MML tag to encrypt/sign the entire message."
-  (interactive)
+  (interactive nil mml-mode)
   (mml-secure-message "pgpauto" 'sign))
 
 (defun mml-secure-message-encrypt-smime (&optional dontsign)
   "Add MML tag to encrypt and sign the entire message.
 If called with a prefix argument, only encrypt (do NOT sign)."
-  (interactive "P")
+  (interactive "P" mml-mode)
   (mml-secure-message "smime" (if dontsign 'encrypt 'signencrypt)))
 
 (defun mml-secure-message-encrypt-pgp (&optional dontsign)
   "Add MML tag to encrypt and sign the entire message.
 If called with a prefix argument, only encrypt (do NOT sign)."
-  (interactive "P")
+  (interactive "P" mml-mode)
   (mml-secure-message "pgp" (if dontsign 'encrypt 'signencrypt)))
 
 (defun mml-secure-message-encrypt-pgpmime (&optional dontsign)
   "Add MML tag to encrypt and sign the entire message.
 If called with a prefix argument, only encrypt (do NOT sign)."
-  (interactive "P")
+  (interactive "P" mml-mode)
   (mml-secure-message "pgpmime" (if dontsign 'encrypt 'signencrypt)))
 
 (defun mml-secure-message-encrypt-pgpauto (&optional dontsign)
   "Add MML tag to encrypt and sign the entire message.
 If called with a prefix argument, only encrypt (do NOT sign)."
-  (interactive "P")
+  (interactive "P" mml-mode)
   (mml-secure-message "pgpauto" (if dontsign 'encrypt 'signencrypt)))
 
 ;;; Common functionality for mml1991.el, mml2015.el, mml-smime.el
diff --git a/lisp/gnus/mml.el b/lisp/gnus/mml.el
index f77e5c6..dcc9ea5 100644
--- a/lisp/gnus/mml.el
+++ b/lisp/gnus/mml.el
@@ -1339,7 +1339,7 @@ If not set, `default-directory' will be used."
 
 (defun mml-quote-region (beg end)
   "Quote the MML tags in the region."
-  (interactive "r")
+  (interactive "r" mml-mode)
   (save-excursion
     (save-restriction
       ;; Temporarily narrow the region to defend from changes
diff --git a/lisp/gnus/nnagent.el b/lisp/gnus/nnagent.el
index 76a7e21..56ca2e1 100644
--- a/lisp/gnus/nnagent.el
+++ b/lisp/gnus/nnagent.el
@@ -1,3 +1,4 @@
+
 ;;; nnagent.el --- offline backend for Gnus  -*- lexical-binding: t; -*-
 
 ;; Copyright (C) 1997-2021 Free Software Foundation, Inc.
diff --git a/lisp/gnus/nnbabyl.el b/lisp/gnus/nnbabyl.el
index 3e6f9e8..5f486f4 100644
--- a/lisp/gnus/nnbabyl.el
+++ b/lisp/gnus/nnbabyl.el
@@ -323,7 +323,7 @@
   (nnbabyl-possibly-change-newsgroup group server)
   (nnmail-check-syntax)
   (let ((buf (current-buffer))
-       result beg)
+       result) ;; beg
     (and
      (nnmail-activate 'nnbabyl)
      (save-excursion
@@ -331,7 +331,7 @@
        (search-forward "\n\n" nil t)
        (forward-line -1)
        (save-excursion
-        (while (re-search-backward "^X-Gnus-Newsgroup: " beg t)
+        (while (re-search-backward "^X-Gnus-Newsgroup: " nil t) ;; beg
           (delete-region (point) (progn (forward-line 1) (point)))))
        (when nnmail-cache-accepted-message-ids
         (nnmail-cache-insert (nnmail-fetch-field "message-id")
diff --git a/lisp/gnus/nnfolder.el b/lisp/gnus/nnfolder.el
index 1dd784d..2de5b83 100644
--- a/lisp/gnus/nnfolder.el
+++ b/lisp/gnus/nnfolder.el
@@ -706,7 +706,7 @@ deleted.  Point is left where the deleted region was."
       (if dont-check
          (setq nnfolder-current-group group
                nnfolder-current-buffer nil)
-       (let (inf file)
+       (let (file) ;; inf
          ;; If we have to change groups, see if we don't already have
          ;; the folder in memory.  If we do, verify the modtime and
          ;; destroy the folder if needed so we can rescan it.
@@ -718,7 +718,7 @@ deleted.  Point is left where the deleted region was."
          ;; touched the file since last time.
          (when (and nnfolder-current-buffer
                     (not (gnus-buffer-live-p nnfolder-current-buffer)))
-           (setq nnfolder-buffer-alist (delq inf nnfolder-buffer-alist)
+           (setq nnfolder-buffer-alist (delq nil nnfolder-buffer-alist) ;; inf
                  nnfolder-current-buffer nil))
 
          (setq nnfolder-current-group group)
diff --git a/lisp/gnus/nnimap.el b/lisp/gnus/nnimap.el
index f4f4ef8..f06959f 100644
--- a/lisp/gnus/nnimap.el
+++ b/lisp/gnus/nnimap.el
@@ -95,7 +95,7 @@ Uses the same syntax as `nnmail-split-methods'.")
   "Articles with the flags in the list will not be considered when splitting.")
 
 (make-obsolete-variable 'nnimap-split-rule "see `nnimap-split-methods'."
-                       "Emacs 24.1")
+                        "24.1")
 
 (defvoo nnimap-authenticator nil
   "How nnimap authenticate itself to the server.
@@ -440,6 +440,7 @@ during splitting, which may be slow."
 
 ;; This is only needed for Windows XP or earlier
 (defun nnimap-map-port (port)
+  (declare-function x-server-version "xfns.c" (&optional terminal))
   (if (and (eq system-type 'windows-nt)
            (<= (car (x-server-version)) 5)
            (equal port "imaps"))
diff --git a/lisp/gnus/nnmail.el b/lisp/gnus/nnmail.el
index 9826bc6..bcf01cf 100644
--- a/lisp/gnus/nnmail.el
+++ b/lisp/gnus/nnmail.el
@@ -240,11 +240,6 @@ If non-nil, also update the cache when copy or move 
articles."
   :group 'nnmail
   :type 'boolean)
 
-(make-obsolete-variable 'nnmail-spool-file 'mail-sources
-                       "Gnus 5.9 (Emacs 22.1)")
-;; revision 5.29 / p0-85 / Gnus 5.9
-;; Variable removed in No Gnus v0.7
-
 (defcustom nnmail-resplit-incoming nil
   "If non-nil, re-split incoming procmail sorted mail."
   :group 'nnmail-procmail
@@ -1321,9 +1316,6 @@ Eudora has a broken References line, but an OK 
In-Reply-To."
     (when (re-search-forward "^\\(In-Reply-To:[^\n]+\\)\n[ \t]+" nil t)
       (replace-match "\\1" t))))
 
-(defalias 'nnmail-fix-eudora-headers #'nnmail-ignore-broken-references)
-(make-obsolete 'nnmail-fix-eudora-headers #'nnmail-ignore-broken-references 
"Emacs 23.1")
-
 (custom-add-option 'nnmail-prepare-incoming-header-hook
                   'nnmail-ignore-broken-references)
 
diff --git a/lisp/gnus/nnmaildir.el b/lisp/gnus/nnmaildir.el
index 46691e3..4867455 100644
--- a/lisp/gnus/nnmaildir.el
+++ b/lisp/gnus/nnmaildir.el
@@ -21,7 +21,7 @@
 
 ;;; Commentary:
 
-;; Maildir format is documented at <URL:http://cr.yp.to/proto/maildir.html>.
+;; Maildir format is documented at <URL:https://cr.yp.to/proto/maildir.html>.
 ;; nnmaildir also stores extra information in the .nnmaildir/ directory
 ;; within a maildir.
 ;;
diff --git a/lisp/gnus/nnmh.el b/lisp/gnus/nnmh.el
index 231583f..0923b8e 100644
--- a/lisp/gnus/nnmh.el
+++ b/lisp/gnus/nnmh.el
@@ -503,6 +503,8 @@ as unread by Gnus.")
       (setcdr active (1+ (cdr active))))
     (cdr active)))
 
+(defvar nnmh-newsgroup-articles)
+
 (defun nnmh-update-gnus-unreads (group)
   ;; Go through the .nnmh-articles file and compare with the actual
   ;; articles in this folder.  The articles that are "new" will be
diff --git a/lisp/gnus/nnrss.el b/lisp/gnus/nnrss.el
index aa7c8e5..a40fa88 100644
--- a/lisp/gnus/nnrss.el
+++ b/lisp/gnus/nnrss.el
@@ -200,7 +200,7 @@ for decoding when the cdr that the data specify is not 
available.")
   (nnrss-possibly-change-group group server)
   (let ((e (assq article nnrss-group-data))
        (nntp-server-buffer (or buffer nntp-server-buffer))
-       err) ;; post
+       ) ;; err post
     (when e
       (with-current-buffer nntp-server-buffer
        (erase-buffer)
@@ -302,8 +302,7 @@ for decoding when the cdr that the data specify is not 
available.")
        (when nnrss-content-function
          (funcall nnrss-content-function e group article))))
     (cond
-     (err
-      (nnheader-report 'nnrss err))
+     ;; (err (nnheader-report 'nnrss err))
      ((not e)
       (nnheader-report 'nnrss "no such id: %d" article))
      (t
@@ -931,60 +930,7 @@ Use Mark Pilgrim's `ultra-liberal rss locator'."
                      (setq rss-link (nnrss-rss-title-description
                                      rss-ns href-data (car hrefs))))
                  (setq hrefs (cdr hrefs)))))
-           (if rss-link
-               rss-link
-             ;;    4. check syndic8
-             (nnrss-find-rss-via-syndic8 url))))))))
-
-(declare-function xml-rpc-method-call "ext:xml-rpc"
-                 (server-url method &rest params))
-
-(defun nnrss-find-rss-via-syndic8 (url)
-  "Query syndic8 for the rss feeds it has for URL."
-  (if (not (locate-library "xml-rpc"))
-      (progn
-       (message "XML-RPC is not available... not checking Syndic8.")
-       nil)
-    (require 'xml-rpc)
-    (let ((feedid (xml-rpc-method-call
-                  "http://www.syndic8.com/xmlrpc.php";
-                  'syndic8.FindSites
-                  url)))
-      (when feedid
-       (let* ((feedinfo (xml-rpc-method-call
-                         "http://www.syndic8.com/xmlrpc.php";
-                         'syndic8.GetFeedInfo
-                         feedid))
-              (urllist
-               (delq nil
-                     (mapcar
-                      (lambda (listinfo)
-                        (if (string-equal
-                             (cdr (assoc "status" listinfo))
-                             "Syndicated")
-                            (cons
-                             (cdr (assoc "sitename" listinfo))
-                             (list
-                              (cons 'title
-                                    (cdr (assoc
-                                          "sitename" listinfo)))
-                              (cons 'href
-                                    (cdr (assoc
-                                          "dataurl" listinfo)))))))
-                      feedinfo))))
-         (if (not (> (length urllist) 1))
-             (cdar urllist)
-           (let ((completion-ignore-case t)
-                 (selection
-                  (mapcar (lambda (listinfo)
-                            (cons (cdr (assoc "sitename" listinfo))
-                                  (string-to-number
-                                   (cdr (assoc "feedid" listinfo)))))
-                          feedinfo)))
-             (cdr (assoc
-                   (gnus-completing-read
-                    "Multiple feeds found. Select one"
-                    selection t) urllist)))))))))
+            rss-link))))))
 
 (defun nnrss-rss-p (data)
   "Test if DATA is an RSS feed.
@@ -1023,6 +969,11 @@ prefix), return the prefix."
        (concat ns ":")
       ns)))
 
+(defun nnrss-find-rss-via-syndic8 (_url)
+  "This function is obsolete and does nothing.  Syndic8 shut down in 2013."
+  (declare (obsolete nil "28.1"))
+  nil)
+
 (provide 'nnrss)
 
 ;;; nnrss.el ends here
diff --git a/lisp/gnus/nnselect.el b/lisp/gnus/nnselect.el
index fffa2d2..1daa8aa 100644
--- a/lisp/gnus/nnselect.el
+++ b/lisp/gnus/nnselect.el
@@ -33,7 +33,7 @@
 ;; turn be a vector of three elements: a real prefixed group name, an
 ;; article number in that group, and an integer score.  The score is
 ;; not used by nnselect but may be used by other code to help in
-;; sorting.  Most functions will just chose a fixed number, such as
+;; sorting.  Most functions will just choose a fixed number, such as
 ;; 100, for this score.
 
 ;; For example the search function `gnus-search-run-query' applied to
diff --git a/lisp/gnus/nntp.el b/lisp/gnus/nntp.el
index 1eb604d..1fd2ed0 100644
--- a/lisp/gnus/nntp.el
+++ b/lisp/gnus/nntp.el
@@ -233,7 +233,7 @@ server there that you can connect to.  See also
                                          (const :format "" "password")
                                          (string :format "Password: %v")))))))
 
-(make-obsolete 'nntp-authinfo-file nil "Emacs 24.1")
+(make-obsolete 'nntp-authinfo-file nil "24.1")
 
 
 
diff --git a/lisp/gnus/score-mode.el b/lisp/gnus/score-mode.el
index d3ed360..5140861 100644
--- a/lisp/gnus/score-mode.el
+++ b/lisp/gnus/score-mode.el
@@ -83,12 +83,12 @@ This mode is an extended emacs-lisp mode.
 
 (defun gnus-score-edit-insert-date ()
   "Insert date in numerical format."
-  (interactive)
+  (interactive nil gnus-score-mode)
   (princ (time-to-days nil) (current-buffer)))
 
 (defun gnus-score-pretty-print ()
   "Format the current score file."
-  (interactive)
+  (interactive nil gnus-score-mode)
   (goto-char (point-min))
   (let ((form (read (current-buffer))))
     (erase-buffer)
@@ -98,7 +98,7 @@ This mode is an extended emacs-lisp mode.
 
 (defun gnus-score-edit-exit ()
   "Stop editing the score file."
-  (interactive)
+  (interactive nil gnus-score-mode)
   (unless (file-exists-p (file-name-directory (buffer-file-name)))
     (make-directory (file-name-directory (buffer-file-name)) t))
   (let ((coding-system-for-write score-mode-coding-system))
diff --git a/lisp/gnus/smiley.el b/lisp/gnus/smiley.el
index 3ee5947..32283af 100644
--- a/lisp/gnus/smiley.el
+++ b/lisp/gnus/smiley.el
@@ -242,7 +242,7 @@ interactively.  If there's no argument, do it at the 
current buffer."
 (defun smiley-toggle-buffer (&optional arg)
   "Toggle displaying smiley faces in article buffer.
 With arg, turn displaying on if and only if arg is positive."
-  (interactive "P")
+  (interactive "P" gnus-article-mode gnus-summary-mode)
   (gnus-with-article-buffer
     (if (if (numberp arg)
            (> arg 0)
diff --git a/lisp/gnus/smime.el b/lisp/gnus/smime.el
index 8900be5..e9f703e 100644
--- a/lisp/gnus/smime.el
+++ b/lisp/gnus/smime.el
@@ -42,7 +42,7 @@
 ;; reflect this.
 ;;
 ;; The home of this file is in Gnus, but also available from
-;; http://josefsson.org/smime.html.
+;; https://josefsson.org/smime.html.
 
 ;;; Quick introduction:
 
@@ -672,7 +672,7 @@ The following commands are available:
 
 (defun smime-exit ()
   "Quit the S/MIME buffer."
-  (interactive)
+  (interactive nil smime-mode)
   (kill-buffer (current-buffer)))
 
 ;; Other functions
diff --git a/lisp/gnus/spam-report.el b/lisp/gnus/spam-report.el
index d87a6c2..7d93f8a 100644
--- a/lisp/gnus/spam-report.el
+++ b/lisp/gnus/spam-report.el
@@ -120,7 +120,8 @@ submitted at once.  Internal variable.")
 
 (defun spam-report-gmane-ham (&rest articles)
   "Report ARTICLES as ham (unregister) through Gmane."
-  (interactive (gnus-summary-work-articles current-prefix-arg))
+  (interactive (gnus-summary-work-articles current-prefix-arg)
+              gnus-summary-mode)
   (let ((count 0))
     (dolist (article articles)
       (setq count (1+ count))
@@ -130,7 +131,8 @@ submitted at once.  Internal variable.")
 
 (defun spam-report-gmane-spam (&rest articles)
   "Report ARTICLES as spam through Gmane."
-  (interactive (gnus-summary-work-articles current-prefix-arg))
+  (interactive (gnus-summary-work-articles current-prefix-arg)
+              gnus-summary-mode)
   (let ((count 0))
     (dolist (article articles)
       (setq count (1+ count))
diff --git a/lisp/gnus/spam-stat.el b/lisp/gnus/spam-stat.el
index 70753ca..3e804ec 100644
--- a/lisp/gnus/spam-stat.el
+++ b/lisp/gnus/spam-stat.el
@@ -575,7 +575,6 @@ check the variable `spam-stat-score-data'."
 
 (defun spam-stat-count ()
   "Return size of `spam-stat'."
-  (interactive)
   (hash-table-count spam-stat))
 
 (defun spam-stat-test-directory (dir &optional verbose)
diff --git a/lisp/gnus/spam.el b/lisp/gnus/spam.el
index f7288c9..d00f0a6 100644
--- a/lisp/gnus/spam.el
+++ b/lisp/gnus/spam.el
@@ -1604,7 +1604,6 @@ parameters.  A string as a parameter will set the
 `spam-split-group' to that string.
 
 See the Info node `(gnus)Fancy Mail Splitting' for more details."
-  (interactive)
   (setq spam-split-last-successful-check nil)
   (unless spam-split-disabled
     (let ((spam-split-group-choice spam-split-group))
@@ -1654,7 +1653,7 @@ See the Info node `(gnus)Fancy Mail Splitting' for more 
details."
 
 (defun spam-find-spam ()
   "Detect spam in the current newsgroup using `spam-split'."
-  (interactive)
+  (interactive nil gnus-summary-mode)
 
   (let* ((group gnus-newsgroup-name)
          (autodetect (gnus-parameter-spam-autodetect group))
@@ -2434,7 +2433,7 @@ With a non-nil REMOVE, remove the ADDRESSES."
 ;; return something sensible if the score can't be determined
 (defun spam-bogofilter-score (&optional recheck)
   "Get the Bogofilter spamicity score."
-  (interactive "P")
+  (interactive "P" gnus-summary-mode)
   (save-window-excursion
     (gnus-summary-show-article t)
     (set-buffer gnus-article-buffer)
@@ -2606,7 +2605,7 @@ With a non-nil REMOVE, remove the ADDRESSES."
 ;; return something sensible if the score can't be determined
 (defun spam-spamassassin-score (&optional recheck)
   "Get the SpamAssassin score."
-  (interactive "P")
+  (interactive "P" gnus-summary-mode)
   (save-window-excursion
     (gnus-summary-show-article t)
     (set-buffer gnus-article-buffer)
@@ -2673,7 +2672,7 @@ With a non-nil REMOVE, remove the ADDRESSES."
 ;; return something sensible if the score can't be determined
 (defun spam-bsfilter-score (&optional recheck)
   "Get the Bsfilter spamicity score."
-  (interactive "P")
+  (interactive "P" gnus-summary-mode)
   (save-window-excursion
     (gnus-summary-show-article t)
     (set-buffer gnus-article-buffer)
@@ -2759,7 +2758,7 @@ With a non-nil REMOVE, remove the ADDRESSES."
 ;; return something sensible if the score can't be determined
 (defun spam-crm114-score ()
   "Get the CRM114 Mailfilter pR."
-  (interactive)
+  (interactive nil gnus-summary-mode)
   (save-window-excursion
     (gnus-summary-show-article t)
     (set-buffer gnus-article-buffer)
diff --git a/lisp/help-at-pt.el b/lisp/help-at-pt.el
index e17bd0a..233c505 100644
--- a/lisp/help-at-pt.el
+++ b/lisp/help-at-pt.el
@@ -1,4 +1,4 @@
-;;; help-at-pt.el --- local help through the keyboard
+;;; help-at-pt.el --- local help through the keyboard  -*- lexical-binding: t 
-*-
 
 ;; Copyright (C) 2003-2021 Free Software Foundation, Inc.
 
@@ -42,9 +42,6 @@
 ;;
 ;; (global-set-key [C-tab] 'scan-buf-next-region)
 ;; (global-set-key [C-M-tab] 'scan-buf-previous-region)
-;;
-;; You do not have to do anything special to use the functionality
-;; provided by this file, because all important functions autoload.
 
 ;;; Code:
 
diff --git a/lisp/help-fns.el b/lisp/help-fns.el
index b03a440..c27cdb5 100644
--- a/lisp/help-fns.el
+++ b/lisp/help-fns.el
@@ -466,13 +466,16 @@ suitable file is found, return nil."
               ;; If lots of ordinary text characters run this command,
               ;; don't mention them one by one.
               (if (< (length non-modified-keys) 10)
-                  (princ (mapconcat #'key-description keys ", "))
+                  (with-current-buffer standard-output
+                    (insert (mapconcat #'help--key-description-fontified
+                                       keys ", ")))
                 (dolist (key non-modified-keys)
                   (setq keys (delq key keys)))
                 (if keys
-                    (progn
-                      (princ (mapconcat #'key-description keys ", "))
-                      (princ ", and many ordinary text characters"))
+                    (with-current-buffer standard-output
+                      (insert (mapconcat #'help--key-description-fontified
+                                        keys ", "))
+                      (insert ", and many ordinary text characters"))
                   (princ "many ordinary text characters"))))
             (when (or remapped keys non-modified-keys)
               (princ ".")
@@ -668,7 +671,7 @@ FILE is the file where FUNCTION was probably defined."
               ;; Almost all entries are of the form "* ... in Emacs NN.MM."
               ;; but there are also a few in the form "* Emacs NN.MM is a bug
               ;; fix release ...".
-              (if (not (re-search-backward "^\\*.* Emacs \\([0-9.]+[0-9]\\)"
+              (if (not (re-search-backward "^\\* .* Emacs \\([0-9.]+[0-9]\\)"
                                            nil t))
                   (message "Ref found in non-versioned section in %S"
                            (file-name-nondirectory f))
@@ -1026,7 +1029,7 @@ it is displayed along with the global value."
              (princ (if file-name
                         (progn
                           (princ (format-message
-                                   " is a variable defined in `%s'.\n"
+                                   " is a variable defined in `%s'.\n\n"
                                    (if (eq file-name 'C-source)
                                        "C source code"
                                      (help-fns-short-filename file-name))))
@@ -1162,7 +1165,6 @@ it is displayed along with the global value."
 
               (with-current-buffer standard-output
                 (help-fns--ensure-empty-line))
-             (princ "Documentation:\n")
              (with-current-buffer standard-output
                (insert (or doc "Not documented as a variable."))))
 
@@ -1743,7 +1745,7 @@ documentation for the major and minor modes of that 
buffer."
   ;; don't switch buffers before calling `help-buffer'.
   (with-help-window (help-buffer)
     (with-current-buffer buffer
-      (let (minor-modes)
+      (let (minors)
        ;; Older packages do not register in minor-mode-list but only in
        ;; minor-mode-alist.
        (dolist (x minor-mode-alist)
@@ -1766,19 +1768,19 @@ documentation for the major and minor modes of that 
buffer."
                          fmode)))
                   (push (list fmode pretty-minor-mode
                               (format-mode-line (assq mode minor-mode-alist)))
-                        minor-modes)))))
+                        minors)))))
        ;; Narrowing is not a minor mode, but its indicator is part of
        ;; mode-line-modes.
        (when (buffer-narrowed-p)
-         (push '(narrow-to-region "Narrow" " Narrow") minor-modes))
-       (setq minor-modes
-             (sort minor-modes
+         (push '(narrow-to-region "Narrow" " Narrow") minors))
+       (setq minors
+             (sort minors
                    (lambda (a b) (string-lessp (cadr a) (cadr b)))))
-       (when minor-modes
+       (when minors
          (princ "Enabled minor modes:\n")
          (make-local-variable 'help-button-cache)
          (with-current-buffer standard-output
-           (dolist (mode minor-modes)
+           (dolist (mode minors)
              (let ((mode-function (nth 0 mode))
                    (pretty-minor-mode (nth 1 mode))
                    (indicator (nth 2 mode)))
@@ -1825,11 +1827,34 @@ documentation for the major and minor modes of that 
buffer."
              (save-excursion
                (re-search-backward (substitute-command-keys "`\\([^`']+\\)'")
                                     nil t)
-               (help-xref-button 1 'help-function-def mode file-name)))))
-       (princ ":\n")
-       (princ (help-split-fundoc (documentation major-mode) nil 'doc)))))
+                (help-xref-button 1 'help-function-def mode file-name)))))
+        (let ((fundoc (help-split-fundoc (documentation major-mode) nil 'doc)))
+          (with-current-buffer standard-output
+            (insert ":\n")
+            (insert fundoc)
+            (insert (help-fns--list-local-commands)))))))
   ;; For the sake of IELM and maybe others
   nil)
+
+(defun help-fns--list-local-commands ()
+  (let ((functions nil))
+    (mapatoms
+     (lambda (sym)
+       (when (and (commandp sym)
+                  ;; Ignore aliases.
+                  (not (symbolp (symbol-function sym)))
+                  ;; Ignore everything bound.
+                  (not (where-is-internal sym))
+                  (apply #'derived-mode-p (command-modes sym)))
+         (push sym functions))))
+    (with-temp-buffer
+      (when functions
+        (setq functions (sort functions #'string<))
+        (insert "\n\nOther commands for this mode, not bound to any keys:\n\n")
+        (dolist (function functions)
+          (insert (format "`%s'\n" function))))
+      (buffer-string))))
+
 
 ;; Widgets.
 
diff --git a/lisp/help-macro.el b/lisp/help-macro.el
index 791b10a..81d2383 100644
--- a/lisp/help-macro.el
+++ b/lisp/help-macro.el
@@ -1,4 +1,4 @@
-;;; help-macro.el --- makes command line help such as help-for-help
+;;; help-macro.el --- makes command line help such as help-for-help  -*- 
lexical-binding: t -*-
 
 ;; Copyright (C) 1993-1994, 2001-2021 Free Software Foundation, Inc.
 
@@ -92,119 +92,117 @@ If HELP-TEXT contains the sequence `%THIS-KEY%', that is 
replaced
 with the key sequence that invoked FNAME.
 When FNAME finally does get a command, it executes that command
 and then returns."
-  (let ((doc-fn (intern (concat (symbol-name fname) "-doc"))))
-    `(progn
-       (defun ,doc-fn () ,help-text nil)
-       (defun ,fname ()
-        "Help command."
-        (interactive)
-        (let ((line-prompt
-               (substitute-command-keys ,help-line)))
-          (when three-step-help
-            (message "%s" line-prompt))
-          (let* ((help-screen (documentation (quote ,doc-fn)))
-                 ;; We bind overriding-local-map for very small
-                 ;; sections, *excluding* where we switch buffers
-                 ;; and where we execute the chosen help command.
-                 (local-map (make-sparse-keymap))
-                 (new-minor-mode-map-alist minor-mode-map-alist)
-                 (prev-frame (selected-frame))
-                 config new-frame key char)
-            (when (string-match "%THIS-KEY%" help-screen)
-              (setq help-screen
-                    (replace-match (key-description
-                                    (substring (this-command-keys) 0 -1))
-                                   t t help-screen)))
-            (unwind-protect
-                (let ((minor-mode-map-alist nil))
-                  (setcdr local-map ,helped-map)
-                  (define-key local-map [t] 'undefined)
-                  ;; Make the scroll bar keep working normally.
-                  (define-key local-map [vertical-scroll-bar]
-                    (lookup-key global-map [vertical-scroll-bar]))
-                  (if three-step-help
-                      (progn
-                        (setq key (let ((overriding-local-map local-map))
-                                    (read-key-sequence nil)))
-                        ;; Make the HELP key translate to C-h.
-                        (if (lookup-key function-key-map key)
-                            (setq key (lookup-key function-key-map key)))
-                        (setq char (aref key 0)))
-                    (setq char ??))
-                  (when (or (eq char ??) (eq char help-char)
-                            (memq char help-event-list))
-                    (setq config (current-window-configuration))
-                    (pop-to-buffer " *Metahelp*" nil t)
-                    (and (fboundp 'make-frame)
-                         (not (eq (window-frame)
-                                  prev-frame))
-                         (setq new-frame (window-frame)
-                               config nil))
-                    (setq buffer-read-only nil)
-                    (let ((inhibit-read-only t))
-                      (erase-buffer)
-                      (insert help-screen))
-                    (let ((minor-mode-map-alist new-minor-mode-map-alist))
-                      (help-mode)
-                      (setq new-minor-mode-map-alist minor-mode-map-alist))
-                    (goto-char (point-min))
-                    (while (or (memq char (append help-event-list
-                                                  (cons help-char '(?? ?\C-v 
?\s ?\177 delete backspace vertical-scroll-bar ?\M-v))))
-                               (eq (car-safe char) 'switch-frame)
-                               (equal key "\M-v"))
-                      (condition-case nil
-                          (cond
-                           ((eq (car-safe char) 'switch-frame)
-                            (handle-switch-frame char))
-                           ((memq char '(?\C-v ?\s))
-                            (scroll-up))
-                           ((or (memq char '(?\177 ?\M-v delete backspace))
-                                (equal key "\M-v"))
-                            (scroll-down)))
-                        (error nil))
-                      (let ((cursor-in-echo-area t)
-                            (overriding-local-map local-map))
-                        (setq key (read-key-sequence
-                                   (format "Type one of the options listed%s: "
-                                           (if (pos-visible-in-window-p
-                                                (point-max))
-                                               "" ", or SPACE or DEL to 
scroll")))
-                              char (aref key 0)))
-
-                      ;; If this is a scroll bar command, just run it.
-                      (when (eq char 'vertical-scroll-bar)
-                        (command-execute (lookup-key local-map key) nil key))))
-                  ;; We don't need the prompt any more.
-                  (message "")
-                  ;; Mouse clicks are not part of the help feature,
-                  ;; so reexecute them in the standard environment.
-                  (if (listp char)
-                      (setq unread-command-events
-                            (cons char unread-command-events)
-                            config nil)
-                    (let ((defn (lookup-key local-map key)))
-                      (if defn
-                          (progn
-                            (when config
-                              (set-window-configuration config)
-                              (setq config nil))
-                            ;; Temporarily rebind `minor-mode-map-alist'
-                            ;; to `new-minor-mode-map-alist' (Bug#10454).
-                            (let ((minor-mode-map-alist 
new-minor-mode-map-alist))
-                              ;; `defn' must make sure that its frame is
-                              ;; selected, so we won't iconify it below.
-                              (call-interactively defn))
-                            (when new-frame
-                              ;; Do not iconify the selected frame.
-                              (unless (eq new-frame (selected-frame))
-                                (iconify-frame new-frame))
-                              (setq new-frame nil)))
-                        (ding)))))
-              (when config
-                (set-window-configuration config))
-              (when new-frame
-                (iconify-frame new-frame))
-              (setq minor-mode-map-alist new-minor-mode-map-alist))))))))
+  (declare (indent defun))
+  `(defun ,fname ()
+     "Help command."
+     (interactive)
+     (let ((line-prompt
+            (substitute-command-keys ,help-line)))
+       (when three-step-help
+         (message "%s" line-prompt))
+       (let* ((help-screen ,help-text)
+              ;; We bind overriding-local-map for very small
+              ;; sections, *excluding* where we switch buffers
+              ;; and where we execute the chosen help command.
+              (local-map (make-sparse-keymap))
+              (new-minor-mode-map-alist minor-mode-map-alist)
+              (prev-frame (selected-frame))
+              config new-frame key char)
+         (when (string-match "%THIS-KEY%" help-screen)
+           (setq help-screen
+                 (replace-match (help--key-description-fontified
+                                 (substring (this-command-keys) 0 -1))
+                                t t help-screen)))
+         (unwind-protect
+             (let ((minor-mode-map-alist nil))
+               (setcdr local-map ,helped-map)
+               (define-key local-map [t] 'undefined)
+               ;; Make the scroll bar keep working normally.
+               (define-key local-map [vertical-scroll-bar]
+                 (lookup-key global-map [vertical-scroll-bar]))
+               (if three-step-help
+                   (progn
+                     (setq key (let ((overriding-local-map local-map))
+                                 (read-key-sequence nil)))
+                     ;; Make the HELP key translate to C-h.
+                     (if (lookup-key function-key-map key)
+                         (setq key (lookup-key function-key-map key)))
+                     (setq char (aref key 0)))
+                 (setq char ??))
+               (when (or (eq char ??) (eq char help-char)
+                         (memq char help-event-list))
+                 (setq config (current-window-configuration))
+                 (pop-to-buffer " *Metahelp*" nil t)
+                 (and (fboundp 'make-frame)
+                      (not (eq (window-frame)
+                               prev-frame))
+                      (setq new-frame (window-frame)
+                            config nil))
+                 (setq buffer-read-only nil)
+                 (let ((inhibit-read-only t))
+                   (erase-buffer)
+                   (insert (substitute-command-keys help-screen)))
+                 (let ((minor-mode-map-alist new-minor-mode-map-alist))
+                   (help-mode)
+                   (setq new-minor-mode-map-alist minor-mode-map-alist))
+                 (goto-char (point-min))
+                 (while (or (memq char (append help-event-list
+                                               (cons help-char '(?? ?\C-v ?\s 
?\177 delete backspace vertical-scroll-bar ?\M-v))))
+                            (eq (car-safe char) 'switch-frame)
+                            (equal key "\M-v"))
+                   (condition-case nil
+                       (cond
+                        ((eq (car-safe char) 'switch-frame)
+                         (handle-switch-frame char))
+                        ((memq char '(?\C-v ?\s))
+                         (scroll-up))
+                        ((or (memq char '(?\177 ?\M-v delete backspace))
+                             (equal key "\M-v"))
+                         (scroll-down)))
+                     (error nil))
+                   (let ((cursor-in-echo-area t)
+                         (overriding-local-map local-map))
+                     (setq key (read-key-sequence
+                                (format "Type one of the options listed%s: "
+                                        (if (pos-visible-in-window-p
+                                             (point-max))
+                                            "" ", or SPACE or DEL to scroll")))
+                           char (aref key 0)))
+
+                   ;; If this is a scroll bar command, just run it.
+                   (when (eq char 'vertical-scroll-bar)
+                     (command-execute (lookup-key local-map key) nil key))))
+               ;; We don't need the prompt any more.
+               (message "")
+               ;; Mouse clicks are not part of the help feature,
+               ;; so reexecute them in the standard environment.
+               (if (listp char)
+                   (setq unread-command-events
+                         (cons char unread-command-events)
+                         config nil)
+                 (let ((defn (lookup-key local-map key)))
+                   (if defn
+                       (progn
+                         (when config
+                           (set-window-configuration config)
+                           (setq config nil))
+                         ;; Temporarily rebind `minor-mode-map-alist'
+                         ;; to `new-minor-mode-map-alist' (Bug#10454).
+                         (let ((minor-mode-map-alist new-minor-mode-map-alist))
+                           ;; `defn' must make sure that its frame is
+                           ;; selected, so we won't iconify it below.
+                           (call-interactively defn))
+                         (when new-frame
+                           ;; Do not iconify the selected frame.
+                           (unless (eq new-frame (selected-frame))
+                             (iconify-frame new-frame))
+                           (setq new-frame nil)))
+                     (ding)))))
+           (when config
+             (set-window-configuration config))
+           (when new-frame
+             (iconify-frame new-frame))
+           (setq minor-mode-map-alist new-minor-mode-map-alist))))))
 
 (provide 'help-macro)
 
diff --git a/lisp/help-mode.el b/lisp/help-mode.el
index 79710a1..c7eaae5 100644
--- a/lisp/help-mode.el
+++ b/lisp/help-mode.el
@@ -30,7 +30,6 @@
 ;;; Code:
 
 (require 'cl-lib)
-(eval-when-compile (require 'easymenu))
 
 (defvar help-mode-map
   (let ((map (make-sparse-keymap)))
@@ -54,14 +53,30 @@
     ["Show Help for Symbol" help-follow-symbol
      :help "Show the docs for the symbol at point"]
     ["Previous Topic" help-go-back
-     :help "Go back to previous topic in this help buffer"]
+     :help "Go back to previous topic in this help buffer"
+     :active help-xref-stack]
     ["Next Topic" help-go-forward
-     :help "Go back to next topic in this help buffer"]
+     :help "Go back to next topic in this help buffer"
+     :active help-xref-forward-stack]
     ["Move to Previous Button" backward-button
      :help "Move to the Previous Button in the help buffer"]
     ["Move to Next Button" forward-button
       :help "Move to the Next Button in the help buffer"]))
 
+(defvar help-mode-tool-bar-map
+  (let ((map (make-sparse-keymap)))
+    (tool-bar-local-item "close" 'quit-window 'quit map
+                         :help "Quit help"
+                         :vert-only t)
+    (define-key-after map [separator-1] menu-bar-separator)
+    (tool-bar-local-item "search" 'isearch-forward 'search map
+                         :help "Search" :vert-only t)
+    (tool-bar-local-item-from-menu 'help-go-back "left-arrow" map help-mode-map
+                                   :rtl "right-arrow" :vert-only t)
+    (tool-bar-local-item-from-menu 'help-go-forward "right-arrow" map 
help-mode-map
+                                   :rtl "left-arrow" :vert-only t)
+    map))
+
 (defvar-local help-xref-stack nil
   "A stack of ways by which to return to help buffers after following xrefs.
 Used by `help-follow' and `help-xref-go-back'.
@@ -317,6 +332,8 @@ Commands:
 \\{help-mode-map}"
   (setq-local revert-buffer-function
               #'help-mode-revert-buffer)
+  (setq-local tool-bar-map
+              help-mode-tool-bar-map)
   (setq-local bookmark-make-record-function
               #'help-bookmark-make-record))
 
@@ -458,8 +475,7 @@ that."
   (with-current-buffer (or buffer (current-buffer))
     (save-excursion
       (goto-char (point-min))
-      ;; Skip the header-type info, though it might be useful to parse
-      ;; it at some stage (e.g. "function in `library'").
+      ;; Skip the first bit, which has already been buttonized.
       (forward-paragraph)
       (let ((old-modified (buffer-modified-p)))
         (let ((stab (syntax-table))
@@ -778,8 +794,8 @@ help buffer by other means."
                   (&optional no-file no-context posn))
 
 (defun help-bookmark-make-record ()
-  "Create and return a help-mode bookmark record.
-Implements `bookmark-make-record-function' for help-mode buffers."
+  "Create and return a `help-mode' bookmark record.
+Implements `bookmark-make-record-function' for `help-mode' buffers."
   (unless (car help-xref-stack-item)
     (error "Cannot create bookmark - help command not known"))
   `(,@(bookmark-make-record-default 'NO-FILE 'NO-CONTEXT)
@@ -792,7 +808,7 @@ Implements `bookmark-make-record-function' for help-mode 
buffers."
 
 ;;;###autoload
 (defun help-bookmark-jump (bookmark)
-  "Jump to help-mode bookmark BOOKMARK.
+  "Jump to `help-mode' bookmark BOOKMARK.
 Handler function for record returned by `help-bookmark-make-record'.
 BOOKMARK is a bookmark name or a bookmark record."
   (let ((help-fn    (bookmark-prop-get bookmark 'help-fn))
diff --git a/lisp/help.el b/lisp/help.el
index 084e941..d4be9aa 100644
--- a/lisp/help.el
+++ b/lisp/help.el
@@ -104,8 +104,8 @@
     (define-key map "R" 'info-display-manual)
     (define-key map "s" 'describe-syntax)
     (define-key map "t" 'help-with-tutorial)
-    (define-key map "w" 'where-is)
     (define-key map "v" 'describe-variable)
+    (define-key map "w" 'where-is)
     (define-key map "q" 'help-quit)
     map)
   "Keymap for characters following the Help key.")
@@ -187,64 +187,58 @@ Do not call this in the scope of `with-help-window'."
 ;; So keyboard macro definitions are documented correctly
 (fset 'defining-kbd-macro (symbol-function 'start-kbd-macro))
 
-(defalias 'help 'help-for-help-internal)
-;; find-function can find this.
-(defalias 'help-for-help 'help-for-help-internal)
-;; It can't find this, but nobody will look.
-(make-help-screen help-for-help-internal
+(defalias 'help 'help-for-help)
+(make-help-screen help-for-help
   (purecopy "Type a help option: [abcCdefFgiIkKlLmnprstvw.] C-[cdefmnoptw] or 
?")
-  ;; Don't purecopy this one, because it's not evaluated (it's
-  ;; directly used as a docstring in a function definition, so it'll
-  ;; be moved to the DOC file anyway: no need for purecopying it).
   "You have typed %THIS-KEY%, the help character.  Type a Help option:
 \(Use SPC or DEL to scroll through this text.  Type \\<help-map>\\[help-quit] 
to exit the Help command.)
 
-a PATTERN   Show commands whose name matches the PATTERN (a list of words
-              or a regexp).  See also the `apropos' command.
-b           Display all key bindings.
-c KEYS      Display the command name run by the given key sequence.
-C CODING    Describe the given coding system, or RET for current ones.
-d PATTERN   Show a list of functions, variables, and other items whose
+\\[apropos-command] PATTERN   Show commands whose name matches the PATTERN (a 
list of words
+              or a regexp).  See also \\[apropos].
+\\[describe-bindings]           Display all key bindings.
+\\[describe-key-briefly] KEYS      Display the command name run by the given 
key sequence.
+\\[describe-coding-system] CODING    Describe the given coding system, or RET 
for current ones.
+\\[apropos-documentation] PATTERN   Show a list of functions, variables, and 
other items whose
               documentation matches the PATTERN (a list of words or a regexp).
-e           Go to the *Messages* buffer which logs echo-area messages.
-f FUNCTION  Display documentation for the given function.
-F COMMAND   Show the Emacs manual's section that describes the command.
-g           Display information about the GNU project.
-h           Display the HELLO file which illustrates various scripts.
-i           Start the Info documentation reader: read included manuals.
-I METHOD    Describe a specific input method, or RET for current.
-k KEYS      Display the full documentation for the key sequence.
-K KEYS      Show the Emacs manual's section for the command bound to KEYS.
-l           Show last 300 input keystrokes (lossage).
-L LANG-ENV  Describes a specific language environment, or RET for current.
-m           Display documentation of current minor modes and current major 
mode,
-              including their special commands.
-n           Display news of recent Emacs changes.
-o SYMBOL    Display the given function or variable's documentation and value.
-p TOPIC     Find packages matching a given topic keyword.
-P PACKAGE   Describe the given Emacs Lisp package.
-r           Display the Emacs manual in Info mode.
-R           Prompt for a manual and then display it in Info mode.
-s           Display contents of current syntax table, plus explanations.
-S SYMBOL    Show the section for the given symbol in the Info manual
+\\[view-echo-area-messages]           Go to the *Messages* buffer which logs 
echo-area messages.
+\\[describe-function] FUNCTION  Display documentation for the given function.
+\\[Info-goto-emacs-command-node] COMMAND   Show the Emacs manual's section 
that describes the command.
+\\[describe-gnu-project]           Display information about the GNU project.
+\\[view-hello-file]           Display the HELLO file which illustrates various 
scripts.
+\\[info]           Start the Info documentation reader: read included manuals.
+\\[describe-input-method] METHOD    Describe a specific input method, or RET 
for current.
+\\[describe-key] KEYS      Display the full documentation for the key sequence.
+\\[Info-goto-emacs-key-command-node] KEYS      Show the Emacs manual's section 
for the command bound to KEYS.
+\\[view-lossage]           Show last 300 input keystrokes (lossage).
+\\[describe-language-environment] LANG-ENV  Describe a specific language 
environment, or RET for current.
+\\[describe-mode]           Display documentation of current minor modes and 
current major mode,
+             including their special commands.
+\\[view-emacs-news]           Display news of recent Emacs changes.
+\\[describe-symbol] SYMBOL    Display the given function or variable's 
documentation and value.
+\\[finder-by-keyword] TOPIC     Find packages matching a given topic keyword.
+\\[describe-package] PACKAGE   Describe the given Emacs Lisp package.
+\\[info-emacs-manual]           Display the Emacs manual in Info mode.
+\\[info-display-manual]           Prompt for a manual and then display it in 
Info mode.
+\\[describe-syntax]           Display contents of current syntax table, plus 
explanations.
+\\[info-lookup-symbol] SYMBOL    Show the section for the given symbol in the 
Info manual
               for the programming language used in this buffer.
-t           Start the Emacs learn-by-doing tutorial.
-v VARIABLE  Display the given variable's documentation and value.
-w COMMAND   Display which keystrokes invoke the given command (where-is).
-.           Display any available local help at point in the echo area.
-
-C-a         Information about Emacs.
-C-c         Emacs copying permission (GNU General Public License).
-C-d         Instructions for debugging GNU Emacs.
-C-e         External packages and information about Emacs.
-C-f         Emacs FAQ.
+\\[help-with-tutorial]           Start the Emacs learn-by-doing tutorial.
+\\[describe-variable] VARIABLE  Display the given variable's documentation and 
value.
+\\[where-is] COMMAND   Display which keystrokes invoke the given command 
(where-is).
+\\[display-local-help]           Display any available local help at point in 
the echo area.
+
+\\[about-emacs]         Information about Emacs.
+\\[describe-copying]         Emacs copying permission (GNU General Public 
License).
+\\[view-emacs-debugging]         Instructions for debugging GNU Emacs.
+\\[view-external-packages]         External packages and information about 
Emacs.
+\\[view-emacs-FAQ]         Emacs FAQ.
 C-m         How to order printed Emacs manuals.
 C-n         News of recent Emacs changes.
-C-o         Emacs ordering and distribution information.
-C-p         Info about known Emacs problems.
-C-s         Search forward \"help window\".
-C-t         Emacs TODO list.
-C-w         Information on absence of warranty for GNU Emacs."
+\\[describe-distribution]         Emacs ordering and distribution information.
+\\[view-emacs-problems]         Info about known Emacs problems.
+\\[search-forward-help-for-help]         Search forward \"help window\".
+\\[view-emacs-todo]         Emacs TODO list.
+\\[describe-no-warranty]         Information on absence of warranty for GNU 
Emacs."
   help-map)
 
 
@@ -492,6 +486,15 @@ To record all your input, use `open-dribble-file'."
 
 ;; Key bindings
 
+(defun help--key-description-fontified (keys &optional prefix)
+  "Like `key-description' but add face for \"*Help*\" buffers."
+  ;; We add both the `font-lock-face' and `face' properties here, as this
+  ;; seems to be the only way to get this to work reliably in any
+  ;; buffer.
+  (propertize (key-description keys prefix)
+              'font-lock-face 'help-key-binding
+              'face 'help-key-binding))
+
 (defun describe-bindings (&optional prefix buffer)
   "Display a buffer showing a list of all defined keys, and their definitions.
 The keys are displayed in order of precedence.
@@ -511,7 +514,6 @@ or a buffer name."
     (with-current-buffer (help-buffer)
       (describe-buffer-bindings buffer prefix))))
 
-;; This function used to be in keymap.c.
 (defun describe-bindings-internal (&optional menus prefix)
   "Show a list of all defined keys, and their definitions.
 We put that list in a buffer, and display the buffer.
@@ -559,7 +561,8 @@ If INSERT (the prefix arg) is non-nil, insert the message 
in the buffer."
       (let* ((remapped (command-remapping symbol))
             (keys (where-is-internal
                    symbol overriding-local-map nil nil remapped))
-            (keys (mapconcat 'key-description keys ", "))
+             (keys (mapconcat #'help--key-description-fontified
+                              keys ", "))
             string)
        (setq string
              (if insert
@@ -587,11 +590,11 @@ If INSERT (the prefix arg) is non-nil, insert the message 
in the buffer."
   nil)
 
 (defun help-key-description (key untranslated)
-  (let ((string (key-description key)))
+  (let ((string (help--key-description-fontified key)))
     (if (or (not untranslated)
            (and (eq (aref untranslated 0) ?\e) (not (eq (aref key 0) ?\e))))
        string
-      (let ((otherstring (key-description untranslated)))
+      (let ((otherstring (help--key-description-fontified untranslated)))
        (if (equal string otherstring)
            string
          (format "%s (translated from %s)" string otherstring))))))
@@ -979,7 +982,7 @@ is currently activated with completion."
   "Substitute key descriptions for command names in STRING.
 Each substring of the form \\\\=[COMMAND] is replaced by either a
 keystroke sequence that invokes COMMAND, or \"M-x COMMAND\" if COMMAND
-is not on any keys.
+is not on any keys.  Keybindings will use the face `help-key-binding'.
 
 Each substring of the form \\\\={MAPVAR} is replaced by a summary of
 the value of MAPVAR as a keymap.  This summary is similar to the one
@@ -999,7 +1002,7 @@ into the output, \\\\==\\[ puts \\[ into the output, and 
\\\\==\\=` puts \\=` in
 output.
 
 Return the original STRING if no substitutions are made.
-Otherwise, return a new string (without any text properties)."
+Otherwise, return a new string."
   (when (not (null string))
     ;; KEYMAP is either nil (which means search all the active
     ;; keymaps) or a specified local map (which means search just that
@@ -1053,12 +1056,16 @@ Otherwise, return a new string (without any text 
properties)."
                                 (where-is-internal fun keymap t))))
                   (if (not key)
                       ;; Function is not on any key.
-                      (progn (insert "M-x ")
-                             (goto-char (+ end-point 3))
-                             (delete-char 1))
+                      (let ((op (point)))
+                        (insert "M-x ")
+                        (goto-char (+ end-point 3))
+                        (add-text-properties op (point)
+                                             '( face help-key-binding
+                                                font-lock-face 
help-key-binding))
+                        (delete-char 1))
                     ;; Function is on a key.
                     (delete-char (- end-point (point)))
-                    (insert (key-description key)))))
+                    (insert (help--key-description-fontified key)))))
                ;; 1D. \{foo} is replaced with a summary of the keymap
                ;;            (symbol-value foo).
                ;;     \<foo> just sets the keymap used for \[cmd].
@@ -1172,7 +1179,7 @@ Any inserted text ends in two newlines (used by
                           (concat title
                                   (if prefix
                                       (concat " Starting With "
-                                              (key-description prefix)))
+                                              (help--key-description-fontified 
prefix)))
                                   ":\n"))
                       "key             binding\n"
                       "---             -------\n")))
@@ -1228,7 +1235,11 @@ Return nil if the key sequence is too long."
                                              (= 
help--previous-description-column 32)))
                                     32)
                                    (t 16))))
-    (indent-to description-column 1)
+    ;; Avoid using the `help-keymap' face.
+    (let ((op (point)))
+      (indent-to description-column 1)
+      (set-text-properties op (point) '( face nil
+                                         font-lock-face nil)))
     (setq help--previous-description-column description-column)
     (cond ((symbolp definition)
            (insert (symbol-name definition) "\n"))
@@ -1240,7 +1251,11 @@ Return nil if the key sequence is too long."
 
 (defun help--describe-translation (definition)
   ;; Converted from describe_translation in keymap.c.
-  (indent-to 16 1)
+  ;; Avoid using the `help-keymap' face.
+  (let ((op (point)))
+    (indent-to 16 1)
+    (set-text-properties op (point) '( face nil
+                                      font-lock-face nil)))
   (cond ((symbolp definition)
          (insert (symbol-name definition) "\n"))
         ((or (stringp definition) (vectorp definition))
@@ -1351,9 +1366,9 @@ TRANSL, PARTIAL, SHADOW, NOMENU, MENTION-SHADOW are as in
               (setq end (caar vect))))
           ;; Now START .. END is the range to describe next.
           ;; Insert the string to describe the event START.
-          (insert (key-description (vector start) prefix))
+          (insert (help--key-description-fontified (vector start) prefix))
           (when (not (eq start end))
-            (insert " .. " (key-description (vector end) prefix)))
+            (insert " .. " (help--key-description-fontified (vector end) 
prefix)))
           ;; Print a description of the definition of this character.
           ;; Called function will take care of spacing out far enough
           ;; for alignment purposes.
@@ -1420,7 +1435,7 @@ TRANSL, PARTIAL, SHADOW, NOMENU, MENTION-SHADOW are as in
 ;;             (setq first nil))
 ;;           (when (and prefix (> (length prefix) 0))
 ;;             (insert (format "%s" prefix)))
-;;           (insert (key-description (vector start-idx) prefix))
+;;           (insert (help--key-description-fontified (vector start-idx) 
prefix))
 ;;           ;; Find all consecutive characters or rows that have the
 ;;           ;; same definition.
 ;;           (while (equal (keymap--get-keyelt (aref vector (1+ idx)) nil)
@@ -1433,7 +1448,7 @@ TRANSL, PARTIAL, SHADOW, NOMENU, MENTION-SHADOW are as in
 ;;             (insert " .. ")
 ;;             (when (and prefix (> (length prefix) 0))
 ;;               (insert (format "%s" prefix)))
-;;             (insert (key-description (vector idx) prefix)))
+;;             (insert (help--key-description-fontified (vector idx) prefix)))
 ;;           (if transl
 ;;               (help--describe-translation definition)
 ;;             (help--describe-command definition))
@@ -1924,6 +1939,8 @@ the suggested string to use instead.  See
 (add-function :after command-error-function
               #'help-command-error-confusable-suggestions)
 
+(define-obsolete-function-alias 'help-for-help-internal #'help-for-help "28.1")
+
 
 (provide 'help)
 
diff --git a/lisp/hi-lock.el b/lisp/hi-lock.el
index 0ad499b..68f8cc5 100644
--- a/lisp/hi-lock.el
+++ b/lisp/hi-lock.el
@@ -254,39 +254,25 @@ that older functionality.  This variable avoids multiple 
reminders.")
 Assumption is made if `hi-lock-mode' used in the *scratch* buffer while
 a library is being loaded.")
 
-(defvar hi-lock-menu
-  (let ((map (make-sparse-keymap "Hi Lock")))
-    (define-key-after map [highlight-regexp]
-      '(menu-item "Highlight Regexp..." highlight-regexp
-        :help "Highlight text matching PATTERN (a regexp)."))
-
-    (define-key-after map [highlight-phrase]
-      '(menu-item "Highlight Phrase..." highlight-phrase
-        :help "Highlight text matching PATTERN (a regexp processed to match 
phrases)."))
-
-    (define-key-after map [highlight-lines-matching-regexp]
-      '(menu-item "Highlight Lines..." highlight-lines-matching-regexp
-        :help "Highlight lines containing match of PATTERN (a regexp)."))
-
-    (define-key-after map [highlight-symbol-at-point]
-      '(menu-item "Highlight Symbol at Point" highlight-symbol-at-point
-        :help "Highlight symbol found near point without prompting."))
-
-    (define-key-after map [unhighlight-regexp]
-      '(menu-item "Remove Highlighting..." unhighlight-regexp
-        :help "Remove previously entered highlighting pattern."
-        :enable hi-lock-interactive-patterns))
-
-    (define-key-after map [hi-lock-write-interactive-patterns]
-      '(menu-item "Patterns to Buffer" hi-lock-write-interactive-patterns
-        :help "Insert interactively added REGEXPs into buffer at point."
-        :enable hi-lock-interactive-patterns))
-
-    (define-key-after map [hi-lock-find-patterns]
-      '(menu-item "Patterns from Buffer" hi-lock-find-patterns
-        :help "Use patterns (if any) near top of buffer."))
-    map)
-  "Menu for hi-lock mode.")
+(easy-menu-define hi-lock-menu nil
+  "Menu for hi-lock mode."
+  '("Hi Lock"
+    ["Highlight Regexp..." highlight-regexp
+     :help "Highlight text matching PATTERN (a regexp)."]
+    ["Highlight Phrase..." highlight-phrase
+     :help "Highlight text matching PATTERN (a regexp processed to match 
phrases)."]
+    ["Highlight Lines..." highlight-lines-matching-regexp
+     :help "Highlight lines containing match of PATTERN (a regexp)."]
+    ["Highlight Symbol at Point" highlight-symbol-at-point
+     :help "Highlight symbol found near point without prompting."]
+    ["Remove Highlighting..." unhighlight-regexp
+     :help "Remove previously entered highlighting pattern."
+     :enable hi-lock-interactive-patterns]
+    ["Patterns to Buffer" hi-lock-write-interactive-patterns
+     :help "Insert interactively added REGEXPs into buffer at point."
+     :enable hi-lock-interactive-patterns]
+    ["Patterns from Buffer" hi-lock-find-patterns
+     :help "Use patterns (if any) near top of buffer."]))
 
 (defvar hi-lock-map
   (let ((map (make-sparse-keymap "Hi Lock")))
diff --git a/lisp/htmlfontify.el b/lisp/htmlfontify.el
index bfbe0ee..0c8d534 100644
--- a/lisp/htmlfontify.el
+++ b/lisp/htmlfontify.el
@@ -983,19 +983,18 @@ merged by the user - `hfy-flatten-style' should do this."
                        (:italic         (hfy-slant 'italic))))))
       (setq that (hfy-face-to-style-i next))
       ;;(lwarn t :warning "%S => %S" fn (nconc this that parent))
-      (nconc this parent that))) )
+      (append this parent that))) )
 
-(defun hfy-size-to-int (spec)
+(defun hfy--size-to-int (spec)
   "Convert SPEC, a CSS font-size specifier, to an Emacs :height attribute 
value.
 Used while merging multiple font-size attributes."
-  ;;(message "hfy-size-to-int");;DBUG
-  (list
-   (if (string-match "\\([0-9]+\\)\\(%\\|pt\\)" spec)
-       (cond ((string= "%"  (match-string 2 spec))
-              (/ (string-to-number (match-string 1 spec)) 100.0))
-             ((string= "pt" (match-string 2 spec))
-              (* (string-to-number (match-string 1 spec))    10)))
-     (string-to-number spec))) )
+  ;;(message "hfy--size-to-int");;DBUG
+  (if (string-match "\\([0-9]+\\)\\(%\\|pt\\)" spec)
+      (cond ((string= "%"  (match-string 2 spec))
+             (/ (string-to-number (match-string 1 spec)) 100.0))
+            ((string= "pt" (match-string 2 spec))
+             (* (string-to-number (match-string 1 spec))    10)))
+    (string-to-number spec)) )
 
 ;; size is different, in that in order to get it right at all,
 ;; we have to trawl the inheritance path, accumulating modifiers,
@@ -1006,19 +1005,18 @@ any multiple attributes appropriately.  Currently only 
font-size is merged
 down to a single occurrence - others may need special handling, but I
 haven't encountered them yet.  Returns a `hfy-style-assoc'."
   ;;(message "(hfy-flatten-style %S)" style) ;;DBUG
-  (let ((n        0)
-        (m (list 1))
+  (let ((m (list 1))
         (x      nil)
         (r      nil))
     (dolist (css style)
       (if (string= (car css) "font-size")
           (progn
-            (when (not x) (setq m (nconc m (hfy-size-to-int (cdr css)))))
+            (when (not x) (push (hfy--size-to-int (cdr css)) m))
             (when (string-match "pt" (cdr css)) (setq x t)))
-        (setq r (nconc r (list css)))))
+        (push css r)))
     ;;(message "r: %S" r)
-    (setq  n (apply #'* m))
-    (nconc r (hfy-size (if x (round n) (* n 1.0)))) ))
+    (let ((n (apply #'* m)))
+      (nconc (nreverse r) (hfy-size (if x (round n) (float n)))))))
 
 (defun hfy-face-resolve-face (fn)
   "For FN return a face specification.
@@ -1052,7 +1050,7 @@ See also `hfy-face-to-style-i', `hfy-flatten-style'."
                      ;; text-decoration is not inherited.
                      ;; but it's not wrong and if this ever changes it will
                      ;; be needed, so I think it's better to leave it in? -- v
-                     (nconc final-style '(("text-decoration" . "none"))))))
+                     (push '("text-decoration" . "none") final-style))))
     final-style))
 
 ;; strip redundant bits from a name. Technically, this could result in
diff --git a/lisp/ibuffer.el b/lisp/ibuffer.el
index 6dc1c7e..b484dd7 100644
--- a/lisp/ibuffer.el
+++ b/lisp/ibuffer.el
@@ -364,64 +364,6 @@ directory, like `default-directory'."
                       (regexp :tag "From")
                        (regexp :tag "To"))))
 
-(defvar ibuffer-mode-groups-popup
-  (let ((groups-map (make-sparse-keymap "Filter Groups")))
-    ;; Filter groups
-
-    (define-key-after groups-map [filters-to-filter-group]
-      '(menu-item "Create filter group from current filters..."
-        ibuffer-filters-to-filter-group
-        :enable (and (featurep 'ibuf-ext) ibuffer-filtering-qualifiers)))
-    (define-key-after groups-map [forward-filter-group]
-      '(menu-item "Move point to the next filter group"
-        ibuffer-forward-filter-group))
-    (define-key-after groups-map [backward-filter-group]
-      '(menu-item "Move point to the previous filter group"
-        ibuffer-backward-filter-group))
-    (define-key-after groups-map [jump-to-filter-group]
-      '(menu-item "Move point to a specific filter group..."
-        ibuffer-jump-to-filter-group))
-    (define-key-after groups-map [kill-filter-group]
-      '(menu-item "Kill filter group named..."
-        ibuffer-kill-filter-group
-        :enable (and (featurep 'ibuf-ext) ibuffer-filter-groups)))
-    (define-key-after groups-map [yank-filter-group]
-      '(menu-item "Yank last killed filter group before..."
-        ibuffer-yank-filter-group
-        :enable (and (featurep 'ibuf-ext) ibuffer-filter-group-kill-ring)))
-    (define-key-after groups-map [pop-filter-group]
-      '(menu-item "Remove top filter group"
-        ibuffer-pop-filter-group
-        :enable (and (featurep 'ibuf-ext) ibuffer-filter-groups)))
-    (define-key-after groups-map [clear-filter-groups]
-      '(menu-item "Remove all filter groups"
-        ibuffer-clear-filter-groups
-        :enable (and (featurep 'ibuf-ext) ibuffer-filter-groups)))
-    (define-key-after groups-map [pop-filter-group]
-      '(menu-item "Decompose filter group..."
-        ibuffer-pop-filter-group
-        :help "\"Unmake\" a filter group"
-        :enable (and (featurep 'ibuf-ext) ibuffer-filter-groups)))
-    (define-key-after groups-map [save-filter-groups]
-      '(menu-item "Save current filter groups permanently..."
-        ibuffer-save-filter-groups
-        :enable (and (featurep 'ibuf-ext) ibuffer-filter-groups)
-        :help "Use a mnemonic name to store current filter groups"))
-    (define-key-after groups-map [switch-to-saved-filter-groups]
-      '(menu-item "Restore permanently saved filters..."
-        ibuffer-switch-to-saved-filter-groups
-        :enable (and (featurep 'ibuf-ext) ibuffer-saved-filter-groups)
-        :help "Replace current filters with a saved stack"))
-    (define-key-after groups-map [delete-saved-filter-groups]
-      '(menu-item "Delete permanently saved filter groups..."
-        ibuffer-delete-saved-filter-groups
-        :enable (and (featurep 'ibuf-ext) ibuffer-saved-filter-groups)))
-    (define-key-after groups-map [set-filter-groups-by-mode]
-      '(menu-item "Set current filter groups to filter by mode"
-        ibuffer-set-filter-groups-by-mode))
-
-    groups-map))
-
 (defvar ibuffer--filter-map
   (let ((map (make-sparse-keymap)))
     (define-key map (kbd "RET") 'ibuffer-filter-by-mode)
@@ -588,303 +530,233 @@ directory, like `default-directory'."
     (define-key map (kbd "C-x 5 RET") 'ibuffer-visit-buffer-other-frame)
 
     (define-key map (kbd "/") ibuffer--filter-map)
-
-    (define-key map [menu-bar view]
-      (cons "View" (make-sparse-keymap "View")))
-
-    (define-key-after map [menu-bar view visit-buffer]
-      '(menu-item "View this buffer" ibuffer-visit-buffer))
-    (define-key-after map [menu-bar view visit-buffer-other-window]
-      '(menu-item "View (other window)" ibuffer-visit-buffer-other-window))
-    (define-key-after map [menu-bar view visit-buffer-other-frame]
-      '(menu-item "View (other frame)" ibuffer-visit-buffer-other-frame))
-    (define-key-after map [menu-bar view ibuffer-update]
-      '(menu-item "Update" ibuffer-update
-        :help "Regenerate the list of buffers"))
-    (define-key-after map [menu-bar view switch-format]
-      '(menu-item "Switch display format" ibuffer-switch-format
-        :help "Toggle between available values of `ibuffer-formats'"))
-
-    (define-key-after map [menu-bar view dashes]
-      '("--"))
-
-    (define-key-after map [menu-bar view sort]
-      (cons "Sort" (make-sparse-keymap "Sort")))
-
-    (define-key-after map [menu-bar view sort do-sort-by-major-mode]
-      '(menu-item "Sort by major mode" ibuffer-do-sort-by-major-mode))
-    (define-key-after map [menu-bar view sort do-sort-by-size]
-      '(menu-item "Sort by buffer size" ibuffer-do-sort-by-size))
-    (define-key-after map [menu-bar view sort do-sort-by-alphabetic]
-      '(menu-item "Sort lexicographically" ibuffer-do-sort-by-alphabetic
-        :help "Sort by the alphabetic order of buffer name"))
-    (define-key-after map [menu-bar view sort do-sort-by-recency]
-      '(menu-item "Sort by view time" ibuffer-do-sort-by-recency
-        :help "Sort by the last time the buffer was displayed"))
-    (define-key-after map [menu-bar view sort dashes]
-      '("--"))
-    (define-key-after map [menu-bar view sort invert-sorting]
-      '(menu-item "Reverse sorting order" ibuffer-invert-sorting))
-    (define-key-after map [menu-bar view sort toggle-sorting-mode]
-      '(menu-item "Switch sorting mode" ibuffer-toggle-sorting-mode
-        :help "Switch between the various sorting criteria"))
-
-    (define-key-after map [menu-bar view filter]
-      (cons "Filter" (make-sparse-keymap "Filter")))
-
-    (define-key-after map [menu-bar view filter filter-disable]
-      '(menu-item "Disable all filtering" ibuffer-filter-disable
-        :enable (and (featurep 'ibuf-ext) ibuffer-filtering-qualifiers)))
-    (define-key-after map [menu-bar view filter filter-by-mode]
-      '(menu-item "Add filter by any major mode..." ibuffer-filter-by-mode))
-    (define-key-after map [menu-bar view filter filter-by-used-mode]
-      '(menu-item "Add filter by a major mode in use..."
-        ibuffer-filter-by-used-mode))
-    (define-key-after map [menu-bar view filter filter-by-derived-mode]
-      '(menu-item "Add filter by derived mode..."
-                  ibuffer-filter-by-derived-mode))
-    (define-key-after map [menu-bar view filter filter-by-name]
-      '(menu-item "Add filter by buffer name..." ibuffer-filter-by-name))
-    (define-key-after map [menu-bar view filter filter-by-starred-name]
-      '(menu-item "Add filter by starred buffer name..."
-                  ibuffer-filter-by-starred-name
-                  :help "List buffers whose names begin with a star"))
-    (define-key-after map [menu-bar view filter filter-by-filename]
-      '(menu-item "Add filter by full filename..." ibuffer-filter-by-filename
-                  :help
-                  (concat "For a buffer associated with file `/a/b/c.d', "
-                          "list buffer if a given pattern matches 
`/a/b/c.d'")))
-    (define-key-after map [menu-bar view filter filter-by-basename]
-      '(menu-item "Add filter by file basename..."
-                  ibuffer-filter-by-basename
-                  :help (concat "For a buffer associated with file `/a/b/c.d', 
"
-                                "list buffer if a given pattern matches 
`c.d'")))
-    (define-key-after map [menu-bar view filter filter-by-file-extension]
-      '(menu-item "Add filter by file name extension..."
-                  ibuffer-filter-by-file-extension
-                  :help (concat "For a buffer associated with file `/a/b/c.d', 
"
-                                "list buffer if a given pattern matches `d'")))
-    (define-key-after map [menu-bar view filter filter-by-directory]
-      '(menu-item "Add filter by filename's directory..."
-                  ibuffer-filter-by-directory
-                  :help
-                  (concat "For a buffer associated with file `/a/b/c.d', "
-                          "list buffer if a given pattern matches `/a/b'")))
-    (define-key-after map [menu-bar view filter filter-by-size-lt]
-      '(menu-item "Add filter by size less than..." ibuffer-filter-by-size-lt))
-    (define-key-after map [menu-bar view filter filter-by-size-gt]
-      '(menu-item "Add filter by size greater than..."
-        ibuffer-filter-by-size-gt))
-    (define-key-after map [menu-bar view filter filter-by-modified]
-      '(menu-item "Add filter by modified buffer" ibuffer-filter-by-modified
-                  :help "List buffers that are marked as modified"))
-    (define-key-after map [menu-bar view filter filter-by-visiting-file]
-      '(menu-item "Add filter by buffer visiting a file"
-                  ibuffer-filter-by-visiting-file
-                  :help "List buffers that are visiting files"))
-    (define-key-after map [menu-bar view filter filter-by-content]
-      '(menu-item "Add filter by content (regexp)..."
-        ibuffer-filter-by-content))
-    (define-key-after map [menu-bar view filter filter-by-predicate]
-      '(menu-item "Add filter by Lisp predicate..."
-        ibuffer-filter-by-predicate))
-    (define-key-after map [menu-bar view filter pop-filter]
-      '(menu-item "Remove top filter" ibuffer-pop-filter
-        :enable (and (featurep 'ibuf-ext) ibuffer-filtering-qualifiers)))
-    (define-key-after map [menu-bar view filter and-filter]
-      '(menu-item "AND top two filters" ibuffer-and-filter
-        :enable (and (featurep 'ibuf-ext) ibuffer-filtering-qualifiers
-                     (cdr ibuffer-filtering-qualifiers))
-        :help
-        "Create a new filter which is the logical AND of the top two filters"))
-    (define-key-after map [menu-bar view filter or-filter]
-      '(menu-item "OR top two filters" ibuffer-or-filter
-        :enable (and (featurep 'ibuf-ext) ibuffer-filtering-qualifiers
-                     (cdr ibuffer-filtering-qualifiers))
-        :help
-        "Create a new filter which is the logical OR of the top two filters"))
-    (define-key-after map [menu-bar view filter negate-filter]
-      '(menu-item "Negate top filter" ibuffer-negate-filter
-        :enable (and (featurep 'ibuf-ext) ibuffer-filtering-qualifiers)))
-    (define-key-after map [menu-bar view filter decompose-filter]
-      '(menu-item "Decompose top filter" ibuffer-decompose-filter
-        :enable (and (featurep 'ibuf-ext)
-                     (memq (car ibuffer-filtering-qualifiers) '(or saved not)))
-        :help "Break down a complex filter like OR or NOT"))
-    (define-key-after map [menu-bar view filter exchange-filters]
-      '(menu-item "Swap top two filters" ibuffer-exchange-filters
-        :enable (and (featurep 'ibuf-ext) ibuffer-filtering-qualifiers
-                     (cdr ibuffer-filtering-qualifiers))))
-    (define-key-after map [menu-bar view filter save-filters]
-      '(menu-item "Save current filters permanently..." ibuffer-save-filters
-        :enable (and (featurep 'ibuf-ext) ibuffer-filtering-qualifiers)
-        :help "Use a mnemonic name to store current filter stack"))
-    (define-key-after map [menu-bar view filter switch-to-saved-filters]
-      '(menu-item "Restore permanently saved filters..."
-        ibuffer-switch-to-saved-filters
-        :enable (and (featurep 'ibuf-ext) ibuffer-saved-filters)
-        :help "Replace current filters with a saved stack"))
-    (define-key-after map [menu-bar view filter add-saved-filters]
-      '(menu-item "Add to permanently saved filters..."
-        ibuffer-add-saved-filters
-        :enable (and (featurep 'ibuf-ext) ibuffer-filtering-qualifiers)
-        :help "Include already saved stack with current filters"))
-    (define-key-after map [menu-bar view filter delete-saved-filters]
-      '(menu-item "Delete permanently saved filters..."
-        ibuffer-delete-saved-filters
-        :enable (and (featurep 'ibuf-ext) ibuffer-saved-filters)))
-
-    (define-key-after map [menu-bar view filter-groups]
-      (cons "Filter Groups" ibuffer-mode-groups-popup))
-
-    (define-key-after map [menu-bar view dashes2]
-      '("--"))
-    (define-key-after map [menu-bar view auto-mode]
-      '(menu-item "Auto Mode" ibuffer-auto-mode
-        :button (:toggle . ibuffer-auto-mode)
-        :help "Attempt to automatically update the Ibuffer buffer"))
-
-    (define-key-after map [menu-bar mark]
-      (cons "Mark" (make-sparse-keymap "Mark")))
-
-    (define-key-after map [menu-bar mark toggle-marks]
-      '(menu-item "Toggle marks" ibuffer-toggle-marks
-        :help "Unmark marked buffers, and mark unmarked buffers"))
-    (define-key-after map [menu-bar mark change-marks]
-      '(menu-item "Change marks" ibuffer-change-marks
-        :help "Change OLD mark for marked buffers with NEW"))
-    (define-key-after map [menu-bar mark mark-forward]
-      '(menu-item "Mark" ibuffer-mark-forward
-        :help "Mark the buffer at point"))
-    (define-key-after map [menu-bar mark unmark-forward]
-      '(menu-item "Unmark" ibuffer-unmark-forward
-        :help "Unmark the buffer at point"))
-    (define-key-after map [menu-bar mark mark-by-mode]
-      '(menu-item "Mark by mode..." ibuffer-mark-by-mode
-        :help "Mark all buffers in a particular major mode"))
-    (define-key-after map [menu-bar mark mark-modified-buffers]
-      '(menu-item "Mark modified buffers" ibuffer-mark-modified-buffers
-        :help "Mark all buffers which have been modified"))
-    (define-key-after map [menu-bar mark mark-unsaved-buffers]
-      '(menu-item "Mark unsaved buffers" ibuffer-mark-unsaved-buffers
-        :help "Mark all buffers which have a file and are modified"))
-    (define-key-after map [menu-bar mark mark-read-only-buffers]
-      '(menu-item "Mark read-only buffers" ibuffer-mark-read-only-buffers
-        :help "Mark all buffers which are read-only"))
-    (define-key-after map [menu-bar mark mark-special-buffers]
-      '(menu-item "Mark special buffers" ibuffer-mark-special-buffers
-        :help "Mark all buffers whose name begins with a *"))
-    (define-key-after map [menu-bar mark mark-dired-buffers]
-      '(menu-item "Mark dired buffers" ibuffer-mark-dired-buffers
-        :help "Mark buffers in dired-mode"))
-    (define-key-after map [menu-bar mark mark-dissociated-buffers]
-      '(menu-item "Mark dissociated buffers" ibuffer-mark-dissociated-buffers
-        :help "Mark buffers with a non-existent associated file"))
-    (define-key-after map [menu-bar mark mark-help-buffers]
-      '(menu-item "Mark help buffers" ibuffer-mark-help-buffers
-        :help "Mark buffers in help-mode"))
-    (define-key-after map [menu-bar mark mark-compressed-file-buffers]
-      '(menu-item "Mark compressed file buffers"
-        ibuffer-mark-compressed-file-buffers
-        :help "Mark buffers which have a file that is compressed"))
-    (define-key-after map [menu-bar mark mark-old-buffers]
-      '(menu-item "Mark old buffers" ibuffer-mark-old-buffers
-        :help "Mark buffers which have not been viewed recently"))
-    (define-key-after map [menu-bar mark unmark-all]
-      '(menu-item "Unmark All" ibuffer-unmark-all))
-    (define-key-after map [menu-bar mark unmark-all-marks]
-      '(menu-item "Unmark All buffers" ibuffer-unmark-all-marks))
-
-    (define-key-after map [menu-bar mark dashes]
-      '("--"))
-
-    (define-key-after map [menu-bar mark mark-by-name-regexp]
-      '(menu-item "Mark by buffer name (regexp)..." ibuffer-mark-by-name-regexp
-        :help "Mark buffers whose name matches a regexp"))
-    (define-key-after map [menu-bar mark mark-by-mode-regexp]
-      '(menu-item "Mark by major mode (regexp)..." ibuffer-mark-by-mode-regexp
-        :help "Mark buffers whose major mode name matches a regexp"))
-    (define-key-after map [menu-bar mark mark-by-file-name-regexp]
-      '(menu-item "Mark by file name (regexp)..."
-        ibuffer-mark-by-file-name-regexp
-        :help "Mark buffers whose file name matches a regexp"))
-    (define-key-after map [menu-bar mark ibuffer-mark-by-content-regexp]
-      '(menu-item "Mark by content (regexp)..."
-        ibuffer-mark-by-content-regexp
-        :help "Mark buffers whose content matches a regexp"))
-    (define-key-after map [menu-bar mark mark-by-locked]
-      '(menu-item "Mark by locked buffers..." ibuffer-mark-by-locked
-        :help "Mark all locked buffers"))
-
     map))
 
-(defvar ibuffer-mode-operate-map
-  (let ((operate-map (make-sparse-keymap "Operate")))
-    (define-key-after operate-map [do-view]
-      '(menu-item "View" ibuffer-do-view))
-    (define-key-after operate-map [do-view-other-frame]
-      '(menu-item "View (separate frame)" ibuffer-do-view-other-frame))
-    (define-key-after operate-map [do-save]
-      '(menu-item "Save" ibuffer-do-save))
-    (define-key-after operate-map [do-replace-regexp]
-      '(menu-item "Replace (regexp)..." ibuffer-do-replace-regexp
-        :help "Replace text inside marked buffers"))
-    (define-key-after operate-map [do-query-replace]
-      '(menu-item "Query Replace..." ibuffer-do-query-replace
-        :help "Replace text in marked buffers, asking each time"))
-    (define-key-after operate-map [do-query-replace-regexp]
-      '(menu-item "Query Replace (regexp)..." ibuffer-do-query-replace-regexp
-        :help "Replace text in marked buffers by regexp, asking each time"))
-    (define-key-after operate-map [do-print]
-      '(menu-item "Print" ibuffer-do-print))
-    (define-key-after operate-map [do-toggle-modified]
-      '(menu-item "Toggle modification flag" ibuffer-do-toggle-modified))
-    (define-key-after operate-map [do-toggle-read-only]
-      '(menu-item "Toggle read-only flag" ibuffer-do-toggle-read-only))
-    (define-key-after operate-map [do-toggle-lock]
-      '(menu-item "Toggle lock flag" ibuffer-do-toggle-lock))
-    (define-key-after operate-map [do-revert]
-      '(menu-item "Revert" ibuffer-do-revert
-        :help "Revert marked buffers to their associated file"))
-    (define-key-after operate-map [do-rename-uniquely]
-      '(menu-item "Rename Uniquely" ibuffer-do-rename-uniquely
-        :help "Rename marked buffers to a new, unique name"))
-    (define-key-after operate-map [do-delete]
-      '(menu-item "Kill" ibuffer-do-delete))
-    (define-key-after operate-map [do-occur]
-      '(menu-item "List lines matching..." ibuffer-do-occur
-        :help "View all lines in marked buffers matching a regexp"))
-    (define-key-after operate-map [do-shell-command-pipe]
-      '(menu-item "Pipe to shell command..." ibuffer-do-shell-command-pipe
-        :help "For each marked buffer, send its contents to a shell command"))
-    (define-key-after operate-map [do-shell-command-pipe-replace]
-      '(menu-item "Pipe to shell command (replace)..." 
ibuffer-do-shell-command-pipe-replace
-        :help "For each marked buffer, replace its contents with output of 
shell command"))
-    (define-key-after operate-map [do-shell-command-file]
-      '(menu-item "Shell command on buffer's file..." 
ibuffer-do-shell-command-file
-        :help "For each marked buffer, run a shell command with its file as 
argument"))
-    (define-key-after operate-map [do-eval]
-      '(menu-item "Eval..." ibuffer-do-eval
-        :help "Evaluate a Lisp form in each marked buffer"))
-    (define-key-after operate-map [do-view-and-eval]
-      '(menu-item "Eval (viewing buffer)..." ibuffer-do-view-and-eval
-        :help "Evaluate a Lisp form in each marked buffer while viewing it"))
-    (define-key-after operate-map [diff-with-file]
-      '(menu-item "Diff with file" ibuffer-diff-with-file
-                  :help "View the differences between this buffer and its 
file"))
-
-    operate-map))
-
-(define-key ibuffer-mode-groups-popup [kill-filter-group]
-  '(menu-item "Kill filter group"
-             ibuffer-kill-line
-             :enable (and (featurep 'ibuf-ext)
-                          ibuffer-filter-groups)))
-(define-key ibuffer-mode-groups-popup [yank-filter-group]
-  '(menu-item "Yank last killed filter group"
-             ibuffer-yank
-             :enable (and (featurep 'ibuf-ext)
-                          ibuffer-filter-group-kill-ring)))
+(defun ibuffer-mode--groups-menu-definition (&optional is-popup)
+  "Build the `ibuffer' \"Filter\" menu.  Internal."
+  `("Filter Groups"
+    ["Create filter group from current filters..."
+     ibuffer-filters-to-filter-group
+     :enable (and (featurep 'ibuf-ext) ibuffer-filtering-qualifiers)]
+    ["Move point to the next filter group"
+     ibuffer-forward-filter-group]
+    ["Move point to the previous filter group"
+     ibuffer-backward-filter-group]
+    ["Move point to a specific filter group..."
+     ibuffer-jump-to-filter-group]
+    ,@(if is-popup
+          '(["Kill filter group"
+             ibuffer-kill-line
+             :enable (and (featurep 'ibuf-ext)
+                          ibuffer-filter-groups)]
+            ["Yank last killed filter group"
+             ibuffer-yank
+             :enable (and (featurep 'ibuf-ext)
+                          ibuffer-filter-group-kill-ring)])
+      '(["Kill filter group named..."
+         ibuffer-kill-filter-group
+         :enable (and (featurep 'ibuf-ext) ibuffer-filter-groups)]
+        ["Yank last killed filter group before..."
+         ibuffer-yank-filter-group
+         :enable (and (featurep 'ibuf-ext) ibuffer-filter-group-kill-ring)]))
+    ["Remove top filter group"
+     ibuffer-pop-filter-group
+     :enable (and (featurep 'ibuf-ext) ibuffer-filter-groups)]
+    ["Remove all filter groups"
+     ibuffer-clear-filter-groups
+     :enable (and (featurep 'ibuf-ext) ibuffer-filter-groups)]
+    ["Decompose filter group..."
+     ibuffer-pop-filter-group
+     :help "\"Unmake\" a filter group"
+     :enable (and (featurep 'ibuf-ext) ibuffer-filter-groups)]
+    ["Save current filter groups permanently..."
+     ibuffer-save-filter-groups
+     :enable (and (featurep 'ibuf-ext) ibuffer-filter-groups)
+     :help "Use a mnemonic name to store current filter groups"]
+    ["Restore permanently saved filters..."
+     ibuffer-switch-to-saved-filter-groups
+     :enable (and (featurep 'ibuf-ext) ibuffer-saved-filter-groups)
+     :help "Replace current filters with a saved stack"]
+    ["Delete permanently saved filter groups..."
+     ibuffer-delete-saved-filter-groups
+     :enable (and (featurep 'ibuf-ext) ibuffer-saved-filter-groups)]
+    ["Set current filter groups to filter by mode"
+     ibuffer-set-filter-groups-by-mode]))
+
+(easy-menu-define ibuffer-mode-groups-popup nil
+  "Menu for `ibuffer'."
+  (ibuffer-mode--groups-menu-definition 'is-popup))
+
+(easy-menu-define ibuffer-mode-mark-menu ibuffer-mode-map
+  "Mark menu for `ibuffer'."
+  '("Mark"
+    ["Toggle marks" ibuffer-toggle-marks
+     :help "Unmark marked buffers, and mark unmarked buffers"]
+    ["Change marks" ibuffer-change-marks
+     :help "Change OLD mark for marked buffers with NEW"]
+    ["Mark" ibuffer-mark-forward
+     :help "Mark the buffer at point"]
+    ["Unmark" ibuffer-unmark-forward
+     :help "Unmark the buffer at point"]
+    ["Mark by mode..." ibuffer-mark-by-mode
+     :help "Mark all buffers in a particular major mode"]
+    ["Mark modified buffers" ibuffer-mark-modified-buffers
+     :help "Mark all buffers which have been modified"]
+    ["Mark unsaved buffers" ibuffer-mark-unsaved-buffers
+     :help "Mark all buffers which have a file and are modified"]
+    ["Mark read-only buffers" ibuffer-mark-read-only-buffers
+     :help "Mark all buffers which are read-only"]
+    ["Mark special buffers" ibuffer-mark-special-buffers
+     :help "Mark all buffers whose name begins with a *"]
+    ["Mark dired buffers" ibuffer-mark-dired-buffers
+     :help "Mark buffers in dired-mode"]
+    ["Mark dissociated buffers" ibuffer-mark-dissociated-buffers
+     :help "Mark buffers with a non-existent associated file"]
+    ["Mark help buffers" ibuffer-mark-help-buffers
+     :help "Mark buffers in help-mode"]
+    ["Mark compressed file buffers" ibuffer-mark-compressed-file-buffers
+     :help "Mark buffers which have a file that is compressed"]
+    ["Mark old buffers" ibuffer-mark-old-buffers
+     :help "Mark buffers which have not been viewed recently"]
+    ["Unmark All" ibuffer-unmark-all]
+    ["Unmark All buffers" ibuffer-unmark-all-marks]
+    "---"
+    ["Mark by buffer name (regexp)..." ibuffer-mark-by-name-regexp
+     :help "Mark buffers whose name matches a regexp"]
+    ["Mark by major mode (regexp)..." ibuffer-mark-by-mode-regexp
+     :help "Mark buffers whose major mode name matches a regexp"]
+    ["Mark by file name (regexp)..." ibuffer-mark-by-file-name-regexp
+     :help "Mark buffers whose file name matches a regexp"]
+    ["Mark by content (regexp)..." ibuffer-mark-by-content-regexp
+     :help "Mark buffers whose content matches a regexp"]
+    ["Mark by locked buffers..." ibuffer-mark-by-locked
+     :help "Mark all locked buffers"]))
+
+(easy-menu-define ibuffer-mode-view-menu ibuffer-mode-map
+  "View menu for `ibuffer'."
+  `("View"
+    ["View this buffer" ibuffer-visit-buffer]
+    ["View (other window)" ibuffer-visit-buffer-other-window]
+    ["View (other frame)" ibuffer-visit-buffer-other-frame]
+    ["Update" ibuffer-update
+     :help "Regenerate the list of buffers"]
+    ["Switch display format" ibuffer-switch-format
+     :help "Toggle between available values of `ibuffer-formats'"]
+    "---"
+    ("Sort"
+     ["Sort by major mode" ibuffer-do-sort-by-major-mode]
+     ["Sort by buffer size" ibuffer-do-sort-by-size]
+     ["Sort lexicographically" ibuffer-do-sort-by-alphabetic
+      :help "Sort by the alphabetic order of buffer name"]
+     ["Sort by view time" ibuffer-do-sort-by-recency
+      :help "Sort by the last time the buffer was displayed"]
+     "---"
+     ["Reverse sorting order" ibuffer-invert-sorting]
+     ["Switch sorting mode" ibuffer-toggle-sorting-mode
+      :help "Switch between the various sorting criteria"])
+    ("Filter"
+     ["Disable all filtering" ibuffer-filter-disable
+      :enable (and (featurep 'ibuf-ext) ibuffer-filtering-qualifiers)]
+     ["Add filter by any major mode..." ibuffer-filter-by-mode]
+     ["Add filter by a major mode in use..." ibuffer-filter-by-used-mode]
+     ["Add filter by derived mode..." ibuffer-filter-by-derived-mode]
+     ["Add filter by buffer name..." ibuffer-filter-by-name]
+     ["Add filter by starred buffer name..." ibuffer-filter-by-starred-name
+      :help "List buffers whose names begin with a star"]
+     ["Add filter by full filename..." ibuffer-filter-by-filename
+      :help (concat "For a buffer associated with file `/a/b/c.d', "
+                    "list buffer if a given pattern matches `/a/b/c.d'")]
+     ["Add filter by file basename..." ibuffer-filter-by-basename
+      :help (concat "For a buffer associated with file `/a/b/c.d', "
+                    "list buffer if a given pattern matches `c.d'")]
+     ["Add filter by file name extension..." ibuffer-filter-by-file-extension
+      :help (concat "For a buffer associated with file `/a/b/c.d', "
+                    "list buffer if a given pattern matches `d'")]
+     ["Add filter by filename's directory..." ibuffer-filter-by-directory
+      :help (concat "For a buffer associated with file `/a/b/c.d', "
+                    "list buffer if a given pattern matches `/a/b'")]
+     ["Add filter by size less than..." ibuffer-filter-by-size-lt]
+     ["Add filter by size greater than..." ibuffer-filter-by-size-gt]
+     ["Add filter by modified buffer" ibuffer-filter-by-modified
+      :help "List buffers that are marked as modified"]
+     ["Add filter by buffer visiting a file" ibuffer-filter-by-visiting-file
+      :help "List buffers that are visiting files"]
+     ["Add filter by content (regexp)..." ibuffer-filter-by-content]
+     ["Add filter by Lisp predicate..." ibuffer-filter-by-predicate]
+     ["Remove top filter" ibuffer-pop-filter
+      :enable (and (featurep 'ibuf-ext) ibuffer-filtering-qualifiers)]
+     ["AND top two filters" ibuffer-and-filter
+      :enable (and (featurep 'ibuf-ext) ibuffer-filtering-qualifiers
+                   (cdr ibuffer-filtering-qualifiers))
+      :help "Create a new filter which is the logical AND of the top two 
filters"]
+     ["OR top two filters" ibuffer-or-filter
+      :enable (and (featurep 'ibuf-ext) ibuffer-filtering-qualifiers
+                   (cdr ibuffer-filtering-qualifiers))
+      :help "Create a new filter which is the logical OR of the top two 
filters"]
+     ["Negate top filter" ibuffer-negate-filter
+      :enable (and (featurep 'ibuf-ext) ibuffer-filtering-qualifiers)]
+     ["Decompose top filter" ibuffer-decompose-filter
+      :enable (and (featurep 'ibuf-ext)
+                   (memq (car ibuffer-filtering-qualifiers) '(or saved not)))
+      :help "Break down a complex filter like OR or NOT"]
+     ["Swap top two filters" ibuffer-exchange-filters
+      :enable (and (featurep 'ibuf-ext) ibuffer-filtering-qualifiers
+                   (cdr ibuffer-filtering-qualifiers))]
+     ["Save current filters permanently..." ibuffer-save-filters
+      :enable (and (featurep 'ibuf-ext) ibuffer-filtering-qualifiers)
+      :help "Use a mnemonic name to store current filter stack"]
+     ["Restore permanently saved filters..." ibuffer-switch-to-saved-filters
+      :enable (and (featurep 'ibuf-ext) ibuffer-saved-filters)
+      :help "Replace current filters with a saved stack"]
+     ["Add to permanently saved filters..." ibuffer-add-saved-filters
+      :enable (and (featurep 'ibuf-ext) ibuffer-filtering-qualifiers)
+      :help "Include already saved stack with current filters"]
+     ["Delete permanently saved filters..." ibuffer-delete-saved-filters
+      :enable (and (featurep 'ibuf-ext) ibuffer-saved-filters)])
+    ;; The "Filter Groups" menu:
+    ,(ibuffer-mode--groups-menu-definition)
+    "---"
+    ["Auto Mode" ibuffer-auto-mode
+     :style toggle
+     :selected ibuffer-auto-mode
+     :help "Attempt to automatically update the Ibuffer buffer"]))
+
+(define-obsolete-variable-alias 'ibuffer-mode-operate-map 
'ibuffer-mode-operate-menu "28.1")
+(easy-menu-define ibuffer-mode-operate-menu ibuffer-mode-map
+  "Operate menu for `ibuffer'."
+  '("Operate"
+    ["View" ibuffer-do-view]
+    ["View (separate frame)" ibuffer-do-view-other-frame]
+    ["Save" ibuffer-do-save]
+    ["Replace (regexp)..." ibuffer-do-replace-regexp
+     :help "Replace text inside marked buffers"]
+    ["Query Replace..." ibuffer-do-query-replace
+     :help "Replace text in marked buffers, asking each time"]
+    ["Query Replace (regexp)..." ibuffer-do-query-replace-regexp
+     :help "Replace text in marked buffers by regexp, asking each time"]
+    ["Print" ibuffer-do-print]
+    ["Toggle modification flag" ibuffer-do-toggle-modified]
+    ["Toggle read-only flag" ibuffer-do-toggle-read-only]
+    ["Toggle lock flag" ibuffer-do-toggle-lock]
+    ["Revert" ibuffer-do-revert
+     :help "Revert marked buffers to their associated file"]
+    ["Rename Uniquely" ibuffer-do-rename-uniquely
+     :help "Rename marked buffers to a new, unique name"]
+    ["Kill" ibuffer-do-delete]
+    ["List lines matching..." ibuffer-do-occur
+     :help "View all lines in marked buffers matching a regexp"]
+    ["Pipe to shell command..." ibuffer-do-shell-command-pipe
+     :help "For each marked buffer, send its contents to a shell command"]
+    ["Pipe to shell command (replace)..." ibuffer-do-shell-command-pipe-replace
+     :help "For each marked buffer, replace its contents with output of shell 
command"]
+    ["Shell command on buffer's file..." ibuffer-do-shell-command-file
+     :help "For each marked buffer, run a shell command with its file as 
argument"]
+    ["Eval..." ibuffer-do-eval
+     :help "Evaluate a Lisp form in each marked buffer"]
+    ["Eval (viewing buffer)..." ibuffer-do-view-and-eval
+     :help "Evaluate a Lisp form in each marked buffer while viewing it"]
+    ["Diff with file" ibuffer-diff-with-file
+     :help "View the differences between this buffer and its file"]))
 
 (defvar ibuffer-name-map
   (let ((map (make-sparse-keymap)))
@@ -1025,7 +897,7 @@ width and the longest string in LIST."
                (goto-char eventpt)
                (ibuffer-set-mark ibuffer-marked-char))
              (save-excursion
-               (popup-menu ibuffer-mode-operate-map)))))
+                (popup-menu ibuffer-mode-operate-menu)))))
       (setq buffer-read-only t)
       (if (= eventpt (point))
          (goto-char origpt)))))
@@ -2425,7 +2297,7 @@ buffers which are visiting a file."
 (defun ibuffer (&optional other-window-p name qualifiers noselect
                          shrink filter-groups formats)
   "Begin using Ibuffer to edit a list of buffers.
-Type `h' after entering ibuffer for more information.
+Type \\<ibuffer-mode-map>\\[describe-mode] after entering ibuffer for more 
information.
 
 All arguments are optional.
 OTHER-WINDOW-P says to use another window.
@@ -2707,7 +2579,7 @@ will be inserted before the group at point."
   (setq buffer-read-only t)
   (buffer-disable-undo)
   (setq truncate-lines ibuffer-truncate-lines)
-  ;; This makes things less ugly for Emacs 21 users with a non-nil
+  ;; This makes things less ugly for users with a non-nil
   ;; `show-trailing-whitespace'.
   (setq show-trailing-whitespace nil)
   ;; disable `show-paren-mode' buffer-locally
@@ -2734,7 +2606,6 @@ will be inserted before the group at point."
   (setq-local ibuffer-tmp-hide-regexps nil)
   (setq-local ibuffer-tmp-show-regexps nil)
   (define-key ibuffer-mode-map [menu-bar edit] 'undefined)
-  (define-key ibuffer-mode-map [menu-bar operate] (cons "Operate" 
ibuffer-mode-operate-map))
   (ibuffer-update-format)
   (when ibuffer-default-directory
     (setq default-directory ibuffer-default-directory))
diff --git a/lisp/ido.el b/lisp/ido.el
index 3ed0d95..9362904 100644
--- a/lisp/ido.el
+++ b/lisp/ido.el
@@ -1746,7 +1746,7 @@ is enabled then some keybindings are changed in the 
keymap."
                       ido-max-file-prompt-width))
          (literal (and (boundp 'ido-find-literal) ido-find-literal "(literal) 
"))
          (vc-off (and ido-saved-vc-hb (not vc-handled-backends) "[-VC] "))
-         (prefix nil)
+         ;; (prefix nil)
          (rule ido-rewrite-file-prompt-rules))
       (let ((case-fold-search nil))
        (while rule
@@ -1762,7 +1762,7 @@ is enabled then some keybindings are changed in the 
keymap."
              ; (if ido-process-ignore-lists "" "&")
              (or literal "")
              (or vc-off  "")
-             (or prefix "")
+             ;; (or prefix "")
              (let ((l (length dirname)))
                (if (and max-width (> max-width 0) (> l max-width))
                    (let* ((s (substring dirname (- max-width)))
diff --git a/lisp/iimage.el b/lisp/iimage.el
index cc1461d..192530a 100644
--- a/lisp/iimage.el
+++ b/lisp/iimage.el
@@ -1,4 +1,4 @@
-;;; iimage.el --- Inline image minor mode.
+;;; iimage.el --- Inline image minor mode.  -*- lexical-binding: t -*-
 
 ;; Copyright (C) 2004-2021 Free Software Foundation, Inc.
 
@@ -51,8 +51,7 @@
 
 (defcustom iimage-mode-image-search-path nil
   "List of directories to search for image files for iimage-mode."
-  :type '(choice (const nil) (repeat directory))
-  :group 'iimage)
+  :type '(choice (const nil) (repeat directory)))
 
 (defvar iimage-mode-image-filename-regex
   (concat "[-+./_0-9a-zA-Z]+\\."
@@ -74,14 +73,12 @@ Examples of image filename patterns to match:
     \\=`file://foo.png\\='
     \\[\\[foo.gif]]
     <foo.png>
-     foo.JPG
-"
-  :type '(alist :key-type regexp :value-type integer)
-  :group 'iimage)
+     foo.JPG"
+  :type '(alist :key-type regexp :value-type integer))
 
 (defvar iimage-mode-map
   (let ((map (make-sparse-keymap)))
-    (define-key map "\C-l" 'iimage-recenter)
+    (define-key map "\C-l" #'iimage-recenter)
     map)
   "Keymap used in `iimage-mode'.")
 
diff --git a/lisp/image-dired.el b/lisp/image-dired.el
index 48f9cd0..2509ecf 100644
--- a/lisp/image-dired.el
+++ b/lisp/image-dired.el
@@ -67,9 +67,9 @@
 ;;
 ;; * For `image-dired-get-exif-data' and `image-dired-set-exif-data' to work,
 ;; the command line tool `exiftool' is needed.  It can be found here:
-;; http://www.sno.phy.queensu.ca/~phil/exiftool/.  These two functions
-;; are, among other things, used for writing comments to image files
-;; using `image-dired-thumbnail-set-image-description' and to create
+;; https://exiftool.org/.  These two functions are, among other
+;; things, used for writing comments to image files using
+;; `image-dired-thumbnail-set-image-description' and to create
 ;; "unique" file names using `image-dired-get-exif-file-name' (used by
 ;; `image-dired-copy-with-exif-file-name').
 ;;
@@ -2553,7 +2553,6 @@ easy-to-use form."
   (let ((files (dired-get-marked-files)))
     (pop-to-buffer-same-window "*Image-Dired Edit Meta Data*")
     (kill-all-local-variables)
-    (make-local-variable 'widget-example-repeat)
     (let ((inhibit-read-only t))
       (erase-buffer))
     (remove-overlays)
diff --git a/lisp/image-mode.el b/lisp/image-mode.el
index 9ed295e..2de16cb 100644
--- a/lisp/image-mode.el
+++ b/lisp/image-mode.el
@@ -95,6 +95,9 @@ Its value should be one of the following:
 (defvar-local image-transform-rotation 0.0
   "Rotation angle for the image in the current Image mode buffer.")
 
+(defvar-local image--transform-smoothing nil
+  "Whether to use transform smoothing.")
+
 (defvar image-transform-right-angle-fudge 0.0001
   "Snap distance to a multiple of a right angle.
 There's no deep theory behind the default value, it should just
@@ -457,6 +460,7 @@ call."
     (define-key map "sb" 'image-transform-fit-both)
     (define-key map "ss" 'image-transform-set-scale)
     (define-key map "sr" 'image-transform-set-rotation)
+    (define-key map "sm" 'image-transform-set-smoothing)
     (define-key map "so" 'image-transform-original)
     (define-key map "s0" 'image-transform-reset)
 
@@ -523,6 +527,8 @@ call."
         :help "Rotate the image"]
        ["Set Rotation..." image-transform-set-rotation
         :help "Set rotation angle of the image"]
+        ["Set Smoothing..." image-transform-set-smoothing
+        :help "Toggle smoothing"]
        ["Original Size" image-transform-original
         :help "Reset image to actual size"]
        ["Reset to Default Size" image-transform-reset
@@ -858,7 +864,9 @@ was inserted."
       (setq image-transform-rotation
             (or (exif-orientation
                  (ignore-error exif-error
-                   (exif-parse-buffer)))
+                   ;; exif-parse-buffer can move point, so preserve it.
+                   (save-excursion
+                     (exif-parse-buffer))))
                 0.0)))
     ;; Swap width and height when changing orientation
     ;; between portrait and landscape.
@@ -985,7 +993,13 @@ Otherwise, display the image by calling `image-mode'."
                    (edges (window-inside-pixel-edges window))
                    (window-width  (- (nth 2 edges) (nth 0 edges)))
                    (window-height (- (nth 3 edges) (nth 1 edges))))
+              ;; If the size has been changed manually (with `+'/`-'),
+              ;; then :max-width/:max-height is nil.  In that case, do
+              ;; no automatic resizing.
               (when (and image-width image-height
+                         ;; Don't do resizing if we have a manual
+                         ;; rotation (from the `r' command), either.
+                         (not (plist-get (cdr spec) :rotation))
                          (or (not (= image-width  window-width))
                              (not (= image-height window-height))))
                 (unless image-fit-to-window-lock
@@ -1130,8 +1144,8 @@ replacing the current Image mode buffer."
       (funcall next))))
 
 (defun image-mode--directory-buffers (file)
-  "Return a alist of type/buffer for all \"parent\" buffers to image FILE.
-This is normally a list of dired buffers, but can also be archive and
+  "Return an alist of type/buffer for all \"parent\" buffers to image FILE.
+This is normally a list of Dired buffers, but can also be archive and
 tar mode buffers."
   (let ((buffers nil)
         (dir (file-name-directory file)))
@@ -1466,7 +1480,10 @@ return value is suitable for appending to an image spec."
        ,@(when (cdr resized)
            (list :height (cdr resized)))
        ,@(unless (= 0.0 image-transform-rotation)
-           (list :rotation image-transform-rotation))))))
+           (list :rotation image-transform-rotation))
+        ,@(when image--transform-smoothing
+            (list :transform-smoothing
+                  (string= image--transform-smoothing "smooth")))))))
 
 (defun image-transform-set-scale (scale)
   "Prompt for a number, and resize the current image by that amount."
@@ -1499,6 +1516,12 @@ ROTATION should be in degrees."
   (setq image-transform-rotation (float (mod rotation 360)))
   (image-toggle-display-image))
 
+(defun image-transform-set-smoothing (smoothing)
+  (interactive (list (completing-read "Smoothing: "
+                                      '("none" "smooth") nil t)))
+  (setq image--transform-smoothing smoothing)
+  (image-toggle-display-image))
+
 (defun image-transform-original ()
   "Display the current image with the original (actual) size and rotation."
   (interactive)
@@ -1511,7 +1534,8 @@ ROTATION should be in degrees."
   (interactive)
   (setq image-transform-resize image-auto-resize
        image-transform-rotation 0.0
-       image-transform-scale 1)
+       image-transform-scale 1
+        image--transform-smoothing nil)
   (image-toggle-display-image))
 
 (provide 'image-mode)
diff --git a/lisp/image.el b/lisp/image.el
index 6955a90..b802c1c 100644
--- a/lisp/image.el
+++ b/lisp/image.el
@@ -141,6 +141,18 @@ based on the font pixel size."
                  (const :tag "Automatically compute" auto))
   :version "26.1")
 
+(defcustom image-transform-smoothing #'image--default-smoothing
+  "Whether to do smoothing when applying transforms to images.
+Common transforms are rescaling and rotation.
+
+Valid values are nil (no smoothing), t (smoothing) or a predicate
+function that is called with the image specification and should return
+either nil or non-nil."
+  :type '(choice (const :tag "Do smoothing" t)
+                 (const :tag "No smoothing" nil)
+                 function)
+  :version "28.1")
+
 (defcustom image-use-external-converter nil
   "If non-nil, `create-image' will use external converters for exotic formats.
 Emacs handles most of the common image formats (SVG, JPEG, PNG, GIF
@@ -485,11 +497,40 @@ Image file names that are not absolute are searched for 
in the
             type 'png
             data-p t)))
   (when (image-type-available-p type)
-    (append (list 'image :type type (if data-p :data :file) file-or-data)
-            (and (not (plist-get props :scale))
-                 (list :scale
-                       (image-compute-scaling-factor image-scaling-factor)))
-           props)))
+    (let ((image
+           (append (list 'image :type type (if data-p :data :file)
+                         file-or-data)
+                   (and (not (plist-get props :scale))
+                        ;; Add default scaling.
+                        (list :scale
+                              (image-compute-scaling-factor
+                               image-scaling-factor)))
+                  props)))
+      ;; Add default smoothing.
+      (unless (plist-member props :transform-smoothing)
+        (setq image (nconc image
+                           (list :transform-smoothing
+                                 (pcase image-transform-smoothing
+                                   ('t t)
+                                   ('nil nil)
+                                   (func (funcall func image)))))))
+      image)))
+
+(defun image--default-smoothing (image)
+  "Say whether IMAGE should be smoothed when transformed."
+  (let* ((props (nthcdr 5 image))
+         (scaling (plist-get props :scale))
+         (rotation (plist-get props :rotation)))
+    (cond
+     ;; We always smooth when scaling down and small upwards scaling.
+     ((and scaling (< scaling 2))
+      t)
+     ;; Smooth when doing non-90-degree rotation
+     ((and rotation
+           (or (not (zerop (mod rotation 1)))
+               (not (zerop (% (truncate rotation) 90)))))
+      t)
+     (t nil))))
 
 (defun image--set-property (image property value)
   "Set PROPERTY in IMAGE to VALUE.
@@ -1089,6 +1130,7 @@ default is 20%."
     image))
 
 (defun image--get-imagemagick-and-warn (&optional position)
+  (declare-function image-transforms-p "image.c" (&optional frame))
   (unless (or (fboundp 'imagemagick-types) (image-transforms-p))
     (error "Cannot rescale images on this terminal"))
   (let ((image (image--get-image position)))
diff --git a/lisp/image/exif.el b/lisp/image/exif.el
index 2dc9419..c2cf234 100644
--- a/lisp/image/exif.el
+++ b/lisp/image/exif.el
@@ -118,8 +118,9 @@ If the data is invalid, an `exif-error' is signaled."
                                     dest))
             (when-let ((app1 (cdr (assq #xffe1 (exif--parse-jpeg)))))
               (exif--parse-exif-chunk app1))))
-      (when-let ((app1 (cdr (assq #xffe1 (exif--parse-jpeg)))))
-        (exif--parse-exif-chunk app1)))))
+      (save-excursion
+        (when-let ((app1 (cdr (assq #xffe1 (exif--parse-jpeg)))))
+          (exif--parse-exif-chunk app1))))))
 
 (defun exif-orientation (exif)
   "Return the orientation (in degrees) in EXIF.
diff --git a/lisp/imenu.el b/lisp/imenu.el
index 2a557e0..7fc57c1 100644
--- a/lisp/imenu.el
+++ b/lisp/imenu.el
@@ -36,14 +36,6 @@
 
 ;;   A mode-specific function is called to generate the index.  It is
 ;;   then presented to the user, who can choose from this index.
-;;
-;;   The package comes with a set of example functions for how to
-;;   utilize this package.
-
-;;   There are *examples* for index gathering functions/regular
-;;   expressions for C/C++ and Lisp/Emacs Lisp but it is easy to
-;;   customize for other modes.  A function for jumping to the chosen
-;;   index position is also supplied.
 
 ;;; History:
 ;;  Thanks go to
@@ -81,25 +73,20 @@ Setting this to nil makes Imenu work a little faster but 
editing the
 buffer will make the generated index positions wrong.
 
 This might not yet be honored by all index-building functions."
-  :type 'boolean
-  :group 'imenu)
-
+  :type 'boolean)
 
 (defcustom imenu-max-item-length 60
   "If a number, truncate Imenu entries to that length."
   :type '(choice integer
-                (const :tag "Unlimited"))
-  :group 'imenu)
+                 (const :tag "Unlimited")))
 
 (defcustom imenu-auto-rescan nil
   "Non-nil means Imenu should always rescan the buffers."
-  :type 'boolean
-  :group 'imenu)
+  :type 'boolean)
 
 (defcustom imenu-auto-rescan-maxout 600000
   "Imenu auto-rescan is disabled in buffers larger than this size (in bytes)."
   :type 'integer
-  :group 'imenu
   :version "26.2")
 
 (defcustom imenu-use-popup-menu 'on-mouse
@@ -109,13 +96,11 @@ If t, always use a popup menu,
 If `on-mouse' use a popup menu when `imenu' was invoked with the mouse."
   :type '(choice (const :tag "On Mouse" on-mouse)
                 (const :tag "Never" nil)
-                (other :tag "Always" t))
-  :group 'imenu)
+                 (other :tag "Always" t)))
 
 (defcustom imenu-eager-completion-buffer t
   "If non-nil, eagerly popup the completion buffer."
   :type 'boolean
-  :group 'imenu
   :version "22.1")
 
 (defcustom imenu-after-jump-hook nil
@@ -123,8 +108,7 @@ If `on-mouse' use a popup menu when `imenu' was invoked 
with the mouse."
 
 Useful things to use here include `reposition-window', `recenter', and
 \(lambda () (recenter 0)) to show at top of screen."
-  :type 'hook
-  :group 'imenu)
+  :type 'hook)
 
 ;;;###autoload
 (defcustom imenu-sort-function nil
@@ -143,39 +127,23 @@ element should come before the second.  The arguments are 
cons cells;
 \(NAME . POSITION).  Look at `imenu--sort-by-name' for an example."
   :type '(choice (const :tag "No sorting" nil)
                 (const :tag "Sort by name" imenu--sort-by-name)
-                (function :tag "Another function"))
-  :group 'imenu)
+                 (function :tag "Another function")))
 
 (defcustom imenu-max-items 25
   "Maximum number of elements in a mouse menu for Imenu."
-  :type 'integer
-  :group 'imenu)
-
-;; No longer used.  KFS 2004-10-27
-;; (defcustom imenu-scanning-message "Scanning buffer for index (%3d%%)"
-;;   "Progress message during the index scanning of the buffer.
-;; If non-nil, user gets a message during the scanning of the buffer.
-;;
-;; Relevant only if the mode-specific function that creates the buffer
-;; index use `imenu-progress-message', and not useful if that is fast, in
-;; which case you might as well set this to nil."
-;;   :type '(choice string
-;;              (const :tag "None" nil))
-;;   :group 'imenu)
+  :type 'integer)
 
 (defcustom imenu-space-replacement "."
   "The replacement string for spaces in index names.
 Used when presenting the index in a completion buffer to make the
 names work as tokens."
-  :type '(choice string (const nil))
-  :group 'imenu)
+  :type '(choice string (const nil)))
 
 (defcustom imenu-level-separator ":"
   "The separator between index names of different levels.
 Used for making mouse-menu titles and for flattening nested indexes
 with name concatenation."
-  :type 'string
-  :group 'imenu)
+  :type 'string)
 
 (defcustom imenu-generic-skip-comments-and-strings t
   "When non-nil, ignore text inside comments and strings.
@@ -183,7 +151,6 @@ Only affects `imenu-default-create-index-function' (and any
 alternative implementation of `imenu-create-index-function' that
 uses `imenu--generic-function')."
   :type 'boolean
-  :group 'imenu
   :version "24.4")
 
 ;;;###autoload
@@ -280,26 +247,11 @@ The function in this variable is called when selecting a 
normal index-item.")
        (not (functionp (cadr item)))))
 
 (defmacro imenu-progress-message (_prevpos &optional _relpos _reverse)
-  "Macro to display a progress message.
-RELPOS is the relative position to display.
-If RELPOS is nil, then the relative position in the buffer
-is calculated.
-PREVPOS is the variable in which we store the last position displayed."
-
+  "This macro is obsolete and does nothing."
+  (declare (obsolete nil "28.1"))
 ;; Made obsolete/empty, as computers are now faster than the eye, and
 ;; it had problems updating the messages correctly, and could shadow
 ;; more important messages/prompts in the minibuffer.  KFS 2004-10-27.
-
-;;  `(and
-;;    imenu-scanning-message
-;;    (let ((pos ,(if relpos
-;;                relpos
-;;              `(imenu--relative-position ,reverse))))
-;;     (if ,(if relpos t
-;;         `(> pos (+ 5 ,prevpos)))
-;;      (progn
-;;        (message imenu-scanning-message pos)
-;;        (setq ,prevpos pos)))))
 )
 
 
diff --git a/lisp/info.el b/lisp/info.el
index 7f169f4..dd7e16f 100644
--- a/lisp/info.el
+++ b/lisp/info.el
@@ -1972,7 +1972,8 @@ If DIRECTION is `backward', search in the reverse 
direction."
                       (format-prompt
                        "Regexp search%s" (car Info-search-history)
                       (if case-fold-search "" " case-sensitively"))
-                     nil 'Info-search-history)))
+                     nil 'Info-search-history))
+               Info-mode)
   (when (equal regexp "")
     (setq regexp (car Info-search-history)))
   (when regexp
@@ -2080,13 +2081,13 @@ If DIRECTION is `backward', search in the reverse 
direction."
 
 (defun Info-search-case-sensitively ()
   "Search for a regexp case-sensitively."
-  (interactive)
+  (interactive nil Info-mode)
   (let ((case-fold-search nil))
     (call-interactively 'Info-search)))
 
 (defun Info-search-next ()
   "Search for next regexp from a previous `Info-search' command."
-  (interactive)
+  (interactive nil Info-mode)
   (let ((case-fold-search Info-search-case-fold))
     (if Info-search-history
         (Info-search (car Info-search-history))
@@ -2098,7 +2099,8 @@ If DIRECTION is `backward', search in the reverse 
direction."
                       (format-prompt
                        "Regexp search%s backward" (car Info-search-history)
                       (if case-fold-search "" " case-sensitively"))
-                     nil 'Info-search-history)))
+                     nil 'Info-search-history))
+               Info-mode)
   (Info-search regexp bound noerror count 'backward))
 
 (defun Info-isearch-search ()
@@ -2235,7 +2237,7 @@ End of submatch 0, 1, and 3 are the same, so you can 
safely concat."
 (defun Info-next ()
   "Go to the \"next\" node, staying on the same hierarchical level.
 This command doesn't descend into sub-nodes, like 
\\<Info-mode-map>\\[Info-forward-node] does."
-  (interactive)
+  (interactive nil Info-mode)
   ;; In case another window is currently selected
   (save-window-excursion
     (or (derived-mode-p 'Info-mode) (switch-to-buffer "*info*"))
@@ -2244,7 +2246,7 @@ This command doesn't descend into sub-nodes, like 
\\<Info-mode-map>\\[Info-forwa
 (defun Info-prev ()
   "Go to the \"previous\" node, staying on the same hierarchical level.
 This command doesn't go up to the parent node, like 
\\<Info-mode-map>\\[Info-backward-node] does."
-  (interactive)
+  (interactive nil Info-mode)
   ;; In case another window is currently selected
   (save-window-excursion
     (or (derived-mode-p 'Info-mode) (switch-to-buffer "*info*"))
@@ -2253,7 +2255,7 @@ This command doesn't go up to the parent node, like 
\\<Info-mode-map>\\[Info-bac
 (defun Info-up (&optional same-file)
   "Go to the superior node of this node.
 If SAME-FILE is non-nil, do not move to a different Info file."
-  (interactive)
+  (interactive nil Info-mode)
   ;; In case another window is currently selected
   (save-window-excursion
     (or (derived-mode-p 'Info-mode) (switch-to-buffer "*info*"))
@@ -2284,7 +2286,7 @@ If SAME-FILE is non-nil, do not move to a different Info 
file."
 
 (defun Info-history-back ()
   "Go back in the history to the last node visited."
-  (interactive)
+  (interactive nil Info-mode)
   (or Info-history
       (user-error "This is the first Info node you looked at"))
   (let ((history-forward
@@ -2304,7 +2306,7 @@ If SAME-FILE is non-nil, do not move to a different Info 
file."
 
 (defun Info-history-forward ()
   "Go forward in the history of visited nodes."
-  (interactive)
+  (interactive nil Info-mode)
   (or Info-history-forward
       (user-error "This is the last Info node you looked at"))
   (let ((history-forward (cdr Info-history-forward))
@@ -2378,7 +2380,7 @@ If SAME-FILE is non-nil, do not move to a different Info 
file."
 
 (defun Info-history ()
   "Go to a node with a menu of visited nodes."
-  (interactive)
+  (interactive nil Info-mode)
   (Info-find-node "*History*" "Top")
   (Info-next-reference)
   (Info-next-reference))
@@ -2415,7 +2417,7 @@ If SAME-FILE is non-nil, do not move to a different Info 
file."
 (defun Info-toc ()
   "Go to a node with table of contents of the current Info file.
 Table of contents is created from the tree structure of menus."
-  (interactive)
+  (interactive nil Info-mode)
   (Info-find-node Info-current-file "*TOC*")
   (let ((prev-node (nth 1 (car Info-history))) p)
     (goto-char (point-min))
@@ -2587,7 +2589,8 @@ new buffer."
           (list (if (equal input "")
                     default input)
                  current-prefix-arg))
-       (user-error "No cross-references in this node"))))
+       (user-error "No cross-references in this node")))
+   Info-mode)
 
   (unless footnotename
     (error "No reference was specified"))
@@ -2789,7 +2792,8 @@ new buffer."
                      (completing-read (format-prompt "Menu item" default)
                                       #'Info-complete-menu-item nil t nil nil
                                        default))))
-       (list item current-prefix-arg))))
+       (list item current-prefix-arg)))
+   Info-mode)
   ;; there is a problem here in that if several menu items have the same
   ;; name you can only go to the node of the first with this command.
   (Info-goto-node (Info-extract-menu-item menu-item)
@@ -2833,19 +2837,19 @@ new buffer."
 (defun Info-nth-menu-item ()
   "Go to the node of the Nth menu item.
 N is the digit argument used to invoke this command."
-  (interactive)
+  (interactive nil Info-mode)
   (Info-goto-node
    (Info-extract-menu-counting
     (- (aref (this-command-keys) (1- (length (this-command-keys)))) ?0))))
 
 (defun Info-top-node ()
   "Go to the Top node of this file."
-  (interactive)
+  (interactive nil Info-mode)
   (Info-goto-node "Top"))
 
 (defun Info-final-node ()
   "Go to the final node in this file."
-  (interactive)
+  (interactive nil Info-mode)
   (Info-goto-node "Top")
   (let ((Info-history nil)
        (case-fold-search t))
@@ -2869,7 +2873,7 @@ to the parent node.
 When called from Lisp, NOT-DOWN non-nil means don't descend into sub-nodes,
 NOT-UP non-nil means don't go to parent nodes, and NO-ERROR non-nil means
 don't signal a user-error if there's no node to go to."
-  (interactive)
+  (interactive nil Info-mode)
   (goto-char (point-min))
   (forward-line 1)
   (let ((case-fold-search t))
@@ -2906,7 +2910,7 @@ don't signal a user-error if there's no node to go to."
   "Go backward one node, considering all nodes as forming one sequence.
 If the current node has a \"previous\" node, go to it, descending into its
 last sub-node, if any; otherwise go \"up\" to the parent node."
-  (interactive)
+  (interactive nil Info-mode)
   (let ((prevnode (Info-extract-pointer "prev[ious]*" t))
        (upnode (Info-extract-pointer "up" t))
        (case-fold-search t))
@@ -2935,7 +2939,7 @@ last sub-node, if any; otherwise go \"up\" to the parent 
node."
 
 (defun Info-next-menu-item ()
   "Go to the node of the next menu item."
-  (interactive)
+  (interactive nil Info-mode)
   ;; Bind this in case the user sets it to nil.
   (let* ((case-fold-search t)
         (node
@@ -2949,7 +2953,7 @@ last sub-node, if any; otherwise go \"up\" to the parent 
node."
 
 (defun Info-last-menu-item ()
   "Go to the node of the previous menu item."
-  (interactive)
+  (interactive nil Info-mode)
   (save-excursion
     (forward-line 1)
     ;; Bind this in case the user sets it to nil.
@@ -2968,7 +2972,7 @@ last sub-node, if any; otherwise go \"up\" to the parent 
node."
 
 (defun Info-next-preorder ()
   "Go to the next subnode or the next node, or go up a level."
-  (interactive)
+  (interactive nil Info-mode)
   (cond ((Info-no-error (Info-next-menu-item)))
        ((Info-no-error (Info-next)))
        ((Info-no-error (Info-up t))
@@ -2987,7 +2991,7 @@ last sub-node, if any; otherwise go \"up\" to the parent 
node."
 
 (defun Info-last-preorder ()
   "Go to the last node, popping up a level if there is none."
-  (interactive)
+  (interactive nil Info-mode)
   (cond ((and Info-scroll-prefer-subnodes
              (Info-no-error
               (Info-last-menu-item)
@@ -3039,7 +3043,7 @@ the menu of a node, it moves to subnode indicated by the 
following menu
 item.  (That case won't normally result from this command, but can happen
 in other ways.)"
 
-  (interactive)
+  (interactive nil Info-mode)
   (if (or (< (window-start) (point-min))
          (> (window-start) (point-max)))
       (set-window-start (selected-window) (point)))
@@ -3061,7 +3065,7 @@ in other ways.)"
 (defun Info-mouse-scroll-up (e)
   "Scroll one screenful forward in Info, using the mouse.
 See `Info-scroll-up'."
-  (interactive "e")
+  (interactive "e" Info-mode)
   (save-selected-window
     (if (eventp e)
        (select-window (posn-window (event-start e))))
@@ -3073,7 +3077,7 @@ If point is within the menu of a node, and 
`Info-scroll-prefer-subnodes'
 is non-nil, this goes to its last subnode.  When you scroll past the
 beginning of a node, that goes to the previous node or back up to the
 parent node."
-  (interactive)
+  (interactive nil Info-mode)
   (if (or (< (window-start) (point-min))
          (> (window-start) (point-max)))
       (set-window-start (selected-window) (point)))
@@ -3093,7 +3097,7 @@ parent node."
 (defun Info-mouse-scroll-down (e)
   "Scroll one screenful backward in Info, using the mouse.
 See `Info-scroll-down'."
-  (interactive "e")
+  (interactive "e" Info-mode)
   (save-selected-window
     (if (eventp e)
        (select-window (posn-window (event-start e))))
@@ -3139,7 +3143,7 @@ Return the new position of point, or nil."
   "Move cursor to the next cross-reference or menu item in the node.
 If COUNT is non-nil (interactively with a prefix arg), jump over
 COUNT cross-references."
-  (interactive "i\np")
+  (interactive "i\np" Info-mode)
   (unless count
     (setq count 1))
   (if (< count 0)
@@ -3167,7 +3171,7 @@ COUNT cross-references."
   "Move cursor to the previous cross-reference or menu item in the node.
 If COUNT is non-nil (interactively with a prefix arg), jump over
 COUNT cross-references."
-  (interactive "i\np")
+  (interactive "i\np" Info-mode)
   (unless count
     (setq count 1))
   (if (< count 0)
@@ -3365,7 +3369,7 @@ Give an empty topic name to go to the Index node itself."
 
 (defun Info-index-next (num)
   "Go to the next matching index item from the last 
\\<Info-mode-map>\\[Info-index] command."
-  (interactive "p")
+  (interactive "p" Info-mode)
   (or Info-index-alternatives
       (user-error "No previous `i' command"))
   (while (< num 0)
@@ -3487,7 +3491,8 @@ search results."
          (with-current-buffer Info-complete-menu-buffer
            (Info-goto-index)
            (completing-read "Index topic: " #'Info-complete-menu-item))
-       (kill-buffer Info-complete-menu-buffer)))))
+       (kill-buffer Info-complete-menu-buffer))))
+   Info-mode)
   (if (equal topic "")
       (Info-find-node Info-current-file "*Index*")
     (unless (assoc (cons Info-current-file topic) Info-virtual-index-nodes)
@@ -3793,7 +3798,7 @@ with a list of packages that contain all specified 
keywords."
 
 (defun Info-undefined ()
   "Make command be undefined in Info."
-  (interactive)
+  (interactive nil Info-mode)
   (ding))
 
 (defun Info-help ()
@@ -3870,7 +3875,7 @@ ERRORSTRING optional fourth argument, controls action on 
no match:
   "\\<Info-mode-map>Follow a node reference near point.
 Like \\[Info-menu], \\[Info-follow-reference], \\[Info-next], \\[Info-prev] or 
\\[Info-up] command, depending on where you click.
 At end of the node's text, moves to the next node, or up if none."
-  (interactive "e")
+  (interactive "e" Info-mode)
   (mouse-set-point click)
   (and (not (Info-follow-nearest-node))
        (save-excursion (forward-line 1) (eobp))
@@ -3884,7 +3889,7 @@ if point is in a menu item description, follow that menu 
item.
 If FORK is non-nil (interactively with a prefix arg), show the node in
 a new Info buffer.
 If FORK is a string, it is the name to use for the new buffer."
-  (interactive "P")
+  (interactive "P" Info-mode)
   (or (Info-try-follow-nearest-node fork)
       (when (save-excursion
              (search-backward "\n* menu:" nil t))
@@ -3954,7 +3959,7 @@ If FORK is non-nil, it is passed to `Info-goto-node'."
 
 (defun Info-mouse-follow-link (click)
   "Follow a link where you click."
-  (interactive "@e")
+  (interactive "@e" Info-mode)
   (let* ((position (event-start click))
         (posn-string (and position (posn-string position)))
         (link-args (if posn-string
@@ -4158,12 +4163,12 @@ If FORK is non-nil, it is passed to `Info-goto-node'."
 
 (defun Info-history-back-menu (e)
   "Pop up the menu with a list of previously visited Info nodes."
-  (interactive "e")
+  (interactive "e" Info-mode)
   (Info-history-menu e "Back in history" Info-history 'Info-history-back))
 
 (defun Info-history-forward-menu (e)
   "Pop up the menu with a list of Info nodes visited with ‘Info-history-back’."
-  (interactive "e")
+  (interactive "e" Info-mode)
   (Info-history-menu e "Forward in history" Info-history-forward 
'Info-history-forward))
 
 (defvar Info-menu-last-node nil)
@@ -4237,7 +4242,7 @@ If FORK is non-nil, it is passed to `Info-goto-node'."
   "Put the name of the current Info node into the kill ring.
 The name of the Info file is prepended to the node name in parentheses.
 With a zero prefix arg, put the name inside a function call to `info'."
-  (interactive "P")
+  (interactive "P" Info-mode)
   (unless Info-current-node
     (user-error "No current Info node"))
   (let ((node (if (stringp Info-current-file)
@@ -4792,10 +4797,10 @@ first line or header line, and for breadcrumb links.")
                    (skip-syntax-backward " ("))
                   (setq other-tag
                        (cond ((save-match-data (looking-back "\\(^\\| \\)see"
-                                                              (- (point) 3)))
+                                                              (- (point) 4)))
                               "")
                              ((save-match-data (looking-back "\\(^\\| \\)in"
-                                                              (- (point) 2)))
+                                                              (- (point) 3)))
                               "")
                              ((memq (char-before) '(nil ?\. ?! ??))
                                "See ")
diff --git a/lisp/international/ccl.el b/lisp/international/ccl.el
index 3c5a461..0eb009f 100644
--- a/lisp/international/ccl.el
+++ b/lisp/international/ccl.el
@@ -43,12 +43,6 @@
 
 ;;; Code:
 
-;; Unused.
-;;; (defgroup ccl nil
-;;;   "CCL (Code Conversion Language) compiler."
-;;;   :prefix "ccl-"
-;;;   :group 'i18n)
-
 (defconst ccl-command-table
   [if branch loop break repeat write-repeat write-read-repeat
       read read-if read-branch write call end
diff --git a/lisp/international/mule-cmds.el b/lisp/international/mule-cmds.el
index e4bdf50..bf0df6f 100644
--- a/lisp/international/mule-cmds.el
+++ b/lisp/international/mule-cmds.el
@@ -1524,7 +1524,7 @@ To deactivate it programmatically, use 
`deactivate-input-method'."
   (interactive
    (let* ((default (or (car input-method-history) default-input-method)))
      (list (read-input-method-name
-           (if default "Select input method (default %s): " "Select input 
method: ")
+           (format-prompt "Select input method" default)
            default t)
           t)))
   (activate-input-method input-method)
@@ -1569,7 +1569,7 @@ which marks the variable `default-input-method' as set 
for Custom buffers."
        (if (or arg (not default))
           (progn
             (read-input-method-name
-             (if default "Input method (default %s): " "Input method: " )
+             (format-prompt "Input method" default)
              default t))
         default))
       (unless default-input-method
@@ -1620,7 +1620,7 @@ If `default-transient-input-method' was not yet defined, 
prompt for it."
   "Describe input method INPUT-METHOD."
   (interactive
    (list (read-input-method-name
-         "Describe input method (default current choice): ")))
+          (format-prompt "Describe input method" current-input-method))))
   (if (and input-method (symbolp input-method))
       (setq input-method (symbol-name input-method)))
   (help-setup-xref (list #'describe-input-method
@@ -1929,7 +1929,7 @@ runs the hook `exit-language-environment-hook'.  After 
setting up
 the new language environment, it runs `set-language-environment-hook'."
   (interactive (list (read-language-name
                      nil
-                     "Set language environment (default English): ")))
+                     (format-prompt "Set language environment" "English"))))
   (if language-name
       (if (symbolp language-name)
          (setq language-name (symbol-name language-name)))
@@ -2144,7 +2144,7 @@ See `set-language-info-alist' for use in programs."
   (interactive
    (list (read-language-name
          'documentation
-         "Describe language environment (default current choice): ")))
+         (format-prompt "Describe language environment" 
current-language-environment))))
   (if (null language-name)
       (setq language-name current-language-environment))
   (if (or (null language-name)
@@ -2245,7 +2245,7 @@ See `set-language-info-alist' for use in programs."
      ;; LANGUAGE is a language code taken from ISO 639:1988 (E/F)
      ;; with additions from ISO 639/RA Newsletter No.1/1989;
      ;; see Internet RFC 2165 (1997-06) and
-     ;; http://www.evertype.com/standards/iso639/iso639-en.html
+     ;; https://www.evertype.com/standards/iso639/iso639-en.html
      ;; TERRITORY is a country code taken from ISO 3166
      ;; http://www.din.de/gremien/nas/nabd/iso3166ma/codlstp1/en_listp1.html.
      ;; CODESET and MODIFIER are implementation-dependent.
diff --git a/lisp/international/mule-conf.el b/lisp/international/mule-conf.el
index 64aac46..2d36dab 100644
--- a/lisp/international/mule-conf.el
+++ b/lisp/international/mule-conf.el
@@ -41,7 +41,7 @@
 ;; Standards docs equivalent to iso-2022 and iso-8859 are at
 ;; https://www.ecma.ch/.
 
-;; FWIW, http://www.microsoft.com/globaldev/ lists the following for
+;; FWIW, https://www.microsoft.com/globaldev/ lists the following for
 ;; MS Windows, which are presumably the only charsets we really need
 ;; to worry about on such systems:
 ;; `OEM codepages': 437, 720, 737, 775, 850, 852, 855, 857, 858, 862, 866
@@ -358,7 +358,7 @@
   :code-offset #x130000
   :unify-map "BIG5")
 ;; Fixme: AKA cp950 according to
-;; <URL:http://www.microsoft.com/globaldev/reference/WinCP.asp>.  Is
+;; <URL:https://www.microsoft.com/globaldev/reference/WinCP.asp>.  Is
 ;; that correct?
 
 (define-charset 'chinese-big5-1
@@ -708,7 +708,7 @@
 ;; Original name for cp1125, says Serhii Hlodin <hlodin@lutsk.bank.gov.ua>
 (define-charset-alias 'cp866u 'cp1125)
 
-;; Fixme: C.f. iconv, http://czyborra.com/charsets/codepages.html
+;; Fixme: C.f. iconv, https://czyborra.com/charsets/codepages.html
 ;; shows this as not ASCII compatible, with various graphics in
 ;; 0x01-0x1F.
 (define-charset 'cp437
diff --git a/lisp/international/mule-diag.el b/lisp/international/mule-diag.el
index d97d090..a0063c8 100644
--- a/lisp/international/mule-diag.el
+++ b/lisp/international/mule-diag.el
@@ -835,6 +835,8 @@ The IGNORED argument is ignored."
    (list (completing-read
           "Font name (default current choice for ASCII chars): "
           (and window-system
+               ;; Implied by `window-system'.
+               (fboundp 'x-list-fonts)
                (fboundp 'fontset-list)
                ;; The final element in `fontset-list' is a default
                ;; (generic) one, so don't include that.
diff --git a/lisp/international/mule-util.el b/lisp/international/mule-util.el
index 580bd29..5544959 100644
--- a/lisp/international/mule-util.el
+++ b/lisp/international/mule-util.el
@@ -278,14 +278,13 @@ Optional 5th argument NIL-FOR-TOO-LONG non-nil means 
return nil
 CODING-SYSTEMS is a list of coding systems.  See `set-coding-system-priority'.
 This affects the implicit sorting of lists of coding systems returned by
 operations such as `find-coding-systems-region'."
+  (declare (indent 1) (debug t))
   (let ((current (make-symbol "current")))
   `(let ((,current (coding-system-priority-list)))
      (apply #'set-coding-system-priority ,coding-systems)
      (unwind-protect
         (progn ,@body)
        (apply #'set-coding-system-priority ,current)))))
-;;;###autoload(put 'with-coding-priority 'lisp-indent-function 1)
-(put 'with-coding-priority 'edebug-form-spec t)
 
 ;;;###autoload
 (defun detect-coding-with-language-environment (from to lang-env)
diff --git a/lisp/international/quail.el b/lisp/international/quail.el
index 67ea006..87a9050 100644
--- a/lisp/international/quail.el
+++ b/lisp/international/quail.el
@@ -1075,7 +1075,7 @@ The installed decode map can be referred by the function 
`quail-decode-map'."
 KEY is a string meaning a sequence of keystrokes to be translated.
 TRANSLATION is a character, a string, a vector, a Quail map,
  a function, or a cons.
-It it is a character, it is the sole translation of KEY.
+If it is a character, it is the sole translation of KEY.
 If it is a string, each character is a candidate for the translation.
 If it is a vector, each element (string or character) is a candidate
  for the translation.
@@ -3066,28 +3066,31 @@ of each directory."
            ;; Don't get fooled by commented-out code.
            (while (re-search-forward "^[ \t]*(quail-define-package" nil t)
              (goto-char (match-beginning 0))
-             (condition-case nil
-                 (let ((form (read (current-buffer))))
-                   (with-current-buffer list-buf
-                     (insert
-                      (format "(register-input-method
+              (let (form)
+               (condition-case err
+                   (progn
+                      (setq form (read (current-buffer)))
+                     (with-current-buffer list-buf
+                       (insert
+                        (format "(register-input-method
  %S %S '%s
  %S %S
  %S)\n"
-                              (nth 1 form) ; PACKAGE-NAME
-                              (nth 2 form) ; LANGUAGE
-                              'quail-use-package ; ACTIVATE-FUNC
-                              (nth 3 form) ; PACKAGE-TITLE
-                              (progn   ; PACKAGE-DESCRIPTION (one line)
-                                (string-match ".*" (nth 5 form))
-                                (match-string 0 (nth 5 form)))
-                              (file-relative-name ; PACKAGE-FILENAME
-                               (file-name-sans-extension (car pkg-list))
-                               (car dirnames))))))
-               (error
-                ;; Ignore the remaining contents of this file.
-                (goto-char (point-max))
-                (message "Some part of \"%s\" is broken" (car pkg-list))))))
+                                (nth 1 form)       ; PACKAGE-NAME
+                                (nth 2 form)       ; LANGUAGE
+                                'quail-use-package ; ACTIVATE-FUNC
+                                (nth 3 form)       ; PACKAGE-TITLE
+                                (progn ; PACKAGE-DESCRIPTION (one line)
+                                  (string-match ".*" (nth 5 form))
+                                  (match-string 0 (nth 5 form)))
+                                (file-relative-name ; PACKAGE-FILENAME
+                                 (file-name-sans-extension (car pkg-list))
+                                 (car dirnames))))))
+                 (error
+                  ;; Ignore the remaining contents of this file.
+                  (goto-char (point-max))
+                  (message "Some part of \"%s\" is broken: %s in %s"
+                            (car pkg-list) err form))))))
          (setq pkg-list (cdr pkg-list)))
        (setq quail-dirs (cdr quail-dirs) dirnames (cdr dirnames))))
 
diff --git a/lisp/isearch.el b/lisp/isearch.el
index b58ca8a..943e24a 100644
--- a/lisp/isearch.el
+++ b/lisp/isearch.el
@@ -26,7 +26,7 @@
 
 ;; Instructions
 
-;; For programmed use of isearch-mode, e.g. calling (isearch-forward),
+;; For programmed use of isearch-mode, e.g. calling `isearch-forward',
 ;; isearch-mode behaves modally and does not return until the search
 ;; is completed.  It uses a recursive-edit to behave this way.
 
@@ -46,7 +46,7 @@
 ;; exits and searches in the last search direction.
 
 ;; Exiting immediately from isearch uses isearch-edit-string instead
-;; of nonincremental-search, if search-nonincremental-instead is non-nil.
+;; of nonincremental-search, if `search-nonincremental-instead' is non-nil.
 ;; The name of this option should probably be changed if we decide to
 ;; keep the behavior.  No point in forcing nonincremental search until
 ;; the last possible moment.
@@ -460,11 +460,11 @@ and doesn't remove full-buffer highlighting after a 
search."
 (make-help-screen isearch-help-for-help-internal
   (purecopy "Type a help option: [bkm] or ?")
   "You have typed %THIS-KEY%, the help character.  Type a Help option:
-\(Type \\<help-map>\\[help-quit] to exit the Help command.)
+\(Type \\<isearch-help-map>\\[help-quit] to exit the Help command.)
 
-b           Display all Isearch key bindings.
-k KEYS      Display full documentation of Isearch key sequence.
-m           Display documentation of Isearch mode.
+\\[isearch-describe-bindings]           Display all Isearch key bindings.
+\\[isearch-describe-key] KEYS      Display full documentation of Isearch key 
sequence.
+\\[isearch-describe-mode]           Display documentation of Isearch mode.
 
 You can't type here other help keys available in the global help map,
 but outside of this help window when you type them in Isearch mode,
@@ -527,159 +527,6 @@ This is like `describe-bindings', but displays only 
Isearch keys."
   '(isearch-tmm-menubar tmm-menubar menu-bar-open mouse-minor-mode-menu)
   "List of commands that can open a menu during Isearch.")
 
-(defvar isearch-menu-bar-yank-map
-  (let ((map (make-sparse-keymap)))
-    (define-key map [isearch-yank-pop]
-      '(menu-item "Previous kill" isearch-yank-pop-only
-                  :help "Replace previous yanked kill on search string"))
-    (define-key map [isearch-yank-kill]
-      '(menu-item "Current kill" isearch-yank-kill
-                  :help "Append current kill to search string"))
-    (define-key map [isearch-yank-until-char]
-      '(menu-item "Until char..." isearch-yank-until-char
-                  :help "Yank from point to specified character into search 
string"))
-    (define-key map [isearch-yank-line]
-      '(menu-item "Rest of line" isearch-yank-line
-                  :help "Yank the rest of the current line on search string"))
-    (define-key map [isearch-yank-symbol-or-char]
-      '(menu-item "Symbol/char"
-                  isearch-yank-symbol-or-char
-                  :help "Yank next symbol or char on search string"))
-    (define-key map [isearch-yank-word-or-char]
-      '(menu-item "Word/char"
-                  isearch-yank-word-or-char
-                  :help "Yank next word or char on search string"))
-    (define-key map [isearch-yank-char]
-      '(menu-item "Char" isearch-yank-char
-                  :help "Yank char at point on search string"))
-    map))
-
-(defvar isearch-menu-bar-map
-  (let ((map (make-sparse-keymap "Isearch")))
-    (define-key map [isearch-complete]
-      '(menu-item "Complete current search string" isearch-complete
-                  :help "Complete current search string over search history"))
-    (define-key map [isearch-complete-separator]
-      '(menu-item "--"))
-    (define-key map [isearch-query-replace-regexp]
-      '(menu-item "Replace search string as regexp" 
isearch-query-replace-regexp
-                  :help "Replace matches for current search string as regexp"))
-    (define-key map [isearch-query-replace]
-      '(menu-item "Replace search string" isearch-query-replace
-                  :help "Replace matches for current search string"))
-    (define-key map [isearch-occur]
-      '(menu-item "Show all matches for search string" isearch-occur
-                  :help "Show all matches for current search string"))
-    (define-key map [isearch-highlight-regexp]
-      '(menu-item "Highlight all matches for search string"
-                  isearch-highlight-regexp
-                  :help "Highlight all matches for current search string"))
-    (define-key map [isearch-search-replace-separator]
-      '(menu-item "--"))
-    (define-key map [isearch-transient-input-method]
-      '(menu-item "Turn on transient input method"
-                  isearch-transient-input-method
-                  :help "Turn on transient input method for search"))
-    (define-key map [isearch-toggle-specified-input-method]
-      '(menu-item "Turn on specific input method"
-                  isearch-toggle-specified-input-method
-                  :help "Turn on specific input method for search"))
-    (define-key map [isearch-toggle-input-method]
-      '(menu-item "Toggle input method" isearch-toggle-input-method
-                  :help "Toggle input method for search"))
-    (define-key map [isearch-input-method-separator]
-      '(menu-item "--"))
-    (define-key map [isearch-char-by-name]
-      '(menu-item "Search for char by name" isearch-char-by-name
-                  :help "Search for character by name"))
-    (define-key map [isearch-quote-char]
-      '(menu-item "Search for literal char" isearch-quote-char
-                  :help "Search for literal char"))
-    (define-key map [isearch-special-char-separator]
-      '(menu-item "--"))
-    (define-key map [isearch-toggle-word]
-      '(menu-item "Word matching" isearch-toggle-word
-                  :help "Word matching"
-                  :button (:toggle
-                           . (eq isearch-regexp-function 
'word-search-regexp))))
-    (define-key map [isearch-toggle-symbol]
-      '(menu-item "Symbol matching" isearch-toggle-symbol
-                  :help "Symbol matching"
-                  :button (:toggle
-                           . (eq isearch-regexp-function
-                                 'isearch-symbol-regexp))))
-    (define-key map [isearch-toggle-regexp]
-      '(menu-item "Regexp matching" isearch-toggle-regexp
-                  :help "Regexp matching"
-                  :button (:toggle . isearch-regexp)))
-    (define-key map [isearch-toggle-invisible]
-      '(menu-item "Invisible text matching" isearch-toggle-invisible
-                  :help "Invisible text matching"
-                  :button (:toggle . isearch-invisible)))
-    (define-key map [isearch-toggle-char-fold]
-      '(menu-item "Character folding matching" isearch-toggle-char-fold
-                  :help "Character folding matching"
-                  :button (:toggle
-                           . (eq isearch-regexp-function
-                                 'char-fold-to-regexp))))
-    (define-key map [isearch-toggle-case-fold]
-      '(menu-item "Case folding matching" isearch-toggle-case-fold
-                  :help "Case folding matching"
-                  :button (:toggle . isearch-case-fold-search)))
-    (define-key map [isearch-toggle-lax-whitespace]
-      '(menu-item "Lax whitespace matching" isearch-toggle-lax-whitespace
-                  :help "Lax whitespace matching"
-                  :button (:toggle . isearch-lax-whitespace)))
-    (define-key map [isearch-toggle-separator]
-      '(menu-item "--"))
-    (define-key map [isearch-yank-menu]
-      `(menu-item "Yank on search string" ,isearch-menu-bar-yank-map))
-    (define-key map [isearch-edit-string]
-      '(menu-item "Edit current search string" isearch-edit-string
-                  :help "Edit current search string"))
-    (define-key map [isearch-ring-retreat]
-      '(menu-item "Edit previous search string" isearch-ring-retreat
-                  :help "Edit previous search string in Isearch history"))
-    (define-key map [isearch-ring-advance]
-      '(menu-item "Edit next search string" isearch-ring-advance
-                  :help "Edit next search string in Isearch history"))
-    (define-key map [isearch-del-char]
-      '(menu-item "Delete last char from search string" isearch-del-char
-                  :help "Delete last character from search string"))
-    (define-key map [isearch-delete-char]
-      '(menu-item "Undo last input item" isearch-delete-char
-                  :help "Undo the effect of the last Isearch command"))
-    (define-key map [isearch-end-of-buffer]
-      '(menu-item "Go to last match" isearch-end-of-buffer
-                  :help "Go to last occurrence of current search string"))
-    (define-key map [isearch-beginning-of-buffer]
-      '(menu-item "Go to first match" isearch-beginning-of-buffer
-                  :help "Go to first occurrence of current search string"))
-    (define-key map [isearch-repeat-backward]
-      '(menu-item "Repeat search backward" isearch-repeat-backward
-                  :help "Repeat current search backward"))
-    (define-key map [isearch-repeat-forward]
-      '(menu-item "Repeat search forward" isearch-repeat-forward
-                  :help "Repeat current search forward"))
-    (define-key map [isearch-nonincremental]
-      '(menu-item "Nonincremental search" isearch-exit
-                  :help "Start nonincremental search"
-                  :visible (string-equal isearch-string "")))
-    (define-key map [isearch-exit]
-      '(menu-item "Finish search" isearch-exit
-                  :help "Finish search leaving point where it is"
-                  :visible (not (string-equal isearch-string ""))))
-    (define-key map [isearch-abort]
-      '(menu-item "Remove characters not found" isearch-abort
-                  :help "Quit current search"
-                  :visible (not isearch-success)))
-    (define-key map [isearch-cancel]
-      `(menu-item "Cancel search" isearch-cancel
-                  :help "Cancel current search and return to starting point"
-                  :filter ,(lambda (binding)
-                             (if isearch-success 'isearch-abort binding))))
-    map))
-
 ;; Note: Before adding more key bindings to this map, please keep in
 ;; mind that any unbound key exits Isearch and runs the command bound
 ;; to it in the local or global map.  So in effect every key unbound
@@ -795,13 +642,116 @@ This is like `describe-bindings', but displays only 
Isearch keys."
     ;; The key translations defined in the C-x 8 prefix should add
     ;; characters to the search string.  See iso-transl.el.
     (define-key map "\C-x8\r" 'isearch-char-by-name)
-
-    (define-key map [menu-bar search-menu]
-      (list 'menu-item "Isearch" isearch-menu-bar-map))
-
     map)
   "Keymap for `isearch-mode'.")
 
+(easy-menu-define isearch-menu-bar-map  isearch-mode-map
+  "Menu for `isearch-mode'."
+  '("Isearch"
+    ["Cancel search" isearch-cancel
+     :help "Cancel current search and return to starting point"
+     :filter (lambda (binding)
+               (if isearch-success 'isearch-abort binding))]
+    ["Remove characters not found" isearch-abort
+     :help "Quit current search"
+     :visible (not isearch-success)]
+    ["Finish search" isearch-exit
+     :help "Finish search leaving point where it is"
+     :visible (not (string-equal isearch-string ""))]
+    ["Nonincremental search" isearch-exit
+     :help "Start nonincremental search"
+     :visible (string-equal isearch-string "")]
+    ["Repeat search forward" isearch-repeat-forward
+     :help "Repeat current search forward"]
+    ["Repeat search backward" isearch-repeat-backward
+     :help "Repeat current search backward"]
+    ["Go to first match" isearch-beginning-of-buffer
+     :help "Go to first occurrence of current search string"]
+    ["Go to last match" isearch-end-of-buffer
+     :help "Go to last occurrence of current search string"]
+    ["Undo last input item" isearch-delete-char
+     :help "Undo the effect of the last Isearch command"]
+    ["Delete last char from search string" isearch-del-char
+     :help "Delete last character from search string"]
+    ["Edit next search string" isearch-ring-advance
+     :help "Edit next search string in Isearch history"]
+    ["Edit previous search string" isearch-ring-retreat
+     :help "Edit previous search string in Isearch history"]
+    ["Edit current search string" isearch-edit-string
+     :help "Edit current search string"]
+    ("Yank on search string"
+     ["Char" isearch-yank-char
+      :help "Yank char at point on search string"]
+     ["Word/char"
+      isearch-yank-word-or-char
+      :help "Yank next word or char on search string"]
+     ["Symbol/char"
+      isearch-yank-symbol-or-char
+      :help "Yank next symbol or char on search string"]
+     ["Rest of line" isearch-yank-line
+      :help "Yank the rest of the current line on search string"]
+     ["Until char..." isearch-yank-until-char
+      :help "Yank from point to specified character into search string"]
+     ["Current kill" isearch-yank-kill
+      :help "Append current kill to search string"]
+     ["Previous kill" isearch-yank-pop-only
+      :help "Replace previous yanked kill on search string"])
+    "---"
+    ["Lax whitespace matching" isearch-toggle-lax-whitespace
+     :help "Lax whitespace matching"
+     :style toggle
+     :selected isearch-lax-whitespace]
+    ["Case folding matching" isearch-toggle-case-fold
+     :help "Case folding matching"
+     :style toggle
+     :selected isearch-case-fold-search]
+    ["Character folding matching" isearch-toggle-char-fold
+     :help "Character folding matching"
+     :style toggle
+     :selected (eq isearch-regexp-function
+                   'char-fold-to-regexp)]
+    ["Invisible text matching" isearch-toggle-invisible
+     :help "Invisible text matching"
+     :style toggle
+     :selected isearch-invisible]
+    ["Regexp matching" isearch-toggle-regexp
+     :help "Regexp matching"
+     :style toggle
+     :selected isearch-regexp]
+    ["Symbol matching" isearch-toggle-symbol
+     :help "Symbol matching"
+     :style toggle
+     :selected (eq isearch-regexp-function
+                   'isearch-symbol-regexp)]
+    ["Word matching" isearch-toggle-word
+     :help "Word matching"
+     :style toggle
+     :selected (eq isearch-regexp-function 'word-search-regexp)]
+    "---"
+    ["Search for literal char" isearch-quote-char
+     :help "Search for literal char"]
+    ["Search for char by name" isearch-char-by-name
+     :help "Search for character by name"]
+    "---"
+    ["Toggle input method" isearch-toggle-input-method
+     :help "Toggle input method for search"]
+    ["Turn on specific input method" isearch-toggle-specified-input-method
+     :help "Turn on specific input method for search"]
+    ["Turn on transient input method" isearch-transient-input-method
+     :help "Turn on transient input method for search"]
+    "---"
+    ["Highlight all matches for search string" isearch-highlight-regexp
+     :help "Highlight all matches for current search string"]
+    ["Show all matches for search string" isearch-occur
+     :help "Show all matches for current search string"]
+    ["Replace search string" isearch-query-replace
+     :help "Replace matches for current search string"]
+    ["Replace search string as regexp" isearch-query-replace-regexp
+     :help "Replace matches for current search string as regexp"]
+    "---"
+    ["Complete current search string" isearch-complete
+     :help "Complete current search string over search history"]))
+
 (defvar isearch-tool-bar-old-map nil
   "Variable holding the old local value of `tool-bar-map', if any.")
 
@@ -1499,7 +1449,7 @@ REGEXP if non-nil says use the regexp search ring."
   (apply 'propertize string properties))
 
 (defun isearch-update-from-string-properties (string)
-  "Update isearch properties from the isearch string"
+  "Update isearch properties from the isearch STRING."
   (when (plist-member (text-properties-at 0 string) 'isearch-case-fold-search)
     (setq isearch-case-fold-search
          (get-text-property 0 'isearch-case-fold-search string)))
@@ -2536,7 +2486,7 @@ minibuffer to read a string from the `kill-ring' as 
`yank-pop' does."
 Unlike `isearch-yank-pop', when this command is called not immediately
 after a `isearch-yank-kill' or a `isearch-yank-pop-only', it only pops
 the last killed string instead of activating the minibuffer to read
-a string from the `kill-ring' as `yank-pop' does.  The prefix arg C-u
+a string from the `kill-ring' as `yank-pop' does.  The prefix arg 
\\[universal-argument]
 always reads a string from the `kill-ring' using the minibuffer."
   (interactive "P")
   (cond
@@ -2695,7 +2645,7 @@ With argument, add COUNT copies of the character."
                                                      string ""))))))))
 
 (defun isearch-search-and-update ()
-  ;; Do the search and update the display.
+  "Do the search and update the display."
   (when (or isearch-success
            ;; Unsuccessful regexp search may become successful by
            ;; addition of characters which make isearch-string valid
@@ -3227,7 +3177,7 @@ If there is no completion possible, say so and continue 
searching."
 ;; Message string
 
 (defun isearch-message (&optional c-q-hack ellipsis)
-  ;; Generate and print the message string.
+  "Generate and print the message string."
 
   ;; N.B.: This function should always be called with point at the
   ;; search point, because in certain (rare) circumstances, undesired
@@ -3356,7 +3306,7 @@ the word mode."
 
 (defun isearch-lazy-count-format (&optional suffix-p)
   "Format the current match number and the total number of matches.
-When SUFFIX-P is non-nil, the returned string is indended for
+When SUFFIX-P is non-nil, the returned string is intended for
 isearch-message-suffix prompt.  Otherwise, for isearch-message-prefix."
   (let ((format-string (if suffix-p
                            lazy-count-suffix-format
@@ -3481,7 +3431,7 @@ Optional third argument, if t, means if fail just return 
nil (no error).
       pos1)))
 
 (defun isearch-search ()
-  ;; Do the search with the current search string.
+  "Do the search with the current search string."
   (if (and (eq isearch-case-fold-search t) search-upper-case)
       (setq isearch-case-fold-search
            (isearch-no-upper-case-p isearch-string isearch-regexp)))
@@ -4127,13 +4077,13 @@ Attempt to do the search exactly the way the pending 
Isearch would."
   "Update highlighting of other matches in the full buffer."
   (let ((max lazy-highlight-buffer-max-at-a-time)
         (looping t)
-        nomore window-start window-end
-        (opoint (point)))
+        nomore opoint window-start window-end)
     (with-local-quit
       (save-selected-window
        (if (and (window-live-p isearch-lazy-highlight-window)
                 (not (memq (selected-window) 
isearch-lazy-highlight-window-group)))
            (select-window isearch-lazy-highlight-window))
+       (setq opoint (point))
        (setq window-start (window-group-start))
        (setq window-end (window-group-end))
        (save-excursion
diff --git a/lisp/jit-lock.el b/lisp/jit-lock.el
index d169e40..a128792 100644
--- a/lisp/jit-lock.el
+++ b/lisp/jit-lock.el
@@ -105,7 +105,7 @@ This means those subsequent lines are refontified to 
reflect their new
 syntactic context, after `jit-lock-context-time' seconds.
 If any other value, e.g., `syntax-driven', it means refontification of
 subsequent lines to reflect their new syntactic context may or may not
-occur after `jit-lock-context-time', depending on the the font-lock
+occur after `jit-lock-context-time', depending on the font-lock
 definitions of the buffer.  Specifically, if `font-lock-keywords-only'
 is nil in a buffer, which generally means the syntactic fontification
 is done using the buffer mode's syntax table, the syntactic
diff --git a/lisp/json.el b/lisp/json.el
index 1f1f608..0e61e1a 100644
--- a/lisp/json.el
+++ b/lisp/json.el
@@ -26,7 +26,7 @@
 ;; This is a library for parsing and generating JSON (JavaScript Object
 ;; Notation).
 
-;; Learn all about JSON here: <URL:http://json.org/>.
+;; Learn all about JSON here: <URL:https://json.org/>.
 
 ;; The user-serviceable entry points for the parser are the functions
 ;; `json-read' and `json-read-from-string'.  The encoder has a single
@@ -40,6 +40,17 @@
 ;; Similarly, since `false' and `null' are distinct in JSON, you can
 ;; distinguish them by binding `json-false' and `json-null' as desired.
 
+;;; Organization:
+
+;; Historically json.el used the prefix `json-read-' for decoding and
+;; the prefix `json-encode-' for encoding.  Many of these definitions
+;; are used by external packages since few were marked as internal.
+;; Optimizing the encoder to manipulate a buffer rather than strings
+;; while minimizing code duplication therefore necessitated a new
+;; namespace `json--print-'.  This rendered many encoding functions
+;; obsolete and unused, but those considered externally useful are
+;; kept for backward compatibility and as a public API.
+
 ;;; History:
 
 ;; 2006-03-11 - Initial version.
@@ -57,7 +68,7 @@
 (require 'map)
 (require 'subr-x)
 
-;; Parameters
+;;;; Parameters
 
 (defvar json-object-type 'alist
   "Type to convert JSON objects to.
@@ -102,13 +113,22 @@ this around your call to `json-read' instead of `setq'ing 
it.")
   "Value to use as an element separator when encoding.")
 
 (defvar json-encoding-default-indentation "  "
-  "The default indentation level for encoding.
+  "String used for a single indentation level during encoding.
+This value is repeated for each further nested element.
+Used only when `json-encoding-pretty-print' is non-nil.")
+
+(defvar json--print-indentation-prefix "\n"
+  "String used to start indentation during encoding.
 Used only when `json-encoding-pretty-print' is non-nil.")
 
-(defvar json--encoding-current-indentation "\n"
-  "Internally used to keep track of the current indentation level of encoding.
+(defvar json--print-indentation-depth 0
+  "Current indentation level during encoding.
+Dictates repetitions of `json-encoding-default-indentation'.
 Used only when `json-encoding-pretty-print' is non-nil.")
 
+(defvar json--print-keyval-separator ":"
+  "String used to separate key-value pairs during encoding.")
+
 (defvar json-encoding-pretty-print nil
   "If non-nil, then the output of `json-encode' will be pretty-printed.")
 
@@ -137,7 +157,7 @@ respectively, with no arguments.")
 
 
 
-;;; Utilities
+;;;; Utilities
 
 (define-obsolete-function-alias 'json-join #'string-join "28.1")
 
@@ -169,18 +189,38 @@ destructively modify PLIST to produce the result."
       (setcdr (cdr plist) prev)))
   plist)
 
+;; Encoder utilities
+
+(defmacro json--with-output-to-string (&rest body)
+  "Eval BODY in a temporary buffer bound to `standard-output'.
+Return the resulting buffer contents as a string."
+  (declare (indent 0) (debug t))
+  `(with-output-to-string
+     (with-current-buffer standard-output
+       ;; This affords decent performance gains.
+       (setq-local inhibit-modification-hooks t)
+       ,@body)))
+
 (defmacro json--with-indentation (&rest body)
-  "Evaluate BODY with the correct indentation for JSON encoding.
-This macro binds `json--encoding-current-indentation' according
-to `json-encoding-pretty-print' around BODY."
+  "Eval BODY with the JSON encoding nesting incremented by one step.
+This macro sets up appropriate variable bindings for
+`json--print-indentation' to produce the correct indentation when
+`json-encoding-pretty-print' is non-nil."
   (declare (debug t) (indent 0))
-  `(let ((json--encoding-current-indentation
-          (if json-encoding-pretty-print
-              (concat json--encoding-current-indentation
-                      json-encoding-default-indentation)
-            "")))
+  `(let ((json--print-indentation-prefix
+          (if json-encoding-pretty-print json--print-indentation-prefix ""))
+         (json--print-keyval-separator (if json-encoding-pretty-print ": " 
":"))
+         (json--print-indentation-depth (1+ json--print-indentation-depth)))
      ,@body))
 
+(defun json--print-indentation ()
+  "Insert the current indentation for JSON encoding at point.
+Has no effect if `json-encoding-pretty-print' is nil."
+  (when json-encoding-pretty-print
+    (insert json--print-indentation-prefix)
+    (dotimes (_ json--print-indentation-depth)
+      (insert json-encoding-default-indentation))))
+
 ;; Reader utilities
 
 (define-inline json-advance (&optional n)
@@ -210,8 +250,6 @@ Signal `json-end-of-file' if called at the end of the 
buffer."
   ;; definition of whitespace in JSON.
   (inline-quote (skip-chars-forward "\t\n\r ")))
 
-
-
 ;; Error conditions
 
 (define-error 'json-error "Unknown JSON error")
@@ -228,7 +266,7 @@ Signal `json-end-of-file' if called at the end of the 
buffer."
 
 
 
-;;; Paths
+;;;; Paths
 
 (defvar json--path '()
   "Keeps track of the path during recursive calls to `json-read'.
@@ -283,7 +321,9 @@ element in a deeply nested structure."
       (when (plist-get path :path)
         path))))
 
-;;; Keywords
+
+
+;;;; Keywords
 
 (defconst json-keywords '("true" "false" "null")
   "List of JSON keywords.")
@@ -316,7 +356,13 @@ element in a deeply nested structure."
         ((eq keyword json-false) "false")
         ((eq keyword json-null)  "null")))
 
-;;; Numbers
+(defun json--print-keyword (keyword)
+  "Insert KEYWORD as a JSON value at point.
+Return nil if KEYWORD is not recognized as a JSON keyword."
+  (prog1 (setq keyword (json-encode-keyword keyword))
+    (and keyword (insert keyword))))
+
+;;;; Numbers
 
 ;; Number parsing
 
@@ -339,10 +385,9 @@ element in a deeply nested structure."
 
 ;; Number encoding
 
-(defalias 'json-encode-number #'number-to-string
-  "Return a JSON representation of NUMBER.")
+(define-obsolete-function-alias 'json-encode-number #'json-encode "28.1")
 
-;;; Strings
+;;;; Strings
 
 (defconst json-special-chars
   '((?\" . ?\")
@@ -410,58 +455,52 @@ element in a deeply nested structure."
 
 ;; String encoding
 
-;; Escape only quotation mark, backslash, and the control
-;; characters U+0000 to U+001F (RFC 4627, ECMA-404).
-(rx-define json--escape (in ?\" ?\\ cntrl))
-
-(defvar json--long-string-threshold 200
-  "Length above which strings are considered long for JSON encoding.
-It is generally faster to manipulate such strings in a buffer
-rather than directly.")
-
-(defvar json--string-buffer nil
-  "Buffer used for encoding Lisp strings as JSON.
-Initialized lazily by `json-encode-string'.")
+(defun json--print-string (string &optional from)
+  "Insert a JSON representation of STRING at point.
+FROM is the index of STRING to start from and defaults to 0."
+  (insert ?\")
+  (goto-char (prog1 (point) (princ string)))
+  (and from (delete-char from))
+  ;; Escape only quotation mark, backslash, and the control
+  ;; characters U+0000 to U+001F (RFC 4627, ECMA-404).
+  (while (re-search-forward (rx (in ?\" ?\\ cntrl)) nil 'move)
+    (let ((char (preceding-char)))
+      (delete-char -1)
+      (insert ?\\ (or
+                   ;; Special JSON character (\n, \r, etc.).
+                   (car (rassq char json-special-chars))
+                   ;; Fallback: UCS code point in \uNNNN form.
+                   (format "u%04x" char)))))
+  (insert ?\")
+  string)
 
 (defun json-encode-string (string)
   "Return a JSON representation of STRING."
-  ;; Try to avoid buffer overhead in trivial cases, while also
-  ;; avoiding searching pathological strings for escape characters.
-  ;; Since `string-match-p' doesn't take a LIMIT argument, we use
-  ;; string length as our heuristic.  See also bug#20154.
-  (if (and (< (length string) json--long-string-threshold)
-           (not (string-match-p (rx json--escape) string)))
-      (concat "\"" (substring-no-properties string) "\"")
-    (with-current-buffer
-        (or json--string-buffer
-            (with-current-buffer (generate-new-buffer " *json-string*" t)
-              ;; This seems to afford decent performance gains.
-              (setq-local inhibit-modification-hooks t)
-              (setq json--string-buffer (current-buffer))))
-      (insert ?\" (substring-no-properties string)) ; see bug#43549
-      (goto-char (1+ (point-min)))
-      (while (re-search-forward (rx json--escape) nil 'move)
-        (let ((char (preceding-char)))
-          (delete-char -1)
-          (insert ?\\ (or
-                       ;; Special JSON character (\n, \r, etc.).
-                       (car (rassq char json-special-chars))
-                       ;; Fallback: UCS code point in \uNNNN form.
-                       (format "u%04x" char)))))
-      (insert ?\")
-      ;; Empty buffer for next invocation.
-      (delete-and-extract-region (point-min) (point-max)))))
+  (json--with-output-to-string (json--print-string string)))
+
+(defun json--print-stringlike (object)
+  "Insert OBJECT encoded as a JSON string at point.
+Return nil if OBJECT cannot be encoded as a JSON string."
+  (cond ((stringp object)  (json--print-string object))
+        ((keywordp object) (json--print-string (symbol-name object) 1))
+        ((symbolp object)  (json--print-string (symbol-name object)))))
+
+(defun json--print-key (object)
+  "Insert a JSON key representation of OBJECT at point.
+Signal `json-key-format' if it cannot be encoded as a string."
+  (or (json--print-stringlike object)
+      (signal 'json-key-format (list object))))
 
 (defun json-encode-key (object)
   "Return a JSON representation of OBJECT.
 If the resulting JSON object isn't a valid JSON object key,
 this signals `json-key-format'."
-  (let ((encoded (json-encode object)))
-    (unless (stringp (json-read-from-string encoded))
-      (signal 'json-key-format (list object)))
-    encoded))
+  (declare (obsolete json-encode "28.1"))
+  (json--with-output-to-string (json--print-key object)))
 
-;;; Objects
+;;;; Objects
+
+;; JSON object parsing
 
 (defun json-new-object ()
   "Create a new Elisp object corresponding to an empty JSON object.
@@ -494,8 +533,6 @@ Please see the documentation of `json-object-type' and 
`json-key-type'."
           ((eq json-object-type 'plist)
            (cons key (cons value object))))))
 
-;; JSON object parsing
-
 (defun json-read-object ()
   "Read the JSON object at point."
   ;; Skip over the '{'.
@@ -530,95 +567,81 @@ Please see the documentation of `json-object-type' and 
`json-key-type'."
       ('plist (json--plist-nreverse elements))
       (_ elements))))
 
+;; JSON object encoding
+
+(defun json--print-pair (key val)
+  "Insert JSON representation of KEY-VAL pair at point.
+This always inserts a trailing `json-encoding-separator'."
+  (json--print-indentation)
+  (json--print-key key)
+  (insert json--print-keyval-separator)
+  (json--print val)
+  (insert json-encoding-separator))
+
+(defun json--print-map (map)
+  "Insert JSON object representation of MAP at point.
+This works for any MAP satisfying `mapp'."
+  (insert ?\{)
+  (unless (map-empty-p map)
+    (json--with-indentation
+      (map-do #'json--print-pair map)
+      (delete-char (- (length json-encoding-separator))))
+    (or json-encoding-lisp-style-closings
+        (json--print-indentation)))
+  (insert ?\}))
+
+(defun json--print-unordered-map (map)
+  "Like `json--print-map', but optionally sort MAP first.
+If `json-encoding-object-sort-predicate' is non-nil, this first
+transforms an unsortable MAP into a sortable alist."
+  (if (and json-encoding-object-sort-predicate
+           (not (map-empty-p map)))
+      (json--print-alist (map-pairs map) t)
+    (json--print-map map)))
+
 ;; Hash table encoding
 
-(defun json-encode-hash-table (hash-table)
-  "Return a JSON representation of HASH-TABLE."
-  (cond ((hash-table-empty-p hash-table) "{}")
-        (json-encoding-object-sort-predicate
-         (json--encode-alist (map-pairs hash-table) t))
-        (t
-         (let ((kv-sep (if json-encoding-pretty-print ": " ":"))
-               result)
-           (json--with-indentation
-             (maphash
-              (lambda (k v)
-                (push (concat json--encoding-current-indentation
-                              (json-encode-key k)
-                              kv-sep
-                              (json-encode v))
-                      result))
-              hash-table))
-           (concat "{"
-                   (string-join (nreverse result) json-encoding-separator)
-                   (and json-encoding-pretty-print
-                        (not json-encoding-lisp-style-closings)
-                        json--encoding-current-indentation)
-                   "}")))))
+(define-obsolete-function-alias 'json-encode-hash-table #'json-encode "28.1")
 
 ;; List encoding (including alists and plists)
 
-(defun json--encode-alist (alist &optional destructive)
-  "Return a JSON representation of ALIST.
-DESTRUCTIVE non-nil means it is safe to modify ALIST by
-side-effects."
-  (when json-encoding-object-sort-predicate
-    (setq alist (sort (if destructive alist (copy-sequence alist))
-                      (lambda (a b)
-                        (funcall json-encoding-object-sort-predicate
-                                 (car a) (car b))))))
-  (concat "{"
-          (let ((kv-sep (if json-encoding-pretty-print ": " ":")))
-            (json--with-indentation
-              (mapconcat (lambda (cons)
-                           (concat json--encoding-current-indentation
-                                   (json-encode-key (car cons))
-                                   kv-sep
-                                   (json-encode (cdr cons))))
-                         alist
-                         json-encoding-separator)))
-          (and json-encoding-pretty-print
-               (not json-encoding-lisp-style-closings)
-               json--encoding-current-indentation)
-          "}"))
+(defun json--print-alist (alist &optional destructive)
+  "Insert a JSON representation of ALIST at point.
+Sort ALIST first if `json-encoding-object-sort-predicate' is
+non-nil.  Sorting can optionally be DESTRUCTIVE for speed."
+  (json--print-map (if (and json-encoding-object-sort-predicate alist)
+                       (sort (if destructive alist (copy-sequence alist))
+                             (lambda (a b)
+                               (funcall json-encoding-object-sort-predicate
+                                        (car a) (car b))))
+                     alist)))
+
+;; The following two are unused but useful to keep around due to the
+;; inherent ambiguity of lists.
 
 (defun json-encode-alist (alist)
   "Return a JSON representation of ALIST."
-  (if alist (json--encode-alist alist) "{}"))
+  (json--with-output-to-string (json--print-alist alist)))
 
 (defun json-encode-plist (plist)
   "Return a JSON representation of PLIST."
-  (cond ((null plist) "{}")
-        (json-encoding-object-sort-predicate
-         (json--encode-alist (map-pairs plist) t))
-        (t
-         (let ((kv-sep (if json-encoding-pretty-print ": " ":"))
-               result)
-           (json--with-indentation
-             (while plist
-               (push (concat json--encoding-current-indentation
-                             (json-encode-key (pop plist))
-                             kv-sep
-                             (json-encode (pop plist)))
-                     result)))
-           (concat "{"
-                   (string-join (nreverse result) json-encoding-separator)
-                   (and json-encoding-pretty-print
-                        (not json-encoding-lisp-style-closings)
-                        json--encoding-current-indentation)
-                   "}")))))
+  (json--with-output-to-string (json--print-unordered-map plist)))
+
+(defun json--print-list (list)
+  "Like `json-encode-list', but insert the JSON at point."
+  (cond ((json-alist-p list) (json--print-alist list))
+        ((json-plist-p list) (json--print-unordered-map list))
+        ((listp list)        (json--print-array list))
+        ((signal 'json-error (list list)))))
 
 (defun json-encode-list (list)
   "Return a JSON representation of LIST.
-Tries to DWIM: simple lists become JSON arrays, while alists and plists
-become JSON objects."
-  (cond ((json-alist-p list) (json-encode-alist list))
-        ((json-plist-p list) (json-encode-plist list))
-        ((listp list)        (json-encode-array list))
-        (t
-         (signal 'json-error (list list)))))
+Tries to DWIM: alists and plists become JSON objects, while
+simple lists become JSON arrays."
+  (declare (obsolete json-encode "28.1"))
+  (json--with-output-to-string (json--print-list list)))
 
-;;; Arrays
+;;;; Arrays
 
 ;; Array parsing
 
@@ -651,29 +674,32 @@ become JSON objects."
 
 ;; Array encoding
 
+(defun json--print-array (array)
+  "Like `json-encode-array', but insert the JSON at point."
+  (insert ?\[)
+  (unless (length= array 0)
+    (json--with-indentation
+      (json--print-indentation)
+      (let ((first t))
+        (mapc (lambda (elt)
+                (if first
+                    (setq first nil)
+                  (insert json-encoding-separator)
+                  (json--print-indentation))
+                (json--print elt))
+              array)))
+    (or json-encoding-lisp-style-closings
+        (json--print-indentation)))
+  (insert ?\]))
+
 (defun json-encode-array (array)
-  "Return a JSON representation of ARRAY."
-  (if (and json-encoding-pretty-print
-           (if (listp array)
-               array
-             (> (length array) 0)))
-      (concat
-       "["
-       (json--with-indentation
-         (concat json--encoding-current-indentation
-                 (mapconcat #'json-encode array
-                            (concat json-encoding-separator
-                                    json--encoding-current-indentation))))
-       (unless json-encoding-lisp-style-closings
-         json--encoding-current-indentation)
-       "]")
-    (concat "["
-            (mapconcat #'json-encode array json-encoding-separator)
-            "]")))
+  "Return a JSON representation of ARRAY.
+ARRAY can also be a list."
+  (json--with-output-to-string (json--print-array array)))
 
 
 
-;;; Reader
+;;;; Reader
 
 (defmacro json-readtable-dispatch (char)
   "Dispatch reader function for CHAR at point.
@@ -729,7 +755,17 @@ you will get the following structure returned:
 
 
 
-;;; Encoder
+;;;; Encoder
+
+(defun json--print (object)
+  "Like `json-encode', but insert or print the JSON at point."
+  (cond ((json--print-keyword object))
+        ((listp object)         (json--print-list object))
+        ((json--print-stringlike object))
+        ((numberp object)       (prin1 object))
+        ((arrayp object)        (json--print-array object))
+        ((hash-table-p object)  (json--print-unordered-map object))
+        ((signal 'json-error (list object)))))
 
 (defun json-encode (object)
   "Return a JSON representation of OBJECT as a string.
@@ -737,21 +773,9 @@ you will get the following structure returned:
 OBJECT should have a structure like one returned by `json-read'.
 If an error is detected during encoding, an error based on
 `json-error' is signaled."
-  (cond ((eq object t)          (json-encode-keyword object))
-        ((eq object json-null)  (json-encode-keyword object))
-        ((eq object json-false) (json-encode-keyword object))
-        ((stringp object)       (json-encode-string object))
-        ((keywordp object)      (json-encode-string
-                                 (substring (symbol-name object) 1)))
-        ((listp object)         (json-encode-list object))
-        ((symbolp object)       (json-encode-string
-                                 (symbol-name object)))
-        ((numberp object)       (json-encode-number object))
-        ((arrayp object)        (json-encode-array object))
-        ((hash-table-p object)  (json-encode-hash-table object))
-        (t                      (signal 'json-error (list object)))))
-
-;;; Pretty printing & minimizing
+  (json--with-output-to-string (json--print object)))
+
+;;;; Pretty printing & minimizing
 
 (defun json-pretty-print-buffer (&optional minimize)
   "Pretty-print current buffer.
@@ -762,7 +786,7 @@ With prefix argument MINIMIZE, minimize it instead."
 (defvar json-pretty-print-max-secs 2.0
   "Maximum time for `json-pretty-print's comparison.
 The function `json-pretty-print' uses `replace-region-contents'
-(which see) passing the value of this variable as argument
+\(which see) passing the value of this variable as argument
 MAX-SECS.")
 
 (defun json-pretty-print (begin end &optional minimize)
@@ -774,6 +798,8 @@ With prefix argument MINIMIZE, minimize it instead."
         (json-null :json-null)
         ;; Ensure that ordering is maintained.
         (json-object-type 'alist)
+        ;; Ensure that keys survive roundtrip (bug#24252, bug#42545).
+        (json-key-type 'string)
         (orig-buf (current-buffer))
         error)
     ;; Strategy: Repeatedly `json-read' from the original buffer and
diff --git a/lisp/language/cyrillic.el b/lisp/language/cyrillic.el
index c12096f..b64a237 100644
--- a/lisp/language/cyrillic.el
+++ b/lisp/language/cyrillic.el
@@ -33,7 +33,7 @@
 ;; are converted to Unicode internally.  See
 ;; <URL:http://www.ecma.ch/ecma1/STAND/ECMA-113.HTM>.  For more info
 ;; on Cyrillic charsets, see
-;; <URL:http://czyborra.com/charsets/cyrillic.html>.  The KOI and
+;; <URL:https://czyborra.com/charsets/cyrillic.html>.  The KOI and
 ;; Alternativnyj coding systems should live in code-pages.el, but
 ;; they've always been preloaded and the coding system autoload
 ;; mechanism didn't get accepted, so they have to stay here and
diff --git a/lisp/ldefs-boot.el b/lisp/ldefs-boot.el
index 9924d62..c9210c6 100644
--- a/lisp/ldefs-boot.el
+++ b/lisp/ldefs-boot.el
@@ -62,7 +62,7 @@ should return a grid vector array that is the new solution.
 ;;;### (autoloads nil "add-log" "vc/add-log.el" (0 0 0 0))
 ;;; Generated autoloads from vc/add-log.el
 
-(put 'change-log-default-name 'safe-local-variable 'string-or-null-p)
+(put 'change-log-default-name 'safe-local-variable #'string-or-null-p)
 
 (defvar add-log-current-defun-function nil "\
 If non-nil, function to guess name of surrounding function.
@@ -1881,7 +1881,7 @@ specifies in the mode line.
 Activate Mouse Avoidance mode.
 See function `mouse-avoidance-mode' for possible values.
 Setting this variable directly does not take effect;
-use either \\[customize] or the function `mouse-avoidance-mode'.")
+use either \\[customize] or \\[mouse-avoidance-mode].")
 
 (custom-autoload 'mouse-avoidance-mode "avoid" nil)
 
@@ -2529,7 +2529,7 @@ deletion, or > if it is flagged for displaying." t nil)
 (defalias 'edit-bookmarks 'bookmark-bmenu-list)
 
 (autoload 'bookmark-bmenu-search "bookmark" "\
-Incremental search of bookmarks, hiding the non-matches as we go." t nil)
+Incremental search of bookmarks, hiding the non-matches as we go." 
'(bookmark-bmenu-mode) nil)
 
 (defvar menu-bar-bookmark-map (let ((map (make-sparse-keymap "Bookmark 
functions"))) (bindings--define-key map [load] '(menu-item "Load a Bookmark 
File..." bookmark-load :help "Load bookmarks from a bookmark file)")) 
(bindings--define-key map [write] '(menu-item "Save Bookmarks As..." 
bookmark-write :help "Write bookmarks to a file (reading the file name with the 
minibuffer)")) (bindings--define-key map [save] '(menu-item "Save Bookmarks" 
bookmark-save :help "Save currently defined bookm [...]
 
@@ -4410,11 +4410,6 @@ Returns a form where all lambdas don't have any free 
variables.
 
 \(fn FORM)" nil nil)
 
-(autoload 'cconv-warnings-only "cconv" "\
-Add the warnings that closure conversion would encounter.
-
-\(fn FORM)" nil nil)
-
 (register-definition-prefixes "cconv" '("cconv-"))
 
 ;;;***
@@ -5940,8 +5935,7 @@ span the needed amount of lines.
 
 Variables `cperl-pod-here-scan', `cperl-pod-here-fontify',
 `cperl-pod-face', `cperl-pod-head-face' control processing of POD and
-here-docs sections.  With capable Emaxen results of scan are used
-for indentation too, otherwise they are used for highlighting only.
+here-docs sections.  Results of scan are used for indentation too.
 
 Variables controlling indentation style:
  `cperl-tab-always-indent'
@@ -6405,9 +6399,9 @@ PACKAGE value appearing in the :package-version keyword.  
Since
 the user might see the value in an error message, a good choice is
 the official name of the package, such as MH-E or Gnus.")
 
-(defalias 'customize-changed 'customize-changed-options)
+(define-obsolete-function-alias 'customize-changed-options #'customize-changed 
"28.1")
 
-(autoload 'customize-changed-options "cus-edit" "\
+(autoload 'customize-changed "cus-edit" "\
 Customize all settings whose meanings have changed in Emacs itself.
 This includes new user options and faces, and new customization
 groups, as well as older options and faces whose meanings or
@@ -6775,6 +6769,13 @@ If the HANDLER returns a `dbus-error', it is propagated 
as return message.
 
 \(fn EVENT)" t nil)
 
+(autoload 'dbus-monitor "dbus" "\
+Invoke `dbus-register-monitor' interactively, and switch to the buffer.
+BUS is either a Lisp keyword, `:system' or `:session', or a
+string denoting the bus address.  The value nil defaults to `:session'.
+
+\(fn &optional BUS)" t nil)
+
 (register-definition-prefixes "dbus" '("dbus-"))
 
 ;;;***
@@ -7006,7 +7007,9 @@ The most useful commands are:
 \\[decipher-frequency-count]  Display the frequency of each ciphertext letter
 \\[decipher-adjacency-list]  Show adjacency list for current letter (lists 
letters appearing next to it)
 \\[decipher-make-checkpoint]  Save the current cipher alphabet (checkpoint)
-\\[decipher-restore-checkpoint]  Restore a saved cipher alphabet (checkpoint)" 
t nil)
+\\[decipher-restore-checkpoint]  Restore a saved cipher alphabet (checkpoint)
+
+\(fn)" t nil)
 
 (register-definition-prefixes "decipher" '("decipher-"))
 
@@ -7130,6 +7133,9 @@ KEYWORD-ARGS:
            :after-hook FORM
                    A single lisp form which is evaluated after the mode
                    hooks have been run.  It should not be quoted.
+           :interactive BOOLEAN
+                   Whether the derived mode should be `interactive' or not.
+                   The default is t.
 
 BODY:      forms to execute just before running the
            hooks for the new mode.  Do not use `interactive' here.
@@ -7475,13 +7481,13 @@ You can control what lines will be unwrapped by frobbing
 indicating the minimum and maximum length of an unwrapped citation line.  If
 NODISPLAY is non-nil, don't redisplay the article buffer.
 
-\(fn &optional NODISPLAY)" t nil)
+\(fn &optional NODISPLAY)" '(gnus-article-mode gnus-summary-mode) nil)
 
 (autoload 'gnus-article-outlook-repair-attribution "deuglify" "\
 Repair a broken attribution line.
 If NODISPLAY is non-nil, don't redisplay the article buffer.
 
-\(fn &optional NODISPLAY)" t nil)
+\(fn &optional NODISPLAY)" '(gnus-article-mode gnus-summary-mode) nil)
 
 (autoload 'gnus-outlook-deuglify-article "deuglify" "\
 Full deuglify of broken Outlook (Express) articles.
@@ -7489,10 +7495,10 @@ Treat \"smartquotes\", unwrap lines, repair attribution 
and
 rearrange citation.  If NODISPLAY is non-nil, don't redisplay the
 article buffer.
 
-\(fn &optional NODISPLAY)" t nil)
+\(fn &optional NODISPLAY)" '(gnus-article-mode gnus-summary-mode) nil)
 
 (autoload 'gnus-article-outlook-deuglify-article "deuglify" "\
-Deuglify broken Outlook (Express) articles and redisplay." t nil)
+Deuglify broken Outlook (Express) articles and redisplay." '(gnus-article-mode 
gnus-summary-mode) nil)
 
 (register-definition-prefixes "deuglify" '("gnus-"))
 
@@ -7559,23 +7565,22 @@ This is a mode for searching a dictionary server 
implementing the
 protocol defined in RFC 2229.
 
 This is a quick reference to this mode describing the default key bindings:
+\\<dictionary-mode-map>
+* \\[dictionary-close] close the dictionary buffer
+* \\[dictionary-help] display this help information
+* \\[dictionary-search] ask for a new word to search
+* \\[dictionary-lookup-definition] search the word at point
+* \\[forward-button] or TAB place point to the next link
+* \\[backward-button] or S-TAB place point to the prev link
 
-* q close the dictionary buffer
-* h display this help information
-* s ask for a new word to search
-* d search the word at point
-* n or Tab place point to the next link
-* p or S-Tab place point to the prev link
+* \\[dictionary-match-words] ask for a pattern and list all matching words.
+* \\[dictionary-select-dictionary] select the default dictionary
+* \\[dictionary-select-strategy] select the default search strategy
 
-* m ask for a pattern and list all matching words.
-* D select the default dictionary
-* M select the default search strategy
-
-* Return or Button2 visit that link
-" nil nil)
+* RET or <mouse-2> visit that link" nil nil)
 
 (autoload 'dictionary "dictionary" "\
-Create a new dictonary buffer and install dictionary-mode." t nil)
+Create a new dictionary buffer and install `dictionary-mode'." t nil)
 
 (autoload 'dictionary-search "dictionary" "\
 Search the WORD in DICTIONARY if given or in all if nil.
@@ -7606,7 +7611,7 @@ Display entries matching WORD or the current word if not 
given.
 Display tooltips for the current word.
 
 This function can be used to enable or disable the tooltip mode
-for the current buffer (based on ARG). If global-tooltip-mode is
+for the current buffer (based on ARG).  If global-tooltip-mode is
 active it will overwrite that mode for the current buffer.
 
 \(fn &optional ARG)" t nil)
@@ -7772,10 +7777,15 @@ Switches passed to `ls' for Dired.  MUST contain the 
`l' option.
 May contain all other options that don't contradict `-l';
 may contain even `F', `b', `i' and `s'.  See also the variable
 `dired-ls-F-marks-symlinks' concerning the `F' switch.
+
+If you have files with names with embedded newline characters, adding
+`b' to the switches will allow Dired to handle those files better.
+
 Options that include embedded whitespace must be quoted
 like this: \"--option=value with spaces\"; you can use
 `combine-and-quote-strings' to produce the correct quoting of
 each option.
+
 On systems such as MS-DOS and MS-Windows, which use `ls' emulation in Lisp,
 some of the `ls' switches are not supported; see the doc string of
 `insert-directory' in `ls-lisp.el' for more details.")
@@ -7873,19 +7883,9 @@ directories again, type \\[dired-do-redisplay] to relist 
the file at point or th
 subdirectory, or type \\[dired-build-subdir-alist] to parse the buffer
 again for the directory tree.
 
-Customization variables (rename this buffer and type \\[describe-variable] on 
each line
-for more info):
+See the `dired' customization group for a list of user options.
 
-  `dired-listing-switches'
-  `dired-trivial-filenames'
-  `dired-marker-char'
-  `dired-del-marker'
-  `dired-keep-marker-rename'
-  `dired-keep-marker-copy'
-  `dired-keep-marker-hardlink'
-  `dired-keep-marker-symlink'
-
-Hooks (use \\[describe-variable] to see their documentation):
+This mode runs the following hooks:
 
   `dired-before-readin-hook'
   `dired-after-readin-hook'
@@ -8266,6 +8266,13 @@ if some action was made, or nil if the URL is ignored.")
 ;;;### (autoloads nil "dns" "net/dns.el" (0 0 0 0))
 ;;; Generated autoloads from net/dns.el
 
+(autoload 'dns-query "dns" "\
+Query a DNS server for NAME of TYPE.
+If FULL, return the entire record returned.
+If REVERSE, look up an IP address.
+
+\(fn NAME &optional TYPE FULL REVERSE)" nil nil)
+
 (register-definition-prefixes "dns" '("dns-"))
 
 ;;;***
@@ -8487,6 +8494,10 @@ BODY contains code to execute each time the mode is 
enabled or disabled.
 :lighter SPEC  Same as the LIGHTER argument.
 :keymap MAP    Same as the KEYMAP argument.
 :require SYM   Same as in `defcustom'.
+:interactive VAL  Whether this mode should be a command or not.  The default
+                is to make it one; use nil to avoid that.  If VAL is a list,
+                it's interpreted as a list of major modes this minor mode
+                is useful in.
 :variable PLACE        The location to use instead of the variable MODE to 
store
                the state of the mode.  This can be simply a different
                named variable, or a generalized variable.
@@ -8586,158 +8597,6 @@ CSS contains a list of syntax specifications of the 
form (CHAR . SYNTAX).
 
 ;;;***
 
-;;;### (autoloads nil "easymenu" "emacs-lisp/easymenu.el" (0 0 0
-;;;;;;  0))
-;;; Generated autoloads from emacs-lisp/easymenu.el
-
-(autoload 'easy-menu-define "easymenu" "\
-Define a pop-up menu and/or menu bar menu specified by MENU.
-If SYMBOL is non-nil, define SYMBOL as a function to pop up the
-submenu defined by MENU, with DOC as its doc string.
-
-MAPS, if non-nil, should be a keymap or a list of keymaps; add
-the submenu defined by MENU to the keymap or each of the keymaps,
-as a top-level menu bar item.
-
-The first element of MENU must be a string.  It is the menu bar
-item name.  It may be followed by the following keyword argument
-pairs:
-
- :filter FUNCTION
-    FUNCTION must be a function which, if called with one
-    argument---the list of the other menu items---returns the
-    items to actually display.
-
- :visible INCLUDE
-    INCLUDE is an expression.  The menu is visible if the
-    expression evaluates to a non-nil value.  `:included' is an
-    alias for `:visible'.
-
- :active ENABLE
-    ENABLE is an expression.  The menu is enabled for selection
-    if the expression evaluates to a non-nil value.  `:enable' is
-    an alias for `:active'.
-
- :label FORM
-    FORM is an expression that is dynamically evaluated and whose
-    value serves as the menu's label (the default is the first
-    element of MENU).
-
- :help HELP
-    HELP is a string, the help to display for the menu.
-    In a GUI this is a \"tooltip\" on the menu button.  (Though
-    in Lucid :help is not shown for the top-level menu bar, only
-    for sub-menus.)
-
-The rest of the elements in MENU are menu items.
-A menu item can be a vector of three elements:
-
-  [NAME CALLBACK ENABLE]
-
-NAME is a string--the menu item name.
-
-CALLBACK is a command to run when the item is chosen, or an
-expression to evaluate when the item is chosen.
-
-ENABLE is an expression; the item is enabled for selection if the
-expression evaluates to a non-nil value.
-
-Alternatively, a menu item may have the form:
-
-   [ NAME CALLBACK [ KEYWORD ARG ]... ]
-
-where NAME and CALLBACK have the same meanings as above, and each
-optional KEYWORD and ARG pair should be one of the following:
-
- :keys KEYS
-    KEYS is a string; a keyboard equivalent to the menu item.
-    This is normally not needed because keyboard equivalents are
-    usually computed automatically.  KEYS is expanded with
-    `substitute-command-keys' before it is used.
-
- :key-sequence KEYS
-    KEYS is a hint for speeding up Emacs's first display of the
-    menu.  It should be nil if you know that the menu item has no
-    keyboard equivalent; otherwise it should be a string or
-    vector specifying a keyboard equivalent for the menu item.
-
- :active ENABLE
-    ENABLE is an expression; the item is enabled for selection
-    whenever this expression's value is non-nil.  `:enable' is an
-    alias for `:active'.
-
- :visible INCLUDE
-    INCLUDE is an expression; this item is only visible if this
-    expression has a non-nil value.  `:included' is an alias for
-    `:visible'.
-
- :label FORM
-    FORM is an expression that is dynamically evaluated and whose
-    value serves as the menu item's label (the default is NAME).
-
- :suffix FORM
-    FORM is an expression that is dynamically evaluated and whose
-    value is concatenated with the menu entry's label.
-
- :style STYLE
-    STYLE is a symbol describing the type of menu item; it should
-    be `toggle' (a checkbox), or `radio' (a radio button), or any
-    other value (meaning an ordinary menu item).
-
- :selected SELECTED
-    SELECTED is an expression; the checkbox or radio button is
-    selected whenever the expression's value is non-nil.
-
- :help HELP
-    HELP is a string, the help to display for the menu item.
-
-Alternatively, a menu item can be a string.  Then that string
-appears in the menu as unselectable text.  A string consisting
-solely of dashes is displayed as a menu separator.
-
-Alternatively, a menu item can be a list with the same format as
-MENU.  This is a submenu.
-
-\(fn SYMBOL MAPS DOC MENU)" nil t)
-
-(function-put 'easy-menu-define 'lisp-indent-function 'defun)
-
-(autoload 'easy-menu-do-define "easymenu" "\
-
-
-\(fn SYMBOL MAPS DOC MENU)" nil nil)
-
-(autoload 'easy-menu-create-menu "easymenu" "\
-Create a menu called MENU-NAME with items described in MENU-ITEMS.
-MENU-NAME is a string, the name of the menu.  MENU-ITEMS is a list of items
-possibly preceded by keyword pairs as described in `easy-menu-define'.
-
-\(fn MENU-NAME MENU-ITEMS)" nil nil)
-
-(autoload 'easy-menu-change "easymenu" "\
-Change menu found at PATH as item NAME to contain ITEMS.
-PATH is a list of strings for locating the menu that
-should contain a submenu named NAME.
-ITEMS is a list of menu items, as in `easy-menu-define'.
-These items entirely replace the previous items in that submenu.
-
-If MAP is specified, it should normally be a keymap; nil stands for the local
-menu-bar keymap.  It can also be a symbol, which has earlier been used as the
-first argument in a call to `easy-menu-define', or the value of such a symbol.
-
-If the menu located by PATH has no submenu named NAME, add one.
-If the optional argument BEFORE is present, add it just before
-the submenu named BEFORE, otherwise add it at the end of the menu.
-
-To implement dynamic menus, either call this from
-`menu-bar-update-hook' or use a menu filter.
-
-\(fn PATH NAME ITEMS &optional BEFORE MAP)" nil nil)
-
-(register-definition-prefixes "easymenu" '("add-submenu" "easy-menu-"))
-
-;;;***
-
 ;;;### (autoloads nil "ebnf-abn" "progmodes/ebnf-abn.el" (0 0 0 0))
 ;;; Generated autoloads from progmodes/ebnf-abn.el
 
@@ -9423,26 +9282,6 @@ an EDE controlled project.
 ;;;### (autoloads nil "edebug" "emacs-lisp/edebug.el" (0 0 0 0))
 ;;; Generated autoloads from emacs-lisp/edebug.el
 
-(defvar edebug-all-defs nil "\
-If non-nil, evaluating defining forms instruments for Edebug.
-This applies to `eval-defun', `eval-region', `eval-buffer', and
-`eval-current-buffer'.  `eval-region' is also called by
-`eval-last-sexp', and `eval-print-last-sexp'.
-
-You can use the command `edebug-all-defs' to toggle the value of this
-variable.  You may wish to make it local to each buffer with
-\(make-local-variable \\='edebug-all-defs) in your
-`emacs-lisp-mode-hook'.")
-
-(custom-autoload 'edebug-all-defs "edebug" t)
-
-(defvar edebug-all-forms nil "\
-Non-nil means evaluation of all forms will instrument for Edebug.
-This doesn't apply to loading or evaluations in the minibuffer.
-Use the command `edebug-all-forms' to toggle the value of this option.")
-
-(custom-autoload 'edebug-all-forms "edebug" t)
-
 (autoload 'edebug-basic-spec "edebug" "\
 Return t if SPEC uses only extant spec symbols.
 An extant spec symbol is a symbol that is not a function and has a
@@ -9476,7 +9315,7 @@ Toggle edebugging of all definitions." t nil)
 (autoload 'edebug-all-forms "edebug" "\
 Toggle edebugging of all forms." t nil)
 
-(register-definition-prefixes "edebug" '("cancel-edebug-on-entry" "edebug" 
"get-edebug-spec" "global-edebug-"))
+(register-definition-prefixes "edebug" '("arglist" "backquote-form" 
"def-declarations" "edebug" "function-form" "interactive" "lambda-" "name" 
"nested-backquote-form"))
 
 ;;;***
 
@@ -9498,9 +9337,9 @@ arguments after setting up the Ediff buffers.
 
 \(fn FILE-A FILE-B FILE-C &optional STARTUP-HOOKS)" t nil)
 
-(defalias 'ediff3 'ediff-files3)
+(defalias 'ediff3 #'ediff-files3)
 
-(defalias 'ediff 'ediff-files)
+(defalias 'ediff #'ediff-files)
 
 (autoload 'ediff-current-file "ediff" "\
 Start ediff between current buffer and its file on disk.
@@ -9526,7 +9365,7 @@ symbol describing the Ediff job type; it defaults to
 
 \(fn BUFFER-A BUFFER-B &optional STARTUP-HOOKS JOB-NAME)" t nil)
 
-(defalias 'ebuffers 'ediff-buffers)
+(defalias 'ebuffers #'ediff-buffers)
 
 (autoload 'ediff-buffers3 "ediff" "\
 Run Ediff on three buffers, BUFFER-A, BUFFER-B, and BUFFER-C.
@@ -9540,7 +9379,7 @@ symbol describing the Ediff job type; it defaults to
 
 \(fn BUFFER-A BUFFER-B BUFFER-C &optional STARTUP-HOOKS JOB-NAME)" t nil)
 
-(defalias 'ebuffers3 'ediff-buffers3)
+(defalias 'ebuffers3 #'ediff-buffers3)
 
 (autoload 'ediff-directories "ediff" "\
 Run Ediff on a pair of directories, DIR1 and DIR2, comparing files that have
@@ -9549,7 +9388,7 @@ expression; only file names that match the regexp are 
considered.
 
 \(fn DIR1 DIR2 REGEXP)" t nil)
 
-(defalias 'edirs 'ediff-directories)
+(defalias 'edirs #'ediff-directories)
 
 (autoload 'ediff-directory-revisions "ediff" "\
 Run Ediff on a directory, DIR1, comparing its files with their revisions.
@@ -9558,7 +9397,7 @@ names.  Only the files that are under revision control 
are taken into account.
 
 \(fn DIR1 REGEXP)" t nil)
 
-(defalias 'edir-revisions 'ediff-directory-revisions)
+(defalias 'edir-revisions #'ediff-directory-revisions)
 
 (autoload 'ediff-directories3 "ediff" "\
 Run Ediff on three directories, DIR1, DIR2, and DIR3, comparing files that
@@ -9567,7 +9406,7 @@ regular expression; only file names that match the regexp 
are considered.
 
 \(fn DIR1 DIR2 DIR3 REGEXP)" t nil)
 
-(defalias 'edirs3 'ediff-directories3)
+(defalias 'edirs3 #'ediff-directories3)
 
 (autoload 'ediff-merge-directories "ediff" "\
 Run Ediff on a pair of directories, DIR1 and DIR2, merging files that have
@@ -9577,7 +9416,7 @@ MERGE-AUTOSTORE-DIR is the directory in which to store 
merged files.
 
 \(fn DIR1 DIR2 REGEXP &optional MERGE-AUTOSTORE-DIR)" t nil)
 
-(defalias 'edirs-merge 'ediff-merge-directories)
+(defalias 'edirs-merge #'ediff-merge-directories)
 
 (autoload 'ediff-merge-directories-with-ancestor "ediff" "\
 Merge files in directories DIR1 and DIR2 using files in ANCESTOR-DIR as 
ancestors.
@@ -9597,7 +9436,7 @@ MERGE-AUTOSTORE-DIR is the directory in which to store 
merged files.
 
 \(fn DIR1 REGEXP &optional MERGE-AUTOSTORE-DIR)" t nil)
 
-(defalias 'edir-merge-revisions 'ediff-merge-directory-revisions)
+(defalias 'edir-merge-revisions #'ediff-merge-directory-revisions)
 
 (autoload 'ediff-merge-directory-revisions-with-ancestor "ediff" "\
 Run Ediff on a directory, DIR1, merging its files with their revisions and 
ancestors.
@@ -9839,7 +9678,7 @@ Call `ediff-merge-directories-with-ancestor' with the 
next four command line arg
 (autoload 'ediff-show-registry "ediff-mult" "\
 Display Ediff's registry." t nil)
 
-(defalias 'eregistry 'ediff-show-registry)
+(defalias 'eregistry #'ediff-show-registry)
 
 (register-definition-prefixes "ediff-mult" '("ediff-"))
 
@@ -10866,10 +10705,6 @@ it has to be wrapped in `(eval (quote ...))'.
 
 (function-put 'ert-deftest 'lisp-indent-function '2)
 
-(put 'ert-deftest 'lisp-indent-function 2)
-
-(put 'ert-info 'lisp-indent-function 1)
-
 (autoload 'ert-run-tests-batch "ert" "\
 Run the tests specified by SELECTOR, printing results to the terminal.
 
@@ -10916,8 +10751,6 @@ Display the documentation for TEST-OR-TEST-NAME (a 
symbol or ert-test).
 ;;;### (autoloads nil "ert-x" "emacs-lisp/ert-x.el" (0 0 0 0))
 ;;; Generated autoloads from emacs-lisp/ert-x.el
 
-(put 'ert-with-test-buffer 'lisp-indent-function 1)
-
 (autoload 'ert-kill-all-test-buffers "ert-x" "\
 Kill all test buffers that are still live." t nil)
 
@@ -12034,9 +11867,9 @@ INC may be passed as a numeric prefix argument.
 The actual adjustment made depends on the final component of the
 key-binding used to invoke the command, with all modifiers removed:
 
-   +, =   Increase the default face height by one step
-   -      Decrease the default face height by one step
-   0      Reset the default face height to the global default
+   +, =   Increase the height of the default face by one step
+   -      Decrease the height of the default face by one step
+   0      Reset the height of the default face to the global default
 
 After adjusting, continue to read input events and further adjust
 the face height as long as the input event read
@@ -13931,7 +13764,7 @@ regular expression that can be used as an element of
 ;;;### (autoloads nil "generic-x" "generic-x.el" (0 0 0 0))
 ;;; Generated autoloads from generic-x.el
 
-(register-definition-prefixes "generic-x" '("default-generic-mode" "generic-"))
+(register-definition-prefixes "generic-x" '("alias-generic-mode" 
"ansible-inventory-generic-mode" "apache-" "astap-generic-mode" 
"default-generic-mode" "etc-" "fvwm-generic-mode" "generic-" 
"hosts-generic-mode" "ibis-generic-mode" "java-" "mail" "named-" 
"pkginfo-generic-mode" "prototype-generic-mode" "rc-generic-mode" "rul-" 
"samba-generic-mode" "show-tabs-generic-mode" "spice-generic-mode" 
"vrml-generic-mode" "x-resource-generic-mode" "xmodmap-generic-mode"))
 
 ;;;***
 
@@ -14190,7 +14023,7 @@ Make the current buffer look like a nice article." nil 
nil)
 ;;; Generated autoloads from gnus/gnus-bookmark.el
 
 (autoload 'gnus-bookmark-set "gnus-bookmark" "\
-Set a bookmark for this article." t nil)
+Set a bookmark for this article." '(gnus-article-mode gnus-summary-mode) nil)
 
 (autoload 'gnus-bookmark-jump "gnus-bookmark" "\
 Jump to a Gnus bookmark (BMK-NAME).
@@ -14296,7 +14129,7 @@ The value of `message-draft-headers' determines which 
headers are
 generated when the article is delayed.  Remaining headers are
 generated when the article is sent.
 
-\(fn DELAY)" t nil)
+\(fn DELAY)" '(message-mode) nil)
 
 (autoload 'gnus-delay-send-queue "gnus-delay" "\
 Send all the delayed messages that are due now." t nil)
@@ -14440,13 +14273,13 @@ Insert a random Face header from 
`gnus-face-directory'." nil nil)
 Display gravatar in the From header.
 If gravatar is already displayed, remove it.
 
-\(fn &optional FORCE)" t nil)
+\(fn &optional FORCE)" '(gnus-article-mode gnus-summary-mode) nil)
 
 (autoload 'gnus-treat-mail-gravatar "gnus-gravatar" "\
 Display gravatars in the Cc and To headers.
 If gravatars are already displayed, remove them.
 
-\(fn &optional FORCE)" t nil)
+\(fn &optional FORCE)" '(gnus-article-mode gnus-summary-mode) nil)
 
 (register-definition-prefixes "gnus-gravatar" '("gnus-gravatar-"))
 
@@ -14724,15 +14557,15 @@ This is typically a function to add in
 
 (autoload 'gnus-treat-from-picon "gnus-picon" "\
 Display picons in the From header.
-If picons are already displayed, remove them." t nil)
+If picons are already displayed, remove them." '(gnus-article-mode 
gnus-summary-mode) nil)
 
 (autoload 'gnus-treat-mail-picon "gnus-picon" "\
 Display picons in the Cc and To headers.
-If picons are already displayed, remove them." t nil)
+If picons are already displayed, remove them." '(gnus-article-mode 
gnus-summary-mode) nil)
 
 (autoload 'gnus-treat-newsgroups-picon "gnus-picon" "\
 Display picons in the Newsgroups and Followup-To headers.
-If picons are already displayed, remove them." t nil)
+If picons are already displayed, remove them." '(gnus-article-mode 
gnus-summary-mode) nil)
 
 (register-definition-prefixes "gnus-picon" '("gnus-picon-"))
 
@@ -14864,7 +14697,7 @@ between gnus-sieve-region-start and 
gnus-sieve-region-end with
 \(gnus-sieve-script gnus-sieve-select-method gnus-sieve-crosspost).
 See the documentation for these variables and functions for details." t nil)
 
-(autoload 'gnus-sieve-article-add-rule "gnus-sieve" nil t nil)
+(autoload 'gnus-sieve-article-add-rule "gnus-sieve" nil '(gnus-article-mode 
gnus-summary-mode) nil)
 
 (register-definition-prefixes "gnus-sieve" '("gnus-sieve-"))
 
@@ -15472,6 +15305,8 @@ arguments as NAME.  DO is a function as defined in 
`gv-get'.
 
 (or (assq 'gv-setter defun-declarations-alist) (push (list 'gv-setter 
#'gv--setter-defun-declaration) defun-declarations-alist))
 
+(let ((spec (get 'compiler-macro 'edebug-declaration-spec))) (put 'gv-expander 
'edebug-declaration-spec spec) (put 'gv-setter 'edebug-declaration-spec spec))
+
 (autoload 'gv-define-setter "gv" "\
 Define a setter method for generalized variable NAME.
 This macro is an easy-to-use substitute for `gv-define-expander' that works
@@ -15512,7 +15347,7 @@ The return value is the last VAL in the list.
 
 \(fn PLACE VAL PLACE VAL ...)" nil t)
 
-(put 'gv-place 'edebug-form-spec 'edebug-match-form)
+(def-edebug-elem-spec 'gv-place '(form))
 
 (autoload 'gv-ref "gv" "\
 Return a reference to PLACE.
@@ -15993,7 +15828,7 @@ Add xrefs for symbols in `pp's output between FROM and 
TO.
 (define-obsolete-function-alias 'help-xref-interned 'describe-symbol "25.1")
 
 (autoload 'help-bookmark-jump "help-mode" "\
-Jump to help-mode bookmark BOOKMARK.
+Jump to `help-mode' bookmark BOOKMARK.
 Handler function for record returned by `help-bookmark-make-record'.
 BOOKMARK is a bookmark name or a bookmark record.
 
@@ -17029,7 +16864,7 @@ If optional arg OTHER-WINDOW is non-nil, then use 
another window.
 
 \(fn &optional OTHER-WINDOW)" t nil)
 
-(register-definition-prefixes "ibuffer" '("filename" "ibuffer-" "locked" 
"mark" "mod" "name" "process" "read-only" "size"))
+(register-definition-prefixes "ibuffer" '("filename" "ibuffer-" "locked" 
"mark" "mod" "name" "process" "read-only" "recency" "size"))
 
 ;;;***
 
@@ -18192,7 +18027,7 @@ element should come before the second.  The arguments 
are cons cells;
 
 (custom-autoload 'imenu-sort-function "imenu" t)
 
-(defvar imenu-generic-expression nil "\
+(defvar-local imenu-generic-expression nil "\
 List of definition matchers for creating an Imenu index.
 Each element of this list should have the form
 
@@ -18228,9 +18063,7 @@ characters which normally have \"symbol\" syntax are 
considered to have
 \"word\" syntax during matching.")
 (put 'imenu-generic-expression 'risky-local-variable t)
 
-(make-variable-buffer-local 'imenu-generic-expression)
-
-(defvar imenu-create-index-function 'imenu-default-create-index-function "\
+(defvar-local imenu-create-index-function 'imenu-default-create-index-function 
"\
 The function to use for creating an index alist of the current buffer.
 
 It should be a function that takes no arguments and returns
@@ -18239,9 +18072,7 @@ called within a `save-excursion'.
 
 See `imenu--index-alist' for the format of the buffer index alist.")
 
-(make-variable-buffer-local 'imenu-create-index-function)
-
-(defvar imenu-prev-index-position-function 'beginning-of-defun "\
+(defvar-local imenu-prev-index-position-function 'beginning-of-defun "\
 Function for finding the next index position.
 
 If `imenu-create-index-function' is set to
@@ -18252,18 +18083,14 @@ file.
 The function should leave point at the place to be connected to the
 index and it should return nil when it doesn't find another index.")
 
-(make-variable-buffer-local 'imenu-prev-index-position-function)
-
-(defvar imenu-extract-index-name-function nil "\
+(defvar-local imenu-extract-index-name-function nil "\
 Function for extracting the index item name, given a position.
 
 This function is called after `imenu-prev-index-position-function'
 finds a position for an index item, with point at that position.
 It should return the name for that index item.")
 
-(make-variable-buffer-local 'imenu-extract-index-name-function)
-
-(defvar imenu-name-lookup-function nil "\
+(defvar-local imenu-name-lookup-function nil "\
 Function to compare string with index item.
 
 This function will be called with two strings, and should return
@@ -18274,18 +18101,28 @@ Set this to some other function for more advanced 
comparisons,
 such as \"begins with\" or \"name matches and number of
 arguments match\".")
 
-(make-variable-buffer-local 'imenu-name-lookup-function)
-
-(defvar imenu-default-goto-function 'imenu-default-goto-function "\
+(defvar-local imenu-default-goto-function 'imenu-default-goto-function "\
 The default function called when selecting an Imenu item.
 The function in this variable is called when selecting a normal index-item.")
-
-(make-variable-buffer-local 'imenu-default-goto-function)
 (put 'imenu--index-alist 'risky-local-variable t)
 
-(make-variable-buffer-local 'imenu-syntax-alist)
+(defvar-local imenu-syntax-alist nil "\
+Alist of syntax table modifiers to use while in `imenu--generic-function'.
+
+The car of the assocs may be either a character or a string and the
+cdr is a syntax description appropriate for `modify-syntax-entry'.  For
+a string, all the characters in the string get the specified syntax.
 
-(make-variable-buffer-local 'imenu-case-fold-search)
+This is typically used to give word syntax to characters which
+normally have symbol syntax to simplify `imenu-expression'
+and speed-up matching.")
+
+(defvar-local imenu-case-fold-search t "\
+Defines whether `imenu--generic-function' should fold case when matching.
+
+This variable should be set (only) by initialization code
+for modes which use `imenu--generic-function'.  If it is not set, but
+`font-lock-defaults' is set, then font-lock's setting is used.")
 
 (autoload 'imenu-add-to-menubar "imenu" "\
 Add an `imenu' entry to the menu bar for the current buffer.
@@ -20685,7 +20522,7 @@ to auto-complete your input based on the installed 
manual pages.
 (autoload 'man-follow "man" "\
 Get a Un*x manual page of the item under point and put it in a buffer.
 
-\(fn MAN-ARGS)" t nil)
+\(fn MAN-ARGS)" '(man-common) nil)
 
 (autoload 'Man-bookmark-jump "man" "\
 Default bookmark handler for Man buffers.
@@ -20922,9 +20759,12 @@ which specify the range to operate on.
 Command to parse command line mailto: links.
 This is meant to be used for MIME handlers: Setting the handler
 for \"x-scheme-handler/mailto;\" to \"emacs -f message-mailto %u\"
-will then start up Emacs ready to compose mail." t nil)
+will then start up Emacs ready to compose mail.  For emacsclient use
+  emacsclient -e '(message-mailto \"%u\")'
 
-(register-definition-prefixes "message" '("message-" "nil"))
+\(fn &optional URL)" t nil)
+
+(register-definition-prefixes "message" '("message-"))
 
 ;;;***
 
@@ -22202,7 +22042,8 @@ This affects the implicit sorting of lists of coding 
systems returned by
 operations such as `find-coding-systems-region'.
 
 \(fn CODING-SYSTEMS &rest BODY)" nil t)
-(put 'with-coding-priority 'lisp-indent-function 1)
+
+(function-put 'with-coding-priority 'lisp-indent-function '1)
 
 (autoload 'detect-coding-with-language-environment "mule-util" "\
 Detect a coding system for the text between FROM and TO with LANG-ENV.
@@ -24585,7 +24426,6 @@ PATTERN matches.  PATTERN can take one of the forms:
   (pred (not FUN)) matches if FUN called on EXPVAL returns nil.
   (app FUN PAT)    matches if FUN called on EXPVAL matches PAT.
   (guard BOOLEXP)  matches if BOOLEXP evaluates to non-nil.
-  (let PAT EXPR)   matches if EXPR matches PAT.
   (and PAT...)     matches if all the patterns match.
   (or PAT...)      matches if any of the patterns matches.
 
@@ -24595,7 +24435,7 @@ FUN in `pred' and `app' can take one of the forms:
   (F ARG1 .. ARGn)
      call F with ARG1..ARGn and EXPVAL as n+1'th argument
 
-FUN, BOOLEXP, EXPR, and subsequent PAT can refer to variables
+FUN, BOOLEXP, and subsequent PAT can refer to variables
 bound earlier in the pattern by a SYMBOL pattern.
 
 Additional patterns can be defined using `pcase-defmacro'.
@@ -27428,6 +27268,34 @@ recently executed command not bound to an input 
event\".
 
 \(fn REPEAT-ARG)" t nil)
 
+(defvar repeat-mode nil "\
+Non-nil if Repeat mode is enabled.
+See the `repeat-mode' command
+for a description of this minor mode.
+Setting this variable directly does not take effect;
+either customize it (see the info node `Easy Customization')
+or call the function `repeat-mode'.")
+
+(custom-autoload 'repeat-mode "repeat" nil)
+
+(autoload 'repeat-mode "repeat" "\
+Toggle Repeat mode.
+When Repeat mode is enabled, and the command symbol has the property named
+`repeat-map', this map is activated temporarily for the next command.
+
+If called interactively, toggle `Repeat mode'.  If the prefix argument
+is positive, enable the mode, and if it is zero or negative, disable
+the mode.
+
+If called from Lisp, toggle the mode if ARG is `toggle'.  Enable the
+mode if ARG is nil, omitted, or is a positive number.  Disable the
+mode if ARG is a negative number.
+
+The mode's hook is called both when the mode is enabled and when it is
+disabled.
+
+\(fn &optional ARG)" t nil)
+
 (register-definition-prefixes "repeat" '("repeat-"))
 
 ;;;***
@@ -28269,7 +28137,7 @@ Major mode for editing Ruby code.
 ;;;### (autoloads nil "ruler-mode" "ruler-mode.el" (0 0 0 0))
 ;;; Generated autoloads from ruler-mode.el
 
-(defvar ruler-mode nil "\
+(defvar-local ruler-mode nil "\
 Non-nil if Ruler mode is enabled.
 Use the command `ruler-mode' to change this variable.")
 
@@ -29433,6 +29301,12 @@ Equality is defined by TESTFN if non-nil or by `equal' 
if nil.
 
 \(fn SEQUENCE ELT &optional TESTFN)" nil nil)
 
+(autoload 'seq-intersection "seq" "\
+Return a list of the elements that appear in both SEQUENCE1 and SEQUENCE2.
+Equality is defined by TESTFN if non-nil or by `equal' if nil.
+
+\(fn SEQUENCE1 SEQUENCE2 &optional TESTFN)" nil nil)
+
 (autoload 'seq-group-by "seq" "\
 Apply FUNCTION to each element of SEQUENCE.
 Separate the elements of SEQUENCE into an alist using the results as
@@ -31785,9 +31659,7 @@ disabled.
 
 \(fn &optional ARG)" t nil)
 
-(defvar tab-line-exclude nil)
-
-(make-variable-buffer-local 'tab-line-exclude)
+(defvar-local tab-line-exclude nil)
 
 (put 'global-tab-line-mode 'globalized-minor-mode t)
 
@@ -35515,6 +35387,22 @@ first backend that could register the file is used.
 
 \(fn &optional VC-FILESET COMMENT)" t nil)
 
+(autoload 'vc-ignore "vc" "\
+Ignore FILE under the VCS of DIRECTORY.
+
+Normally, FILE is a wildcard specification that matches the files
+to be ignored.  When REMOVE is non-nil, remove FILE from the list
+of ignored files.
+
+DIRECTORY defaults to `default-directory' and is used to
+determine the responsible VC backend.
+
+When called interactively, prompt for a FILE to ignore, unless a
+prefix argument is given, in which case prompt for a file FILE to
+remove from the list of ignored files.
+
+\(fn FILE &optional DIRECTORY REMOVE)" t nil)
+
 (autoload 'vc-version-diff "vc" "\
 Report diffs between revisions REV1 and REV2 in the repository history.
 This compares two revisions of the current fileset.
@@ -36119,7 +36007,7 @@ Add a description of the problem and include a 
reproducible test case.
 Feel free to send questions and enhancement requests to <reto@gnu.org>.
 
 Official distribution is at
-URL `http://www.iis.ee.ethz.ch/~zimmi/emacs/vera-mode.html'
+URL `https://www.iis.ee.ethz.ch/~zimmi/emacs/vera-mode.html'
 
 
                                                   The Vera Mode Maintainer
@@ -36139,7 +36027,7 @@ Key bindings:
 ;;;### (autoloads nil "verilog-mode" "progmodes/verilog-mode.el"
 ;;;;;;  (0 0 0 0))
 ;;; Generated autoloads from progmodes/verilog-mode.el
-(push (purecopy '(verilog-mode 2020 6 27 14326051)) package--builtin-versions)
+(push (purecopy '(verilog-mode 2021 2 2 263931197)) package--builtin-versions)
 
 (autoload 'verilog-mode "verilog-mode" "\
 Major mode for editing Verilog code.
@@ -36888,13 +36776,11 @@ If nil, make an icon of the frame.  If non-nil, 
delete the frame.")
 
 (custom-autoload 'view-remove-frame-by-deleting "view" t)
 
-(defvar view-mode nil "\
+(defvar-local view-mode nil "\
 Non-nil if View mode is enabled.
 Don't change this variable directly, you must change it by one of the
 functions that enable or disable view mode.")
 
-(make-variable-buffer-local 'view-mode)
-
 (autoload 'kill-buffer-if-not-modified "view" "\
 Like `kill-buffer', but does nothing if the buffer is modified.
 
@@ -38476,12 +38362,12 @@ Zone out, completely." t nil)
 ;;;;;;  "cus-face.el" "cus-start.el" "custom.el" "dired-aux.el" "dired-x.el"
 ;;;;;;  "electric.el" "emacs-lisp/backquote.el" "emacs-lisp/byte-run.el"
 ;;;;;;  "emacs-lisp/cl-extra.el" "emacs-lisp/cl-macs.el" 
"emacs-lisp/cl-preloaded.el"
-;;;;;;  "emacs-lisp/cl-seq.el" "emacs-lisp/eieio-compat.el" 
"emacs-lisp/eieio-custom.el"
-;;;;;;  "emacs-lisp/eieio-opt.el" "emacs-lisp/float-sup.el" 
"emacs-lisp/lisp-mode.el"
-;;;;;;  "emacs-lisp/lisp.el" "emacs-lisp/macroexp.el" "emacs-lisp/map-ynp.el"
-;;;;;;  "emacs-lisp/nadvice.el" "emacs-lisp/syntax.el" "emacs-lisp/timer.el"
-;;;;;;  "env.el" "epa-hook.el" "erc/erc-autoaway.el" "erc/erc-button.el"
-;;;;;;  "erc/erc-capab.el" "erc/erc-dcc.el" "erc/erc-desktop-notifications.el"
+;;;;;;  "emacs-lisp/cl-seq.el" "emacs-lisp/easymenu.el" 
"emacs-lisp/eieio-compat.el"
+;;;;;;  "emacs-lisp/eieio-custom.el" "emacs-lisp/eieio-opt.el" 
"emacs-lisp/float-sup.el"
+;;;;;;  "emacs-lisp/lisp-mode.el" "emacs-lisp/lisp.el" "emacs-lisp/macroexp.el"
+;;;;;;  "emacs-lisp/map-ynp.el" "emacs-lisp/nadvice.el" "emacs-lisp/syntax.el"
+;;;;;;  "emacs-lisp/timer.el" "env.el" "epa-hook.el" "erc/erc-autoaway.el"
+;;;;;;  "erc/erc-button.el" "erc/erc-capab.el" "erc/erc-dcc.el" 
"erc/erc-desktop-notifications.el"
 ;;;;;;  "erc/erc-ezbounce.el" "erc/erc-fill.el" "erc/erc-identd.el"
 ;;;;;;  "erc/erc-imenu.el" "erc/erc-join.el" "erc/erc-list.el" "erc/erc-log.el"
 ;;;;;;  "erc/erc-match.el" "erc/erc-menu.el" "erc/erc-netsplit.el"
diff --git a/lisp/leim/quail/hangul.el b/lisp/leim/quail/hangul.el
index ca1aae7..c03e86b 100644
--- a/lisp/leim/quail/hangul.el
+++ b/lisp/leim/quail/hangul.el
@@ -1,4 +1,4 @@
-;;; hangul.el --- Korean Hangul input method
+;;; hangul.el --- Korean Hangul input method  -*- lexical-binding: t; -*-
 
 ;; Copyright (C) 2008-2021 Free Software Foundation, Inc.
 
@@ -88,9 +88,9 @@
 
 (defvar hangul-im-keymap
   (let ((map (make-sparse-keymap)))
-    (define-key map "\d" 'hangul-delete-backward-char)
-    (define-key map [f9] 'hangul-to-hanja-conversion)
-    (define-key map [Hangul_Hanja] 'hangul-to-hanja-conversion)
+    (define-key map "\d" #'hangul-delete-backward-char)
+    (define-key map [f9] #'hangul-to-hanja-conversion)
+    (define-key map [Hangul_Hanja] #'hangul-to-hanja-conversion)
     map)
   "Keymap for Hangul method.  It is used by all Hangul input methods.")
 
@@ -337,7 +337,7 @@ Other parts are the same as a `hangul3-input-method-cho'."
                         char)))))
              (aset hangul-queue 5 char)))
       (hangul-insert-character hangul-queue)
-    (if (zerop (apply '+ (append hangul-queue nil)))
+    (if (zerop (apply #'+ (append hangul-queue nil)))
        (hangul-insert-character (setq hangul-queue (vector 0 0 0 0 char 0)))
       (hangul-insert-character hangul-queue
                               (setq hangul-queue (vector 0 0 0 0 char 0))))))
@@ -349,7 +349,7 @@ Other parts are the same as a `hangul3-input-method-cho'."
     (while (and (> i 0) (zerop (aref hangul-queue i)))
       (setq i (1- i)))
     (aset hangul-queue i 0))
-  (if (notzerop (apply '+ (append hangul-queue nil)))
+  (if (notzerop (apply #'+ (append hangul-queue nil)))
       (hangul-insert-character hangul-queue)
     (delete-char -1)))
 
@@ -514,16 +514,16 @@ When a Korean input method is off, convert the following 
hangul character."
 (defvar-local hangul-input-method-help-text nil)
 
 ;;;###autoload
-(defun hangul-input-method-activate (input-method func help-text &rest args)
+(defun hangul-input-method-activate (_input-method func help-text &rest _args)
   "Activate Hangul input method INPUT-METHOD.
 FUNC is a function to handle input key.
 HELP-TEXT is a text set in `hangul-input-method-help-text'."
-  (setq deactivate-current-input-method-function 
'hangul-input-method-deactivate
-       describe-current-input-method-function 'hangul-input-method-help
+  (setq deactivate-current-input-method-function 
#'hangul-input-method-deactivate
+       describe-current-input-method-function #'hangul-input-method-help
        hangul-input-method-help-text help-text)
   (quail-delete-overlays)
   (if (eq (selected-window) (minibuffer-window))
-      (add-hook 'minibuffer-exit-hook 'quail-exit-from-minibuffer))
+      (add-hook 'minibuffer-exit-hook #'quail-exit-from-minibuffer))
   (setq-local input-method-function func))
 
 (defun hangul-input-method-deactivate ()
@@ -538,7 +538,7 @@ HELP-TEXT is a text set in `hangul-input-method-help-text'."
 
 (define-obsolete-function-alias
   'hangul-input-method-inactivate
-  'hangul-input-method-deactivate "24.3")
+  #'hangul-input-method-deactivate "24.3")
 
 (defun hangul-input-method-help ()
   "Describe the current Hangul input method."
diff --git a/lisp/leim/quail/indian.el b/lisp/leim/quail/indian.el
index 6f5054e..251b18c 100644
--- a/lisp/leim/quail/indian.el
+++ b/lisp/leim/quail/indian.el
@@ -1,4 +1,4 @@
-;;; indian.el --- Quail packages for inputting Indian
+;;; indian.el --- Quail packages for inputting Indian  -*- lexical-binding: t; 
-*-
 
 ;; Copyright (C) 2000-2021 Free Software Foundation, Inc.
 
@@ -39,7 +39,10 @@
 
 (defun quail-define-indian-trans-package (hashtbls pkgname
                                                   lang title doc)
-  (funcall 'quail-define-package pkgname lang title t doc
+  ;; This is a funcall to avoid `quail-update-leim-list-file'
+  ;; determining that this is a quail definition (it searches for
+  ;; "(quail-define-package").
+  (funcall #'quail-define-package pkgname lang title t doc
           nil nil nil nil nil nil t nil)
   (maphash
    (lambda (key val)
@@ -200,7 +203,7 @@
        (setq clm 6)
 
        (dolist (v vowels)
-         (apply 'insert (propertize "\t" 'display (list 'space :align-to clm))
+         (apply #'insert (propertize "\t" 'display (list 'space :align-to clm))
                 (if (nth 1 c) (list (nth 1 c) (nth 2 v)) (list "")))
          (setq clm (+ clm 6))))
       (insert "\n")
@@ -309,7 +312,10 @@ Full key sequences are listed below:")
 
 (defun quail-define-inscript-package (char-tables key-tables pkgname lang
                                                   title docstring)
-  (funcall 'quail-define-package pkgname lang title nil docstring
+  ;; This is a funcall to avoid `quail-update-leim-list-file'
+  ;; determining that this is a quail definition (it searches for
+  ;; "(quail-define-package").
+  (funcall #'quail-define-package pkgname lang title nil docstring
           nil nil nil t nil nil nil nil)
   (let (char-table key-table char key)
     (while (and char-tables key-tables)
@@ -627,7 +633,7 @@ Full key sequences are listed below:")
 (quail-define-package "malayalam-mozhi" "Malayalam" "MlmMI" t
                       "Malayalam transliteration by Mozhi method."
                       nil nil t nil nil nil t nil
-                      'indian-mlm-mozhi-update-translation)
+                      #'indian-mlm-mozhi-update-translation)
 
 (maphash
  (lambda (key val)
@@ -636,9 +642,9 @@ Full key sequences are listed below:")
                        (vector val))))
  (cdr indian-mlm-mozhi-hash))
 
-(defun indian-mlm-mozhi-underscore (key len) (throw 'quail-tag nil))
+(defun indian-mlm-mozhi-underscore (_key _len) (throw 'quail-tag nil))
 
-(quail-defrule "_" 'indian-mlm-mozhi-underscore)
+(quail-defrule "_" #'indian-mlm-mozhi-underscore)
 (quail-defrule "|" ?‌)
 (quail-defrule "||" ?​)
 
diff --git a/lisp/leim/quail/ipa-praat.el b/lisp/leim/quail/ipa-praat.el
index 0920bc7..1a95395 100644
--- a/lisp/leim/quail/ipa-praat.el
+++ b/lisp/leim/quail/ipa-praat.el
@@ -35,7 +35,7 @@
  "ipa-praat" "IPA" "IPAP" t
  "International Phonetic Alphabet input method.
 This follows the input method of the phonetic analysis program
-Praat (http://www.fon.hum.uva.nl/praat/).
+Praat (https://www.fon.hum.uva.nl/praat/).
 
 
 * Vowels
diff --git a/lisp/leim/quail/ipa.el b/lisp/leim/quail/ipa.el
index d9f5888..c256875 100644
--- a/lisp/leim/quail/ipa.el
+++ b/lisp/leim/quail/ipa.el
@@ -1,4 +1,4 @@
-;;; ipa.el --- Quail package for inputting IPA characters  -*-coding: utf-8;-*-
+;;; ipa.el --- Quail package for inputting IPA characters  -*- 
lexical-binding: t; -*-
 
 ;; Copyright (C) 2009-2021 Free Software Foundation, Inc.
 ;; Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
@@ -276,7 +276,7 @@ string."
       (cl-assert (vectorp quail-keymap) t)
       (setq quail-keymap (append quail-keymap nil))))
   (list
-   (apply 'vector
+   (apply #'vector
          (mapcar
           #'(lambda (entry)
                (cl-assert (char-or-string-p entry) t)
@@ -336,12 +336,12 @@ exchange in environments where Unicode is not available.  
This input method
 uses this transliteration to allow you to produce the IPA in your editor
 with a keyboard that's limited to ASCII.
 
-See http://www.phon.ucl.ac.uk/home/sampa/ipasam-x.pdf for a full definition
+See https://www.phon.ucl.ac.uk/home/sampa/ipasam-x.pdf for a full definition
 of the mapping.")
 
 (quail-define-rules
  ;; Table taken from https://en.wikipedia.org/wiki/X-SAMPA, checked with
- ;; http://www.phon.ucl.ac.uk/home/sampa/ipasam-x.pdf
+ ;; https://www.phon.ucl.ac.uk/home/sampa/ipasam-x.pdf
 
  ("d`" "ɖ")    ;; Voiced retroflex plosive             U+0256
  ("g" "ɡ")     ;; Voiced velar plosive                 U+0261
@@ -502,9 +502,9 @@ of the mapping.")
 ;; diacritic. To avoid this, handle the input specially with the function
 ;; ipa-x-sampa-underscore-implosive.
 
-(dolist (implosive-x-sampa (mapcar 'car ipa-x-sampa-implosive-submap))
+(dolist (implosive-x-sampa (mapcar #'car ipa-x-sampa-implosive-submap))
   (setq implosive-x-sampa (car (split-string implosive-x-sampa "_")))
   (quail-defrule (format "%s_" implosive-x-sampa)
-                'ipa-x-sampa-underscore-implosive))
+                #'ipa-x-sampa-underscore-implosive))
 
 ;;; ipa.el ends here
diff --git a/lisp/leim/quail/japanese.el b/lisp/leim/quail/japanese.el
index a4ea550..6a2bcdc 100644
--- a/lisp/leim/quail/japanese.el
+++ b/lisp/leim/quail/japanese.el
@@ -1,4 +1,4 @@
-;;; japanese.el --- Quail package for inputting Japanese
+;;; japanese.el --- Quail package for inputting Japanese  -*- lexical-binding: 
t; -*-
 
 ;; Copyright (C) 2001-2021 Free Software Foundation, Inc.
 ;; Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
@@ -412,7 +412,7 @@ C-h         kkc-help
        List these key bindings.
 "
  nil t t nil nil nil nil nil
- 'quail-japanese-update-translation
+ #'quail-japanese-update-translation
  '(("K" . quail-japanese-toggle-kana)
    (" " . quail-japanese-kanji-kkc)
    ("\C-m" . quail-no-conversion)
@@ -491,7 +491,7 @@ qh: shift to the input method `japanese',
 qq:    toggle between this input method and the input method `japanese-ascii'.
 "
  nil t t nil nil nil nil nil
- 'quail-japanese-hankaku-update-translation)
+ #'quail-japanese-hankaku-update-translation)
 
 (dolist (elt quail-japanese-transliteration-rules)
   (quail-defrule (car elt)
@@ -517,7 +517,7 @@ qq: toggle between this input method and the input method 
`japanese-ascii'.
  nil
  "Japanese hiragana input method by Roman transliteration."
  nil t t nil nil nil nil nil
- 'quail-japanese-update-translation)
+ #'quail-japanese-update-translation)
 
 ;; Use the same map as that of `japanese'.
 (setcar (cdr (cdr quail-current-package))
@@ -538,7 +538,7 @@ qq: toggle between this input method and the input method 
`japanese-ascii'.
  nil
  "Japanese katakana input method by Roman transliteration."
  nil t t nil nil nil nil nil
- 'quail-japanese-katakana-update-translation)
+ #'quail-japanese-katakana-update-translation)
 
 (dolist (elt quail-japanese-transliteration-rules)
   (quail-defrule (car elt)
diff --git a/lisp/leim/quail/lao.el b/lisp/leim/quail/lao.el
index af3b589..a932460 100644
--- a/lisp/leim/quail/lao.el
+++ b/lisp/leim/quail/lao.el
@@ -1,4 +1,4 @@
-;;; lao.el --- Quail package for inputting Lao characters  -*-coding: utf-8;-*-
+;;; lao.el --- Quail package for inputting Lao characters  -*- 
lexical-binding: t; -*-
 
 ;; Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
 ;;   2006, 2007, 2008, 2009, 2010, 2011
@@ -195,7 +195,7 @@ you need to re-load it to properly re-initialize related 
alists.")
 (quail-define-package
  "lao" "Lao" "ລ" t
  "Lao input method simulating Lao keyboard layout based on Thai TIS620"
- nil t t t t nil nil nil 'quail-lao-update-translation nil t)
+ nil t t t t nil nil nil #'quail-lao-update-translation nil t)
 
 (quail-install-map
  (quail-map-from-table
diff --git a/lisp/leim/quail/latin-ltx.el b/lisp/leim/quail/latin-ltx.el
index fd78253..8b1e520 100644
--- a/lisp/leim/quail/latin-ltx.el
+++ b/lisp/leim/quail/latin-ltx.el
@@ -1,4 +1,4 @@
-;;; latin-ltx.el --- Quail package for TeX-style input -*-coding: utf-8;-*-
+;;; latin-ltx.el --- Quail package for TeX-style input -*- lexical-binding: t; 
-*-
 
 ;; Copyright (C) 2001-2021 Free Software Foundation, Inc.
 ;; Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,
diff --git a/lisp/leim/quail/latin-post.el b/lisp/leim/quail/latin-post.el
index 8e21ed8..1040877 100644
--- a/lisp/leim/quail/latin-post.el
+++ b/lisp/leim/quail/latin-post.el
@@ -744,7 +744,7 @@ Doubling the postfix separates the letter and postfix: e.g. 
a\\='\\=' -> a\\='
 ;;; correctly on most displays.
 
 ;;; This reference is an authoritative guide to Hawaiian orthography:
-;;; http://www2.hawaii.edu/~strauch/tips/HawaiianOrthography.html
+;;; https://www2.hawaii.edu/~strauch/tips/HawaiianOrthography.html
 
 ;;; Initial coding 2018-09-08 Bob Newell, Honolulu, Hawaiʻi
 ;;; Comments to bobnewell@bobnewell.net
diff --git a/lisp/leim/quail/latin-pre.el b/lisp/leim/quail/latin-pre.el
index 2200654..b8b0fab 100644
--- a/lisp/leim/quail/latin-pre.el
+++ b/lisp/leim/quail/latin-pre.el
@@ -1294,7 +1294,7 @@ of characters from a single Latin-N charset.
 ;;; correctly on most displays.
 
 ;;; This reference is an authoritative guide to Hawaiian orthography:
-;;; http://www2.hawaii.edu/~strauch/tips/HawaiianOrthography.html
+;;; https://www2.hawaii.edu/~strauch/tips/HawaiianOrthography.html
 
 ;;; Initial coding 2018-09-08 Bob Newell, Honolulu, Hawaiʻi
 ;;; Comments to bobnewell@bobnewell.net
diff --git a/lisp/leim/quail/lrt.el b/lisp/leim/quail/lrt.el
index e05bc1e..68eaeb5 100644
--- a/lisp/leim/quail/lrt.el
+++ b/lisp/leim/quail/lrt.el
@@ -1,4 +1,4 @@
-;;; lrt.el --- Quail package for inputting Lao characters by LRT method  
-*-coding: utf-8;-*-
+;;; lrt.el --- Quail package for inputting Lao characters by LRT method  -*- 
lexical-binding: t; -*-
 
 ;; Copyright (C) 1998, 2001-2021 Free Software Foundation, Inc.
 ;; Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
@@ -60,7 +60,7 @@
 `\\' (backslash) + `$'         => ຯ            LAO ELLIPSIS
 "
  nil 'forget-last-selection 'deterministic 'kbd-translate 'show-layout
-  nil nil nil 'quail-lrt-update-translation nil t)
+  nil nil nil #'quail-lrt-update-translation nil t)
 
 ;; LRT (Lao Roman Transcription) input method accepts the following
 ;; key sequence:
diff --git a/lisp/leim/quail/programmer-dvorak.el 
b/lisp/leim/quail/programmer-dvorak.el
index 49f9d82..9e1e23c 100644
--- a/lisp/leim/quail/programmer-dvorak.el
+++ b/lisp/leim/quail/programmer-dvorak.el
@@ -24,7 +24,7 @@
 ;;; Commentary:
 
 ;;; This file provides an input method for the programmers Dvorak keyboard
-;;; layout by Roland Kaufman (<http://www.kaufmann.no/roland/dvorak/>).
+;;; layout by Roland Kaufman (<https://www.kaufmann.no/roland/dvorak/>).
 
 ;;; Code:
 
diff --git a/lisp/leim/quail/sisheng.el b/lisp/leim/quail/sisheng.el
index 8e7a500..aa35bb0 100644
--- a/lisp/leim/quail/sisheng.el
+++ b/lisp/leim/quail/sisheng.el
@@ -1,4 +1,4 @@
-;;; sisheng.el --- sisheng input method for Chinese pinyin transliteration
+;;; sisheng.el --- sisheng input method for Chinese pinyin transliteration  
-*- lexical-binding: t; -*-
 
 ;; Copyright (C) 2004-2021 Free Software Foundation, Inc.
 
diff --git a/lisp/leim/quail/thai.el b/lisp/leim/quail/thai.el
index 7cf11da..07ba657 100644
--- a/lisp/leim/quail/thai.el
+++ b/lisp/leim/quail/thai.el
@@ -1,4 +1,4 @@
-;;; thai.el --- Quail package for inputting Thai characters -*-coding: 
utf-8;-*-
+;;; thai.el --- Quail package for inputting Thai characters -*- 
lexical-binding: t; -*-
 
 ;; Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
 ;;   2005, 2006, 2007, 2008, 2009, 2010, 2011
diff --git a/lisp/leim/quail/tibetan.el b/lisp/leim/quail/tibetan.el
index a54763d..33cc6f5 100644
--- a/lisp/leim/quail/tibetan.el
+++ b/lisp/leim/quail/tibetan.el
@@ -1,4 +1,4 @@
-;;; tibetan.el --- Quail package for inputting Tibetan characters -*-coding: 
utf-8-emacs;-*-
+;;; tibetan.el --- Quail package for inputting Tibetan characters -*-coding: 
utf-8-emacs; lexical-binding: t; -*-
 
 ;; Copyright (C) 1997, 2001-2021 Free Software Foundation, Inc.
 ;; Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
@@ -158,7 +158,7 @@
   Tsheg is assigned to SPC.  Space is assigned to period `.'.
 "
  nil nil nil nil nil nil nil nil
- 'quail-tibetan-update-translation)
+ #'quail-tibetan-update-translation)
 
 ;; Here we build up a Quail map for a Tibetan sequence the whole of
 ;; which can be one composition.
@@ -371,7 +371,7 @@
            (setq trans-list (cons trans trans-list)
                  i last)
          (setq trans-list nil i len))))
-    (apply 'concat (nreverse trans-list))))
+    (apply #'concat (nreverse trans-list))))
 
 (defvar quail-tibkey-characters nil)
 
@@ -440,7 +440,7 @@
        I hope I'll complete in a future revision.
 "
  nil nil nil nil nil nil nil nil
- 'quail-tibkey-update-translation)
+ #'quail-tibkey-update-translation)
 
 (quail-install-map
  (quail-map-from-table
diff --git a/lisp/leim/quail/uni-input.el b/lisp/leim/quail/uni-input.el
index c7cf6ab..bfe4ce6 100644
--- a/lisp/leim/quail/uni-input.el
+++ b/lisp/leim/quail/uni-input.el
@@ -1,4 +1,4 @@
-;;; uni-input.el --- Hex Unicode input method
+;;; uni-input.el --- Hex Unicode input method  -*- lexical-binding: t; -*-
 
 ;; Copyright (C) 2001-2021 Free Software Foundation, Inc.
 ;; Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011
@@ -57,11 +57,12 @@
          (echo-keystrokes 0)
          (help-char nil)
          (events (list key))
-         (str "    "))
+         ;; (str "    ")
+         )
       (unwind-protect
          (catch 'non-digit
            (progn
-             (dotimes (i 4)
+             (dotimes (_ 4)
                (let ((seq (read-key-sequence nil))
                      key)
                  (if (and (stringp seq)
@@ -76,7 +77,7 @@
                    (throw 'non-digit (append (reverse events)
                                              (listify-key-sequence seq))))))
              (quail-delete-region)
-             (let ((n (string-to-number (apply 'string
+             (let ((n (string-to-number (apply #'string
                                            (cdr (nreverse events)))
                                     16)))
                (if (characterp n)
@@ -100,12 +101,12 @@ While this input method is active, the variable
            (quail-delete-overlays)
            (setq describe-current-input-method-function nil))
        (kill-local-variable 'input-method-function))
-    (setq deactivate-current-input-method-function 'ucs-input-deactivate)
-    (setq describe-current-input-method-function 'ucs-input-help)
+    (setq deactivate-current-input-method-function #'ucs-input-deactivate)
+    (setq describe-current-input-method-function #'ucs-input-help)
     (quail-delete-overlays)
     (if (eq (selected-window) (minibuffer-window))
-       (add-hook 'minibuffer-exit-hook 'quail-exit-from-minibuffer))
-    (setq-local input-method-function 'ucs-input-method)))
+       (add-hook 'minibuffer-exit-hook #'quail-exit-from-minibuffer))
+    (setq-local input-method-function #'ucs-input-method)))
 
 (defun ucs-input-deactivate ()
   "Deactivate UCS input method."
@@ -114,7 +115,7 @@ While this input method is active, the variable
 
 (define-obsolete-function-alias
   'ucs-input-inactivate
-  'ucs-input-deactivate "24.3")
+  #'ucs-input-deactivate "24.3")
 
 (defun ucs-input-help ()
   (interactive)
diff --git a/lisp/loadup.el b/lisp/loadup.el
index 9cee6a2..4a0b8f5 100644
--- a/lisp/loadup.el
+++ b/lisp/loadup.el
@@ -253,9 +253,6 @@
 (load "startup")
 (load "term/tty-colors")
 (load "font-core")
-;; facemenu must be loaded before font-lock, because `facemenu-keymap'
-;; needs to be defined when font-lock is loaded.
-(load "facemenu")
 (load "emacs-lisp/syntax")
 (load "font-lock")
 (load "jit-lock")
@@ -265,6 +262,7 @@
     (load "scroll-bar"))
 (load "select")
 (load "emacs-lisp/timer")
+(load "emacs-lisp/easymenu")
 (load "isearch")
 (load "rfn-eshadow")
 
@@ -477,6 +475,8 @@ lost after dumping")))
 ;; Make sure we will attempt bidi reordering henceforth.
 (setq redisplay--inhibit-bidi nil)
 
+
+
 (if dump-mode
     (let ((output (cond ((equal dump-mode "pdump") "emacs.pdmp")
                         ((equal dump-mode "dump") "emacs")
diff --git a/lisp/mail/binhex.el b/lisp/mail/binhex.el
index edb52b6..af32744 100644
--- a/lisp/mail/binhex.el
+++ b/lisp/mail/binhex.el
@@ -38,19 +38,16 @@
   "Non-nil value should be a string that names a binhex decoder.
 The program should expect to read binhex data on its standard
 input and write the converted data to its standard output."
-  :type 'string
-  :group 'binhex)
+  :type 'string)
 
 (defcustom binhex-decoder-switches '("-d")
   "List of command line flags passed to the command `binhex-decoder-program'."
-  :group 'binhex
   :type '(repeat string))
 
 (defcustom binhex-use-external
   (executable-find binhex-decoder-program)
   "Use external binhex program."
   :version "22.1"
-  :group 'binhex
   :type 'boolean)
 
 (defconst binhex-alphabet-decoding-alist
@@ -80,7 +77,7 @@ input and write the converted data to its standard output."
 (make-obsolete-variable 'binhex-temporary-file-directory
                         'temporary-file-directory "28.1")
 
-(defun binhex-insert-char (char &optional count ignored buffer)
+(defun binhex-insert-char (char &optional count _ignored buffer)
   "Insert COUNT copies of CHARACTER into BUFFER."
   (if (or (null buffer) (eq buffer (current-buffer)))
       (insert-char char count)
@@ -273,7 +270,8 @@ If HEADER-ONLY is non-nil only decode header and return 
filename."
 (defun binhex-decode-region-external (start end)
   "Binhex decode region between START and END using external decoder."
   (interactive "r")
-  (let ((cbuf (current-buffer)) firstline work-buffer
+  (let ((cbuf (current-buffer))
+       work-buffer ;; firstline
        (file-name (expand-file-name
                    (concat (binhex-decode-region-internal start end t)
                            ".data")
@@ -287,9 +285,9 @@ If HEADER-ONLY is non-nil only decode header and return 
filename."
                (set-buffer (setq work-buffer
                                  (generate-new-buffer " *binhex-work*")))
                (buffer-disable-undo work-buffer)
-               (insert-buffer-substring cbuf firstline end)
+               (insert-buffer-substring cbuf nil end) ;; firstline
                (cd temporary-file-directory)
-               (apply 'call-process-region
+               (apply #'call-process-region
                       (point-min)
                       (point-max)
                       binhex-decoder-program
diff --git a/lisp/mail/blessmail.el b/lisp/mail/blessmail.el
index 505ce5d..f380f0d 100644
--- a/lisp/mail/blessmail.el
+++ b/lisp/mail/blessmail.el
@@ -1,4 +1,4 @@
-;;; blessmail.el --- decide whether movemail needs special privileges -*- 
no-byte-compile: t -*-
+;;; blessmail.el --- decide whether movemail needs special privileges -*- 
no-byte-compile: t; lexical-binding: t; -*-
 
 ;; Copyright (C) 1994, 2001-2021 Free Software Foundation, Inc.
 
diff --git a/lisp/mail/emacsbug.el b/lisp/mail/emacsbug.el
index 815ff43..5f3d75e 100644
--- a/lisp/mail/emacsbug.el
+++ b/lisp/mail/emacsbug.el
@@ -1,4 +1,4 @@
-;;; emacsbug.el --- command to report Emacs bugs to appropriate mailing list
+;;; emacsbug.el --- command to report Emacs bugs to appropriate mailing list  
-*- lexical-binding: t; -*-
 
 ;; Copyright (C) 1985, 1994, 1997-1998, 2000-2021 Free Software
 ;; Foundation, Inc.
@@ -45,12 +45,10 @@
 
 (defcustom report-emacs-bug-no-confirmation nil
   "If non-nil, suppress the confirmations asked for the sake of novice users."
-  :group 'emacsbug
   :type 'boolean)
 
 (defcustom report-emacs-bug-no-explanations nil
   "If non-nil, suppress the explanations given for the sake of novice users."
-  :group 'emacsbug
   :type 'boolean)
 
 ;; User options end here.
@@ -204,7 +202,7 @@ This requires either the macOS \"open\" command, or the 
freedesktop
 (defvar message-sendmail-envelope-from)
 
 ;;;###autoload
-(defun report-emacs-bug (topic &optional unused)
+(defun report-emacs-bug (topic &optional _unused)
   "Report a bug in GNU Emacs.
 Prompts for bug subject.  Leaves you in a mail buffer.
 
@@ -219,10 +217,10 @@ Already submitted bugs can be found in the Emacs bug 
tracker:
   (let ((from-buffer (current-buffer))
        (can-insert-mail (or (report-emacs-bug-can-use-xdg-email)
                             (report-emacs-bug-can-use-osx-open)))
-        user-point message-end-point)
-    (setq message-end-point
-         (with-current-buffer (messages-buffer)
-           (point-max-marker)))
+        user-point) ;; message-end-point
+    ;; (setq message-end-point
+    ;;       (with-current-buffer (messages-buffer)
+    ;;         (point-max-marker)))
     (condition-case nil
         ;; For the novice user make sure there's always enough space for
         ;; the mail and the warnings buffer on this frame (Bug#10873).
@@ -263,7 +261,7 @@ Already submitted bugs can be found in the Emacs bug 
tracker:
         "Bug-GNU-Emacs"
         'face 'link
         'help-echo (concat "mouse-2, RET: Follow this link")
-        'action (lambda (button)
+        'action (lambda (_button)
                   (browse-url "https://lists.gnu.org/r/bug-gnu-emacs/";))
         'follow-link t)
        (insert " mailing list\nand the GNU bug tracker at ")
@@ -271,7 +269,7 @@ Already submitted bugs can be found in the Emacs bug 
tracker:
         "debbugs.gnu.org"
         'face 'link
         'help-echo (concat "mouse-2, RET: Follow this link")
-        'action (lambda (button)
+        'action (lambda (_button)
                   (browse-url 
"https://debbugs.gnu.org/cgi/pkgreport.cgi?package=emacs;max-bugs=100;base-order=1;bug-rev=1";))
         'follow-link t)
 
@@ -347,10 +345,10 @@ usually do not have translators for other 
languages.\n\n")))
 
     ;; This is so the user has to type something in order to send easily.
     (use-local-map (nconc (make-sparse-keymap) (current-local-map)))
-    (define-key (current-local-map) "\C-c\C-i" 'info-emacs-bug)
+    (define-key (current-local-map) "\C-c\C-i" #'info-emacs-bug)
     (if can-insert-mail
        (define-key (current-local-map) "\C-c\M-i"
-         'report-emacs-bug-insert-to-mailer))
+         #'report-emacs-bug-insert-to-mailer))
     (setq report-emacs-bug-send-command (get mail-user-agent 'sendfunc)
          report-emacs-bug-send-hook (get mail-user-agent 'hookvar))
     (if report-emacs-bug-send-command
@@ -376,7 +374,7 @@ usually do not have translators for other languages.\n\n")))
       (shrink-window-if-larger-than-buffer (get-buffer-window "*Bug Help*")))
     ;; Make it less likely people will send empty messages.
     (if report-emacs-bug-send-hook
-        (add-hook report-emacs-bug-send-hook 'report-emacs-bug-hook nil t))
+        (add-hook report-emacs-bug-send-hook #'report-emacs-bug-hook nil t))
     (goto-char (point-max))
     (skip-chars-backward " \t\n")
     (setq-local report-emacs-bug-orig-text
@@ -398,7 +396,7 @@ usually do not have translators for other languages.\n\n")))
           ;; This is used not only for X11 but also W32 and others.
          (insert "Windowing system distributor '" (x-server-vendor)
                   "', version "
-                 (mapconcat 'number-to-string (x-server-version) ".") "\n")
+                 (mapconcat #'number-to-string (x-server-version) ".") "\n")
        (error t)))
   (let ((os (ignore-errors (report-emacs-bug--os-description))))
     (if (stringp os)
@@ -409,7 +407,7 @@ usually do not have translators for other languages.\n\n")))
            system-configuration-options "'\n\n")
     (fill-region (line-beginning-position -1) (point))))
 
-(define-obsolete-function-alias 'report-emacs-bug-info 'info-emacs-bug "24.3")
+(define-obsolete-function-alias 'report-emacs-bug-info #'info-emacs-bug "24.3")
 
 (defun report-emacs-bug-hook ()
   "Do some checking before sending a bug report."
diff --git a/lisp/mail/feedmail.el b/lisp/mail/feedmail.el
index 2bcbdf4..cec5736 100644
--- a/lisp/mail/feedmail.el
+++ b/lisp/mail/feedmail.el
@@ -163,7 +163,7 @@
 ;;     (autoload 'feedmail-buffer-to-smtpmail "feedmail" nil t)
 ;;     (setq feedmail-buffer-eating-function 'feedmail-buffer-to-smtpmail)
 ;;
-;; Alternatively, the FLIM <http://www.m17n.org/FLIM/> project
+;; Alternatively, the FLIM <https://www.m17n.org/FLIM/> project
 ;; provides a library called smtp.el.  If you want to use that, the above lines
 ;; would be:
 ;;
@@ -1381,7 +1381,7 @@ It shows the simple addresses and gets a confirmation.  
Use as:
   (save-window-excursion
     (display-buffer (set-buffer (get-buffer-create " F-C-A-H-E")))
     (erase-buffer)
-    (insert (mapconcat 'identity feedmail-address-list " "))
+    (insert (mapconcat #'identity feedmail-address-list " "))
     (if (not (y-or-n-p "How do you like them apples? "))
        (error "FQM: Sending...gave up in last chance hook"))))
 
@@ -1592,10 +1592,10 @@ Feeds the buffer to it."
   (feedmail-say-debug ">in-> feedmail-buffer-to-binmail %s" addr-listoid)
   (set-buffer prepped)
   (apply
-   'call-process-region
+   #'call-process-region
    (append (list (point-min) (point-max) "/bin/sh" nil errors-to nil "-c"
                 (format feedmail-binmail-template
-                        (mapconcat 'identity addr-listoid " "))))))
+                        (mapconcat #'identity addr-listoid " "))))))
 
 
 (defvar sendmail-program)
@@ -1609,7 +1609,7 @@ local gurus."
   (require 'sendmail)
   (feedmail-say-debug ">in-> feedmail-buffer-to-sendmail %s" addr-listoid)
   (set-buffer prepped)
-  (apply 'call-process-region
+  (apply #'call-process-region
         (append (list (point-min) (point-max) sendmail-program
                       nil errors-to nil "-oi" "-t")
                 ;; provide envelope "from" to sendmail; results will vary
@@ -2042,7 +2042,7 @@ backup file names and the like)."
                       (message "FQM: Trapped `%s', message left in queue." 
(car signal-stuff))
                       (sit-for 3)
                       (message "FQM: Trap details: \"%s\""
-                               (mapconcat 'identity (cdr signal-stuff) "\" 
\""))
+                               (mapconcat #'identity (cdr signal-stuff) "\" 
\""))
                       (sit-for 3)))
              (kill-buffer blobby-buffer)
              (feedmail-say-chatter
diff --git a/lisp/mail/flow-fill.el b/lisp/mail/flow-fill.el
index 0fab1b2..5319ab9 100644
--- a/lisp/mail/flow-fill.el
+++ b/lisp/mail/flow-fill.el
@@ -81,7 +81,7 @@ RFC 2646 suggests 66 characters for readability."
        (while (setq end (text-property-any start (point-max) 'hard 't))
          (save-restriction
            (narrow-to-region start end)
-           (let ((fill-column (eval fill-flowed-encode-column)))
+           (let ((fill-column (eval fill-flowed-encode-column t)))
              (fill-flowed-fill-buffer))
            (goto-char (point-min))
            (while (re-search-forward "\n" nil t)
@@ -119,7 +119,7 @@ If BUFFER is nil, default to the current buffer.
 If DELETE-SPACE, delete RFC2646 spaces padding at the end of
 lines."
   (with-current-buffer (or buffer (current-buffer))
-    (let ((fill-column  (eval fill-flowed-display-column)))
+    (let ((fill-column  (eval fill-flowed-display-column t)))
       (goto-char (point-min))
       (while (not (eobp))
         (cond
diff --git a/lisp/mail/ietf-drums.el b/lisp/mail/ietf-drums.el
index 795e37d..2d68357 100644
--- a/lisp/mail/ietf-drums.el
+++ b/lisp/mail/ietf-drums.el
@@ -232,13 +232,13 @@ If DECODE, the DISPLAY-NAME will have RFC2047 decoding 
performed
       ;; If we found no display-name, then we look for comments.
       (if display-name
          (setq display-string
-               (mapconcat 'identity (reverse display-name) " "))
+               (mapconcat #'identity (reverse display-name) " "))
        (setq display-string (ietf-drums-get-comment string)))
       (if (not mailbox)
          (when (and display-string
                     (string-match "@" display-string))
            (cons
-            (mapconcat 'identity (nreverse display-name) "")
+            (mapconcat #'identity (nreverse display-name) "")
             (ietf-drums-get-comment string)))
        (cons mailbox (if decode
                           (rfc2047-decode-string display-string)
diff --git a/lisp/mail/mail-extr.el b/lisp/mail/mail-extr.el
index 4e3bf78..7fbdfef 100644
--- a/lisp/mail/mail-extr.el
+++ b/lisp/mail/mail-extr.el
@@ -1,4 +1,4 @@
-;;; mail-extr.el --- extract full name and address from email header
+;;; mail-extr.el --- extract full name and address from email header  -*- 
lexical-binding: t; -*-
 
 ;; Copyright (C) 1991-1994, 1997, 2001-2021 Free Software Foundation,
 ;; Inc.
@@ -222,23 +222,20 @@
   "Whether to try to guess middle initial from mail address.
 If true, then when we see an address like \"John Smith <jqs@host.com>\"
 we will assume that \"John Q. Smith\" is the fellow's name."
-  :type 'boolean
-  :group 'mail-extr)
+  :type 'boolean)
 
 (defcustom mail-extr-ignore-single-names nil
   "Whether to ignore a name that is just a single word.
 If true, then when we see an address like \"Idiot <dumb@stupid.com>\"
 we will act as though we couldn't find a full name in the address."
   :type 'boolean
-  :version "22.1"
-  :group 'mail-extr)
+  :version "22.1")
 
 (defcustom mail-extr-ignore-realname-equals-mailbox-name t
 "Whether to ignore a name that is equal to the mailbox name.
 If true, then when the address is like \"Single <single@address.com>\"
 we will act as though we couldn't find a full name in the address."
-  :type 'boolean
-  :group 'mail-extr)
+  :type 'boolean)
 
 ;; Matches a leading title that is not part of the name (does not
 ;; contribute to uniquely identifying the person).
@@ -248,19 +245,16 @@ we will act as though we couldn't find a full name in the 
address."
   "Matches prefixes to the full name that identify a person's position.
 These are stripped from the full name because they do not contribute to
 uniquely identifying the person."
-  :type 'regexp
-  :group 'mail-extr)
+  :type 'regexp)
 
 (defcustom mail-extr-@-binds-tighter-than-! nil
   "Whether the local mail transport agent looks at ! before @."
-  :type 'boolean
-  :group 'mail-extr)
+  :type 'boolean)
 
 (defcustom mail-extr-mangle-uucp nil
   "Whether to throw away information in UUCP addresses
 by translating things like \"foo!bar!baz@host\" into \"baz@bar.UUCP\"."
-  :type 'boolean
-  :group 'mail-extr)
+  :type 'boolean)
 
 ;;----------------------------------------------------------------------
 ;; what orderings are meaningful?????
@@ -760,7 +754,6 @@ non-display use, you should probably use
              end-of-address
              <-pos >-pos @-pos colon-pos comma-pos !-pos %-pos \;-pos
              group-:-pos group-\;-pos route-addr-:-pos
-             record-pos-symbol
              first-real-pos last-real-pos
              phrase-beg phrase-end
              ;; Dynamically set in mail-extr-voodoo.
@@ -852,13 +845,16 @@ non-display use, you should probably use
              )
             ;; record the position of various interesting chars, determine
             ;; validity later.
-            ((setq record-pos-symbol
-                   (cdr (assq char
-                              '((?< . <-pos) (?> . >-pos) (?@ . @-pos)
-                                (?: . colon-pos) (?, . comma-pos) (?! . !-pos)
-                                (?% . %-pos) (?\; . \;-pos)))))
-             (set record-pos-symbol
-                  (cons (point) (symbol-value record-pos-symbol)))
+            ((memq char '(?< ?> ?@ ?: ?, ?!  ?% ?\;))
+             (push (point) (pcase-exhaustive char
+                             (?<  <-pos)
+                             (?>  >-pos)
+                             (?@  @-pos)
+                             (?:  colon-pos)
+                             (?,  comma-pos)
+                             (?!  !-pos)
+                             (?%  %-pos)
+                             (?\; \;-pos)))
              (forward-char 1))
             ((eq char ?.)
              (forward-char 1))
@@ -1065,7 +1061,7 @@ non-display use, you should probably use
            (mail-extr-demarkerize route-addr-:-pos)
            (setq route-addr-:-pos nil
                  >-pos (mail-extr-demarkerize >-pos)
-                 %-pos (mapcar 'mail-extr-demarkerize %-pos)))
+                 %-pos (mapcar #'mail-extr-demarkerize %-pos)))
 
          ;; de-listify @-pos
          (setq @-pos (car @-pos))
@@ -1122,7 +1118,7 @@ non-display use, you should probably use
                       (setq insert-point (point-max)))
                      (%-pos
                       (setq insert-point (car (last %-pos))
-                            saved-%-pos (mapcar 'mail-extr-markerize %-pos)
+                            saved-%-pos (mapcar #'mail-extr-markerize %-pos)
                             %-pos nil
                             @-pos (mail-extr-markerize @-pos)))
                      (@-pos
@@ -1162,7 +1158,7 @@ non-display use, you should probably use
                       "uucp"))
                  (setq !-pos (cdr !-pos))))
              (and saved-%-pos
-                  (setq %-pos (append (mapcar 'mail-extr-demarkerize
+                  (setq %-pos (append (mapcar #'mail-extr-demarkerize
                                               saved-%-pos)
                                       %-pos)))
              (setq @-pos (mail-extr-demarkerize @-pos))
@@ -1461,8 +1457,7 @@ If it is neither nil nor a string, modifying of names 
will never take
 place.  It affects how `mail-extract-address-components' works."
   :type '(choice (regexp :size 0)
                 (const :tag "Always enabled" nil)
-                (const :tag "Always disabled" t))
-  :group 'mail-extr)
+                (const :tag "Always disabled" t)))
 
 (defun mail-extr-voodoo (mbox-beg mbox-end canonicalization-buffer)
   (unless (and mail-extr-disable-voodoo
diff --git a/lisp/mail/mail-hist.el b/lisp/mail/mail-hist.el
index 37c8ad6..239b386 100644
--- a/lisp/mail/mail-hist.el
+++ b/lisp/mail/mail-hist.el
@@ -1,4 +1,4 @@
-;;; mail-hist.el --- headers and message body history for outgoing mail
+;;; mail-hist.el --- headers and message body history for outgoing mail  -*- 
lexical-binding: t; -*-
 
 ;; Copyright (C) 1994, 2001-2021 Free Software Foundation, Inc.
 
@@ -69,8 +69,8 @@
 
 ;;;###autoload
 (defun mail-hist-enable ()
-  (add-hook 'mail-mode-hook 'mail-hist-define-keys)
-  (add-hook 'mail-send-hook 'mail-hist-put-headers-into-history))
+  (add-hook 'mail-mode-hook #'mail-hist-define-keys)
+  (add-hook 'mail-send-hook #'mail-hist-put-headers-into-history))
 
 (defvar mail-hist-header-ring-alist nil
   "Alist of form (header-name . history-ring).
@@ -80,14 +80,12 @@ previous/next input.")
 (defcustom mail-hist-history-size (or kill-ring-max 1729)
   "The maximum number of elements in a mail field's history.
 Oldest elements are dumped first."
-  :type 'integer
-  :group 'mail-hist)
+  :type 'integer)
 
 ;;;###autoload
 (defcustom mail-hist-keep-history t
   "Non-nil means keep a history for headers and text of outgoing mail."
-  :type 'boolean
-  :group 'mail-hist)
+  :type 'boolean)
 
 ;; For handling repeated history requests
 (defvar mail-hist-access-count 0)
@@ -184,8 +182,7 @@ HEADER is a string without the colon."
 (defcustom mail-hist-text-size-limit nil
   "Don't store any header or body with more than this many characters.
 If the value is nil, that means no limit on text size."
-  :type '(choice (const nil) integer)
-  :group 'mail-hist)
+  :type '(choice (const nil) integer))
 
 (defun mail-hist-text-too-long-p (text)
   "Return non-nil if TEXT's length exceeds `mail-hist-text-size-limit'."
diff --git a/lisp/mail/mail-utils.el b/lisp/mail/mail-utils.el
index ad2dee5..bb1f8f1 100644
--- a/lisp/mail/mail-utils.el
+++ b/lisp/mail/mail-utils.el
@@ -1,4 +1,4 @@
-;;; mail-utils.el --- utility functions used both by rmail and rnews
+;;; mail-utils.el --- utility functions used both by rmail and rnews  -*- 
lexical-binding: t -*-
 
 ;; Copyright (C) 1985, 2001-2021 Free Software Foundation, Inc.
 
@@ -46,6 +46,7 @@ also the To field, unless this would leave an empty To field."
   :type '(choice regexp (const :tag "Your Name" nil))
   :group 'mail)
 
+(defvar epa-inhibit)
 ;; Returns t if file FILE is an Rmail file.
 ;;;###autoload
 (defun mail-file-babyl-p (file)
@@ -58,6 +59,7 @@ also the To field, unless this would leave an empty To field."
 (defun mail-string-delete (string start end)
   "Return a string containing all of STRING except the part
 from START (inclusive) to END (exclusive)."
+  ;; FIXME: This is not used anywhere.  Make obsolete?
   (if (null end) (substring string 0 start)
     (concat (substring string 0 start)
            (substring string end nil))))
@@ -132,7 +134,7 @@ we expect to find and remove the wrapper characters 
=?ISO-8859-1?Q?....?=."
                                       (aref string (1+ (match-beginning 1))))))
                      strings)))
        (setq i (match-end 0)))
-      (apply 'concat (nreverse (cons (substring string i) strings))))))
+      (apply #'concat (nreverse (cons (substring string i) strings))))))
 
 ;; FIXME Gnus for some reason has `quoted-printable-decode-region' in qp.el.
 ;;;###autoload
@@ -192,7 +194,7 @@ Also delete leading/trailing whitespace and replace FOO 
<BAR> with just BAR.
 Return a modified address list."
   (when address
     (if mail-use-rfc822
-       (mapconcat 'identity (rfc822-addresses address) ", ")
+       (mapconcat #'identity (rfc822-addresses address) ", ")
       (let (pos)
 
         ;; Strip comments.
@@ -280,7 +282,7 @@ comma-separated list, and return the pruned list."
     destinations))
 
 ;; Legacy name
-(define-obsolete-function-alias 'rmail-dont-reply-to 'mail-dont-reply-to 
"24.1")
+(define-obsolete-function-alias 'rmail-dont-reply-to #'mail-dont-reply-to 
"24.1")
 
 
 ;;;###autoload
diff --git a/lisp/mail/mailabbrev.el b/lisp/mail/mailabbrev.el
index 2147049..5cb4a74 100644
--- a/lisp/mail/mailabbrev.el
+++ b/lisp/mail/mailabbrev.el
@@ -1,4 +1,4 @@
-;;; mailabbrev.el --- abbrev-expansion of mail aliases
+;;; mailabbrev.el --- abbrev-expansion of mail aliases  -*- lexical-binding: 
t; -*-
 
 ;; Copyright (C) 1985-1987, 1992-1993, 1996-1997, 2000-2021 Free
 ;; Software Foundation, Inc.
@@ -140,15 +140,13 @@ abbrev-like expansion is performed when editing certain 
mail
 headers (those specified by `mail-abbrev-mode-regexp'), based on
 the entries in your `mail-personal-alias-file'."
   :global t
-  :group 'mail-abbrev
   :version "20.3"
   (if mail-abbrevs-mode (mail-abbrevs-enable) (mail-abbrevs-disable)))
 
 (defcustom mail-abbrevs-only nil
   "Non-nil means only mail abbrevs should expand automatically.
 Other abbrevs expand only when you explicitly use `expand-abbrev'."
-  :type 'boolean
-  :group 'mail-abbrev)
+  :type 'boolean)
 
 ;; originally defined in sendmail.el - used to be an alist, now is a table.
 (defvar mail-abbrevs nil
@@ -186,11 +184,11 @@ no aliases, which is represented by this being a table 
with no entries.)")
   (abbrev-mode 1))
 
 (defun mail-abbrevs-enable ()
-  (add-hook 'mail-mode-hook 'mail-abbrevs-setup))
+  (add-hook 'mail-mode-hook #'mail-abbrevs-setup))
 
 (defun mail-abbrevs-disable ()
   "Turn off use of the `mailabbrev' package."
-  (remove-hook 'mail-mode-hook 'mail-abbrevs-setup)
+  (remove-hook 'mail-mode-hook #'mail-abbrevs-setup)
   (abbrev-mode (if (default-value 'abbrev-mode) 1 -1)))
 
 ;;;###autoload
@@ -258,8 +256,7 @@ By default this is the file specified by 
`mail-personal-alias-file'."
   "String inserted between addresses in multi-address mail aliases.
 This has to contain a comma, so \", \" is a reasonable value.  You might
 also want something like \",\\n    \" to get each address on its own line."
-  :type 'string
-  :group 'mail-abbrev)
+  :type 'string)
 
 ;; define-mail-abbrev sets this flag, which causes mail-resolve-all-aliases
 ;; to be called before expanding abbrevs if it's necessary.
@@ -367,7 +364,7 @@ double-quotes."
 (defun mail-resolve-all-aliases-1 (sym &optional so-far)
   (if (memq sym so-far)
       (error "mail alias loop detected: %s"
-            (mapconcat 'symbol-name (cons sym so-far) " <- ")))
+            (mapconcat #'symbol-name (cons sym so-far) " <- ")))
   (let ((definition (and (boundp sym) (symbol-value sym))))
     (if definition
        (let ((result '())
@@ -420,8 +417,7 @@ of the current line; if it matches, abbrev mode will be 
turned on, otherwise
 it will be turned off.  (You don't need to worry about continuation lines.)
 This should be set to match those mail fields in which you want abbreviations
 turned on."
-  :type 'regexp
-  :group 'mail-abbrev)
+  :type 'regexp)
 
 (defvar mail-abbrev-syntax-table nil
   "The syntax-table used for abbrev-expansion purposes.
@@ -433,14 +429,14 @@ of a mail alias.  The value is set up, buffer-local, when 
first needed.")
   (make-local-variable 'mail-abbrev-syntax-table)
   (unless mail-abbrev-syntax-table
     (let ((tab (copy-syntax-table (syntax-table)))
-         (_ (aref (standard-syntax-table) ?_))
+         (syntax-_ (aref (standard-syntax-table) ?_))
          (w (aref (standard-syntax-table) ?w)))
       (map-char-table
        (lambda (key value)
          (if (null value)
              ;; Fetch the inherited value
              (setq value (aref tab key)))
-         (if (equal value _)
+         (if (equal value syntax-_)
              (set-char-table-range tab key w)))
        tab)
       (modify-syntax-entry ?@ "w" tab)
@@ -600,12 +596,12 @@ In other respects, this behaves like `end-of-buffer', 
which see."
 
 (eval-after-load "sendmail"
   '(progn
-     (define-key mail-mode-map "\C-c\C-a" 'mail-abbrev-insert-alias)
+     (define-key mail-mode-map "\C-c\C-a" #'mail-abbrev-insert-alias)
      (define-key mail-mode-map "\e\t"  ; like completion-at-point
-       'mail-abbrev-complete-alias)))
+       #'mail-abbrev-complete-alias))) ;; FIXME: Use `completion-at-point'.
 
-;;(define-key mail-mode-map "\C-n" 'mail-abbrev-next-line)
-;;(define-key mail-mode-map "\M->" 'mail-abbrev-end-of-buffer)
+;;(define-key mail-mode-map "\C-n" #'mail-abbrev-next-line)
+;;(define-key mail-mode-map "\M->" #'mail-abbrev-end-of-buffer)
 
 (provide 'mailabbrev)
 
diff --git a/lisp/mail/mailclient.el b/lisp/mail/mailclient.el
index 3cba6a6..5c153ce 100644
--- a/lisp/mail/mailclient.el
+++ b/lisp/mail/mailclient.el
@@ -1,4 +1,4 @@
-;;; mailclient.el --- mail sending via system's mail client.
+;;; mailclient.el --- mail sending via system's mail client.  -*- 
lexical-binding: t; -*-
 
 ;; Copyright (C) 2005-2021 Free Software Foundation, Inc.
 
diff --git a/lisp/mail/mailheader.el b/lisp/mail/mailheader.el
index cbc01e4..0443279 100644
--- a/lisp/mail/mailheader.el
+++ b/lisp/mail/mailheader.el
@@ -1,4 +1,4 @@
-;;; mailheader.el --- mail header parsing, merging, formatting
+;;; mailheader.el --- mail header parsing, merging, formatting  -*- 
lexical-binding: t; -*-
 
 ;; Copyright (C) 1996, 2001-2021 Free Software Foundation, Inc.
 
@@ -99,23 +99,23 @@ value."
   headers)
 
 ;; Advertised part of the interface; see mail-header, mail-header-set.
-(with-suppressed-warnings ((lexical headers))
-  (defvar headers))
 
-(defsubst mail-header (header &optional header-alist)
+(defun mail-header (header &optional header-alist)
   "Return the value associated with header HEADER in HEADER-ALIST.
 If the value is a string, it is the original value of the header.  If the
 value is a list, its first element is the original value of the header,
-with any subsequent elements being the result of parsing the value.
-If HEADER-ALIST is nil, the dynamically bound variable `headers' is used."
+with any subsequent elements being the result of parsing the value."
   (declare (gv-setter (lambda (value)
                         `(mail-header-set ,header ,value ,header-alist))))
+  (with-suppressed-warnings ((lexical headers)) (defvar headers))
   (cdr (assq header (or header-alist headers))))
 
 (defun mail-header-set (header value &optional header-alist)
   "Set the value associated with header HEADER to VALUE in HEADER-ALIST.
 HEADER-ALIST defaults to the dynamically bound variable `headers' if nil.
 See `mail-header' for the semantics of VALUE."
+  (declare (obsolete alist-get "28.1"))
+  (with-suppressed-warnings ((lexical headers)) (defvar headers))
   (let* ((alist (or header-alist headers))
        (entry (assq header alist)))
     (if entry
@@ -131,10 +131,13 @@ should be a string or a list of string.  The first 
element may be nil to
 denote that the formatting functions must use the remaining elements, or
 skip the header altogether if there are no other elements.
   The macro `mail-header' can be used to access headers in HEADERS."
-  (mapcar
-   (lambda (rule)
-     (cons (car rule) (eval (cdr rule))))
-   merge-rules))
+  (declare (obsolete alist-get "28.1"))
+  (with-suppressed-warnings ((lexical headers)) (defvar headers))
+  (let ((headers headers))
+    (mapcar
+     (lambda (rule)
+       (cons (car rule) (eval (cdr rule) t)))
+     merge-rules)))
 
 (defvar mail-header-format-function
   (lambda (header value)
@@ -167,7 +170,7 @@ A key of nil has as its value a list of defaulted headers 
to ignore."
                        (mapcar #'car format-rules))))
     (dolist (rule format-rules)
       (let* ((header (car rule))
-           (value (mail-header header)))
+           (value (alist-get header headers)))
        (if (stringp header)
            (setq header (intern header)))
        (cond ((null header) 'ignore)
@@ -176,13 +179,11 @@ A key of nil has as its value a list of defaulted headers 
to ignore."
                 (unless (memq (car defaulted) ignore)
                   (let* ((header (car defaulted))
                          (value (cdr defaulted)))
-                    (if (cdr rule)
-                        (funcall (cdr rule) header value)
-                      (funcall mail-header-format-function header value))))))
+                    (funcall (or (cdr rule) mail-header-format-function)
+                             header value)))))
              (value
-              (if (cdr rule)
-                  (funcall (cdr rule) header value)
-                (funcall mail-header-format-function header value))))))
+              (funcall (or (cdr rule) mail-header-format-function)
+                       header value)))))
     (insert "\n")))
 
 (provide 'mailheader)
diff --git a/lisp/mail/mspools.el b/lisp/mail/mspools.el
index 970f52c..6d83414 100644
--- a/lisp/mail/mspools.el
+++ b/lisp/mail/mspools.el
@@ -167,11 +167,11 @@ your primary spool is.  If this fails, set it to 
something like
 
 (defvar mspools-mode-map
   (let ((map (make-sparse-keymap)))
-    (define-key map "\C-c\C-c" 'mspools-visit-spool)
-    (define-key map "\C-m" 'mspools-visit-spool)
-    (define-key map " " 'mspools-visit-spool)
-    (define-key map "n" 'next-line)
-    (define-key map "p" 'previous-line)
+    (define-key map "\C-c\C-c" #'mspools-visit-spool)
+    (define-key map "\C-m" #'mspools-visit-spool)
+    (define-key map " " #'mspools-visit-spool)
+    (define-key map "n" #'next-line)
+    (define-key map "p" #'previous-line)
     map)
   "Keymap for the *spools* buffer.")
 
diff --git a/lisp/mail/rfc822.el b/lisp/mail/rfc822.el
index f07fcdf..2e97226 100644
--- a/lisp/mail/rfc822.el
+++ b/lisp/mail/rfc822.el
@@ -1,4 +1,4 @@
-;;; rfc822.el --- hairy RFC 822 (or later) parser for mail, news, etc.
+;;; rfc822.el --- hairy RFC 822 (or later) parser for mail, news, etc.  -*- 
lexical-binding: t; -*-
 
 ;; Copyright (C) 1986-1987, 1990, 2001-2021 Free Software Foundation,
 ;; Inc.
diff --git a/lisp/mail/rmail-spam-filter.el b/lisp/mail/rmail-spam-filter.el
index dda472e..d833685 100644
--- a/lisp/mail/rmail-spam-filter.el
+++ b/lisp/mail/rmail-spam-filter.el
@@ -1,4 +1,4 @@
-;;; rmail-spam-filter.el --- spam filter for Rmail, the Emacs mail reader
+;;; rmail-spam-filter.el --- spam filter for Rmail, the Emacs mail reader  -*- 
lexical-binding: t; -*-
 
 ;; Copyright (C) 2002-2021 Free Software Foundation, Inc.
 ;; Keywords: email, spam, filter, rmail
@@ -82,50 +82,42 @@
 (defcustom rmail-use-spam-filter nil
   "Non-nil to activate the Rmail spam filter.
 Set `rsf-definitions-alist' to define what you consider spam emails."
-  :type 'boolean
-  :group 'rmail-spam-filter)
+  :type 'boolean)
 
 (defcustom rsf-file "~/XRMAIL-SPAM"
   "Name of Rmail file for optionally saving some of the spam.
 You can either just delete spam, or save it in this file for
 later review.  Which action to take for each spam definition is
 specified by the \"action\" element of the definition."
-  :type 'string
-  :group 'rmail-spam-filter)
+  :type 'string)
 
 (defcustom rsf-no-blind-cc nil
   "Non-nil means mail with no explicit To: or Cc: is spam."
-  :type 'boolean
-  :group 'rmail-spam-filter)
+  :type 'boolean)
 
 (defcustom rsf-ignore-case nil
   "Non-nil means to ignore case in `rsf-definitions-alist'."
-  :type 'boolean
-  :group 'rmail-spam-filter)
+  :type 'boolean)
 
 (defcustom rsf-beep nil
   "Non-nil means to beep if spam is found."
-  :type 'boolean
-  :group 'rmail-spam-filter)
+  :type 'boolean)
 
 (defcustom rsf-sleep-after-message 2.0
   "Seconds to wait after displaying a message that spam was found."
-  :type 'number
-  :group 'rmail-spam-filter)
+  :type 'number)
 
 (defcustom rsf-min-region-to-spam-list 7
   "Minimum size of region that you can add to the spam list.
 The aim is to avoid adding too short a region, which could result
 in false positive identification of a valid message as spam."
-  :type 'integer
-  :group 'rmail-spam-filter)
+  :type 'integer)
 
 (defcustom rsf-autosave-newly-added-definitions nil
   "Non-nil to auto-save new spam entries.
 Any time you add an entry via the \"Spam\" menu, immediately saves
 the custom file."
-  :type 'boolean
-  :group 'rmail-spam-filter)
+  :type 'boolean)
 
 (defcustom rsf-white-list nil
   "List of regexps to identify valid senders.
@@ -133,8 +125,7 @@ If any element matches the \"From\" header, the message is
 flagged as a valid, non-spam message.  E.g., if your domain is
 \"emacs.com\" then including \"emacs\\\\.com\" in this list would
 flag all mail (purporting to be) from your colleagues as valid."
-  :type '(repeat regexp)
-  :group 'rmail-spam-filter)
+  :type '(repeat regexp))
 
 (defcustom rsf-definitions-alist nil
   "A list of rules (definitions) matching spam messages.
@@ -178,8 +169,7 @@ A rule matches only if all the specified elements match."
                 (choice :tag "Action selection"
                  (const :tag "Output and delete" output-and-delete)
                  (const :tag "Delete" delete-spam)
-                 ))))
-  :group 'rmail-spam-filter)
+                 )))))
 
 ;; FIXME nothing uses this, and it could just be let-bound.
 (defvar rsf-scanning-messages-now nil
@@ -224,6 +214,8 @@ the cdr is set to t.  Else, the car is set to nil."
        ;; empty buffer.
        (1- (or (rmail-first-unseen-message) 1))))
 
+(defvar bbdb/mail_auto_create_p)
+
 (defun rmail-spam-filter (msg)
   "Return nil if message number MSG is spam based on `rsf-definitions-alist'.
 If spam, optionally output message to a file `rsf-file' and delete
@@ -522,12 +514,12 @@ to the spam list (remember to save it)" 
region-to-spam-list))))))
       ["Customize spam definitions" rsf-customize-spam-definitions]
       ["Browse spam customizations" rsf-customize-group]
       ))
-  (define-key map "\C-cSt" 'rsf-add-subject-to-spam-list)
-  (define-key map "\C-cSr" 'rsf-add-sender-to-spam-list)
-  (define-key map "\C-cSn" 'rsf-add-region-to-spam-list)
-  (define-key map "\C-cSa" 'rsf-custom-save-all)
-  (define-key map "\C-cSd" 'rsf-customize-spam-definitions)
-  (define-key map "\C-cSg" 'rsf-customize-group))
+  (define-key map "\C-cSt" #'rsf-add-subject-to-spam-list)
+  (define-key map "\C-cSr" #'rsf-add-sender-to-spam-list)
+  (define-key map "\C-cSn" #'rsf-add-region-to-spam-list)
+  (define-key map "\C-cSa" #'rsf-custom-save-all)
+  (define-key map "\C-cSd" #'rsf-customize-spam-definitions)
+  (define-key map "\C-cSg" #'rsf-customize-group))
 
 (defun rsf-add-content-type-field ()
   "Maintain backward compatibility for `rmail-spam-filter'.
diff --git a/lisp/mail/rmail.el b/lisp/mail/rmail.el
index 8ccf1bf..c7960f8 100644
--- a/lisp/mail/rmail.el
+++ b/lisp/mail/rmail.el
@@ -551,7 +551,7 @@ Examples:
 (defvar rmail-reply-regexp
   (concat "\\`\\("
           rmail-re-abbrevs
-          "\\(([0-9]+)\\|\\[[0-9]+\\]\\|\\^[0-9]+\\)?[::] *\\)*")
+          "\\(([0-9]+)\\|\\[[0-9]+\\]\\|\\^[0-9]+\\)?\u00a0*[::] *\\)*")
   "Regexp to delete from Subject line before inserting `rmail-reply-prefix'.")
 
 (defcustom rmail-display-summary nil
@@ -1721,7 +1721,7 @@ not be a new one).  It returns non-nil if it got any new 
messages."
                  (buffer-read-only nil)
                  ;; Don't make undo records while getting mail.
                  (buffer-undo-list t)
-                 delete-files files file-last-names)
+                 files file-last-names) ;; delete-files
              ;; Pull files off all-files onto files as long as there is
              ;; no name conflict.  A conflict happens when two inbox
              ;; file names have the same last component.
@@ -1743,7 +1743,7 @@ not be a new one).  It returns non-nil if it got any new 
messages."
                (while (not (looking-back "\n\n" (- (point) 2)))
                  (insert "\n")))
              (setq found (or
-                          (rmail-get-new-mail-1 file-name files delete-files)
+                          (rmail-get-new-mail-1 file-name files nil) ;; 
delete-files
                           found))))
          ;; Move to the first new message unless we have other unseen
          ;; messages before it.
@@ -3356,7 +3356,7 @@ whitespace, replacing whitespace runs with a single space 
and
 removing prefixes such as Re:, Fwd: and so on and mailing list
 tags such as [tag]."
   (let ((subject (or (rmail-get-header "Subject" msgnum) ""))
-       (regexp "\\`[ \t\n]*\\(\\(\\w\\{1,4\\}[::]\\|\\[[^]]+]\\)[ \t\n]+\\)*"))
+       (regexp "\\`[ \t\n]*\\(\\(\\w\\{1,4\\}\u00a0*[::]\\|\\[[^]]+]\\)[ 
\t\n]+\\)*"))
     (setq subject (rfc2047-decode-string subject))
     (setq subject (replace-regexp-in-string regexp "" subject))
     (replace-regexp-in-string "[ \t\n]+" " " subject)))
diff --git a/lisp/mail/rmailedit.el b/lisp/mail/rmailedit.el
index c3b351d..fd24bdc 100644
--- a/lisp/mail/rmailedit.el
+++ b/lisp/mail/rmailedit.el
@@ -1,4 +1,4 @@
-;;; rmailedit.el --- "RMAIL edit mode"  Edit the current message
+;;; rmailedit.el --- "RMAIL edit mode"  Edit the current message  -*- 
lexical-binding: t; -*-
 
 ;; Copyright (C) 1985, 1994, 2001-2021 Free Software Foundation, Inc.
 
@@ -38,8 +38,8 @@
   (let ((map (make-sparse-keymap)))
     ;; Make a keymap that inherits text-mode-map.
     (set-keymap-parent map text-mode-map)
-    (define-key map "\C-c\C-c" 'rmail-cease-edit)
-    (define-key map "\C-c\C-]" 'rmail-abort-edit)
+    (define-key map "\C-c\C-c" #'rmail-cease-edit)
+    (define-key map "\C-c\C-]" #'rmail-abort-edit)
     map))
 
 (declare-function rmail-summary-disable "rmailsum" ())
@@ -69,7 +69,7 @@ This function runs the hooks `text-mode-hook' and 
`rmail-edit-mode-hook'.
     (setq-local auto-save-include-big-deletions t)
     ;; If someone uses C-x C-s, don't clobber the rmail file (bug#2625).
     (add-hook 'write-region-annotate-functions
-             'rmail-write-region-annotate nil t)
+             #'rmail-write-region-annotate nil t)
     (run-mode-hooks 'rmail-edit-mode-hook)))
 
 ;; Rmail Edit mode is suitable only for specially formatted data.
diff --git a/lisp/mail/rmailkwd.el b/lisp/mail/rmailkwd.el
index 657b362..acbb588 100644
--- a/lisp/mail/rmailkwd.el
+++ b/lisp/mail/rmailkwd.el
@@ -1,4 +1,4 @@
-;;; rmailkwd.el --- part of the "RMAIL" mail reader for Emacs
+;;; rmailkwd.el --- part of the "RMAIL" mail reader for Emacs  -*- 
lexical-binding: t; -*-
 
 ;; Copyright (C) 1985, 1988, 1994, 2001-2021 Free Software Foundation,
 ;; Inc.
@@ -73,7 +73,7 @@ according to the choice made, and returns a symbol."
            (or (eq major-mode 'rmail-summary-mode)
                (rmail-summary-exists)
                (and (setq old (rmail-get-keywords))
-                    (mapc 'rmail-make-label (split-string old ", "))))
+                    (mapc #'rmail-make-label (split-string old ", "))))
            (completing-read (concat prompt
                                     (if rmail-last-label
                                         (concat " (default "
diff --git a/lisp/mail/rmailmm.el b/lisp/mail/rmailmm.el
index ab5b49a..cdb994a 100644
--- a/lisp/mail/rmailmm.el
+++ b/lisp/mail/rmailmm.el
@@ -1,4 +1,4 @@
-;;; rmailmm.el --- MIME decoding and display stuff for RMAIL
+;;; rmailmm.el --- MIME decoding and display stuff for RMAIL  -*- 
lexical-binding: t; -*-
 
 ;; Copyright (C) 2006-2021 Free Software Foundation, Inc.
 
@@ -78,6 +78,7 @@
 (require 'rmail)
 (require 'mail-parse)
 (require 'message)
+(require 'cl-lib)
 
 ;;; User options.
 
@@ -101,8 +102,7 @@ all others are handled by `rmail-mime-bulk-handler'.
 Note also that this alist is ignored when the variable
 `rmail-enable-mime' is non-nil."
   :type '(alist :key-type regexp :value-type (repeat function))
-  :version "23.1"
-  :group 'rmail-mime)
+  :version "23.1")
 
 (defcustom rmail-mime-attachment-dirs-alist
   `(("text/.*" "~/Documents")
@@ -114,8 +114,7 @@ The first item is a regular expression matching a 
content-type.
 The remaining elements are directories, in order of decreasing preference.
 The first directory that exists is used."
   :type '(alist :key-type regexp :value-type (repeat directory))
-  :version "23.1"
-  :group 'rmail-mime)
+  :version "23.1")
 
 (defcustom rmail-mime-show-images 'button
   "What to do with image attachments that Emacs is capable of displaying.
@@ -128,12 +127,11 @@ automatically display the image in the buffer."
                 (const :tag "No special treatment" nil)
                 (number :tag "Show if smaller than certain size")
                 (other :tag "Always show" show))
-  :version "23.2"
-  :group 'rmail-mime)
+  :version "23.2")
 
 (defcustom rmail-mime-render-html-function
-  (cond ((fboundp 'libxml-parse-html-region) 'rmail-mime-render-html-shr)
-       ((executable-find "lynx") 'rmail-mime-render-html-lynx)
+  (cond ((fboundp 'libxml-parse-html-region) #'rmail-mime-render-html-shr)
+       ((executable-find "lynx") #'rmail-mime-render-html-lynx)
        (t nil))
   "Function to convert HTML to text.
 Called with buffer containing HTML extracted from message in a
@@ -177,9 +175,12 @@ operations such as HTML decoding")
 
 ;;; MIME-entity object
 
-(defun rmail-mime-entity (type disposition transfer-encoding
-                              display header tagline body children handler
-                              &optional truncated)
+(cl-defstruct (rmail-mime-entity
+               (:copier nil) (:constructor nil)
+               (:constructor rmail-mime-entity
+               ( type disposition transfer-encoding
+                 display header tagline body children handler
+                 &optional truncated)
   "Return a newly created MIME-entity object from arguments.
 
 A MIME-entity is a vector of 10 elements:
@@ -210,12 +211,7 @@ Content-Transfer-Encoding, and is a lower-case string.
 DISPLAY is a vector [CURRENT NEW], where CURRENT indicates how
 the header, tag line, and body of the entity are displayed now,
 and NEW indicates how their display should be updated.
-Both elements are vectors [HEADER-DISPLAY TAGLINE-DISPLAY BODY-DISPLAY],
-where each constituent element is a symbol for the corresponding
-item with these values:
-  nil: not displayed
-  t:   displayed by the decoded presentation form
-  raw: displayed by the raw MIME data (for the header and body only)
+Both elements are `rmail-mime-display' objects.
 
 HEADER and BODY are vectors [BEG END DISPLAY-FLAG], where BEG and
 END are markers that specify the region of the header or body lines
@@ -236,24 +232,13 @@ has just one child.  Any other entity has no child.
 HANDLER is a function to insert the entity according to DISPLAY.
 It is called with one argument ENTITY.
 
-TRUNCATED is non-nil if the text of this entity was truncated."
-
-  (vector type disposition transfer-encoding
-         display header tagline body children handler truncated))
-
-;; Accessors for a MIME-entity object.
-(defsubst rmail-mime-entity-type (entity) (aref entity 0))
-(defsubst rmail-mime-entity-disposition (entity) (aref entity 1))
-(defsubst rmail-mime-entity-transfer-encoding (entity) (aref entity 2))
-(defsubst rmail-mime-entity-display (entity) (aref entity 3))
-(defsubst rmail-mime-entity-header (entity) (aref entity 4))
-(defsubst rmail-mime-entity-tagline (entity) (aref entity 5))
-(defsubst rmail-mime-entity-body (entity) (aref entity 6))
-(defsubst rmail-mime-entity-children (entity) (aref entity 7))
-(defsubst rmail-mime-entity-handler (entity) (aref entity 8))
-(defsubst rmail-mime-entity-truncated (entity) (aref entity 9))
+TRUNCATED is non-nil if the text of this entity was truncated."))
+  type disposition transfer-encoding
+  display header tagline body children handler truncated)
+
 (defsubst rmail-mime-entity-set-truncated (entity truncated)
-  (aset entity 9 truncated))
+  (declare (obsolete (setf rmail-mime-entity-truncated) "28.1"))
+  (setf (rmail-mime-entity-truncated entity) truncated))
 
 ;;; Buttons
 
@@ -303,9 +288,16 @@ TRUNCATED is non-nil if the text of this entity was 
truncated."
 
 ;; Display options returned by rmail-mime-entity-display.
 ;; Value is on of nil, t, raw.
-(defsubst rmail-mime-display-header (disp)  (aref disp 0))
-(defsubst rmail-mime-display-tagline (disp) (aref disp 1))
-(defsubst rmail-mime-display-body (disp)    (aref disp 2))
+(cl-defstruct (rmail-mime-display
+               (:copier rmail-mime--copy-display) (:constructor nil)
+               (:constructor rmail-mime--make-display (header tagline body)
+                "Make an object describing how to display.
+Each field's value is a symbol for the corresponding
+item with these values:
+  nil: not displayed
+  t:   displayed by the decoded presentation form
+  raw: displayed by the raw MIME data (for the header and body only)."))
+  header tagline body)
 
 (defun rmail-mime-entity-segment (pos &optional entity)
   "Return a vector describing the displayed region of a MIME-entity at POS.
@@ -371,27 +363,30 @@ The value is a vector [INDEX HEADER TAGLINE BODY END], 
where
 (defun rmail-mime-shown-mode (entity)
   "Make MIME-entity ENTITY display in the default way."
   (let ((new (aref (rmail-mime-entity-display entity) 1)))
-    (aset new 0 (aref (rmail-mime-entity-header entity) 2))
-    (aset new 1 (aref (rmail-mime-entity-tagline entity) 2))
-    (aset new 2 (aref (rmail-mime-entity-body entity) 2)))
+    (setf (rmail-mime-display-header new)
+          (aref (rmail-mime-entity-header entity) 2))
+    (setf (rmail-mime-display-tagline new)
+          (aref (rmail-mime-entity-tagline entity) 2))
+    (setf (rmail-mime-display-body new)
+          (aref (rmail-mime-entity-body entity) 2)))
   (dolist (child (rmail-mime-entity-children entity))
     (rmail-mime-shown-mode child)))
 
 (defun rmail-mime-hidden-mode (entity)
   "Make MIME-entity ENTITY display in hidden mode."
   (let ((new (aref (rmail-mime-entity-display entity) 1)))
-    (aset new 0 nil)
-    (aset new 1 t)
-    (aset new 2 nil))
+    (setf (rmail-mime-display-header  new) nil)
+    (setf (rmail-mime-display-tagline new) t)
+    (setf (rmail-mime-display-body    new) nil))
   (dolist (child (rmail-mime-entity-children entity))
     (rmail-mime-hidden-mode child)))
 
 (defun rmail-mime-raw-mode (entity)
   "Make MIME-entity ENTITY display in raw mode."
   (let ((new (aref (rmail-mime-entity-display entity) 1)))
-    (aset new 0 'raw)
-    (aset new 1 nil)
-    (aset new 2 'raw))
+    (setf (rmail-mime-display-header  new) 'raw)
+    (setf (rmail-mime-display-tagline new) nil)
+    (setf (rmail-mime-display-body    new) 'raw))
   (dolist (child (rmail-mime-entity-children entity))
     (rmail-mime-raw-mode child)))
 
@@ -404,8 +399,8 @@ Use `raw' for raw mode, and any other non-nil value for 
decoded mode."
         (current (aref (rmail-mime-entity-display entity) 0))
         (segment (rmail-mime-entity-segment pos entity)))
     (if (or (eq state 'raw)
-           (and (not state)
-                (not (eq (rmail-mime-display-header current) 'raw))))
+           (not (or state
+                    (eq (rmail-mime-display-header current) 'raw))))
        ;; Enter the raw mode.
        (rmail-mime-raw-mode entity)
       ;; Enter the shown mode.
@@ -439,7 +434,7 @@ Use `raw' for raw mode, and any other non-nil value for 
decoded mode."
            ;; header.
            (if (and rmail-mime-mbox-buffer (= (aref segment 1) (point-min)))
                (let ((new (aref (rmail-mime-entity-display entity) 1)))
-                 (aset new 0 t))))
+                 (setf (rmail-mime-display-header new) t))))
        ;; Query as a warning before showing if truncated.
        (if (and (not (stringp entity))
                 (rmail-mime-entity-truncated entity))
@@ -448,7 +443,8 @@ Use `raw' for raw mode, and any other non-nil value for 
decoded mode."
        ;; Enter the shown mode.
        (rmail-mime-shown-mode entity)
        ;; Force this body shown.
-       (aset (aref (rmail-mime-entity-display entity) 1) 2 t))
+       (let ((new (aref (rmail-mime-entity-display entity) 1)))
+         (setf (rmail-mime-display-body new) t)))
       (let ((inhibit-read-only t)
            (modified (buffer-modified-p))
            (rmail-mime-mbox-buffer rmail-view-buffer)
@@ -458,9 +454,9 @@ Use `raw' for raw mode, and any other non-nil value for 
decoded mode."
          (rmail-mime-insert entity)
          (restore-buffer-modified-p modified))))))
 
-(define-key rmail-mode-map "\t" 'forward-button)
-(define-key rmail-mode-map [backtab] 'backward-button)
-(define-key rmail-mode-map "\r" 'rmail-mime-toggle-hidden)
+(define-key rmail-mode-map "\t" #'forward-button)
+(define-key rmail-mode-map [backtab] #'backward-button)
+(define-key rmail-mode-map "\r" #'rmail-mime-toggle-hidden)
 
 ;;; Handlers
 
@@ -483,7 +479,7 @@ to the tag line."
     (when item
       (if (stringp item)
          (insert item)
-       (apply 'insert-button item))))
+       (apply #'insert-button item))))
   ;; Follow the tagline by an empty line to make it a separate
   ;; paragraph, so that the paragraph direction of the following text
   ;; is determined based on that text.
@@ -495,8 +491,10 @@ to the tag line."
        (modified (buffer-modified-p))
        ;; If we are going to show the body, the new button label is
        ;; "Hide".  Otherwise, it's "Show".
-       (label (if (aref (aref (rmail-mime-entity-display entity) 1) 2) "Hide"
-                "Show"))
+       (label
+        (if (rmail-mime-display-body
+             (aref (rmail-mime-entity-display entity) 1))
+            "Hide" "Show"))
        (button (next-button (point))))
     ;; Go to the second character of the button "Show" or "Hide".
     (goto-char (1+ (button-start button)))
@@ -556,9 +554,10 @@ HEADER is a header component of a MIME-entity object (see
   (rmail-mime-insert-text
    (rmail-mime-entity content-type content-disposition
                      content-transfer-encoding
-                     (vector (vector nil nil nil) (vector nil nil t))
+                     (vector (rmail-mime--make-display nil nil nil)
+                             (rmail-mime--make-display nil nil t))
                      (vector nil nil nil) (vector "" (cons nil nil) t)
-                     (vector nil nil nil) nil 'rmail-mime-insert-text))
+                     (vector nil nil nil) nil #'rmail-mime-insert-text))
   t)
 
 (defun rmail-mime-insert-decoded-text (entity)
@@ -592,7 +591,7 @@ HEADER is a header component of a MIME-entity object (see
   (let ((current (aref (rmail-mime-entity-display entity) 0))
        (new (aref (rmail-mime-entity-display entity) 1))
        (header (rmail-mime-entity-header entity))
-       (tagline (rmail-mime-entity-tagline entity))
+       ;; (tagline (rmail-mime-entity-tagline entity))
        (body (rmail-mime-entity-body entity))
        (beg (point))
        (segment (rmail-mime-entity-segment (point) entity)))
@@ -634,7 +633,7 @@ HEADER is a header component of a MIME-entity object (see
 
 (defun rmail-mime-insert-image (entity)
   "Decode and insert the image body of MIME-entity ENTITY."
-  (let* ((content-type (car (rmail-mime-entity-type entity)))
+  (let* (;; (content-type (car (rmail-mime-entity-type entity)))
         (bulk-data (aref (rmail-mime-entity-tagline entity) 1))
         (body (rmail-mime-entity-body entity))
         data)
@@ -709,6 +708,9 @@ HEADER is a header component of a MIME-entity object (see
 (declare-function libxml-parse-html-region "xml.c"
                  (start end &optional base-url discard-comments))
 
+(defvar shr-inhibit-images)
+(defvar shr-width)
+
 (defun rmail-mime-render-html-shr (source-buffer)
   (let ((dom (with-current-buffer source-buffer
               (libxml-parse-html-region (point-min) (point-max))))
@@ -759,7 +761,8 @@ For images that Emacs is capable of displaying, the behavior
 depends upon the value of `rmail-mime-show-images'."
   (rmail-mime-insert-bulk
    (rmail-mime-entity content-type content-disposition 
content-transfer-encoding
-                     (vector (vector nil nil nil) (vector nil t nil))
+                     (vector (rmail-mime--make-display nil nil nil)
+                             (rmail-mime--make-display nil t nil))
                      (vector nil nil nil) (vector "" (cons nil nil) t)
                      (vector nil nil nil) nil 'rmail-mime-insert-bulk)))
 
@@ -1024,9 +1027,10 @@ The other arguments are the same as 
`rmail-mime-multipart-handler'."
                            nil (format "%s/%d" parse-tag index)
                            content-type content-disposition)))
                ;; Display a tagline.
-               (aset (aref (rmail-mime-entity-display child) 1) 1
+               (setf (rmail-mime-display-tagline
+                      (aref (rmail-mime-entity-display child) 1))
                      (aset (rmail-mime-entity-tagline child) 2 t))
-               (rmail-mime-entity-set-truncated child truncated)
+               (setf (rmail-mime-entity-truncated child) truncated)
                (push child entities)))
 
          (delete-region end next)
@@ -1072,8 +1076,8 @@ The other arguments are the same as 
`rmail-mime-multipart-handler'."
   (let ((current (aref (rmail-mime-entity-display entity) 0))
        (new (aref (rmail-mime-entity-display entity) 1))
        (header (rmail-mime-entity-header entity))
-       (tagline (rmail-mime-entity-tagline entity))
-       (body (rmail-mime-entity-body entity))
+       ;; (tagline (rmail-mime-entity-tagline entity))
+       ;; (body (rmail-mime-entity-body entity))
        (beg (point))
        (segment (rmail-mime-entity-segment (point) entity)))
     ;; header
@@ -1169,13 +1173,11 @@ The parsed header value:
                       content-transfer-encoding))
   (save-restriction
     (widen)
-    (let ((entity (get-text-property (1- (point)) 'rmail-mime-entity))
-         current new)
+    (let ((entity (get-text-property (1- (point)) 'rmail-mime-entity)))
       (when entity
-       (setq current (aref (rmail-mime-entity-display entity) 0)
-             new (aref (rmail-mime-entity-display entity) 1))
-       (dotimes (i 3)
-         (aset current i (aref new i)))))))
+       (let ((new (aref (rmail-mime-entity-display entity) 1)))
+         (setf (aref (rmail-mime-entity-display entity) 0)
+               (rmail-mime--copy-display new)))))))
 
 (defun rmail-mime-show (&optional show-headers)
   "Handle the current buffer as a MIME message.
@@ -1240,13 +1242,15 @@ modified."
               (header (vector (point-min-marker) hdr-end nil))
               (tagline (vector parse-tag (cons nil nil) t))
               (body (vector hdr-end (point-max-marker) is-inline))
-              (new (vector (aref header 2) (aref tagline 2) (aref body 2)))
+              (new (rmail-mime--make-display
+                    (aref header 2) (aref tagline 2) (aref body 2)))
               children handler entity)
          (cond ((string-match "multipart/.*" (car content-type))
                 (save-restriction
                   (narrow-to-region (1- end) (point-max))
                   (if (zerop (length parse-tag)) ; top level of message
-                      (aset new 1 (aset tagline 2 nil))) ; don't show tagline
+                      (setf (rmail-mime-display-tagline new)
+                            (aset tagline 2 nil))) ; don't show tagline
                   (setq children (rmail-mime-process-multipart
                                   content-type
                                   content-disposition
@@ -1260,37 +1264,38 @@ modified."
                                                   '("text/plain") '("inline")))
                          (msg-new (aref (rmail-mime-entity-display msg) 1)))
                     ;; Show header of the child.
-                    (aset msg-new 0 t)
+                    (setf (rmail-mime-display-header msg-new) t)
                     (aset (rmail-mime-entity-header msg) 2 t)
                     ;; Hide tagline of the child.
-                    (aset msg-new 1 nil)
+                    (setf (rmail-mime-display-tagline msg-new) nil)
                     (aset (rmail-mime-entity-tagline msg) 2 nil)
                     (setq children (list msg)
                           handler 'rmail-mime-insert-multipart))))
                ((and is-inline (string-match "text/html" (car content-type)))
                 ;; Display tagline, so part can be detached
-                (aset new 1 (aset tagline 2 t))
-                (aset new 2 (aset body 2 t)) ; display body also.
+                (setf (rmail-mime-display-tagline new) (aset tagline 2 t))
+                (setf (rmail-mime-display-body new) (aset body 2 t)) ; display 
body also.
                 (setq handler 'rmail-mime-insert-bulk))
                ;; Inline non-HTML text
                ((and is-inline (string-match "text/" (car content-type)))
                 ;; Don't need a tagline.
-                (aset new 1 (aset tagline 2 nil))
+                (setf (rmail-mime-display-tagline new) (aset tagline 2 nil))
                 (setq handler 'rmail-mime-insert-text))
                (t
                 ;; Force hidden mode.
-                (aset new 1 (aset tagline 2 t))
-                (aset new 2 (aset body 2 nil))
+                (setf (rmail-mime-display-tagline new) (aset tagline 2 t))
+                (setf (rmail-mime-display-body new) (aset body 2 nil))
                 (setq handler 'rmail-mime-insert-bulk)))
-         (setq entity (rmail-mime-entity content-type
-                                         content-disposition
-                                         content-transfer-encoding
-                                         (vector (vector nil nil nil) new)
-                                         header tagline body children handler))
+         (setq entity (rmail-mime-entity
+                       content-type
+                       content-disposition
+                       content-transfer-encoding
+                       (vector (rmail-mime--make-display nil nil nil) new)
+                       header tagline body children handler))
          (if (and (eq handler 'rmail-mime-insert-bulk)
                   (rmail-mime-set-bulk-data entity))
              ;; Show the body.
-             (aset new 2 (aset body 2 t)))
+             (setf (rmail-mime-display-body new) (aset body 2 t)))
          entity)
 
       ;; Hide headers and handle the part.
@@ -1324,7 +1329,8 @@ If an error occurs, return an error message string."
                                               '("text/plain") '("inline")))
                   (new (aref (rmail-mime-entity-display entity) 1)))
              ;; Show header.
-             (aset new 0 (aset (rmail-mime-entity-header entity) 2 t))
+             (setf (rmail-mime-display-header new)
+                   (aset (rmail-mime-entity-header entity) 2 t))
              entity)))
       (error (format "%s" err)))))
 
@@ -1339,7 +1345,7 @@ available."
        ;; Not a raw-mode.  Each handler should handle it.
        (funcall (rmail-mime-entity-handler entity) entity)
       (let ((header (rmail-mime-entity-header entity))
-           (tagline (rmail-mime-entity-tagline entity))
+           ;; (tagline (rmail-mime-entity-tagline entity))
            (body (rmail-mime-entity-body entity))
            (beg (point))
            (segment (rmail-mime-entity-segment (point) entity)))
@@ -1370,15 +1376,15 @@ available."
                                       (aref body 0) (aref body 1))
              (or (bolp) (insert "\n")))
            (put-text-property beg (point) 'rmail-mime-entity entity)))))
-    (dotimes (i 3)
-      (aset current i (aref new i)))))
+    (setf (aref (rmail-mime-entity-display entity) 0)
+          (rmail-mime--copy-display new))))
 
 (define-derived-mode rmail-mime-mode fundamental-mode "RMIME"
   "Major mode used in `rmail-mime' buffers."
   (setq font-lock-defaults '(rmail-font-lock-keywords t t nil nil)))
 
 ;;;###autoload
-(defun rmail-mime (&optional arg state)
+(defun rmail-mime (&optional _arg state)
   "Toggle the display of a MIME message.
 
 The actual behavior depends on the value of `rmail-enable-mime'.
@@ -1442,7 +1448,7 @@ The arguments ARG and STATE have no effect in this case."
        (rmail-mime-view-buffer rmail-view-buffer)
        (rmail-mime-coding-system nil))
     ;; If ENTITY is not a vector, it is a string describing an error.
-    (if (vectorp entity)
+    (if (rmail-mime-entity-p entity)
        (with-current-buffer rmail-mime-view-buffer
          (erase-buffer)
          ;; This condition-case is for catching an error in the
@@ -1530,7 +1536,7 @@ This is the usual value of 
`rmail-insert-mime-forwarded-message-function'."
           (rmail-mime-view-buffer rmail-view-buffer)
           (header-end (save-excursion
                         (re-search-forward "^$" nil 'move) (point)))
-          (body-end (point-max))
+          ;; (body-end (point-max))
           (entity (rmail-mime-parse)))
       (or
        ;; At first, just search the headers.
diff --git a/lisp/mail/rmailmsc.el b/lisp/mail/rmailmsc.el
index ef5f3c3..673b2c5 100644
--- a/lisp/mail/rmailmsc.el
+++ b/lisp/mail/rmailmsc.el
@@ -1,4 +1,4 @@
-;;; rmailmsc.el --- miscellaneous support functions for the RMAIL mail reader
+;;; rmailmsc.el --- miscellaneous support functions for the RMAIL mail reader  
-*- lexical-binding: t; -*-
 
 ;; Copyright (C) 1985, 2001-2021 Free Software Foundation, Inc.
 
@@ -45,7 +45,7 @@ This applies only to the current session."
           (nreverse (mail-parse-comma-list)))))
     (when (or (not rmail-inbox-list)
              (y-or-n-p (concat "Replace "
-                               (mapconcat 'identity
+                               (mapconcat #'identity
                                           rmail-inbox-list
                                           ", ")
                                "? ")))
diff --git a/lisp/mail/rmailout.el b/lisp/mail/rmailout.el
index 9305a48..eb8590f 100644
--- a/lisp/mail/rmailout.el
+++ b/lisp/mail/rmailout.el
@@ -1,4 +1,4 @@
-;;; rmailout.el --- "RMAIL" mail reader for Emacs: output message to a file
+;;; rmailout.el --- "RMAIL" mail reader for Emacs: output message to a file  
-*- lexical-binding: t; -*-
 
 ;; Copyright (C) 1985, 1987, 1993-1994, 2001-2021 Free Software
 ;; Foundation, Inc.
@@ -81,14 +81,14 @@ This uses `rmail-output-file-alist'."
                      (widen)
                      (narrow-to-region beg end)
                      (let ((tail rmail-output-file-alist)
-                           answer err)
+                           answer) ;; err
                        ;; Suggest a file based on a pattern match.
                        (while (and tail (not answer))
                          (goto-char (point-min))
                          (if (re-search-forward (caar tail) nil t)
                              (setq answer
                                    (condition-case err
-                                       (eval (cdar tail))
+                                       (eval (cdar tail) t)
                                      (error
                                       (display-warning
                                        'rmail-output
@@ -197,7 +197,8 @@ display message number MSG."
 
 (defun rmail-convert-to-babyl-format ()
   "Convert the mbox message in the current buffer to Babyl format."
-  (let ((count 0) (start (point-min))
+  (let (;; (count 0)
+       (start (point-min))
        (case-fold-search nil)
        (buffer-undo-list t))
     (goto-char (point-min))
@@ -357,7 +358,7 @@ unless NOMSG is a symbol (neither nil nor t).
 AS-SEEN is non-nil if we are copying the message \"as seen\"."
   (let ((case-fold-search t)
         encrypted-file-name
-       from date)
+       ) ;; from date
     (goto-char (point-min))
     ;; Preserve the Mail-From and MIME-Version fields
     ;; even if they have been pruned.
diff --git a/lisp/mail/rmailsort.el b/lisp/mail/rmailsort.el
index 2c42e6c..1669c8c 100644
--- a/lisp/mail/rmailsort.el
+++ b/lisp/mail/rmailsort.el
@@ -1,4 +1,4 @@
-;;; rmailsort.el --- Rmail: sort messages
+;;; rmailsort.el --- Rmail: sort messages  -*- lexical-binding: t; -*-
 
 ;; Copyright (C) 1990, 1993-1994, 2001-2021 Free Software Foundation,
 ;; Inc.
@@ -142,7 +142,7 @@ If prefix argument REVERSE is non-nil, sorts in reverse 
order."
                              "\\(,\\|\\'\\)")
                      labelvec))
       (setq labels (substring labels (match-end 0))))
-    (setq labelvec (apply 'vector (nreverse labelvec))
+    (setq labelvec (apply #'vector (nreverse labelvec))
          nmax (length labelvec))
     (rmail-sort-messages reverse
                         ;; If no labels match, returns nmax; if they
@@ -205,7 +205,7 @@ Numeric keys are sorted numerically, all others as strings."
            (inhibit-read-only t)
            (current-message nil)
            (msgnum 1)
-           (msginfo nil)
+           ;; (msginfo nil)
            (undo (not (eq buffer-undo-list t))))
        ;; There's little hope that we can easily undo after that.
        (buffer-disable-undo (current-buffer))
diff --git a/lisp/mail/smtpmail.el b/lisp/mail/smtpmail.el
index 5526f2f..ac5e8c3 100644
--- a/lisp/mail/smtpmail.el
+++ b/lisp/mail/smtpmail.el
@@ -186,7 +186,7 @@ mean \"try again\"."
 (defvar smtpmail-auth-supported '(cram-md5 plain login)
   "List of supported SMTP AUTH mechanisms.
 The list is in preference order.
-Every element should have a matching `cl-defmethod' for
+Every element should have a matching `cl-defmethod'
 for `smtpmail-try-auth-method'.")
 
 (defvar smtpmail-mail-address nil
@@ -326,7 +326,7 @@ for `smtpmail-try-auth-method'.")
            ;; Insert an extra newline if we need it to work around
            ;; Sun's bug that swallows newlines.
            (goto-char (1+ delimline))
-           (if (eval mail-mailer-swallows-blank-line)
+           (if (eval mail-mailer-swallows-blank-line t)
                (newline))
            ;; Find and handle any Fcc fields.
            (goto-char (point-min))
@@ -627,7 +627,7 @@ USER and PASSWORD should be non-nil."
           (= code (car response)))))
 
 (defun smtpmail-response-text (response)
-  (mapconcat 'identity (cdr response) "\n"))
+  (mapconcat #'identity (cdr response) "\n"))
 
 (defun smtpmail-query-smtp-server ()
   "Query for an SMTP server and try to contact it.
@@ -741,7 +741,7 @@ Returns an error if the server cannot be contacted."
                           "Unable to contact server")))
 
          ;; set the send-filter
-         (set-process-filter process 'smtpmail-process-filter)
+         (set-process-filter process #'smtpmail-process-filter)
 
          (let* ((greeting (plist-get (cdr result) :greeting))
                 (code (smtpmail-response-code greeting)))
diff --git a/lisp/mail/supercite.el b/lisp/mail/supercite.el
index 99ac41d..dc1c641 100644
--- a/lisp/mail/supercite.el
+++ b/lisp/mail/supercite.el
@@ -1,4 +1,4 @@
-;;; supercite.el --- minor mode for citing mail and news replies
+;;; supercite.el --- minor mode for citing mail and news replies  -*- 
lexical-binding: t; -*-
 
 ;; Copyright (C) 1993, 1997, 2001-2021 Free Software Foundation, Inc.
 
@@ -527,71 +527,71 @@ string."
 
 (defvar sc-T-keymap
   (let ((map (make-sparse-keymap)))
-    (define-key map "a" 'sc-S-preferred-attribution-list)
-    (define-key map "b" 'sc-T-mail-nuke-blank-lines)
-    (define-key map "c" 'sc-T-confirm-always)
-    (define-key map "d" 'sc-T-downcase)
-    (define-key map "e" 'sc-T-electric-references)
-    (define-key map "f" 'sc-T-auto-fill-region)
-    (define-key map "h" 'sc-T-describe)
-    (define-key map "l" 'sc-S-cite-region-limit)
-    (define-key map "n" 'sc-S-mail-nuke-mail-headers)
-    (define-key map "N" 'sc-S-mail-header-nuke-list)
-    (define-key map "o" 'sc-T-electric-circular)
-    (define-key map "p" 'sc-S-preferred-header-style)
-    (define-key map "s" 'sc-T-nested-citation)
-    (define-key map "u" 'sc-T-use-only-preferences)
-    (define-key map "w" 'sc-T-fixup-whitespace)
-    (define-key map "?" 'sc-T-describe)
+    (define-key map "a" #'sc-S-preferred-attribution-list)
+    (define-key map "b" #'sc-T-mail-nuke-blank-lines)
+    (define-key map "c" #'sc-T-confirm-always)
+    (define-key map "d" #'sc-T-downcase)
+    (define-key map "e" #'sc-T-electric-references)
+    (define-key map "f" #'sc-T-auto-fill-region)
+    (define-key map "h" #'sc-T-describe)
+    (define-key map "l" #'sc-S-cite-region-limit)
+    (define-key map "n" #'sc-S-mail-nuke-mail-headers)
+    (define-key map "N" #'sc-S-mail-header-nuke-list)
+    (define-key map "o" #'sc-T-electric-circular)
+    (define-key map "p" #'sc-S-preferred-header-style)
+    (define-key map "s" #'sc-T-nested-citation)
+    (define-key map "u" #'sc-T-use-only-preferences)
+    (define-key map "w" #'sc-T-fixup-whitespace)
+    (define-key map "?" #'sc-T-describe)
     map)
   "Keymap for sub-keymap of setting and toggling functions.")
 
 (defvar sc-mode-map
   (let ((map (make-sparse-keymap)))
-    (define-key map "c"    'sc-cite-region)
-    (define-key map "f"    'sc-mail-field-query)
-    (define-key map "g"    'sc-mail-process-headers)
-    (define-key map "h"    'sc-describe)
-    (define-key map "i"    'sc-insert-citation)
-    (define-key map "o"    'sc-open-line)
-    (define-key map "r"    'sc-recite-region)
-    (define-key map "\C-p" 'sc-raw-mode-toggle)
-    (define-key map "u"    'sc-uncite-region)
-    (define-key map "w"    'sc-insert-reference)
-    (define-key map "\C-t"  sc-T-keymap)
-    (define-key map "?"    'sc-describe)
+    (define-key map "c"    #'sc-cite-region)
+    (define-key map "f"    #'sc-mail-field-query)
+    (define-key map "g"    #'sc-mail-process-headers)
+    (define-key map "h"    #'sc-describe)
+    (define-key map "i"    #'sc-insert-citation)
+    (define-key map "o"    #'sc-open-line)
+    (define-key map "r"    #'sc-recite-region)
+    (define-key map "\C-p" #'sc-raw-mode-toggle)
+    (define-key map "u"    #'sc-uncite-region)
+    (define-key map "w"    #'sc-insert-reference)
+    (define-key map "\C-t"   sc-T-keymap)
+    (define-key map "?"    #'sc-describe)
     map)
   "Keymap for Supercite quasi-mode.")
 
 (defvar sc-electric-mode-map
   (let ((map (make-sparse-keymap)))
-    (define-key map "p"    'sc-eref-prev)
-    (define-key map "n"    'sc-eref-next)
-    (define-key map "s"    'sc-eref-setn)
-    (define-key map "j"    'sc-eref-jump)
-    (define-key map "x"    'sc-eref-abort)
-    (define-key map "q"    'sc-eref-abort)
-    (define-key map "\r"   'sc-eref-exit)
-    (define-key map "\n"   'sc-eref-exit)
-    (define-key map "g"    'sc-eref-goto)
-    (define-key map "?"    'describe-mode)
-    (define-key map "\C-h" 'describe-mode)
-    (define-key map [f1]   'describe-mode)
-    (define-key map [help] 'describe-mode)
+    (define-key map "p"    #'sc-eref-prev)
+    (define-key map "n"    #'sc-eref-next)
+    (define-key map "s"    #'sc-eref-setn)
+    (define-key map "j"    #'sc-eref-jump)
+    (define-key map "x"    #'sc-eref-abort)
+    (define-key map "q"    #'sc-eref-abort)
+    (define-key map "\r"   #'sc-eref-exit)
+    (define-key map "\n"   #'sc-eref-exit)
+    (define-key map "g"    #'sc-eref-goto)
+    (define-key map "?"    #'describe-mode)
+    (define-key map "\C-h" #'describe-mode)
+    (define-key map [f1]   #'describe-mode)
+    (define-key map [help] #'describe-mode)
     map)
   "Keymap for `sc-electric-mode' electric references mode.")
 
 
 (defvar sc-minibuffer-local-completion-map
   (let ((map (copy-keymap minibuffer-local-completion-map)))
-    (define-key map "\C-t" 'sc-toggle-fn)
-    (define-key map " "    'self-insert-command)
+    (define-key map "\C-t" #'sc-toggle-fn)
+    (define-key map " "    #'self-insert-command)
     map)
   "Keymap for minibuffer confirmation of attribution strings.")
 
 (defvar sc-minibuffer-local-map
   (let ((map (copy-keymap minibuffer-local-map)))
-    (define-key map "\C-t" 'sc-toggle-fn)
+    (define-key map "\C-t" #'sc-toggle-fn)
     map)
   "Keymap for minibuffer confirmation of attribution strings.")
 
@@ -1109,6 +1109,8 @@ Only used during confirmation."
   (setq sc-attrib-or-cite (not sc-attrib-or-cite))
   (throw 'sc-reconfirm t))
 
+(defvar completer-disable) ;; From some `completer.el' package.
+
 (defun sc-select-attribution ()
   "Select an attribution from `sc-attributions'.
 
@@ -1150,7 +1152,7 @@ to the auto-selected attribution string."
              (setq attribution attrib
                    attriblist nil))
             ((listp attrib)
-             (setq attribution (eval attrib))
+             (setq attribution (eval attrib t))
               (if (stringp attribution)
                   (setq attriblist nil)
                 (setq attribution nil
@@ -1593,7 +1595,7 @@ error occurs."
   (let ((ref (nth sc-eref-style sc-rewrite-header-list)))
     (condition-case err
        (progn
-         (eval ref)
+         (eval ref t)
          (let ((lines (count-lines (point-min) (point-max))))
            (or nomsg (message "Ref header %d [%d line%s]: %s"
                               sc-eref-style lines
@@ -1767,8 +1769,7 @@ querying you by typing `C-h'.  Note that the format is 
changed
 slightly from that used by `set-variable' -- the current value is
 printed just after the variable's name instead of at the bottom of the
 help window."
-  (let* ((minibuffer-help-form '(funcall myhelp))
-        (myhelp
+  (let* ((myhelp
          (lambda ()
            (with-output-to-temp-buffer "*Help*"
              (prin1 var)
@@ -1784,7 +1785,8 @@ help window."
                                1))
              (with-current-buffer standard-output
                (help-mode))
-             nil))))
+             nil)))
+        (minibuffer-help-form `(funcall #',myhelp)))
     (set var (eval-minibuffer (format "Set %s to value: " var)))))
 
 (defmacro sc-toggle-symbol (rootname)
diff --git a/lisp/mail/uce.el b/lisp/mail/uce.el
index a573c8a..9ebffef 100644
--- a/lisp/mail/uce.el
+++ b/lisp/mail/uce.el
@@ -1,4 +1,4 @@
-;;; uce.el --- facilitate reply to unsolicited commercial email
+;;; uce.el --- facilitate reply to unsolicited commercial email  -*- 
lexical-binding: t; -*-
 
 ;; Copyright (C) 1996, 1998, 2000-2021 Free Software Foundation, Inc.
 
@@ -127,14 +127,12 @@
   "A symbol indicating which mail reader you are using.
 Choose from: `gnus', `rmail'."
   :type '(choice (const gnus) (const rmail))
-  :version "20.3"
-  :group 'uce)
+  :version "20.3")
 
 (defcustom uce-setup-hook nil
   "Hook to run after UCE rant message is composed.
 This hook is run after `mail-setup-hook', which is run as well."
-  :type 'hook
-  :group 'uce)
+  :type 'hook)
 
 (defcustom uce-message-text
   "Recently, I have received an Unsolicited Commercial E-mail from you.
@@ -180,36 +178,31 @@ on beginning of some line from the spamming list.  So, 
when you set it
 up, it might be a good idea to actually use this feature.
 
 Value nil means insert no text by default, lets you type it in."
-  :type '(choice (const nil) string)
-  :group 'uce)
+  :type '(choice (const nil) string))
 
 (defcustom uce-uce-separator
   "----- original unsolicited commercial email follows -----"
   "Line that will begin quoting of the UCE.
 Value nil means use no separator."
-  :type '(choice (const nil) string)
-  :group 'uce)
+  :type '(choice (const nil) string))
 
 (defcustom uce-signature mail-signature
 "Text to put as your signature after the note to UCE sender.
 Value nil means none, t means insert `~/.signature' file (if it happens
 to exist), if this variable is a string this string will be inserted
 as your signature."
-  :type '(choice (const nil) (const t) string)
-  :group 'uce)
+  :type '(choice (const nil) (const t) string))
 
 (defcustom uce-default-headers
   "Errors-To: nobody@localhost\nPrecedence: bulk\n"
   "Additional headers to use when responding to a UCE with 
\\[uce-reply-to-uce].
 These are mostly meant for headers that prevent delivery errors reporting."
-  :type '(choice (const nil) string)
-  :group 'uce)
+  :type '(choice (const nil) string))
 
 (defcustom uce-subject-line
   "Spam alert: unsolicited commercial e-mail"
   "Subject of the message that will be sent in response to a UCE."
-  :type 'string
-  :group 'uce)
+  :type 'string)
 
 ;; End of user options.
 
@@ -221,7 +214,7 @@ These are mostly meant for headers that prevent delivery 
errors reporting."
 (declare-function rmail-toggle-header "rmail" (&optional arg))
 
 ;;;###autoload
-(defun uce-reply-to-uce (&optional ignored)
+(defun uce-reply-to-uce (&optional _ignored)
   "Compose a reply to unsolicited commercial email (UCE).
 Sets up a reply buffer addressed to: the sender, his postmaster,
 his abuse@ address, and the postmaster of the mail relay used.
@@ -367,7 +360,7 @@ You might need to set `uce-mail-reader' before using this."
       ;; functions in mail-mode, etc.
       (run-hooks 'mail-setup-hook 'uce-setup-hook))))
 
-(defun uce-insert-ranting (&optional ignored)
+(defun uce-insert-ranting (&optional _ignored)
   "Insert text of the usual reply to UCE into current buffer."
   (interactive "P")
   (insert uce-message-text))
diff --git a/lisp/mail/unrmail.el b/lisp/mail/unrmail.el
index 34de416..5b1abd5 100644
--- a/lisp/mail/unrmail.el
+++ b/lisp/mail/unrmail.el
@@ -1,4 +1,4 @@
-;;; unrmail.el --- convert Rmail Babyl files to mbox files
+;;; unrmail.el --- convert Rmail Babyl files to mbox files  -*- 
lexical-binding: t; -*-
 
 ;; Copyright (C) 1992, 2001-2021 Free Software Foundation, Inc.
 
@@ -235,7 +235,7 @@ The variable `unrmail-mbox-format' controls which mbox 
format to use."
            ;; Insert the `From ' line.
            (insert mail-from)
            ;; Record the keywords and attributes in our special way.
-           (insert "X-RMAIL-ATTRIBUTES: " (apply 'string attrs) "\n")
+           (insert "X-RMAIL-ATTRIBUTES: " (apply #'string attrs) "\n")
            (when keywords
              (insert "X-RMAIL-KEYWORDS: " keywords "\n"))
            ;; Convert From to >From, etc.
diff --git a/lisp/man.el b/lisp/man.el
index 1fded38..abb9bba 100644
--- a/lisp/man.el
+++ b/lisp/man.el
@@ -1024,7 +1024,7 @@ to auto-complete your input based on the installed manual 
pages."
 ;;;###autoload
 (defun man-follow (man-args)
   "Get a Un*x manual page of the item under point and put it in a buffer."
-  (interactive (list (Man-default-man-entry)))
+  (interactive (list (Man-default-man-entry)) man-common)
   (if (or (not man-args)
          (string= man-args ""))
       (error "No item under point")
@@ -1143,7 +1143,7 @@ Return the buffer in which the manpage will appear."
 
 (defun Man-update-manpage ()
   "Reformat current manpage by calling the man command again synchronously."
-  (interactive)
+  (interactive nil man-common)
   (when (eq Man-arguments nil)
     ;;this shouldn't happen unless it is not in a Man buffer."
     (error "Man-arguments not initialized"))
@@ -1239,7 +1239,7 @@ See the variable `Man-notify-method' for the different 
notification behaviors."
 (defun Man-fontify-manpage ()
   "Convert overstriking and underlining to the correct fonts.
 Same for the ANSI bold and normal escape sequences."
-  (interactive)
+  (interactive nil man-common)
   (goto-char (point-min))
   ;; Fontify ANSI escapes.
   (let ((ansi-color-apply-face-function #'ansi-color-apply-text-property-face)
@@ -1355,7 +1355,7 @@ default type, `Man-xref-man-page' is used for the 
buttons."
 Normally skip any jobs that should have been done by the sed script,
 but when called interactively, do those jobs even if the sed
 script would have done them."
-  (interactive "p")
+  (interactive "p" man-common)
   (if (or interactive (not Man-sed-script))
       (progn
        (goto-char (point-min))
@@ -1527,7 +1527,14 @@ manpage command."
 
 (defvar bookmark-make-record-function)
 
-(define-derived-mode Man-mode special-mode "Man"
+(define-derived-mode man-common special-mode "Man Shared"
+  "Parent mode for `Man-mode' like modes.
+This mode is here to be inherited by modes that need to use
+commands from `Man-mode'.  Used by `woman'.
+(In itself, this mode currently does nothing.)"
+  :interactive nil)
+
+(define-derived-mode Man-mode man-common "Man"
   "A mode for browsing Un*x manual pages.
 
 The following man commands are available in the buffer.  Try
@@ -1723,7 +1730,7 @@ The following key bindings are currently in effect in the 
buffer:
 
 (defun Man-next-section (n)
   "Move point to Nth next section (default 1)."
-  (interactive "p")
+  (interactive "p" man-common)
   (let ((case-fold-search nil)
         (start (point)))
     (if (looking-at Man-heading-regexp)
@@ -1739,7 +1746,7 @@ The following key bindings are currently in effect in the 
buffer:
 
 (defun Man-previous-section (n)
   "Move point to Nth previous section (default 1)."
-  (interactive "p")
+  (interactive "p" man-common)
   (let ((case-fold-search nil))
     (if (looking-at Man-heading-regexp)
        (forward-line -1))
@@ -1756,8 +1763,7 @@ Returns t if section is found, nil otherwise."
     (if (re-search-forward (concat "^" section) (point-max) t)
        (progn (beginning-of-line) t)
       (goto-char curpos)
-      nil)
-    ))
+      nil)))
 
 (defvar Man--last-section nil)
 
@@ -1771,7 +1777,8 @@ Returns t if section is found, nil otherwise."
           (prompt (concat "Go to section (default " default "): "))
           (chosen (completing-read prompt Man--sections
                                    nil nil nil nil default)))
-     (list chosen)))
+     (list chosen))
+   man-common)
   (setq Man--last-section section)
   (unless (Man-find-section section)
     (error "Section %s not found" section)))
@@ -1780,7 +1787,7 @@ Returns t if section is found, nil otherwise."
 (defun Man-goto-see-also-section ()
   "Move point to the \"SEE ALSO\" section.
 Actually the section moved to is described by `Man-see-also-regexp'."
-  (interactive)
+  (interactive nil man-common)
   (if (not (Man-find-section Man-see-also-regexp))
       (error "%s" (concat "No " Man-see-also-regexp
                     " section found in the current manpage"))))
@@ -1834,7 +1841,8 @@ Specify which REFERENCE to use; default is based on word 
at point."
             (prompt (concat "Refer to (default " default "): "))
             (chosen (completing-read prompt Man--refpages
                                      nil nil nil nil defaults)))
-        chosen))))
+        chosen)))
+   man-common)
   (if (not Man--refpages)
       (error "Can't find any references in the current manpage")
     (setq Man--last-refpage reference)
@@ -1843,7 +1851,7 @@ Specify which REFERENCE to use; default is based on word 
at point."
 
 (defun Man-kill ()
   "Kill the buffer containing the manpage."
-  (interactive)
+  (interactive nil man-common)
   (quit-window t))
 
 (defun Man-goto-page (page &optional noerror)
@@ -1854,7 +1862,8 @@ Specify which REFERENCE to use; default is based on word 
at point."
      (if (= (length Man-page-list) 1)
         (error "You're looking at the only manpage in the buffer")
        (list (read-minibuffer (format "Go to manpage [1-%d]: "
-                                     (length Man-page-list)))))))
+                                      (length Man-page-list))))))
+    man-common)
   (if (and (not Man-page-list) (not noerror))
       (error "Not a man page buffer"))
   (when Man-page-list
@@ -1876,7 +1885,7 @@ Specify which REFERENCE to use; default is based on word 
at point."
 
 (defun Man-next-manpage ()
   "Find the next manpage entry in the buffer."
-  (interactive)
+  (interactive nil man-common)
   (if (= (length Man-page-list) 1)
       (error "This is the only manpage in the buffer"))
   (if (< Man-current-page (length Man-page-list))
@@ -1887,7 +1896,7 @@ Specify which REFERENCE to use; default is based on word 
at point."
 
 (defun Man-previous-manpage ()
   "Find the previous manpage entry in the buffer."
-  (interactive)
+  (interactive nil man-common)
   (if (= (length Man-page-list) 1)
       (error "This is the only manpage in the buffer"))
   (if (> Man-current-page 1)
diff --git a/lisp/master.el b/lisp/master.el
index 796f218..3dcee50 100644
--- a/lisp/master.el
+++ b/lisp/master.el
@@ -1,4 +1,4 @@
-;;; master.el --- make a buffer the master over another buffer
+;;; master.el --- make a buffer the master over another buffer  -*- 
lexical-binding: t -*-
 
 ;; Copyright (C) 1999-2021 Free Software Foundation, Inc.
 
@@ -23,7 +23,7 @@
 
 ;;; Commentary:
 
-;; master-mode is a minor mode which enables you to scroll another
+;; `master-mode' is a minor mode which enables you to scroll another
 ;; buffer (the slave) without leaving your current buffer (the master).
 
 ;; It can be used by sql.el, for example: The SQL buffer is the master
@@ -47,17 +47,8 @@
 ;;
 ;; Rob Riepel <networking.stanford.edu>
 
-;;; History:
-;;
-
 ;;; Code:
 
-;; Unused.
-;;; (defgroup master nil
-;;;   "Support for master/slave relationships between buffers."
-;;;   :version "22.1"
-;;;   :group 'convenience)
-
 ;; Variables that don't need initialization.
 
 (defvar master-of nil
@@ -93,7 +84,7 @@ yourself the value of `master-of' by calling 
`master-show-slave'."
 ;; Initialize Master mode by setting a slave buffer.
 
 (defun master-set-slave (buffer)
-  "Makes BUFFER the slave of the current buffer.
+  "Make BUFFER the slave of the current buffer.
 Use \\[master-mode] to toggle control of the slave buffer."
   (interactive "bSlave: ")
   (setq-local master-of buffer)
diff --git a/lisp/mb-depth.el b/lisp/mb-depth.el
index f9a24e3..88003af 100644
--- a/lisp/mb-depth.el
+++ b/lisp/mb-depth.el
@@ -30,10 +30,17 @@
 
 ;;; Code:
 
-(defvar minibuffer-depth-indicator-function nil
-  "If non-nil, function to set up the minibuffer depth indicator.
-It is called with one argument, the minibuffer depth,
-and must return a string.")
+(defcustom minibuffer-depth-indicator-function nil
+  "If non-nil, a function to produce the minibuffer depth indicator.
+The function will be called with one argument, the minibuffer depth,
+and must return a string to display as indication of the minibuffer
+depth.
+If nil, display the depth as a number inside brackets, [NN], with
+the `minibuffer-depth-indicator' face."
+  :version "28.1"
+  :type '(choice (const :tag "Default indicator display, [NN]" nil)
+                 (function))
+  :group 'minibuffer)
 
 (defface minibuffer-depth-indicator '((t :inherit highlight))
   "Face to use for minibuffer depth indicator."
diff --git a/lisp/menu-bar.el b/lisp/menu-bar.el
index 133df65..e6cce59 100644
--- a/lisp/menu-bar.el
+++ b/lisp/menu-bar.el
@@ -604,7 +604,7 @@ Do the same for the keys of the same name."
   (define-key global-map [f20] 'clipboard-kill-region)
   (define-key global-map [f16] 'clipboard-kill-ring-save)
   (define-key global-map [f18] 'clipboard-yank)
-  ;; X11R6 versions:
+  ;; X11 versions:
   (define-key global-map [cut] 'clipboard-kill-region)
   (define-key global-map [copy] 'clipboard-kill-ring-save)
   (define-key global-map [paste] 'clipboard-yank))
diff --git a/lisp/mh-e/mh-acros.el b/lisp/mh-e/mh-acros.el
index af6f2f1..dd953ee 100644
--- a/lisp/mh-e/mh-acros.el
+++ b/lisp/mh-e/mh-acros.el
@@ -1,4 +1,4 @@
-;;; mh-acros.el --- macros used in MH-E
+;;; mh-acros.el --- macros used in MH-E  -*- lexical-binding: t; -*-
 
 ;; Copyright (C) 2004, 2006-2021 Free Software Foundation, Inc.
 
@@ -49,20 +49,19 @@
 ;;;###mh-autoload
 (defmacro mh-do-in-gnu-emacs (&rest body)
   "Execute BODY if in GNU Emacs."
-  (declare (debug t))
+  (declare (debug t) (indent defun))
   (unless (featurep 'xemacs) `(progn ,@body)))
-(put 'mh-do-in-gnu-emacs 'lisp-indent-hook 'defun)
 
 ;;;###mh-autoload
 (defmacro mh-do-in-xemacs (&rest body)
   "Execute BODY if in XEmacs."
-  (declare (debug t))
+  (declare (debug t) (indent defun))
   (when (featurep 'xemacs) `(progn ,@body)))
-(put 'mh-do-in-xemacs 'lisp-indent-hook 'defun)
 
 ;;;###mh-autoload
 (defmacro mh-funcall-if-exists (function &rest args)
   "Call FUNCTION with ARGS as parameters if it exists."
+  (declare (debug (symbolp body)))
   ;; FIXME: Not clear when this should be used.  If the function happens
   ;; not to exist at compile-time (e.g. because the corresponding package
   ;; wasn't loaded), then it won't ever be used :-(
@@ -75,25 +74,24 @@
   "Create function NAME.
 If FUNCTION exists, then NAME becomes an alias for FUNCTION.
 Otherwise, create function NAME with ARG-LIST and BODY."
+  (declare (indent defun) (doc-string 4)
+           (debug (&define name symbolp sexp def-body)))
   `(defalias ',name
      (if (fboundp ',function)
          ',function
        (lambda ,arg-list ,@body))))
-(put 'defun-mh 'lisp-indent-function 'defun)
-(put 'defun-mh 'doc-string-elt 4)
 
 ;;;###mh-autoload
 (defmacro defmacro-mh (name macro arg-list &rest body)
   "Create macro NAME.
 If MACRO exists, then NAME becomes an alias for MACRO.
 Otherwise, create macro NAME with ARG-LIST and BODY."
+  (declare (indent defun) (doc-string 4)
+           (debug (&define name symbolp sexp def-body)))
   (let ((defined-p (fboundp macro)))
     (if defined-p
         `(defalias ',name ',macro)
       `(defmacro ,name ,arg-list ,@body))))
-(put 'defmacro-mh 'lisp-indent-function 'defun)
-(put 'defmacro-mh 'doc-string-elt 4)
-
 
 
 ;;; Miscellaneous
@@ -127,7 +125,7 @@ Execute BODY, which can modify the folder buffer without 
having to
 worry about file locking or the read-only flag, and return its result.
 If SAVE-MODIFICATION-FLAG is non-nil, the buffer's modification flag
 is unchanged, otherwise it is cleared."
-  (declare (debug t))
+  (declare (debug t) (indent defun))
   (setq save-modification-flag (car save-modification-flag)) ; CL style
   `(prog1
        (let ((mh-folder-updating-mod-flag (buffer-modified-p))
@@ -139,14 +137,13 @@ is unchanged, otherwise it is cleared."
            (mh-set-folder-modified-p mh-folder-updating-mod-flag)))
      ,@(if (not save-modification-flag)
            '((mh-set-folder-modified-p nil)))))
-(put 'with-mh-folder-updating 'lisp-indent-hook 'defun)
 
 ;;;###mh-autoload
 (defmacro mh-in-show-buffer (show-buffer &rest body)
   "Format is (mh-in-show-buffer (SHOW-BUFFER) &body BODY).
 Display buffer SHOW-BUFFER in other window and execute BODY in it.
 Stronger than `save-excursion', weaker than `save-window-excursion'."
-  (declare (debug t))
+  (declare (debug t) (indent defun))
   (setq show-buffer (car show-buffer))  ; CL style
   `(let ((mh-in-show-buffer-saved-window (selected-window)))
      (switch-to-buffer-other-window ,show-buffer)
@@ -155,7 +152,6 @@ Stronger than `save-excursion', weaker than 
`save-window-excursion'."
          (progn
            ,@body)
        (select-window mh-in-show-buffer-saved-window))))
-(put 'mh-in-show-buffer 'lisp-indent-hook 'defun)
 
 ;;;###mh-autoload
 (defmacro mh-do-at-event-location (event &rest body)
@@ -163,7 +159,7 @@ Stronger than `save-excursion', weaker than 
`save-window-excursion'."
 After BODY has been executed return to original window.
 The modification flag of the buffer in the event window is
 preserved."
-  (declare (debug t))
+  (declare (debug t) (indent defun))
   (let ((event-window (make-symbol "event-window"))
         (event-position (make-symbol "event-position"))
         (original-window (make-symbol "original-window"))
@@ -190,7 +186,6 @@ preserved."
            (goto-char ,original-position)
            (set-marker ,original-position nil)
            (select-window ,original-window))))))
-(put 'mh-do-at-event-location 'lisp-indent-hook 'defun)
 
 
 
@@ -209,7 +204,7 @@ VAR is bound to the message on the current line as we loop
 starting from BEGIN till END.  In each step BODY is executed.
 
 If VAR is nil then the loop is executed without any binding."
-  (declare (debug (symbolp body)))
+  (declare (debug (symbolp body)) (indent defun))
   (unless (symbolp var)
     (error "Can not bind the non-symbol %s" var))
   (let ((binding-needed-flag var))
@@ -221,7 +216,6 @@ If VAR is nil then the loop is executed without any 
binding."
            (let ,(if binding-needed-flag `((,var (mh-get-msg-num t))) ())
              ,@body))
          (forward-line 1)))))
-(put 'mh-iterate-on-messages-in-region 'lisp-indent-hook 'defun)
 
 ;;;###mh-autoload
 (defmacro mh-iterate-on-range (var range &rest body)
@@ -235,7 +229,7 @@ a string.  In each iteration, BODY is executed.
 The parameter RANGE is usually created with
 `mh-interactive-range' in order to provide a uniform interface to
 MH-E functions."
-  (declare (debug (symbolp body)))
+  (declare (debug (symbolp body)) (indent defun))
   (unless (symbolp var)
     (error "Can not bind the non-symbol %s" var))
   (let ((binding-needed-flag var)
@@ -263,7 +257,6 @@ MH-E functions."
                   (when (gethash v ,seq-hash-table)
                     (let ,(if binding-needed-flag `((,var v)) ())
                       ,@body))))))))
-(put 'mh-iterate-on-range 'lisp-indent-hook 'defun)
 
 (defmacro mh-dlet* (binders &rest body)
   "Like `let*' but always dynamically scoped."
diff --git a/lisp/mh-e/mh-alias.el b/lisp/mh-e/mh-alias.el
index 012725c..67c019a 100644
--- a/lisp/mh-e/mh-alias.el
+++ b/lisp/mh-e/mh-alias.el
@@ -1,4 +1,4 @@
-;;; mh-alias.el --- MH-E mail alias completion and expansion
+;;; mh-alias.el --- MH-E mail alias completion and expansion  -*- 
lexical-binding: t; -*-
 
 ;; Copyright (C) 1994-1997, 2001-2021 Free Software Foundation, Inc.
 
@@ -42,8 +42,8 @@
   "Time aliases were last loaded.")
 (defvar mh-alias-read-address-map
   (let ((map (copy-keymap minibuffer-local-completion-map)))
-    (define-key map "," 'mh-alias-minibuffer-confirm-address)
-    (define-key map " " 'self-insert-command)
+    (define-key map "," #'mh-alias-minibuffer-confirm-address)
+    (define-key map " " #'self-insert-command)
     map))
 
 (defcustom mh-alias-system-aliases
@@ -270,9 +270,9 @@ Blind aliases or users from /etc/passwd are not expanded."
                   (t (split-string
                       (completing-read prompt mh-alias-alist nil nil) ",")))))
       (if (not mh-alias-expand-aliases-flag)
-          (mapconcat 'identity the-answer ", ")
+          (mapconcat #'identity the-answer ", ")
         ;; Loop over all elements, checking if in passwd alias or blind first
-        (mapconcat 'mh-alias-expand the-answer ",\n ")))))
+        (mapconcat #'mh-alias-expand the-answer ",\n ")))))
 
 ;;;###mh-autoload
 (defun mh-alias-minibuffer-confirm-address ()
@@ -427,10 +427,10 @@ contains it."
       (if (or (not alias)
               (string-equal alias (mh-alias-ali alias))) ;alias doesn't exist
           (completing-read "Alias file: "
-                           (mapcar 'list mh-alias-insert-file) nil t)
+                           (mapcar #'list mh-alias-insert-file) nil t)
         (or (mh-alias-which-file-has-alias alias mh-alias-insert-file)
             (completing-read "Alias file: "
-                             (mapcar 'list mh-alias-insert-file) nil t)))))
+                             (mapcar #'list mh-alias-insert-file) nil t)))))
    ((and mh-alias-insert-file (stringp mh-alias-insert-file))
     mh-alias-insert-file)
    (t
@@ -449,11 +449,10 @@ set `mh-alias-insert-file' or the \"Aliasfile:\" profile 
component"))
         (car autolist))
        ((or (not alias)
             (string-equal alias (mh-alias-ali alias))) ;alias doesn't exist
-        (completing-read "Alias file: " (mapcar 'list autolist) nil t))
+        (completing-read "Alias file: " autolist nil t))
        (t
         (or (mh-alias-which-file-has-alias alias autolist)
-            (completing-read "Alias file: "
-                             (mapcar 'list autolist) nil t))))))))
+            (completing-read "Alias file: " autolist nil t))))))))
 
 ;;;###mh-autoload
 (defun mh-alias-address-to-alias (address)
diff --git a/lisp/mh-e/mh-buffers.el b/lisp/mh-e/mh-buffers.el
index 55f74b6..a32f61c 100644
--- a/lisp/mh-e/mh-buffers.el
+++ b/lisp/mh-e/mh-buffers.el
@@ -1,4 +1,4 @@
-;;; mh-buffers.el --- MH-E buffer constants and utilities
+;;; mh-buffers.el --- MH-E buffer constants and utilities  -*- 
lexical-binding: t; -*-
 
 ;; Copyright (C) 1993, 1995, 1997, 2000-2021 Free Software Foundation,
 ;; Inc.
diff --git a/lisp/mh-e/mh-comp.el b/lisp/mh-e/mh-comp.el
index 0dedb7e..c1cd6c1 100644
--- a/lisp/mh-e/mh-comp.el
+++ b/lisp/mh-e/mh-comp.el
@@ -1,4 +1,4 @@
-;;; mh-comp.el --- MH-E functions for composing and sending messages
+;;; mh-comp.el --- MH-E functions for composing and sending messages  -*- 
lexical-binding: t; -*-
 
 ;; Copyright (C) 1993, 1995, 1997, 2000-2021 Free Software Foundation,
 ;; Inc.
@@ -719,12 +719,14 @@ message and scan line."
                (mh-insert-fields field value)))))
          (mh-components-to-list components-file))
         (delete-file components-file))
-      (mh-insert-fields "Resent-To:" (mapconcat 'identity (list to comp-to) ", 
")
-                        "Resent-Cc:" (mapconcat 'identity (list cc comp-cc) ", 
")
-                        "Resent-Fcc:" (mapconcat 'identity (list fcc
-                                                                 comp-fcc) ", 
")
-                        "Resent-Bcc:" (mapconcat 'identity (list bcc
-                                                                 comp-bcc) ", 
")
+      (mh-insert-fields "Resent-To:" (mapconcat #'identity (list to comp-to)
+                                                ", ")
+                        "Resent-Cc:" (mapconcat #'identity (list cc comp-cc)
+                                                ", ")
+                        "Resent-Fcc:" (mapconcat #'identity (list fcc comp-fcc)
+                                                 ", ")
+                        "Resent-Bcc:" (mapconcat #'identity (list bcc comp-bcc)
+                                                 ", ")
                         "Resent-From:" from)
       (save-buffer)
       (message "Redistributing...")
@@ -1096,7 +1098,7 @@ letter."
   (setq mode-line-buffer-identification (list "    {%b}"))
   (mh-logo-display)
   (mh-make-local-hook 'kill-buffer-hook)
-  (add-hook 'kill-buffer-hook 'mh-tidy-draft-buffer nil t)
+  (add-hook 'kill-buffer-hook #'mh-tidy-draft-buffer nil t)
   (run-hook-with-args 'mh-compose-letter-function to subject cc))
 
 (defun mh-insert-x-mailer ()
@@ -1165,7 +1167,7 @@ This should be the last function called when composing 
the draft."
 MSG can be a message number, a list of message numbers, or a sequence.
 The hook `mh-annotate-msg-hook' is run after annotating; see its
 documentation for variables it can use."
-  (apply 'mh-exec-cmd "anno" folder
+  (apply #'mh-exec-cmd "anno" folder
          (if (listp msg) (append msg args) (cons msg args)))
   (save-excursion
     (cond ((get-buffer folder)          ; Buffer may be deleted
diff --git a/lisp/mh-e/mh-compat.el b/lisp/mh-e/mh-compat.el
index 07bf03b..0363c5a 100644
--- a/lisp/mh-e/mh-compat.el
+++ b/lisp/mh-e/mh-compat.el
@@ -1,4 +1,4 @@
-;;; mh-compat.el --- make MH-E compatible with various versions of Emacs
+;;; mh-compat.el --- make MH-E compatible with various versions of Emacs  -*- 
lexical-binding: t; -*-
 
 ;; Copyright (C) 2006-2021 Free Software Foundation, Inc.
 
@@ -42,7 +42,7 @@
 (eval-when-compile (require 'mh-acros))
 
 (mh-do-in-gnu-emacs
-  (defalias 'mh-require 'require))
+  (defalias 'mh-require #'require))
 
 (mh-do-in-xemacs
   (defun mh-require (feature &optional filename noerror)
@@ -83,6 +83,7 @@ This is an analogue of a dynamically scoped `let' that 
operates on
 the function cell of FUNCs rather than their value cell.
 
 \(fn ((FUNC ARGLIST BODY...) ...) FORM...)"
+  (declare (indent 1) (debug ((&rest (sexp sexp &rest form)) &rest form)))
   (if (fboundp 'cl-letf)
       `(cl-letf ,(mapcar (lambda (binding)
                            `((symbol-function ',(car binding))
@@ -90,9 +91,6 @@ the function cell of FUNCs rather than their value cell.
                          bindings)
          ,@body)
     `(flet ,bindings ,@body)))
-(put 'mh-flet 'lisp-indent-function 1)
-(put 'mh-flet 'edebug-form-spec
-     '((&rest (sexp sexp &rest form)) &rest form))
 
 (defun mh-display-color-cells (&optional display)
   "Return the number of color cells supported by DISPLAY.
diff --git a/lisp/mh-e/mh-e.el b/lisp/mh-e/mh-e.el
index 2eb7fba..1aac337 100644
--- a/lisp/mh-e/mh-e.el
+++ b/lisp/mh-e/mh-e.el
@@ -1,4 +1,4 @@
-;;; mh-e.el --- GNU Emacs interface to the MH mail system
+;;; mh-e.el --- GNU Emacs interface to the MH mail system  -*- 
lexical-binding: t; -*-
 
 ;; Copyright (C) 1985-1988, 1990, 1992-1995, 1997, 1999-2021 Free
 ;; Software Foundation, Inc.
@@ -522,7 +522,7 @@ parsed by MH-E."
     (let* ((initial-size (mh-truncate-log-buffer))
            (start (point))
            (args (mh-list-to-string args)))
-      (apply 'call-process (expand-file-name command mh-progs) nil t nil args)
+      (apply #'call-process (expand-file-name command mh-progs) nil t nil args)
       (when (> (buffer-size) initial-size)
         (save-excursion
           (goto-char start)
@@ -560,7 +560,7 @@ ARGS are passed to COMMAND as command line arguments."
   (with-current-buffer (get-buffer-create mh-log-buffer)
     (mh-truncate-log-buffer))
   (let* ((process-connection-type nil)
-         (process (apply 'start-process
+         (process (apply #'start-process
                          command nil
                          (expand-file-name command mh-progs)
                          (mh-list-to-string args))))
@@ -602,7 +602,7 @@ RAISE-ERROR is non-nil, in which case an error is signaled 
if
   (set-buffer (get-buffer-create mh-temp-buffer))
   (erase-buffer)
   (let ((value
-         (apply 'call-process
+         (apply #'call-process
                 (expand-file-name command mh-progs) nil t nil
                 args)))
     (goto-char (point-min))
@@ -616,7 +616,7 @@ Put the output into buffer after point.
 Set mark after inserted text.
 Output is expected to be shown to user, not parsed by MH-E."
   (push-mark (point) t)
-  (apply 'call-process
+  (apply #'call-process
          (expand-file-name command mh-progs) nil t display
          (mh-list-to-string args))
 
@@ -650,7 +650,7 @@ preserves whether the mark is active or not."
   "Execute MH library command COMMAND with ARGS.
 Put the output into buffer after point.
 Set mark after inserted text."
-  (apply 'mh-exec-cmd-output (expand-file-name command mh-lib-progs) nil args))
+  (apply #'mh-exec-cmd-output (expand-file-name command mh-lib-progs) nil 
args))
 
 (defun mh-handle-process-error (command status)
   "Raise error if COMMAND returned non-zero STATUS, otherwise return STATUS."
@@ -695,9 +695,8 @@ See documentation for `defgroup' for a description of the 
arguments
 SYMBOL, MEMBERS, DOC and ARGS.
 This macro is used by Emacs versions that lack the :package-version
 keyword, introduced in Emacs 22."
-  (declare (doc-string 3))
+  (declare (doc-string 3) (indent defun))
   `(defgroup ,symbol ,members ,doc ,@(mh-strip-package-version args)))
-(put 'defgroup-mh 'lisp-indent-function 'defun)
 
 (defmacro defcustom-mh (symbol value doc &rest args)
   "Declare SYMBOL as a customizable variable that defaults to VALUE.
@@ -705,9 +704,8 @@ See documentation for `defcustom' for a description of the 
arguments
 SYMBOL, VALUE, DOC and ARGS.
 This macro is used by Emacs versions that lack the :package-version
 keyword, introduced in Emacs 22."
-  (declare (doc-string 3))
+  (declare (doc-string 3) (indent defun))
   `(defcustom ,symbol ,value ,doc ,@(mh-strip-package-version args)))
-(put 'defcustom-mh 'lisp-indent-function 'defun)
 
 (defmacro defface-mh (face spec doc &rest args)
   "Declare FACE as a customizable face that defaults to SPEC.
@@ -715,9 +713,8 @@ See documentation for `defface' for a description of the 
arguments
 FACE, SPEC, DOC and ARGS.
 This macro is used by Emacs versions that lack the :package-version
 keyword, introduced in Emacs 22."
-  (declare (doc-string 3))
+  (declare (doc-string 3) (indent defun))
   `(defface ,face ,spec ,doc ,@(mh-strip-package-version args)))
-(put 'defface-mh 'lisp-indent-function 'defun)
 
 
 
@@ -977,7 +974,7 @@ necessary and can actually cause problems."
   :set (lambda (symbol value)
          (set-default symbol value)     ;Done in mh-variant-set-variant!
          (mh-variant-set value))
-  :initialize 'custom-initialize-default
+  :initialize #'custom-initialize-default
   :group 'mh-e
   :package-version '(MH-E . "8.0"))
 
@@ -1551,7 +1548,7 @@ as the result is undefined."
                                  '(radio)
                                  (mapcar
                                   (lambda (arg) `(const ,arg))
-                                  (mapcar 'car mh-identity-list))))
+                                  (mapcar #'car mh-identity-list))))
                          (cons :tag "Fcc Field"
                                (const "fcc")
                                (string :tag "Value"))
@@ -1578,7 +1575,7 @@ See `mh-identity-list'."
          '(radio)
          (cons '(const :tag "None" nil)
                (mapcar (lambda (arg) `(const ,arg))
-                       (mapcar 'car mh-identity-list))))
+                       (mapcar #'car mh-identity-list))))
   :group 'mh-identity
   :package-version '(MH-E . "7.1"))
 
@@ -1747,7 +1744,7 @@ bogofilter, then you can set this option to 
\"Bogofilter\"."
                  (const :tag "SpamAssassin" spamassassin)
                  (const :tag "Bogofilter" bogofilter)
                  (const :tag "SpamProbe" spamprobe))
-  :set 'mh-junk-choose
+  :set #'mh-junk-choose
   :group 'mh-junk
   :package-version '(MH-E . "7.3"))
 
@@ -1910,7 +1907,7 @@ white image, can be generated using the \"compface\" 
command (see URL
 `ftp://ftp.cs.indiana.edu/pub/faces/compface/compface.tar.Z'). The
 \"Online X-Face Converter\" is a useful resource for quick conversion
 of images into \"X-Face:\" header fields (see URL
-`http://www.dairiki.org/xface/').
+`https://www.dairiki.org/xface/').
 
 Use the \"make-face\" script to convert a JPEG image to the higher
 resolution, color, \"Face:\" header field (see URL
@@ -2008,7 +2005,7 @@ call `mh-set-cmd-note' with the width specified by your 
format file
 you would use \"(mh-set-cmd-note 4)\"."
   :type 'boolean
   :group 'mh-scan-line-formats
-  :set 'mh-adaptive-cmd-note-flag-check
+  :set #'mh-adaptive-cmd-note-flag-check
   :package-version '(MH-E . "7.0"))
 
 (defun mh-scan-format-file-check (symbol value)
@@ -2047,7 +2044,7 @@ Emacs start with 0)."
                  (const :tag "Use Default scan Format" nil)
                  (file  :tag "Specify a scan Format File"))
   :group 'mh-scan-line-formats
-  :set 'mh-scan-format-file-check
+  :set #'mh-scan-format-file-check
   :package-version '(MH-E . "6.0"))
 
 (defun mh-adaptive-cmd-note-flag-check (symbol value)
@@ -2469,9 +2466,9 @@ of citations entirely, choose \"None\"."
     "Disposition-Notification-Options:" ; RFC 2298
     "Disposition-Notification-To:"      ; RFC 2298
     "Distribution:"                     ; RFC 1036
-    "DKIM-"                             ; http://antispam.yahoo.com/domainkeys
+    "DKIM-"                             ; 
https://en.wikipedia.org/wiki/DomainKeys_Identified_Mail
     "DL-Expansion-History:"             ; RFC 2156
-    "DomainKey-"                        ; http://antispam.yahoo.com/domainkeys
+    "DomainKey-"                        ; 
https://en.wikipedia.org/wiki/DomainKeys_Identified_Mail
     "DomainKey-Signature:"
     "Encoding:"                         ; RFC 1505
     "Envelope-to:"
@@ -2558,7 +2555,7 @@ of citations entirely, choose \"None\"."
     "X-Abuse-Info:"
     "X-Accept-Language:"                ; Netscape/Mozilla
     "X-Ack:"
-    "X-ACL-Warn:"                      ; http://www.exim.org
+    "X-ACL-Warn:"                      ; https://www.exim.org
     "X-Admin:"                          ; 
https://people.dsv.su.se/~jpalme/ietf/mail-headers/
     "X-Administrivia-To:"
     "X-AMAZON"                          ; Amazon.com
@@ -2582,8 +2579,8 @@ of citations entirely, choose \"None\"."
     "X-BFI:"
     "X-Bigfish:"
     "X-Bogosity:"                       ; bogofilter
-    "X-BPS1:"                          ; http://www.boggletools.com
-    "X-BPS2:"                          ; http://www.boggletools.com
+    "X-BPS1:"                          ; http://www.boggletools.com [dead 
link?]
+    "X-BPS2:"                          ; http://www.boggletools.com [dead 
link?]
     "X-Brightmail-Tracker:"             ; Brightmail
     "X-BrightmailFiltered:"             ; Brightmail
     "X-Bugzilla-"                       ; Bugzilla
@@ -2599,12 +2596,12 @@ of citations entirely, choose \"None\"."
     "X-Confirm-Reading-To:"             ; 
https://people.dsv.su.se/~jpalme/ietf/mail-headers/
     "X-Content-Filtered-By:"
     "X-ContentStamp:"                   ; NetZero
-    "X-Country-Chain:"                  ; http://www.declude.com/x-note.htm
+    "X-Country-Chain:"                  ; http://www.declude.com/x-note.htm 
[dead link?]
     "X-Cr-Hashedpuzzle:"
     "X-Cr-Puzzleid:"
     "X-Cron-Env:"
     "X-DCC-"                            ; SpamAssassin
-    "X-Declude-"                        ; http://www.declude.com/x-note.htm
+    "X-Declude-"                        ; http://www.declude.com/x-note.htm 
[dead link?]
     "X-Dedicated:"
     "X-Delivered"
     "X-Destination-ID:"
@@ -2619,7 +2616,7 @@ of citations entirely, choose \"None\"."
     "X-EID:"
     "X-ELNK-Trace:"                     ; Earthlink mailer
     "X-EM-"                            ; Some ecommerce software
-    "X-Email-Type-Id:"                 ; Paypal http://www.paypal.com
+    "X-Email-Type-Id:"                 ; Paypal https://www.paypal.com
     "X-Enigmail-Version:"
     "X-Envelope-Date:"                  ; GNU mailutils
     "X-Envelope-From:"                  ; 
https://people.dsv.su.se/~jpalme/ietf/mail-headers/
@@ -2635,21 +2632,21 @@ of citations entirely, choose \"None\"."
     "X-Folder:"                         ; Spam
     "X-Forwarded-"                      ; Google+
     "X-From-Line"
-    "X-FuHaFi:"                                ; http://www.gmx.net/
+    "X-FuHaFi:"                                ; https://www.gmx.net/
     "X-Generated-By:"                   ; launchpad.net
     "X-Gmail-"                          ; Gmail
     "X-Gnus-Mail-Source:"               ; gnus
     "X-Google-"                         ; Google mail
     "X-Google-Sender-Auth:"
     "X-Greylist:"                       ; milter-greylist-1.2.1
-    "X-Habeas-"                                ; http://www.returnpath.net
+    "X-Habeas-"                                ; https://www.returnpath.net
     "X-Hashcash:"                       ; hashcash
     "X-Headers-End:"                    ; SpamCop
     "X-HPL-"
     "X-HR-"
     "X-HTTP-UserAgent:"
     "X-Hz"                             ; Hertz
-    "X-Identity:"                       ; http://www.declude.com/x-note.htm
+    "X-Identity:"                       ; http://www.declude.com/x-note.htm 
[dead link?]
     "X-IEEE-UCE-"                       ; IEEE spam filter
     "X-Image-URL:"
     "X-IMAP:"                           ; 
https://people.dsv.su.se/~jpalme/ietf/mail-headers/
@@ -2670,7 +2667,7 @@ of citations entirely, choose \"None\"."
     "X-Loop:"                           ; 
https://people.dsv.su.se/~jpalme/ietf/mail-headers/
     "X-Lrde-Mailscanner:"
     "X-Lumos-SenderID:"                 ; Roving ConstantContact
-    "X-mail_abuse_inquiries:"          ; http://www.salesforce.com
+    "X-mail_abuse_inquiries:"          ; https://www.salesforce.com
     "X-Mail-from:"                      ; fastmail.fm
     "X-MAIL-INFO:"                      ; NetZero
     "X-Mailer_"
@@ -2683,11 +2680,11 @@ of citations entirely, choose \"None\"."
     "X-Mailutils-Message-Id"            ; GNU Mailutils
     "X-Majordomo:"                      ; Majordomo mailing list manager
     "X-Match:"
-    "X-MaxCode-Template:"              ; Paypal http://www.paypal.com
+    "X-MaxCode-Template:"              ; Paypal https://www.paypal.com
     "X-MB-Message-"                     ; AOL WebMail
     "X-MDaemon-Deliver-To:"
     "X-MDRemoteIP:"
-    "X-ME-Bayesian:"                   ; 
http://www.newmediadevelopment.net/page.cfm/parent/Client-Area/content/Managing-spam/
+    "X-ME-Bayesian:"                   ; 
https://www.newmediadevelopment.net/page.cfm/parent/Client-Area/content/Managing-spam/
     "X-Message-Id"
     "X-Message-Type:"
     "X-MessageWall-Score:"              ; Unknown mailing list manager, AUC TeX
@@ -2758,7 +2755,7 @@ of citations entirely, choose \"None\"."
     "X-Server-Date:"
     "X-Server-Uuid:"
     "X-Service-Code:"
-    "X-SFDC-"                          ; http://www.salesforce.com
+    "X-SFDC-"                          ; https://www.salesforce.com
     "X-Sieve:"                          ; Sieve filtering
     "X-SMFBL:"
     "X-SMHeaderMap:"
@@ -2773,7 +2770,7 @@ of citations entirely, choose \"None\"."
     "X-Submissions-To:"
     "X-Sun-Charset:"
     "X-Telecom-Digest"
-    "X-TM-IMSS-Message-ID:"            ; http://www.trendmicro.com
+    "X-TM-IMSS-Message-ID:"            ; https://www.trendmicro.com
     "X-Trace:"
     "X-UID"
     "X-UIDL:"                           ; 
https://people.dsv.su.se/~jpalme/ietf/mail-headers/
@@ -2793,10 +2790,10 @@ of citations entirely, choose \"None\"."
     "X-WebTV-Signature:"
     "X-Wss-Id:"                         ; Worldtalk gateways
     "X-X-Sender:"                       ; 
https://people.dsv.su.se/~jpalme/ietf/mail-headers/
-    "X-XPT-XSL-Name:"                  ; Paypal http://www.paypal.com
+    "X-XPT-XSL-Name:"                  ; Paypal https://www.paypal.com
     "X-xsi-"
-    "X-XWALL-"                         ; 
http://www.dataenter.co.at/doc/xwall_undocumented_config.htm
-    "X-Y-GMX-Trusted:"                 ; http://www.gmx.net/
+    "X-XWALL-"                         ; 
https://www.dataenter.co.at/doc/xwall_undocumented_config.htm
+    "X-Y-GMX-Trusted:"                 ; https://www.gmx.net/
     "X-Yahoo"
     "X-Yahoo-Newman-"
     "X-YMail-"
@@ -3042,7 +3039,7 @@ XEmacs. For more information, see URL
 `ftp://ftp.cs.indiana.edu/pub/faces/compface/compface.tar.z'). Recent
 versions of XEmacs have internal support for \"X-Face:\" images. If
 your version of XEmacs does not, then you'll need both \"uncompface\"
-and the x-face package (see URL `http://www.jpl.org/ftp/pub/elisp/').
+and the x-face package (see URL `https://www.jpl.org/ftp/pub/elisp/').
 
 Finally, MH-E will display images referenced by the \"X-Image-URL:\"
 header field if neither the \"Face:\" nor the \"X-Face:\" fields are
diff --git a/lisp/mh-e/mh-folder.el b/lisp/mh-e/mh-folder.el
index 555d13d..2e28806 100644
--- a/lisp/mh-e/mh-folder.el
+++ b/lisp/mh-e/mh-folder.el
@@ -1,4 +1,4 @@
-;;; mh-folder.el --- MH-Folder mode
+;;; mh-folder.el --- MH-Folder mode  -*- lexical-binding: t; -*-
 
 ;; Copyright (C) 2002-2003, 2005-2021 Free Software Foundation, Inc.
 
@@ -209,10 +209,10 @@ annotation.")
 
 ;; Use defalias to make sure the documented primary key bindings
 ;; appear in menu lists.
-(defalias 'mh-alt-show 'mh-show)
-(defalias 'mh-alt-refile-msg 'mh-refile-msg)
-(defalias 'mh-alt-send 'mh-send)
-(defalias 'mh-alt-visit-folder 'mh-visit-folder)
+(defalias 'mh-alt-show #'mh-show)
+(defalias 'mh-alt-refile-msg #'mh-refile-msg)
+(defalias 'mh-alt-send #'mh-send)
+(defalias 'mh-alt-visit-folder #'mh-visit-folder)
 
 ;; Save the "b" binding for a future `back'. Maybe?
 (gnus-define-keys  mh-folder-mode-map
@@ -650,11 +650,11 @@ perform the operation on all messages in that region.
   (auto-save-mode -1)
   (setq buffer-offer-save t)
   (mh-make-local-hook (mh-write-file-functions))
-  (add-hook (mh-write-file-functions) 'mh-execute-commands nil t)
+  (add-hook (mh-write-file-functions) #'mh-execute-commands nil t)
   (make-local-variable 'revert-buffer-function)
   (make-local-variable 'hl-line-mode)   ; avoid pollution
   (mh-funcall-if-exists hl-line-mode 1)
-  (setq revert-buffer-function 'mh-undo-folder)
+  (setq revert-buffer-function #'mh-undo-folder)
   (add-to-list 'minor-mode-alist '(mh-showing-mode " Show"))
   (mh-do-in-xemacs
     (easy-menu-add mh-folder-sequence-menu)
@@ -1117,7 +1117,7 @@ called interactively."
          (message "Destination folder: %s" (cdr mh-last-destination)))
         (t
          (mh-iterate-on-range msg range
-           (apply 'mh-write-msg-to-file msg (cdr mh-last-destination)))
+           (apply #'mh-write-msg-to-file msg (cdr mh-last-destination)))
          (mh-next-msg interactive-flag))))
 
 ;;;###mh-autoload
@@ -1606,7 +1606,7 @@ after the commands are processed."
       ;; Now delete messages
       (cond (mh-delete-list
              (setq redraw-needed-flag t)
-             (apply 'mh-exec-cmd "rmm" folder
+             (apply #'mh-exec-cmd "rmm" folder
                     (mh-coalesce-msg-list mh-delete-list))
              (mh-delete-scan-msgs mh-delete-list)
              (setq mh-delete-list nil)))
@@ -1620,8 +1620,8 @@ after the commands are processed."
           ;; (mh-refile-a-msg nil (intern dest))
           ;; (mh-delete-a-msg nil)))
           (if (null dest)
-              (apply 'mh-exec-cmd "rmm" folder msg-list)
-            (apply 'mh-exec-cmd "refile" "-src" folder dest msg-list)
+              (apply #'mh-exec-cmd "rmm" folder msg-list)
+            (apply #'mh-exec-cmd "refile" "-src" folder dest msg-list)
             (push dest folders-changed))
           (setq redraw-needed-flag t)
           (mh-delete-scan-msgs mh-blacklist)
@@ -1703,7 +1703,7 @@ after the commands are processed."
       (mh-recenter nil)))
 
 ;;;###mh-autoload
-(defun mh-make-folder-mode-line (&optional ignored)
+(defun mh-make-folder-mode-line (&optional _ignored)
   "Set the fields of the mode line for a folder buffer.
 The optional argument is now obsolete and IGNORED. It used to be
 used to pass in what is now stored in the buffer-local variable
diff --git a/lisp/mh-e/mh-funcs.el b/lisp/mh-e/mh-funcs.el
index 309bcb4..38ba431 100644
--- a/lisp/mh-e/mh-funcs.el
+++ b/lisp/mh-e/mh-funcs.el
@@ -1,4 +1,4 @@
-;;; mh-funcs.el --- MH-E functions not everyone will use right away
+;;; mh-funcs.el --- MH-E functions not everyone will use right away  -*- 
lexical-binding: t; -*-
 
 ;; Copyright (C) 1993, 1995, 2001-2021 Free Software Foundation, Inc.
 
@@ -348,7 +348,7 @@ See `mh-store-msg' for a description of DIRECTORY."
         (error "Error occurred during execution of %s" command)))))
 
 ;;;###mh-autoload
-(defun mh-undo-folder (&rest ignored)
+(defun mh-undo-folder (&rest _ignored)
   "Undo all refiles and deletes in the current folder.
 Arguments are IGNORED (for `revert-buffer')."
   (interactive)
diff --git a/lisp/mh-e/mh-gnus.el b/lisp/mh-e/mh-gnus.el
index 6a98516..ac46cc6 100644
--- a/lisp/mh-e/mh-gnus.el
+++ b/lisp/mh-e/mh-gnus.el
@@ -1,4 +1,4 @@
-;;; mh-gnus.el --- make MH-E compatible with various versions of Gnus
+;;; mh-gnus.el --- make MH-E compatible with various versions of Gnus  -*- 
lexical-binding: t; -*-
 
 ;; Copyright (C) 2003-2004, 2006-2021 Free Software Foundation, Inc.
 
@@ -129,7 +129,7 @@
   (unless default
     (setq default (mml-content-disposition type filename)))
   (let ((disposition (completing-read
-                     (format "Disposition (default %s): " default)
+                     (format-prompt "Disposition" default)
                      '(("attachment") ("inline") (""))
                      nil t nil nil default)))
     (if (not (equal disposition ""))
diff --git a/lisp/mh-e/mh-identity.el b/lisp/mh-e/mh-identity.el
index 1844399..aeab049 100644
--- a/lisp/mh-e/mh-identity.el
+++ b/lisp/mh-e/mh-identity.el
@@ -1,4 +1,4 @@
-;;; mh-identity.el --- multiple identify support for MH-E
+;;; mh-identity.el --- multiple identify support for MH-E  -*- 
lexical-binding: t; -*-
 
 ;; Copyright (C) 2002-2021 Free Software Foundation, Inc.
 
@@ -50,7 +50,7 @@ This is normally set as part of an Identity in
 (defvar mh-identity-menu nil
   "The Identity menu.")
 
-(defalias 'mh-identity-make-menu-no-autoload 'mh-identity-make-menu)
+(defalias 'mh-identity-make-menu-no-autoload #'mh-identity-make-menu)
 
 ;;;###mh-autoload
 (defun mh-identity-make-menu ()
@@ -74,7 +74,7 @@ See `mh-identity-add-menu'."
      (mapcar (lambda (arg)
                `[,arg  (mh-insert-identity ,arg) :style radio
                        :selected (equal mh-identity-local ,arg)])
-             (mapcar 'car mh-identity-list))
+             (mapcar #'car mh-identity-list))
      '(["None"
         (mh-insert-identity "None") :style radio
         :selected (not mh-identity-local)]
@@ -142,7 +142,7 @@ See `mh-identity-list'."
           (completing-read
            "Identity: "
            (cons '("None")
-                 (mapcar 'list (mapcar 'car mh-identity-list)))
+                 (mapcar #'list (mapcar #'car mh-identity-list)))
            nil t default nil default))
     (if (eq identity "None")
         nil
@@ -171,8 +171,8 @@ See `mh-identity-list'."
           "Identity: "
           (if mh-identity-local
               (cons '("None")
-                    (mapcar 'list (mapcar 'car mh-identity-list)))
-            (mapcar 'list (mapcar 'car mh-identity-list)))
+                    (mapcar #'list (mapcar #'car mh-identity-list)))
+            (mapcar #'list (mapcar #'car mh-identity-list)))
           nil t)
          nil))
 
diff --git a/lisp/mh-e/mh-inc.el b/lisp/mh-e/mh-inc.el
index 32f7317..6a29195 100644
--- a/lisp/mh-e/mh-inc.el
+++ b/lisp/mh-e/mh-inc.el
@@ -1,4 +1,4 @@
-;;; mh-inc.el --- MH-E "inc" and separate mail spool handling
+;;; mh-inc.el --- MH-E "inc" and separate mail spool handling  -*- 
lexical-binding: t; -*-
 
 ;; Copyright (C) 2003-2004, 2006-2021 Free Software Foundation, Inc.
 
@@ -58,19 +58,15 @@
                     (mh-inc-spool-generator folder spool)
                     (mh-inc-spool-def-key key folder))))))
 
-(defalias 'mh-inc-spool-make-no-autoload 'mh-inc-spool-make)
+(defalias 'mh-inc-spool-make-no-autoload #'mh-inc-spool-make)
 
 (defun mh-inc-spool-generator (folder spool)
   "Create a command to inc into FOLDER from SPOOL file."
-  (let ((folder1 (make-symbol "folder"))
-        (spool1 (make-symbol "spool")))
-    (set folder1 folder)
-    (set spool1 spool)
-    (setf (symbol-function (intern (concat "mh-inc-spool-" folder)))
-          `(lambda ()
-             ,(format "Inc spool file %s into folder %s." spool folder)
-             (interactive)
-             (mh-inc-folder ,spool1 (concat "+" ,folder1))))))
+  (defalias (symbol-function (intern (concat "mh-inc-spool-" folder)))
+    (lambda ()
+      (:documentation (format "Inc spool file %s into folder %s." spool 
folder))
+      (interactive)
+      (mh-inc-folder spool (concat "+" folder)))))
 
 (defun mh-inc-spool-def-key (key folder)
   "Define a KEY in `mh-inc-spool-map' to inc FOLDER and collect help string."
diff --git a/lisp/mh-e/mh-junk.el b/lisp/mh-e/mh-junk.el
index b49c632..5a40794 100644
--- a/lisp/mh-e/mh-junk.el
+++ b/lisp/mh-e/mh-junk.el
@@ -1,4 +1,4 @@
-;;; mh-junk.el --- MH-E interface to anti-spam measures
+;;; mh-junk.el --- MH-E interface to anti-spam measures  -*- lexical-binding: 
t; -*-
 
 ;; Copyright (C) 2003-2021 Free Software Foundation, Inc.
 
diff --git a/lisp/mh-e/mh-letter.el b/lisp/mh-e/mh-letter.el
index f5ad73d..5979018 100644
--- a/lisp/mh-e/mh-letter.el
+++ b/lisp/mh-e/mh-letter.el
@@ -1,4 +1,4 @@
-;;; mh-letter.el --- MH-Letter mode
+;;; mh-letter.el --- MH-Letter mode  -*- lexical-binding: t; -*-
 
 ;; Copyright (C) 1993, 1995, 1997, 2000-2021 Free Software Foundation,
 ;; Inc.
@@ -334,15 +334,15 @@ order).
   ;; Maybe we want to use the existing Mail menu from mail-mode in
   ;; 9.0; in the mean time, let's remove it since the redundancy will
   ;; only produce confusion.
-  (define-key mh-letter-mode-map [menu-bar mail] 'undefined)
+  (define-key mh-letter-mode-map [menu-bar mail] #'undefined)
   (mh-do-in-xemacs (easy-menu-remove mail-menubar-menu))
   (setq fill-column mh-letter-fill-column)
   (add-hook 'completion-at-point-functions
-            'mh-letter-completion-at-point nil 'local)
+            #'mh-letter-completion-at-point nil 'local)
   ;; If text-mode-hook turned on auto-fill, tune it for messages
   (when auto-fill-function
     (make-local-variable 'auto-fill-function)
-    (setq auto-fill-function 'mh-auto-fill-for-letter)))
+    (setq auto-fill-function #'mh-auto-fill-for-letter)))
 
 
 
@@ -390,10 +390,7 @@ This command leaves the mark before the letter and point 
after it."
                 (or mh-sent-from-msg (nth 0 (mh-translate-range folder "cur")))
               (nth 0 (mh-translate-range folder "cur"))))
           (message
-           (read-string (concat "Message number"
-                                (or (and default
-                                         (format " (default %d): " default))
-                                    ": "))
+           (read-string (format-prompt "Message number" default)
                         nil nil
                         (if (numberp default)
                             (int-to-string default)
@@ -851,7 +848,7 @@ body."
              (forward-line)))))
 
 ;;;###mh-autoload
-(defun mh-position-on-field (field &optional ignored)
+(defun mh-position-on-field (field &optional _ignored)
   "Move to the end of the FIELD in the header.
 Move to end of entire header if FIELD not found.
 Returns non-nil if FIELD was found.
diff --git a/lisp/mh-e/mh-limit.el b/lisp/mh-e/mh-limit.el
index 036522f..08f1b40 100644
--- a/lisp/mh-e/mh-limit.el
+++ b/lisp/mh-e/mh-limit.el
@@ -1,4 +1,4 @@
-;;; mh-limit.el --- MH-E display limits
+;;; mh-limit.el --- MH-E display limits  -*- lexical-binding: t; -*-
 
 ;; Copyright (C) 2001-2003, 2006-2021 Free Software Foundation, Inc.
 
@@ -237,7 +237,7 @@ Return number of messages put in the sequence:
               (setq list (cons (mh-get-msg-num t) list)))
           (if (assoc 'subject mh-seq-list) (mh-delete-seq 'subject))
           ;; sort the result into a sequence
-          (let ((sorted-list (sort (copy-sequence list) 'mh-lessp)))
+          (let ((sorted-list (sort (copy-sequence list) #'mh-lessp)))
             (while sorted-list
               (mh-add-msgs-to-seq (car sorted-list) 'subject nil)
               (setq sorted-list (cdr sorted-list)))
diff --git a/lisp/mh-e/mh-mime.el b/lisp/mh-e/mh-mime.el
index 70df9e6..fec2293 100644
--- a/lisp/mh-e/mh-mime.el
+++ b/lisp/mh-e/mh-mime.el
@@ -1,4 +1,4 @@
-;;; mh-mime.el --- MH-E MIME support
+;;; mh-mime.el --- MH-E MIME support  -*- lexical-binding: t; -*-
 
 ;; Copyright (C) 1993, 1995, 2001-2021 Free Software Foundation, Inc.
 
@@ -190,9 +190,9 @@ Set from last use.")
       ;; XEmacs doesn't care.
       (set-keymap-parent map mh-show-mode-map))
     (mh-do-in-gnu-emacs
-     (define-key map [mouse-2] 'mh-push-button))
+     (define-key map [mouse-2] #'mh-push-button))
     (mh-do-in-xemacs
-     (define-key map '(button2) 'mh-push-button))
+     (define-key map '(button2) #'mh-push-button))
     (dolist (c mh-mime-button-commands)
       (define-key map (cadr c) (car c)))
     map))
@@ -214,11 +214,11 @@ Set from last use.")
   (let ((map (make-sparse-keymap)))
     (unless (>= (string-to-number emacs-version) 21)
       (set-keymap-parent map mh-show-mode-map))
-    (define-key map "\r" 'mh-press-button)
+    (define-key map "\r" #'mh-press-button)
     (mh-do-in-gnu-emacs
-     (define-key map [mouse-2] 'mh-push-button))
+     (define-key map [mouse-2] #'mh-push-button))
     (mh-do-in-xemacs
-     (define-key map '(button2) 'mh-push-button))
+     (define-key map '(button2) #'mh-push-button))
     map))
 
 
@@ -259,9 +259,7 @@ usually reads the file \"/etc/mailcap\"."
               (methods (mapcar (lambda (x) (list (cdr (assoc 'viewer x))))
                                (mailcap-mime-info type 'all)))
               (def (caar methods))
-              (prompt (format "Viewer%s: " (if def
-                                               (format " (default %s)" def)
-                                             "")))
+              (prompt (format-prompt "Viewer" def))
               (method (completing-read prompt methods nil nil nil nil def))
               (folder mh-show-folder-buffer)
               (buffer-read-only nil))
@@ -395,9 +393,9 @@ do the work."
           ((and (or prompt
                     (equal t mh-mime-save-parts-default-directory))
                 mh-mime-save-parts-directory)
-           (read-directory-name (format
-                            "Store in directory (default %s): "
-                            mh-mime-save-parts-directory)
+           (read-directory-name (format-prompt
+                                 "Store in directory"
+                                 mh-mime-save-parts-directory)
                            "" mh-mime-save-parts-directory t ""))
           ((stringp mh-mime-save-parts-default-directory)
            mh-mime-save-parts-default-directory)
@@ -413,7 +411,7 @@ do the work."
         (cd directory)
         (setq mh-mime-save-parts-directory directory)
         (let ((initial-size (mh-truncate-log-buffer)))
-          (apply 'call-process
+          (apply #'call-process
                  (expand-file-name command mh-progs) nil t nil
                  (mh-list-to-string (list folder msg "-auto"
                                           (if (not (mh-variant-p 'nmh))
@@ -452,7 +450,7 @@ decoding the same message multiple times."
   (let ((b (point))
         (clean-message-header mh-clean-message-header-flag)
         (invisible-headers mh-invisible-header-fields-compiled)
-        (visible-headers nil))
+        ) ;; (visible-headers nil)
     (save-excursion
       (save-restriction
         (narrow-to-region b b)
@@ -474,7 +472,7 @@ decoding the same message multiple times."
         (cond (clean-message-header
                (mh-clean-msg-header (point-min)
                                     invisible-headers
-                                    visible-headers)
+                                    nil) ;; visible-headers
                (goto-char (point-min)))
               (t
                (mh-start-of-uncleaned-message)))
@@ -489,15 +487,11 @@ decoding the same message multiple times."
         (mh-display-emphasis)
         (mm-handle-set-undisplayer
          handle
-         `(lambda ()
-            (let (buffer-read-only)
-              (if (fboundp 'remove-specifier)
-                  ;; This is only valid on XEmacs.
-                  (mapcar (lambda (prop)
-                            (remove-specifier
-                             (face-property 'default prop) (current-buffer)))
-                          '(background background-pixmap foreground)))
-              (delete-region ,(point-min-marker) ,(point-max-marker)))))))))
+         (let ((beg (point-min-marker))
+               (end (point-max-marker)))
+           (lambda ()
+             (let ((inhibit-read-only t))
+               (delete-region beg end)))))))))
 
 ;;;###mh-autoload
 (defun mh-decode-message-header ()
@@ -783,7 +777,7 @@ This is only useful if a Content-Disposition header is not 
present."
          (funcall media-test handle) ; Since mm-inline-large-images is T,
                                         ; this only tells us if the image is
                                         ; something that emacs can display
-         (let* ((image (mm-get-image handle)))
+         (let ((image (mm-get-image handle)))
            (or (mh-do-in-xemacs
                  (and (mh-funcall-if-exists glyphp image)
                       (< (glyph-width image)
@@ -792,7 +786,7 @@ This is only useful if a Content-Disposition header is not 
present."
                          (or mh-max-inline-image-height
                              (window-pixel-height)))))
                (mh-do-in-gnu-emacs
-                 (let ((size (mh-funcall-if-exists image-size image)))
+                 (let ((size (and (fboundp 'image-size) (image-size image))))
                    (and size
                         (< (cdr size) (or mh-max-inline-image-height
                                           (1- (window-height))))
@@ -1225,7 +1219,7 @@ The option `mh-compose-insertion' controls what type of 
tags are inserted."
                               t)
                           t t)))
      (list description folder range)))
-  (let ((messages (mapconcat 'identity (mh-list-to-string range) " ")))
+  (let ((messages (mapconcat #'identity (mh-list-to-string range) " ")))
     (dolist (message (mh-translate-range folder messages))
       (if (equal mh-compose-insertion 'mml)
           (mh-mml-forward-message description folder (format "%s" message))
@@ -1258,11 +1252,7 @@ See also \\[mh-mh-to-mime]."
   (interactive (list
                 (mml-minibuffer-read-description)
                 (mh-prompt-for-folder "Message from" mh-sent-from-folder nil)
-                (read-string (concat "Messages"
-                                     (if (numberp mh-sent-from-msg)
-                                         (format " (default %d): "
-                                                 mh-sent-from-msg)
-                                       ": ")))))
+                (read-string (format-prompt "Messages" mh-sent-from-msg))))
   (beginning-of-line)
   (insert "#forw [")
   (and description
@@ -1596,7 +1586,7 @@ the possible security methods (see 
`mh-mml-method-default')."
   (if current-prefix-arg
       (let ((def (or (car mh-mml-cryptographic-method-history)
                      mh-mml-method-default)))
-        (completing-read (format "Method (default %s): " def)
+        (completing-read (format-prompt "Method" def)
                          '(("pgp") ("pgpmime") ("smime"))
                          nil t nil 'mh-mml-cryptographic-method-history def))
     mh-mml-method-default))
@@ -1731,7 +1721,7 @@ Optional argument DEFAULT is returned if a type isn't 
entered."
          (type (or (and (not (equal probed-type "application/octet-stream"))
                         probed-type)
                    (completing-read
-                    (format "Content type (default %s): " default)
+                    (format-prompt "Content type" default)
                     (mapcar #'list (mailcap-mime-types))))))
     (if (not (equal type ""))
         type
diff --git a/lisp/mh-e/mh-print.el b/lisp/mh-e/mh-print.el
index 513a1bc..d084cf6 100644
--- a/lisp/mh-e/mh-print.el
+++ b/lisp/mh-e/mh-print.el
@@ -1,4 +1,4 @@
-;;; mh-print.el --- MH-E printing support
+;;; mh-print.el --- MH-E printing support  -*- lexical-binding: t; -*-
 
 ;; Copyright (C) 2003-2021 Free Software Foundation, Inc.
 
@@ -207,8 +207,9 @@ Consider using \\[mh-ps-print-msg] instead."
     ;; Print scan listing if we have more than one message.
     (if (> (length msgs) 1)
         (let* ((msgs-string
-                (mapconcat 'identity (mh-list-to-string
-                                      (mh-coalesce-msg-list msgs)) " "))
+                (mapconcat #'identity (mh-list-to-string
+                                       (mh-coalesce-msg-list msgs))
+                           " "))
                (lpr-command
                 (format mh-lpr-command-format
                         (cond ((listp range)
diff --git a/lisp/mh-e/mh-scan.el b/lisp/mh-e/mh-scan.el
index cec3313..f00ab22 100644
--- a/lisp/mh-e/mh-scan.el
+++ b/lisp/mh-e/mh-scan.el
@@ -1,4 +1,4 @@
-;;; mh-scan.el --- MH-E scan line constants and utilities
+;;; mh-scan.el --- MH-E scan line constants and utilities  -*- 
lexical-binding: t; -*-
 
 ;; Copyright (C) 1993, 1995, 1997, 2000-2021 Free Software Foundation,
 ;; Inc.
@@ -497,7 +497,7 @@ with `mh-scan-msg-format-string'."
         (width 0))
     (with-current-buffer tmp-buffer
       (erase-buffer)
-      (apply 'call-process
+      (apply #'call-process
              (expand-file-name mh-scan-prog mh-progs) nil '(t nil) nil
              (list folder "last" "-format" "%(msg)"))
       (goto-char (point-min))
diff --git a/lisp/mh-e/mh-search.el b/lisp/mh-e/mh-search.el
index 05ba12d..aece03e 100644
--- a/lisp/mh-e/mh-search.el
+++ b/lisp/mh-e/mh-search.el
@@ -1,4 +1,4 @@
-;;; mh-search  ---  MH-Search mode
+;;; mh-search  ---  MH-Search mode  -*- lexical-binding: t; -*-
 
 ;; Copyright (C) 1993, 1995, 2001-2021 Free Software Foundation, Inc.
 
@@ -332,7 +332,7 @@ configuration and is used when the search folder is 
dismissed."
   (interactive (list (mh-prompt-for-folder "Search" mh-current-folder nil nil 
t)
                      (current-window-configuration)))
   ;; FIXME: `pick-folder' is unused!
-  (let ((pick-folder (if (equal folder "+") mh-current-folder folder)))
+  (let () ;; (pick-folder (if (equal folder "+") mh-current-folder folder))
     (switch-to-buffer-other-window "search-pattern")
     (if (or (zerop (buffer-size))
             (not (y-or-n-p "Reuse pattern? ")))
@@ -356,7 +356,7 @@ configuration and is used when the search folder is 
dismissed."
           "---------\n")
   (mh-search-mode)
   (goto-char (point-min))
-  (dotimes (i 5)
+  (dotimes (_ 5)
     (add-text-properties (point) (1+ (point)) '(front-sticky t))
     (add-text-properties (- (mh-line-end-position) 2)
                          (1- (mh-line-end-position))
@@ -453,7 +453,7 @@ search all folders."
 
 (defvar mh-flists-search-folders)
 
-(defun mh-flists-execute (&rest ignored)
+(defun mh-flists-execute (&rest _ignored)
   "Execute flists.
 Search for messages belonging to `mh-flists-sequence' in the
 folders specified by `mh-flists-search-folders'. If
@@ -880,7 +880,7 @@ used to search."
               folder-path
             (format "%s/" folder-path)))))
 
-(defalias 'mh-swish++-next-result 'mh-swish-next-result)
+(defalias 'mh-swish++-next-result #'mh-swish-next-result)
 
 (defun mh-swish++-regexp-builder (regexp-list)
   "Generate query for swish++.
@@ -1853,7 +1853,7 @@ PROC is used to convert the value to actual data."
                                     (1+ last-slash) (1- last-space)))
                  (buffer-substring-no-properties (1+ last-space) end))))))
 
-(defalias 'mh-md5-parser 'mh-openssl-parser)
+(defalias 'mh-md5-parser #'mh-openssl-parser)
 
 ;;;###mh-autoload
 (defun mh-index-update-maps (folder &optional origin-map)
diff --git a/lisp/mh-e/mh-seq.el b/lisp/mh-e/mh-seq.el
index e8a03f6..9b9675c 100644
--- a/lisp/mh-e/mh-seq.el
+++ b/lisp/mh-e/mh-seq.el
@@ -1,4 +1,4 @@
-;;; mh-seq.el --- MH-E sequences support
+;;; mh-seq.el --- MH-E sequences support  -*- lexical-binding: t; -*-
 
 ;; Copyright (C) 1993, 1995, 2001-2021 Free Software Foundation, Inc.
 
@@ -156,7 +156,7 @@ The list appears in a buffer named \"*MH-E Sequences*\"."
           (let ((name (mh-seq-name (car seq-list)))
                 (sorted-seq-msgs
                  (mh-coalesce-msg-list
-                  (sort (copy-sequence (mh-seq-msgs (car seq-list))) '<)))
+                  (sort (copy-sequence (mh-seq-msgs (car seq-list))) #'<)))
                 name-spec)
             (insert (setq name-spec (format (format "%%%ss:" max-len) name)))
             (while sorted-seq-msgs
@@ -191,7 +191,7 @@ MESSAGE appears."
              (cond (dest-folder (format " (to be refiled to %s)" dest-folder))
                    (deleted-flag (format " (to be deleted)"))
                    (t ""))
-             (mapconcat 'concat
+             (mapconcat #'concat
                         (mh-list-to-string (mh-seq-containing-msg message t))
                         " "))))
 
@@ -390,10 +390,7 @@ Prompt with PROMPT, raise an error if the sequence is 
empty and
 the NOT-EMPTY flag is non-nil, and supply an optional DEFAULT
 sequence. A reply of `%' defaults to the first sequence
 containing the current message."
-  (let* ((input (completing-read (format "%s sequence%s: " prompt
-                                         (if default
-                                             (format " (default %s)" default)
-                                           ""))
+  (let* ((input (completing-read (format-prompt "%s sequence" default prompt)
                                  (mh-seq-names mh-seq-list)
                                  nil nil nil 'mh-sequence-history))
          (seq (cond ((equal input "%")
@@ -494,13 +491,13 @@ folder buffer are not updated."
   ;; Add to a SEQUENCE each message the list of MSGS.
   (if (and (mh-valid-seq-p seq) (not (mh-folder-name-p seq)))
       (if msgs
-          (apply 'mh-exec-cmd "mark" mh-current-folder "-add"
+          (apply #'mh-exec-cmd "mark" mh-current-folder "-add"
                  "-sequence" (symbol-name seq)
                  (mh-coalesce-msg-list msgs)))))
 
 (defun mh-canonicalize-sequence (msgs)
   "Sort MSGS in decreasing order and remove duplicates."
-  (let* ((sorted-msgs (sort (copy-sequence msgs) '>))
+  (let* ((sorted-msgs (sort (copy-sequence msgs) #'>))
          (head sorted-msgs))
     (while (cdr head)
       (if (= (car head) (cadr head))
@@ -565,7 +562,7 @@ OP is one of `widen' and `unthread'."
 (defvar mh-range-seq-names)
 (defvar mh-range-history ())
 (defvar mh-range-completion-map (copy-keymap minibuffer-local-completion-map))
-(define-key mh-range-completion-map " " 'self-insert-command)
+(define-key mh-range-completion-map " " #'self-insert-command)
 
 ;;;###mh-autoload
 (defun mh-interactive-range (range-prompt &optional default)
@@ -646,13 +643,10 @@ should be replaced with:
                         ((stringp default) default)
                         ((symbolp default) (symbol-name default))))
          (prompt (cond ((and guess large default)
-                        (format "%s (folder has %s messages, default %s)"
-                                prompt (car counts) default))
-                       ((and guess large)
-                        (format "%s (folder has %s messages)"
-                                prompt (car counts)))
+                        (format-prompt "%s (folder has %s messages)"
+                                default prompt (car counts)))
                        (default
-                         (format "%s (default %s)" prompt default))))
+                         (format-prompt prompt default))))
          (minibuffer-local-completion-map mh-range-completion-map)
          (seq-list (if (eq folder mh-current-folder)
                        mh-seq-list
@@ -662,7 +656,7 @@ should be replaced with:
                   (mh-seq-names seq-list)))
          (input (cond ((and (not ask-flag) unseen) (symbol-name mh-unseen-seq))
                       ((and (not ask-flag) (not large)) "all")
-                      (t (completing-read (format "%s: " prompt)
+                      (t (completing-read prompt
                                           'mh-range-completion-function nil nil
                                           nil 'mh-range-history default))))
          msg-list)
diff --git a/lisp/mh-e/mh-show.el b/lisp/mh-e/mh-show.el
index 9ad843c..cb9819f 100644
--- a/lisp/mh-e/mh-show.el
+++ b/lisp/mh-e/mh-show.el
@@ -1,4 +1,4 @@
-;;; mh-show.el --- MH-Show mode
+;;; mh-show.el --- MH-Show mode  -*- lexical-binding: t; -*-
 
 ;; Copyright (C) 1993, 1995, 1997, 2000-2021 Free Software Foundation,
 ;; Inc.
@@ -136,7 +136,7 @@ displayed."
         (show-window (get-buffer-window mh-show-buffer))
         (display-mime-buttons-flag mh-display-buttons-for-inline-parts-flag))
     (if (not (eq (next-window (minibuffer-window)) (selected-window)))
-        (delete-other-windows))         ; force ourself to the top window
+        (delete-other-windows))         ; force ourselves to the top window
     (mh-in-show-buffer (mh-show-buffer)
       (setq mh-display-buttons-for-inline-parts-flag display-mime-buttons-flag)
       (if (and show-window
@@ -195,7 +195,7 @@ Sets the current buffer to the show buffer."
     (let ((formfile mh-mhl-format-file)
           (clean-message-header mh-clean-message-header-flag)
           (invisible-headers mh-invisible-header-fields-compiled)
-          (visible-headers nil)
+          ;; (visible-headers nil)
           (msg-filename (mh-msg-filename msg-num folder-name))
           (show-buffer mh-show-buffer)
           (mm-inline-media-tests mh-mm-inline-media-tests))
@@ -241,7 +241,7 @@ Sets the current buffer to the show buffer."
              (cond (clean-message-header
                     (mh-clean-msg-header (point-min)
                                          invisible-headers
-                                         visible-headers)
+                                         nil) ;; visible-headers
                     (goto-char (point-min)))
                    (t
                     (mh-start-of-uncleaned-message)))
@@ -862,7 +862,7 @@ See also `mh-folder-mode'.
       (turn-on-font-lock))
   (when mh-decode-mime-flag
     (mh-make-local-hook 'kill-buffer-hook)
-    (add-hook 'kill-buffer-hook 'mh-mime-cleanup nil t))
+    (add-hook 'kill-buffer-hook #'mh-mime-cleanup nil t))
   (mh-do-in-xemacs
     (easy-menu-add mh-show-sequence-menu)
     (easy-menu-add mh-show-message-menu)
diff --git a/lisp/mh-e/mh-speed.el b/lisp/mh-e/mh-speed.el
index 7cbd42c..b2deacf 100644
--- a/lisp/mh-e/mh-speed.el
+++ b/lisp/mh-e/mh-speed.el
@@ -1,4 +1,4 @@
-;;; mh-speed.el --- MH-E speedbar support
+;;; mh-speed.el --- MH-E speedbar support  -*- lexical-binding: t; -*-
 
 ;; Copyright (C) 2002-2021 Free Software Foundation, Inc.
 
@@ -100,9 +100,9 @@
 
 ;; Alphabetical.
 
-(defalias 'mh-speed-contract-folder 'mh-speed-toggle)
+(defalias 'mh-speed-contract-folder #'mh-speed-toggle)
 
-(defalias 'mh-speed-expand-folder 'mh-speed-toggle)
+(defalias 'mh-speed-expand-folder #'mh-speed-toggle)
 
 (defun mh-speed-refresh ()
   "Regenerates the list of folders in the speedbar.
@@ -202,9 +202,9 @@ created."
       (mh-speed-flists nil))))
 
 ;;;###mh-autoload
-(defalias 'mh-show-speedbar-buttons 'mh-folder-speedbar-buttons)
+(defalias 'mh-show-speedbar-buttons #'mh-folder-speedbar-buttons)
 ;;;###mh-autoload
-(defalias 'mh-letter-speedbar-buttons 'mh-folder-speedbar-buttons)
+(defalias 'mh-letter-speedbar-buttons #'mh-folder-speedbar-buttons)
 
 (defmacro mh-speed-select-attached-frame ()
   "Compatibility macro to handle speedbar versions 0.11a and 0.14beta4."
@@ -431,7 +431,7 @@ flists is run only for that one folder."
                (setq mh-speed-flists-folder nil)
                (mh-process-kill-without-query mh-speed-flists-process)
                (set-process-filter mh-speed-flists-process
-                                   'mh-speed-parse-flists-output)))))))
+                                   #'mh-speed-parse-flists-output)))))))
 
 ;; Copied from mh-make-folder-list-filter...
 ;; XXX Refactor to use mh-make-folder-list-filer?
diff --git a/lisp/mh-e/mh-thread.el b/lisp/mh-e/mh-thread.el
index 3657462..a7878aa 100644
--- a/lisp/mh-e/mh-thread.el
+++ b/lisp/mh-e/mh-thread.el
@@ -1,4 +1,4 @@
-;;; mh-thread.el --- MH-E threading support
+;;; mh-thread.el --- MH-E threading support  -*- lexical-binding: t; -*-
 
 ;; Copyright (C) 2002-2004, 2006-2021 Free Software Foundation, Inc.
 
diff --git a/lisp/mh-e/mh-tool-bar.el b/lisp/mh-e/mh-tool-bar.el
index 7dbddbc..40a430b 100644
--- a/lisp/mh-e/mh-tool-bar.el
+++ b/lisp/mh-e/mh-tool-bar.el
@@ -1,4 +1,4 @@
-;;; mh-tool-bar.el --- MH-E tool bar support
+;;; mh-tool-bar.el --- MH-E tool bar support  -*- lexical-binding: t; -*-
 
 ;; Copyright (C) 2002-2003, 2005-2021 Free Software Foundation, Inc.
 
@@ -356,7 +356,7 @@ Use SEQUENCE-MAP if display is limited; DEFAULT-MAP 
otherwise."
         '(list ,@(mapcar (lambda (x) `(quote ,x)) folder-defaults))
         "List of buttons to include in MH-Folder tool bar."
         :group 'mh-tool-bar
-        :set 'mh-tool-bar-folder-buttons-set
+        :set #'mh-tool-bar-folder-buttons-set
         :type '(set ,@(cl-loop for x in folder-buttons
                                for y in folder-docs
                                collect `(const :tag ,y ,x)))
@@ -367,7 +367,7 @@ Use SEQUENCE-MAP if display is limited; DEFAULT-MAP 
otherwise."
         '(list ,@(mapcar (lambda (x) `(quote ,x)) letter-defaults))
         "List of buttons to include in MH-Letter tool bar."
         :group 'mh-tool-bar
-        :set 'mh-tool-bar-letter-buttons-set
+        :set #'mh-tool-bar-letter-buttons-set
         :type '(set ,@(cl-loop for x in letter-buttons
                                for y in letter-docs
                                collect `(const :tag ,y ,x)))
diff --git a/lisp/mh-e/mh-utils.el b/lisp/mh-e/mh-utils.el
index d7c607d..be66e62 100644
--- a/lisp/mh-e/mh-utils.el
+++ b/lisp/mh-e/mh-utils.el
@@ -1,4 +1,4 @@
-;;; mh-utils.el --- MH-E general utilities
+;;; mh-utils.el --- MH-E general utilities  -*- lexical-binding: t; -*-
 
 ;; Copyright (C) 1993, 1995, 1997, 2000-2021 Free Software Foundation,
 ;; Inc.
@@ -268,7 +268,7 @@ and displayed in a help buffer."
   (interactive)
   (let* ((help (or help-messages
                   (cdr (assoc nil (assoc major-mode mh-help-messages)))))
-         (text (substitute-command-keys (mapconcat 'identity help ""))))
+         (text (substitute-command-keys (mapconcat #'identity help ""))))
     (with-electric-help
      (lambda ()
        (insert text))
@@ -298,7 +298,7 @@ and displayed in a help buffer."
 This is the inverse of `mh-read-msg-list', which expands ranges.
 Message lists passed to MH programs should be processed by this
 function to avoid exceeding system command line argument limits."
-  (let ((msgs (sort (copy-sequence messages) 'mh-greaterp))
+  (let ((msgs (sort (copy-sequence messages) #'mh-greaterp))
         (range-high nil)
         (prev -1)
         (ranges nil))
@@ -669,7 +669,7 @@ three arguments so we bind this variable to t or nil.
 This variable should never be set.")
 
 (defvar mh-folder-completion-map (copy-keymap minibuffer-local-completion-map))
-(define-key mh-folder-completion-map " " 'minibuffer-complete)  ;Why???
+(define-key mh-folder-completion-map " " #'minibuffer-complete)  ;Why???
 
 (defvar mh-speed-flists-inhibit-flag nil)
 
@@ -730,8 +730,7 @@ See Info node `(elisp) Programmed Completion' for details."
                    (t (file-directory-p path))))))))
 
 ;; Shush compiler.
-(mh-do-in-xemacs
-  (defvar completion-root-regexp))
+(defvar completion-root-regexp) ;; Apparently used in XEmacs
 
 (defun mh-folder-completing-read (prompt default allow-root-folder-flag)
   "Read folder name with PROMPT and default result DEFAULT.
@@ -758,10 +757,9 @@ function will accept the folder +, which means all folders 
when
 used in searching."
   (if (null default)
       (setq default ""))
-  (let* ((default-string (cond (default-string (format " (default %s)" 
default-string))
-                               ((equal "" default) "")
-                               (t (format " (default %s)" default))))
-         (prompt (format "%s folder%s: " prompt default-string))
+  (let* ((default-string (or default-string
+                             (if (equal default "") nil default)))
+         (prompt (format-prompt "%s folder" default-string prompt))
          (mh-current-folder-name mh-current-folder)
          read-name folder-name)
     (while (and (setq read-name (mh-folder-completing-read
@@ -925,10 +923,10 @@ Handle RFC 822 (or later) continuation lines."
 (defvar mh-hidden-header-keymap
   (let ((map (make-sparse-keymap)))
     (mh-do-in-gnu-emacs
-      (define-key map [mouse-2] 'mh-letter-toggle-header-field-display-button))
+      (define-key map [mouse-2] 
#'mh-letter-toggle-header-field-display-button))
     (mh-do-in-xemacs
       (define-key map '(button2)
-        'mh-letter-toggle-header-field-display-button))
+        #'mh-letter-toggle-header-field-display-button))
     map))
 
 ;;;###mh-autoload
diff --git a/lisp/mh-e/mh-xface.el b/lisp/mh-e/mh-xface.el
index 036575a..0b53829 100644
--- a/lisp/mh-e/mh-xface.el
+++ b/lisp/mh-e/mh-xface.el
@@ -1,4 +1,4 @@
-;;; mh-xface.el --- MH-E X-Face and Face header field display
+;;; mh-xface.el --- MH-E X-Face and Face header field display  -*- 
lexical-binding: t; -*-
 
 ;; Copyright (C) 2002-2003, 2005-2021 Free Software Foundation, Inc.
 
@@ -365,7 +365,7 @@ Replace the ?/ character with a ?! character and append 
.png.
 Also replaces special characters with `mh-url-hexify-string'
 since not all characters, such as :, are valid within Windows
 filenames.  In addition, replaces * with %2a. See URL
-`http://msdn.microsoft.com/library/default.asp?url=/library/en-us/shellcc/platform/shell/reference/ifaces/iitemnamelimits/GetValidCharacters.asp'."
+`https://msdn.microsoft.com/library/default.asp?url=/library/en-us/shellcc/platform/shell/reference/ifaces/iitemnamelimits/GetValidCharacters.asp'."
   (format "%s/%s.png" mh-x-image-cache-directory
           (mh-replace-regexp-in-string
            "\\*" "%2a"
diff --git a/lisp/minibuffer.el b/lisp/minibuffer.el
index a899a94..5f59467 100644
--- a/lisp/minibuffer.el
+++ b/lisp/minibuffer.el
@@ -2116,18 +2116,19 @@ variables.")
 (defun exit-minibuffer ()
   "Terminate this minibuffer argument."
   (interactive)
-  (when (or
-         (innermost-minibuffer-p)
-         (not (minibufferp)))
+  (when (minibufferp)
+    (when (not (minibuffer-innermost-command-loop-p))
+      (error "%s" "Not in most nested command loop"))
+    (when (not (innermost-minibuffer-p))
+      (error "%s" "Not in most nested minibuffer")))
   ;; If the command that uses this has made modifications in the minibuffer,
   ;; we don't want them to cause deactivation of the mark in the original
   ;; buffer.
   ;; A better solution would be to make deactivate-mark buffer-local
   ;; (or to turn it into a list of buffers, ...), but in the mean time,
   ;; this should do the trick in most cases.
-    (setq deactivate-mark nil)
-    (throw 'exit nil))
-  (error "%s" "Not in most nested minibuffer"))
+  (setq deactivate-mark nil)
+  (throw 'exit nil))
 
 (defun self-insert-and-exit ()
   "Terminate minibuffer input."
@@ -3161,7 +3162,7 @@ or a symbol, see `completion-pcm--merge-completions'."
   (let ((n '()))
     (while p
       (pcase p
-        (`(,(or 'any 'any-delim) ,(or 'any 'point) . ,rest)
+        (`(,(or 'any 'any-delim) ,(or 'any 'point) . ,_)
          (setq p (cdr p)))
         ;; This is not just a performance improvement: it turns a
         ;; terminating `point' into an implicit `any', which affects
@@ -3940,13 +3941,15 @@ it.  See `format' for details.
 If DEFAULT is a list, the first element is used as the default.
 If not, the element is used as is.
 
-If DEFAULT is nil, no \"default value\" string is included in the
-return value."
+If DEFAULT is nil or an empty string, no \"default value\" string
+is included in the return value."
   (concat
    (if (null format-args)
        prompt
      (apply #'format prompt format-args))
    (and default
+        (or (not (stringp default))
+            (length> default 0))
         (format minibuffer-default-prompt-format
                 (if (consp default)
                     (car default)
diff --git a/lisp/misc.el b/lisp/misc.el
index 09f6011..39ec949 100644
--- a/lisp/misc.el
+++ b/lisp/misc.el
@@ -41,7 +41,7 @@ The characters copied are inserted in the buffer before 
point."
     (save-excursion
       (beginning-of-line)
       (backward-char 1)
-      (skip-chars-backward "\ \t\n")
+      (skip-chars-backward " \t\n")
       (move-to-column cc)
       ;; Default is enough to copy the whole rest of the line.
       (setq n (if arg (prefix-numeric-value arg) (point-max)))
diff --git a/lisp/mouse-copy.el b/lisp/mouse-copy.el
index 8155c9d..14fbb51 100644
--- a/lisp/mouse-copy.el
+++ b/lisp/mouse-copy.el
@@ -1,4 +1,4 @@
-;;; mouse-copy.el --- one-click text copy and move
+;;; mouse-copy.el --- one-click text copy and move  -*- lexical-binding: t -*-
 
 ;; Copyright (C) 1996, 2001-2021 Free Software Foundation, Inc.
 
@@ -213,8 +213,7 @@ by johnh@ficus.cs.ucla.edu."
   (if (mouse-drag-secondary start-event)
       (progn
        (mouse-kill-preserving-secondary)
-       (insert (gui-get-selection 'SECONDARY))))
-)
+        (insert (gui-get-selection 'SECONDARY)))))
 
 (provide 'mouse-copy)
 
diff --git a/lisp/mouse-drag.el b/lisp/mouse-drag.el
index b2960a4..b424b6e 100644
--- a/lisp/mouse-drag.el
+++ b/lisp/mouse-drag.el
@@ -1,4 +1,4 @@
-;;; mouse-drag.el --- use mouse-2 to do a new style of scrolling
+;;; mouse-drag.el --- use mouse-2 to do a new style of scrolling  -*- 
lexical-binding: t -*-
 
 ;; Copyright (C) 1996-1997, 2001-2021 Free Software Foundation, Inc.
 
diff --git a/lisp/mouse.el b/lisp/mouse.el
index 8732fb8..f4979e3 100644
--- a/lisp/mouse.el
+++ b/lisp/mouse.el
@@ -119,7 +119,9 @@ Expects to be bound to `(double-)mouse-1' in 
`key-translation-map'."
                              (time-since (cdr mouse--last-down))
                               (/ (abs mouse-1-click-follows-link) 1000.0))))))
        (eq (car mouse--last-down)
-           (event-convert-list (list 'down (car-safe last-input-event))))
+           (event-convert-list
+            `(down ,@(event-modifiers last-input-event)
+                   ,(event-basic-type last-input-event))))
        (let* ((action (mouse-on-link-p (event-start last-input-event))))
          (when (and action
                     (or mouse-1-click-in-non-selected-windows
diff --git a/lisp/mwheel.el b/lisp/mwheel.el
index adfeacc..048f50c 100644
--- a/lisp/mwheel.el
+++ b/lisp/mwheel.el
@@ -411,6 +411,7 @@ an event used for scrolling, such as 
`mouse-wheel-down-event'."
       (cons (vector event)
             (mapcar (lambda (prefix) (vector prefix event)) prefixes)))))
 
+;;;###autoload
 (define-minor-mode mouse-wheel-mode
   "Toggle mouse wheel support (Mouse Wheel mode)."
   :init-value t
diff --git a/lisp/net/ange-ftp.el b/lisp/net/ange-ftp.el
index fa13dd5..86b5d44 100644
--- a/lisp/net/ange-ftp.el
+++ b/lisp/net/ange-ftp.el
@@ -3716,7 +3716,7 @@ so return the size on the remote host exactly. See RFC 
3659."
             (binary (or (ange-ftp-binary-file filename)
                         (ange-ftp-binary-file newname)))
             temp1
-            temp2)
+            ) ;; temp2
 
        ;; check to see if we can overwrite
        (if (or (not ok-if-already-exists)
@@ -3750,7 +3750,7 @@ so return the size on the remote host exactly. See RFC 
3659."
                     filename newname binary msg
                     f-parsed f-host f-user f-name f-abbr
                     t-parsed t-host t-user t-name t-abbr
-                    temp1 temp2 cont nowait)
+                    temp1 nil cont nowait) ;; temp2
               nowait))
 
          ;; filename wasn't remote.  newname must be remote.  call the
@@ -6111,8 +6111,7 @@ Other orders of $ and _ seem to all work just fine.")
                                       (1- (match-end 2)))))
                (filename (if (match-beginning 3)
                              (substring name (match-beginning 3)))))
-           (if (and (boundp 'filename)
-                    (stringp filename)
+           (if (and (stringp filename)
                     (string-match "[#@].+" filename))
                (setq filename (concat ange-ftp-bs2000-special-prefix
                                       (substring filename 1))))
diff --git a/lisp/net/browse-url.el b/lisp/net/browse-url.el
index 58f01d5..1c98335 100644
--- a/lisp/net/browse-url.el
+++ b/lisp/net/browse-url.el
@@ -826,7 +826,7 @@ If optional arg TEMP-FILE-NAME is non-nil, delete it 
instead."
     (if (and file-name (file-exists-p file-name))
        (delete-file file-name))))
 
-(add-hook 'kill-buffer-hook 'browse-url-delete-temp-file)
+(add-hook 'kill-buffer-hook #'browse-url-delete-temp-file)
 
 (declare-function dired-get-filename "dired"
                  (&optional localp no-error-if-not-filep))
@@ -1064,7 +1064,7 @@ xdg-open is a desktop utility that calls your preferred 
web browser."
        (executable-find "xdg-open")))
 
 ;;;###autoload
-(defun browse-url-xdg-open (url &optional ignored)
+(defun browse-url-xdg-open (url &optional _ignored)
   "Pass the specified URL to the \"xdg-open\" command.
 xdg-open is a desktop utility that calls your preferred web browser.
 The optional argument IGNORED is not used."
@@ -1095,7 +1095,7 @@ used instead of `browse-url-new-window-flag'."
   (setq url (browse-url-encode-url url))
   (let* ((process-environment (browse-url-process-environment))
         (process
-         (apply 'start-process
+         (apply #'start-process
                 (concat "netscape " url) nil
                 browse-url-netscape-program
                 (append
@@ -1125,7 +1125,7 @@ used instead of `browse-url-new-window-flag'."
       (let* ((process-environment (browse-url-process-environment)))
        ;; Netscape not running - start it
        (message "Starting %s..." browse-url-netscape-program)
-       (apply 'start-process (concat "netscape" url) nil
+       (apply #'start-process (concat "netscape" url) nil
               browse-url-netscape-program
               (append browse-url-netscape-startup-arguments (list url))))))
 
@@ -1144,7 +1144,7 @@ How depends on `browse-url-netscape-version'."
   "Send a remote control command to Netscape."
   (declare (obsolete nil "25.1"))
   (let* ((process-environment (browse-url-process-environment)))
-    (apply 'start-process "netscape" nil
+    (apply #'start-process "netscape" nil
            browse-url-netscape-program
            (append browse-url-netscape-arguments
                    (list "-remote" command)))))
@@ -1170,7 +1170,7 @@ used instead of `browse-url-new-window-flag'."
   (setq url (browse-url-encode-url url))
   (let* ((process-environment (browse-url-process-environment))
          (process
-         (apply 'start-process
+         (apply #'start-process
                 (concat "mozilla " url) nil
                 browse-url-mozilla-program
                 (append
@@ -1196,7 +1196,7 @@ used instead of `browse-url-new-window-flag'."
       (let* ((process-environment (browse-url-process-environment)))
        ;; Mozilla is not running - start it
        (message "Starting %s..." browse-url-mozilla-program)
-       (apply 'start-process (concat "mozilla " url) nil
+       (apply #'start-process (concat "mozilla " url) nil
               browse-url-mozilla-program
               (append browse-url-mozilla-startup-arguments (list url))))))
 
@@ -1219,7 +1219,7 @@ instead of `browse-url-new-window-flag'."
   (interactive (browse-url-interactive-arg "URL: "))
   (setq url (browse-url-encode-url url))
   (let* ((process-environment (browse-url-process-environment)))
-    (apply 'start-process
+    (apply #'start-process
            (concat "firefox " url) nil
            browse-url-firefox-program
            (append
@@ -1242,7 +1242,7 @@ The optional argument NEW-WINDOW is not used."
   (interactive (browse-url-interactive-arg "URL: "))
   (setq url (browse-url-encode-url url))
   (let* ((process-environment (browse-url-process-environment)))
-    (apply 'start-process
+    (apply #'start-process
           (concat "chromium " url) nil
           browse-url-chromium-program
           (append
@@ -1260,7 +1260,7 @@ The optional argument NEW-WINDOW is not used."
   (interactive (browse-url-interactive-arg "URL: "))
   (setq url (browse-url-encode-url url))
   (let* ((process-environment (browse-url-process-environment)))
-    (apply 'start-process
+    (apply #'start-process
           (concat "google-chrome " url) nil
           browse-url-chrome-program
           (append
@@ -1290,7 +1290,7 @@ used instead of `browse-url-new-window-flag'."
   (interactive (browse-url-interactive-arg "URL: "))
   (setq url (browse-url-encode-url url))
   (let* ((process-environment (browse-url-process-environment))
-         (process (apply 'start-process
+         (process (apply #'start-process
                         (concat "galeon " url)
                         nil
                         browse-url-galeon-program
@@ -1315,7 +1315,7 @@ used instead of `browse-url-new-window-flag'."
       (let* ((process-environment (browse-url-process-environment)))
        ;; Galeon is not running - start it
        (message "Starting %s..." browse-url-galeon-program)
-       (apply 'start-process (concat "galeon " url) nil
+       (apply #'start-process (concat "galeon " url) nil
               browse-url-galeon-program
               (append browse-url-galeon-startup-arguments (list url))))))
 
@@ -1338,7 +1338,7 @@ used instead of `browse-url-new-window-flag'."
   (interactive (browse-url-interactive-arg "URL: "))
   (setq url (browse-url-encode-url url))
   (let* ((process-environment (browse-url-process-environment))
-         (process (apply 'start-process
+         (process (apply #'start-process
                         (concat "epiphany " url)
                         nil
                         browse-url-epiphany-program
@@ -1362,7 +1362,7 @@ used instead of `browse-url-new-window-flag'."
       (let* ((process-environment (browse-url-process-environment)))
        ;; Epiphany is not running - start it
        (message "Starting %s..." browse-url-epiphany-program)
-       (apply 'start-process (concat "epiphany " url) nil
+       (apply #'start-process (concat "epiphany " url) nil
               browse-url-epiphany-program
               (append browse-url-epiphany-startup-arguments (list url))))))
 
@@ -1403,7 +1403,7 @@ When called non-interactively, optional second argument 
NEW-WINDOW is
 used instead of `browse-url-new-window-flag'."
   (declare (obsolete nil "25.1"))
   (interactive (browse-url-interactive-arg "URL: "))
-  (apply 'start-process (concat "gnome-moz-remote " url)
+  (apply #'start-process (concat "gnome-moz-remote " url)
         nil
         browse-url-gnome-moz-program
         (append
@@ -1437,7 +1437,7 @@ NEW-WINDOW instead of `browse-url-new-window-flag'."
   (interactive (browse-url-interactive-arg "URL: "))
   (setq url (browse-url-encode-url url))
   (let* ((process-environment (browse-url-process-environment)))
-    (apply 'start-process (format "conkeror %s" url)
+    (apply #'start-process (format "conkeror %s" url)
           nil
           browse-url-conkeror-program
           (append
@@ -1487,7 +1487,7 @@ The `browse-url-gnudoit-program' program is used with 
options given by
 `browse-url-gnudoit-args'.  Default to the URL around or before point."
   (declare (obsolete nil "25.1"))
   (interactive (browse-url-interactive-arg "W3 URL: "))
-  (apply 'start-process (concat "gnudoit:" url) nil
+  (apply #'start-process (concat "gnudoit:" url) nil
         browse-url-gnudoit-program
         (append browse-url-gnudoit-args
                 (list (concat "(w3-fetch \"" url "\")")
@@ -1667,7 +1667,7 @@ don't offer a form of remote control."
   (interactive (browse-url-interactive-arg "URL: "))
   (if (not browse-url-generic-program)
       (error "No browser defined (`browse-url-generic-program')"))
-  (apply 'call-process browse-url-generic-program nil
+  (apply #'call-process browse-url-generic-program nil
         0 nil
         (append browse-url-generic-args (list url))))
 
@@ -1742,9 +1742,9 @@ from `browse-url-elinks-wrapper'."
 
 (defvar browse-url-button-map
   (let ((map (make-sparse-keymap)))
-    (define-key map "\r" 'browse-url-button-open)
-    (define-key map [mouse-2] 'browse-url-button-open)
-    (define-key map "w" 'browse-url-button-copy)
+    (define-key map "\r" #'browse-url-button-open)
+    (define-key map [mouse-2] #'browse-url-button-open)
+    (define-key map "w" #'browse-url-button-copy)
     map)
   "The keymap used for browse-url buttons.")
 
diff --git a/lisp/net/dbus.el b/lisp/net/dbus.el
index a9de35c..4116d29 100644
--- a/lisp/net/dbus.el
+++ b/lisp/net/dbus.el
@@ -1144,6 +1144,7 @@ compound type arguments (TYPE VALUE) will be kept as is."
 EVENT is a D-Bus event, see `dbus-check-event'.  HANDLER, being
 part of the event, is called with arguments ARGS (without type information).
 If the HANDLER returns a `dbus-error', it is propagated as return message."
+  (declare (completion ignore))
   (interactive "e")
   (condition-case err
       (let (monitor args result)
@@ -2028,8 +2029,9 @@ either a method name, a signal name, or an error name."
            ",")
           rule (or rule ""))
 
-    (unless (ignore-errors (dbus-get-unique-name bus-private))
-      (dbus-init-bus bus 'private))
+    (when (fboundp 'dbus-get-unique-name)
+      (unless (ignore-errors (dbus-get-unique-name bus-private))
+        (dbus-init-bus bus 'private)))
     (dbus-call-method
      bus-private dbus-service-dbus dbus-path-dbus dbus-interface-monitoring
      "BecomeMonitor" `(:array :string ,rule) :uint32 0)
diff --git a/lisp/net/dictionary-connection.el 
b/lisp/net/dictionary-connection.el
index 8ad4fe4..b874c48 100644
--- a/lisp/net/dictionary-connection.el
+++ b/lisp/net/dictionary-connection.el
@@ -22,10 +22,10 @@
 
 ;;; Commentary:
 
-;; dictionary-connection allows to handle TCP-based connections in
-;; client mode where text-based information are exchanged.  There is
+;; dictionary-connection allows handling TCP-based connections in
+;; client mode where text-based information is exchanged.  There is
 ;; special support for handling CR LF (and the usual CR LF . CR LF
-;; terminater).
+;; terminator).
 
 ;;; Code:
 
@@ -68,7 +68,7 @@
 
 (defun dictionary-connection-open (server port)
   "Open a connection to SERVER at PORT.
-A data structure identifing the connection is returned"
+Return a data structure identifying the connection."
 
   (let ((process-buffer (generate-new-buffer (format " connection to %s:%s"
                                                     server
@@ -82,11 +82,11 @@ A data structure identifing the connection is returned"
 (defun dictionary-connection-status (connection)
   "Return the status of the CONNECTION.
 Possible return values are the symbols:
-nil: argument is no connection object
-'none: argument has no connection
-'up: connection is open and buffer is existing
-'down: connection is closed
-'alone: connection is not associated with a buffer"
+    nil:    argument is not a connection object
+    'none:  argument is not connected
+    'up:    connection is open and buffer is existing
+    'down:  connection is closed
+    'alone: connection is not associated with a buffer"
   (when (dictionary-connection-p connection)
     (let ((process (dictionary-connection-process connection))
           (buffer (dictionary-connection-buffer connection)))
diff --git a/lisp/net/dictionary.el b/lisp/net/dictionary.el
index 6f08605..f33cbaf 100644
--- a/lisp/net/dictionary.el
+++ b/lisp/net/dictionary.el
@@ -35,7 +35,6 @@
 ;;; Code:
 
 (require 'cl-lib)
-(require 'easymenu)
 (require 'custom)
 (require 'dictionary-connection)
 (require 'button)
@@ -77,7 +76,7 @@ You can specify here:
 - dict.org: Only use dict.org
 - User-defined: You can specify your own server here"
   :group 'dictionary
-  :set 'dictionary-set-server-var
+  :set #'dictionary-set-server-var
   :type '(choice (const :tag "Automatic" nil)
                  (const :tag "localhost" "localhost")
                  (const :tag "dict.org" "dict.org")
@@ -89,7 +88,7 @@ You can specify here:
   "The port of the dictionary server.
 This port is propably always 2628 so there should be no need to modify it."
   :group 'dictionary
-  :set 'dictionary-set-server-var
+  :set #'dictionary-set-server-var
   :type 'number
   :version "28.1")
 
@@ -127,9 +126,9 @@ by the choice value:
 
   The found word exactly matches the searched word.
 
-- Similiar sounding
+- Similar sounding
 
-  The found word sounds similiar to the searched word.  For this match type
+  The found word sounds similar to the searched word.  For this match type
   the soundex algorithm defined by Donald E. Knuth is used.  It will only
   works with english words and the algorithm is not very reliable (i.e.,
   the soundex algorithm is quite simple).
@@ -148,7 +147,7 @@ by the choice value:
   dictionary server."
   :group 'dictionary
   :type '(choice (const :tag "Exact match" "exact")
-                (const :tag "Similiar sounding" "soundex")
+                (const :tag "Similar sounding" "soundex")
                 (const :tag "Levenshtein distance one" "lev")
                 (string :tag "User choice"))
   :version "28.1")
@@ -190,7 +189,7 @@ where the current word was found."
   nil
   "Connects via a HTTP proxy using the CONNECT command when not nil."
   :group 'dictionary-proxy
-  :set 'dictionary-set-server-var
+  :set #'dictionary-set-server-var
   :type 'boolean
   :version "28.1")
 
@@ -198,7 +197,7 @@ where the current word was found."
   "proxy"
   "The name of the HTTP proxy to use when `dictionary-use-http-proxy' is set."
   :group 'dictionary-proxy
-  :set 'dictionary-set-server-var
+  :set #'dictionary-set-server-var
   :type 'string
   :version "28.1")
 
@@ -206,7 +205,7 @@ where the current word was found."
   3128
   "The port of the proxy server, used only when `dictionary-use-http-proxy' is 
set."
   :group 'dictionary-proxy
-  :set 'dictionary-set-server-var
+  :set #'dictionary-set-server-var
   :type 'number
   :version "28.1")
 
@@ -332,19 +331,19 @@ is utf-8"
     (suppress-keymap map)
     (set-keymap-parent map button-buffer-map)
 
-    (define-key map "q" 'dictionary-close)
-    (define-key map "h" 'dictionary-help)
-    (define-key map "s" 'dictionary-search)
-    (define-key map "d" 'dictionary-lookup-definition)
-    (define-key map "D" 'dictionary-select-dictionary)
-    (define-key map "M" 'dictionary-select-strategy)
-    (define-key map "m" 'dictionary-match-words)
-    (define-key map "l" 'dictionary-previous)
-    (define-key map "n" 'forward-button)
-    (define-key map "p" 'backward-button)
-    (define-key map " " 'scroll-up-command)
-    (define-key map [?\S-\ ] 'scroll-down-command)
-    (define-key map (read-kbd-macro "M-SPC") 'scroll-down-command)
+    (define-key map "q" #'dictionary-close)
+    (define-key map "h" #'dictionary-help)
+    (define-key map "s" #'dictionary-search)
+    (define-key map "d" #'dictionary-lookup-definition)
+    (define-key map "D" #'dictionary-select-dictionary)
+    (define-key map "M" #'dictionary-select-strategy)
+    (define-key map "m" #'dictionary-match-words)
+    (define-key map "l" #'dictionary-previous)
+    (define-key map "n" #'forward-button)
+    (define-key map "p" #'backward-button)
+    (define-key map " " #'scroll-up-command)
+    (define-key map [?\S-\ ] #'scroll-down-command)
+    (define-key map (read-kbd-macro "M-SPC") #'scroll-down-command)
     map)
   "Keymap for the dictionary mode.")
 
@@ -414,12 +413,12 @@ This is a quick reference to this mode describing the 
default key bindings:
   (make-local-variable 'dictionary-default-dictionary)
   (make-local-variable 'dictionary-default-strategy)
 
-  (add-hook 'kill-buffer-hook 'dictionary-close t t)
+  (add-hook 'kill-buffer-hook #'dictionary-close t t)
   (run-hooks 'dictionary-mode-hook))
 
 ;;;###autoload
 (defun dictionary ()
-  "Create a new dictonary buffer and install `dictionary-mode'."
+  "Create a new dictionary buffer and install `dictionary-mode'."
   (interactive)
   (let ((buffer (or (and dictionary-use-single-buffer
                          (get-buffer "*Dictionary*"))
@@ -536,7 +535,7 @@ The connection takes the proxy setting in customization 
group
 ;; Dealing with closing the buffer
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
-(defun dictionary-close (&rest ignored)
+(defun dictionary-close (&rest _ignored)
   "Close the current dictionary buffer and its connection."
   (interactive)
   (if (eq major-mode 'dictionary-mode)
@@ -568,7 +567,7 @@ The connection takes the proxy setting in customization 
group
       answer)))
 
 (defun dictionary-split-string (string)
-  "Split STRING constiting of space-separated words into elements.
+  "Split STRING consisting of space-separated words into elements.
 This function knows about the special meaning of quotes (\")"
   (let ((list))
     (while (and string (> (length string) 0))
@@ -670,7 +669,7 @@ previous state."
   (setq dictionary-positions (cons (point) (window-start))))
 
 ;; Restore the previous state
-(defun dictionary-restore-state (&rest ignored)
+(defun dictionary-restore-state (&rest _ignored)
   "Restore the state just before the last operation."
   (let ((position (pop dictionary-position-stack))
        (data (pop dictionary-data-stack)))
@@ -722,13 +721,14 @@ of matching words."
     (if (dictionary-check-reply reply 552)
        (progn
          (unless nomatching
-           (beep)
-           (insert "Word not found, maybe you are looking "
-                   "for one of these words\n\n")
-           (dictionary-do-matching word
-                                   dictionary
-                                   "."
-                                   'dictionary-display-only-match-result)
+           (insert "Word not found")
+           (dictionary-do-matching
+             word
+            dictionary
+            "."
+            (lambda (reply)
+               (insert ", maybe you are looking for one of these words\n\n")
+               (dictionary-display-only-match-result reply)))
            (dictionary-post-buffer)))
       (if (dictionary-check-reply reply 550)
           (error "Dictionary \"%s\" is unknown, please select an existing one"
@@ -830,7 +830,7 @@ The DICTIONARY is only used for decoding the bytes to 
display the DESCRIPTION."
 (defun dictionary-display-word-definition (reply word dictionary)
   "Insert the definition in REPLY for the current WORD from DICTIONARY.
 It will replace links which are found in the REPLY and replace
-them with buttons to perform a a new search."
+them with buttons to perform a new search."
   (let ((start (point)))
     (insert (dictionary-decode-charset reply dictionary))
     (insert "\n\n")
@@ -873,7 +873,7 @@ The word is taken from the buffer, the DICTIONARY is given 
as argument."
                    'help-echo (concat "Press Mouse-2 to lookup \""
                                       word "\" in \"" dictionary "\"")))))
 
-(defun dictionary-select-dictionary (&rest ignored)
+(defun dictionary-select-dictionary (&rest _ignored)
   "Save the current state and start a dictionary selection."
   (interactive)
   (dictionary-ensure-buffer)
@@ -881,7 +881,7 @@ The word is taken from the buffer, the DICTIONARY is given 
as argument."
   (dictionary-do-select-dictionary)
   (dictionary-store-state 'dictionary-do-select-dictionary nil))
 
-(defun dictionary-do-select-dictionary (&rest ignored)
+(defun dictionary-do-select-dictionary (&rest _ignored)
   "The workhorse for doing the dictionary selection."
 
   (message "Looking up databases and descriptions")
@@ -894,7 +894,7 @@ The word is taken from the buffer, the DICTIONARY is given 
as argument."
       (unless (dictionary-check-reply reply 110)
        (error "Unknown server answer: %s"
               (dictionary-reply reply)))
-      (dictionary-display-dictionarys))))
+      (dictionary-display-dictionaries))))
 
 (defun dictionary-simple-split-string (string &optional pattern)
   "Return a list of substrings of STRING which are separated by PATTERN.
@@ -909,7 +909,7 @@ If PATTERN is omitted, it defaults to \"[ 
\\f\\t\\n\\r\\v]+\"."
            start (match-end 0)))
     (nreverse (cons (substring string start) parts))))
 
-(defun dictionary-display-dictionarys ()
+(defun dictionary-display-dictionaries ()
   "Handle the display of all dictionaries existing on the server."
   (dictionary-pre-buffer)
   (insert "Please select your default dictionary:\n\n")
@@ -917,7 +917,7 @@ If PATTERN is omitted, it defaults to \"[ 
\\f\\t\\n\\r\\v]+\"."
   (dictionary-display-dictionary-line "! \"The first matching dictionary\"")
   (let* ((reply (dictionary-read-answer))
         (list (dictionary-simple-split-string reply "\n+")))
-    (mapc 'dictionary-display-dictionary-line list))
+    (mapc #'dictionary-display-dictionary-line list))
   (dictionary-post-buffer))
 
 (defun dictionary-display-dictionary-line (string)
@@ -985,7 +985,7 @@ If PATTERN is omitted, it defaults to \"[ 
\\f\\t\\n\\r\\v]+\"."
 
       (dictionary-store-state 'dictionary-display-more-info dictionary))))
 
-(defun dictionary-select-strategy (&rest ignored)
+(defun dictionary-select-strategy (&rest _ignored)
   "Save the current state and start a strategy selection."
   (interactive)
   (dictionary-ensure-buffer)
@@ -1015,7 +1015,7 @@ If PATTERN is omitted, it defaults to \"[ 
\\f\\t\\n\\r\\v]+\"."
   (dictionary-display-strategy-line ". \"The servers default\"")
   (let* ((reply (dictionary-read-answer))
         (list (dictionary-simple-split-string reply "\n+")))
-    (mapc 'dictionary-display-strategy-line list))
+    (mapc #'dictionary-display-strategy-line list))
   (dictionary-post-buffer))
 
 (defun dictionary-display-strategy-line (string)
@@ -1031,7 +1031,7 @@ If PATTERN is omitted, it defaults to \"[ 
\\f\\t\\n\\r\\v]+\"."
                          'help-echo (purecopy "Mouse-2 to select this matching 
algorithm"))
          (insert "\n")))))
 
-(defun dictionary-set-strategy (strategy &rest ignored)
+(defun dictionary-set-strategy (strategy &rest _ignored)
   "Select this STRATEGY as new default."
   (setq dictionary-default-strategy strategy)
   (dictionary-restore-state)
@@ -1075,7 +1075,6 @@ If PATTERN is omitted, it defaults to \"[ 
\\f\\t\\n\\r\\v]+\"."
 
 (defun dictionary-display-only-match-result (reply)
   "Display the results from the current matches in REPLY without the headers."
-
   (let ((number (nth 1 (dictionary-reply-list reply)))
        (list (dictionary-simple-split-string (dictionary-read-answer) "\n+")))
     (insert number " matching word" (if (equal number "1") "" "s")
@@ -1171,7 +1170,7 @@ allows editing it."
   ;; if called by pressing the button
   (unless word
     (setq word (read-string "Search word: " nil 'dictionary-word-history)))
-  ;; just in case non-interactivly called
+  ;; just in case non-interactively called
   (unless dictionary
     (setq dictionary dictionary-default-dictionary))
   (dictionary-new-search (cons word dictionary)))
@@ -1195,7 +1194,7 @@ allows editing it."
   (describe-function 'dictionary-mode))
 
 ;;;###autoload
-(defun dictionary-match-words (&optional pattern &rest ignored)
+(defun dictionary-match-words (&optional pattern &rest _ignored)
   "Search PATTERN in current default dictionary using default strategy."
   (interactive)
   ;; can't use interactive because of mouse events
@@ -1249,10 +1248,10 @@ allows editing it."
 
 ;;; Tooltip support
 
-;; Add a mode indicater named "Dict"
+;; Add a mode indicator named "Dict"
 (defvar dictionary-tooltip-mode
   nil
-  "Indicates wheather the dictionary tooltip mode is active.")
+  "Indicates whether the dictionary tooltip mode is active.")
 (nconc minor-mode-alist '((dictionary-tooltip-mode " Dict")))
 
 (defcustom dictionary-tooltip-dictionary
@@ -1271,7 +1270,7 @@ allows editing it."
 
 (defun dictionary-read-definition (&ignore)
   (let ((list (dictionary-simple-split-string (dictionary-read-answer) "\n+")))
-    (mapconcat 'identity (cdr list) "\n")))
+    (mapconcat #'identity (cdr list) "\n")))
 
 ;;; Tooltip support for GNU Emacs
 (defvar global-dictionary-tooltip-mode
@@ -1323,8 +1322,8 @@ will be set to nil."
   (interactive)
   (tooltip-mode on)
   (if on
-      (add-hook 'tooltip-functions 'dictionary-display-tooltip)
-    (remove-hook 'tooltip-functions 'dictionary-display-tooltip)))
+      (add-hook 'tooltip-functions #'dictionary-display-tooltip)
+    (remove-hook 'tooltip-functions #'dictionary-display-tooltip)))
 
 ;;;###autoload
 (defun dictionary-tooltip-mode (&optional arg)
@@ -1365,9 +1364,8 @@ any buffer where (dictionary-tooltip-mode 1) has been 
called."
     (make-local-variable 'dictionary-tooltip-mouse-event)
     (setq-default track-mouse on)
     (dictionary-switch-tooltip-mode 1)
-    (if on
-        (global-set-key [mouse-movement] 'dictionary-tooltip-track-mouse)
-      (global-set-key [mouse-movement] 'ignore))
+    (global-set-key [mouse-movement]
+                    (if on #'dictionary-tooltip-track-mouse #'ignore))
     on))
 
 (provide 'dictionary)
diff --git a/lisp/net/dig.el b/lisp/net/dig.el
index 92dcf73..ddbfb95 100644
--- a/lisp/net/dig.el
+++ b/lisp/net/dig.el
@@ -79,7 +79,7 @@ and is a commonly available debugging tool."
     (push domain cmdline)
     (if server (push (concat "@" server) cmdline)
       (if dig-dns-server (push (concat "@" dig-dns-server) cmdline)))
-    (apply 'call-process dig-program nil buf nil cmdline)
+    (apply #'call-process dig-program nil buf nil cmdline)
     buf))
 
 (defun dig-extract-rr (domain &optional type class)
@@ -120,7 +120,7 @@ Buffer should contain output generated by `dig-invoke'."
 (defvar dig-mode-map
   (let ((map (make-sparse-keymap)))
     (define-key map "g" nil)
-    (define-key map "q" 'dig-exit)
+    (define-key map "q" #'dig-exit)
     map))
 
 (define-derived-mode dig-mode special-mode "Dig"
diff --git a/lisp/net/dns.el b/lisp/net/dns.el
index 2045d4d..1086bab 100644
--- a/lisp/net/dns.el
+++ b/lisp/net/dns.el
@@ -135,8 +135,8 @@ updated.  Set this variable to t to disable the check.")
     (if (stringp ended)
        (if (null name)
            ended
-         (concat (mapconcat 'identity (nreverse name) ".") "." ended))
-      (mapconcat 'identity (nreverse name) "."))))
+         (concat (mapconcat #'identity (nreverse name) ".") "." ended))
+      (mapconcat #'identity (nreverse name) "."))))
 
 (defun dns-write (spec &optional tcp-p)
   "Write a DNS packet according to SPEC.
@@ -283,7 +283,7 @@ If TCP-P, the first two bytes of the packet will be the 
length field."
             (let ((bytes nil))
               (dotimes (_ 4)
                 (push (dns-read-bytes 1) bytes))
-              (mapconcat 'number-to-string (nreverse bytes) ".")))
+              (mapconcat #'number-to-string (nreverse bytes) ".")))
            ((eq type 'AAAA)
             (let (hextets)
               (dotimes (_ 8)
@@ -332,7 +332,7 @@ Parses \"/etc/resolv.conf\" or calls \"nslookup\"."
          (setq dns-servers (nreverse dns-servers))))
       (when (executable-find "nslookup")
        (with-temp-buffer
-         (call-process "nslookup" nil t nil "localhost")
+         (call-process "nslookup" nil t nil "-retry=0" "-timeout=2" 
"localhost")
          (goto-char (point-min))
           (when (re-search-forward
           "^Address:[ 
\t]*\\([0-9]+\\.[0-9]+\\.[0-9]+\\.[0-9]+\\|[[:xdigit:]:]*\\)" nil t)
@@ -386,7 +386,7 @@ If REVERSE, look up an IP address."
 
   (when reverse
     (setq name (concat
-               (mapconcat 'identity (nreverse (split-string name "\\.")) ".")
+               (mapconcat #'identity (nreverse (split-string name "\\.")) ".")
                ".in-addr.arpa")
          type 'PTR))
 
@@ -492,19 +492,22 @@ If REVERSE, look up an IP address."
                            (dns-get-txt-answer (dns-get 'answers result))
                          (dns-get 'data answer))))))))))
 
+;;;###autoload
 (defun dns-query (name &optional type full reverse)
   "Query a DNS server for NAME of TYPE.
 If FULL, return the entire record returned.
 If REVERSE, look up an IP address."
-  (let ((result nil))
-    (dns-query-asynchronous
-     name
-     (lambda (response)
-       (setq result (list response)))
-     type full reverse)
-    ;; Loop until we get the callback.
-    (while (not result)
-      (sleep-for 0.01))
+  (let* ((result nil)
+         (query-started
+          (dns-query-asynchronous
+           name
+           (lambda (response)
+             (setq result (list response)))
+           type full reverse)))
+    (if query-started
+        ;; Loop until we get the callback.
+        (while (not result)
+          (sleep-for 0.01)))
     (car result)))
 
 (provide 'dns)
diff --git a/lisp/net/eudc-bob.el b/lisp/net/eudc-bob.el
index 456d70e..1d7af7f 100644
--- a/lisp/net/eudc-bob.el
+++ b/lisp/net/eudc-bob.el
@@ -41,38 +41,38 @@
 
 (defvar eudc-bob-generic-keymap
   (let ((map (make-sparse-keymap)))
-    (define-key map "s" 'eudc-bob-save-object)
-    (define-key map "!" 'eudc-bob-pipe-object-to-external-program)
-    (define-key map [down-mouse-3] 'eudc-bob-popup-menu)
+    (define-key map "s" #'eudc-bob-save-object)
+    (define-key map "!" #'eudc-bob-pipe-object-to-external-program)
+    (define-key map [down-mouse-3] #'eudc-bob-popup-menu)
     map)
   "Keymap for multimedia objects.")
 
 (defvar eudc-bob-image-keymap
   (let ((map (make-sparse-keymap)))
     (set-keymap-parent map eudc-bob-generic-keymap)
-    (define-key map "t" 'eudc-bob-toggle-inline-display)
+    (define-key map "t" #'eudc-bob-toggle-inline-display)
     map)
   "Keymap for inline images.")
 
 (defvar eudc-bob-sound-keymap
   (let ((map (make-sparse-keymap)))
     (set-keymap-parent map eudc-bob-generic-keymap)
-    (define-key map (kbd "RET") 'eudc-bob-play-sound-at-point)
-    (define-key map [down-mouse-2] 'eudc-bob-play-sound-at-mouse)
+    (define-key map (kbd "RET") #'eudc-bob-play-sound-at-point)
+    (define-key map [down-mouse-2] #'eudc-bob-play-sound-at-mouse)
     map)
   "Keymap for inline sounds.")
 
 (defvar eudc-bob-url-keymap
   (let ((map (make-sparse-keymap)))
-    (define-key map (kbd "RET") 'browse-url-at-point)
-    (define-key map [down-mouse-2] 'browse-url-at-mouse)
+    (define-key map (kbd "RET") #'browse-url-at-point)
+    (define-key map [down-mouse-2] #'browse-url-at-mouse)
     map)
   "Keymap for inline urls.")
 
 (defvar eudc-bob-mail-keymap
   (let ((map (make-sparse-keymap)))
-    (define-key map (kbd "RET") 'goto-address-at-point)
-    (define-key map [down-mouse-2] 'goto-address-at-point)
+    (define-key map (kbd "RET") #'goto-address-at-point)
+    (define-key map [down-mouse-2] #'goto-address-at-point)
     map)
   "Keymap for inline e-mail addresses.")
 
diff --git a/lisp/net/eudc-export.el b/lisp/net/eudc-export.el
index bac75e6..66db781 100644
--- a/lisp/net/eudc-export.el
+++ b/lisp/net/eudc-export.el
@@ -1,4 +1,4 @@
-;;; eudc-export.el --- functions to export EUDC query results
+;;; eudc-export.el --- functions to export EUDC query results  -*- 
lexical-binding: t; -*-
 
 ;; Copyright (C) 1998-2021 Free Software Foundation, Inc.
 
@@ -35,6 +35,7 @@
 ;; NOERROR is so we can compile it.
 (require 'bbdb nil t)
 (require 'bbdb-com nil t)
+(require 'cl-lib)
 
 (defun eudc-create-bbdb-record (record &optional silent)
   "Create a BBDB record using the RECORD alist.
@@ -42,24 +43,22 @@ RECORD is an alist of (KEY . VALUE) where KEY is a 
directory attribute name
 symbol and VALUE is the corresponding value for the record.
 If SILENT is non-nil then the created BBDB record is not displayed."
   (require 'bbdb)
+  (declare-function bbdb-create-internal "bbdb-com" (&rest spec))
+  (declare-function bbdb-display-records "bbdb"
+                    (records &optional layout append))
   ;; This function runs in a special context where lisp symbols corresponding
   ;; to field names in record are bound to the corresponding values
-  (eval
-   `(let* (,@(mapcar (lambda (c)
-                       (list (car c) (if (listp (cdr c))
-                                         (list 'quote (cdr c))
-                                       (cdr c))))
-                    record)
-            bbdb-name
-            bbdb-company
-            bbdb-net
-            bbdb-address
-            bbdb-phones
-            bbdb-notes
-            spec
-            bbdb-record
-            value
-            (conversion-alist (symbol-value eudc-bbdb-conversion-alist)))
+  (cl-progv (mapcar #'car record) (mapcar #'cdr record)
+    (let* (bbdb-name
+          bbdb-company
+          bbdb-net
+          bbdb-address
+          bbdb-phones
+          bbdb-notes
+          spec
+          bbdb-record
+          value
+          (conversion-alist (symbol-value eudc-bbdb-conversion-alist)))
 
       ;; BBDB standard fields
       (setq bbdb-name (eudc-parse-spec (cdr (assq 'name conversion-alist)) 
record nil)
@@ -68,14 +67,14 @@ If SILENT is non-nil then the created BBDB record is not 
displayed."
            bbdb-notes (eudc-parse-spec (cdr (assq 'notes conversion-alist)) 
record nil))
       (setq spec (cdr (assq 'address conversion-alist)))
       (setq bbdb-address (delq nil (eudc-parse-spec (if (listp (car spec))
-                                                     spec
-                                                   (list spec))
-                                                 record t)))
+                                                       spec
+                                                     (list spec))
+                                                   record t)))
       (setq spec (cdr (assq 'phone conversion-alist)))
       (setq bbdb-phones (delq nil (eudc-parse-spec (if (listp (car spec))
-                                                    spec
-                                                  (list spec))
-                                                record t)))
+                                                      spec
+                                                    (list spec))
+                                                  record t)))
       ;; BBDB custom fields
       (setq bbdb-notes (append (list (and bbdb-notes (cons 'notes bbdb-notes)))
                                (mapcar (lambda (mapping)
@@ -85,19 +84,20 @@ If SILENT is non-nil then the created BBDB record is not 
displayed."
                                              (cons (car mapping) value)))
                                       conversion-alist)))
       (setq bbdb-notes (delq nil bbdb-notes))
-      (setq bbdb-record (bbdb-create-internal
-                        bbdb-name
-                        ,@(when (eudc--using-bbdb-3-or-newer-p)
-                            '(nil
-                              nil))
-                        bbdb-company
-                        bbdb-net
-                        ,@(if (eudc--using-bbdb-3-or-newer-p)
-                              '(bbdb-phones
-                                bbdb-address)
-                            '(bbdb-address
-                              bbdb-phones))
-                        bbdb-notes))
+      (setq bbdb-record
+           (apply #'bbdb-create-internal
+                  `(,bbdb-name
+                    ,@(when (eudc--using-bbdb-3-or-newer-p)
+                        '(nil
+                          nil))
+                    ,bbdb-company
+                    ,bbdb-net
+                    ,@(if (eudc--using-bbdb-3-or-newer-p)
+                          (list bbdb-phones
+                                bbdb-address)
+                        (list bbdb-address
+                              bbdb-phones))
+                    ,bbdb-notes)))
       (or silent
          (bbdb-display-records (list bbdb-record))))))
 
@@ -111,7 +111,7 @@ If RECURSE is non-nil then SPEC may be a list of atomic 
specs."
             (symbolp (car spec))
             (fboundp (car spec))))
     (condition-case nil
-       (eval spec)
+       (eval spec t)
       (void-variable nil)))
    ((and recurse
         (listp spec))
@@ -194,9 +194,9 @@ LOCATION is used as the phone location for BBDB."
           (signal (car err) (cdr err)))))
       (if (= 3 (length phone-list))
          (setq phone-list (append phone-list '(nil))))
-      (apply 'vector location phone-list)))
+      (apply #'vector location phone-list)))
    ((listp phone)
-    (vector location (mapconcat 'identity phone ", ")))
+    (vector location (mapconcat #'identity phone ", ")))
    (t
     (error "Invalid phone specification"))))
 
diff --git a/lisp/net/eudc-hotlist.el b/lisp/net/eudc-hotlist.el
index e4b7e8a..a737a99 100644
--- a/lisp/net/eudc-hotlist.el
+++ b/lisp/net/eudc-hotlist.el
@@ -1,4 +1,4 @@
-;;; eudc-hotlist.el --- hotlist management for EUDC
+;;; eudc-hotlist.el --- hotlist management for EUDC  -*- lexical-binding: t; 
-*-
 
 ;; Copyright (C) 1998-2021 Free Software Foundation, Inc.
 
@@ -37,12 +37,12 @@
 
 (defvar eudc-hotlist-mode-map
   (let ((map (make-sparse-keymap)))
-    (define-key map "a" 'eudc-hotlist-add-server)
-    (define-key map "d" 'eudc-hotlist-delete-server)
-    (define-key map "s" 'eudc-hotlist-select-server)
-    (define-key map "t" 'eudc-hotlist-transpose-servers)
-    (define-key map "q" 'eudc-hotlist-quit-edit)
-    (define-key map "x" 'kill-current-buffer)
+    (define-key map "a" #'eudc-hotlist-add-server)
+    (define-key map "d" #'eudc-hotlist-delete-server)
+    (define-key map "s" #'eudc-hotlist-select-server)
+    (define-key map "t" #'eudc-hotlist-transpose-servers)
+    (define-key map "q" #'eudc-hotlist-quit-edit)
+    (define-key map "x" #'kill-current-buffer)
     map))
 
 (define-derived-mode eudc-hotlist-mode fundamental-mode "EUDC-Servers"
diff --git a/lisp/net/eudc.el b/lisp/net/eudc.el
index f61929c..c112d27 100644
--- a/lisp/net/eudc.el
+++ b/lisp/net/eudc.el
@@ -49,10 +49,6 @@
 
 (require 'cl-lib)
 
-(eval-and-compile
-  (if (not (fboundp 'make-overlay))
-      (require 'overlay)))
-
 (unless (fboundp 'custom-menu-create)
   (autoload 'custom-menu-create "cus-edit"))
 
@@ -69,12 +65,12 @@
 (defvar eudc-mode-map
   (let ((map (make-sparse-keymap)))
     (set-keymap-parent map widget-keymap)
-    (define-key map "q" 'kill-current-buffer)
-    (define-key map "x" 'kill-current-buffer)
-    (define-key map "f" 'eudc-query-form)
-    (define-key map "b" 'eudc-try-bbdb-insert)
-    (define-key map "n" 'eudc-move-to-next-record)
-    (define-key map "p" 'eudc-move-to-previous-record)
+    (define-key map "q" #'kill-current-buffer)
+    (define-key map "x" #'kill-current-buffer)
+    (define-key map "f" #'eudc-query-form)
+    (define-key map "b" #'eudc-try-bbdb-insert)
+    (define-key map "n" #'eudc-move-to-next-record)
+    (define-key map "p" #'eudc-move-to-previous-record)
     map))
 
 (defvar mode-popup-menu)
@@ -411,7 +407,7 @@ if any, is called to print the value in cdr of FIELD."
        (val (cdr field)))
     (if match
        (progn
-         (eval (list (cdr match) val))
+         (funcall (cdr match) val)
          (insert "\n"))
       (mapc
        (lambda (val-elem)
@@ -1056,8 +1052,6 @@ queries the server for the existing fields and displays a 
corresponding form."
 
 ;;{{{      Menus and keymaps
 
-(require 'easymenu)
-
 (defconst eudc-custom-generated-menu (cdr (custom-menu-create 'eudc)))
 
 (defconst eudc-tail-menu
diff --git a/lisp/net/eudcb-bbdb.el b/lisp/net/eudcb-bbdb.el
index e11458b..e241a1c 100644
--- a/lisp/net/eudcb-bbdb.el
+++ b/lisp/net/eudcb-bbdb.el
@@ -1,4 +1,4 @@
-;;; eudcb-bbdb.el --- Emacs Unified Directory Client - BBDB Backend
+;;; eudcb-bbdb.el --- Emacs Unified Directory Client - BBDB Backend  -*- 
lexical-binding: t; -*-
 
 ;; Copyright (C) 1998-2021 Free Software Foundation, Inc.
 
@@ -34,6 +34,7 @@
 ;; Make it loadable on systems without bbdb.
 (require 'bbdb nil t)
 (require 'bbdb-com nil t)
+(require 'seq)
 
 ;;{{{      Internal cooking
 
@@ -87,33 +88,30 @@ BBDB < 3 used `net'; BBDB >= 3 uses `mail'."
   "Return RECORD if it matches `eudc-bbdb-current-query', nil otherwise."
   (require 'bbdb)
   (catch 'unmatch
-    (progn
-      (dolist (condition eudc-bbdb-current-query)
-        (let ((attr (car condition))
-              (val (cdr condition))
-              (case-fold-search t)
-              bbdb-val)
-          (or (and (memq attr '(firstname lastname aka company phones
-                                addresses net))
-                   (progn
-                     (setq bbdb-val
-                           (eval (list (intern (concat "bbdb-record-"
-                                                       (symbol-name
-                                                        (eudc-bbdb-field
-                                                         attr))))
-                                       'record)))
-                     (if (listp bbdb-val)
-                         (if eudc-bbdb-enable-substring-matches
-                             (eval `(or ,@(mapcar (lambda (subval)
-                                                    (string-match val subval))
-                                                  bbdb-val)))
-                           (member (downcase val)
-                                   (mapcar 'downcase bbdb-val)))
+    (dolist (condition eudc-bbdb-current-query)
+      (let ((attr (car condition))
+            (val (cdr condition))
+            (case-fold-search t))
+        (or (and (memq attr '(firstname lastname aka company phones
+                              addresses net))
+                 (let ((bbdb-val
+                        (funcall (intern (concat "bbdb-record-"
+                                                 (symbol-name
+                                                  (eudc-bbdb-field
+                                                   attr))))
+                                 record)))
+                   (if (listp bbdb-val)
                        (if eudc-bbdb-enable-substring-matches
-                           (string-match val bbdb-val)
-                         (string-equal (downcase val) (downcase bbdb-val))))))
-              (throw 'unmatch nil))))
-      record)))
+                           (seq-some (lambda (subval)
+                                       (string-match val subval))
+                                     bbdb-val)
+                         (member (downcase val)
+                                 (mapcar #'downcase bbdb-val)))
+                     (if eudc-bbdb-enable-substring-matches
+                         (string-match val bbdb-val)
+                       (string-equal (downcase val) (downcase bbdb-val))))))
+            (throw 'unmatch nil))))
+    record))
 
 ;; External.
 (declare-function bbdb-phone-location   "ext:bbdb" t) ; via bbdb-defstruct
@@ -182,40 +180,34 @@ The record is filtered according to 
`eudc-bbdb-current-return-attributes'."
   (require 'bbdb)
   (let ((attrs (or eudc-bbdb-current-return-attributes
                   '(firstname lastname aka company phones addresses net 
notes)))
-       attr
-       eudc-rec
-       val)
-    (while (prog1
-              (setq attr (car attrs))
-            (setq attrs (cdr attrs)))
-      (cond
-       ((eq attr 'phones)
-       (setq val (eudc-bbdb-extract-phones record)))
-       ((eq attr 'addresses)
-       (setq val (eudc-bbdb-extract-addresses record)))
-       ((eq attr 'notes)
-        (if (eudc--using-bbdb-3-or-newer-p)
-            (setq val (bbdb-record-xfield record 'notes))
-          (setq val (bbdb-record-notes record))))
-       ((memq attr '(firstname lastname aka company net))
-       (setq val (eval
-                  (list (intern
-                         (concat "bbdb-record-"
-                                 (symbol-name (eudc-bbdb-field attr))))
-                        'record))))
-       (t
-       (error "Unknown BBDB attribute")))
-      (cond
-       ((or (not val) (equal val ""))) ; do nothing
-       ((memq attr '(phones addresses))
-       (setq eudc-rec (append val eudc-rec)))
-       ((and (listp val)
-            (= 1 (length val)))
-       (setq eudc-rec (cons (cons attr (car val)) eudc-rec)))
-       ((> (length val) 0)
-       (setq eudc-rec (cons (cons attr val) eudc-rec)))
-       (t
-       (error "Unexpected attribute value"))))
+       eudc-rec)
+    (dolist (attr attrs)
+      (let ((val
+             (pcase attr
+              ('phones    (eudc-bbdb-extract-phones record))
+             ('addresses (eudc-bbdb-extract-addresses record))
+             ('notes
+               (if (eudc--using-bbdb-3-or-newer-p)
+                   (bbdb-record-xfield record 'notes)
+                 (bbdb-record-notes record)))
+              ((or 'firstname 'lastname 'aka 'company 'net)
+               (funcall (intern
+                        (concat "bbdb-record-"
+                                (symbol-name (eudc-bbdb-field attr))))
+                       record))
+             (_
+              (error "Unknown BBDB attribute")))))
+       (cond
+        ((or (not val) (equal val ""))) ; do nothing
+        ((memq attr '(phones addresses))
+         (setq eudc-rec (append val eudc-rec)))
+        ((and (listp val)
+              (= 1 (length val)))
+         (push (cons attr (car val)) eudc-rec))
+        ((> (length val) 0)
+         (push (cons attr val) eudc-rec))
+        (t
+         (error "Unexpected attribute value")))))
     (nreverse eudc-rec)))
 
 
@@ -240,21 +232,20 @@ RETURN-ATTRS is a list of attributes to return, 
defaulting to
     (while (and records (> (length query-attrs) 0))
       (setq bbdb-attrs (append bbdb-attrs (list (car query-attrs))))
       (if (car query-attrs)
-         (setq records (eval `(bbdb-search ,(quote records) ,@bbdb-attrs))))
+         ;; BEWARE: `bbdb-search' is a macro!
+         (setq records (eval `(bbdb-search records ,@bbdb-attrs) t)))
       (setq query-attrs (cdr query-attrs)))
     (mapc (lambda (record)
             (setq filtered (eudc-filter-duplicate-attributes record))
             ;; If there were duplicate attributes reverse the order of the
             ;; record so the unique attributes appear first
             (if (> (length filtered) 1)
-                (setq filtered (mapcar (lambda (rec)
-                                         (reverse rec))
-                                       filtered)))
+                (setq filtered (mapcar #'reverse filtered)))
             (setq result (append result filtered)))
          (delq nil
-               (mapcar 'eudc-bbdb-format-record-as-result
+               (mapcar #'eudc-bbdb-format-record-as-result
                        (delq nil
-                             (mapcar 'eudc-bbdb-filter-non-matching-record
+                             (mapcar #'eudc-bbdb-filter-non-matching-record
                                      records)))))
     result))
 
diff --git a/lisp/net/eudcb-ldap.el b/lisp/net/eudcb-ldap.el
index 4623079..0aff276 100644
--- a/lisp/net/eudcb-ldap.el
+++ b/lisp/net/eudcb-ldap.el
@@ -1,4 +1,4 @@
-;;; eudcb-ldap.el --- Emacs Unified Directory Client - LDAP Backend
+;;; eudcb-ldap.el --- Emacs Unified Directory Client - LDAP Backend  -*- 
lexical-binding: t; -*-
 
 ;; Copyright (C) 1998-2021 Free Software Foundation, Inc.
 
@@ -38,10 +38,10 @@
 
 ;;{{{      Internal cooking
 
-(eval-and-compile
+(defalias 'eudc-ldap-get-host-parameter
   (if (fboundp 'ldap-get-host-parameter)
-      (fset 'eudc-ldap-get-host-parameter 'ldap-get-host-parameter)
-    (defun eudc-ldap-get-host-parameter (host parameter)
+      #'ldap-get-host-parameter
+    (lambda (host parameter)
       "Get the value of PARAMETER for HOST in `ldap-host-parameters-alist'."
       (plist-get (cdr (assoc host ldap-host-parameters-alist))
                 parameter))))
@@ -84,7 +84,7 @@
    record))
 
 (defun eudc-filter-$ (string)
-  (mapconcat 'identity (split-string string "\\$") "\n"))
+  (mapconcat #'identity (split-string string "\\$") "\n"))
 
 (defun eudc-ldap-cleanup-record-filtering-addresses (record)
   "Clean up RECORD to make it suitable for EUDC.
@@ -104,7 +104,7 @@ multiple addresses."
            (value (cdr field)))
        (when (and clean-up-addresses
                   (memq name '(postaladdress registeredaddress)))
-         (setq value (mapcar 'eudc-filter-$ value)))
+         (setq value (mapcar #'eudc-filter-$ value)))
        (if (eq name 'mail)
            (setq mail-addresses (append mail-addresses value))
          (push (cons name (if (cdr value)
@@ -126,9 +126,9 @@ RETURN-ATTRS is a list of attributes to return, defaulting 
to
   (let ((result (ldap-search (eudc-ldap-format-query-as-rfc1558 query)
                             eudc-server
                             (if (listp return-attrs)
-                                (mapcar 'symbol-name return-attrs))))
+                                (mapcar #'symbol-name return-attrs))))
        final-result)
-    (setq result (mapcar 'eudc-ldap-cleanup-record-filtering-addresses result))
+    (setq result (mapcar #'eudc-ldap-cleanup-record-filtering-addresses 
result))
 
     (if (and eudc-strict-return-matches
             return-attrs
@@ -154,7 +154,7 @@ attribute names are returned.  Default to `person'."
   (let ((ldap-host-parameters-alist
         (list (cons eudc-server
                     '(scope subtree sizelimit 1)))))
-    (mapcar 'eudc-ldap-cleanup-record-filtering-addresses
+    (mapcar #'eudc-ldap-cleanup-record-filtering-addresses
            (ldap-search
             (eudc-ldap-format-query-as-rfc1558
              (list (cons "objectclass"
diff --git a/lisp/net/eudcb-mab.el b/lisp/net/eudcb-mab.el
index eb7032a..732881f 100644
--- a/lisp/net/eudcb-mab.el
+++ b/lisp/net/eudcb-mab.el
@@ -1,4 +1,4 @@
-;;; eudcb-mab.el --- Emacs Unified Directory Client - AddressBook backend
+;;; eudcb-mab.el --- Emacs Unified Directory Client - AddressBook backend  -*- 
lexical-binding: t; -*-
 
 ;; Copyright (C) 2003-2021 Free Software Foundation, Inc.
 
diff --git a/lisp/net/eudcb-macos-contacts.el b/lisp/net/eudcb-macos-contacts.el
index 66a684d..18c8958 100644
--- a/lisp/net/eudcb-macos-contacts.el
+++ b/lisp/net/eudcb-macos-contacts.el
@@ -1,4 +1,4 @@
-;;; eudcb-macos-contacts.el --- EUDC - macOS Contacts backend
+;;; eudcb-macos-contacts.el --- EUDC - macOS Contacts backend  -*- 
lexical-binding: t; -*-
 
 ;; Copyright (C) 2020-2021 Free Software Foundation, Inc.
 
@@ -74,7 +74,7 @@ end tell" str))
                     "`osascript' executable not found. "
                     "Is this is a macOS 10.0 or later system?"))))
 
-(defun eudc-macos-contacts-query-internal (query &optional return-attrs)
+(defun eudc-macos-contacts-query-internal (query &optional _return-attrs)
   "Query macOS Contacts with QUERY.
 QUERY is a list of cons cells (ATTR . VALUE) where ATTRs should be valid
 macOS Contacts attribute names.
@@ -108,7 +108,7 @@ RETURN-ATTRS is a list of attributes to return, defaulting 
to
 (defun eudc-macos-contacts-set-server (dummy)
   "Set the EUDC server to macOS Contacts app.
 The server in DUMMY is not actually used, since this backend
-always and implicitly connetcs to an instance of the Contacts app
+always and implicitly connects to an instance of the Contacts app
 running on the local host."
   (interactive)
   (eudc-set-server dummy 'macos-contacts)
diff --git a/lisp/net/eww.el b/lisp/net/eww.el
index e39a4c3..32fe857 100644
--- a/lisp/net/eww.el
+++ b/lisp/net/eww.el
@@ -855,7 +855,7 @@ Currently this means either text/html or 
application/xhtml+xml."
 
 (defun eww-view-source ()
   "View the HTML source code of the current page."
-  (interactive)
+  (interactive nil eww-mode)
   (let ((buf (get-buffer-create "*eww-source*"))
         (source (plist-get eww-data :source)))
     (with-current-buffer buf
@@ -881,7 +881,7 @@ Currently this means either text/html or 
application/xhtml+xml."
 
 (defun eww-toggle-paragraph-direction ()
   "Cycle the paragraph direction between left-to-right, right-to-left and 
auto."
-  (interactive)
+  (interactive nil eww-mode)
   (setq bidi-paragraph-direction
         (cond ((eq bidi-paragraph-direction 'left-to-right)
                nil)
@@ -899,7 +899,7 @@ Currently this means either text/html or 
application/xhtml+xml."
 This command uses heuristics to find the parts of the web page that
 contains the main textual portion, leaving out navigation menus and
 the like."
-  (interactive)
+  (interactive nil eww-mode)
   (let* ((old-data eww-data)
         (dom (with-temp-buffer
                (insert (plist-get old-data :source))
@@ -1038,6 +1038,7 @@ the like."
 ;;;###autoload
 (define-derived-mode eww-mode special-mode "eww"
   "Mode for browsing the web."
+  :interactive nil
   (setq-local eww-data (list :title ""))
   (setq-local browse-url-browser-function #'eww-browse-url)
   (add-hook 'after-change-functions #'eww-process-text-input nil t)
@@ -1090,7 +1091,7 @@ instead of `browse-url-new-window-flag'."
 
 (defun eww-back-url ()
   "Go to the previously displayed page."
-  (interactive)
+  (interactive nil eww-mode)
   (when (>= eww-history-position (length eww-history))
     (user-error "No previous page"))
   (eww-save-history)
@@ -1099,7 +1100,7 @@ instead of `browse-url-new-window-flag'."
 
 (defun eww-forward-url ()
   "Go to the next displayed page."
-  (interactive)
+  (interactive nil eww-mode)
   (when (zerop eww-history-position)
     (user-error "No next page"))
   (eww-save-history)
@@ -1123,7 +1124,7 @@ instead of `browse-url-new-window-flag'."
   "Go to the page marked `next'.
 A page is marked `next' if rel=\"next\" appears in a <link>
 or <a> tag."
-  (interactive)
+  (interactive nil eww-mode)
   (if (plist-get eww-data :next)
       (eww-browse-url (shr-expand-url (plist-get eww-data :next)
                                      (plist-get eww-data :url)))
@@ -1133,7 +1134,7 @@ or <a> tag."
   "Go to the page marked `previous'.
 A page is marked `previous' if rel=\"previous\" appears in a <link>
 or <a> tag."
-  (interactive)
+  (interactive nil eww-mode)
   (if (plist-get eww-data :previous)
       (eww-browse-url (shr-expand-url (plist-get eww-data :previous)
                                      (plist-get eww-data :url)))
@@ -1143,7 +1144,7 @@ or <a> tag."
   "Go to the page marked `up'.
 A page is marked `up' if rel=\"up\" appears in a <link>
 or <a> tag."
-  (interactive)
+  (interactive nil eww-mode)
   (if (plist-get eww-data :up)
       (eww-browse-url (shr-expand-url (plist-get eww-data :up)
                                      (plist-get eww-data :url)))
@@ -1153,7 +1154,7 @@ or <a> tag."
   "Go to the page marked `top'.
 A page is marked `top' if rel=\"start\", rel=\"home\", or rel=\"contents\"
 appears in a <link> or <a> tag."
-  (interactive)
+  (interactive nil eww-mode)
   (let ((best-url (or (plist-get eww-data :start)
                      (plist-get eww-data :contents)
                      (plist-get eww-data :home))))
@@ -1166,7 +1167,7 @@ appears in a <link> or <a> tag."
 If LOCAL is non-nil (interactively, the command was invoked with
 a prefix argument), don't reload the page from the network, but
 just re-display the HTML already fetched."
-  (interactive "P")
+  (interactive "P" eww-mode)
   (let ((url (plist-get eww-data :url)))
     (if local
        (if (null (plist-get eww-data :dom))
@@ -1232,12 +1233,12 @@ just re-display the HTML already fetched."
 
 (defun eww-beginning-of-text ()
   "Move to the start of the input field."
-  (interactive)
+  (interactive nil eww-mode)
   (goto-char (eww-beginning-of-field)))
 
 (defun eww-end-of-text ()
   "Move to the end of the text in the input field."
-  (interactive)
+  (interactive nil eww-mode)
   (goto-char (eww-end-of-field))
   (let ((start (eww-beginning-of-field)))
     (while (and (equal (following-char) ? )
@@ -1329,7 +1330,7 @@ just re-display the HTML already fetched."
 
 (defun eww-select-file ()
   "Change the value of the upload file menu under point."
-  (interactive)
+  (interactive nil eww-mode)
   (let*  ((input (get-text-property (point) 'eww-form)))
     (let ((filename
           (let ((insert-default-directory t))
@@ -1537,7 +1538,9 @@ See URL 
`https://developer.mozilla.org/en-US/docs/Web/HTML/Element/Input'.")
 
 (defun eww-change-select (event)
   "Change the value of the select drop-down menu under point."
-  (interactive (list last-nonmenu-event))
+  (interactive
+   (list last-nonmenu-event)
+   eww-mode)
   (mouse-set-point event)
   (let ((input (get-text-property (point) 'eww-form)))
     (popup-menu
@@ -1572,7 +1575,7 @@ See URL 
`https://developer.mozilla.org/en-US/docs/Web/HTML/Element/Input'.")
 
 (defun eww-toggle-checkbox ()
   "Toggle the value of the checkbox under point."
-  (interactive)
+  (interactive nil eww-mode)
   (let* ((input (get-text-property (point) 'eww-form))
         (type (plist-get input :type)))
     (if (equal type "checkbox")
@@ -1592,9 +1595,9 @@ See URL 
`https://developer.mozilla.org/en-US/docs/Web/HTML/Element/Input'.")
              (goto-char (car elem))
              (if (not (eq (cdr elem) input))
                  (progn
-                   (plist-put input :checked nil)
+                   (plist-put (cdr elem) :checked nil)
                    (eww-update-field eww-form-checkbox-symbol))
-               (plist-put input :checked t)
+               (plist-put (cdr elem) :checked t)
                (eww-update-field eww-form-checkbox-selected-symbol)))))
        (forward-char 1)))))
 
@@ -1642,7 +1645,7 @@ See URL 
`https://developer.mozilla.org/en-US/docs/Web/HTML/Element/Input'.")
 
 (defun eww-submit ()
   "Submit the current form."
-  (interactive)
+  (interactive nil eww-mode)
   (let* ((this-input (get-text-property (point) 'eww-form))
         (form (plist-get this-input :eww-form))
         values next-submit)
@@ -1729,7 +1732,7 @@ See URL 
`https://developer.mozilla.org/en-US/docs/Web/HTML/Element/Input'.")
   "Browse the current URL with an external browser.
 The browser to used is specified by the
 `browse-url-secondary-browser-function' variable."
-  (interactive)
+  (interactive nil eww-mode)
   (funcall browse-url-secondary-browser-function
            (or url (plist-get eww-data :url))))
 
@@ -1739,7 +1742,9 @@ If EXTERNAL is single prefix, browse the URL using
 `browse-url-secondary-browser-function'.
 
 If EXTERNAL is double prefix, browse in new buffer."
-  (interactive (list current-prefix-arg last-nonmenu-event))
+  (interactive
+   (list current-prefix-arg last-nonmenu-event)
+   eww-mode)
   (mouse-set-point mouse-event)
   (let ((url (get-text-property (point) 'shr-url)))
     (cond
@@ -1773,14 +1778,14 @@ Differences in #targets are ignored."
 
 (defun eww-copy-page-url ()
   "Copy the URL of the current page into the kill ring."
-  (interactive)
+  (interactive nil eww-mode)
   (message "%s" (plist-get eww-data :url))
   (kill-new (plist-get eww-data :url)))
 
 (defun eww-download ()
   "Download URL to `eww-download-directory'.
 Use link at point if there is one, else the current page's URL."
-  (interactive)
+  (interactive nil eww-mode)
   (let ((dir (if (stringp eww-download-directory)
                  eww-download-directory
                (funcall eww-download-directory))))
@@ -1848,14 +1853,14 @@ Use link at point if there is one, else the current 
page's URL."
 (defun eww-set-character-encoding (charset)
   "Set character encoding to CHARSET.
 If CHARSET is nil then use UTF-8."
-  (interactive "zUse character set (default utf-8): ")
+  (interactive "zUse character set (default utf-8): " eww-mode)
   (if (null charset)
       (eww-reload nil 'utf-8)
     (eww-reload nil charset)))
 
 (defun eww-switch-to-buffer ()
   "Prompt for an EWW buffer to display in the selected window."
-  (interactive)
+  (interactive nil eww-mode)
   (let ((completion-extra-properties
          '(:annotation-function (lambda (buf)
                                   (with-current-buffer buf
@@ -1873,7 +1878,7 @@ If CHARSET is nil then use UTF-8."
 
 (defun eww-toggle-fonts ()
   "Toggle whether to use monospaced or font-enabled layouts."
-  (interactive)
+  (interactive nil eww-mode)
   (setq shr-use-fonts (not shr-use-fonts))
   (eww-reload)
   (message "Proportional fonts are now %s"
@@ -1881,7 +1886,7 @@ If CHARSET is nil then use UTF-8."
 
 (defun eww-toggle-colors ()
   "Toggle whether to use HTML-specified colors or not."
-  (interactive)
+  (interactive nil eww-mode)
   (message "Colors are now %s"
           (if (setq shr-use-colors (not shr-use-colors))
               "on"
@@ -1894,7 +1899,7 @@ If CHARSET is nil then use UTF-8."
 
 (defun eww-add-bookmark ()
   "Bookmark the current page."
-  (interactive)
+  (interactive nil eww-mode)
   (eww-read-bookmarks)
   (dolist (bookmark eww-bookmarks)
     (when (equal (plist-get eww-data :url) (plist-get bookmark :url))
@@ -1958,7 +1963,7 @@ If ERROR-OUT, signal user-error if there are no 
bookmarks."
 
 (defun eww-bookmark-kill ()
   "Kill the current bookmark."
-  (interactive)
+  (interactive nil eww-bookmark-mode)
   (let* ((start (line-beginning-position))
         (bookmark (get-text-property start 'eww-bookmark))
         (inhibit-read-only t))
@@ -1972,7 +1977,7 @@ If ERROR-OUT, signal user-error if there are no 
bookmarks."
 
 (defun eww-bookmark-yank ()
   "Yank a previously killed bookmark to the current line."
-  (interactive)
+  (interactive nil eww-bookmark-mode)
   (unless eww-bookmark-kill-ring
     (user-error "No previously killed bookmark"))
   (beginning-of-line)
@@ -1990,7 +1995,7 @@ If ERROR-OUT, signal user-error if there are no 
bookmarks."
 
 (defun eww-bookmark-browse ()
   "Browse the bookmark under point in eww."
-  (interactive)
+  (interactive nil eww-bookmark-mode)
   (let ((bookmark (get-text-property (line-beginning-position) 'eww-bookmark)))
     (unless bookmark
       (user-error "No bookmark on the current line"))
@@ -1999,7 +2004,7 @@ If ERROR-OUT, signal user-error if there are no 
bookmarks."
 
 (defun eww-next-bookmark ()
   "Go to the next bookmark in the list."
-  (interactive)
+  (interactive nil eww-bookmark-mode)
   (let ((first nil)
        bookmark)
     (unless (get-buffer "*eww bookmarks*")
@@ -2018,7 +2023,7 @@ If ERROR-OUT, signal user-error if there are no 
bookmarks."
 
 (defun eww-previous-bookmark ()
   "Go to the previous bookmark in the list."
-  (interactive)
+  (interactive nil eww-bookmark-mode)
   (let ((first nil)
        bookmark)
     (unless (get-buffer "*eww bookmarks*")
@@ -2061,6 +2066,7 @@ If ERROR-OUT, signal user-error if there are no 
bookmarks."
   "Mode for listing bookmarks.
 
 \\{eww-bookmark-mode-map}"
+  :interactive nil
   (buffer-disable-undo)
   (setq truncate-lines t))
 
@@ -2109,7 +2115,7 @@ If ERROR-OUT, signal user-error if there are no 
bookmarks."
 
 (defun eww-history-browse ()
   "Browse the history under point in eww."
-  (interactive)
+  (interactive nil eww-history-mode)
   (let ((history (get-text-property (line-beginning-position) 'eww-history)))
     (unless history
       (error "No history on the current line"))
@@ -2137,6 +2143,7 @@ If ERROR-OUT, signal user-error if there are no 
bookmarks."
   "Mode for listing eww-histories.
 
 \\{eww-history-mode-map}"
+  :interactive nil
   (buffer-disable-undo)
   (setq truncate-lines t))
 
@@ -2191,7 +2198,7 @@ If ERROR-OUT, signal user-error if there are no 
bookmarks."
 
 (defun eww-buffer-select ()
   "Switch to eww buffer."
-  (interactive)
+  (interactive nil eww-buffers-mode)
   (let ((buffer (get-text-property (line-beginning-position)
                                    'eww-buffer)))
     (unless buffer
@@ -2211,7 +2218,7 @@ If ERROR-OUT, signal user-error if there are no 
bookmarks."
 
 (defun eww-buffer-show-next ()
   "Move to next eww buffer in the list and display it."
-  (interactive)
+  (interactive nil eww-buffers-mode)
   (forward-line)
   (when (eobp)
     (goto-char (point-min)))
@@ -2219,7 +2226,7 @@ If ERROR-OUT, signal user-error if there are no 
bookmarks."
 
 (defun eww-buffer-show-previous ()
   "Move to previous eww buffer in the list and display it."
-  (interactive)
+  (interactive nil eww-buffers-mode)
   (beginning-of-line)
   (when (bobp)
     (goto-char (point-max)))
@@ -2228,7 +2235,7 @@ If ERROR-OUT, signal user-error if there are no 
bookmarks."
 
 (defun eww-buffer-kill ()
   "Kill buffer from eww list."
-  (interactive)
+  (interactive nil eww-buffers-mode)
   (let* ((start (line-beginning-position))
         (buffer (get-text-property start 'eww-buffer))
         (inhibit-read-only t))
@@ -2262,6 +2269,7 @@ If ERROR-OUT, signal user-error if there are no 
bookmarks."
   "Mode for listing buffers.
 
 \\{eww-buffers-mode-map}"
+  :interactive nil
   (buffer-disable-undo)
   (setq truncate-lines t))
 
diff --git a/lisp/net/gnutls.el b/lisp/net/gnutls.el
index ff58cbb..683abaa 100644
--- a/lisp/net/gnutls.el
+++ b/lisp/net/gnutls.el
@@ -1,10 +1,10 @@
-;;; gnutls.el --- Support SSL/TLS connections through GnuTLS
+;;; gnutls.el --- Support SSL/TLS connections through GnuTLS  -*- 
lexical-binding: t; -*-
 
 ;; Copyright (C) 2010-2021 Free Software Foundation, Inc.
 
 ;; Author: Ted Zlatanov <tzz@lifelogs.com>
 ;; Keywords: comm, tls, ssl, encryption
-;; Originally-By: Simon Josefsson (See http://josefsson.org/emacs-security/)
+;; Originally-By: Simon Josefsson (See https://josefsson.org/emacs-security/)
 ;; Thanks-To: Lars Magne Ingebrigtsen <larsi@gnus.org>
 
 ;; This file is part of GNU Emacs.
@@ -59,7 +59,6 @@ general, Emacs network security is handled by the Network
 Security Manager (NSM), and the default value of nil delegates
 the job of checking the connection security to the NSM.
 See Info node `(emacs) Network Security'."
-  :group 'gnutls
   :type '(choice (const nil)
                  string))
 
@@ -91,7 +90,6 @@ checks are performed at the gnutls level.  Instead the checks 
are
 performed via `open-network-stream' at a higher level by the
 Network Security Manager.  See Info node `(emacs) Network
 Security'."
-  :group 'gnutls
   :version "24.4"
   :type '(choice
           (const t)
@@ -118,7 +116,6 @@ Security'."
 If a file path contains glob wildcards, they will be expanded.
 The files may be in PEM or DER format, as per the GnuTLS documentation.
 The files may not exist, in which case they will be ignored."
-  :group 'gnutls
   :type '(choice (function :tag "Function to produce list of bundle filenames")
                  (repeat (file :tag "Bundle filename"))))
 
@@ -139,7 +136,6 @@ network security is handled at a higher level via
 node `(emacs) Network Security'."
   :type '(choice (const :tag "Use default value" nil)
                  (integer :tag "Number of bits" 2048))
-  :group 'gnutls
   :version "27.1")
 
 (defcustom gnutls-crlfiles
@@ -150,7 +146,6 @@ node `(emacs) Network Security'."
 If a file path contains glob wildcards, they will be expanded.
 The files may be in PEM or DER format, as per the GnuTLS documentation.
 The files may not exist, in which case they will be ignored."
-  :group 'gnutls
   :type '(choice (function :tag "Function to produce list of CRL filenames")
                  (repeat (file :tag "CRL filename")))
   :version "27.1")
diff --git a/lisp/net/goto-addr.el b/lisp/net/goto-addr.el
index d192630..af12f69 100644
--- a/lisp/net/goto-addr.el
+++ b/lisp/net/goto-addr.el
@@ -1,4 +1,4 @@
-;;; goto-addr.el --- click to browse URL or to send to e-mail address
+;;; goto-addr.el --- click to browse URL or to send to e-mail address  -*- 
lexical-binding: t; -*-
 
 ;; Copyright (C) 1995, 2000-2021 Free Software Foundation, Inc.
 
@@ -73,19 +73,16 @@
 (defcustom goto-address-fontify-p t
   "Non-nil means URLs and e-mail addresses in buffer are fontified.
 But only if `goto-address-highlight-p' is also non-nil."
-  :type 'boolean
-  :group 'goto-address)
+  :type 'boolean)
 
 (defcustom goto-address-highlight-p t
   "Non-nil means URLs and e-mail addresses in buffer are highlighted."
-  :type 'boolean
-  :group 'goto-address)
+  :type 'boolean)
 
 (defcustom goto-address-fontify-maximum-size 30000
   "Maximum size of file in which to fontify and/or highlight URLs.
 A value of t means there is no limit--fontify regardless of the size."
-  :type '(choice (integer :tag "Maximum size") (const :tag "No limit" t))
-  :group 'goto-address)
+  :type '(choice (integer :tag "Maximum size") (const :tag "No limit" t)))
 
 (defvar goto-address-mail-regexp
   ;; Actually pretty much any char could appear in the username part.  -stef
@@ -122,30 +119,26 @@ will have no effect.")
 
 (defvar goto-address-highlight-keymap
   (let ((m (make-sparse-keymap)))
-    (define-key m (kbd "<mouse-2>") 'goto-address-at-point)
-    (define-key m (kbd "C-c RET") 'goto-address-at-point)
+    (define-key m (kbd "<mouse-2>") #'goto-address-at-point)
+    (define-key m (kbd "C-c RET") #'goto-address-at-point)
     m)
   "Keymap to hold goto-addr's mouse key defs under highlighted URLs.")
 
 (defcustom goto-address-url-face 'link
   "Face to use for URLs."
-  :type 'face
-  :group 'goto-address)
+  :type 'face)
 
 (defcustom goto-address-url-mouse-face 'highlight
   "Face to use for URLs when the mouse is on them."
-  :type 'face
-  :group 'goto-address)
+  :type 'face)
 
 (defcustom goto-address-mail-face 'italic
   "Face to use for e-mail addresses."
-  :type 'face
-  :group 'goto-address)
+  :type 'face)
 
 (defcustom goto-address-mail-mouse-face 'secondary-selection
   "Face to use for e-mail addresses when the mouse is on them."
-  :type 'face
-  :group 'goto-address)
+  :type 'face)
 
 (defun goto-address-unfontify (start end)
   "Remove `goto-address' fontification from the given region."
@@ -287,7 +280,6 @@ Also fontifies the buffer appropriately (see 
`goto-address-fontify-p' and
 ;;;###autoload
 (define-globalized-minor-mode global-goto-address-mode
   goto-address-mode goto-addr-mode--turn-on
-  :group 'goto-address
   :version "28.1")
 
 ;;;###autoload
diff --git a/lisp/net/mailcap.el b/lisp/net/mailcap.el
index b95cd0f..3097c9a 100644
--- a/lisp/net/mailcap.el
+++ b/lisp/net/mailcap.el
@@ -332,7 +332,7 @@ whose car is a symbol, it is `eval'uated to yield the 
validity.  If it
 is a string or list of strings, it represents a shell command to run
 to return a true or false shell value for the validity.
 
-The last matching entry in this structure takes presedence over
+The last matching entry in this structure takes precedence over
 preceding entries.")
 (put 'mailcap-mime-data 'risky-local-variable t)
 
diff --git a/lisp/net/net-utils.el b/lisp/net/net-utils.el
index d5aad3a..3a561a0 100644
--- a/lisp/net/net-utils.el
+++ b/lisp/net/net-utils.el
@@ -1,4 +1,4 @@
-;;; net-utils.el --- network functions
+;;; net-utils.el --- network functions  -*- lexical-binding: t; -*-
 
 ;; Copyright (C) 1998-2021 Free Software Foundation, Inc.
 
@@ -67,17 +67,14 @@
       "tracert"
     "traceroute")
   "Program to trace network hops to a destination."
-  :group 'net-utils
   :type  'string)
 
 (defcustom traceroute-program-options nil
   "Options for the traceroute program."
-  :group 'net-utils
   :type  '(repeat string))
 
 (defcustom ping-program "ping"
   "Program to send network test packets to a host."
-  :group 'net-utils
   :type  'string)
 
 ;; On GNU/Linux and Irix, the system's ping program seems to send packets
@@ -87,7 +84,6 @@
        (list "-c" "4"))
   "Options for the ping program.
 These options can be used to limit how many ICMP packets are emitted."
-  :group 'net-utils
   :type  '(repeat string))
 
 (defcustom ifconfig-program
@@ -98,7 +94,6 @@ These options can be used to limit how many ICMP packets are 
emitted."
         (t "ip"))
   "Program to print network configuration information."
   :version "25.1"                       ; add ip
-  :group 'net-utils
   :type  'string)
 
 (defcustom ifconfig-program-options
@@ -108,7 +103,6 @@ These options can be used to limit how many ICMP packets 
are emitted."
   "Options for the ifconfig program."
   :version "25.1"
   :set-after '(ifconfig-program)
-  :group 'net-utils
   :type  '(repeat string))
 
 (defcustom iwconfig-program
@@ -116,7 +110,6 @@ These options can be used to limit how many ICMP packets 
are emitted."
         ((net-utils--executable-find-sbin "iw") "iw")
         (t "iw"))
   "Program to print wireless network configuration information."
-  :group 'net-utils
   :type 'string
   :version "26.1")
 
@@ -124,7 +117,6 @@ These options can be used to limit how many ICMP packets 
are emitted."
   (cond ((string-match-p "iw\\'" iwconfig-program) (list "dev"))
         (t nil))
  "Options for the iwconfig program."
- :group 'net-utils
  :type '(repeat string)
  :version "26.1")
 
@@ -133,25 +125,21 @@ These options can be used to limit how many ICMP packets 
are emitted."
         ((net-utils--executable-find-sbin "ss"))
         (t "ss"))
   "Program to print network statistics."
-  :group 'net-utils
   :type  'string
   :version "26.1")
 
 (defcustom netstat-program-options
   (list "-a")
   "Options for the netstat program."
-  :group 'net-utils
   :type  '(repeat string))
 
 (defcustom arp-program (or (net-utils--executable-find-sbin "arp") "arp")
   "Program to print IP to address translation tables."
-  :group 'net-utils
   :type  'string)
 
 (defcustom arp-program-options
   (list "-a")
   "Options for the arp program."
-  :group 'net-utils
   :type  '(repeat string))
 
 (defcustom route-program
@@ -162,7 +150,6 @@ These options can be used to limit how many ICMP packets 
are emitted."
         ((net-utils--executable-find-sbin "ip"))
         (t "ip"))
   "Program to print routing tables."
-  :group 'net-utils
   :type  'string
   :version "26.1")
 
@@ -171,18 +158,15 @@ These options can be used to limit how many ICMP packets 
are emitted."
         ((string-match-p "netstat\\'" route-program) (list "-r"))
         (t (list "route")))
   "Options for the route program."
-  :group 'net-utils
   :type  '(repeat string)
   :version "26.1")
 
 (defcustom nslookup-program "nslookup"
   "Program to interactively query DNS information."
-  :group 'net-utils
   :type  'string)
 
 (defcustom nslookup-program-options nil
   "Options for the nslookup program."
-  :group 'net-utils
   :type  '(repeat string))
 
 (defcustom nslookup-prompt-regexp "^> "
@@ -190,28 +174,23 @@ These options can be used to limit how many ICMP packets 
are emitted."
 
 This variable is only used if the variable
 `comint-use-prompt-regexp' is non-nil."
-  :group 'net-utils
   :type  'regexp)
 
 (defcustom dig-program "dig"
   "Program to query DNS information."
-  :group 'net-utils
   :type  'string)
 
 (defcustom dig-program-options nil
   "Options for the dig program."
-  :group 'net-utils
   :type '(repeat string)
   :version "26.1")
 
 (defcustom ftp-program "ftp"
   "Program to run to do FTP transfers."
-  :group 'net-utils
   :type  'string)
 
 (defcustom ftp-program-options nil
   "Options for the ftp program."
-  :group 'net-utils
   :type  '(repeat string))
 
 (defcustom ftp-prompt-regexp "^ftp>"
@@ -219,17 +198,14 @@ This variable is only used if the variable
 
 This variable is only used if the variable
 `comint-use-prompt-regexp' is non-nil."
-  :group 'net-utils
   :type  'regexp)
 
 (defcustom smbclient-program "smbclient"
   "Smbclient program."
-  :group 'net-utils
   :type  'string)
 
 (defcustom smbclient-program-options nil
   "Options for the smbclient program."
-  :group 'net-utils
   :type  '(repeat string))
 
 (defcustom smbclient-prompt-regexp "^smb: >"
@@ -237,17 +213,14 @@ This variable is only used if the variable
 
 This variable is only used if the variable
 `comint-use-prompt-regexp' is non-nil."
-  :group 'net-utils
   :type  'regexp)
 
 (defcustom dns-lookup-program "host"
   "Program to interactively query DNS information."
-  :group 'net-utils
   :type  'string)
 
 (defcustom dns-lookup-program-options nil
   "Options for the dns-lookup program."
-  :group 'net-utils
   :type  '(repeat string))
 
 ;; Internal variables
@@ -265,7 +238,7 @@ This variable is only used if the variable
          1 'font-lock-keyword-face)
    ;; Dotted quads
    (list
-    (mapconcat 'identity
+    (mapconcat #'identity
                (make-list 4 "[0-9]+")
                "\\.")
     0 'font-lock-variable-name-face)
@@ -273,7 +246,7 @@ This variable is only used if the variable
    (list
     (let ((host-expression "[-A-Za-z0-9]+"))
       (concat
-       (mapconcat 'identity
+       (mapconcat #'identity
                   (make-list 2 host-expression)
                   "\\.")
        "\\(\\." host-expression "\\)*"))
@@ -288,7 +261,7 @@ This variable is only used if the variable
   (list
    ;; Dotted quads
    (list
-    (mapconcat 'identity (make-list 4 "[0-9]+") "\\.")
+    (mapconcat #'identity (make-list 4 "[0-9]+") "\\.")
     0 'font-lock-variable-name-face)
    ;; Simple rfc4291 addresses
    (list (concat
@@ -300,7 +273,7 @@ This variable is only used if the variable
    (list
     (let ((host-expression "[-A-Za-z0-9]+"))
       (concat
-       (mapconcat 'identity (make-list 2 host-expression) "\\.")
+       (mapconcat #'identity (make-list 2 host-expression) "\\.")
        "\\(\\." host-expression "\\)*"))
     0 'font-lock-variable-name-face))
   "Expressions to font-lock for general network utilities.")
@@ -371,8 +344,8 @@ This variable is only used if the variable
     (erase-buffer)
     (insert header "\n")
     (set-process-filter
-     (apply 'start-process name buf program args)
-     'net-utils-remove-ctrl-m-filter)
+     (apply #'start-process name buf program args)
+     #'net-utils-remove-ctrl-m-filter)
     (display-buffer buf)
     buf))
 
@@ -405,12 +378,12 @@ This variable is only used if the variable
                 `(net-utils-run-simple ,(current-buffer)
                                        ,program-name ,args nodisplay))
     (set-process-filter
-         (apply 'start-process program-name
-                (current-buffer) program-name args)
-         'net-utils-remove-ctrl-m-filter)
+     (apply #'start-process program-name
+            (current-buffer) program-name args)
+     #'net-utils-remove-ctrl-m-filter)
     (unless nodisplay (display-buffer (current-buffer)))))
 
-(defun net-utils--revert-function (&optional ignore-auto noconfirm)
+(defun net-utils--revert-function (&optional _ignore-auto _noconfirm)
   (message "Reverting `%s'..." (buffer-name))
   (apply (car net-utils--revert-cmd) (cdr net-utils--revert-cmd))
   (let ((proc (get-buffer-process (current-buffer))))
@@ -430,7 +403,7 @@ This variable is only used if the variable
    ifconfig-program
    ifconfig-program-options))
 
-(defalias 'ipconfig 'ifconfig)
+(defalias 'ipconfig #'ifconfig)
 
 ;;;###autoload
 (defun iwconfig ()
@@ -532,7 +505,7 @@ in Lisp code."
     (net-utils-run-program
      "Nslookup"
      (concat "** "
-      (mapconcat 'identity
+      (mapconcat #'identity
                (list "Nslookup" host nslookup-program)
                " ** "))
      nslookup-program
@@ -618,7 +591,7 @@ This command uses `nslookup-program' to look up DNS 
records."
 
 (defvar nslookup-mode-map
   (let ((map (make-sparse-keymap)))
-    (define-key map "\t" 'completion-at-point)
+    (define-key map "\t" #'completion-at-point)
     map))
 
 ;; Using a derived mode gives us keymaps, hooks, etc.
@@ -646,9 +619,9 @@ This command uses `dns-lookup-program' for looking up the 
DNS information."
     (net-utils-run-program
      (concat "DNS Lookup [" host "]")
      (concat "** "
-      (mapconcat 'identity
-               (list "DNS Lookup" host dns-lookup-program)
-               " ** "))
+            (mapconcat #'identity
+                       (list "DNS Lookup" host dns-lookup-program)
+                       " ** "))
      dns-lookup-program
      options)))
 
@@ -669,13 +642,14 @@ This command uses `dig-program' for looking up the DNS 
information."
   (net-utils-run-program
    "Dig"
    (concat "** "
-          (mapconcat 'identity
+          (mapconcat #'identity
                      (list "Dig" host dig-program)
                      " ** "))
    dig-program
    options)))
 
 (autoload 'comint-exec "comint")
+(declare-function comint-watch-for-password-prompt "comint" (string))
 
 ;; This is a lot less than ange-ftp, but much simpler.
 ;;;###autoload
@@ -697,7 +671,7 @@ This command uses `dig-program' for looking up the DNS 
information."
 (defvar ftp-mode-map
   (let ((map (make-sparse-keymap)))
     ;; Occasionally useful
-    (define-key map "\t" 'completion-at-point)
+    (define-key map "\t" #'completion-at-point)
     map))
 
 (define-derived-mode ftp-mode comint-mode "FTP"
@@ -710,9 +684,9 @@ This command uses `dig-program' for looking up the DNS 
information."
   ;; password prompts will probably immediately follow the initial
   ;; connection), but it's better than getting prompted twice for the
   ;; same password.
-  (unless (memq 'comint-watch-for-password-prompt
+  (unless (memq #'comint-watch-for-password-prompt
                (default-value 'comint-output-filter-functions))
-    (add-hook 'comint-output-filter-functions 'comint-watch-for-password-prompt
+    (add-hook 'comint-output-filter-functions 
#'comint-watch-for-password-prompt
              nil t)))
 
 (defun smbclient (host service)
@@ -759,9 +733,9 @@ This command uses `smbclient-program' to connect to HOST."
   ;; password prompts will probably immediately follow the initial
   ;; connection), but it's better than getting prompted twice for the
   ;; same password.
-  (unless (memq 'comint-watch-for-password-prompt
+  (unless (memq #'comint-watch-for-password-prompt
                (default-value 'comint-output-filter-functions))
-    (add-hook 'comint-output-filter-functions 'comint-watch-for-password-prompt
+    (add-hook 'comint-output-filter-functions 
#'comint-watch-for-password-prompt
              nil t)))
 
 
@@ -810,7 +784,7 @@ This list is not complete.")
      (error "Could not open connection to %s" host))
     (erase-buffer)
     (set-marker (process-mark tcp-connection) (point-min))
-    (set-process-filter tcp-connection 'net-utils-remove-ctrl-m-filter)
+    (set-process-filter tcp-connection #'net-utils-remove-ctrl-m-filter)
     (and initial-string
         (process-send-string tcp-connection
                              (concat initial-string "\r\n")))
@@ -825,7 +799,6 @@ This list is not complete.")
 If a host name passed to `finger' matches one of these regular
 expressions, it is assumed to be a host that doesn't accept
 queries of the form USER@HOST, and wants a query containing USER only."
-  :group 'net-utils
   :type '(repeat regexp)
   :version "21.1")
 
@@ -852,7 +825,7 @@ and `network-connection-service-alist', which see."
   (let* ((user-and-host (concat user "@" host))
         (process-name (concat "Finger [" user-and-host "]"))
         (regexps finger-X.500-host-regexps)
-        found)
+        ) ;; found
     (and regexps
         (while (not (string-match (car regexps) host))
           (setq regexps (cdr regexps)))
@@ -866,7 +839,6 @@ and `network-connection-service-alist', which see."
 
 (defcustom whois-server-name "rs.internic.net"
   "Default host name for the whois service."
-  :group 'net-utils
   :type  'string)
 
 (defcustom whois-server-list
@@ -880,7 +852,6 @@ and `network-connection-service-alist', which see."
     ("whois.nic.gov")
     ("whois.ripe.net"))
   "A list of whois servers that can be queried."
-  :group 'net-utils
   :type '(repeat (list string)))
 
 ;; FIXME: modern whois clients include a much better tld <-> whois server
@@ -903,14 +874,12 @@ and `network-connection-service-alist', which see."
     ("whois.nic.gov" . "gov")
     ("whois.nic.mil" . "mil"))
   "Alist to map top level domains to whois servers."
-  :group 'net-utils
   :type '(repeat (cons string string)))
 
 (defcustom whois-guess-server t
   "If non-nil then whois will try to deduce the appropriate whois
 server from the query.  If the query doesn't look like a domain or hostname
 then the server named by `whois-server-name' is used."
-  :group 'net-utils
   :type 'boolean)
 
 (defun whois-get-tld (host)
@@ -951,7 +920,6 @@ The port is deduced from 
`network-connection-service-alist'."
 
 (defcustom whois-reverse-lookup-server "whois.arin.net"
   "Server which provides inverse DNS mapping."
-  :group 'net-utils
   :type  'string)
 
 ;;;###autoload
diff --git a/lisp/net/network-stream.el b/lisp/net/network-stream.el
index b45cefc..1983688 100644
--- a/lisp/net/network-stream.el
+++ b/lisp/net/network-stream.el
@@ -248,8 +248,7 @@ gnutls-boot (as returned by `gnutls-boot-parameters')."
             (list key cert)))))))
 
 ;;;###autoload
-(defalias 'open-protocol-stream 'open-network-stream)
-(define-obsolete-function-alias 'open-protocol-stream 'open-network-stream
+(define-obsolete-function-alias 'open-protocol-stream #'open-network-stream
   "26.1")
 
 (defun network-stream-open-plain (name buffer host service parameters)
diff --git a/lisp/net/newst-backend.el b/lisp/net/newst-backend.el
index ea96012..1d3a5e0 100644
--- a/lisp/net/newst-backend.el
+++ b/lisp/net/newst-backend.el
@@ -39,10 +39,10 @@
 (require 'iso8601)
 
 ;; Silence warnings
+(defvar newsticker-groups)
 (defvar w3-mode-map)
 (defvar w3m-minor-mode-map)
 
-
 (defvar newsticker--retrieval-timer-list nil
   "List of timers for news retrieval.
 This is an alist, each element consisting of (feed-name . timer).")
@@ -66,35 +66,34 @@ considered to be running if the newsticker timer list is 
not empty."
 
 ;; Hard-coding URLs like this is a recipe for propagating obsolete info.
 (defconst newsticker--raw-url-list-defaults
-  '(
-    ("Debian Security Advisories"
-    "http://www.debian.org/security/dsa.en.rdf";)
+  '(("Debian Security Advisories"
+     "https://www.debian.org/security/dsa.en.rdf";)
     ("Debian Security Advisories - Long format"
-    "http://www.debian.org/security/dsa-long.en.rdf";)
+     "https://www.debian.org/security/dsa-long.en.rdf";)
     ("Emacs Wiki"
-    "https://www.emacswiki.org/emacs?action=rss";
-    nil
-    3600)
+     "https://www.emacswiki.org/emacs?action=rss";
+     nil
+     3600)
     ("LWN (Linux Weekly News)"
-    "https://lwn.net/headlines/rss";)
+     "https://lwn.net/headlines/rss";)
     ("Quote of the day"
-    "http://feeds.feedburner.com/quotationspage/qotd";
-    "07:00"
-    86400)
+     "https://feeds.feedburner.com/quotationspage/qotd";
+     "07:00"
+     86400)
     ("The Register"
-    "https://www.theregister.co.uk/headlines.rss";)
+     "https://www.theregister.co.uk/headlines.rss";)
     ("slashdot"
-    "http://rss.slashdot.org/Slashdot/slashdot";
-    nil
-    3600)                        ;/. will ban you if under 3600 seconds!
+     "http://rss.slashdot.org/Slashdot/slashdot";
+     nil
+     3600)                        ;/. will ban you if under 3600 seconds!
     ("Wired News"
-    "https://www.wired.com/feed/rss";)
+     "https://www.wired.com/feed/rss";)
     ("Heise News (german)"
-    "http://www.heise.de/newsticker/heise.rdf";)
+     "http://www.heise.de/newsticker/heise.rdf";)
     ("Tagesschau (german)"
-    "http://www.tagesschau.de/newsticker.rdf";
-    nil
-    1800))
+     "http://www.tagesschau.de/newsticker.rdf";
+     nil
+     1800))
   "Default URL list in raw form.
 This list is fed into defcustom via `newsticker--splicer'.")
 
@@ -153,10 +152,10 @@ value effective."
   :group 'newsticker)
 
 (defcustom newsticker-url-list-defaults
- '(("Emacs Wiki"
-    "https://www.emacswiki.org/emacs?action=rss";
-    nil
-    3600))
+  '(("Emacs Wiki"
+     "https://www.emacswiki.org/emacs?action=rss";
+     nil
+     3600))
   "A customizable list of news feeds to select from.
 These were mostly extracted from the Radio Community Server
 <http://rcs.userland.com/>.
@@ -164,7 +163,7 @@ These were mostly extracted from the Radio Community Server
 You may add other entries in `newsticker-url-list'."
   :type `(set ,@(mapcar #'newsticker--splicer
                         newsticker--raw-url-list-defaults))
-  :set 'newsticker--set-customvar-retrieval
+  :set #'newsticker--set-customvar-retrieval
   :group 'newsticker-retrieval)
 
 (defcustom newsticker-url-list nil
@@ -218,7 +217,7 @@ which apply for this feed only, overriding the value of
                        (choice :tag "Wget Arguments"
                                (const  :tag "Default arguments" nil)
                                (repeat :tag "Special arguments" string))))
-  :set 'newsticker--set-customvar-retrieval
+  :set #'newsticker--set-customvar-retrieval
   :group 'newsticker-retrieval)
 
 (defcustom newsticker-retrieval-method
@@ -261,7 +260,7 @@ make it less than 1800 seconds (30 minutes)!"
                  (const   :tag "Daily" 86400)
                  (const   :tag "Weekly" 604800)
                  (integer :tag "Interval"))
-  :set 'newsticker--set-customvar-retrieval
+  :set #'newsticker--set-customvar-retrieval
   :group 'newsticker-retrieval)
 
 (defcustom newsticker-desc-comp-max
@@ -550,7 +549,7 @@ name/timer pair to `newsticker--retrieval-timer-list'."
       (if (<= interval 0)
           (setq interval nil))
       (setq timer (run-at-time start-time interval
-                               'newsticker-get-news feed-name))
+                               #'newsticker-get-news feed-name))
       (if interval
           (add-to-list 'newsticker--retrieval-timer-list
                        (cons feed-name timer))))))
@@ -645,6 +644,15 @@ If URL is nil it is searched at point."
   (add-to-list 'newsticker-url-list (list name url nil nil nil) t)
   (customize-variable 'newsticker-url-list))
 
+(defun newsticker-customize-feed (feed-name)
+  "Open customization buffer for `newsticker-url-list' and jump to FEED-NAME."
+  (interactive
+   (list (completing-read "Name of feed or group to edit: "
+                          (mapcar #'car newsticker-url-list))))
+  (customize-variable 'newsticker-url-list)
+  (when (search-forward (concat "Label: " feed-name) nil t)
+    (forward-line -1)))
+
 (defun newsticker-customize ()
   "Open the newsticker customization group."
   (interactive)
@@ -671,8 +679,8 @@ See `newsticker-get-news'."
     (condition-case error-data
         (url-retrieve url 'newsticker--get-news-by-url-callback
                       (list feed-name))
-          (error (message "Error retrieving news from %s: %s" feed-name
-                          error-data))))
+      (error (message "Error retrieving news from %s: %s" feed-name
+                      error-data))))
   (force-mode-line-update))
 
 (defun newsticker--get-news-by-url-callback (status feed-name)
@@ -719,10 +727,10 @@ See `newsticker-get-news'."
           (error "Another wget-process is running for %s" feed-name))
       ;; start wget
       (let* ((args (append wget-arguments (list url)))
-             (proc (apply 'start-process feed-name buffername
+             (proc (apply #'start-process feed-name buffername
                           newsticker-wget-name args)))
         (set-process-coding-system proc 'no-conversion 'no-conversion)
-        (set-process-sentinel proc 'newsticker--sentinel)
+        (set-process-sentinel proc #'newsticker--sentinel)
         (process-put proc 'nt-feed-name feed-name)
         (setq newsticker--process-ids (cons (process-id proc)
                                             newsticker--process-ids))
@@ -816,7 +824,7 @@ Argument BUFFER is the buffer of the retrieval process."
                     (setq coding-system (intern (downcase (match-string 1))))
                   (setq coding-system
                         (condition-case nil
-                              (check-coding-system coding-system)
+                            (check-coding-system coding-system)
                           (coding-system-error
                            (message
                             "newsticker.el: ignoring coding system %s for %s"
@@ -927,8 +935,8 @@ Argument BUFFER is the buffer of the retrieval process."
         ;; setup scrollable text
         (when (= 0 (length newsticker--process-ids))
           (when (fboundp 'newsticker--ticker-text-setup) ;silence
-                                                         ;compiler
-                                                         ;warnings
+                                        ;compiler
+                                        ;warnings
             (newsticker--ticker-text-setup)))
         (setq newsticker--latest-update-time (current-time))
         (when something-was-added
@@ -936,8 +944,8 @@ Argument BUFFER is the buffer of the retrieval process."
           (newsticker--cache-save-feed
            (newsticker--cache-get-feed name-symbol))
           (when (fboundp 'newsticker--buffer-set-uptodate) ;silence
-                                                           ;compiler
-                                                           ;warnings
+                                        ;compiler
+                                        ;warnings
             (newsticker--buffer-set-uptodate nil)))
         ;; kill the process buffer if wanted
         (unless newsticker-debug
@@ -1004,7 +1012,7 @@ Argument BUFFER is the buffer of the retrieval process."
   ;; And another one (20050702)! If description is HTML
   ;; encoded and starts with a `<', wrap the whole
   ;; description in a CDATA expression.  This happened for
-  ;; http://www.thefreedictionary.com/_/WoD/rss.aspx?type=quote
+  ;; https://www.thefreedictionary.com/_/WoD/rss.aspx?type=quote
   (goto-char (point-min))
   (while (re-search-forward
           "<description>\\(<img.*?\\)</description>" nil t)
@@ -1098,8 +1106,8 @@ same as in `newsticker--parse-atom-1.0'."
                     ;; time-fn
                     (lambda (node)
                       (newsticker--decode-rfc822-date
-                            (car (xml-node-children
-                                  (car (xml-get-children node 'modified))))))
+                       (car (xml-node-children
+                             (car (xml-get-children node 'modified))))))
                     ;; guid-fn
                     (lambda (node)
                       (newsticker--guid-to-string
@@ -1123,9 +1131,9 @@ Restore an xml-string from a an xml NODE that was 
returned by xml-parse..."
         (children (cddr node)))
     (concat "<" qname
             (when att-list " ")
-            (mapconcat 'newsticker--unxml-attribute att-list " ")
+            (mapconcat #'newsticker--unxml-attribute att-list " ")
             ">"
-            (mapconcat 'newsticker--unxml children "") "</" qname ">")))
+            (mapconcat #'newsticker--unxml children "") "</" qname ">")))
 
 (defun newsticker--unxml-attribute (attribute)
   "Actually restore xml-string of an ATTRIBUTE of an xml node."
@@ -1168,7 +1176,7 @@ URL 
`http://www.atompub.org/2005/08/17/draft-ietf-atompub-format-11.html'"
                       ;; unxml the content or the summary node. Atom
                       ;; allows for integrating (x)html into the atom
                       ;; structure but we need the raw html string.
-                      ;; e.g. http://www.heise.de/open/news/news-atom.xml
+                      ;; e.g. https://www.heise.de/open/news/news-atom.xml
                       ;; http://feeds.feedburner.com/ru_nix_blogs
                       (or (newsticker--unxml
                            (car (xml-node-children
@@ -1548,6 +1556,7 @@ argument, which is one of the items in ITEMLIST."
 ;; ======================================================================
 
 (defun newsticker--insert-bytes (bytes)
+  "Decode BYTES and insert in current buffer."
   (insert (decode-coding-string bytes 'binary)))
 
 (defun newsticker--remove-whitespace (string)
@@ -1571,7 +1580,7 @@ Remove the pre-formatted from `newsticker--cache'."
   "Forget all cached pre-formatted data.
 Remove the pre-formatted from `newsticker--cache'."
   (mapc (lambda (feed)
-          (mapc 'newsticker--do-forget-preformatted
+          (mapc #'newsticker--do-forget-preformatted
                 (cdr feed)))
         newsticker--cache)
   (when (fboundp 'newsticker--buffer-set-uptodate)
@@ -1584,10 +1593,10 @@ This function calls `message' with arguments STRING and 
ARGS, if
   (and newsticker-debug
        ;;(not (active-minibuffer-window))
        ;;(not (current-message))
-       (apply 'message string args)))
+       (apply #'message string args)))
 
 (defun newsticker--decode-iso8601-date (string)
-  "Return ISO8601-STRING in format like `encode-time'.
+  "Return ISO8601-encoded STRING in format like `encode-time'.
 Converts from ISO-8601 to Emacs representation.  If no time zone
 is present, this function defaults to universal time."
   (if string
@@ -1669,7 +1678,7 @@ Sat, 07 Sep 2002 00:00:01 GMT
              (message "Cannot decode \"%s\": %s %s" rfc822-string
                       (car error-data) (cdr error-data))
              nil))))
-      nil))
+    nil))
 
 (defun newsticker--lists-intersect-p (list1 list2)
   "Return t if LIST1 and LIST2 share elements."
@@ -1728,27 +1737,27 @@ Save image as FILENAME in DIRECTORY, download it from 
URL."
   (let* ((proc-name (concat feed-name "-" filename))
          (buffername (concat " *newsticker-wget-image-" proc-name "*"))
          (item (or (assoc feed-name newsticker-url-list)
-                       (assoc feed-name newsticker-url-list-defaults)
-                       (error
-                        "Cannot get image for %s: Check newsticker-url-list"
-                        feed-name)))
+                   (assoc feed-name newsticker-url-list-defaults)
+                   (error
+                    "Cannot get image for %s: Check newsticker-url-list"
+                    feed-name)))
          (wget-arguments (or (car (cdr (cdr (cdr (cdr item)))))
                              newsticker-wget-arguments)))
-        (with-current-buffer (get-buffer-create buffername)
-          (erase-buffer)
-          ;; throw an error if there is an old wget-process around
-          (if (get-process feed-name)
-              (error "Another wget-process is running for image %s"
-                     feed-name))
-          ;; start wget
-          (let* ((args (append wget-arguments (list url)))
-                 (proc (apply 'start-process proc-name buffername
-                              newsticker-wget-name args)))
-            (set-process-coding-system proc 'no-conversion 'no-conversion)
-            (set-process-sentinel proc 'newsticker--image-sentinel)
-            (process-put proc 'nt-directory directory)
-            (process-put proc 'nt-feed-name feed-name)
-            (process-put proc 'nt-filename filename)))))
+    (with-current-buffer (get-buffer-create buffername)
+      (erase-buffer)
+      ;; throw an error if there is an old wget-process around
+      (if (get-process feed-name)
+          (error "Another wget-process is running for image %s"
+                 feed-name))
+      ;; start wget
+      (let* ((args (append wget-arguments (list url)))
+             (proc (apply #'start-process proc-name buffername
+                          newsticker-wget-name args)))
+        (set-process-coding-system proc 'no-conversion 'no-conversion)
+        (set-process-sentinel proc #'newsticker--image-sentinel)
+        (process-put proc 'nt-directory directory)
+        (process-put proc 'nt-feed-name feed-name)
+        (process-put proc 'nt-filename filename)))))
 
 (defun newsticker--image-sentinel (process _event)
   "Sentinel for image-retrieving PROCESS caused by EVENT."
@@ -1773,18 +1782,18 @@ Save image as FILENAME in DIRECTORY, download it from 
URL."
   "Save contents of BUFFER in DIRECTORY as FILE-NAME.
 Finally kill buffer."
   (with-current-buffer buffer
-      (let ((image-name (concat directory file-name)))
-        (set-buffer-file-coding-system 'no-conversion)
-        ;; make sure the cache dir exists
-        (unless (file-directory-p directory)
-          (make-directory directory))
-        ;; write and close buffer
-        (let ((require-final-newline nil)
-              (backup-inhibited t)
-              (coding-system-for-write 'no-conversion))
-          (write-region nil nil image-name nil 'quiet))
-        (set-buffer-modified-p nil)
-        (kill-buffer buffer))))
+    (let ((image-name (concat directory file-name)))
+      (set-buffer-file-coding-system 'no-conversion)
+      ;; make sure the cache dir exists
+      (unless (file-directory-p directory)
+        (make-directory directory))
+      ;; write and close buffer
+      (let ((require-final-newline nil)
+            (backup-inhibited t)
+            (coding-system-for-write 'no-conversion))
+        (write-region nil nil image-name nil 'quiet))
+      (set-buffer-modified-p nil)
+      (kill-buffer buffer))))
 
 (defun newsticker--image-remove (directory file-name)
   "In DIRECTORY remove FILE-NAME."
@@ -1799,8 +1808,8 @@ Save image as FILENAME in DIRECTORY, download it from 
URL."
     (condition-case error-data
         (url-retrieve url 'newsticker--image-download-by-url-callback
                       (list feed-name directory filename))
-          (error (message "Error retrieving image from %s: %s" feed-name
-                          error-data))))
+      (error (message "Error retrieving image from %s: %s" feed-name
+                      error-data))))
   (force-mode-line-update))
 
 (defun newsticker--image-download-by-url-callback (status feed-name directory 
filename)
@@ -2137,11 +2146,11 @@ FEED is a symbol!"
   (concat newsticker-dir "/feeds"))
 
 (defun newsticker--cache-save ()
-    "Save cache data for all feeds."
-    (unless (file-directory-p newsticker-dir)
-      (make-directory newsticker-dir t))
-    (mapc 'newsticker--cache-save-feed newsticker--cache)
-    nil)
+  "Save cache data for all feeds."
+  (unless (file-directory-p newsticker-dir)
+    (make-directory newsticker-dir t))
+  (mapc #'newsticker--cache-save-feed newsticker--cache)
+  nil)
 
 (defun newsticker--cache-save-feed (feed)
   "Save cache data for FEED."
@@ -2207,14 +2216,14 @@ If AGES is nil, the total number of items is returned."
           (if (memq (newsticker--age (car items)) ages)
               (setq num (1+ num)))
         (if (memq (newsticker--age (car items)) '(new old immortal obsolete))
-              (setq num (1+ num))))
+            (setq num (1+ num))))
       (setq items (cdr items)))
     num))
 
 (defun newsticker--stat-num-items-total (&optional age)
   "Return total number of items in all feeds which have the given AGE.
 If AGE is nil, the total number of items is returned."
-  (apply '+
+  (apply #'+
          (mapcar (lambda (feed)
                    (if age
                        (newsticker--stat-num-items (intern (car feed)) age)
@@ -2227,39 +2236,66 @@ If AGE is nil, the total number of items is returned."
 (defun newsticker-opml-export ()
   "OPML subscription export.
 Export subscriptions to a buffer in OPML Format."
-  ;; FIXME: use newsticker-groups
   (interactive)
   (with-current-buffer (get-buffer-create "*OPML Export*")
+    (erase-buffer)
     (set-buffer-file-coding-system 'utf-8)
     (insert (concat
              "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"
              "<!-- OPML generated by Emacs newsticker.el -->\n"
              "<opml version=\"1.0\">\n"
              "  <head>\n"
-             "    <title>mySubscriptions</title>\n"
+             "    <title>Emacs newsticker subscriptions</title>\n"
              "    <dateCreated>" (format-time-string "%a, %d %b %Y %T %z")
              "</dateCreated>\n"
              "    <ownerEmail>" user-mail-address "</ownerEmail>\n"
              "    <ownerName>" (user-full-name) "</ownerName>\n"
              "  </head>\n"
              "  <body>\n"))
-    (dolist (sub (append newsticker-url-list newsticker-url-list-defaults))
-      (insert "    <outline text=\"")
-      (insert (newsticker--title sub))
-      (insert "\" xmlUrl=\"")
-      (insert (xml-escape-string (let ((url (cadr sub)))
-                                   (if (stringp url) url (prin1-to-string 
url)))))
-      (insert "\"/>\n"))
-    (insert "  </body>\n</opml>\n"))
+    (let ((feeds (append newsticker-url-list newsticker-url-list-defaults))
+          ;; insert the feed groups and all feeds that are contained
+          (saved-feed-names (newsticker--opml-insert-elt newsticker-groups 2)))
+      ;; to be safe: insert all feeds that are not contained in any group
+      (dolist (f feeds)
+        (unless (seq-find (lambda (sfn) (string= (car f) sfn)) 
saved-feed-names)
+          (newsticker--opml-insert-feed (car f) 4)))
+      (insert "  </body>\n</opml>\n")))
   (pop-to-buffer "*OPML Export*")
   (when (fboundp 'sgml-mode)
     (sgml-mode)))
 
+(defun newsticker--opml-insert-elt (elt depth)
+  "Insert an OPML ELT with indentation level DEPTH."
+  (if (listp elt)
+      (newsticker--opml-insert-group elt (+ 2 depth))
+    (newsticker--opml-insert-feed elt (+ 2 depth))))
+
+(defun newsticker--opml-insert-group (group depth)
+  "Insert an OPML GROUP with indentation level DEPTH."
+  (let (saved-feeds)
+    (insert (make-string depth ? ) "<outline type=\"folder\" text=\"" (car 
group) "\">\n")
+    (setq saved-feeds (mapcar (lambda (e)
+                                (newsticker--opml-insert-elt e depth))
+                              (cdr group)))
+    (insert (make-string depth ? ) "</outline>\n")
+    (flatten-tree saved-feeds)))
+
+(defun newsticker--opml-insert-feed (feed-name depth)
+  "Insert an OPML FEED-NAME with indentation level DEPTH."
+  (let* ((feed-definition (seq-find (lambda (f)
+                                      (string= feed-name (car f)))
+                                    (append newsticker-url-list 
newsticker-url-list-defaults)))
+         (url (nth 1 feed-definition))
+         (url-string (if (functionp url) (prin1-to-string url)
+                       (xml-escape-string url))))
+    (insert (make-string depth ? ) "<outline text=\"" feed-name
+            "\" xmlUrl=\"" url-string
+            "\"/>\n"))
+  feed-name)
+
 (defun newsticker--opml-import-outlines (outlines)
-  "Recursively import OUTLINES from OPML data.
-Note that nested outlines are currently flattened -- i.e. grouping is
-removed."
-  (mapc (lambda (outline)
+  "Recursively import OUTLINES from OPML data."
+  (mapcar (lambda (outline)
             (let ((name (xml-get-attribute outline 'text))
                   (url (xml-get-attribute outline 'xmlUrl))
                   (children (xml-get-children outline 'outline)))
@@ -2267,18 +2303,27 @@ removed."
                 (add-to-list 'newsticker-url-list
                              (list name url nil nil nil) t))
               (if children
-                  (newsticker--opml-import-outlines children))))
-        outlines))
+                        (append (list name)
+                                (newsticker--opml-import-outlines children))
+                      name)))
+          outlines))
 
 (defun newsticker-opml-import (filename)
-  "Import OPML data from FILENAME."
+  "Import OPML data from FILENAME.
+Feeds are added to `newsticker-url-list' and `newsticker-groups'
+preserving the outline structure."
   (interactive "fOPML file: ")
   (set-buffer (find-file-noselect filename))
   (goto-char (point-min))
   (let* ((node-list (xml-parse-region (point-min) (point-max)))
+         (title (car (xml-node-children
+                      (car (xml-get-children
+                            (car (xml-get-children (car node-list) 'head))
+                            'title)))))
          (body (car (xml-get-children (car node-list) 'body)))
-         (outlines (xml-get-children body 'outline)))
-    (newsticker--opml-import-outlines outlines))
+         (outlines (xml-get-children body 'outline))
+         (imported-groups-data (newsticker--opml-import-outlines outlines)))
+    (add-to-list 'newsticker-groups (cons title imported-groups-data) t))
   (customize-variable 'newsticker-url-list))
 
 ;; ======================================================================
@@ -2350,7 +2395,7 @@ the item."
             (make-directory temp-dir t))
           (cd temp-dir)
           (message "Getting image %s" url)
-          (apply 'start-process "wget-image"
+          (apply #'start-process "wget-image"
                  " *newsticker-wget-download-images*"
                  newsticker-wget-name
                  (list url))
@@ -2372,7 +2417,7 @@ This function is suited for adding it to 
`newsticker-new-item-functions'."
           (make-directory temp-dir t))
         (cd temp-dir)
         (message "Getting enclosure %s" url)
-        (apply 'start-process "wget-enclosure"
+        (apply #'start-process "wget-enclosure"
                " *newsticker-wget-download-enclosures*"
                newsticker-wget-name
                (list url))
diff --git a/lisp/net/newst-plainview.el b/lisp/net/newst-plainview.el
index 21d47b8..420cf82 100644
--- a/lisp/net/newst-plainview.el
+++ b/lisp/net/newst-plainview.el
@@ -1,10 +1,10 @@
-;;; newst-plainview.el --- Single buffer frontend for newsticker.
+;;; newst-plainview.el --- Single buffer frontend for newsticker.  -*- 
lexical-binding: t; -*-
 
 ;; Copyright (C) 2003-2021 Free Software Foundation, Inc.
 
 ;; Author:      Ulf Jasper <ulf.jasper@web.de>
 ;; Filename:    newst-plainview.el
-;; URL:         http://www.nongnu.org/newsticker
+;; URL:         https://www.nongnu.org/newsticker
 ;; Package:     newsticker
 
 ;; ======================================================================
@@ -90,7 +90,7 @@ The following sort methods are available:
           (const :tag "Keep original order" sort-by-original-order)
           (const :tag "Sort by time"        sort-by-time)
           (const :tag "Sort by title"       sort-by-title))
-  :set 'newsticker--set-customvar-sorting
+  :set #'newsticker--set-customvar-sorting
   :group 'newsticker-plainview)
 
 (defcustom newsticker-heading-format
@@ -107,7 +107,7 @@ The following printf-like specifiers can be used:
 %s  The statistical data of the feed.  See `newsticker-statistics-format'.
 %t  The title of the feed, i.e. its name."
   :type 'string
-  :set 'newsticker--set-customvar-formatting
+  :set #'newsticker--set-customvar-formatting
   :group 'newsticker-plainview)
 
 (defcustom newsticker-item-format
@@ -122,7 +122,7 @@ The following printf-like specifiers can be used:
     the title of the feed is used.
 %t  The title of the item."
   :type 'string
-  :set 'newsticker--set-customvar-formatting
+  :set #'newsticker--set-customvar-formatting
   :group 'newsticker-plainview)
 
 (defcustom newsticker-desc-format
@@ -133,7 +133,7 @@ The following printf-like specifiers can be used:
 %d  The date the item was (first) retrieved.  See
     `newsticker-date-format'."
   :type 'string
-  :set 'newsticker--set-customvar-formatting
+  :set #'newsticker--set-customvar-formatting
   :group 'newsticker-plainview)
 
 (defcustom newsticker-statistics-format
@@ -146,7 +146,7 @@ The following printf-like specifiers can be used:
 %o  The number of old items in the feed.
 %O  The number of obsolete items in the feed."
   :type 'string
-  :set 'newsticker--set-customvar-formatting
+  :set #'newsticker--set-customvar-formatting
   :group 'newsticker-plainview)
 
 
@@ -195,7 +195,7 @@ If set to t old items will be completely folded and only new
 items will show up in the *newsticker* buffer.  Otherwise old as
 well as new items will be visible."
   :type 'boolean
-  :set 'newsticker--set-customvar-buffer
+  :set #'newsticker--set-customvar-buffer
   :group 'newsticker-plainview)
 
 (defcustom newsticker-show-descriptions-of-new-items
@@ -204,14 +204,14 @@ well as new items will be visible."
 If set to t old items will be folded and new items will be
 unfolded.  Otherwise old as well as new items will be folded."
   :type 'boolean
-  :set 'newsticker--set-customvar-buffer
+  :set #'newsticker--set-customvar-buffer
   :group 'newsticker-plainview)
 
 (defcustom newsticker-show-all-news-elements
   nil
   "Show all news elements."
   :type 'boolean
-  ;;:set 'newsticker--set-customvar
+  ;;:set #'newsticker--set-customvar
   :group 'newsticker-plainview)
 
 ;; ======================================================================
@@ -273,6 +273,7 @@ images."
 
 (defvar newsticker--plainview-tool-bar-map
   (when (boundp 'tool-bar-map)
+    (defvar tool-bar-map)
     (let ((tool-bar-map (make-sparse-keymap)))
       (tool-bar-add-item "newsticker/prev-feed"
                          'newsticker-previous-feed
@@ -386,51 +387,45 @@ images."
 
 (defvar newsticker-mode-map
   (let ((map (make-keymap)))
-    (define-key map "sO" 'newsticker-show-old-items)
-    (define-key map "hO" 'newsticker-hide-old-items)
-    (define-key map "sa" 'newsticker-show-all-desc)
-    (define-key map "ha" 'newsticker-hide-all-desc)
-    (define-key map "sf" 'newsticker-show-feed-desc)
-    (define-key map "hf" 'newsticker-hide-feed-desc)
-    (define-key map "so" 'newsticker-show-old-item-desc)
-    (define-key map "ho" 'newsticker-hide-old-item-desc)
-    (define-key map "sn" 'newsticker-show-new-item-desc)
-    (define-key map "hn" 'newsticker-hide-new-item-desc)
-    (define-key map "se" 'newsticker-show-entry)
-    (define-key map "he" 'newsticker-hide-entry)
-    (define-key map "sx" 'newsticker-show-extra)
-    (define-key map "hx" 'newsticker-hide-extra)
-
-    (define-key map [?\S-\ ] 'scroll-down-command)
-    (define-key map " "  'scroll-up-command)
-    (define-key map "q"  'newsticker-close-buffer)
-    (define-key map "p"  'newsticker-previous-item)
-    (define-key map "P"  'newsticker-previous-new-item)
-    (define-key map "F"  'newsticker-previous-feed)
-    (define-key map "\t" 'newsticker-next-item)
-    (define-key map "n"  'newsticker-next-item)
-    (define-key map "N"  'newsticker-next-new-item)
-    (define-key map "f"  'newsticker-next-feed)
-    (define-key map "M"  'newsticker-mark-all-items-as-read)
-    (define-key map "m"
-      'newsticker-mark-all-items-at-point-as-read-and-redraw)
-    (define-key map "o"
-      'newsticker-mark-item-at-point-as-read)
-    (define-key map "O"
-      'newsticker-mark-all-items-at-point-as-read)
-    (define-key map "G"  'newsticker-get-all-news)
-    (define-key map "g"  'newsticker-get-news-at-point)
-    (define-key map "u"  'newsticker-buffer-update)
-    (define-key map "U"  'newsticker-buffer-force-update)
-    (define-key map "a"  'newsticker-add-url)
-
-    (define-key map "i"
-      'newsticker-mark-item-at-point-as-immortal)
-
-    (define-key map "xf"
-      'newsticker-toggle-auto-narrow-to-feed)
-    (define-key map "xi"
-      'newsticker-toggle-auto-narrow-to-item)
+    (define-key map "sO" #'newsticker-show-old-items)
+    (define-key map "hO" #'newsticker-hide-old-items)
+    (define-key map "sa" #'newsticker-show-all-desc)
+    (define-key map "ha" #'newsticker-hide-all-desc)
+    (define-key map "sf" #'newsticker-show-feed-desc)
+    (define-key map "hf" #'newsticker-hide-feed-desc)
+    (define-key map "so" #'newsticker-show-old-item-desc)
+    (define-key map "ho" #'newsticker-hide-old-item-desc)
+    (define-key map "sn" #'newsticker-show-new-item-desc)
+    (define-key map "hn" #'newsticker-hide-new-item-desc)
+    (define-key map "se" #'newsticker-show-entry)
+    (define-key map "he" #'newsticker-hide-entry)
+    (define-key map "sx" #'newsticker-show-extra)
+    (define-key map "hx" #'newsticker-hide-extra)
+
+    (define-key map [?\S-\ ] #'scroll-down-command)
+    (define-key map " "  #'scroll-up-command)
+    (define-key map "q"  #'newsticker-close-buffer)
+    (define-key map "p"  #'newsticker-previous-item)
+    (define-key map "P"  #'newsticker-previous-new-item)
+    (define-key map "F"  #'newsticker-previous-feed)
+    (define-key map "\t" #'newsticker-next-item)
+    (define-key map "n"  #'newsticker-next-item)
+    (define-key map "N"  #'newsticker-next-new-item)
+    (define-key map "f"  #'newsticker-next-feed)
+    (define-key map "M"  #'newsticker-mark-all-items-as-read)
+    (define-key map "m" 
#'newsticker-mark-all-items-at-point-as-read-and-redraw)
+    (define-key map "o"  #'newsticker-mark-item-at-point-as-read)
+    (define-key map "O"  #'newsticker-mark-all-items-at-point-as-read)
+    (define-key map "G"  #'newsticker-get-all-news)
+    (define-key map "g"  #'newsticker-get-news-at-point)
+    (define-key map "u"  #'newsticker-buffer-update)
+    (define-key map "U"  #'newsticker-buffer-force-update)
+    (define-key map "a"  #'newsticker-add-url)
+
+    (define-key map "i"  #'newsticker-mark-item-at-point-as-immortal)
+
+    (define-key map "xf" #'newsticker-toggle-auto-narrow-to-feed)
+    (define-key map "xi" #'newsticker-toggle-auto-narrow-to-item)
 
     ;; Bind menu to mouse.
     (define-key map [down-mouse-3] newsticker-menu)
@@ -479,11 +474,11 @@ images."
 ;; maps for the clickable portions
 (defvar newsticker--url-keymap
   (let ((map (make-sparse-keymap)))
-    (define-key map [mouse-1] 'newsticker-mouse-browse-url)
-    (define-key map [mouse-2] 'newsticker-mouse-browse-url)
-    (define-key map "\n" 'newsticker-browse-url)
-    (define-key map "\C-m" 'newsticker-browse-url)
-    (define-key map [(control return)] 'newsticker-handle-url)
+    (define-key map [mouse-1] #'newsticker-mouse-browse-url)
+    (define-key map [mouse-2] #'newsticker-mouse-browse-url)
+    (define-key map "\n" #'newsticker-browse-url)
+    (define-key map "\C-m" #'newsticker-browse-url)
+    (define-key map [(control return)] #'newsticker-handle-url)
     map)
   "Key map for click-able headings in the newsticker buffer.")
 
@@ -980,7 +975,7 @@ not get changed."
     (let* (pos1 pos2
                 (inhibit-read-only t)
                 inv-prop org-inv-prop
-                is-invisible)
+                ) ;; is-invisible
       (newsticker--buffer-beginning-of-item)
       (newsticker--buffer-goto '(desc))
       (setq pos1 (max (point-min) (1- (point))))
@@ -1009,7 +1004,7 @@ not get changed."
     (let* (pos1 pos2
                 (inhibit-read-only t)
                 inv-prop org-inv-prop
-                is-invisible)
+                ) ;; is-invisible
       (newsticker--buffer-beginning-of-item)
       (newsticker--buffer-goto '(desc))
       (setq pos1 (max (point-min) (1- (point))))
@@ -1147,7 +1142,7 @@ If VALUE is nil, auto-narrowing is turned off, otherwise 
it is turned on."
        (setq index-alist (list feed-list)))
       index-alist)))
 
-(defun newsticker--imenu-goto (name pos &rest args)
+(defun newsticker--imenu-goto (_name pos &rest _args)
   "Go to item NAME at position POS and show item.
 ARGS are ignored."
   (goto-char pos)
@@ -1236,6 +1231,9 @@ item-retrieval time is added as well."
   ;; insert the description
   (newsticker--buffer-do-insert-text item 'desc feed-name-symbol))
 
+(defvar w3m-fill-column)
+(defvar w3-maximum-line-length)
+
 (defun newsticker--buffer-do-insert-text (item type feed-name-symbol)
   "Actually insert contents of news item, format it, render it and all that.
 ITEM is a news item, TYPE tells which part of the item shall be inserted,
diff --git a/lisp/net/newst-reader.el b/lisp/net/newst-reader.el
index b188bd4..40e3044 100644
--- a/lisp/net/newst-reader.el
+++ b/lisp/net/newst-reader.el
@@ -1,4 +1,4 @@
-;;; newst-reader.el --- Generic RSS reader functions.
+;;; newst-reader.el --- Generic RSS reader functions.  -*- lexical-binding: t; 
-*-
 
 ;; Copyright (C) 2003-2021 Free Software Foundation, Inc.
 
@@ -94,7 +94,7 @@ done."
                  (const :tag "Right"      right)
                  (const :tag "Center"     center)
                  (const :tag "Full"       full))
-  :set 'newsticker--set-customvar-formatting
+  :set #'newsticker--set-customvar-formatting
   :group 'newsticker-reader)
 
 (defcustom newsticker-use-full-width
@@ -103,7 +103,7 @@ done."
 If non-nil newsticker sets `fill-column' so that the whole
 window is used when filling.  See also `newsticker-justification'."
   :type 'boolean
-  :set 'newsticker--set-customvar-formatting
+  :set #'newsticker--set-customvar-formatting
   :group 'newsticker-reader)
 
 (defcustom newsticker-html-renderer
@@ -122,7 +122,7 @@ htmlr if this option is set."
                  (const :tag "w3" w3-region)
                  (const :tag "w3m" w3m-region)
                  (const :tag "htmlr" newsticker-htmlr-render))
-  :set 'newsticker--set-customvar-formatting
+  :set #'newsticker--set-customvar-formatting
   :group 'newsticker-reader)
 
 (defcustom newsticker-date-format
@@ -130,7 +130,7 @@ htmlr if this option is set."
   "Format for the date part in item and feed lines.
 See `format-time-string' for a list of valid specifiers."
   :type 'string
-  :set 'newsticker--set-customvar-formatting
+  :set #'newsticker--set-customvar-formatting
   :group 'newsticker-reader)
 
 (defgroup newsticker-faces nil
diff --git a/lisp/net/newst-ticker.el b/lisp/net/newst-ticker.el
index 275c91a..2f76470 100644
--- a/lisp/net/newst-ticker.el
+++ b/lisp/net/newst-ticker.el
@@ -1,4 +1,4 @@
-;; newst-ticker.el --- mode line ticker for newsticker.
+;; newst-ticker.el --- mode line ticker for newsticker.  -*- lexical-binding: 
t; -*-
 
 ;; Copyright (C) 2003-2021 Free Software Foundation, Inc.
 
@@ -83,7 +83,7 @@ smooth display (see `newsticker-scroll-smoothly') a value of 
0.3 seems
 reasonable.  For non-smooth display a value of 10 is a good starting
 point."
   :type 'number
-  :set 'newsticker--set-customvar-ticker
+  :set #'newsticker--set-customvar-ticker
   :group 'newsticker-ticker)
 
 (defcustom newsticker-scroll-smoothly
@@ -104,7 +104,7 @@ at all.  If you change `newsticker-scroll-smoothly' you 
should also change
 If t the echo area will not show immortal items.  See also
 `newsticker-hide-old-items-in-echo-area'."
   :type 'boolean
-  :set 'newsticker--set-customvar-ticker
+  :set #'newsticker--set-customvar-ticker
   :group 'newsticker-ticker)
 
 (defcustom newsticker-hide-old-items-in-echo-area
@@ -113,7 +113,7 @@ If t the echo area will not show immortal items.  See also
 If t the echo area will show only new items, i.e. only items which have
 been added between the last two retrievals."
   :type 'boolean
-  :set 'newsticker--set-customvar-ticker
+  :set #'newsticker--set-customvar-ticker
   :group 'newsticker-ticker)
 
 (defcustom newsticker-hide-obsolete-items-in-echo-area
@@ -122,7 +122,7 @@ been added between the last two retrievals."
 If t the echo area will not show obsolete items.  See also
 `newsticker-hide-old-items-in-echo-area'."
   :type 'boolean
-  :set 'newsticker--set-customvar-ticker
+  :set #'newsticker--set-customvar-ticker
   :group 'newsticker-ticker)
 
 (defun newsticker--display-tick ()
@@ -205,7 +205,7 @@ running already."
       (setq newsticker--ticker-timer
             (run-at-time newsticker-ticker-interval
                          newsticker-ticker-interval
-                         'newsticker--display-tick))))
+                         #'newsticker--display-tick))))
 
 (defun newsticker-stop-ticker ()
   "Stop newsticker's ticker (but not the news retrieval)."
diff --git a/lisp/net/newst-treeview.el b/lisp/net/newst-treeview.el
index cf55f66..29c92d5 100644
--- a/lisp/net/newst-treeview.el
+++ b/lisp/net/newst-treeview.el
@@ -52,72 +52,73 @@
 (defface newsticker-treeview-face
   '((((class color) (background dark))  :foreground "white")
     (((class color) (background light)) :foreground "black"))
-  "Face for newsticker tree."
-  :group 'newsticker-treeview)
+  "Face for newsticker tree.")
 
 (defface newsticker-treeview-new-face
   '((t :inherit newsticker-treeview-face :weight bold))
-  "Face for newsticker tree."
-  :group 'newsticker-treeview)
+  "Face for newsticker tree.")
 
 (defface newsticker-treeview-old-face
   '((t :inherit newsticker-treeview-face))
-  "Face for newsticker tree."
-  :group 'newsticker-treeview)
+  "Face for newsticker tree.")
 
 (defface newsticker-treeview-immortal-face
   '((default :inherit newsticker-treeview-face :slant italic)
     (((class color) (background dark))  :foreground "orange")
     (((class color) (background light)) :foreground "blue"))
-  "Face for newsticker tree."
-  :group 'newsticker-treeview)
+  "Face for newsticker tree.")
 
 (defface newsticker-treeview-obsolete-face
   '((t :inherit newsticker-treeview-face :strike-through t))
-  "Face for newsticker tree."
-  :group 'newsticker-treeview)
+  "Face for newsticker tree.")
 
 (defface newsticker-treeview-selection-face
   '((((class color) (background dark))  :background "#4444aa")
     (((class color) (background light)) :background "#bbbbff"))
-  "Face for newsticker selection."
-  :group 'newsticker-treeview)
+  "Face for newsticker selection.")
 
 (defcustom newsticker-treeview-date-format
   "%d.%m.%y, %H:%M"
   "Format for the date column in the treeview list buffer.
 See `format-time-string' for a list of valid specifiers."
   :version "25.1"
-  :type 'string
-  :group 'newsticker-treeview)
+  :type 'string)
 
 (defcustom newsticker-treeview-own-frame
   nil
   "Decides whether newsticker treeview creates and uses its own frame."
-  :type 'boolean
-  :group 'newsticker-treeview)
+  :type 'boolean)
 
 (defcustom newsticker-treeview-treewindow-width
   30
   "Width of tree window in treeview layout.
 See also `newsticker-treeview-listwindow-height'."
-  :type 'integer
-  :group 'newsticker-treeview)
+  :type 'integer)
 
 (defcustom newsticker-treeview-listwindow-height
   10
   "Height of list window in treeview layout.
 See also `newsticker-treeview-treewindow-width'."
-  :type 'integer
-  :group 'newsticker-treeview)
+  :type 'integer)
 
 (defcustom newsticker-treeview-automatically-mark-displayed-items-as-old
   t
   "Decides whether to automatically mark displayed items as old.
 If t an item is marked as old as soon as it is displayed.  This
 applies to newsticker only."
-  :type 'boolean
-  :group 'newsticker-treeview)
+  :type 'boolean)
+
+(defcustom newsticker-treeview-use-feed-name-from-url-list-in-treeview
+  t
+  "Use the feed names from 'newsticker-url-list' for display in treeview."
+  :version "28.1"
+  :type 'boolean)
+
+(defcustom newsticker-treeview-use-feed-name-from-url-list-in-itemview
+  t
+  "Use feed names from 'newsticker-url-list' in itemview."
+  :version "28.1"
+  :type 'boolean)
 
 (defvar newsticker-groups
   '("Feeds")
@@ -152,14 +153,16 @@ Example: (\"Topmost group\" \"feed1\" (\"subgroup1\" 
\"feed 2\")
 (defvar newsticker--treeview-feed-tree nil)
 (defvar newsticker--treeview-vfeed-tree nil)
 
+(declare-function newsticker-handle-url "newst-plainview" ())
+
 ;; maps for the clickable portions
 (defvar newsticker--treeview-url-keymap
   (let ((map (make-sparse-keymap 'newsticker--treeview-url-keymap)))
-    (define-key map [mouse-1] 'newsticker-treeview-mouse-browse-url)
-    (define-key map [mouse-2] 'newsticker-treeview-mouse-browse-url)
-    (define-key map "\n" 'newsticker-treeview-browse-url)
-    (define-key map "\C-m" 'newsticker-treeview-browse-url)
-    (define-key map [(control return)] 'newsticker-handle-url)
+    (define-key map [mouse-1] #'newsticker-treeview-mouse-browse-url)
+    (define-key map [mouse-2] #'newsticker-treeview-mouse-browse-url)
+    (define-key map "\n" #'newsticker-treeview-browse-url)
+    (define-key map "\C-m" #'newsticker-treeview-browse-url)
+    (define-key map [(control return)] #'newsticker-handle-url)
     map)
   "Key map for click-able headings in the newsticker treeview buffers.")
 
@@ -328,9 +331,9 @@ If string SHOW-FEED is non-nil it is shown in the item 
string."
         (replace-match " "))
       (let ((map (make-sparse-keymap)))
         (dolist (key'([mouse-1] [mouse-3]))
-                    (define-key map key 'newsticker-treeview-tree-click))
-        (define-key map "\n" 'newsticker-treeview-show-item)
-        (define-key map "\C-m" 'newsticker-treeview-show-item)
+          (define-key map key #'newsticker-treeview-tree-click))
+        (define-key map "\n" #'newsticker-treeview-show-item)
+        (define-key map "\C-m" #'newsticker-treeview-show-item)
         (add-text-properties pos1 (point-max)
                              (list :nt-item item
                                    :nt-feed feed
@@ -612,9 +615,9 @@ If CLEAR-BUFFER is non-nil the list buffer is completely 
erased."
 (defvar newsticker-treeview-list-sort-button-map
   (let ((map (make-sparse-keymap)))
     (define-key map [header-line mouse-1]
-      'newsticker--treeview-list-sort-by-column)
+      #'newsticker--treeview-list-sort-by-column)
     (define-key map [header-line mouse-2]
-      'newsticker--treeview-list-sort-by-column)
+      #'newsticker--treeview-list-sort-by-column)
     map)
   "Local keymap for newsticker treeview list window sort buttons.")
 
@@ -738,11 +741,14 @@ for the button."
                (img (newsticker--image-read feed-name-symbol nil 40)))
           (if (and (display-images-p) img)
               (newsticker--insert-image img (car item))
-            (insert (newsticker--real-feed-name feed-name-symbol))))
+            (insert (if 
newsticker-treeview-use-feed-name-from-url-list-in-itemview
+                        (symbol-name feed-name-symbol)
+                      (newsticker--real-feed-name feed-name-symbol)))))
         (add-text-properties (point-min) (point)
                              (list 'face 'newsticker-feed-face
                                    'mouse-face 'highlight
-                                   'help-echo "Visit in web browser."
+                                   'help-echo (concat 
(newsticker--real-feed-name feed-name-symbol)
+                                                      "\nClick to visit in web 
browser.")
                                    :nt-link (newsticker--link item)
                                    'keymap newsticker--treeview-url-keymap))
         (setq pos (point))
@@ -933,31 +939,31 @@ Optional arguments CHANGED-WIDGET and EVENT are ignored."
     (newsticker-treeview-mode)))
 
 (defun newsticker--treeview-propertize-tag (tag &optional num-new nt-id feed
-                                                vfeed)
+                                                vfeed tooltip)
   "Return propertized copy of string TAG.
 Optional argument NUM-NEW is used for choosing face, other
-arguments NT-ID, FEED, and VFEED are added as properties."
+arguments NT-ID, FEED, VFEED and TOOLTIP are added as properties."
   ;;(message "newsticker--treeview-propertize-tag `%s' %s" feed nt-id)
   (let ((face 'newsticker-treeview-face)
         (map (make-sparse-keymap)))
     (if (and num-new (> num-new 0))
         (setq face 'newsticker-treeview-new-face))
     (dolist (key '([mouse-1] [mouse-3]))
-                 (define-key map key 'newsticker-treeview-tree-click))
-    (define-key map "\n" 'newsticker-treeview-tree-do-click)
-    (define-key map "\C-m" 'newsticker-treeview-tree-do-click)
+      (define-key map key #'newsticker-treeview-tree-click))
+    (define-key map "\n" #'newsticker-treeview-tree-do-click)
+    (define-key map "\C-m" #'newsticker-treeview-tree-do-click)
     (propertize tag 'face face 'keymap map
                 :nt-id nt-id
                 :nt-feed feed
                 :nt-vfeed vfeed
-                'help-echo tag
+                'help-echo tooltip
                 'mouse-face 'highlight)))
 
 (defun newsticker--treeview-tree-get-tag (feed-name vfeed-name
                                                     &optional nt-id)
   "Return a tag string for either FEED-NAME or, if it is nil, for VFEED-NAME.
 Optional argument NT-ID is added to the tag's properties."
-  (let (tag (num-new 0))
+  (let (tag tooltip (num-new 0))
     (cond (vfeed-name
            (cond ((string= vfeed-name "new")
                   (setq num-new (newsticker--stat-num-items-total 'new))
@@ -970,18 +976,29 @@ Optional argument NT-ID is added to the tag's properties."
                   (setq tag (format "Obsolete items (%d)" num-new)))
                  ((string= vfeed-name "all")
                   (setq num-new (newsticker--stat-num-items-total))
-                  (setq tag (format "All items (%d)" num-new)))))
+                  (setq tag (format "All items (%d)" num-new))))
+           (setq tooltip tag))
           (feed-name
            (setq num-new (newsticker--stat-num-items-for-group
                           (intern feed-name) 'new 'immortal))
            (setq tag
                  (format "%s (%d)"
-                         (newsticker--real-feed-name (intern feed-name))
-                         num-new))))
+                         (if 
newsticker-treeview-use-feed-name-from-url-list-in-itemview
+                             feed-name
+                           (newsticker--real-feed-name (intern feed-name)))
+                         num-new))
+           (setq tooltip
+                 (if (newsticker--group-get-group feed-name)
+                     tag
+                   (format "%s (%d)\n%s"
+                           feed-name
+                           num-new
+                           (newsticker--real-feed-name (intern feed-name)))))))
     (if tag
         (newsticker--treeview-propertize-tag tag num-new
                                              nt-id
-                                             feed-name vfeed-name))))
+                                             feed-name vfeed-name
+                                             tooltip))))
 
 (defun newsticker--stat-num-items-for-group (feed-name-symbol &rest ages)
   "Count number of items in feed FEED-NAME-SYMBOL that have an age matching 
AGES."
@@ -1085,6 +1102,7 @@ Arguments are ignored."
 ;; ======================================================================
 (defvar newsticker-treeview-tool-bar-map
   (when (boundp 'tool-bar-map)
+    (defvar tool-bar-map)
     (let ((tool-bar-map (make-sparse-keymap)))
       (tool-bar-add-item "newsticker/prev-feed"
                          'newsticker-treeview-prev-feed
@@ -1434,6 +1452,15 @@ Move to next item unless DONT-PROCEED is non-nil."
                                   newsticker--treeview-current-vfeed)
                               (newsticker--treeview-get-selected-item)))
 
+(defun newsticker-treeview-customize-current-feed ()
+  "Open customization buffer for `newsticker-url-list' and move to current 
feed."
+  (interactive)
+  (let ((cur-feed (or newsticker--treeview-current-feed
+                      newsticker--treeview-current-vfeed)))
+    (if (newsticker--group-get-group cur-feed)
+        (message "Cannot customize groups.  Please select a feed.")
+      (newsticker-customize-feed cur-feed))))
+
 (defun newsticker--treeview-set-current-node (node)
   "Make NODE the current node."
   (with-current-buffer (newsticker--treeview-tree-buffer)
@@ -1626,7 +1653,7 @@ Return t if a new feed was activated, nil otherwise."
   (interactive
    (list (let ((completion-ignore-case t))
            (completing-read
-            "Jump to feed: "
+            "Jump to feed/group: "
             (append '("new" "obsolete" "immortal" "all")
                     (mapcar #'car (append newsticker-url-list
                                           newsticker-url-list-defaults)))
@@ -1852,28 +1879,34 @@ of the shift.  If MOVE-GROUP is nil the currently 
selected feed
 `newsticker--treeview-current-feed' is shifted, if it is t then
 the current feed's parent group is shifted.."
   (let* ((cur-feed newsticker--treeview-current-feed)
-         (thing (if move-group
-                    (newsticker--group-find-parent-group cur-feed)
+         (thing (if (and move-group
+                         (not (newsticker--group-get-group cur-feed)))
+                    (car (newsticker--group-find-parent-group cur-feed))
                   cur-feed))
          (parent-group (newsticker--group-find-parent-group
-                        (if move-group (car thing) thing))))
+                        ;;(if move-group (car thing) thing)
+                        thing)))
     (unless parent-group
       (error "Group not found!"))
     (let* ((siblings (cdr parent-group))
-           (pos (cl-position thing siblings :test 'equal))
+           (pos (cl-position thing siblings :test
+                             (lambda (o1 o2)
+                               (equal (if (listp o1) (car o1) o1)
+                                      (if (listp o2) (car o2) o2)))))
            (tpos (+ pos delta ))
            (new-pos (max 0 (min (length siblings) tpos)))
            (beg (cl-subseq siblings 0 (min pos new-pos)))
            (end (cl-subseq siblings (+ 1 (max pos new-pos))))
            (p (elt siblings new-pos)))
       (when (not (= pos new-pos))
-        (setcdr parent-group
-                (cl-concatenate 'list
-                                beg
-                                (if (> delta 0)
-                                    (list p thing)
-                                  (list thing p))
-                                end))
+        (let ((th (or (newsticker--group-get-group thing) thing)))
+          (setcdr parent-group
+                  (cl-concatenate 'list
+                                  beg
+                                  (if (> delta 0)
+                                      (list p th)
+                                    (list th p))
+                                  end)))
         (newsticker--treeview-tree-update)
         (newsticker-treeview-update)
         (newsticker-treeview-jump cur-feed)))))
@@ -1986,36 +2019,37 @@ Return t if groups have changed, nil otherwise."
 
 (defvar newsticker-treeview-mode-map
   (let ((map (make-sparse-keymap 'newsticker-treeview-mode-map)))
-    (define-key map " " 'newsticker-treeview-next-page)
-    (define-key map "a" 'newsticker-add-url)
-    (define-key map "b" 'newsticker-treeview-browse-url-item)
-    (define-key map "F" 'newsticker-treeview-prev-feed)
-    (define-key map "f" 'newsticker-treeview-next-feed)
-    (define-key map "g" 'newsticker-treeview-get-news)
-    (define-key map "G" 'newsticker-get-all-news)
-    (define-key map "i" 'newsticker-treeview-toggle-item-immortal)
-    (define-key map "j" 'newsticker-treeview-jump)
-    (define-key map "n" 'newsticker-treeview-next-item)
-    (define-key map "N" 'newsticker-treeview-next-new-or-immortal-item)
-    (define-key map "O" 'newsticker-treeview-mark-list-items-old)
-    (define-key map "o" 'newsticker-treeview-mark-item-old)
-    (define-key map "p" 'newsticker-treeview-prev-item)
-    (define-key map "P" 'newsticker-treeview-prev-new-or-immortal-item)
-    (define-key map "q" 'newsticker-treeview-quit)
-    (define-key map "S" 'newsticker-treeview-save-item)
-    (define-key map "s" 'newsticker-treeview-save)
-    (define-key map "u" 'newsticker-treeview-update)
-    (define-key map "v" 'newsticker-treeview-browse-url)
-    ;;(define-key map "\n" 'newsticker-treeview-scroll-item)
-    ;;(define-key map "\C-m" 'newsticker-treeview-scroll-item)
-    (define-key map "\M-m" 'newsticker-group-move-feed)
-    (define-key map "\M-a" 'newsticker-group-add-group)
-    (define-key map "\M-d" 'newsticker-group-delete-group)
-    (define-key map "\M-r" 'newsticker-group-rename-group)
-    (define-key map [M-down] 'newsticker-group-shift-feed-down)
-    (define-key map [M-up] 'newsticker-group-shift-feed-up)
-    (define-key map [M-S-down] 'newsticker-group-shift-group-down)
-    (define-key map [M-S-up] 'newsticker-group-shift-group-up)
+    (define-key map " " #'newsticker-treeview-next-page)
+    (define-key map "a" #'newsticker-add-url)
+    (define-key map "b" #'newsticker-treeview-browse-url-item)
+    (define-key map "c" #'newsticker-treeview-customize-current-feed)
+    (define-key map "F" #'newsticker-treeview-prev-feed)
+    (define-key map "f" #'newsticker-treeview-next-feed)
+    (define-key map "g" #'newsticker-treeview-get-news)
+    (define-key map "G" #'newsticker-get-all-news)
+    (define-key map "i" #'newsticker-treeview-toggle-item-immortal)
+    (define-key map "j" #'newsticker-treeview-jump)
+    (define-key map "n" #'newsticker-treeview-next-item)
+    (define-key map "N" #'newsticker-treeview-next-new-or-immortal-item)
+    (define-key map "O" #'newsticker-treeview-mark-list-items-old)
+    (define-key map "o" #'newsticker-treeview-mark-item-old)
+    (define-key map "p" #'newsticker-treeview-prev-item)
+    (define-key map "P" #'newsticker-treeview-prev-new-or-immortal-item)
+    (define-key map "q" #'newsticker-treeview-quit)
+    (define-key map "S" #'newsticker-treeview-save-item)
+    (define-key map "s" #'newsticker-treeview-save)
+    (define-key map "u" #'newsticker-treeview-update)
+    (define-key map "v" #'newsticker-treeview-browse-url)
+    ;;(define-key map "\n" #'newsticker-treeview-scroll-item)
+    ;;(define-key map "\C-m" #'newsticker-treeview-scroll-item)
+    (define-key map "\M-m" #'newsticker-group-move-feed)
+    (define-key map "\M-a" #'newsticker-group-add-group)
+    (define-key map "\M-d" #'newsticker-group-delete-group)
+    (define-key map "\M-r" #'newsticker-group-rename-group)
+    (define-key map [M-down] #'newsticker-group-shift-feed-down)
+    (define-key map [M-up] #'newsticker-group-shift-feed-up)
+    (define-key map [M-S-down] #'newsticker-group-shift-group-down)
+    (define-key map [M-S-up] #'newsticker-group-shift-group-up)
     map)
   "Mode map for newsticker treeview.")
 
diff --git a/lisp/net/nsm.el b/lisp/net/nsm.el
index 0ce65a3..1d9ee6d 100644
--- a/lisp/net/nsm.el
+++ b/lisp/net/nsm.el
@@ -640,7 +640,7 @@ References:
 
 [1]: Sotirov A, Stevens M et al (2008).  \"MD5 considered harmful today
 - Creating a rogue CA certificate\",
-`http://www.win.tue.nl/hashclash/rogue-ca/'
+`https://www.win.tue.nl/hashclash/rogue-ca/'
 [2]: Turner S, Chen L (2011).  \"Updated Security Considerations for
 the MD5 Message-Digest and the HMAC-MD5 Algorithms\",
 `https://tools.ietf.org/html/rfc6151'"
diff --git a/lisp/net/puny.el b/lisp/net/puny.el
index 6b3663a..42a7e79 100644
--- a/lisp/net/puny.el
+++ b/lisp/net/puny.el
@@ -37,7 +37,7 @@ For instance, \"fśf.org\" => \"xn--ff-2sa.org\"."
   ;; add a check first to avoid doing unnecessary work.
   (if (string-match "\\`[[:ascii:]]+\\'" domain)
       domain
-    (mapconcat 'puny-encode-string (split-string domain "[.]") ".")))
+    (mapconcat #'puny-encode-string (split-string domain "[.]") ".")))
 
 (defun puny-encode-string (string)
   "Encode STRING according to the IDNA/punycode algorithm.
@@ -57,7 +57,7 @@ For instance, \"bücher\" => \"xn--bcher-kva\"."
 (defun puny-decode-domain (domain)
   "Decode DOMAIN according to the IDNA/punycode algorithm.
 For instance, \"xn--ff-2sa.org\" => \"fśf.org\"."
-  (mapconcat 'puny-decode-string (split-string domain "[.]") "."))
+  (mapconcat #'puny-decode-string (split-string domain "[.]") "."))
 
 (defun puny-decode-string (string)
   "Decode an IDNA/punycode-encoded string.
@@ -75,7 +75,7 @@ For instance \"xn--bcher-kva\" => \"bücher\"."
 (defconst puny-damp 700)
 (defconst puny-tmin 1)
 (defconst puny-tmax 26)
-(defconst puny-skew 28)
+(defconst puny-skew 38)
 
 ;; 0-25  a-z
 ;; 26-36 0-9
diff --git a/lisp/net/quickurl.el b/lisp/net/quickurl.el
index ab1f43f..2574c8c 100644
--- a/lisp/net/quickurl.el
+++ b/lisp/net/quickurl.el
@@ -1,4 +1,4 @@
-;;; quickurl.el --- insert a URL based on text at point in buffer
+;;; quickurl.el --- insert a URL based on text at point in buffer  -*- 
lexical-binding: t; -*-
 
 ;; Copyright (C) 1999-2021 Free Software Foundation, Inc.
 
@@ -97,23 +97,19 @@
   (locate-user-emacs-file "quickurls" ".quickurls")
   "File that contains the URL list."
   :version "24.4"                       ; added locate-user-emacs-file
-  :type  'file
-  :group 'quickurl)
+  :type  'file)
 
 (defcustom quickurl-format-function #'quickurl-format-url
   "Function to format the URL before insertion into the current buffer."
-  :type  'function
-  :group 'quickurl)
+  :type  'function)
 
 (defcustom quickurl-sort-function #'quickurl-sort-urls
   "Function to sort the URL list."
-  :type  'function
-  :group 'quickurl)
+  :type  'function)
 
 (defcustom quickurl-grab-lookup-function #'current-word
   "Function to grab the thing to lookup."
-  :type  'function
-  :group 'quickurl)
+  :type  'function)
 
 (defun quickurl--assoc-function (key alist)
   "Default function for `quickurl-assoc-function'."
@@ -122,31 +118,26 @@
 (defcustom quickurl-assoc-function #'quickurl--assoc-function
   "Function to use for alist lookup into `quickurl-urls'."
   :version "26.1"                 ; was the obsolete assoc-ignore-case
-  :type  'function
-  :group 'quickurl)
+  :type  'function)
 
 (defcustom quickurl-completion-ignore-case t
   "Should `quickurl-ask' ignore case when doing the input lookup?"
-  :type  'boolean
-  :group 'quickurl)
+  :type  'boolean)
 
 (defcustom quickurl-prefix ";; -*- lisp -*-\n\n"
   "Text to write to `quickurl-url-file' before writing the URL list."
-  :type  'string
-  :group 'quickurl)
+  :type  'string)
 
 (defcustom quickurl-postfix ""
   "Text to write to `quickurl-url-file' after writing the URL list.
 
 See the constant `quickurl-reread-hook-postfix' for some example text that
 could be used here."
-  :type  'string
-  :group 'quickurl)
+  :type  'string)
 
 (defcustom quickurl-list-mode-hook nil
   "Hooks for `quickurl-list-mode'."
-  :type  'hook
-  :group 'quickurl)
+  :type  'hook)
 
 ;; Constants.
 
diff --git a/lisp/net/rcirc.el b/lisp/net/rcirc.el
index 58cc8b1..938fadf 100644
--- a/lisp/net/rcirc.el
+++ b/lisp/net/rcirc.el
@@ -293,7 +293,7 @@ The following replacements are made:
 Setting this alone will not affect the prompt;
 use either M-x customize or also call `rcirc-update-prompt'."
   :type 'string
-  :set 'rcirc-set-changed
+  :set #'rcirc-set-changed
   :initialize 'custom-initialize-default)
 
 (defcustom rcirc-keywords nil
@@ -329,7 +329,8 @@ Called with 5 arguments, PROCESS, SENDER, RESPONSE, TARGET 
and TEXT."
   :type 'hook)
 
 (defvar rcirc-authenticated-hook nil
-  "Hook run after successfully authenticated.")
+  "Hook run after successfully authenticated.
+Functions in this hook are called with a single argument PROCESS.")
 
 (defcustom rcirc-always-use-server-buffer-flag nil
   "Non-nil means messages without a channel target will go to the server 
buffer."
diff --git a/lisp/net/secrets.el b/lisp/net/secrets.el
index ad27167..94db318 100644
--- a/lisp/net/secrets.el
+++ b/lisp/net/secrets.el
@@ -643,7 +643,7 @@ starting with a colon.  Example:
 The object labels of the found items are returned as list."
   (mapcar
    (lambda (item-path) (secrets-get-item-property item-path "Label"))
-   (apply 'secrets-search-item-paths collection attributes)))
+   (apply #'secrets-search-item-paths collection attributes)))
 
 (defun secrets-create-item (collection item password &rest attributes)
   "Create a new item in COLLECTION with label ITEM and password PASSWORD.
@@ -780,9 +780,9 @@ ITEM can also be an object path, which is used if contained 
in COLLECTION."
 (defvar secrets-mode-map
   (let ((map (make-sparse-keymap)))
     (set-keymap-parent map (make-composed-keymap special-mode-map 
widget-keymap))
-    (define-key map "n" 'next-line)
-    (define-key map "p" 'previous-line)
-    (define-key map "z" 'kill-current-buffer)
+    (define-key map "n" #'next-line)
+    (define-key map "p" #'previous-line)
+    (define-key map "z" #'kill-current-buffer)
     map)
   "Keymap used in `secrets-mode' buffers.")
 
@@ -859,7 +859,7 @@ to their attributes."
         ;; padding is needed to format attribute names.
         (padding
          (apply
-          'max
+          #'max
           (cons
            (1+ (length "password"))
            (mapcar
diff --git a/lisp/net/shr-color.el b/lisp/net/shr-color.el
index ac1f701..eb78a25 100644
--- a/lisp/net/shr-color.el
+++ b/lisp/net/shr-color.el
@@ -36,14 +36,12 @@
 (defcustom shr-color-visible-luminance-min 40
   "Minimum luminance distance between two colors to be considered visible.
 Must be between 0 and 100."
-  :group 'shr-color
   :type 'number)
 
 (defcustom shr-color-visible-distance-min 5
   "Minimum color distance between two colors to be considered visible.
 This value is used to compare result for `ciede2000'.  It's an
 absolute value without any unit."
-  :group 'shr-color
   :type 'integer)
 
 (defconst shr-color-html-colors-alist
@@ -332,8 +330,8 @@ color will be adapted to be visible on BG."
     (if (or (null fg-norm)
            (null bg-norm))
        (list bg fg)
-      (let* ((fg-lab (apply 'color-srgb-to-lab fg-norm))
-            (bg-lab (apply 'color-srgb-to-lab bg-norm))
+      (let* ((fg-lab (apply #'color-srgb-to-lab fg-norm))
+            (bg-lab (apply #'color-srgb-to-lab bg-norm))
             ;; Compute color distance using CIE DE 2000
             (fg-bg-distance (color-cie-de2000 fg-lab bg-lab))
             ;; Compute luminance distance (subtract L component)
@@ -351,12 +349,12 @@ color will be adapted to be visible on BG."
            (list
             (if fixed-background
                 bg
-              (apply 'format "#%02x%02x%02x"
+              (apply #'format "#%02x%02x%02x"
                      (mapcar (lambda (x) (* (max (min 1 x) 0) 255))
-                             (apply 'color-lab-to-srgb bg-lab))))
-            (apply 'format "#%02x%02x%02x"
+                             (apply #'color-lab-to-srgb bg-lab))))
+            (apply #'format "#%02x%02x%02x"
                    (mapcar (lambda (x) (* (max (min 1 x) 0) 255))
-                           (apply 'color-lab-to-srgb fg-lab))))))))))
+                           (apply #'color-lab-to-srgb fg-lab))))))))))
 
 (provide 'shr-color)
 
diff --git a/lisp/net/shr.el b/lisp/net/shr.el
index 9c3740f..c122a19 100644
--- a/lisp/net/shr.el
+++ b/lisp/net/shr.el
@@ -220,20 +220,20 @@ and other things:
 
 (defvar shr-map
   (let ((map (make-sparse-keymap)))
-    (define-key map "a" 'shr-show-alt-text)
-    (define-key map "i" 'shr-browse-image)
-    (define-key map "z" 'shr-zoom-image)
-    (define-key map [?\t] 'shr-next-link)
-    (define-key map [?\M-\t] 'shr-previous-link)
+    (define-key map "a" #'shr-show-alt-text)
+    (define-key map "i" #'shr-browse-image)
+    (define-key map "z" #'shr-zoom-image)
+    (define-key map [?\t] #'shr-next-link)
+    (define-key map [?\M-\t] #'shr-previous-link)
     (define-key map [follow-link] 'mouse-face)
-    (define-key map [mouse-2] 'shr-browse-url)
-    (define-key map [C-down-mouse-1] 'shr-mouse-browse-url-new-window)
-    (define-key map "I" 'shr-insert-image)
-    (define-key map "w" 'shr-maybe-probe-and-copy-url)
-    (define-key map "u" 'shr-maybe-probe-and-copy-url)
-    (define-key map "v" 'shr-browse-url)
-    (define-key map "O" 'shr-save-contents)
-    (define-key map "\r" 'shr-browse-url)
+    (define-key map [mouse-2] #'shr-browse-url)
+    (define-key map [C-down-mouse-1] #'shr-mouse-browse-url-new-window)
+    (define-key map "I" #'shr-insert-image)
+    (define-key map "w" #'shr-maybe-probe-and-copy-url)
+    (define-key map "u" #'shr-maybe-probe-and-copy-url)
+    (define-key map "v" #'shr-browse-url)
+    (define-key map "O" #'shr-save-contents)
+    (define-key map "\r" #'shr-browse-url)
     map))
 
 (defvar shr-image-map
@@ -434,6 +434,7 @@ Value is a pair of positions (START . END) if there is a 
non-nil
 
 (defun shr-show-alt-text ()
   "Show the ALT text of the image under point."
+  (declare (completion (lambda (_ b) (command-completion-button-p 'shr b))))
   (interactive)
   (let ((text (get-text-property (point) 'shr-alt)))
     (if (not text)
diff --git a/lisp/net/sieve-mode.el b/lisp/net/sieve-mode.el
index 7bc1d16..966f0f0 100644
--- a/lisp/net/sieve-mode.el
+++ b/lisp/net/sieve-mode.el
@@ -139,9 +139,9 @@
 
 (defvar sieve-mode-map
   (let ((map (make-sparse-keymap)))
-    (define-key map "\C-c\C-l" 'sieve-upload)
-    (define-key map "\C-c\C-c" 'sieve-upload-and-kill)
-    (define-key map "\C-c\C-m" 'sieve-manage)
+    (define-key map "\C-c\C-l" #'sieve-upload)
+    (define-key map "\C-c\C-c" #'sieve-upload-and-kill)
+    (define-key map "\C-c\C-m" #'sieve-manage)
     map)
   "Key map used in sieve mode.")
 
diff --git a/lisp/net/sieve.el b/lisp/net/sieve.el
index ca10026..595d633 100644
--- a/lisp/net/sieve.el
+++ b/lisp/net/sieve.el
@@ -1,4 +1,4 @@
-;;; sieve.el --- Utilities to manage sieve scripts
+;;; sieve.el --- Utilities to manage sieve scripts  -*- lexical-binding: t; -*-
 
 ;; Copyright (C) 2001-2021 Free Software Foundation, Inc.
 
@@ -69,13 +69,11 @@
 
 (defcustom sieve-new-script "<new script>"
   "Name of name script indicator."
-  :type 'string
-  :group 'sieve)
+  :type 'string)
 
 (defcustom sieve-buffer "*sieve*"
   "Name of sieve management buffer."
-  :type 'string
-  :group 'sieve)
+  :type 'string)
 
 (defcustom sieve-template "\
 require \"fileinto\";
@@ -91,8 +89,7 @@ require \"fileinto\";
 # }
 "
   "Template sieve script."
-  :type 'string
-  :group 'sieve)
+  :type 'string)
 
 ;; Internal variables:
 
@@ -104,31 +101,36 @@ require \"fileinto\";
 
 ;; Sieve-manage mode:
 
+;; This function is defined by `easy-menu-define' but it's only done
+;; at run time and the compiler is not aware of it.
+;; FIXME: This is arguably a bug/problem in `easy-menu-define'.
+(declare-function sieve-manage-mode-menu "sieve")
+
 (defvar sieve-manage-mode-map
   (let ((map (make-sparse-keymap)))
     ;; various
-    (define-key map "?" 'sieve-help)
-    (define-key map "h" 'sieve-help)
+    (define-key map "?" #'sieve-help)
+    (define-key map "h" #'sieve-help)
     ;; activating
-    (define-key map "m" 'sieve-activate)
-    (define-key map "u" 'sieve-deactivate)
-    (define-key map "\M-\C-?" 'sieve-deactivate-all)
+    (define-key map "m" #'sieve-activate)
+    (define-key map "u" #'sieve-deactivate)
+    (define-key map "\M-\C-?" #'sieve-deactivate-all)
     ;; navigation keys
-    (define-key map "\C-p" 'sieve-prev-line)
-    (define-key map [up] 'sieve-prev-line)
-    (define-key map "\C-n" 'sieve-next-line)
-    (define-key map [down] 'sieve-next-line)
-    (define-key map " " 'sieve-next-line)
-    (define-key map "n" 'sieve-next-line)
-    (define-key map "p" 'sieve-prev-line)
-    (define-key map "\C-m" 'sieve-edit-script)
-    (define-key map "f" 'sieve-edit-script)
-    (define-key map "o" 'sieve-edit-script-other-window)
-    (define-key map "r" 'sieve-remove)
-    (define-key map "q" 'sieve-bury-buffer)
-    (define-key map "Q" 'sieve-manage-quit)
-    (define-key map [(down-mouse-2)] 'sieve-edit-script)
-    (define-key map [(down-mouse-3)] 'sieve-manage-mode-menu)
+    (define-key map "\C-p" #'sieve-prev-line)
+    (define-key map [up] #'sieve-prev-line)
+    (define-key map "\C-n" #'sieve-next-line)
+    (define-key map [down] #'sieve-next-line)
+    (define-key map " " #'sieve-next-line)
+    (define-key map "n" #'sieve-next-line)
+    (define-key map "p" #'sieve-prev-line)
+    (define-key map "\C-m" #'sieve-edit-script)
+    (define-key map "f" #'sieve-edit-script)
+    ;; (define-key map "o" #'sieve-edit-script-other-window)
+    (define-key map "r" #'sieve-remove)
+    (define-key map "q" #'sieve-bury-buffer)
+    (define-key map "Q" #'sieve-manage-quit)
+    (define-key map [(down-mouse-2)] #'sieve-edit-script)
+    (define-key map [(down-mouse-3)] #'sieve-manage-mode-menu)
     map)
   "Keymap for `sieve-manage-mode'.")
 
@@ -159,8 +161,8 @@ require \"fileinto\";
   (interactive)
   (bury-buffer))
 
-(defun sieve-activate (&optional pos)
-  (interactive "d")
+(defun sieve-activate (&optional _pos)
+  (interactive)
   (let ((name (sieve-script-at-point)) err)
     (when (or (null name) (string-equal name sieve-new-script))
       (error "No sieve script at point"))
@@ -171,20 +173,20 @@ require \"fileinto\";
        (message "Activating script %s...done" name)
       (message "Activating script %s...failed: %s" name (nth 2 err)))))
 
-(defun sieve-deactivate-all (&optional pos)
-  (interactive "d")
-  (let ((name (sieve-script-at-point)) err)
-    (message "Deactivating scripts...")
-    (setq err (sieve-manage-setactive "" sieve-manage-buffer))
+(defun sieve-deactivate-all (&optional _pos)
+  (interactive)
+  (message "Deactivating scripts...")
+  (let (;; (name (sieve-script-at-point))
+        (err (sieve-manage-setactive "" sieve-manage-buffer)))
     (sieve-refresh-scriptlist)
     (if (sieve-manage-ok-p err)
        (message "Deactivating scripts...done")
       (message "Deactivating scripts...failed: %s" (nth 2 err)))))
 
-(defalias 'sieve-deactivate 'sieve-deactivate-all)
+(defalias 'sieve-deactivate #'sieve-deactivate-all)
 
-(defun sieve-remove (&optional pos)
-  (interactive "d")
+(defun sieve-remove (&optional _pos)
+  (interactive)
   (let ((name (sieve-script-at-point)) err)
     (when (or (null name) (string-equal name sieve-new-script))
       (error "No sieve script at point"))
@@ -195,8 +197,8 @@ require \"fileinto\";
     (sieve-refresh-scriptlist)
     (message "Removing sieve script %s...done" name)))
 
-(defun sieve-edit-script (&optional pos)
-  (interactive "d")
+(defun sieve-edit-script (&optional _pos)
+  (interactive)
   (let ((name (sieve-script-at-point)))
     (unless name
       (error "No sieve script at point"))
@@ -224,11 +226,11 @@ require \"fileinto\";
 (defmacro sieve-change-region (&rest body)
   "Turns off sieve-region before executing BODY, then re-enables it after.
 Used to bracket operations which move point in the sieve-buffer."
+  (declare (indent 0) (debug t))
   `(progn
      (sieve-highlight nil)
      ,@body
      (sieve-highlight t)))
-(put 'sieve-change-region 'lisp-indent-function 0)
 
 (defun sieve-next-line (&optional arg)
   (interactive)
diff --git a/lisp/net/snmp-mode.el b/lisp/net/snmp-mode.el
index 983e6d9..ae878ef 100644
--- a/lisp/net/snmp-mode.el
+++ b/lisp/net/snmp-mode.el
@@ -1,4 +1,4 @@
-;;; snmp-mode.el --- SNMP & SNMPv2 MIB major mode
+;;; snmp-mode.el --- SNMP & SNMPv2 MIB major mode  -*- lexical-binding: t -*-
 
 ;; Copyright (C) 1995, 1998, 2001-2021 Free Software Foundation, Inc.
 
@@ -69,16 +69,6 @@
 ;; Once the template is done, you can use C-cC-f and C-cC-b to move back
 ;; and forth between the Tempo sequence points to fill in the rest of
 ;; the information.
-;;
-;; Font Lock
-;; ------------
-;;
-;; If you want font-lock in your MIB buffers, add this:
-;;
-;;  (add-hook 'snmp-common-mode-hook 'turn-on-font-lock)
-;;
-;; Enabling global-font-lock-mode is also sufficient.
-;;
 
 ;;; Code:
 
@@ -101,42 +91,35 @@
 (defcustom snmp-special-indent t
   "If non-nil, use a simple heuristic to try to guess the right indentation.
 If nil, then no special indentation is attempted."
-  :type 'boolean
-  :group 'snmp)
+  :type 'boolean)
 
 (defcustom snmp-indent-level 4
   "Indentation level for SNMP MIBs."
-  :type 'integer
-  :group 'snmp)
+  :type 'integer)
 
 (defcustom snmp-tab-always-indent nil
   "Non-nil means TAB should always reindent the current line.
 A value of nil means reindent if point is within the initial line indentation;
 otherwise insert a TAB."
-  :type 'boolean
-  :group 'snmp)
+  :type 'boolean)
 
 (defcustom snmp-completion-ignore-case t
   "Non-nil means that case differences are ignored during completion.
 A value of nil means that case is significant.
 This is used during Tempo template completion."
-  :type 'boolean
-  :group 'snmp)
+  :type 'boolean)
 
 (defcustom snmp-common-mode-hook nil
   "Hook(s) evaluated when a buffer enters either SNMP or SNMPv2 mode."
-  :type 'hook
-  :group 'snmp)
+  :type 'hook)
 
 (defcustom snmp-mode-hook nil
   "Hook(s) evaluated when a buffer enters SNMP mode."
-  :type 'hook
-  :group 'snmp)
+  :type 'hook)
 
 (defcustom snmpv2-mode-hook nil
   "Hook(s) evaluated when a buffer enters SNMPv2 mode."
-  :type 'hook
-  :group 'snmp)
+  :type 'hook)
 
 (defvar snmp-tempo-tags nil
   "Tempo tags for SNMP mode.")
@@ -291,7 +274,7 @@ This is used during Tempo template completion."
 
 ;; Set up the stuff that's common between snmp-mode and snmpv2-mode
 ;;
-(defun snmp-common-mode (name mode abbrev font-keywords imenu-index tempo-tags)
+(defun snmp-common-mode (name mode abbrev font-keywords imenu-index 
mode-tempo-tags)
   (kill-all-local-variables)
 
   ;; Become the current major mode
@@ -326,7 +309,7 @@ This is used during Tempo template completion."
   (setq-local imenu-create-index-function imenu-index)
 
   ;; Tempo
-  (tempo-use-tag-list tempo-tags)
+  (tempo-use-tag-list mode-tempo-tags)
   (setq-local tempo-match-finder "\\b\\(.+\\)\\=")
   (setq-local tempo-interactive t)
 
@@ -338,6 +321,7 @@ This is used during Tempo template completion."
 ;;
 ;;;###autoload
 (defun snmp-mode ()
+  ;; FIXME: Use define-derived-mode.
   "Major mode for editing SNMP MIBs.
 Expression and list commands understand all C brackets.
 Tab indents for C code.
@@ -370,6 +354,7 @@ Turning on snmp-mode runs the hooks in 
`snmp-common-mode-hook', then
 
 ;;;###autoload
 (defun snmpv2-mode ()
+  ;; FIXME: Use define-derived-mode.
   "Major mode for editing SNMPv2 MIBs.
 Expression and list commands understand all C brackets.
 Tab indents for C code.
@@ -474,13 +459,11 @@ lines for the purposes of this function."
        (index-table-alist '())
        (index-trap-alist '())
         (case-fold-search nil) ; keywords must be uppercase
-       prev-pos token end)
+        token end)
     (goto-char (point-min))
-    (imenu-progress-message prev-pos 0)
     ;; Search for a useful MIB item (that's not in a comment)
     (save-match-data
       (while (re-search-forward snmp-clause-regexp nil t)
-        (imenu-progress-message prev-pos)
         (setq
          end (match-end 0)
          token (cons (match-string 1)
@@ -498,7 +481,6 @@ lines for the purposes of this function."
                (push token index-tc-alist)))
         (goto-char end)))
     ;; Create the menu
-    (imenu-progress-message prev-pos 100)
     (setq index-alist (nreverse index-alist))
     (and index-tc-alist
         (push (cons "Textual Conventions" (nreverse index-tc-alist))
diff --git a/lisp/net/soap-client.el b/lisp/net/soap-client.el
index 3cc5569..821ef4a 100644
--- a/lisp/net/soap-client.el
+++ b/lisp/net/soap-client.el
@@ -10,6 +10,7 @@
 ;; Package: soap-client
 ;; Homepage: https://github.com/alex-hhh/emacs-soap-client
 ;; Package-Requires: ((cl-lib "0.6.1"))
+;;FIXME: Put in `Package-Requires:' the Emacs version we expect.
 
 ;; This file is part of GNU Emacs.
 
@@ -771,6 +772,8 @@ This is a specialization of `soap-decode-type' for
         (Array (soap-decode-array node))))))
 
 (defalias 'soap-type-of
+  ;; FIXME: Once we drop support for Emacs<25, use generic functions
+  ;; via `cl-defmethod' instead of our own ad-hoc version of it.
   (if (eq 'soap-xs-basic-type (type-of (make-soap-xs-basic-type)))
       ;; `type-of' in Emacs ≥ 26 already does what we need.
       #'type-of
@@ -1263,7 +1266,7 @@ See also `soap-wsdl-resolve-references'."
              (soap-l2wk (xml-node-name node)))
 
   (setf (soap-xs-simple-type-base type)
-        (mapcar 'soap-l2fq
+        (mapcar #'soap-l2fq
                 (split-string
                  (or (xml-get-attribute-or-nil node 'memberTypes) ""))))
 
@@ -1343,7 +1346,7 @@ See also `soap-wsdl-resolve-references'."
                               (soap-validate-xs-basic-type value base))))
               (error (push (cadr error-object) messages))))
           (when messages
-            (error (mapconcat 'identity (nreverse messages) "; and: "))))
+            (error (mapconcat #'identity (nreverse messages) "; and: "))))
       (cl-labels ((fail-with-message (format value)
                                      (push (format format value) messages)
                                      (throw 'invalid nil)))
@@ -2345,8 +2348,8 @@ See also `soap-resolve-references' and
 
   (when (= (length (soap-operation-parameter-order operation)) 0)
     (setf (soap-operation-parameter-order operation)
-          (mapcar 'car (soap-message-parts
-                        (cdr (soap-operation-input operation))))))
+          (mapcar #'car (soap-message-parts
+                         (cdr (soap-operation-input operation))))))
 
   (setf (soap-operation-parameter-order operation)
         (mapcar (lambda (p)
@@ -2391,13 +2394,13 @@ See also `soap-wsdl-resolve-references'."
 ;; Install resolvers for our types
 (progn
   (put (soap-type-of (make-soap-message)) 'soap-resolve-references
-       'soap-resolve-references-for-message)
+       #'soap-resolve-references-for-message)
   (put (soap-type-of (make-soap-operation)) 'soap-resolve-references
-       'soap-resolve-references-for-operation)
+       #'soap-resolve-references-for-operation)
   (put (soap-type-of (make-soap-binding)) 'soap-resolve-references
-       'soap-resolve-references-for-binding)
+       #'soap-resolve-references-for-binding)
   (put (soap-type-of (make-soap-port)) 'soap-resolve-references
-       'soap-resolve-references-for-port))
+       #'soap-resolve-references-for-port))
 
 (defun soap-wsdl-resolve-references (wsdl)
   "Resolve all references inside the WSDL structure.
@@ -2511,7 +2514,7 @@ Build on WSDL if it is provided."
     (soap-wsdl-resolve-references (soap-parse-wsdl xml wsdl))
     wsdl))
 
-(defalias 'soap-load-wsdl-from-url 'soap-load-wsdl)
+(defalias 'soap-load-wsdl-from-url #'soap-load-wsdl)
 
 (defun soap-parse-wsdl-phase-validate-node (node)
   "Assert that NODE is valid."
@@ -2884,7 +2887,7 @@ decode function to perform the actual decoding."
 
 (if (fboundp 'define-error)
     (define-error 'soap-error "SOAP error")
-  ;; Support older Emacs versions that do not have define-error, so
+  ;; Support Emacs<24.4 that do not have define-error, so
   ;; that soap-client can remain unchanged in GNU ELPA.
   (put 'soap-error
        'error-conditions
@@ -3123,8 +3126,7 @@ http://schemas.xmlsoap.org/soap/encoding/\"\n";))
 
 (defcustom soap-debug nil
   "When t, enable some debugging facilities."
-  :type 'boolean
-  :group 'soap-client)
+  :type 'boolean)
 
 (defun soap-find-port (wsdl service)
   "Return the WSDL port having SERVICE name.
diff --git a/lisp/net/soap-inspect.el b/lisp/net/soap-inspect.el
index 9d4e440..6f9ce6a 100644
--- a/lisp/net/soap-inspect.el
+++ b/lisp/net/soap-inspect.el
@@ -109,7 +109,7 @@ soap-xs-attribute objects."
 This is a specialization of `soap-sample-value' for
 `soap-xs-simple-type' objects."
   (append
-   (mapcar 'soap-sample-value-for-xs-attribute
+   (mapcar #'soap-sample-value-for-xs-attribute
            (soap-xs-type-attributes type))
    (cond
     ((soap-xs-simple-type-enumeration type)
@@ -143,7 +143,7 @@ This is a specialization of `soap-sample-value' for
 This is a specialization of `soap-sample-value' for
 `soap-xs-complex-type' objects."
   (append
-   (mapcar 'soap-sample-value-for-xs-attribute
+   (mapcar #'soap-sample-value-for-xs-attribute
            (soap-xs-type-attributes type))
    (cl-case (soap-xs-complex-type-indicator type)
      (array
@@ -176,31 +176,31 @@ This is a specialization of `soap-sample-value' for
   ;; Install soap-sample-value methods for our types
   (put (soap-type-of (make-soap-xs-basic-type))
        'soap-sample-value
-       'soap-sample-value-for-xs-basic-type)
+       #'soap-sample-value-for-xs-basic-type)
 
   (put (soap-type-of (make-soap-xs-element))
        'soap-sample-value
-       'soap-sample-value-for-xs-element)
+       #'soap-sample-value-for-xs-element)
 
   (put (soap-type-of (make-soap-xs-attribute))
        'soap-sample-value
-       'soap-sample-value-for-xs-attribute)
+       #'soap-sample-value-for-xs-attribute)
 
   (put (soap-type-of (make-soap-xs-attribute))
        'soap-sample-value
-       'soap-sample-value-for-xs-attribute-group)
+       #'soap-sample-value-for-xs-attribute-group)
 
   (put (soap-type-of (make-soap-xs-simple-type))
        'soap-sample-value
-       'soap-sample-value-for-xs-simple-type)
+       #'soap-sample-value-for-xs-simple-type)
 
   (put (soap-type-of (make-soap-xs-complex-type))
        'soap-sample-value
-       'soap-sample-value-for-xs-complex-type)
+       #'soap-sample-value-for-xs-complex-type)
 
   (put (soap-type-of (make-soap-message))
        'soap-sample-value
-       'soap-sample-value-for-message))
+       #'soap-sample-value-for-message))
 
 
 
@@ -437,7 +437,7 @@ TYPE is a `soap-xs-complex-type'."
         (funcall (list 'soap-invoke '*WSDL* "SomeService"
                        (soap-element-name operation))))
     (let ((sample-invocation
-           (append funcall (mapcar 'cdr sample-message-value))))
+           (append funcall (mapcar #'cdr sample-message-value))))
       (pp sample-invocation (current-buffer)))))
 
 (defun soap-inspect-port-type (port-type)
@@ -460,7 +460,7 @@ TYPE is a `soap-xs-complex-type'."
                               collect o))
          op-name-width)
 
-    (setq operations (sort operations 'string<))
+    (setq operations (sort operations #'string<))
 
     (setq op-name-width (cl-loop for o in operations maximizing (length o)))
 
@@ -504,39 +504,39 @@ TYPE is a `soap-xs-complex-type'."
   ;; Install the soap-inspect methods for our types
 
   (put (soap-type-of (make-soap-xs-basic-type)) 'soap-inspect
-       'soap-inspect-xs-basic-type)
+       #'soap-inspect-xs-basic-type)
 
   (put (soap-type-of (make-soap-xs-element)) 'soap-inspect
-       'soap-inspect-xs-element)
+       #'soap-inspect-xs-element)
 
   (put (soap-type-of (make-soap-xs-simple-type)) 'soap-inspect
-       'soap-inspect-xs-simple-type)
+       #'soap-inspect-xs-simple-type)
 
   (put (soap-type-of (make-soap-xs-complex-type)) 'soap-inspect
-       'soap-inspect-xs-complex-type)
+       #'soap-inspect-xs-complex-type)
 
   (put (soap-type-of (make-soap-xs-attribute)) 'soap-inspect
-       'soap-inspect-xs-attribute)
+       #'soap-inspect-xs-attribute)
 
   (put (soap-type-of (make-soap-xs-attribute-group)) 'soap-inspect
-       'soap-inspect-xs-attribute-group)
+       #'soap-inspect-xs-attribute-group)
 
   (put (soap-type-of (make-soap-message)) 'soap-inspect
-       'soap-inspect-message)
+       #'soap-inspect-message)
   (put (soap-type-of (make-soap-operation)) 'soap-inspect
-       'soap-inspect-operation)
+       #'soap-inspect-operation)
 
   (put (soap-type-of (make-soap-port-type)) 'soap-inspect
-       'soap-inspect-port-type)
+       #'soap-inspect-port-type)
 
   (put (soap-type-of (make-soap-binding)) 'soap-inspect
-       'soap-inspect-binding)
+       #'soap-inspect-binding)
 
   (put (soap-type-of (make-soap-port)) 'soap-inspect
-       'soap-inspect-port)
+       #'soap-inspect-port)
 
   (put (soap-type-of (soap-make-wsdl "origin")) 'soap-inspect
-       'soap-inspect-wsdl))
+       #'soap-inspect-wsdl))
 
 (provide 'soap-inspect)
 ;;; soap-inspect.el ends here
diff --git a/lisp/net/socks.el b/lisp/net/socks.el
index 96fafc8..1da1d31 100644
--- a/lisp/net/socks.el
+++ b/lisp/net/socks.el
@@ -390,6 +390,8 @@
       proc)))
 
 (defun socks-send-command (proc command atype address port)
+  "Send COMMAND to SOCKS service PROC for proxying ADDRESS and PORT.
+When ATYPE indicates an IP, param ADDRESS must be given as raw bytes."
   (let ((addr (cond
               ((or (= atype socks-address-type-v4)
                    (= atype socks-address-type-v6))
@@ -528,7 +530,7 @@
                (setq host (socks-nslookup-host host))
                (if (not (listp host))
                    (error "Could not get IP address for: %s" host))
-               (setq host (apply #'format "%c%c%c%c" host))
+               (setq host (apply #'unibyte-string host))
                 socks-address-type-v4)
                (t
                 socks-address-type-name))))
diff --git a/lisp/net/telnet.el b/lisp/net/telnet.el
index 44f535f..bb65eca 100644
--- a/lisp/net/telnet.el
+++ b/lisp/net/telnet.el
@@ -1,4 +1,4 @@
-;;; telnet.el --- run a telnet session from within an Emacs buffer
+;;; telnet.el --- run a telnet session from within an Emacs buffer  -*- 
lexical-binding: t; -*-
 
 ;; Copyright (C) 1985, 1988, 1992, 1994, 2001-2021 Free Software
 ;; Foundation, Inc.
@@ -63,11 +63,11 @@ LOGIN-NAME, which is optional, says what to log in as on 
that machine.")
 (defvar telnet-new-line "\r")
 (defvar telnet-mode-map
   (let ((map (nconc (make-sparse-keymap) comint-mode-map)))
-    (define-key map "\C-m" 'telnet-send-input)
-    ;; (define-key map "\C-j" 'telnet-send-input)
-    (define-key map "\C-c\C-q" 'send-process-next-char)
-    (define-key map "\C-c\C-c" 'telnet-interrupt-subjob)
-    (define-key map "\C-c\C-z" 'telnet-c-z)
+    (define-key map "\C-m" #'telnet-send-input)
+    ;; (define-key map "\C-j" #'telnet-send-input)
+    (define-key map "\C-c\C-q" #'send-process-next-char)
+    (define-key map "\C-c\C-c" #'telnet-interrupt-subjob)
+    (define-key map "\C-c\C-z" #'telnet-c-z)
     map))
 
 (defvar telnet-prompt-pattern "^[^#$%>\n]*[#$%>] *")
@@ -152,7 +152,7 @@ rejecting one login and prompting again for a username and 
password.")
            (t (telnet-check-software-type-initialize string)
               (telnet-filter proc string)
               (cond ((> telnet-count telnet-maximum-count)
-                     (set-process-filter proc 'telnet-filter))
+                     (set-process-filter proc #'telnet-filter))
                     (t (setq telnet-count (1+ telnet-count)))))))))
 
 ;; Identical to comint-simple-send, except that it sends telnet-new-line
@@ -227,9 +227,9 @@ Normally input is edited in Emacs and sent a line at a 
time."
     (if (and buffer (get-buffer-process buffer))
        (switch-to-buffer (concat "*" name "*"))
       (switch-to-buffer
-       (apply 'make-comint name telnet-program nil telnet-options))
+       (apply #'make-comint name telnet-program nil telnet-options))
       (setq process (get-buffer-process (current-buffer)))
-      (set-process-filter process 'telnet-initial-filter)
+      (set-process-filter process #'telnet-initial-filter)
       ;; Don't send the `open' cmd till telnet is ready for it.
       (accept-process-output process)
       (erase-buffer)
@@ -263,7 +263,7 @@ Normally input is edited in Emacs and sent a line at a 
time."
   (require 'shell)
   (let ((name (concat "rsh-" host )))
     (switch-to-buffer (make-comint name remote-shell-program nil host))
-    (set-process-filter (get-process name) 'telnet-initial-filter)
+    (set-process-filter (get-process name) #'telnet-initial-filter)
     (telnet-mode)
     (setq-local telnet-connect-command (list 'rsh host))
     (setq telnet-count -16)))
diff --git a/lisp/net/tramp-adb.el b/lisp/net/tramp-adb.el
index 6ec4d1f..aacf83e 100644
--- a/lisp/net/tramp-adb.el
+++ b/lisp/net/tramp-adb.el
@@ -44,7 +44,6 @@
   :version "24.4"
   :type 'string)
 
-;;;###tramp-autoload
 (defcustom tramp-adb-connect-if-not-connected nil
   "Try to run `adb connect' if provided device is not connected currently.
 It is used for TCP/IP devices."
@@ -56,7 +55,6 @@ It is used for TCP/IP devices."
 (defconst tramp-adb-method "adb"
   "When this method name is used, forward all calls to Android Debug Bridge.")
 
-;;;###tramp-autoload
 (defcustom tramp-adb-prompt "^[^#$\n\r]*[#$][[:space:]]"
   "Regexp used as prompt in almquist shell."
   :type 'regexp
diff --git a/lisp/net/tramp-cache.el b/lisp/net/tramp-cache.el
index 2b0a4d9..2fcb7b1 100644
--- a/lisp/net/tramp-cache.el
+++ b/lisp/net/tramp-cache.el
@@ -162,16 +162,20 @@ Return DEFAULT if not set."
     (tramp-message
      key 8 "%s %s %s; inhibit: %s; cache used: %s; cached at: %s"
      file property value remote-file-name-inhibit-cache cache-used cached-at)
+    ;; For analysis purposes, count the number of getting this file attribute.
     (when (>= tramp-verbose 10)
       (let* ((var (intern (concat "tramp-cache-get-count-" property)))
-            (val (or (numberp (bound-and-true-p var))
-                     (progn
-                       (add-hook 'tramp-cache-unload-hook
-                                 (lambda () (makunbound var)))
-                       0))))
+            (val (or (and (boundp var) (numberp (symbol-value var))
+                          (symbol-value var))
+                     0)))
        (set var (1+ val))))
     value))
 
+(add-hook 'tramp-cache-unload-hook
+         (lambda ()
+           (dolist (var (all-completions "tramp-cache-get-count-" obarray))
+             (unintern var obarray))))
+
 ;;;###tramp-autoload
 (defun tramp-set-file-property (key file property value)
   "Set the PROPERTY of FILE to VALUE, in the cache context of KEY.
@@ -186,16 +190,20 @@ Return VALUE."
     ;; We put the timestamp there.
     (puthash property (cons (current-time) value) hash)
     (tramp-message key 8 "%s %s %s" file property value)
+    ;; For analysis purposes, count the number of setting this file attribute.
     (when (>= tramp-verbose 10)
       (let* ((var (intern (concat "tramp-cache-set-count-" property)))
-            (val (or (numberp (bound-and-true-p var))
-                     (progn
-                       (add-hook 'tramp-cache-unload-hook
-                                 (lambda () (makunbound var)))
-                       0))))
+            (val (or (and (boundp var) (numberp (symbol-value var))
+                          (symbol-value var))
+                     0)))
        (set var (1+ val))))
     value))
 
+(add-hook 'tramp-cache-unload-hook
+         (lambda ()
+           (dolist (var (all-completions "tramp-cache-set-count-" obarray))
+             (unintern var obarray))))
+
 ;;;###tramp-autoload
 (defun tramp-flush-file-property (key file property)
   "Remove PROPERTY of FILE in the cache context of KEY."
diff --git a/lisp/net/tramp-cmds.el b/lisp/net/tramp-cmds.el
index 097f25e..d208f0e 100644
--- a/lisp/net/tramp-cmds.el
+++ b/lisp/net/tramp-cmds.el
@@ -144,11 +144,18 @@ When called interactively, a Tramp connection has to be 
selected."
 ;;;###tramp-autoload
 (defun tramp-cleanup-this-connection ()
   "Flush all connection related objects of the current buffer's connection."
+  ;; (declare (completion tramp-command-completion-p)))
   (interactive)
   (and (tramp-tramp-file-p default-directory)
        (tramp-cleanup-connection
        (tramp-dissect-file-name default-directory 'noexpand))))
 
+;; Starting with Emacs 28.1, this can be replaced by the "(declare ...)" form.
+;;;###tramp-autoload
+(function-put
+ #'tramp-cleanup-this-connection 'completion-predicate
+ #'tramp-command-completion-p)
+
 ;;;###tramp-autoload
 (defvar tramp-cleanup-all-connections-hook nil
   "List of functions to be called after all Tramp connections are cleaned up.")
@@ -201,7 +208,6 @@ This includes password cache, file cache, connection cache, 
buffers."
   (dolist (name (tramp-list-remote-buffers))
     (when (bufferp (get-buffer name)) (kill-buffer name))))
 
-;;;###tramp-autoload
 (defcustom tramp-default-rename-alist nil
   "Default target for renaming remote buffer file names.
 This is an alist of cons cells (SOURCE . TARGET).  The first
@@ -224,7 +230,6 @@ expression which always matches."
   :type '(repeat (cons (choice :tag "Source regexp" regexp sexp)
                       (choice :tag "Target   name" string (const nil)))))
 
-;;;###tramp-autoload
 (defcustom tramp-confirm-rename-file-names t
   "Whether renaming a buffer file name must be confirmed."
   :group 'tramp
@@ -243,7 +248,7 @@ function returns nil"
          (host (or (file-remote-p string 'host) ""))
          item result)
       (while (setq item (pop tdra))
-       (when (string-match-p (or (eval (car item)) "") string)
+       (when (string-match-p (or (eval (car item) t) "") string)
          (setq tdra nil
                result
                (format-spec
@@ -431,6 +436,7 @@ Interactively, TARGET is selected from 
`tramp-default-rename-alist'
 without confirmation if the prefix argument is non-nil.
 
 For details, see `tramp-rename-files'."
+  ;; (declare (completion tramp-command-completion-p))
   (interactive
    (let ((source default-directory)
         target
@@ -461,11 +467,16 @@ For details, see `tramp-rename-files'."
 
   (tramp-rename-files default-directory target))
 
+;; Starting with Emacs 28.1, this can be replaced by the "(declare ...)" form.
+;;;###tramp-autoload
+(function-put
+ #'tramp-rename-these-files 'completion-predicate #'tramp-command-completion-p)
+
 ;; Tramp version is useful in a number of situations.
 
 ;;;###tramp-autoload
 (defun tramp-version (arg)
-  "Print version number of tramp.el in minibuffer or current buffer."
+  "Print version number of tramp.el in echo area or current buffer."
   (interactive "P")
   (if arg (insert tramp-version) (message tramp-version)))
 
diff --git a/lisp/net/tramp-compat.el b/lisp/net/tramp-compat.el
index 27461e6..b67de1b 100644
--- a/lisp/net/tramp-compat.el
+++ b/lisp/net/tramp-compat.el
@@ -70,7 +70,7 @@
 It is the default value of `temporary-file-directory'."
   ;; We must return a local directory.  If it is remote, we could run
   ;; into an infloop.
-  (eval (car (get 'temporary-file-directory 'standard-value))))
+  (eval (car (get 'temporary-file-directory 'standard-value)) t))
 
 (defsubst tramp-compat-make-temp-name ()
   "Generate a local temporary file name (compat function)."
diff --git a/lisp/net/tramp-crypt.el b/lisp/net/tramp-crypt.el
index f8de708..1d8c0ad 100644
--- a/lisp/net/tramp-crypt.el
+++ b/lisp/net/tramp-crypt.el
@@ -112,6 +112,18 @@ initializing a new crypted remote directory."
   "Non-nil when encryption support is available.")
 (setq tramp-crypt-enabled (executable-find tramp-crypt-encfs-program))
 
+;; This function takes action since Emacs 28.1, when
+;; `read-extended-command-predicate' is set to
+;; `command-completion-default-include-p'.
+(defun tramp-crypt-command-completion-p (symbol _buffer)
+  "A predicate for Tramp interactive commands.
+They are completed by \"M-x TAB\" only when encryption support is enabled."
+  (and tramp-crypt-enabled
+       ;; `tramp-crypt-remove-directory' needs to be completed only in
+       ;; case we have already crypted directories.
+       (or (not (eq symbol #'tramp-crypt-remove-directory))
+          tramp-crypt-directories)))
+
 ;;;###tramp-autoload
 (defconst tramp-crypt-encfs-config ".encfs6.xml"
   "Encfs configuration file name.")
@@ -481,10 +493,17 @@ directory.  File names will be also encrypted."
     (setq tramp-crypt-directories (cons name tramp-crypt-directories)))
   (tramp-register-file-name-handlers))
 
+;; `tramp-crypt-command-completion-p' is not autoloaded, and this
+;; setting isn't either.
+(function-put
+ #'tramp-crypt-add-directory 'completion-predicate
+ #'tramp-crypt-command-completion-p)
+
 (defun tramp-crypt-remove-directory (name)
   "Unmark remote directory NAME for encryption.
 Existing files in that directory and its subdirectories will be
 kept in their encrypted form."
+  ;; (declare (completion tramp-crypt-command-completion-p))
   (interactive "DRemote directory name: ")
   (unless tramp-crypt-enabled
     (tramp-user-error nil "Feature is not enabled."))
@@ -498,6 +517,11 @@ kept in their encrypted form."
     (setq tramp-crypt-directories (delete name tramp-crypt-directories))
     (tramp-register-file-name-handlers)))
 
+;; Starting with Emacs 28.1, this can be replaced by the "(declare ...)" form.
+(function-put
+ #'tramp-crypt-remove-directory 'completion-predicate
+ #'tramp-crypt-command-completion-p)
+
 ;; `auth-source' requires a user.
 (defun tramp-crypt-dissect-file-name (name)
   "Return a `tramp-file-name' structure for NAME.
diff --git a/lisp/net/tramp-fuse.el b/lisp/net/tramp-fuse.el
new file mode 100644
index 0000000..ec1db86
--- /dev/null
+++ b/lisp/net/tramp-fuse.el
@@ -0,0 +1,205 @@
+;;; tramp-fuse.el --- Tramp access functions for FUSE mounts  -*- 
lexical-binding:t -*-
+
+;; Copyright (C) 2021 Free Software Foundation, Inc.
+
+;; Author: Michael Albinus <michael.albinus@gmx.de>
+;; Keywords: comm, processes
+;; Package: tramp
+
+;; 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:
+
+;; These are helper functions for FUSE file systems.
+
+;;; Code:
+
+(require 'tramp)
+
+;; File name primitives.
+
+(defun tramp-fuse-handle-delete-directory
+    (directory &optional recursive trash)
+  "Like `delete-directory' for Tramp files."
+  (with-parsed-tramp-file-name (expand-file-name directory) nil
+    (tramp-flush-directory-properties v localname)
+    (delete-directory (tramp-fuse-local-file-name directory) recursive trash)))
+
+(defun tramp-fuse-handle-delete-file (filename &optional trash)
+  "Like `delete-file' for Tramp files."
+  (with-parsed-tramp-file-name (expand-file-name filename) nil
+    (delete-file (tramp-fuse-local-file-name filename) trash)
+    (tramp-flush-file-properties v localname)))
+
+(defun tramp-fuse-handle-directory-files
+    (directory &optional full match nosort count)
+  "Like `directory-files' for Tramp files."
+  (unless (file-exists-p directory)
+    (tramp-compat-file-missing (tramp-dissect-file-name directory) directory))
+  (when (file-directory-p directory)
+    (setq directory (file-name-as-directory (expand-file-name directory)))
+    (with-parsed-tramp-file-name directory nil
+      (let ((result
+            (tramp-compat-directory-files
+             (tramp-fuse-local-file-name directory) full match nosort count)))
+       ;; Massage the result.
+       (when full
+         (let ((local (concat "^" (regexp-quote (tramp-fuse-mount-point v))))
+               (remote (directory-file-name
+                        (funcall
+                         (if (tramp-compat-file-name-quoted-p directory)
+                             #'tramp-compat-file-name-quote #'identity)
+                         (file-remote-p directory)))))
+           (setq result
+                 (mapcar
+                  (lambda (x) (replace-regexp-in-string local remote x))
+                  result))))
+       ;; Some storage systems do not return "." and "..".
+       (dolist (item '(".." "."))
+         (when (and (string-match-p (or match (regexp-quote item)) item)
+                    (not
+                     (member (if full (setq item (concat directory item)) item)
+                             result)))
+           (setq result (cons item result))))
+       ;; Return result.
+       (if nosort result (sort result #'string<))))))
+
+(defun tramp-fuse-handle-file-attributes (filename &optional id-format)
+  "Like `file-attributes' for Tramp files."
+  (with-parsed-tramp-file-name (expand-file-name filename) nil
+    (with-tramp-file-property
+        v localname (format "file-attributes-%s" id-format)
+      (file-attributes (tramp-fuse-local-file-name filename) id-format))))
+
+(defun tramp-fuse-handle-file-executable-p (filename)
+  "Like `file-executable-p' for Tramp files."
+  (with-parsed-tramp-file-name (expand-file-name filename) nil
+    (with-tramp-file-property v localname "file-executable-p"
+      (file-executable-p (tramp-fuse-local-file-name filename)))))
+
+(defun tramp-fuse-handle-file-name-all-completions (filename directory)
+  "Like `file-name-all-completions' for Tramp files."
+  (all-completions
+   filename
+   (delete-dups
+    (append
+     (file-name-all-completions
+      filename (tramp-fuse-local-file-name directory))
+     ;; Some storage systems do not return "." and "..".
+     (let (result)
+       (dolist (item '(".." ".") result)
+        (when (string-prefix-p filename item)
+          (catch 'match
+            (dolist (elt completion-regexp-list)
+              (unless (string-match-p elt item) (throw 'match nil)))
+            (setq result (cons (concat item "/") result))))))))))
+
+(defun tramp-fuse-handle-file-readable-p (filename)
+  "Like `file-readable-p' for Tramp files."
+  (with-parsed-tramp-file-name (expand-file-name filename) nil
+    (with-tramp-file-property v localname "file-readable-p"
+      (file-readable-p (tramp-fuse-local-file-name filename)))))
+
+;; This function isn't used.
+(defun tramp-fuse-handle-insert-directory
+    (filename switches &optional wildcard full-directory-p)
+  "Like `insert-directory' for Tramp files."
+  (insert-directory
+   (tramp-fuse-local-file-name filename) switches wildcard full-directory-p)
+  (goto-char (point-min))
+  (while (search-forward (tramp-fuse-local-file-name filename) nil 'noerror)
+    (replace-match filename)))
+
+(defun tramp-fuse-handle-make-directory (dir &optional parents)
+  "Like `make-directory' for Tramp files."
+  (with-parsed-tramp-file-name (expand-file-name dir) nil
+    (make-directory (tramp-fuse-local-file-name dir) parents)
+    ;; When PARENTS is non-nil, DIR could be a chain of non-existent
+    ;; directories a/b/c/...  Instead of checking, we simply flush the
+    ;; whole file cache.
+    (tramp-flush-file-properties v localname)
+    (tramp-flush-directory-properties
+     v (if parents "/" (file-name-directory localname)))))
+
+
+;; File name helper functions.
+
+(defun tramp-fuse-mount-spec (vec)
+  "Return local mount spec of VEC."
+  (if-let ((host (tramp-file-name-host vec))
+          (user (tramp-file-name-user vec)))
+      (format "%s@%s:/" user host)
+    (format "%s:/" host)))
+
+(defun tramp-fuse-mount-point (vec)
+  "Return local mount point of VEC."
+  (or (tramp-get-connection-property vec "mount-point" nil)
+      (expand-file-name
+       (concat
+       tramp-temp-name-prefix
+       (tramp-file-name-method vec) "."
+       (when (tramp-file-name-user vec)
+         (concat (tramp-file-name-user-domain vec) "@"))
+       (tramp-file-name-host-port vec))
+       (tramp-compat-temporary-file-directory))))
+
+(defun tramp-fuse-mounted-p (vec)
+  "Check, whether fuse volume determined by VEC is mounted."
+  (when (tramp-get-connection-process vec)
+    ;; We cannot use `with-connection-property', because we don't want
+    ;; to cache a nil result.
+    (or (tramp-get-connection-property
+         (tramp-get-connection-process vec) "mounted" nil)
+        (let* ((default-directory (tramp-compat-temporary-file-directory))
+               (fuse (concat "fuse." (tramp-file-name-method vec)))
+               (mount (shell-command-to-string (format "mount -t %s" fuse))))
+          (tramp-message vec 6 "%s %s" "mount -t" fuse)
+          (tramp-message vec 6 "\n%s" mount)
+          (tramp-set-connection-property
+           (tramp-get-connection-process vec) "mounted"
+           (when (string-match
+                 (format
+                   "^\\(%s\\)\\s-" (regexp-quote (tramp-fuse-mount-spec vec)))
+                 mount)
+             (match-string 1 mount)))))))
+
+(defun tramp-fuse-local-file-name (filename)
+  "Return local mount name of FILENAME."
+  (setq filename (tramp-compat-file-name-unquote (expand-file-name filename)))
+  (with-parsed-tramp-file-name filename nil
+    ;; As long as we call `tramp-*-maybe-open-connection' here,
+    ;; we cache the result.
+    (with-tramp-file-property v localname "local-file-name"
+      (funcall
+       (intern
+       (format "tramp-%s-maybe-open-connection" (tramp-file-name-method v)))
+       v)
+      (let ((quoted (tramp-compat-file-name-quoted-p localname))
+           (localname (tramp-compat-file-name-unquote localname)))
+       (funcall
+        (if quoted #'tramp-compat-file-name-quote #'identity)
+        (expand-file-name
+         (if (file-name-absolute-p localname)
+             (substring localname 1) localname)
+         (tramp-fuse-mount-point v)))))))
+
+(add-hook 'tramp-unload-hook
+         (lambda ()
+           (unload-feature 'tramp-fuse 'force)))
+
+(provide 'tramp-fuse)
+
+;;; tramp-fuse.el ends here
diff --git a/lisp/net/tramp-gvfs.el b/lisp/net/tramp-gvfs.el
index e946d73..c4ec112 100644
--- a/lisp/net/tramp-gvfs.el
+++ b/lisp/net/tramp-gvfs.el
@@ -175,7 +175,6 @@ They are checked during start up via
                    (dbus-list-known-names :session))
       (setq tramp-media-methods (delete method tramp-media-methods)))))
 
-;;;###tramp-autoload
 (defcustom tramp-gvfs-zeroconf-domain "local"
   "Zeroconf domain to be used for discovering services, like host names."
   :group 'tramp
@@ -1172,6 +1171,9 @@ file names."
       ;; There might be a double slash.  Remove this.
       (while (string-match "//" localname)
        (setq localname (replace-match "/" t t localname)))
+      ;; Do not keep "/..".
+      (when (string-match-p "^/\\.\\.?$" localname)
+       (setq localname "/"))
       ;; No tilde characters in file name, do normal
       ;; `expand-file-name' (this does "/./" and "/../").
       (tramp-make-tramp-file-name
diff --git a/lisp/net/tramp-integration.el b/lisp/net/tramp-integration.el
index 64b5b48..2931b4f 100644
--- a/lisp/net/tramp-integration.el
+++ b/lisp/net/tramp-integration.el
@@ -49,6 +49,7 @@
 (defvar recentf-exclude)
 (defvar tramp-current-connection)
 (defvar tramp-postfix-host-format)
+(defvar tramp-use-ssh-controlmaster-options)
 
 ;;; Fontification of `read-file-name':
 
@@ -231,7 +232,7 @@ NAME must be equal to `tramp-current-connection'."
             (delete (info-lookup->mode-cache 'symbol 'tramp-info-lookup-mode)
                     (info-lookup->topic-cache 'symbol)))))
 
-  (dolist (mode (mapcar 'car (info-lookup->topic-value 'symbol)))
+  (dolist (mode (mapcar #'car (info-lookup->topic-value 'symbol)))
     ;; Add `tramp-info-lookup-mode' to `other-modes' for either
     ;; `emacs-lisp-mode' itself, or to modes which use
     ;; `emacs-lisp-mode' as `other-modes'.  Reset `info-lookup-cache'.
@@ -261,6 +262,23 @@ NAME must be equal to `tramp-current-connection'."
                  (delete (info-lookup->mode-cache 'symbol ',mode)
                          (info-lookup->topic-cache 'symbol))))))))
 
+;;; Integration of compile.el:
+
+;; Compilation processes use `accept-process-output' such a way that
+;; Tramp's parallel `accept-process-output' blocks.  See last part of
+;; Bug#45518.  So we don't use ssh ControlMaster options.
+(defun tramp-compile-disable-ssh-controlmaster-options ()
+  "Don't allow ssh ControlMaster while compiling."
+  (setq-local tramp-use-ssh-controlmaster-options nil))
+
+(with-eval-after-load 'compile
+  (add-hook 'compilation-mode-hook
+           #'tramp-compile-disable-ssh-controlmaster-options)
+  (add-hook 'tramp-integration-unload-hook
+           (lambda ()
+             (remove-hook 'compilation-start-hook
+                          #'tramp-compile-disable-ssh-controlmaster-options))))
+
 ;;; Default connection-local variables for Tramp:
 ;; `connection-local-set-profile-variables' and
 ;; `connection-local-set-profiles' exists since Emacs 26.1.
@@ -277,7 +295,7 @@ NAME must be equal to `tramp-current-connection'."
 
 (tramp-compat-funcall
  'connection-local-set-profiles
- `(:application tramp)
+ '(:application tramp)
  'tramp-connection-local-default-system-profile)
 
 (defconst tramp-connection-local-default-shell-variables
@@ -293,7 +311,7 @@ NAME must be equal to `tramp-current-connection'."
 (with-eval-after-load 'shell
   (tramp-compat-funcall
    'connection-local-set-profiles
-   `(:application tramp)
+   '(:application tramp)
    'tramp-connection-local-default-shell-profile))
 
 (add-hook 'tramp-unload-hook
diff --git a/lisp/net/tramp-rclone.el b/lisp/net/tramp-rclone.el
index 96f7d9a..3b6de3e 100644
--- a/lisp/net/tramp-rclone.el
+++ b/lisp/net/tramp-rclone.el
@@ -35,14 +35,13 @@
 
 ;;; Code:
 
-(eval-when-compile (require 'cl-lib))
 (require 'tramp)
+(require 'tramp-fuse)
 
 ;;;###tramp-autoload
 (defconst tramp-rclone-method "rclone"
   "When this method name is used, forward all calls to rclone mounts.")
 
-;;;###tramp-autoload
 (defcustom tramp-rclone-program "rclone"
   "Name of the rclone program."
   :group 'tramp
@@ -53,7 +52,12 @@
 (tramp--with-startup
  (add-to-list 'tramp-methods
              `(,tramp-rclone-method
-               (tramp-mount-args nil)
+               ;; Be careful changing "--dir-cache-time", this could
+               ;; delay visibility of files.  Since we use Tramp's
+               ;; internal cache for file attributes, there shouldn't
+               ;; be serious performance penalties when set to 0.
+               (tramp-mount-args
+                ("--no-unicode-normalization" "--dir-cache-time" "0s"))
                (tramp-copyto-args nil)
                (tramp-moveto-args nil)
                (tramp-about-args ("--full"))))
@@ -72,11 +76,11 @@
     ;; `byte-compiler-base-file-name' performed by default handler.
     (copy-directory . tramp-handle-copy-directory)
     (copy-file . tramp-rclone-handle-copy-file)
-    (delete-directory . tramp-rclone-handle-delete-directory)
-    (delete-file . tramp-rclone-handle-delete-file)
+    (delete-directory . tramp-fuse-handle-delete-directory)
+    (delete-file . tramp-fuse-handle-delete-file)
     ;; `diff-latest-backup-file' performed by default handler.
     (directory-file-name . tramp-handle-directory-file-name)
-    (directory-files . tramp-rclone-handle-directory-files)
+    (directory-files . tramp-fuse-handle-directory-files)
     (directory-files-and-attributes
      . tramp-handle-directory-files-and-attributes)
     (dired-compress-file . ignore)
@@ -85,15 +89,15 @@
     (expand-file-name . tramp-handle-expand-file-name)
     (file-accessible-directory-p . tramp-handle-file-accessible-directory-p)
     (file-acl . ignore)
-    (file-attributes . tramp-rclone-handle-file-attributes)
+    (file-attributes . tramp-fuse-handle-file-attributes)
     (file-directory-p . tramp-handle-file-directory-p)
     (file-equal-p . tramp-handle-file-equal-p)
-    (file-executable-p . tramp-rclone-handle-file-executable-p)
+    (file-executable-p . tramp-fuse-handle-file-executable-p)
     (file-exists-p . tramp-handle-file-exists-p)
     (file-in-directory-p . tramp-handle-file-in-directory-p)
     (file-local-copy . tramp-handle-file-local-copy)
     (file-modes . tramp-handle-file-modes)
-    (file-name-all-completions . tramp-rclone-handle-file-name-all-completions)
+    (file-name-all-completions . tramp-fuse-handle-file-name-all-completions)
     (file-name-as-directory . tramp-handle-file-name-as-directory)
     (file-name-case-insensitive-p . tramp-handle-file-name-case-insensitive-p)
     (file-name-completion . tramp-handle-file-name-completion)
@@ -105,7 +109,7 @@
     (file-notify-rm-watch . ignore)
     (file-notify-valid-p . ignore)
     (file-ownership-preserved-p . ignore)
-    (file-readable-p . tramp-rclone-handle-file-readable-p)
+    (file-readable-p . tramp-fuse-handle-file-readable-p)
     (file-regular-p . tramp-handle-file-regular-p)
     (file-remote-p . tramp-handle-file-remote-p)
     (file-selinux-context . tramp-handle-file-selinux-context)
@@ -119,7 +123,7 @@
     (insert-file-contents . tramp-handle-insert-file-contents)
     (load . tramp-handle-load)
     (make-auto-save-file-name . tramp-handle-make-auto-save-file-name)
-    (make-directory . tramp-rclone-handle-make-directory)
+    (make-directory . tramp-fuse-handle-make-directory)
     (make-directory-internal . ignore)
     (make-nearby-temp-file . tramp-handle-make-nearby-temp-file)
     (make-process . ignore)
@@ -247,24 +251,13 @@ file names."
               "Error %s `%s' `%s'" msg-operation filename newname)))
 
          (when (and t1 (eq op 'rename))
-           (with-parsed-tramp-file-name filename v1
-             (tramp-flush-file-properties v1 v1-localname)
-             (when (tramp-rclone-file-name-p filename)
-               (tramp-rclone-flush-directory-cache v1)
-               ;; The mount point's directory cache might need time
-               ;; to flush.
-               (while (file-exists-p filename)
-                 (tramp-flush-file-properties v1 v1-localname)))))
+           (while (file-exists-p filename)
+             (with-parsed-tramp-file-name filename v1
+               (tramp-flush-file-properties v1 v1-localname))))
 
          (when t2
            (with-parsed-tramp-file-name newname v2
-             (tramp-flush-file-properties v2 v2-localname)
-             (when (tramp-rclone-file-name-p newname)
-               (tramp-rclone-flush-directory-cache v2)
-               ;; The mount point's directory cache might need time
-               ;; to flush.
-               (while (not (file-exists-p newname))
-                 (tramp-flush-file-properties v2 v2-localname))))))))))
+             (tramp-flush-file-properties v2 v2-localname))))))))
 
 (defun tramp-rclone-handle-copy-file
   (filename newname &optional ok-if-already-exists keep-date
@@ -283,88 +276,6 @@ file names."
      (list filename newname ok-if-already-exists keep-date
           preserve-uid-gid preserve-extended-attributes))))
 
-(defun tramp-rclone-handle-delete-directory
-    (directory &optional recursive trash)
-  "Like `delete-directory' for Tramp files."
-  (with-parsed-tramp-file-name (expand-file-name directory) nil
-    (tramp-flush-directory-properties v localname)
-    (tramp-rclone-flush-directory-cache v)
-    (delete-directory (tramp-rclone-local-file-name directory) recursive 
trash)))
-
-(defun tramp-rclone-handle-delete-file (filename &optional trash)
-  "Like `delete-file' for Tramp files."
-  (with-parsed-tramp-file-name (expand-file-name filename) nil
-    (tramp-rclone-flush-directory-cache v)
-    (delete-file (tramp-rclone-local-file-name filename) trash)
-    (tramp-flush-file-properties v localname)))
-
-(defun tramp-rclone-handle-directory-files
-    (directory &optional full match nosort count)
-  "Like `directory-files' for Tramp files."
-  (unless (file-exists-p directory)
-    (tramp-compat-file-missing (tramp-dissect-file-name directory) directory))
-  (when (file-directory-p directory)
-    (setq directory (file-name-as-directory (expand-file-name directory)))
-    (with-parsed-tramp-file-name directory nil
-      (let ((result
-            (tramp-compat-directory-files
-             (tramp-rclone-local-file-name directory) full match nosort 
count)))
-       ;; Massage the result.
-       (when full
-         (let ((local (concat "^" (regexp-quote (tramp-rclone-mount-point v))))
-               (remote (funcall (if (tramp-compat-file-name-quoted-p directory)
-                                    #'tramp-compat-file-name-quote #'identity)
-                                (file-remote-p directory))))
-           (setq result
-                 (mapcar
-                  (lambda (x) (replace-regexp-in-string local remote x))
-                  result))))
-       ;; Some storage systems do not return "." and "..".
-       (dolist (item '(".." "."))
-         (when (and (string-match-p (or match (regexp-quote item)) item)
-                    (not
-                     (member (if full (setq item (concat directory item)) item)
-                             result)))
-           (setq result (cons item result))))
-       ;; Return result.
-       (if nosort result (sort result #'string<))))))
-
-(defun tramp-rclone-handle-file-attributes (filename &optional id-format)
-  "Like `file-attributes' for Tramp files."
-  (with-parsed-tramp-file-name (expand-file-name filename) nil
-    (with-tramp-file-property
-       v localname (format "file-attributes-%s" id-format)
-      (file-attributes (tramp-rclone-local-file-name filename) id-format))))
-
-(defun tramp-rclone-handle-file-executable-p (filename)
-  "Like `file-executable-p' for Tramp files."
-  (with-parsed-tramp-file-name (expand-file-name filename) nil
-    (with-tramp-file-property v localname "file-executable-p"
-      (file-executable-p (tramp-rclone-local-file-name filename)))))
-
-(defun tramp-rclone-handle-file-name-all-completions (filename directory)
-  "Like `file-name-all-completions' for Tramp files."
-  (all-completions
-   filename
-   (delete-dups
-    (append
-     (file-name-all-completions
-      filename (tramp-rclone-local-file-name directory))
-     ;; Some storage systems do not return "." and "..".
-     (let (result)
-       (dolist (item '(".." ".") result)
-        (when (string-prefix-p filename item)
-          (catch 'match
-            (dolist (elt completion-regexp-list)
-              (unless (string-match-p elt item) (throw 'match nil)))
-            (setq result (cons (concat item "/") result))))))))))
-
-(defun tramp-rclone-handle-file-readable-p (filename)
-  "Like `file-readable-p' for Tramp files."
-  (with-parsed-tramp-file-name (expand-file-name filename) nil
-    (with-tramp-file-property v localname "file-readable-p"
-      (file-readable-p (tramp-rclone-local-file-name filename)))))
-
 (defun tramp-rclone-handle-file-system-info (filename)
   "Like `file-system-info' for Tramp files."
   (ignore-errors
@@ -392,37 +303,6 @@ file names."
          (when (and total free)
            (list total free (- total free))))))))
 
-(defun tramp-rclone-handle-insert-directory
-  (filename switches &optional wildcard full-directory-p)
-  "Like `insert-directory' for Tramp files."
-  (insert-directory
-   (tramp-rclone-local-file-name filename) switches wildcard full-directory-p)
-  (goto-char (point-min))
-  (while (search-forward (tramp-rclone-local-file-name filename) nil 'noerror)
-    (replace-match filename)))
-
-(defun tramp-rclone-handle-insert-file-contents
-  (filename &optional visit beg end replace)
-  "Like `insert-file-contents' for Tramp files."
-  (let ((result
-        (insert-file-contents
-         (tramp-rclone-local-file-name filename) visit beg end replace)))
-    (prog1
-       (list (expand-file-name filename) (cadr result))
-      (when visit (setq buffer-file-name filename)))))
-
-(defun tramp-rclone-handle-make-directory (dir &optional parents)
-  "Like `make-directory' for Tramp files."
-  (with-parsed-tramp-file-name (expand-file-name dir) nil
-    (make-directory (tramp-rclone-local-file-name dir) parents)
-    ;; When PARENTS is non-nil, DIR could be a chain of non-existent
-    ;; directories a/b/c/...  Instead of checking, we simply flush the
-    ;; whole file cache.
-    (tramp-flush-file-properties v localname)
-    (tramp-flush-directory-properties
-     v (if parents "/" (file-name-directory localname)))
-    (tramp-rclone-flush-directory-cache v)))
-
 (defun tramp-rclone-handle-rename-file
   (filename newname &optional ok-if-already-exists)
   "Like `rename-file' for Tramp files."
@@ -440,83 +320,6 @@ file names."
 
 ;; File name conversions.
 
-(defun tramp-rclone-mount-point (vec)
-  "Return local mount point of VEC."
-  (expand-file-name
-   (concat
-    tramp-temp-name-prefix (tramp-file-name-method vec)
-    "." (tramp-file-name-host vec))
-   (tramp-compat-temporary-file-directory)))
-
-(defun tramp-rclone-mounted-p (vec)
-  "Check, whether storage system determined by VEC is mounted."
-  (when (tramp-get-connection-process vec)
-    ;; We cannot use `with-connection-property', because we don't want
-    ;; to cache a nil result.
-    (or (tramp-get-connection-property
-        (tramp-get-connection-process vec) "mounted" nil)
-       (let* ((default-directory (tramp-compat-temporary-file-directory))
-              (mount (shell-command-to-string "mount -t fuse.rclone")))
-         (tramp-message vec 6 "%s" "mount -t fuse.rclone")
-         (tramp-message vec 6 "\n%s" mount)
-         (tramp-set-connection-property
-          (tramp-get-connection-process vec) "mounted"
-          (when (string-match
-                 (format
-                  "^\\(%s:\\S-*\\)" (regexp-quote (tramp-file-name-host vec)))
-                 mount)
-            (match-string 1 mount)))))))
-
-(defun tramp-rclone-flush-directory-cache (vec)
-  "Flush directory cache of VEC mount."
-  (let ((rclone-pid
-        ;; Identify rclone process.
-        (when (tramp-get-connection-process vec)
-          (with-tramp-connection-property
-              (tramp-get-connection-process vec) "rclone-pid"
-            (catch 'pid
-              (dolist
-                  (pid
-                   ;; Until Emacs 25, `process-attributes' could
-                   ;; crash Emacs for some processes.  So we use
-                   ;; "pidof", which might not work everywhere.
-                   (if (<= emacs-major-version 25)
-                       (let ((default-directory
-                               (tramp-compat-temporary-file-directory)))
-                         (mapcar
-                          #'string-to-number
-                          (split-string
-                           (shell-command-to-string "pidof rclone"))))
-                     (list-system-processes)))
-                (and (string-match-p
-                      (regexp-quote
-                       (format "rclone mount %s:" (tramp-file-name-host vec)))
-                      (or (cdr (assoc 'args (process-attributes pid))) ""))
-                     (throw 'pid pid))))))))
-    ;; Send a SIGHUP in order to flush directory cache.
-    (when rclone-pid
-      (tramp-message
-       vec 6 "Send SIGHUP %d: %s"
-       rclone-pid (cdr (assoc 'args (process-attributes rclone-pid))))
-      (signal-process rclone-pid 'SIGHUP))))
-
-(defun tramp-rclone-local-file-name (filename)
-  "Return local mount name of FILENAME."
-  (setq filename (tramp-compat-file-name-unquote (expand-file-name filename)))
-  (with-parsed-tramp-file-name filename nil
-    ;; As long as we call `tramp-rclone-maybe-open-connection' here,
-    ;; we cache the result.
-    (with-tramp-file-property v localname "local-file-name"
-      (tramp-rclone-maybe-open-connection v)
-      (let ((quoted (tramp-compat-file-name-quoted-p localname))
-           (localname (tramp-compat-file-name-unquote localname)))
-       (funcall
-        (if quoted #'tramp-compat-file-name-quote #'identity)
-        (expand-file-name
-         (if (file-name-absolute-p localname)
-             (substring localname 1) localname)
-         (tramp-rclone-mount-point v)))))))
-
 (defun tramp-rclone-remote-file-name (filename)
   "Return FILENAME as used in the `rclone' command."
   (setq filename (tramp-compat-file-name-unquote (expand-file-name filename)))
@@ -529,7 +332,7 @@ file names."
          ;; TODO: This shall be handled by `expand-file-name'.
          (setq localname
                (replace-regexp-in-string "^\\." "" (or localname "")))
-         (format "%s%s" (tramp-rclone-mounted-p v) localname)))
+         (format "%s%s" (tramp-fuse-mounted-p v) localname)))
     ;; It is a local file name.
     filename))
 
@@ -559,20 +362,18 @@ connection if a previous connection has died for some 
reason."
          (tramp-set-connection-local-variables vec)))
 
       ;; Create directory.
-      (unless (file-directory-p (tramp-rclone-mount-point vec))
-       (make-directory (tramp-rclone-mount-point vec) 'parents))
+      (unless (file-directory-p (tramp-fuse-mount-point vec))
+       (make-directory (tramp-fuse-mount-point vec) 'parents))
 
       ;; Mount.  This command does not return, so we use 0 as
       ;; DESTINATION of `tramp-call-process'.
-      (unless (tramp-rclone-mounted-p vec)
+      (unless (tramp-fuse-mounted-p vec)
        (apply
         #'tramp-call-process
         vec tramp-rclone-program nil 0 nil
-        (delq nil
-              `("mount" ,(concat host ":/")
-                ,(tramp-rclone-mount-point vec)
-                ;; This could be nil.
-                ,(tramp-get-method-parameter vec 'tramp-mount-args))))
+        "mount" (tramp-fuse-mount-spec vec)
+        (tramp-fuse-mount-point vec)
+        (tramp-get-method-parameter vec 'tramp-mount-args))
        (while (not (file-exists-p (tramp-make-tramp-file-name vec 'noloc)))
          (tramp-cleanup-connection vec 'keep-debug 'keep-password))
 
@@ -607,9 +408,4 @@ The command is the list of strings ARGS."
 
 (provide 'tramp-rclone)
 
-;;; TODO:
-
-;; * If possible, get rid of "rclone mount".  Maybe it is more
-;;   performant then.
-
 ;;; tramp-rclone.el ends here
diff --git a/lisp/net/tramp-sh.el b/lisp/net/tramp-sh.el
index bcdc014..1764f2e 100644
--- a/lisp/net/tramp-sh.el
+++ b/lisp/net/tramp-sh.el
@@ -46,7 +46,6 @@
 (defconst tramp-default-remote-shell "/bin/sh"
   "The default remote shell Tramp applies.")
 
-;;;###tramp-autoload
 (defcustom tramp-inline-compress-start-size 4096
   "The minimum size of compressing where inline transfer.
 When inline transfer, compress transferred data of file whose
@@ -56,23 +55,12 @@ If it is nil, no compression at all will be applied."
   :group 'tramp
   :type '(choice (const nil) integer))
 
-;;;###tramp-autoload
 (defcustom tramp-copy-size-limit 10240
   "Maximum file size where inline copying is preferred to an out-of-the-band 
copy.
 If it is nil, out-of-the-band copy will be used without a check."
   :group 'tramp
   :type '(choice (const nil) integer))
 
-;;;###tramp-autoload
-(defcustom tramp-terminal-type "dumb"
-  "Value of TERM environment variable for logging in to remote host.
-Because Tramp wants to parse the output of the remote shell, it is easily
-confused by ANSI color escape sequences and suchlike.  Often, shell init
-files conditionalize this setup based on the TERM environment variable."
-  :group 'tramp
-  :type 'string)
-
-;;;###tramp-autoload
 (defcustom tramp-histfile-override "~/.tramp_history"
   "When invoking a shell, override the HISTFILE with this value.
 When setting to a string, it redirects the shell history to that
@@ -115,7 +103,6 @@ detected as prompt when being sent on echoing hosts, 
therefore.")
 (defconst tramp-end-of-heredoc (md5 tramp-end-of-output)
   "String used to recognize end of heredoc strings.")
 
-;;;###tramp-autoload
 (defcustom tramp-use-ssh-controlmaster-options t
   "Whether to use `tramp-ssh-controlmaster-options'.
 Set it to nil, if you use Control* or Proxy* options in your ssh
@@ -477,70 +464,6 @@ The string is used in `tramp-methods'.")
  (tramp-set-completion-function "psftp" tramp-completion-function-alist-ssh)
  (tramp-set-completion-function "fcp" tramp-completion-function-alist-ssh))
 
-;; "getconf PATH" yields:
-;; HP-UX: 
/usr/bin:/usr/ccs/bin:/opt/ansic/bin:/opt/langtools/bin:/opt/fortran/bin
-;; Solaris: /usr/xpg4/bin:/usr/ccs/bin:/usr/bin:/opt/SUNWspro/bin
-;; GNU/Linux (Debian, Suse, RHEL): /bin:/usr/bin
-;; FreeBSD, DragonFly: /usr/bin:/bin:/usr/sbin:/sbin: - beware trailing ":"!
-;; FreeBSD 12.1, Darwin: /usr/bin:/bin:/usr/sbin:/sbin
-;; IRIX64: /usr/bin
-;; QNAP QTS: ---
-;; Hydra: /run/current-system/sw/bin:/bin:/usr/bin
-;;;###tramp-autoload
-(defcustom tramp-remote-path
-  '(tramp-default-remote-path "/bin" "/usr/bin" "/sbin" "/usr/sbin"
-    "/usr/local/bin" "/usr/local/sbin" "/local/bin" "/local/freeware/bin"
-    "/local/gnu/bin" "/usr/freeware/bin" "/usr/pkg/bin" "/usr/contrib/bin"
-    "/opt/bin" "/opt/sbin" "/opt/local/bin")
-  "List of directories to search for executables on remote host.
-For every remote host, this variable will be set buffer local,
-keeping the list of existing directories on that host.
-
-You can use \"~\" in this list, but when searching for a shell which groks
-tilde expansion, all directory names starting with \"~\" will be ignored.
-
-`Default Directories' represent the list of directories given by
-the command \"getconf PATH\".  It is recommended to use this
-entry on head of this list, because these are the default
-directories for POSIX compatible commands.  On remote hosts which
-do not offer the getconf command (like cygwin), the value
-\"/bin:/usr/bin\" is used instead.  This entry is represented in
-the list by the special value `tramp-default-remote-path'.
-
-`Private Directories' are the settings of the $PATH environment,
-as given in your `~/.profile'.  This entry is represented in
-the list by the special value `tramp-own-remote-path'."
-  :group 'tramp
-  :type '(repeat (choice
-                 (const :tag "Default Directories" tramp-default-remote-path)
-                 (const :tag "Private Directories" tramp-own-remote-path)
-                 (string :tag "Directory"))))
-
-;;;###tramp-autoload
-(defcustom tramp-remote-process-environment
-  '("ENV=''" "TMOUT=0" "LC_CTYPE=''"
-    "CDPATH=" "HISTORY=" "MAIL=" "MAILCHECK=" "MAILPATH=" "PAGER=cat"
-    "autocorrect=" "correct=")
-  "List of environment variables to be set on the remote host.
-
-Each element should be a string of the form ENVVARNAME=VALUE.  An
-entry ENVVARNAME= disables the corresponding environment variable,
-which might have been set in the init files like ~/.profile.
-
-Special handling is applied to some environment variables,
-which should not be set here:
-
-The PATH environment variable should be set via `tramp-remote-path'.
-
-The TERM environment variable should be set via `tramp-terminal-type'.
-
-The INSIDE_EMACS environment variable will automatically be set
-based on the Tramp and Emacs versions, and should not be set here."
-  :group 'tramp
-  :version "26.1"
-  :type '(repeat string))
-
-;;;###tramp-autoload
 (defcustom tramp-sh-extra-args
   '(("/bash\\'" . "-noediting -norc -noprofile")
     ("/zsh\\'" . "-f +Z -V"))
@@ -2370,53 +2293,29 @@ The method used must be an out-of-band method."
            (setq listener (number-to-string (+ 50000 (random 10000))))))
 
        ;; Compose copy command.
-       (setq host (or host "")
-             user (or user "")
-             port (or port "")
-             spec (format-spec-make
-                   ?t (tramp-get-connection-property
-                       (tramp-get-connection-process v) "temp-file" ""))
-             options (format-spec (tramp-ssh-controlmaster-options v) spec)
-             spec (format-spec-make
-                   ?h host ?u user ?p port ?r listener ?c options
-                   ?k (if keep-date " " "")
+       (setq options
+             (format-spec
+              (tramp-ssh-controlmaster-options v)
+              (format-spec-make
+               ?t (tramp-get-connection-property
+                   (tramp-get-connection-process v) "temp-file" "")))
+             spec (list
+                   ?h (or host "") ?u (or user "") ?p (or port "")
+                   ?r listener ?c options ?k (if keep-date " " "")
                     ?n (concat "2>" (tramp-get-remote-null-device v)))
              copy-program (tramp-get-method-parameter v 'tramp-copy-program)
              copy-keep-date (tramp-get-method-parameter
                              v 'tramp-copy-keep-date)
-
              copy-args
-             (delete
-              ;; " " has either been a replacement of "%k" (when
-              ;; keep-date argument is non-nil), or a replacement
-              ;; for the whole keep-date sublist.
-              " "
-              (dolist
-                  (x (tramp-get-method-parameter v 'tramp-copy-args) copy-args)
-                (setq copy-args
-                      (append
-                       copy-args
-                       (let ((y (mapcar (lambda (z) (format-spec z spec)) x)))
-                         (if (member "" y) '(" ") y))))))
-
-             copy-env
-             (delq
-              nil
-              (mapcar
-               (lambda (x)
-                 (setq x (mapcar (lambda (y) (format-spec y spec)) x))
-                 (unless (member "" x) (string-join x " ")))
-               (tramp-get-method-parameter v 'tramp-copy-env)))
-
+             ;; " " has either been a replacement of "%k" (when
+             ;; keep-date argument is non-nil), or a replacement for
+             ;; the whole keep-date sublist.
+             (delete " " (apply #'tramp-expand-args v 'tramp-copy-args spec))
+             copy-env (apply #'tramp-expand-args v 'tramp-copy-env spec)
              remote-copy-program
-             (tramp-get-method-parameter v 'tramp-remote-copy-program))
-
-       (dolist (x (tramp-get-method-parameter v 'tramp-remote-copy-args))
-         (setq remote-copy-args
-               (append
-                remote-copy-args
-                (let ((y (mapcar (lambda (z) (format-spec z spec)) x)))
-                  (if (member "" y) '(" ") y)))))
+             (tramp-get-method-parameter v 'tramp-remote-copy-program)
+             remote-copy-args
+             (apply #'tramp-expand-args v 'tramp-remote-copy-args spec))
 
        ;; Check for local copy program.
        (unless (executable-find copy-program)
@@ -2462,10 +2361,11 @@ The method used must be an out-of-band method."
                 v "process-name" (buffer-name (current-buffer)))
                (tramp-set-connection-property
                 v "process-buffer" (current-buffer))
-               (while copy-env
+               (when copy-env
                  (tramp-message
-                  orig-vec 6 "%s=\"%s\"" (car copy-env) (cadr copy-env))
-                 (setenv (pop copy-env) (pop copy-env)))
+                  orig-vec 6 "%s=\"%s\""
+                  (car copy-env) (string-join (cdr copy-env) " "))
+                 (setenv (car copy-env) (string-join (cdr copy-env) " ")))
                (setq
                 copy-args
                 (append
@@ -2818,6 +2718,9 @@ the result will be a local, non-Tramp, file name."
       ;; expands to "/".  Remove this.
       (while (string-match "//" localname)
        (setq localname (replace-match "/" t t localname)))
+      ;; Do not keep "/..".
+      (when (string-match-p "^/\\.\\.?$" localname)
+       (setq localname "/"))
       ;; No tilde characters in file name, do normal
       ;; `expand-file-name' (this does "/./" and "/../").
       ;; `default-directory' is bound, because on Windows there would
@@ -2927,16 +2830,11 @@ alternative implementation will be used."
                             elt (default-toplevel-value 'process-environment))
                            (if (string-match-p "=" elt)
                                (setq env (append env `(,elt)))
-                             (if (tramp-get-env-with-u-option v)
-                                 (setq env (append `("-u" ,elt) env))
-                               (setq uenv (cons elt uenv)))))))
+                             (setq uenv (cons elt uenv))))))
+                (env (setenv-internal
+                      env "INSIDE_EMACS" (tramp-inside-emacs) 'keep))
                 (command
                  (when (stringp program)
-                   (setenv-internal
-                    env "INSIDE_EMACS"
-                    (concat (or (getenv "INSIDE_EMACS") emacs-version)
-                            ",tramp:" tramp-version)
-                    'keep)
                    (format "cd %s && %s exec %s %s env %s %s"
                            (tramp-shell-quote-argument localname)
                            (if uenv
@@ -3147,14 +3045,8 @@ alternative implementation will be used."
         (or (member elt (default-toplevel-value 'process-environment))
             (if (string-match-p "=" elt)
                 (setq env (append env `(,elt)))
-              (if (tramp-get-env-with-u-option v)
-                  (setq env (append `("-u" ,elt) env))
-                (setq uenv (cons elt uenv))))))
-      (setenv-internal
-       env "INSIDE_EMACS"
-       (concat (or (getenv "INSIDE_EMACS") emacs-version)
-              ",tramp:" tramp-version)
-       'keep)
+              (setq uenv (cons elt uenv)))))
+      (setenv-internal env "INSIDE_EMACS" (tramp-inside-emacs) 'keep)
       (when env
        (setq command
              (format
@@ -3762,6 +3654,8 @@ Fall back to normal file name handler if no Tramp handler 
exists."
   (setq file-name (expand-file-name file-name))
   (with-parsed-tramp-file-name file-name nil
     (let ((default-directory (file-name-directory file-name))
+          (process-environment
+           (cons "GIO_USE_FILE_MONITOR=help" process-environment))
          command events filter p sequence)
       (cond
        ;; "inotifywait".
@@ -3794,18 +3688,6 @@ Fall back to normal file name handler if no Tramp 
handler exists."
                '(created changed changes-done-hint moved deleted))
               ((memq 'attribute-change flags) '(attribute-changed)))
              sequence `(,command "monitor" ,localname)))
-       ;; "gvfs-monitor-dir".
-       ((setq command (tramp-get-remote-gvfs-monitor-dir v))
-       (setq filter #'tramp-sh-gvfs-monitor-dir-process-filter
-             events
-             (cond
-              ((and (memq 'change flags) (memq 'attribute-change flags))
-               '(created changed changes-done-hint moved deleted
-                         attribute-changed))
-              ((memq 'change flags)
-               '(created changed changes-done-hint moved deleted))
-              ((memq 'attribute-change flags) '(attribute-changed)))
-             sequence `(,command ,localname)))
        ;; None.
        (t (tramp-error
           v 'file-notify-error
@@ -3838,10 +3720,6 @@ Fall back to normal file name handler if no Tramp 
handler exists."
        (unless (process-live-p p)
          (tramp-error
           p 'file-notify-error "Monitoring not supported for `%s'" file-name))
-       ;; Set "gio-file-monitor" property if needed.
-       (when (string-equal (file-name-nondirectory command) "gio")
-         (tramp-set-connection-property
-          p "gio-file-monitor" (tramp-get-remote-gio-file-monitor v)))
        p))))
 
 (defun tramp-sh-gio-monitor-process-filter (proc string)
@@ -3862,91 +3740,64 @@ Fall back to normal file name handler if no Tramp 
handler exists."
                  "changes done" "changes-done-hint" string)
           string (tramp-compat-string-replace
                  "renamed to" "moved" string))
-    ;; https://bugs.launchpad.net/bugs/1742946
-    (when
-       (string-match-p "Monitoring not supported\\|No locations given" string)
-      (delete-process proc))
-
-    ;; Delete empty lines.
-    (setq string (tramp-compat-string-replace "\n\n" "\n" string))
-
-    (while (string-match
-           (eval-when-compile
-             (concat "^[^:]+:"
-                     "[[:space:]]\\([^:]+\\):"
-                     "[[:space:]]" (regexp-opt tramp-gio-events t)
-                     "\\([[:space:]]\\([^:]+\\)\\)?$"))
-           string)
-
-      (let* ((file (match-string 1 string))
-            (file1 (match-string 4 string))
-            (object
-             (list
-              proc
-              (list
-               (intern-soft (match-string 2 string)))
-              ;; File names are returned as absolute paths.  We must
-              ;; add the remote prefix.
-              (concat remote-prefix file)
-              (when file1 (concat remote-prefix file1)))))
-       (setq string (replace-match "" nil nil string))
-       ;; Usually, we would add an Emacs event now.  Unfortunately,
-       ;; `unread-command-events' does not accept several events at
-       ;; once.  Therefore, we apply the handler directly.
-       (when (member (cl-caadr object) events)
-         (tramp-compat-funcall
-          (lookup-key special-event-map [file-notify])
-          `(file-notify ,object file-notify-callback)))))
-
-    ;; Save rest of the string.
-    (when (zerop (length string)) (setq string nil))
-    (when string (tramp-message proc 10 "Rest string:\n%s" string))
-    (process-put proc 'rest-string string)))
 
-(defun tramp-sh-gvfs-monitor-dir-process-filter (proc string)
-  "Read output from \"gvfs-monitor-dir\" and add corresponding \
-`file-notify' events."
-  (let ((events (process-get proc 'events))
-       (remote-prefix
-        (with-current-buffer (process-buffer proc)
-          (file-remote-p default-directory)))
-       (rest-string (process-get proc 'rest-string)))
-    (when rest-string
-      (tramp-message proc 10 "Previous string:\n%s" rest-string))
-    (tramp-message proc 6 "%S\n%s" proc string)
-    (setq string (concat rest-string string)
-         ;; Attribute change is returned in unused wording.
-         string (tramp-compat-string-replace
-                 "ATTRIB CHANGED" "ATTRIBUTE_CHANGED" string))
-
-    (while (string-match
-           (concat "^[\n\r]*"
-                   "Directory Monitor Event:[\n\r]+"
-                   "Child = \\([^\n\r]+\\)[\n\r]+"
-                   "\\(Other = \\([^\n\r]+\\)[\n\r]+\\)?"
-                   "Event = \\([^[:blank:]]+\\)[\n\r]+")
-           string)
-      (let* ((file (match-string 1 string))
-            (file1 (match-string 3 string))
-            (object
-             (list
-              proc
-              (list
-               (intern-soft
-                (tramp-compat-string-replace
-                 "_" "-" (downcase (match-string 4 string)))))
-              ;; File names are returned as absolute paths.  We must
-              ;; add the remote prefix.
-              (concat remote-prefix file)
-              (when file1 (concat remote-prefix file1)))))
-       (setq string (replace-match "" nil nil string))
-       ;; Usually, we would add an Emacs event now.  Unfortunately,
-       ;; `unread-command-events' does not accept several events at
-       ;; once.  Therefore, we apply the handler directly.
-       (when (member (cl-caadr object) events)
-         (tramp-compat-funcall
-          (lookup-key special-event-map [file-notify])
-          `(file-notify ,object file-notify-callback)))))
+    (catch 'doesnt-work
+      ;; https://bugs.launchpad.net/bugs/1742946
+      (when
+          (string-match-p "Monitoring not supported\\|No locations given" 
string)
+        (delete-process proc)
+        (throw 'doesnt-work nil))
+
+      ;; Determine monitor name.
+      (unless (tramp-connection-property-p proc "gio-file-monitor")
+        (cond
+         ;; We have seen this only on cygwin gio, which uses the
+         ;; GPollFileMonitor.
+         ((string-match
+           "Can't find module 'help' specified in GIO_USE_FILE_MONITOR" string)
+          (tramp-set-connection-property
+           proc "gio-file-monitor" 'GPollFileMonitor))
+         ;; TODO: What happens, if several monitor names are reported?
+         ((string-match "\
+Supported arguments for GIO_USE_FILE_MONITOR environment variable:
+\\s-*\\([[:alpha:]]+\\) - 20" string)
+          (tramp-set-connection-property
+           proc "gio-file-monitor"
+           (intern
+            (format "G%sFileMonitor" (capitalize (match-string 1 string))))))
+         (t (throw 'doesnt-work nil)))
+        (setq string (replace-match "" nil nil string)))
+
+      ;; Delete empty lines.
+      (setq string (tramp-compat-string-replace "\n\n" "\n" string))
+
+      (while (string-match
+             (eval-when-compile
+               (concat "^[^:]+:"
+                       "[[:space:]]\\([^:]+\\):"
+                       "[[:space:]]" (regexp-opt tramp-gio-events t)
+                       "\\([[:space:]]\\([^:]+\\)\\)?$"))
+             string)
+
+        (let* ((file (match-string 1 string))
+              (file1 (match-string 4 string))
+              (object
+               (list
+                proc
+                (list
+                 (intern-soft (match-string 2 string)))
+                ;; File names are returned as absolute paths.  We
+                ;; must add the remote prefix.
+                (concat remote-prefix file)
+                (when file1 (concat remote-prefix file1)))))
+         (setq string (replace-match "" nil nil string))
+         ;; Usually, we would add an Emacs event now.  Unfortunately,
+         ;; `unread-command-events' does not accept several events at
+         ;; once.  Therefore, we apply the handler directly.
+         (when (member (cl-caadr object) events)
+           (tramp-compat-funcall
+            (lookup-key special-event-map [file-notify])
+            `(file-notify ,object file-notify-callback))))))
 
     ;; Save rest of the string.
     (when (zerop (length string)) (setq string nil))
@@ -4307,10 +4158,9 @@ file exists and nonzero exit status otherwise."
     (tramp-send-command
      vec (format
          (concat
-          "exec env TERM='%s' INSIDE_EMACS='%s,tramp:%s' "
+          "exec env TERM='%s' INSIDE_EMACS='%s' "
           "ENV=%s %s PROMPT_COMMAND='' PS1=%s PS2='' PS3='' %s %s -i")
-          tramp-terminal-type
-          (or (getenv "INSIDE_EMACS") emacs-version) tramp-version
+          tramp-terminal-type (tramp-inside-emacs)
           (or (getenv-internal "ENV" tramp-remote-process-environment) "")
          (if (stringp tramp-histfile-override)
              (format "HISTFILE=%s"
@@ -4927,7 +4777,7 @@ If there is just some editing, retry it after 5 seconds."
       (progn
        (tramp-message
         vec 5 "Cannot timeout session, trying it again in %s seconds." 5)
-       (run-at-time 5 nil 'tramp-timeout-session vec))
+       (run-at-time 5 nil #'tramp-timeout-session vec))
     (tramp-message
      vec 3 "Timeout session %s" (tramp-make-tramp-file-name vec 'noloc))
     (tramp-cleanup-connection vec 'keep-debug nil 'keep-processes)))
@@ -5058,19 +4908,17 @@ connection if a previous connection has died for some 
reason."
                         (l-domain (tramp-file-name-domain hop))
                         (l-host (tramp-file-name-host hop))
                         (l-port (tramp-file-name-port hop))
-                        (login-program
-                         (tramp-get-method-parameter hop 'tramp-login-program))
-                        (login-args
-                         (tramp-get-method-parameter hop 'tramp-login-args))
                         (remote-shell
                          (tramp-get-method-parameter hop 'tramp-remote-shell))
                         (extra-args (tramp-get-sh-extra-args remote-shell))
                         (async-args
-                         (tramp-get-method-parameter hop 'tramp-async-args))
+                         (tramp-compat-flatten-tree
+                          (tramp-get-method-parameter hop 'tramp-async-args)))
                         (connection-timeout
                          (tramp-get-method-parameter
                           hop 'tramp-connection-timeout))
-                        (command login-program)
+                        (command
+                         (tramp-get-method-parameter hop 'tramp-login-program))
                         ;; We don't create the temporary file.  In
                         ;; fact, it is just a prefix for the
                         ;; ControlPath option of ssh; the real
@@ -5084,11 +4932,7 @@ connection if a previous connection has died for some 
reason."
                          (with-tramp-connection-property
                              (tramp-get-process vec) "temp-file"
                            (tramp-compat-make-temp-name)))
-                        spec r-shell)
-
-                   ;; Add arguments for asynchronous processes.
-                   (when (and process-name async-args)
-                     (setq login-args (append async-args login-args)))
+                        r-shell)
 
                    ;; Check, whether there is a restricted shell.
                    (dolist (elt tramp-restricted-shell-hosts-alist)
@@ -5113,31 +4957,28 @@ connection if a previous connection has died for some 
reason."
 
                    ;; Replace `login-args' place holders.
                    (setq
-                    l-host (or l-host "")
-                    l-user (or l-user "")
-                    l-port (or l-port "")
-                    spec (format-spec-make ?t tmpfile)
-                    options (format-spec options spec)
-                    spec (format-spec-make
-                          ?h l-host ?u l-user ?p l-port ?c options
-                          ?l (concat remote-shell " " extra-args " -i"))
                     command
-                    (concat
-                     ;; We do not want to see the trailing local
-                     ;; prompt in `start-file-process'.
-                     (unless r-shell "exec ")
-                     command " "
-                     (mapconcat
-                      (lambda (x)
-                        (setq x (mapcar (lambda (y) (format-spec y spec)) x))
-                        (unless (member "" x) (string-join x " ")))
-                      login-args " ")
-                     ;; Local shell could be a Windows COMSPEC.  It
-                     ;; doesn't know the ";" syntax, but we must exit
-                     ;; always for `start-file-process'.  It could
-                     ;; also be a restricted shell, which does not
-                     ;; allow "exec".
-                     (when r-shell " && exit || exit")))
+                    (mapconcat
+                     #'identity
+                     (append
+                      ;; We do not want to see the trailing local
+                      ;; prompt in `start-file-process'.
+                      (unless r-shell '("exec"))
+                      `(,command)
+                      ;; Add arguments for asynchronous processes.
+                      (when process-name async-args)
+                      (tramp-expand-args
+                       hop 'tramp-login-args
+                       ?h (or l-host "") ?u (or l-user "") ?p (or l-port "")
+                       ?c (format-spec options (format-spec-make ?t tmpfile))
+                       ?l (concat remote-shell " " extra-args " -i"))
+                      ;; Local shell could be a Windows COMSPEC.  It
+                      ;; doesn't know the ";" syntax, but we must
+                      ;; exit always for `start-file-process'.  It
+                      ;; could also be a restricted shell, which does
+                      ;; not allow "exec".
+                      (when r-shell '("&&" "exit" "||" "exit")))
+                     " "))
 
                    ;; Send the command.
                    (tramp-message vec 3 "Sending command `%s'" command)
@@ -5158,7 +4999,7 @@ connection if a previous connection has died for some 
reason."
                (when (tramp-get-connection-property p "session-timeout" nil)
                  (run-at-time
                   (tramp-get-connection-property p "session-timeout" nil) nil
-                  'tramp-timeout-session vec))
+                  #'tramp-timeout-session vec))
 
                ;; Make initial shell settings.
                (tramp-open-connection-setup-interactive-shell p vec)
@@ -5478,7 +5319,7 @@ Nonexistent directories are removed from spec."
                  (progn
                    (tramp-message
                     vec 3
-                   "`getconf PATH' not successful, using default value \"%s\"."
+                    "`getconf PATH' not successful, using default value 
\"%s\"."
                     "/bin:/usr/bin")
                    "/bin:/usr/bin"))))
             (own-remote-path
@@ -5765,42 +5606,6 @@ This command is returned only if 
`delete-by-moving-to-trash' is non-nil."
     (tramp-message vec 5 "Finding a suitable `gio-monitor' command")
     (tramp-find-executable vec "gio" (tramp-get-remote-path vec) t t)))
 
-(defun tramp-get-remote-gio-file-monitor (vec)
-  "Determine remote GFileMonitor."
-  (with-tramp-connection-property vec "gio-file-monitor"
-    (with-current-buffer (tramp-get-connection-buffer vec)
-      (tramp-message vec 5 "Finding the used GFileMonitor")
-      (when-let ((gio (tramp-get-remote-gio-monitor vec)))
-       ;; Search for the used FileMonitor.  There is no known way to
-       ;; get this information directly from gio, so we check for
-       ;; linked libraries of libgio.
-       (when (tramp-send-command-and-check vec (concat "ldd " gio))
-         (goto-char (point-min))
-         (when (re-search-forward "\\S-+/libgio\\S-+")
-           (when (tramp-send-command-and-check
-                  vec (concat "strings " (match-string 0)))
-             (goto-char (point-min))
-             (re-search-forward
-              (format
-               "^%s$"
-               (regexp-opt
-                '("GFamFileMonitor" "GFenFileMonitor"
-                  "GInotifyFileMonitor" "GKqueueFileMonitor")))
-              nil 'noerror)
-             (intern (match-string 0)))))))))
-
-(defun tramp-get-remote-gvfs-monitor-dir (vec)
-  "Determine remote `gvfs-monitor-dir' command."
-  (with-tramp-connection-property vec "gvfs-monitor-dir"
-    (tramp-message vec 5 "Finding a suitable `gvfs-monitor-dir' command")
-    ;; We distinguish "gvfs-monitor-dir.exe" from cygwin in order to
-    ;; establish better timeouts in filenotify-tests.el.  Any better
-    ;; distinction approach would be welcome!
-    (or (tramp-find-executable
-        vec "gvfs-monitor-dir.exe" (tramp-get-remote-path vec) t t)
-       (tramp-find-executable
-        vec "gvfs-monitor-dir" (tramp-get-remote-path vec) t t))))
-
 (defun tramp-get-remote-inotifywait (vec)
   "Determine remote `inotifywait' command."
   (with-tramp-connection-property vec "inotifywait"
@@ -5945,16 +5750,6 @@ This command is returned only if 
`delete-by-moving-to-trash' is non-nil."
            (tramp-file-local-name tmpfile) (tramp-file-local-name tmpfile)))
        (delete-file tmpfile)))))
 
-(defun tramp-get-env-with-u-option (vec)
-  "Check, whether the remote `env' command supports the -u option."
-  (with-tramp-connection-property vec "env-u-option"
-    (tramp-message vec 5 "Checking, whether `env -u' works")
-    ;; Option "-u" is a GNU extension.
-    (tramp-send-command-and-check
-     vec (format "env FOO=foo env -u FOO 2>%s | grep -qv FOO"
-                 (tramp-get-remote-null-device vec))
-     t)))
-
 ;; Some predefined connection properties.
 (defun tramp-get-inline-compress (vec prop size)
   "Return the compress command related to PROP.
diff --git a/lisp/net/tramp-smb.el b/lisp/net/tramp-smb.el
index 26ec910..6fbf088 100644
--- a/lisp/net/tramp-smb.el
+++ b/lisp/net/tramp-smb.el
@@ -60,20 +60,17 @@
   tramp-smb-method
   '((tramp-parse-netrc "~/.netrc"))))
 
-;;;###tramp-autoload
 (defcustom tramp-smb-program "smbclient"
   "Name of SMB client to run."
   :group 'tramp
   :type 'string)
 
-;;;###tramp-autoload
 (defcustom tramp-smb-acl-program "smbcacls"
   "Name of SMB acls to run."
   :group 'tramp
   :type 'string
   :version "24.4")
 
-;;;###tramp-autoload
 (defcustom tramp-smb-conf null-device
   "Path of the \"smb.conf\" file.
 If it is nil, no \"smb.conf\" will be added to the `tramp-smb-program'
@@ -81,7 +78,6 @@ call, letting the SMB client use the default one."
   :group 'tramp
   :type '(choice (const nil) (file :must-match t)))
 
-;;;###tramp-autoload
 (defcustom tramp-smb-options nil
   "List of additional options.
 They are added to the `tramp-smb-program' call via \"--option '...'\".
@@ -305,7 +301,6 @@ See `tramp-actions-before-shell' for more info.")
 Operations not mentioned here will be handled by the default Emacs 
primitives.")
 
 ;; Options for remote processes via winexe.
-;;;###tramp-autoload
 (defcustom tramp-smb-winexe-program "winexe"
   "Name of winexe client to run.
 If it isn't found in the local $PATH, the absolute path of winexe
@@ -314,7 +309,6 @@ shall be given.  This is needed for remote processes."
   :type 'string
   :version "24.3")
 
-;;;###tramp-autoload
 (defcustom tramp-smb-winexe-shell-command "powershell.exe"
   "Shell to be used for processes on remote machines.
 This must be Powershell V2 compatible."
@@ -322,7 +316,6 @@ This must be Powershell V2 compatible."
   :type 'string
   :version "24.3")
 
-;;;###tramp-autoload
 (defcustom tramp-smb-winexe-shell-command-switch "-file -"
   "Command switch used together with `tramp-smb-winexe-shell-command'.
 This can be used to disable echo etc."
@@ -743,6 +736,9 @@ PRESERVE-UID-GID and PRESERVE-EXTENDED-ATTRIBUTES are 
completely ignored."
       ;; Make the file name absolute.
       (unless (tramp-run-real-handler #'file-name-absolute-p (list localname))
        (setq localname (concat "/" localname)))
+     ;; Do not keep "/..".
+      (when (string-match-p "^/\\.\\.?$" localname)
+       (setq localname "/"))
       ;; No tilde characters in file name, do normal
       ;; `expand-file-name' (this does "/./" and "/../").
       (tramp-make-tramp-file-name
@@ -1925,7 +1921,7 @@ If ARGUMENT is non-nil, use it as argument for
 
     ;; Check whether we still have the same smbclient version.
     ;; Otherwise, we must delete the connection cache, because
-    ;; capabilities migh have changed.
+    ;; capabilities might have changed.
     (unless (or argument (processp p))
       (let ((default-directory (tramp-compat-temporary-file-directory))
            (command (concat tramp-smb-program " -V")))
diff --git a/lisp/net/tramp-sshfs.el b/lisp/net/tramp-sshfs.el
new file mode 100644
index 0000000..c4a36fe
--- /dev/null
+++ b/lisp/net/tramp-sshfs.el
@@ -0,0 +1,367 @@
+;;; tramp-sshfs.el --- Tramp access functions via sshfs  -*- lexical-binding:t 
-*-
+
+;; Copyright (C) 2021 Free Software Foundation, Inc.
+
+;; Author: Michael Albinus <michael.albinus@gmx.de>
+;; Keywords: comm, processes
+;; Package: tramp
+
+;; 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:
+
+;; sshfs is a program to mount a virtual file system, based on an sftp
+;; connection.  Tramp uses its mount utility to access files and
+;; directories there.
+
+;; A remote file under sshfs control has the form
+;; "/sshfs:user@host#port:/path/to/file".  User name and port number
+;; are optional.
+
+;;; Code:
+
+(require 'tramp)
+(require 'tramp-fuse)
+
+;;;###tramp-autoload
+(defconst tramp-sshfs-method "sshfs"
+  "Tramp method for sshfs mounts.")
+
+(defcustom tramp-sshfs-program "sshfs"
+  "The sshfs mount command."
+  :group 'tramp
+  :version "28.1"
+  :type 'string)
+
+;;;###tramp-autoload
+(tramp--with-startup
+ (add-to-list 'tramp-methods
+             `(,tramp-sshfs-method
+               (tramp-mount-args            (("-C") ("-p" "%p")
+                                             ("-o" "idmap=user,reconnect")))
+               ;; These are for remote processes.
+                (tramp-login-program        "ssh")
+                (tramp-login-args           (("-q")("-l" "%u") ("-p" "%p")
+                                            ("-e" "none") ("%h") ("%l")))
+                (tramp-direct-async         t)
+                (tramp-remote-shell         ,tramp-default-remote-shell)
+                (tramp-remote-shell-login   ("-l"))
+                (tramp-remote-shell-args    ("-c"))))
+
+ (add-to-list 'tramp-connection-properties
+             `(,(format "/%s:" tramp-sshfs-method) "direct-async-process" t))
+
+ (tramp-set-completion-function
+  tramp-sshfs-method tramp-completion-function-alist-ssh))
+
+
+;; New handlers should be added here.
+;;;###tramp-autoload
+(defconst tramp-sshfs-file-name-handler-alist
+  '((access-file . tramp-handle-access-file)
+    (add-name-to-file . tramp-handle-add-name-to-file)
+    ;; `byte-compiler-base-file-name' performed by default handler.
+    (copy-directory . tramp-handle-copy-directory)
+    (copy-file . tramp-sshfs-handle-copy-file)
+    (delete-directory . tramp-fuse-handle-delete-directory)
+    (delete-file . tramp-fuse-handle-delete-file)
+    ;; `diff-latest-backup-file' performed by default handler.
+    (directory-file-name . tramp-handle-directory-file-name)
+    (directory-files . tramp-fuse-handle-directory-files)
+    (directory-files-and-attributes
+     . tramp-handle-directory-files-and-attributes)
+    (dired-compress-file . ignore)
+    (dired-uncache . tramp-handle-dired-uncache)
+    (exec-path . tramp-sshfs-handle-exec-path)
+    (expand-file-name . tramp-handle-expand-file-name)
+    (file-accessible-directory-p . tramp-handle-file-accessible-directory-p)
+    (file-acl . ignore)
+    (file-attributes . tramp-fuse-handle-file-attributes)
+    (file-directory-p . tramp-handle-file-directory-p)
+    (file-equal-p . tramp-handle-file-equal-p)
+    (file-executable-p . tramp-fuse-handle-file-executable-p)
+    (file-exists-p . tramp-handle-file-exists-p)
+    (file-in-directory-p . tramp-handle-file-in-directory-p)
+    (file-local-copy . tramp-handle-file-local-copy)
+    (file-modes . tramp-handle-file-modes)
+    (file-name-all-completions . tramp-fuse-handle-file-name-all-completions)
+    (file-name-as-directory . tramp-handle-file-name-as-directory)
+    (file-name-case-insensitive-p . tramp-handle-file-name-case-insensitive-p)
+    (file-name-completion . tramp-handle-file-name-completion)
+    (file-name-directory . tramp-handle-file-name-directory)
+    (file-name-nondirectory . tramp-handle-file-name-nondirectory)
+    ;; `file-name-sans-versions' performed by default handler.
+    (file-newer-than-file-p . tramp-handle-file-newer-than-file-p)
+    (file-notify-add-watch . ignore)
+    (file-notify-rm-watch . ignore)
+    (file-notify-valid-p . ignore)
+    (file-ownership-preserved-p . ignore)
+    (file-readable-p . tramp-fuse-handle-file-readable-p)
+    (file-regular-p . tramp-handle-file-regular-p)
+    (file-remote-p . tramp-handle-file-remote-p)
+    (file-selinux-context . tramp-handle-file-selinux-context)
+    (file-symlink-p . tramp-handle-file-symlink-p)
+    (file-system-info . tramp-sshfs-handle-file-system-info)
+    (file-truename . tramp-handle-file-truename)
+    (file-writable-p . tramp-handle-file-writable-p)
+    (find-backup-file-name . tramp-handle-find-backup-file-name)
+    ;; `get-file-buffer' performed by default handler.
+    (insert-directory . tramp-handle-insert-directory)
+    (insert-file-contents . tramp-sshfs-handle-insert-file-contents)
+    (load . tramp-handle-load)
+    (make-auto-save-file-name . tramp-handle-make-auto-save-file-name)
+    (make-directory . tramp-fuse-handle-make-directory)
+    (make-directory-internal . ignore)
+    (make-nearby-temp-file . tramp-handle-make-nearby-temp-file)
+    (make-process . tramp-handle-make-process)
+    (make-symbolic-link . tramp-handle-make-symbolic-link)
+    (process-file . tramp-sshfs-handle-process-file)
+    (rename-file . tramp-sshfs-handle-rename-file)
+    (set-file-acl . ignore)
+    (set-file-modes . tramp-sshfs-handle-set-file-modes)
+    (set-file-selinux-context . ignore)
+    (set-file-times . ignore)
+    (set-visited-file-modtime . tramp-handle-set-visited-file-modtime)
+    (shell-command . tramp-handle-shell-command)
+    (start-file-process . tramp-handle-start-file-process)
+    (substitute-in-file-name . tramp-handle-substitute-in-file-name)
+    (temporary-file-directory . tramp-handle-temporary-file-directory)
+    (tramp-get-remote-gid . ignore)
+    (tramp-get-remote-uid . ignore)
+    (tramp-set-file-uid-gid . ignore)
+    (unhandled-file-name-directory . ignore)
+    (vc-registered . ignore)
+    (verify-visited-file-modtime . tramp-handle-verify-visited-file-modtime)
+    (write-region . tramp-sshfs-handle-write-region))
+"Alist of handler functions for Tramp SSHFS method.
+Operations not mentioned here will be handled by the default Emacs 
primitives.")
+
+;; It must be a `defsubst' in order to push the whole code into
+;; tramp-loaddefs.el.  Otherwise, there would be recursive autoloading.
+;;;###tramp-autoload
+(defsubst tramp-sshfs-file-name-p (filename)
+  "Check if it's a FILENAME for sshfs."
+  (and (tramp-tramp-file-p filename)
+       (string= (tramp-file-name-method (tramp-dissect-file-name filename))
+               tramp-sshfs-method)))
+
+;;;###tramp-autoload
+(defun tramp-sshfs-file-name-handler (operation &rest args)
+  "Invoke the sshfs handler for OPERATION and ARGS.
+First arg specifies the OPERATION, second arg is a list of
+arguments to pass to the OPERATION."
+  (if-let ((fn (assoc operation tramp-sshfs-file-name-handler-alist)))
+      (save-match-data (apply (cdr fn) args))
+    (tramp-run-real-handler operation args)))
+
+;;;###tramp-autoload
+(tramp--with-startup
+ (tramp-register-foreign-file-name-handler
+  #'tramp-sshfs-file-name-p #'tramp-sshfs-file-name-handler))
+
+
+;; File name primitives.
+
+(defun tramp-sshfs-handle-copy-file
+    (filename newname &optional ok-if-already-exists keep-date
+     preserve-uid-gid preserve-extended-attributes)
+  "Like `copy-file' for Tramp files."
+  (setq filename (expand-file-name filename)
+       newname (expand-file-name newname))
+  (if (file-directory-p filename)
+      (copy-directory filename newname keep-date t)
+    (copy-file
+     (if (tramp-sshfs-file-name-p filename)
+        (tramp-fuse-local-file-name filename) filename)
+     (if (tramp-sshfs-file-name-p newname)
+        (tramp-fuse-local-file-name newname) newname)
+     ok-if-already-exists keep-date
+     preserve-uid-gid preserve-extended-attributes)
+    (when (tramp-sshfs-file-name-p newname)
+      (with-parsed-tramp-file-name newname nil
+       (tramp-flush-file-properties v localname)))))
+
+(defun tramp-sshfs-handle-exec-path ()
+  "Like `exec-path' for Tramp files."
+  (append
+   (with-parsed-tramp-file-name default-directory nil
+     (with-tramp-connection-property (tramp-get-process v) "remote-path"
+       (with-temp-buffer
+        (process-file "getconf" nil t nil "PATH")
+        (split-string
+         (progn
+           ;; Read the expression.
+           (goto-char (point-min))
+           (buffer-substring (point) (point-at-eol)))
+         ":" 'omit))))
+   ;; The equivalent to `exec-directory'.
+   `(,(tramp-file-local-name (expand-file-name default-directory)))))
+
+(defun tramp-sshfs-handle-file-system-info (filename)
+  "Like `file-system-info' for Tramp files."
+  ;;`file-system-info' exists since Emacs 27.1.
+  (tramp-compat-funcall 'file-system-info (tramp-fuse-local-file-name 
filename)))
+
+(defun tramp-sshfs-handle-insert-file-contents
+  (filename &optional visit beg end replace)
+  "Like `insert-file-contents' for Tramp files."
+  (let ((result
+        (insert-file-contents
+         (tramp-fuse-local-file-name filename) visit beg end replace)))
+    (when visit (setq buffer-file-name filename))
+    (cons (expand-file-name filename) (cdr result))))
+
+(defun tramp-sshfs-handle-process-file
+  (program &optional infile destination display &rest args)
+  "Like `process-file' for Tramp files."
+  ;; The implementation is not complete yet.
+  (when (and (numberp destination) (zerop destination))
+    (error "Implementation does not handle immediate return"))
+
+  (with-parsed-tramp-file-name default-directory nil
+    (let ((command
+          (format
+           "cd %s && exec %s"
+           localname
+           (mapconcat #'tramp-shell-quote-argument (cons program args) " "))))
+      (unwind-protect
+         (apply
+          #'tramp-call-process
+          v (tramp-get-method-parameter v 'tramp-login-program)
+          infile destination display
+          (tramp-expand-args
+           v 'tramp-login-args
+           ?h (or (tramp-file-name-host v) "")
+           ?u (or (tramp-file-name-user v) "")
+           ?p (or (tramp-file-name-port v) "")
+           ?l command))
+
+       (unless process-file-side-effects
+          (tramp-flush-directory-properties v ""))))))
+
+(defun tramp-sshfs-handle-rename-file
+    (filename newname &optional ok-if-already-exists)
+  "Like `rename-file' for Tramp files."
+  (setq filename (expand-file-name filename)
+       newname (expand-file-name newname))
+  (rename-file
+   (if (tramp-sshfs-file-name-p filename)
+       (tramp-fuse-local-file-name filename) filename)
+   (if (tramp-sshfs-file-name-p newname)
+       (tramp-fuse-local-file-name newname) newname)
+   ok-if-already-exists)
+  (when (tramp-sshfs-file-name-p filename)
+    (with-parsed-tramp-file-name filename nil
+      (tramp-flush-file-properties v localname)))
+  (when (tramp-sshfs-file-name-p newname)
+    (with-parsed-tramp-file-name newname nil
+      (tramp-flush-file-properties v localname))))
+
+(defun tramp-sshfs-handle-set-file-modes (filename mode &optional flag)
+  "Like `set-file-modes' for Tramp files."
+  (with-parsed-tramp-file-name filename nil
+    (unless (and (eq flag 'nofollow) (file-symlink-p filename))
+      (tramp-flush-file-properties v localname)
+      (tramp-compat-set-file-modes
+       (tramp-fuse-local-file-name filename) mode flag))))
+
+(defun tramp-sshfs-handle-write-region
+  (start end filename &optional append visit lockname mustbenew)
+  "Like `write-region' for Tramp files."
+  (setq filename (expand-file-name filename))
+  (with-parsed-tramp-file-name filename nil
+    (when (and mustbenew (file-exists-p filename)
+              (or (eq mustbenew 'excl)
+                  (not
+                   (y-or-n-p
+                    (format "File %s exists; overwrite anyway? " filename)))))
+      (tramp-error v 'file-already-exists filename))
+
+    (write-region
+     start end (tramp-fuse-local-file-name filename) append 'nomessage 
lockname)
+    (tramp-flush-file-properties v localname)
+
+    ;; The end.
+    (when (and (null noninteractive)
+              (or (eq visit t) (null visit) (stringp visit)))
+      (tramp-message v 0 "Wrote %s" filename))
+    (run-hooks 'tramp-handle-write-region-hook)))
+
+
+;; File name conversions.
+
+(defun tramp-sshfs-maybe-open-connection (vec)
+  "Maybe open a connection VEC.
+Does not do anything if a connection is already open, but re-opens the
+connection if a previous connection has died for some reason."
+  ;; During completion, don't reopen a new connection.
+  (unless (tramp-connectable-p vec)
+    (throw 'non-essential 'non-essential))
+
+  ;; We need a process bound to the connection buffer.  Therefore, we
+  ;; create a dummy process.  Maybe there is a better solution?
+  (unless (get-buffer-process (tramp-get-connection-buffer vec))
+    (let ((p (make-network-process
+             :name (tramp-get-connection-name vec)
+             :buffer (tramp-get-connection-buffer vec)
+             :server t :host 'local :service t :noquery t)))
+      (process-put p 'vector vec)
+      (set-process-query-on-exit-flag p nil)
+
+      ;; Set connection-local variables.
+      (tramp-set-connection-local-variables vec)
+
+      ;; Create directory.
+      (unless (file-directory-p (tramp-fuse-mount-point vec))
+       (make-directory (tramp-fuse-mount-point vec) 'parents))
+
+      (unless
+         (or (tramp-fuse-mounted-p vec)
+             (with-temp-buffer
+               (zerop
+                (apply
+                 #'tramp-call-process
+                 vec tramp-sshfs-program nil t nil
+                 (tramp-fuse-mount-spec vec)
+                 (tramp-fuse-mount-point vec)
+                 (tramp-expand-args
+                  vec 'tramp-mount-args
+                  ?p (or (tramp-file-name-port vec) "")))))
+         (tramp-error
+          vec 'file-error "Error mounting %s" (tramp-fuse-mount-spec vec))))
+
+      ;; Mark it as connected.
+      (tramp-set-connection-property
+       (tramp-get-connection-process vec) "connected" t)))
+
+  ;; In `tramp-check-cached-permissions', the connection properties
+  ;; "{uid,gid}-{integer,string}" are used.  We set them to proper values.
+  (with-tramp-connection-property
+      vec "uid-integer" (tramp-get-local-uid 'integer))
+  (with-tramp-connection-property
+      vec "gid-integer" (tramp-get-local-gid 'integer))
+  (with-tramp-connection-property
+      vec "uid-string" (tramp-get-local-uid 'string))
+  (with-tramp-connection-property
+      vec "gid-string" (tramp-get-local-gid 'string)))
+
+(add-hook 'tramp-unload-hook
+         (lambda ()
+           (unload-feature 'tramp-sshfs 'force)))
+
+(provide 'tramp-sshfs)
+
+;;; tramp-sshfs.el ends here
diff --git a/lisp/net/tramp-sudoedit.el b/lisp/net/tramp-sudoedit.el
index 0a60b79..66737e6 100644
--- a/lisp/net/tramp-sudoedit.el
+++ b/lisp/net/tramp-sudoedit.el
@@ -364,6 +364,9 @@ the result will be a local, non-Tramp, file name."
        (when (string-equal uname "~")
          (setq uname (concat uname user)))
        (setq localname (concat uname fname))))
+     ;; Do not keep "/..".
+      (when (string-match-p "^/\\.\\.?$" localname)
+       (setq localname "/"))
     ;; Do normal `expand-file-name' (this does "~user/", "/./" and "/../").
     (tramp-make-tramp-file-name v (expand-file-name localname))))
 
@@ -788,22 +791,16 @@ in case of error, t otherwise."
   (tramp-sudoedit-maybe-open-connection vec)
   (with-current-buffer (tramp-get-connection-buffer vec)
     (erase-buffer)
-    (let* ((login (tramp-get-method-parameter vec 'tramp-sudo-login))
-          (host (or (tramp-file-name-host vec) ""))
-          (user (or (tramp-file-name-user vec) ""))
-          (spec (format-spec-make ?h host ?u user))
-          (args (append
-                 (tramp-compat-flatten-tree
-                  (mapcar
-                   (lambda (x)
-                     (setq x (mapcar (lambda (y) (format-spec y spec)) x))
-                     (unless (member "" x) x))
-                   login))
-                 (tramp-compat-flatten-tree (delq nil args))))
-          (delete-exited-processes t)
+    (let* ((delete-exited-processes t)
           (process-connection-type tramp-process-connection-type)
           (p (apply #'start-process
-                    (tramp-get-connection-name vec) (current-buffer) args))
+                    (tramp-get-connection-name vec) (current-buffer)
+                    (append
+                     (tramp-expand-args
+                      vec 'tramp-sudo-login
+                      ?h (or (tramp-file-name-host vec) "")
+                      ?u (or (tramp-file-name-user vec) ""))
+                     (tramp-compat-flatten-tree args))))
           ;; We suppress the messages `Waiting for prompts from remote shell'.
           (tramp-verbose (if (= tramp-verbose 3) 2 tramp-verbose))
           ;; We do not want to save the password.
diff --git a/lisp/net/tramp.el b/lisp/net/tramp.el
index 690dd99..8141f02 100644
--- a/lisp/net/tramp.el
+++ b/lisp/net/tramp.el
@@ -386,6 +386,8 @@ Also see `tramp-default-method-alist'."
   :type 'string)
 
 (defcustom tramp-default-method-alist nil
+  ;; FIXME: This is not an "alist", because its elements are not of
+  ;; the form (KEY . VAL) but (KEY1 KEY2 VAL).
   "Default method to use for specific host/user pairs.
 This is an alist of items (HOST USER METHOD).  The first matching item
 specifies the method to use for a file name which does not specify a
@@ -413,6 +415,8 @@ This variable is regarded as obsolete, and will be removed 
soon."
   :type '(choice (const nil) string))
 
 (defcustom tramp-default-user-alist nil
+  ;; FIXME: This is not an "alist", because its elements are not of
+  ;; the form (KEY . VAL) but (KEY1 KEY2 VAL).
   "Default user to use for specific method/host pairs.
 This is an alist of items (METHOD HOST USER).  The first matching item
 specifies the user to use for a file name which does not specify a
@@ -432,6 +436,8 @@ Useful for su and sudo methods mostly."
   :type 'string)
 
 (defcustom tramp-default-host-alist nil
+  ;; FIXME: This is not an "alist", because its elements are not of
+  ;; the form (KEY . VAL) but (KEY1 KEY2 VAL).
   "Default host to use for specific method/user pairs.
 This is an alist of items (METHOD USER HOST).  The first matching item
 specifies the host to use for a file name which does not specify a
@@ -447,6 +453,8 @@ empty string for the method name."
                       (choice :tag "    Host name" string (const nil)))))
 
 (defcustom tramp-default-proxies-alist nil
+  ;; FIXME: This is not an "alist", because its elements are not of
+  ;; the form (KEY . VAL) but (KEY1 KEY2 VAL).
   "Route to be followed for specific host/user pairs.
 This is an alist of items (HOST USER PROXY).  The first matching
 item specifies the proxy to be passed for a file name located on
@@ -652,6 +660,14 @@ The regexp should match at end of buffer.
 See also `tramp-yesno-prompt-regexp'."
   :type 'regexp)
 
+(defcustom tramp-terminal-type "dumb"
+  "Value of TERM environment variable for logging in to remote host.
+Because Tramp wants to parse the output of the remote shell, it is easily
+confused by ANSI color escape sequences and suchlike.  Often, shell init
+files conditionalize this setup based on the TERM environment variable."
+  :group 'tramp
+  :type 'string)
+
 (defcustom tramp-terminal-prompt-regexp
   (concat "\\("
          "TERM = (.*)"
@@ -1235,6 +1251,67 @@ let-bind this variable."
   :version "24.4"
   :type '(choice (const nil) integer))
 
+;; "getconf PATH" yields:
+;; HP-UX: 
/usr/bin:/usr/ccs/bin:/opt/ansic/bin:/opt/langtools/bin:/opt/fortran/bin
+;; Solaris: /usr/xpg4/bin:/usr/ccs/bin:/usr/bin:/opt/SUNWspro/bin
+;; GNU/Linux (Debian, Suse, RHEL): /bin:/usr/bin
+;; FreeBSD, DragonFly: /usr/bin:/bin:/usr/sbin:/sbin: - beware trailing ":"!
+;; FreeBSD 12.1, Darwin: /usr/bin:/bin:/usr/sbin:/sbin
+;; IRIX64: /usr/bin
+;; QNAP QTS: ---
+;; Hydra: /run/current-system/sw/bin:/bin:/usr/bin
+(defcustom tramp-remote-path
+  '(tramp-default-remote-path "/bin" "/usr/bin" "/sbin" "/usr/sbin"
+    "/usr/local/bin" "/usr/local/sbin" "/local/bin" "/local/freeware/bin"
+    "/local/gnu/bin" "/usr/freeware/bin" "/usr/pkg/bin" "/usr/contrib/bin"
+    "/opt/bin" "/opt/sbin" "/opt/local/bin")
+  "List of directories to search for executables on remote host.
+For every remote host, this variable will be set buffer local,
+keeping the list of existing directories on that host.
+
+You can use \"~\" in this list, but when searching for a shell which groks
+tilde expansion, all directory names starting with \"~\" will be ignored.
+
+`Default Directories' represent the list of directories given by
+the command \"getconf PATH\".  It is recommended to use this
+entry on head of this list, because these are the default
+directories for POSIX compatible commands.  On remote hosts which
+do not offer the getconf command (like cygwin), the value
+\"/bin:/usr/bin\" is used instead.  This entry is represented in
+the list by the special value `tramp-default-remote-path'.
+
+`Private Directories' are the settings of the $PATH environment,
+as given in your `~/.profile'.  This entry is represented in
+the list by the special value `tramp-own-remote-path'."
+  :group 'tramp
+  :type '(repeat (choice
+                 (const :tag "Default Directories" tramp-default-remote-path)
+                 (const :tag "Private Directories" tramp-own-remote-path)
+                 (string :tag "Directory"))))
+
+(defcustom tramp-remote-process-environment
+  '("ENV=''" "TMOUT=0" "LC_CTYPE=''"
+    "CDPATH=" "HISTORY=" "MAIL=" "MAILCHECK=" "MAILPATH=" "PAGER=cat"
+    "autocorrect=" "correct=")
+  "List of environment variables to be set on the remote host.
+
+Each element should be a string of the form ENVVARNAME=VALUE.  An
+entry ENVVARNAME= disables the corresponding environment variable,
+which might have been set in the init files like ~/.profile.
+
+Special handling is applied to some environment variables,
+which should not be set here:
+
+The PATH environment variable should be set via `tramp-remote-path'.
+
+The TERM environment variable should be set via `tramp-terminal-type'.
+
+The INSIDE_EMACS environment variable will automatically be set
+based on the Tramp and Emacs versions, and should not be set here."
+  :group 'tramp
+  :version "26.1"
+  :type '(repeat string))
+
 (defcustom tramp-completion-reread-directory-timeout 10
   "Defines seconds since last remote command before rereading a directory.
 A remote directory might have changed its contents.  In order to
@@ -1710,6 +1787,10 @@ version, the function does nothing."
   "Used for highlighting Tramp debug buffers in `outline-mode'.")
 
 (defconst tramp-debug-font-lock-keywords
+  ;; FIXME: Make it a function instead of an ELisp expression, so you
+  ;; can evaluate it with `funcall' rather than `eval'!
+  ;; Also, in `font-lock-defaults' you can specify a function name for
+  ;; the "KEYWORDS" part, so font-lock calls it to get the actual keywords!
   '(list
     (concat "^\\(?:" tramp-debug-outline-regexp "\\).+")
     '(1 font-lock-warning-face t t)
@@ -1738,8 +1819,11 @@ The outline level is equal to the verbosity of the Tramp 
message."
        (outline-mode))
       (setq-local outline-level 'tramp-debug-outline-level)
       (setq-local font-lock-keywords
-                  `(t (eval ,tramp-debug-font-lock-keywords)
-                      ,(eval tramp-debug-font-lock-keywords)))
+                  ;; FIXME: This `(t FOO . BAR)' representation in
+                  ;; `font-lock-keywords' is supposed to be an
+                  ;; internal implementation "detail".  Don't abuse it here!
+                  `(t (eval ,tramp-debug-font-lock-keywords t)
+                      ,(eval tramp-debug-font-lock-keywords t)))
       ;; Do not edit the debug buffer.
       (use-local-map special-mode-map))
     (current-buffer)))
@@ -1750,7 +1834,7 @@ The outline level is equal to the verbosity of the Tramp 
message."
    (tramp-compat-string-replace "/" " " (tramp-debug-buffer-name vec))
    (tramp-compat-temporary-file-directory)))
 
-(defsubst tramp-debug-message (vec fmt-string &rest arguments)
+(defun tramp-debug-message (vec fmt-string &rest arguments)
   "Append message to debug buffer of VEC.
 Message is formatted with FMT-STRING as control string and the remaining
 ARGUMENTS to actually emit the message (if applicable)."
@@ -2591,6 +2675,14 @@ Add operations defined in `HANDLER-alist' to 
`tramp-file-name-handler'."
 
 ;;; File name handler functions for completion mode:
 
+;; This function takes action since Emacs 28.1, when
+;; `read-extended-command-predicate' is set to
+;; `command-completion-default-include-p'.
+(defun tramp-command-completion-p (_symbol buffer)
+  "A predicate for Tramp interactive commands.
+They are completed by \"M-x TAB\" only if the current buffer is remote."
+  (with-current-buffer buffer (tramp-tramp-file-p default-directory)))
+
 (defun tramp-connectable-p (vec-or-filename)
   "Check, whether it is possible to connect the remote host w/o side-effects.
 This is true, if either the remote host is already connected, or if we are
@@ -3163,6 +3255,9 @@ User is always nil."
     (with-parsed-tramp-file-name name nil
       (unless (tramp-run-real-handler #'file-name-absolute-p (list localname))
        (setq localname (concat "/" localname)))
+      ;; Do not keep "/..".
+      (when (string-match-p "^/\\.\\.?$" localname)
+       (setq localname "/"))
       ;; Do normal `expand-file-name' (this does "/./" and "/../").
       ;; `default-directory' is bound, because on Windows there would
       ;; be problems with UNC shares or Cygwin mounts.
@@ -3680,15 +3775,15 @@ User is always nil."
     (setq choices tramp-default-proxies-alist)
     (while choices
       (setq item (pop choices)
-           proxy (eval (nth 2 item)))
+           proxy (eval (nth 2 item) t))
       (when (and
             ;; Host.
             (string-match-p
-             (or (eval (nth 0 item)) "")
+             (or (eval (nth 0 item) t) "")
              (or (tramp-file-name-host-port (car target-alist)) ""))
             ;; User.
             (string-match-p
-             (or (eval (nth 1 item)) "")
+             (or (eval (nth 1 item) t) "")
              (or (tramp-file-name-user-domain (car target-alist)) "")))
        (if (null proxy)
            ;; No more hops needed.
@@ -3739,6 +3834,22 @@ User is always nil."
     ;; Result.
     target-alist))
 
+(defun tramp-expand-args (vec parameter &rest spec-list)
+  "Expand login arguments as given by PARAMETER in `tramp-methods'.
+PARAMETER is a symbol like `tramp-login-args', denoting a list of
+list of strings from `tramp-methods', containing %-sequences for
+substitution.  SPEC-LIST is a list of char/value pairs used for
+`format-spec-make'."
+  (let ((args (tramp-get-method-parameter vec parameter))
+       (spec (apply 'format-spec-make spec-list)))
+    ;; Expand format spec.
+    (tramp-compat-flatten-tree
+     (mapcar
+      (lambda (x)
+       (setq x (mapcar (lambda (y) (format-spec y spec)) x))
+       (unless (member "" x) x))
+      args))))
+
 (defun tramp-direct-async-process-p (&rest args)
   "Whether direct async `make-process' can be called."
   (let ((v (tramp-dissect-file-name default-directory))
@@ -3811,10 +3922,7 @@ It does not support `:stderr'."
                             elt (default-toplevel-value 
'process-environment))))
                        (setq env (cons elt env)))))
               (env (setenv-internal
-                    env "INSIDE_EMACS"
-                    (concat (or (getenv "INSIDE_EMACS") emacs-version)
-                            ",tramp:" tramp-version)
-                    'keep))
+                    env "INSIDE_EMACS" (tramp-inside-emacs) 'keep))
               (env (mapcar #'tramp-shell-quote-argument (delq nil env)))
               ;; Quote command.
               (command (mapconcat #'tramp-shell-quote-argument command " "))
@@ -3823,14 +3931,11 @@ It does not support `:stderr'."
                (append `("cd" ,localname "&&" "(" "env") env `(,command ")"))))
 
          ;; Check for `tramp-sh-file-name-handler', because something
-         ;; is different between tramp-adb.el and tramp-sh.el.
+         ;; is different between tramp-sh.el, and tramp-adb.el or
+         ;; tramp-sshfs.el.
          (let* ((sh-file-name-handler-p (tramp-sh-file-name-handler-p v))
                 (login-program
                  (tramp-get-method-parameter v 'tramp-login-program))
-                (login-args
-                 (tramp-get-method-parameter v 'tramp-login-args))
-                (async-args
-                 (tramp-get-method-parameter v 'tramp-async-args))
                 ;; We don't create the temporary file.  In fact, it
                 ;; is just a prefix for the ControlPath option of
                 ;; ssh; the real temporary file has another name, and
@@ -3848,29 +3953,23 @@ It does not support `:stderr'."
                  (when sh-file-name-handler-p
                    (tramp-compat-funcall
                     'tramp-ssh-controlmaster-options v)))
-                spec p)
+                login-args p)
 
-           ;; Replace `login-args' place holders.
+           ;; Replace `login-args' place holders.  Split
+           ;; ControlMaster options.
            (setq
-            spec (format-spec-make ?t tmpfile)
-            options (format-spec (or options "") spec)
-            spec (format-spec-make
-                  ?h (or host "") ?u (or user "") ?p (or port "")
-                  ?c options ?l "")
-            ;; Add arguments for asynchronous processes.
-            login-args (append async-args login-args)
-            ;; Expand format spec.
-            login-args
-            (tramp-compat-flatten-tree
-             (mapcar
-              (lambda (x)
-                (setq x (mapcar (lambda (y) (format-spec y spec)) x))
-                (unless (member "" x) x))
-              login-args))
-            ;; Split ControlMaster options.
             login-args
-            (tramp-compat-flatten-tree
-             (mapcar (lambda (x) (split-string x " ")) login-args))
+            (append
+             (tramp-compat-flatten-tree
+              (tramp-get-method-parameter v 'tramp-async-args))
+             (tramp-compat-flatten-tree
+              (mapcar
+               (lambda (x) (split-string x " "))
+               (tramp-expand-args
+                v 'tramp-login-args
+                ?h (or host "") ?u (or user "") ?p (or port "")
+                ?c (format-spec (or options "") (format-spec-make ?t tmpfile))
+                ?l ""))))
             p (make-process
                :name name :buffer buffer
                :command (append `(,login-program) login-args command)
@@ -5439,11 +5538,6 @@ BODY is the backend specific code."
 ;;   strange when doing zerop, we should kill the process and start
 ;;   again.  (Greg Stark)
 ;;
-;; * I was wondering if it would be possible to use tramp even if I'm
-;;   actually using sshfs.  But when I launch a command I would like
-;;   to get it executed on the remote machine where the files really
-;;   are.  (Andrea Crotti)
-;;
 ;; * Run emerge on two remote files.  Bug is described here:
 ;;   <https://www.mail-archive.com/tramp-devel@nongnu.org/msg01041.html>.
 ;;   (Bug#6850)
diff --git a/lisp/net/trampver.el b/lisp/net/trampver.el
index ced3e93..abd9221 100644
--- a/lisp/net/trampver.el
+++ b/lisp/net/trampver.el
@@ -80,6 +80,11 @@
             (replace-regexp-in-string "\n" "" (emacs-version))))))
   (unless (string-equal "ok" x) (error "%s" x)))
 
+(defun tramp-inside-emacs ()
+  "Version string provided by INSIDE_EMACS enmvironment variable."
+  (concat (or (getenv "INSIDE_EMACS") emacs-version)
+         ",tramp:" tramp-version))
+
 ;; Tramp versions integrated into Emacs.  If a user option declares a
 ;; `:package-version' which doesn't belong to an integrated Tramp
 ;; version, it must be added here as well (see `tramp-syntax', for
diff --git a/lisp/net/webjump.el b/lisp/net/webjump.el
index 1fa625c..4baa657 100644
--- a/lisp/net/webjump.el
+++ b/lisp/net/webjump.el
@@ -252,7 +252,7 @@ Please submit bug reports and other feedback to the author, 
Neil W. Van Dyke
                 (cond ((not expr) "")
                       ((stringp expr) expr)
                       ((vectorp expr) (webjump-builtin expr name))
-                      ((listp expr) (eval expr))
+                      ((listp expr) (eval expr t))
                       ((symbolp expr)
                        (if (fboundp expr)
                            (funcall expr name)
diff --git a/lisp/newcomment.el b/lisp/newcomment.el
index ea47eec..a5bfb06 100644
--- a/lisp/newcomment.el
+++ b/lisp/newcomment.el
@@ -1300,7 +1300,11 @@ out."
         (let ((s (comment-padleft comment-end numarg)))
           (and s (if (string-match comment-end-skip s) s
                    (comment-padright comment-end))))
-        (if multi (comment-padright comment-continue numarg))
+        (if multi
+             (or (comment-padright comment-continue numarg)
+                 ;; `comment-padright' returns nil when
+                 ;; `comment-continue' contains only whitespace
+                 (and (stringp comment-continue) comment-continue)))
         (if multi
             (comment-padleft (comment-string-reverse comment-continue) numarg))
         block
diff --git a/lisp/notifications.el b/lisp/notifications.el
index 2241afa..b439d82 100644
--- a/lisp/notifications.el
+++ b/lisp/notifications.el
@@ -1,4 +1,4 @@
-;;; notifications.el --- Client interface to desktop notifications.
+;;; notifications.el --- Client interface to desktop notifications.  -*- 
lexical-binding: t -*-
 
 ;; Copyright (C) 2010-2021 Free Software Foundation, Inc.
 
@@ -229,56 +229,69 @@ of another `notifications-notify' call."
          id)
       ;; Build hints array
       (when urgency
-       (add-to-list 'hints `(:dict-entry
-                             "urgency"
-                             (:variant :byte ,(pcase urgency
-                                                ('low 0)
-                                                ('critical 2)
-                                                (_ 1)))) t))
+        (push `(:dict-entry
+                "urgency"
+                (:variant :byte ,(pcase urgency
+                                   ('low 0)
+                                   ('critical 2)
+                                   (_ 1))))
+              hints))
       (when category
-       (add-to-list 'hints `(:dict-entry
-                             "category"
-                             (:variant :string ,category)) t))
+        (push `(:dict-entry
+                "category"
+                (:variant :string ,category))
+              hints))
       (when desktop-entry
-       (add-to-list 'hints `(:dict-entry
-                             "desktop-entry"
-                             (:variant :string ,desktop-entry)) t))
+        (push `(:dict-entry
+                "desktop-entry"
+                (:variant :string ,desktop-entry))
+              hints))
       (when image-data
-       (add-to-list 'hints `(:dict-entry
-                             "image-data"
-                             (:variant :struct ,image-data)) t))
+        (push `(:dict-entry
+                "image-data"
+                (:variant :struct ,image-data))
+              hints))
       (when image-path
-       (add-to-list 'hints `(:dict-entry
-                             "image-path"
-                             (:variant :string ,image-path)) t))
+        (push `(:dict-entry
+                "image-path"
+                (:variant :string ,image-path))
+              hints))
       (when action-items
-       (add-to-list 'hints `(:dict-entry
-                             "action-items"
-                             (:variant :boolean ,action-items)) t))
+        (push `(:dict-entry
+                "action-items"
+                (:variant :boolean ,action-items))
+              hints))
       (when sound-file
-       (add-to-list 'hints `(:dict-entry
-                             "sound-file"
-                             (:variant :string ,sound-file)) t))
+        (push `(:dict-entry
+                "sound-file"
+                (:variant :string ,sound-file))
+              hints))
       (when sound-name
-       (add-to-list 'hints `(:dict-entry
-                             "sound-name"
-                             (:variant :string ,sound-name)) t))
+        (push `(:dict-entry
+                "sound-name"
+                (:variant :string ,sound-name))
+              hints))
       (when suppress-sound
-       (add-to-list 'hints `(:dict-entry
-                             "suppress-sound"
-                             (:variant :boolean ,suppress-sound)) t))
+        (push `(:dict-entry
+                "suppress-sound"
+                (:variant :boolean ,suppress-sound))
+              hints))
       (when resident
-       (add-to-list 'hints `(:dict-entry
-                             "resident"
-                             (:variant :boolean ,resident)) t))
+        (push `(:dict-entry
+                "resident"
+                (:variant :boolean ,resident))
+              hints))
       (when transient
-       (add-to-list 'hints `(:dict-entry
-                             "transient"
-                             (:variant :boolean ,transient)) t))
+        (push `(:dict-entry
+                "transient"
+                (:variant :boolean ,transient))
+              hints))
       (when x
-       (add-to-list 'hints `(:dict-entry "x" (:variant :int32 ,x)) t))
+        (push `(:dict-entry "x" (:variant :int32 ,x)) hints))
       (when y
-       (add-to-list 'hints `(:dict-entry "y" (:variant :int32 ,y)) t))
+        (push `(:dict-entry "y" (:variant :int32 ,y)) hints))
+
+      (setq hints (nreverse hints))
 
       ;; Call Notify method.
       (setq id
@@ -313,8 +326,8 @@ of another `notifications-notify' call."
            (on-close (plist-get params :on-close))
            (unique-name (dbus-get-name-owner bus notifications-service)))
        (when on-action
-         (add-to-list 'notifications-on-action-map
-                      (list (list bus unique-name id) on-action))
+          (push (list (list bus unique-name id) on-action)
+                notifications-on-action-map)
          (unless notifications-on-action-object
            (setq notifications-on-action-object
                  (dbus-register-signal
@@ -326,8 +339,8 @@ of another `notifications-notify' call."
                   'notifications-on-action-signal))))
 
        (when on-close
-         (add-to-list 'notifications-on-close-map
-                      (list (list bus unique-name id) on-close))
+          (push (list (list bus unique-name id) on-close)
+                notifications-on-close-map)
          (unless notifications-on-close-object
            (setq notifications-on-close-object
                  (dbus-register-signal
diff --git a/lisp/novice.el b/lisp/novice.el
index 22eca21..16766c2 100644
--- a/lisp/novice.el
+++ b/lisp/novice.el
@@ -1,4 +1,4 @@
-;;; novice.el --- handling of disabled commands ("novice mode") for Emacs
+;;; novice.el --- handling of disabled commands ("novice mode") for Emacs  -*- 
lexical-binding: t -*-
 
 ;; Copyright (C) 1985-1987, 1994, 2001-2021 Free Software Foundation,
 ;; Inc.
diff --git a/lisp/nxml/nxml-mode.el b/lisp/nxml/nxml-mode.el
index 0602943..1bc905c 100644
--- a/lisp/nxml/nxml-mode.el
+++ b/lisp/nxml/nxml-mode.el
@@ -546,7 +546,7 @@ Many aspects this mode can be customized using
     (when (and nxml-default-buffer-file-coding-system
               (not (local-variable-p 'buffer-file-coding-system)))
       (setq buffer-file-coding-system nxml-default-buffer-file-coding-system))
-    ;; When starting a new file, insert the XML declaraction.
+    ;; When starting a new file, insert the XML declaration.
     (when (and nxml-auto-insert-xml-declaration-flag
                (zerop (buffer-size)))
       (nxml-insert-xml-declaration)))
diff --git a/lisp/nxml/rng-cmpct.el b/lisp/nxml/rng-cmpct.el
index 45a69a7..3d4b9f8 100644
--- a/lisp/nxml/rng-cmpct.el
+++ b/lisp/nxml/rng-cmpct.el
@@ -26,7 +26,7 @@
 ;; specified in rng-pttrn.el.
 ;;
 ;; RELAX NG Compact Syntax is specified by
-;;    http://relaxng.org/compact.html
+;;    https://relaxng.org/compact.html
 ;;
 ;; This file uses the prefix "rng-c-".
 
diff --git a/lisp/nxml/rng-nxml.el b/lisp/nxml/rng-nxml.el
index 7d74fd3..7ea6fb2 100644
--- a/lisp/nxml/rng-nxml.el
+++ b/lisp/nxml/rng-nxml.el
@@ -24,7 +24,6 @@
 
 ;;; Code:
 
-(require 'easymenu)
 (require 'xmltok)
 (require 'nxml-util)
 (require 'nxml-ns)
diff --git a/lisp/nxml/rng-xsd.el b/lisp/nxml/rng-xsd.el
index 81314b8..9941aba 100644
--- a/lisp/nxml/rng-xsd.el
+++ b/lisp/nxml/rng-xsd.el
@@ -24,14 +24,14 @@
 
 ;; The main entry point is `rng-xsd-compile'. The validator
 ;; knows to use this for the datatype library with URI
-;; http://www.w3.org/2001/XMLSchema-datatypes because it
+;; https://www.w3.org/2001/XMLSchema-datatypes because it
 ;; is the value of the rng-dt-compile property on that URI
 ;; as a symbol.
 ;;
 ;; W3C XML Schema Datatypes are specified by
-;;   http://www.w3.org/TR/xmlschema-2/
+;;   https://www.w3.org/TR/xmlschema-2/
 ;; Guidelines for using them with RELAX NG are described in
-;;   http://relaxng.org/xsd.html
+;;   https://relaxng.org/xsd.html
 
 ;;; Code:
 
diff --git a/lisp/obsolete/abbrevlist.el b/lisp/obsolete/abbrevlist.el
index 1d517db..c9c0956 100644
--- a/lisp/obsolete/abbrevlist.el
+++ b/lisp/obsolete/abbrevlist.el
@@ -1,4 +1,4 @@
-;;; abbrevlist.el --- list one abbrev table alphabetically ordered
+;;; abbrevlist.el --- list one abbrev table alphabetically ordered  -*- 
lexical-binding: t; -*-
 
 ;; Copyright (C) 1986, 1992, 2001-2021 Free Software Foundation, Inc.
 ;; Suggested by a previous version by Gildea.
@@ -38,7 +38,7 @@
          (function (lambda (abbrev)
                      (setq abbrev-list (cons abbrev abbrev-list))))
          abbrev-table)
-       (setq abbrev-list (sort abbrev-list 'string-lessp))
+       (setq abbrev-list (sort abbrev-list #'string-lessp))
        (while abbrev-list
          (if (> (+ first-column 40) (window-width))
              (progn
diff --git a/lisp/obsolete/bruce.el b/lisp/obsolete/bruce.el
index 398f315..1c3581f 100644
--- a/lisp/obsolete/bruce.el
+++ b/lisp/obsolete/bruce.el
@@ -1,4 +1,4 @@
-;;; bruce.el --- bruce phrase utility for overloading the Communications
+;;; bruce.el --- bruce phrase utility for overloading the Communications  -*- 
lexical-binding: t; -*-
 ;;; Decency Act snoops, if any.
 
 ;; Copyright (C) 1988, 1993, 1997, 2001-2021 Free Software Foundation,
@@ -30,7 +30,7 @@
 ;; Decency Act of 1996. This Act bans "indecent speech", whatever that is,
 ;; from the Internet. For more on the CDA, see Richard Stallman's essay on
 ;; censorship, included in the etc directory of emacs distributions 19.34
-;; and up. See also http://www.eff.org/blueribbon.html.
+;; and up. See also https://www.eff.org/blueribbon.html.
 
 ;; For many years, emacs has included a program called Spook. This program
 ;; adds a series of "keywords" to email just before it goes out. On the
@@ -113,13 +113,11 @@
 
 (defcustom bruce-phrases-file "~/bruce.lines"
   "Keep your favorite phrases here."
-  :type 'file
-  :group 'bruce)
+  :type 'file)
 
 (defcustom bruce-phrase-default-count 15
   "Default number of phrases to insert."
-  :type 'integer
-  :group 'bruce)
+  :type 'integer)
 
 ;;;###autoload
 (defun bruce ()
diff --git a/lisp/obsolete/cc-compat.el b/lisp/obsolete/cc-compat.el
index 96b036e..037a8e9 100644
--- a/lisp/obsolete/cc-compat.el
+++ b/lisp/obsolete/cc-compat.el
@@ -1,4 +1,4 @@
-;;; cc-compat.el --- cc-mode compatibility with c-mode.el confusion
+;;; cc-compat.el --- cc-mode compatibility with c-mode.el confusion  -*- 
lexical-binding: t; -*-
 
 ;; Copyright (C) 1985, 1987, 1992-2021 Free Software Foundation, Inc.
 
@@ -156,7 +156,7 @@ This is in addition to c-continued-statement-offset.")
         (if bracep 0 c-indent-level)))))
 
 
-(defun cc-substatement-open-offset (langelem)
+(defun cc-substatement-open-offset (_langelem)
   (+ c-continued-statement-offset c-continued-brace-offset))
 
 
diff --git a/lisp/obsolete/cl-compat.el b/lisp/obsolete/cl-compat.el
index 4abedf3..619bc06 100644
--- a/lisp/obsolete/cl-compat.el
+++ b/lisp/obsolete/cl-compat.el
@@ -1,4 +1,4 @@
-;;; cl-compat.el --- Common Lisp extensions for GNU Emacs Lisp (compatibility)
+;;; cl-compat.el --- Common Lisp extensions for GNU Emacs Lisp (compatibility) 
 -*- lexical-binding: t; -*-
 
 ;; Copyright (C) 1993, 2001-2021 Free Software Foundation, Inc.
 
@@ -46,31 +46,23 @@
 
 ;;; Code:
 
-;; This used to be:
-;; (or (featurep 'cl) (require 'cl))
-;; which just has the effect of fooling the byte-compiler into not
-;; loading cl when compiling.  However, that leads to some bogus
-;; compiler warnings.  Loading cl when compiling cannot do any harm,
-;; because for a long time bootstrap-emacs contained 'cl, due to being
-;; dumped from uncompiled files that eval-when-compile'd cl.  So every
-;; file was compiled with 'cl loaded.
-(require 'cl)
+(require 'cl-lib)
 
 
 ;;; Keyword routines not supported by new package.
 
 (defmacro defkeyword (x &optional doc)
-  (list* 'defconst x (list 'quote x) (and doc (list doc))))
+  (cl-list* 'defconst x (list 'quote x) (and doc (list doc))))
 
 (defun keyword-of (sym)
   (or (keywordp sym) (keywordp (intern (format ":%s" sym)))))
 
 
-;;; Multiple values.  Note that the new package uses a different
-;;; convention for multiple values.  The following definitions
-;;; emulate the old convention; all function names have been changed
-;;; by capitalizing the first letter: Values, Multiple-value-*,
-;;; to avoid conflict with the new-style definitions in cl-macs.
+;; Multiple values.  Note that the new package uses a different
+;; convention for multiple values.  The following definitions
+;; emulate the old convention; all function names have been changed
+;; by capitalizing the first letter: Values, Multiple-value-*,
+;; to avoid conflict with the new-style definitions in cl-macs.
 
 (defvar *mvalues-values* nil)
 
@@ -79,7 +71,7 @@
   (car val-forms))
 
 (defun Values-list (val-forms)
-  (apply 'values val-forms))
+  (apply #'cl-values val-forms))
 
 (defmacro Multiple-value-list (form)
   (list 'let* (list '(*mvalues-values* nil) (list '*mvalues-temp* form))
@@ -95,7 +87,7 @@
 
 (defmacro Multiple-value-bind (vars form &rest body)
   (declare (indent 2))
-  (list* 'multiple-value-bind vars (list 'Multiple-value-list form) body))
+  (cl-list* 'multiple-value-bind vars (list 'Multiple-value-list form) body))
 
 (defmacro Multiple-value-setq (vars form)
   (declare (indent 2))
@@ -103,17 +95,16 @@
 
 (defmacro Multiple-value-prog1 (form &rest body)
   (declare (indent 1))
-  (list 'prog1 form (list* 'let '((*mvalues-values* nil)) body)))
+  (list 'prog1 form (cl-list* 'let '((*mvalues-values* nil)) body)))
 
 
 ;;; Routines for parsing keyword arguments.
 
 (defun build-klist (arglist keys &optional allow-others)
-  (let ((res (Multiple-value-call 'mapcar* 'cons (unzip-lists arglist))))
+  (let ((res (Multiple-value-call #'cl-mapcar 'cons (unzip-lists arglist))))
     (or allow-others
-        (with-suppressed-warnings ((obsolete set-difference))
-          (let ((bad (set-difference (mapcar 'car res) keys)))
-            (if bad (error "Bad keywords: %s not in %s" bad keys)))))
+        (let ((bad (cl-set-difference (mapcar #'car res) keys)))
+          (if bad (error "Bad keywords: %s not in %s" bad keys))))
     res))
 
 (defun extract-from-klist (klist key &optional def)
@@ -131,18 +122,16 @@
       (funcall (or test 'eql) item elt))))
 
 (defun safe-idiv (a b)
-  (with-suppressed-warnings ((obsolete signum))
-    (let* ((q (/ (abs a) (abs b)))
-           (s (* (signum a) (signum b))))
-      (Values q (- a (* s q b)) s))))
+  (let* ((q (/ (abs a) (abs b)))
+         (s (* (cl-signum a) (cl-signum b))))
+    (Values q (- a (* s q b)) s)))
 
 
 ;; Internal routines.
 
 (defun pair-with-newsyms (oldforms)
-  (with-suppressed-warnings ((obsolete mapcar*))
-    (let ((newsyms (mapcar (lambda (x) (make-symbol "--cl-var--")) oldforms)))
-      (Values (mapcar* 'list newsyms oldforms) newsyms))))
+  (let ((newsyms (mapcar (lambda (_) (make-symbol "--cl-var--")) oldforms)))
+    (Values (cl-mapcar #'list newsyms oldforms) newsyms)))
 
 (defun zip-lists (evens odds)
   (cl-mapcan 'list evens odds))
@@ -154,7 +143,7 @@
     (Values (nreverse e) (nreverse o))))
 
 (defun reassemble-argslists (list)
-  (let ((n (apply 'min (mapcar 'length list))) (res nil))
+  (let ((n (apply #'min (mapcar #'length list))) (res nil))
     (while (>= (setq n (1- n)) 0)
       (setq res (cons (mapcar (function (lambda (x) (elt x n))) list) res)))
     res))
diff --git a/lisp/obsolete/cl.el b/lisp/obsolete/cl.el
index 95af29b..09f9ab7 100644
--- a/lisp/obsolete/cl.el
+++ b/lisp/obsolete/cl.el
@@ -331,7 +331,7 @@ The two cases that are handled are:
                         (cddr f))))
       (if (and cl-closure-vars
                (cl--expr-contains-any body cl-closure-vars))
-          (let* ((new (mapcar 'cl-gensym cl-closure-vars))
+          (let* ((new (mapcar #'cl-gensym cl-closure-vars))
                  (sub (cl-pairlis cl-closure-vars new)) (decls nil))
             (while (or (stringp (car body))
                        (eq (car-safe (car body)) 'interactive))
@@ -438,7 +438,7 @@ definitions, or lack thereof).
              (let ((func `(cl-function
                            (lambda ,(cadr x)
                              (cl-block ,(car x) ,@(cddr x))))))
-               (when (cl--compiling-file)
+               (when (macroexp-compiling-p)
                  ;; Bug#411.  It would be nice to fix this.
                  (and (get (car x) 'byte-compile)
                       (error "Byte-compiling a redefinition of `%s' \
@@ -446,7 +446,7 @@ will not work - use `labels' instead" (symbol-name (car 
x))))
                  ;; FIXME This affects the rest of the file, when it
                  ;; should be restricted to the flet body.
                  (and (boundp 'byte-compile-function-environment)
-                      (push (cons (car x) (eval func))
+                      (push (cons (car x) (eval func t))
                             byte-compile-function-environment)))
                (list `(symbol-function ',(car x)) func)))
            bindings)
@@ -630,10 +630,10 @@ You can replace this macro with `gv-letplace'."
 ;;; Additional compatibility code.
 ;; For names that were clean but really aren't needed any more.
 
-(define-obsolete-function-alias 'cl-macroexpand 'macroexpand "24.3")
+(define-obsolete-function-alias 'cl-macroexpand #'macroexpand "24.3")
 (define-obsolete-variable-alias 'cl-macro-environment
   'macroexpand-all-environment "24.3")
-(define-obsolete-function-alias 'cl-macroexpand-all 'macroexpand-all "24.3")
+(define-obsolete-function-alias 'cl-macroexpand-all #'macroexpand-all "24.3")
 
 ;;; Hash tables.
 ;; This is just kept for compatibility with code byte-compiled by Emacs-20.
@@ -652,22 +652,22 @@ You can replace this macro with `gv-letplace'."
 (defvar cl-builtin-maphash (symbol-function 'maphash))
 
 (make-obsolete-variable 'cl-builtin-maphash nil "24.3")
-(define-obsolete-function-alias 'cl-map-keymap 'map-keymap "24.3")
-(define-obsolete-function-alias 'cl-copy-tree 'copy-tree "24.3")
-(define-obsolete-function-alias 'cl-gethash 'gethash "24.3")
-(define-obsolete-function-alias 'cl-puthash 'puthash "24.3")
-(define-obsolete-function-alias 'cl-remhash 'remhash "24.3")
-(define-obsolete-function-alias 'cl-clrhash 'clrhash "24.3")
-(define-obsolete-function-alias 'cl-maphash 'maphash "24.3")
-(define-obsolete-function-alias 'cl-make-hash-table 'make-hash-table "24.3")
-(define-obsolete-function-alias 'cl-hash-table-p 'hash-table-p "24.3")
-(define-obsolete-function-alias 'cl-hash-table-count 'hash-table-count "24.3")
+(define-obsolete-function-alias 'cl-map-keymap #'map-keymap "24.3")
+(define-obsolete-function-alias 'cl-copy-tree #'copy-tree "24.3")
+(define-obsolete-function-alias 'cl-gethash #'gethash "24.3")
+(define-obsolete-function-alias 'cl-puthash #'puthash "24.3")
+(define-obsolete-function-alias 'cl-remhash #'remhash "24.3")
+(define-obsolete-function-alias 'cl-clrhash #'clrhash "24.3")
+(define-obsolete-function-alias 'cl-maphash #'maphash "24.3")
+(define-obsolete-function-alias 'cl-make-hash-table #'make-hash-table "24.3")
+(define-obsolete-function-alias 'cl-hash-table-p #'hash-table-p "24.3")
+(define-obsolete-function-alias 'cl-hash-table-count #'hash-table-count "24.3")
 
 (define-obsolete-function-alias 'cl-map-keymap-recursively
-  'cl--map-keymap-recursively "24.3")
-(define-obsolete-function-alias 'cl-map-intervals 'cl--map-intervals "24.3")
-(define-obsolete-function-alias 'cl-map-extents 'cl--map-overlays "24.3")
-(define-obsolete-function-alias 'cl-set-getf 'cl--set-getf "24.3")
+  #'cl--map-keymap-recursively "24.3")
+(define-obsolete-function-alias 'cl-map-intervals #'cl--map-intervals "24.3")
+(define-obsolete-function-alias 'cl-map-extents #'cl--map-overlays "24.3")
+(define-obsolete-function-alias 'cl-set-getf #'cl--set-getf "24.3")
 
 (defun cl-maclisp-member (item list)
   (declare (obsolete member "24.3"))
diff --git a/lisp/obsolete/complete.el b/lisp/obsolete/complete.el
index 735e1e0..1c1167d 100644
--- a/lisp/obsolete/complete.el
+++ b/lisp/obsolete/complete.el
@@ -1,4 +1,4 @@
-;;; complete.el --- partial completion mechanism plus other goodies
+;;; complete.el --- partial completion mechanism plus other goodies  -*- 
lexical-binding: t; -*-
 
 ;; Copyright (C) 1990-1993, 1999-2021 Free Software Foundation, Inc.
 
@@ -102,14 +102,12 @@ If non-nil and non-t, the first character is taken 
literally only for file name
 completion."
   :type '(choice (const :tag "delimiter" nil)
                 (const :tag "literal" t)
-                (other :tag "find-file" find-file))
-  :group 'partial-completion)
+                (other :tag "find-file" find-file)))
 
 (defcustom PC-meta-flag t
   "If non-nil, TAB means PC completion and M-TAB means normal completion.
 Otherwise, TAB means normal completion and M-TAB means Partial Completion."
-  :type 'boolean
-  :group 'partial-completion)
+  :type 'boolean)
 
 (defcustom PC-word-delimiters "-_. "
   "A string of characters treated as word delimiters for completion.
@@ -119,19 +117,16 @@ If `^' is in this string, it must not come first.
 If `-' is in this string, it must come first or right after `]'.
 In other words, if S is this string, then `[S]' must be a valid Emacs regular
 expression (not containing character ranges like `a-z')."
-  :type 'string
-  :group 'partial-completion)
+  :type 'string)
 
 (defcustom PC-include-file-path '("/usr/include" "/usr/local/include")
   "A list of directories in which to look for include files.
 If nil, means use the colon-separated path in the variable $INCPATH instead."
-  :type '(repeat directory)
-  :group 'partial-completion)
+  :type '(repeat directory))
 
 (defcustom PC-disable-includes nil
   "If non-nil, include-file support in \\[find-file] is disabled."
-  :type 'boolean
-  :group 'partial-completion)
+  :type 'boolean)
 
 (defvar PC-default-bindings t
   "If non-nil, default partial completion key bindings are suppressed.")
@@ -146,36 +141,36 @@ If nil, means use the colon-separated path in the 
variable $INCPATH instead."
     (cond ((not bind)
           ;; These bindings are the default bindings.  It would be better to
           ;; restore the previous bindings.
-          (define-key read-expression-map "\e\t" 'lisp-complete-symbol)
+          (define-key read-expression-map "\e\t" #'completion-at-point)
 
-          (define-key completion-map "\t"      'minibuffer-complete)
-          (define-key completion-map " "       'minibuffer-complete-word)
-          (define-key completion-map "?"       'minibuffer-completion-help)
+          (define-key completion-map "\t"      #'minibuffer-complete)
+          (define-key completion-map " "       #'minibuffer-complete-word)
+          (define-key completion-map "?"       #'minibuffer-completion-help)
 
-          (define-key must-match-map "\r"      'minibuffer-complete-and-exit)
-          (define-key must-match-map "\n"      'minibuffer-complete-and-exit)
+          (define-key must-match-map "\r"      #'minibuffer-complete-and-exit)
+          (define-key must-match-map "\n"      #'minibuffer-complete-and-exit)
 
           (define-key global-map [remap lisp-complete-symbol]  nil))
          (PC-default-bindings
-          (define-key read-expression-map "\e\t" 'PC-lisp-complete-symbol)
+          (define-key read-expression-map "\e\t" #'PC-lisp-complete-symbol)
 
-          (define-key completion-map "\t"      'PC-complete)
-          (define-key completion-map " "       'PC-complete-word)
-          (define-key completion-map "?"       'PC-completion-help)
+          (define-key completion-map "\t"      #'PC-complete)
+          (define-key completion-map " "       #'PC-complete-word)
+          (define-key completion-map "?"       #'PC-completion-help)
 
-          (define-key completion-map "\e\t"    'PC-complete)
-          (define-key completion-map "\e "     'PC-complete-word)
-          (define-key completion-map "\e\r"    'PC-force-complete-and-exit)
-          (define-key completion-map "\e\n"    'PC-force-complete-and-exit)
-          (define-key completion-map "\e?"     'PC-completion-help)
+          (define-key completion-map "\e\t"    #'PC-complete)
+          (define-key completion-map "\e "     #'PC-complete-word)
+          (define-key completion-map "\e\r"    #'PC-force-complete-and-exit)
+          (define-key completion-map "\e\n"    #'PC-force-complete-and-exit)
+          (define-key completion-map "\e?"     #'PC-completion-help)
 
-          (define-key must-match-map "\r"      'PC-complete-and-exit)
-          (define-key must-match-map "\n"      'PC-complete-and-exit)
+          (define-key must-match-map "\r"      #'PC-complete-and-exit)
+          (define-key must-match-map "\n"      #'PC-complete-and-exit)
 
-          (define-key must-match-map "\e\r"    'PC-complete-and-exit)
-          (define-key must-match-map "\e\n"    'PC-complete-and-exit)
+          (define-key must-match-map "\e\r"    #'PC-complete-and-exit)
+          (define-key must-match-map "\e\n"    #'PC-complete-and-exit)
 
-          (define-key global-map [remap lisp-complete-symbol]  
'PC-lisp-complete-symbol)))))
+          (define-key global-map [remap lisp-complete-symbol]  
#'PC-lisp-complete-symbol)))))
 
 (defvar PC-do-completion-end nil
   "Internal variable used by `PC-do-completion'.")
@@ -212,14 +207,15 @@ see), so that if it is neither nil nor t, Emacs shows the 
`*Completions*'
 buffer only on the second attempt to complete.  That is, if TAB finds nothing
 to complete, the first TAB just says \"Next char not unique\" and the
 second TAB brings up the `*Completions*' buffer."
-  :global t :group 'partial-completion
+  :global t
   ;; Deal with key bindings...
   (PC-bindings partial-completion-mode)
   ;; Deal with include file feature...
   (cond ((not partial-completion-mode)
-        (remove-hook 'find-file-not-found-functions 'PC-look-for-include-file))
+        (remove-hook 'find-file-not-found-functions
+                     #'PC-look-for-include-file))
        ((not PC-disable-includes)
-        (add-hook 'find-file-not-found-functions 'PC-look-for-include-file)))
+        (add-hook 'find-file-not-found-functions #'PC-look-for-include-file)))
   ;; Adjust the completion selection in *Completion* buffers to the way
   ;; we work.  The default minibuffer completion code only completes the
   ;; text before point and leaves the text after point alone (new in
@@ -229,9 +225,9 @@ second TAB brings up the `*Completions*' buffer."
   ;; to trick choose-completion into replacing the whole minibuffer text
   ;; rather than only the text before point.  --Stef
   (funcall
-   (if partial-completion-mode 'add-hook 'remove-hook)
+   (if partial-completion-mode #'add-hook #'remove-hook)
    'choose-completion-string-functions
-   (lambda (choice buffer &rest ignored)
+   (lambda (_choice buffer &rest _)
      ;; When completing M-: (lisp- ) with point before the ), it is
      ;; not appropriate to go to point-max (unlike the filename case).
      (if (and (not PC-goto-end)
@@ -648,7 +644,7 @@ GOTO-END is non-nil, however, it instead replaces up to 
END."
                       (when (string-match regex x)
                         (push x p)))
                     (setq basestr (try-completion "" p)))
-                  (setq basestr (mapconcat 'list str "-"))
+                  (setq basestr (mapconcat #'list str "-"))
                   (delete-region beg end)
                   (setq end (+ beg (length basestr)))
                   (insert basestr))))
@@ -672,7 +668,7 @@ GOTO-END is non-nil, however, it instead replaces up to 
END."
                  (setq PC-ignored-regexp
                        (concat "\\("
                                (mapconcat
-                                'regexp-quote
+                                #'regexp-quote
                                 (setq PC-ignored-extensions
                                       completion-ignored-extensions)
                                 "\\|")
@@ -815,7 +811,7 @@ GOTO-END is non-nil, however, it instead replaces up to 
END."
                        (eq mode 'help))
                     (let ((prompt-end (minibuffer-prompt-end)))
                       (with-output-to-temp-buffer "*Completions*"
-                        (display-completion-list (sort helpposs 'string-lessp))
+                        (display-completion-list (sort helpposs 
#'string-lessp))
                         (setq PC-do-completion-end end
                               PC-goto-end goto-end)
                         (with-current-buffer standard-output
@@ -1093,7 +1089,7 @@ absolute rather than relative to some directory on the 
SEARCH-PATH."
                       file-lists))))
          (setq search-path (cdr search-path))))
       ;; Compress out duplicates while building complete list (slloooow!)
-      (let ((sorted (sort (apply 'nconc file-lists)
+      (let ((sorted (sort (apply #'nconc file-lists)
                          (lambda (x y) (not (string-lessp x y)))))
            compressed)
        (while sorted
diff --git a/lisp/obsolete/crisp.el b/lisp/obsolete/crisp.el
index 91ff899..69bf3ed 100644
--- a/lisp/obsolete/crisp.el
+++ b/lisp/obsolete/crisp.el
@@ -1,4 +1,4 @@
-;;; crisp.el --- CRiSP/Brief Emacs emulator
+;;; crisp.el --- CRiSP/Brief Emacs emulator  -*- lexical-binding: t; -*-
 
 ;; Copyright (C) 1997-1999, 2001-2021 Free Software Foundation, Inc.
 
@@ -66,63 +66,63 @@
 
 (defvar crisp-mode-map
   (let ((map (make-sparse-keymap)))
-    (define-key map [(f1)]           'other-window)
+    (define-key map [(f1)]           #'other-window)
 
-    (define-key map [(f2) (down)]    'enlarge-window)
-    (define-key map [(f2) (left)]    'shrink-window-horizontally)
-    (define-key map [(f2) (right)]   'enlarge-window-horizontally)
-    (define-key map [(f2) (up)]      'shrink-window)
-    (define-key map [(f3) (down)]    'split-window-below)
-    (define-key map [(f3) (right)]   'split-window-right)
+    (define-key map [(f2) (down)]    #'enlarge-window)
+    (define-key map [(f2) (left)]    #'shrink-window-horizontally)
+    (define-key map [(f2) (right)]   #'enlarge-window-horizontally)
+    (define-key map [(f2) (up)]      #'shrink-window)
+    (define-key map [(f3) (down)]    #'split-window-below)
+    (define-key map [(f3) (right)]   #'split-window-right)
 
-    (define-key map [(f4)]           'delete-window)
-    (define-key map [(control f4)]   'delete-other-windows)
+    (define-key map [(f4)]           #'delete-window)
+    (define-key map [(control f4)]   #'delete-other-windows)
 
-    (define-key map [(f5)]           'search-forward-regexp)
-    (define-key map [(f19)]          'search-forward-regexp)
-    (define-key map [(meta f5)]      'search-backward-regexp)
+    (define-key map [(f5)]           #'search-forward-regexp)
+    (define-key map [(f19)]          #'search-forward-regexp)
+    (define-key map [(meta f5)]      #'search-backward-regexp)
 
-    (define-key map [(f6)]           'query-replace)
+    (define-key map [(f6)]           #'query-replace)
 
-    (define-key map [(f7)]           'start-kbd-macro)
-    (define-key map [(meta f7)]      'end-kbd-macro)
+    (define-key map [(f7)]           #'start-kbd-macro)
+    (define-key map [(meta f7)]      #'end-kbd-macro)
 
-    (define-key map [(f8)]           'call-last-kbd-macro)
-    (define-key map [(meta f8)]      'save-kbd-macro)
+    (define-key map [(f8)]           #'call-last-kbd-macro)
+    ;;(define-key map [(meta f8)]    #'save-kbd-macro) ;FIXME:Unknown command?
 
-    (define-key map [(f9)]           'find-file)
-    (define-key map [(meta f9)]      'load-library)
+    (define-key map [(f9)]           #'find-file)
+    (define-key map [(meta f9)]      #'load-library)
 
-    (define-key map [(f10)]          'execute-extended-command)
-    (define-key map [(meta f10)]     'compile)
+    (define-key map [(f10)]          #'execute-extended-command)
+    (define-key map [(meta f10)]     #'compile)
 
-    (define-key map [(SunF37)]       'kill-buffer)
-    (define-key map [(kp-add)]       'crisp-copy-line)
-    (define-key map [(kp-subtract)]  'crisp-kill-line)
+    (define-key map [(SunF37)]       #'kill-buffer)
+    (define-key map [(kp-add)]       #'crisp-copy-line)
+    (define-key map [(kp-subtract)]  #'crisp-kill-line)
     ;; just to cover all the bases (GNU Emacs, for instance)
-    (define-key map [(f24)]          'crisp-kill-line)
-    (define-key map [(insert)]       'crisp-yank-clipboard)
-    (define-key map [(f16)]          'crisp-set-clipboard) ; copy on Sun5 kbd
-    (define-key map [(f20)]          'crisp-kill-region) ; cut on Sun5 kbd
-    (define-key map [(f18)]          'crisp-yank-clipboard) ; paste on Sun5 kbd
+    (define-key map [(f24)]          #'crisp-kill-line)
+    (define-key map [(insert)]       #'crisp-yank-clipboard)
+    (define-key map [(f16)]          #'crisp-set-clipboard) ; copy on Sun5 kbd
+    (define-key map [(f20)]          #'crisp-kill-region) ; cut on Sun5 kbd
+    (define-key map [(f18)]          #'crisp-yank-clipboard) ; paste on Sun5 
kbd
 
-    (define-key map [(control f)]    'fill-paragraph-or-region)
+    ;; (define-key map [(control f)]    #'fill-paragraph-or-region)
     (define-key map [(meta d)]       (lambda ()
                                        (interactive)
                                        (beginning-of-line) (kill-line)))
-    (define-key map [(meta e)]       'find-file)
-    (define-key map [(meta g)]       'goto-line)
-    (define-key map [(meta h)]       'help)
-    (define-key map [(meta i)]       'overwrite-mode)
-    (define-key map [(meta j)]       'bookmark-jump)
-    (define-key map [(meta l)]       'crisp-mark-line)
-    (define-key map [(meta m)]       'set-mark-command)
-    (define-key map [(meta n)]       'bury-buffer)
-    (define-key map [(meta p)]       'crisp-unbury-buffer)
-    (define-key map [(meta u)]       'undo)
-    (define-key map [(f14)]          'undo)
-    (define-key map [(meta w)]       'save-buffer)
-    (define-key map [(meta x)]       'crisp-meta-x-wrapper)
+    (define-key map [(meta e)]       #'find-file)
+    (define-key map [(meta g)]       #'goto-line)
+    (define-key map [(meta h)]       #'help)
+    (define-key map [(meta i)]       #'overwrite-mode)
+    (define-key map [(meta j)]       #'bookmark-jump)
+    (define-key map [(meta l)]       #'crisp-mark-line)
+    (define-key map [(meta m)]       #'set-mark-command)
+    (define-key map [(meta n)]       #'bury-buffer)
+    (define-key map [(meta p)]       #'crisp-unbury-buffer)
+    (define-key map [(meta u)]       #'undo)
+    (define-key map [(f14)]          #'undo)
+    (define-key map [(meta w)]       #'save-buffer)
+    (define-key map [(meta x)]       #'crisp-meta-x-wrapper)
     (define-key map [(meta ?0)]      (lambda ()
                                        (interactive)
                                        (bookmark-set "0")))
@@ -154,21 +154,21 @@
                                        (interactive)
                                        (bookmark-set "9")))
 
-    (define-key map [(shift delete)]    'kill-word)
-    (define-key map [(shift backspace)] 'backward-kill-word)
-    (define-key map [(control left)]    'backward-word)
-    (define-key map [(control right)]   'forward-word)
+    (define-key map [(shift delete)]    #'kill-word)
+    (define-key map [(shift backspace)] #'backward-kill-word)
+    (define-key map [(control left)]    #'backward-word)
+    (define-key map [(control right)]   #'forward-word)
 
-    (define-key map [(home)]            'crisp-home)
+    (define-key map [(home)]            #'crisp-home)
     (define-key map [(control home)]    (lambda ()
                                           (interactive)
                                           (move-to-window-line 0)))
-    (define-key map [(meta home)]       'beginning-of-line)
-    (define-key map [(end)]             'crisp-end)
+    (define-key map [(meta home)]       #'beginning-of-line)
+    (define-key map [(end)]             #'crisp-end)
     (define-key map [(control end)]     (lambda ()
                                           (interactive)
                                           (move-to-window-line -1)))
-    (define-key map [(meta end)]        'end-of-line)
+    (define-key map [(meta end)]        #'end-of-line)
     map)
   "Local keymap for CRiSP emulation mode.
 All the bindings are done here instead of globally to try and be
@@ -179,8 +179,7 @@ nice to the world.")
 
 (defcustom crisp-mode-mode-line-string " *CRiSP*"
   "String to display in the mode line when CRiSP emulation mode is enabled."
-  :type 'string
-  :group 'crisp)
+  :type 'string)
 
 ;;;###autoload
 (defcustom crisp-mode nil
@@ -190,20 +189,18 @@ indicates CRiSP mode is enabled.
 
 Setting this variable directly does not take effect;
 use either M-x customize or the function `crisp-mode'."
-  :set (lambda (symbol value) (crisp-mode (if value 1 0)))
-  :initialize 'custom-initialize-default
+  :set (lambda (_symbol value) (crisp-mode (if value 1 0)))
+  :initialize #'custom-initialize-default
   :require 'crisp
   :version "20.4"
-  :type 'boolean
-  :group 'crisp)
+  :type 'boolean)
 
 (defcustom crisp-override-meta-x t
   "Controls overriding the normal Emacs M-x key binding in the CRiSP emulator.
 Normally the CRiSP emulator rebinds M-x to `save-buffers-exit-emacs', and
 provides the usual M-x functionality on the F10 key.  If this variable
 is non-nil, M-x will exit Emacs."
-  :type 'boolean
-  :group 'crisp)
+  :type 'boolean)
 
 (defcustom crisp-load-scroll-all nil
   "Controls loading of the Scroll Lock in the CRiSP emulator.
@@ -212,18 +209,15 @@ package when enabling the CRiSP emulator.
 
 If this variable is nil when you start the CRiSP emulator, it
 does not load the scroll-all package."
-  :type 'boolean
-  :group 'crisp)
+  :type 'boolean)
 
 (defcustom crisp-load-hook nil
   "Hooks to run after loading the CRiSP emulator package."
-  :type 'hook
-  :group 'crisp)
+  :type 'hook)
 
 (defcustom crisp-mode-hook nil
   "Hook run by the function `crisp-mode'."
-  :type 'hook
-  :group 'crisp)
+  :type 'hook)
 
 (defconst crisp-version "1.34"
   "The version of the CRiSP emulator.")
@@ -370,11 +364,11 @@ normal CRiSP binding) and when it is nil M-x will run
     (if crisp-load-scroll-all
        (require 'scroll-all))
     (if (featurep 'scroll-all)
-       (define-key crisp-mode-map [(meta f1)] 'scroll-all-mode))))
+       (define-key crisp-mode-map [(meta f1)] #'scroll-all-mode))))
 
 ;; People might use Apropos on `brief'.
 ;;;###autoload
-(defalias 'brief-mode 'crisp-mode)
+(defalias 'brief-mode #'crisp-mode)
 
 (run-hooks 'crisp-load-hook)
 (provide 'crisp)
diff --git a/lisp/obsolete/cust-print.el b/lisp/obsolete/cust-print.el
index c7342b6..01fcd38 100644
--- a/lisp/obsolete/cust-print.el
+++ b/lisp/obsolete/cust-print.el
@@ -1,4 +1,4 @@
-;;; cust-print.el --- handles print-level and print-circle
+;;; cust-print.el --- handles print-level and print-circle  -*- 
lexical-binding: t; -*-
 
 ;; Copyright (C) 1992, 2001-2021 Free Software Foundation, Inc.
 
@@ -118,9 +118,6 @@
 
 ;; Emacs 18 doesn't have defalias.
 ;; Provide def for byte compiler.
-(eval-and-compile
-  (or (fboundp 'defalias) (fset 'defalias 'fset)))
-
 
 ;; Variables:
 ;;=========================================================
@@ -141,8 +138,7 @@ If non-nil, components at levels equal to or greater than 
`print-level'
 are printed simply as `#'.  The object to be printed is at level 0,
 and if the object is a list or vector, its top-level components are at
 level 1."
-  :type '(choice (const nil) integer)
-  :group 'cust-print)
+  :type '(choice (const nil) integer))
 
 
 (defcustom print-circle nil
@@ -157,14 +153,12 @@ If non-nil, shared substructures anywhere in the 
structure are printed
 with `#N=' before the first occurrence (in the order of the print
 representation) and `#N#' in place of each subsequent occurrence,
 where N is a positive decimal integer."
-  :type 'boolean
-  :group 'cust-print)
+  :type 'boolean)
 
 
 (defcustom custom-print-vectors nil
   "Non-nil if printing of vectors should obey `print-level' and 
`print-length'."
-  :type 'boolean
-  :group 'cust-print)
+  :type 'boolean)
 
 
 ;; Custom printers
@@ -201,7 +195,7 @@ Any pair that has the same PREDICATE is first removed."
   (cust-print-update-custom-printers))
 
 
-(defun cust-print-use-custom-printer (object)
+(defun cust-print-use-custom-printer (_object)
   ;; Default function returns nil.
   nil)
 
@@ -231,11 +225,11 @@ Any pair that has the same PREDICATE is first removed."
   (defalias (car symbol-pair)
     (symbol-function (car (cdr symbol-pair)))))
 
-(defun cust-print-original-princ (object &optional stream)) ; dummy def
+(defun cust-print-original-princ (_object &optional _stream) nil) ; dummy def
 
 ;; Save emacs routines.
 (if (not (fboundp 'cust-print-original-prin1))
-    (mapc 'cust-print-set-function-cell
+    (mapc #'cust-print-set-function-cell
          '((cust-print-original-prin1 prin1)
            (cust-print-original-princ princ)
            (cust-print-original-print print)
@@ -243,14 +237,15 @@ Any pair that has the same PREDICATE is first removed."
            (cust-print-original-format format)
            (cust-print-original-message message)
            (cust-print-original-error error))))
-
+(declare-function cust-print-original-format "cust-print")
+(declare-function cust-print-original-message "cust-print")
 
 (defun custom-print-install ()
   "Replace print functions with general, customizable, Lisp versions.
 The Emacs subroutines are saved away, and you can reinstall them
 by running `custom-print-uninstall'."
   (interactive)
-  (mapc 'cust-print-set-function-cell
+  (mapc #'cust-print-set-function-cell
        '((prin1 custom-prin1)
          (princ custom-princ)
          (print custom-print)
@@ -264,7 +259,7 @@ by running `custom-print-uninstall'."
 (defun custom-print-uninstall ()
   "Reset print functions to their Emacs subroutines."
   (interactive)
-  (mapc 'cust-print-set-function-cell
+  (mapc #'cust-print-set-function-cell
        '((prin1 cust-print-original-prin1)
          (princ cust-print-original-princ)
          (print cust-print-original-print)
@@ -275,22 +270,20 @@ by running `custom-print-uninstall'."
          ))
   t)
 
-(defalias 'custom-print-funcs-installed-p 'custom-print-installed-p)
+(defalias 'custom-print-funcs-installed-p #'custom-print-installed-p)
 (defun custom-print-installed-p ()
   "Return t if custom-print is currently installed, nil otherwise."
   (eq (symbol-function 'custom-prin1) (symbol-function 'prin1)))
 
-(put 'with-custom-print-funcs 'edebug-form-spec '(body))
-(put 'with-custom-print 'edebug-form-spec '(body))
-
-(defalias 'with-custom-print-funcs 'with-custom-print)
 (defmacro with-custom-print (&rest body)
   "Temporarily install the custom print package while executing BODY."
+  (declare (debug t))
   `(unwind-protect
        (progn
         (custom-print-install)
         ,@body)
      (custom-print-uninstall)))
+(defalias 'with-custom-print-funcs #'with-custom-print)
 
 
 ;; Lisp replacements for prin1 and princ, and for some subrs that use them
@@ -369,7 +362,7 @@ vector, or symbol args.  The format specification for such 
args should
 be `%s' in any case, so a string argument will also work.  The string
 is generated with `custom-prin1-to-string', which quotes quotable
 characters."
-  (apply 'cust-print-original-format fmt
+  (apply #'cust-print-original-format fmt
         (mapcar (function (lambda (arg)
                             (if (or (listp arg) (vectorp arg) (symbolp arg))
                                 (custom-prin1-to-string arg)
@@ -393,7 +386,7 @@ See `custom-format' for the details."
   ;; because the echo area requires special handling
   ;; to avoid duplicating the output.
   ;; cust-print-original-message does it right.
-  (apply 'cust-print-original-message  fmt
+  (apply #'cust-print-original-message  fmt
         (mapcar (function (lambda (arg)
                             (if (or (listp arg) (vectorp arg) (symbolp arg))
                                 (custom-prin1-to-string arg)
@@ -406,7 +399,7 @@ See `custom-format' for the details."
 
 This is the custom-print replacement for the standard `error'.
 See `custom-format' for the details."
-  (signal 'error (list (apply 'custom-format fmt args))))
+  (signal 'error (list (apply #'custom-format fmt args))))
 
 
 
@@ -417,9 +410,9 @@ See `custom-format' for the details."
 (defvar circle-table)
 (defvar cust-print-current-level)
 
-(defun cust-print-original-printer (object))  ; One of the standard printers.
-(defun cust-print-low-level-prin (object))    ; Used internally.
-(defun cust-print-prin (object))              ; Call this to print recursively.
+(defun cust-print-original-printer (_object) nil) ; One of the standard 
printers.
+(defun cust-print-low-level-prin (_object) nil)   ; Used internally.
+(defun cust-print-prin (_object) nil) ; Call this to print recursively.
 
 (defun cust-print-top-level (object stream emacs-printer)
   ;; Set up for printing.
diff --git a/lisp/obsolete/erc-compat.el b/lisp/obsolete/erc-compat.el
index 203ef07..9972e92 100644
--- a/lisp/obsolete/erc-compat.el
+++ b/lisp/obsolete/erc-compat.el
@@ -1,4 +1,4 @@
-;;; erc-compat.el --- ERC compatibility code for XEmacs
+;;; erc-compat.el --- ERC compatibility code for XEmacs  -*- lexical-binding: 
t; -*-
 
 ;; Copyright (C) 2002-2003, 2005-2021 Free Software Foundation, Inc.
 
@@ -31,8 +31,7 @@
 (require 'format-spec)
 
 ;;;###autoload(autoload 'erc-define-minor-mode "erc-compat")
-(defalias 'erc-define-minor-mode 'define-minor-mode)
-(put 'erc-define-minor-mode 'edebug-form-spec 'define-minor-mode)
+(defalias 'erc-define-minor-mode #'define-minor-mode)
 
 (defun erc-decode-coding-string (s coding-system)
   "Decode S using CODING-SYSTEM."
@@ -73,7 +72,7 @@ are placed.
 Note that this should end with a directory separator.")
 
 (defun erc-replace-match-subexpression-in-string
-  (newtext string match subexp start &optional fixedcase literal)
+  (newtext string _match subexp _start &optional fixedcase literal)
   "Replace the subexpression SUBEXP of the last match in STRING with NEWTEXT.
 MATCH is the text which matched the subexpression (see `match-string').
 START is the beginning position of the last match (see `match-beginning').
diff --git a/lisp/obsolete/erc-hecomplete.el b/lisp/obsolete/erc-hecomplete.el
index fce79f7..36b08d5 100644
--- a/lisp/obsolete/erc-hecomplete.el
+++ b/lisp/obsolete/erc-hecomplete.el
@@ -1,4 +1,4 @@
-;;; erc-hecomplete.el --- Provides Nick name completion for ERC
+;;; erc-hecomplete.el --- Provides Nick name completion for ERC  -*- 
lexical-binding: t; -*-
 
 ;; Copyright (C) 2001-2002, 2004, 2006-2021 Free Software Foundation,
 ;; Inc.
@@ -39,8 +39,8 @@
 ;;;###autoload (autoload 'erc-hecomplete-mode "erc-hecomplete" nil t)
 (define-erc-module hecomplete nil
   "Complete nick at point."
-  ((add-hook 'erc-complete-functions 'erc-hecomplete))
-  ((remove-hook 'erc-complete-functions 'erc-hecomplete)))
+  ((add-hook 'erc-complete-functions #'erc-hecomplete))
+  ((remove-hook 'erc-complete-functions #'erc-hecomplete)))
 
 (defun erc-hecomplete ()
   "Complete nick at point.
@@ -70,15 +70,13 @@ or you may use an arbitrary lisp expression."
                        erc-nick-completion-exclude-myself)
                 (repeat :tag "List" (string :tag "Nick"))
                 function
-                sexp)
-  :group 'erc-hecomplete)
+                sexp))
 
 (defcustom erc-nick-completion-ignore-case t
   "Non-nil means don't consider case significant in nick completion.
 Case will be automatically corrected when non-nil.
 For instance if you type \"dely TAB\" the word completes and changes to
 \"delYsid\"."
-  :group 'erc-hecomplete
   :type 'boolean)
 
 (defun erc-nick-completion-exclude-myself ()
@@ -95,7 +93,6 @@ typing \"f o TAB\" will directly give you foobar.  Use this 
with
 (defcustom erc-nick-completion-postfix ": "
   "When `erc-complete' is used in the first word after the prompt,
 add this string when a unique expansion was found."
-  :group 'erc-hecomplete
   :type 'string)
 
 (defun erc-command-list ()
diff --git a/lisp/obsolete/eudcb-ph.el b/lisp/obsolete/eudcb-ph.el
index c7212e3..187879c 100644
--- a/lisp/obsolete/eudcb-ph.el
+++ b/lisp/obsolete/eudcb-ph.el
@@ -1,4 +1,4 @@
-;;; eudcb-ph.el --- Emacs Unified Directory Client - CCSO PH/QI Backend
+;;; eudcb-ph.el --- Emacs Unified Directory Client - CCSO PH/QI Backend  -*- 
lexical-binding: t; -*-
 
 ;; Copyright (C) 1998-2021 Free Software Foundation, Inc.
 
@@ -69,7 +69,7 @@ defaulting to `eudc-default-return-attributes'."
                               query
                               " "))
                  (if return-fields
-                     (concat " return " (mapconcat 'symbol-name return-fields 
" ")))))
+                     (concat " return " (mapconcat #'symbol-name return-fields 
" ")))))
     (and (> (length request) 6)
         (eudc-ph-do-request request)
         (eudc-ph-parse-query-result return-fields))))
@@ -189,7 +189,7 @@ SERVER is either a string naming the server or a list (NAME 
PORT)."
   (with-current-buffer (process-buffer process)
     (eudc-ph-send-command process "quit")
     (eudc-ph-read-response process)
-    (run-at-time 2 nil 'delete-process process)))
+    (run-at-time 2 nil #'delete-process process)))
 
 (defun eudc-ph-send-command (process command)
   (goto-char (point-max))
diff --git a/lisp/obsolete/fast-lock.el b/lisp/obsolete/fast-lock.el
index 8848c89..baed8be 100644
--- a/lisp/obsolete/fast-lock.el
+++ b/lisp/obsolete/fast-lock.el
@@ -1,4 +1,4 @@
-;;; fast-lock.el --- automagic text properties caching for fast Font Lock mode
+;;; fast-lock.el --- automagic text properties caching for fast Font Lock mode 
 -*- lexical-binding: t; -*-
 
 ;; Copyright (C) 1994-1998, 2001-2021 Free Software Foundation, Inc.
 
@@ -190,18 +190,6 @@
 (defvar font-lock-face-list)
 
 (eval-when-compile
- ;; We use this to preserve or protect things when modifying text properties.
- (defmacro save-buffer-state (varlist &rest body)
-   "Bind variables according to VARLIST and eval BODY restoring buffer state."
-   `(let* (,@(append varlist
-                     '((modified (buffer-modified-p)) (buffer-undo-list t)
-                       (inhibit-read-only t) (inhibit-point-motion-hooks t)
-                       (inhibit-modification-hooks t)
-                       deactivate-mark buffer-file-name buffer-file-truename)))
-     ,@body
-     (when (and (not modified) (buffer-modified-p))
-       (set-buffer-modified-p nil))))
- (put 'save-buffer-state 'lisp-indent-function 1)
  ;;
  ;; We use this to verify that a face should be saved.
  (defmacro fast-lock-save-facep (face)
@@ -244,8 +232,7 @@ for buffers in Rmail mode, and size is irrelevant 
otherwise."
                                      (symbol :tag "name"))
                               (radio :tag "Size"
                                      (const :tag "none" nil)
-                                     (integer :tag "size")))))
-  :group 'fast-lock)
+                                     (integer :tag "size"))))))
 
 (defcustom fast-lock-cache-directories '("~/.emacs-flc")
 ; - `internal', keep each file's Font Lock cache file in the same file.
@@ -271,8 +258,7 @@ to avoid the possibility of using the cache of another 
user."
   :type '(repeat (radio (directory :tag "directory")
                        (cons :tag "Matching"
                              (regexp :tag "regexp")
-                             (directory :tag "directory"))))
-  :group 'fast-lock)
+                             (directory :tag "directory")))))
 (put 'fast-lock-cache-directories 'risky-local-variable t)
 
 (defcustom fast-lock-save-events '(kill-buffer kill-emacs)
@@ -282,23 +268,20 @@ If concurrent editing sessions use the same associated 
cache file for a file's
 buffer, then you should add `save-buffer' to this list."
   :type '(set (const :tag "buffer saving" save-buffer)
              (const :tag "buffer killing" kill-buffer)
-             (const :tag "emacs killing" kill-emacs))
-  :group 'fast-lock)
+             (const :tag "emacs killing" kill-emacs)))
 
 (defcustom fast-lock-save-others t
   "If non-nil, save Font Lock cache files irrespective of file owner.
 If nil, means only buffer files known to be owned by you can have associated
 Font Lock cache files saved.  Ownership may be unknown for networked files."
-  :type 'boolean
-  :group 'fast-lock)
+  :type 'boolean)
 
 (defcustom fast-lock-verbose font-lock-verbose
   "If non-nil, means show status messages for cache processing.
 If a number, only buffers greater than this size have processing messages."
   :type '(choice (const :tag "never" nil)
                 (other :tag "always" t)
-                (integer :tag "size"))
-  :group 'fast-lock)
+                (integer :tag "size")))
 
 (defvar fast-lock-save-faces
   (when (featurep 'xemacs)
@@ -455,8 +438,7 @@ See `fast-lock-mode'."
   ;; Flag so that a cache will be saved later even if the file is never saved.
   (setq fast-lock-cache-timestamp nil))
 
-(defalias 'fast-lock-after-unfontify-buffer
-  'ignore)
+(defalias 'fast-lock-after-unfontify-buffer #'ignore)
 
 ;; Miscellaneous Functions:
 
@@ -473,7 +455,7 @@ See `fast-lock-mode'."
 (defun fast-lock-save-caches-before-kill-emacs ()
   ;; Do `fast-lock-save-cache's if `kill-emacs' is on `fast-lock-save-events'.
   (when (memq 'kill-emacs fast-lock-save-events)
-    (mapcar 'fast-lock-save-cache (buffer-list))))
+    (mapcar #'fast-lock-save-cache (buffer-list))))
 
 (defun fast-lock-cache-directory (directory create)
   "Return usable directory based on DIRECTORY.
@@ -534,7 +516,7 @@ See `fast-lock-cache-directory'."
            (function (lambda (c) (or (cdr (assq c chars-alist)) (list c))))))
       (concat
        (file-name-as-directory (expand-file-name directory))
-       (mapconcat 'char-to-string (apply 'append (mapcar mapchars bufile)) "")
+       (mapconcat #'char-to-string (apply #'append (mapcar mapchars bufile)) 
"")
        ".flc"))))
 
 ;; Font Lock Cache Processing Functions:
@@ -581,7 +563,7 @@ See `fast-lock-cache-directory'."
 (defun fast-lock-cache-data (version timestamp
                             syntactic-keywords syntactic-properties
                             keywords face-properties
-                            &rest ignored)
+                            &rest _ignored)
   ;; Find value of syntactic keywords in case it is a symbol.
   (setq font-lock-syntactic-keywords (font-lock-eval-keywords
                                      font-lock-syntactic-keywords))
@@ -708,86 +690,26 @@ See `fast-lock-get-face-properties'."
   "Add `syntax-table' and `face' text properties to the current buffer.
 Any existing `syntax-table' and `face' text properties are removed first.
 See `fast-lock-get-face-properties'."
-  (save-buffer-state (plist regions)
-    (save-restriction
-      (widen)
-      (font-lock-unfontify-region (point-min) (point-max))
-      ;;
-      ;; Set the `syntax-table' property for each start/end region.
-      (while syntactic-properties
-       (setq plist (list 'syntax-table (car (car syntactic-properties)))
-             regions (cdr (car syntactic-properties))
-             syntactic-properties (cdr syntactic-properties))
-       (while regions
-         (add-text-properties (nth 0 regions) (nth 1 regions) plist)
-         (setq regions (nthcdr 2 regions))))
-      ;;
-      ;; Set the `face' property for each start/end region.
-      (while face-properties
-       (setq plist (list 'face (car (car face-properties)))
-             regions (cdr (car face-properties))
-             face-properties (cdr face-properties))
-       (while regions
-         (add-text-properties (nth 0 regions) (nth 1 regions) plist)
-         (setq regions (nthcdr 2 regions)))))))
+  (with-silent-modifications
+    (let ((inhibit-point-motion-hooks t))
+      (save-restriction
+        (widen)
+        (font-lock-unfontify-region (point-min) (point-max))
+        ;;
+        ;; Set the `syntax-table' property for each start/end region.
+        (pcase-dolist (`(,plist . ,regions) syntactic-properties)
+         (while regions
+           (add-text-properties (nth 0 regions) (nth 1 regions) plist)
+           (setq regions (nthcdr 2 regions))))
+       ;;
+       ;; Set the `face' property for each start/end region.
+        (pcase-dolist (`(,plist . ,regions) face-properties)
+         (while regions
+           (add-text-properties (nth 0 regions) (nth 1 regions) plist)
+           (setq regions (nthcdr 2 regions))))))))
 
 ;; Functions for XEmacs:
 
-(when (featurep 'xemacs)
-  ;;
-  ;; It would be better to use XEmacs' `map-extents' over extents with a
-  ;; `font-lock' property, but `face' properties are on different extents.
-  (defun fast-lock-get-face-properties ()
-    "Return a list of `face' text properties in the current buffer.
-Each element of the list is of the form (VALUE START1 END1 START2 END2 ...)
-where VALUE is a `face' property value and STARTx and ENDx are positions.
-Only those `face' VALUEs in `fast-lock-save-faces' are returned."
-    (save-restriction
-      (widen)
-      (let ((properties ()) cell)
-       (map-extents
-        (function (lambda (extent ignore)
-           (let ((value (extent-face extent)))
-             ;; We're only interested if it's one of `fast-lock-save-faces'.
-             (when (and value (fast-lock-save-facep value))
-               (let ((start (extent-start-position extent))
-                     (end (extent-end-position extent)))
-                 ;; Make or add to existing list of regions with the same
-                 ;; `face' property value.
-                 (if (setq cell (assoc value properties))
-                     (setcdr cell (cons start (cons end (cdr cell))))
-                   (push (list value start end) properties))))
-             ;; Return nil to keep `map-extents' going.
-             nil))))
-       properties)))
-  ;;
-  ;; XEmacs does not support the `syntax-table' text property.
-  (defalias 'fast-lock-get-syntactic-properties
-    'ignore)
-  ;;
-  ;; Make extents just like XEmacs' font-lock.el does.
-  (defun fast-lock-add-properties (syntactic-properties face-properties)
-    "Set `face' text properties in the current buffer.
-Any existing `face' text properties are removed first.
-See `fast-lock-get-face-properties'."
-    (save-restriction
-      (widen)
-      (font-lock-unfontify-region (point-min) (point-max))
-      ;; Set the `face' property, etc., for each start/end region.
-      (while face-properties
-       (let ((face (car (car face-properties)))
-             (regions (cdr (car face-properties))))
-         (while regions
-           (font-lock-set-face (nth 0 regions) (nth 1 regions) face)
-           (setq regions (nthcdr 2 regions)))
-         (setq face-properties (cdr face-properties))))
-      ;; XEmacs does not support the `syntax-table' text property.
-      ))
-  ;;
-  ;; XEmacs 19.12 font-lock.el's `font-lock-fontify-buffer' runs a hook.
-  (add-hook 'font-lock-after-fontify-buffer-hook
-           'fast-lock-after-fontify-buffer))
-
 (unless (boundp 'font-lock-syntactic-keywords)
   (defvar font-lock-syntactic-keywords nil))
 
@@ -795,14 +717,14 @@ See `fast-lock-get-face-properties'."
   (defvar font-lock-inhibit-thing-lock nil))
 
 (unless (fboundp 'font-lock-compile-keywords)
-  (defalias 'font-lock-compile-keywords 'identity))
+  (defalias 'font-lock-compile-keywords #'identity))
 
 (unless (fboundp 'font-lock-eval-keywords)
   (defun font-lock-eval-keywords (keywords)
     (if (symbolp keywords)
        (font-lock-eval-keywords (if (fboundp keywords)
                                     (funcall keywords)
-                                  (eval keywords)))
+                                  (eval keywords t)))
       keywords)))
 
 (unless (fboundp 'font-lock-value-in-major-mode)
@@ -817,10 +739,10 @@ See `fast-lock-get-face-properties'."
 
 ;; Install ourselves:
 
-(add-hook 'after-save-hook 'fast-lock-save-cache-after-save-file)
-(add-hook 'kill-buffer-hook 'fast-lock-save-cache-before-kill-buffer)
+(add-hook 'after-save-hook #'fast-lock-save-cache-after-save-file)
+(add-hook 'kill-buffer-hook #'fast-lock-save-cache-before-kill-buffer)
 (unless noninteractive
-  (add-hook 'kill-emacs-hook 'fast-lock-save-caches-before-kill-emacs))
+  (add-hook 'kill-emacs-hook #'fast-lock-save-caches-before-kill-emacs))
 
 ;;;###autoload
 (when (fboundp 'add-minor-mode)
diff --git a/lisp/obsolete/gs.el b/lisp/obsolete/gs.el
index 6ab3fc5..5a82c6b0 100644
--- a/lisp/obsolete/gs.el
+++ b/lisp/obsolete/gs.el
@@ -1,4 +1,4 @@
-;;; gs.el --- interface to Ghostscript
+;;; gs.el --- interface to Ghostscript  -*- lexical-binding: t; -*-
 
 ;; Copyright (C) 1998, 2001-2021 Free Software Foundation, Inc.
 
@@ -205,7 +205,7 @@ the form \"WINDOW-ID PIXMAP-ID\".  Value is non-nil if 
successful."
        (gs-set-ghostview-window-prop frame spec img-width img-height)
        (gs-set-ghostview-colors-window-prop frame pixel-colors)
        (setenv "GHOSTVIEW" window-and-pixmap-id)
-       (setq gs (apply 'start-process "gs" "*GS*" gs-program
+       (setq gs (apply #'start-process "gs" "*GS*" gs-program
                        (gs-options gs-device file)))
        (set-process-query-on-exit-flag gs nil)
        gs)
diff --git a/lisp/obsolete/gulp.el b/lisp/obsolete/gulp.el
index 0fbaa1c..6ec2f4f 100644
--- a/lisp/obsolete/gulp.el
+++ b/lisp/obsolete/gulp.el
@@ -1,4 +1,4 @@
-;;; gulp.el --- ask for updates for Lisp packages
+;;; gulp.el --- ask for updates for Lisp packages  -*- lexical-binding: t; -*-
 
 ;; Copyright (C) 1996, 2001-2021 Free Software Foundation, Inc.
 
@@ -37,18 +37,15 @@
 (defcustom gulp-discard "^;+ *Maintainer: *\\(FSF\\|emacs-devel@gnu\\.org\\) 
*$"
   "The regexp matching the packages not requiring the request for updates."
   :version "24.4"                      ; added emacs-devel
-  :type 'regexp
-  :group 'gulp)
+  :type 'regexp)
 
 (defcustom gulp-tmp-buffer "*gulp*"
   "The name of the temporary buffer."
-  :type 'string
-  :group 'gulp)
+  :type 'string)
 
 (defcustom gulp-max-len 2000
   "Distance into a Lisp source file to scan for keywords."
-  :type 'integer
-  :group 'gulp)
+  :type 'integer)
 
 (defcustom gulp-request-header
   (concat
@@ -57,8 +54,7 @@ I'm going to start pretesting a new version of GNU Emacs 
soon, so I'd
 like to ask if you have any updates for the Emacs packages you work on.
 You're listed as the maintainer of the following package(s):\n\n")
   "The starting text of a gulp message."
-  :type 'string
-  :group 'gulp)
+  :type 'string)
 
 (defcustom gulp-request-end
   (concat
@@ -75,8 +71,7 @@ of information to include.
 
 Thanks.")
   "The closing text in a gulp message."
-  :type 'string
-  :group 'gulp)
+  :type 'string)
 
 (declare-function mail-subject "sendmail" ())
 (declare-function mail-send "sendmail" ())
diff --git a/lisp/obsolete/html2text.el b/lisp/obsolete/html2text.el
index f01561b..be0553c 100644
--- a/lisp/obsolete/html2text.el
+++ b/lisp/obsolete/html2text.el
@@ -1,4 +1,4 @@
-;;; html2text.el --- a simple html to plain text converter -*- coding: utf-8 
-*-
+;;; html2text.el --- a simple html to plain text converter -*- 
lexical-binding: t; -*-
 
 ;; Copyright (C) 2002-2021 Free Software Foundation, Inc.
 
diff --git a/lisp/obsolete/info-edit.el b/lisp/obsolete/info-edit.el
index c8a187c..c53616d 100644
--- a/lisp/obsolete/info-edit.el
+++ b/lisp/obsolete/info-edit.el
@@ -36,7 +36,7 @@
 (define-obsolete-variable-alias 'Info-edit-map 'Info-edit-mode-map "24.1")
 (defvar Info-edit-mode-map (let ((map (make-sparse-keymap)))
                              (set-keymap-parent map text-mode-map)
-                             (define-key map "\C-c\C-c" 'Info-cease-edit)
+                             (define-key map "\C-c\C-c" #'Info-cease-edit)
                              map)
   "Local keymap used within `e' command of Info.")
 
diff --git a/lisp/cedet/inversion.el b/lisp/obsolete/inversion.el
similarity index 94%
rename from lisp/cedet/inversion.el
rename to lisp/obsolete/inversion.el
index 2ef7e0d..ac7749a 100644
--- a/lisp/cedet/inversion.el
+++ b/lisp/obsolete/inversion.el
@@ -1,10 +1,11 @@
-;;; inversion.el --- When you need something in version XX.XX
+;;; inversion.el --- When you need something in version XX.XX  -*- 
lexical-binding: t; -*-
 
-;;; Copyright (C) 2002-2003, 2005-2021 Free Software Foundation, Inc.
+;; Copyright (C) 2002-2021  Free Software Foundation, Inc.
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
 ;; Version: 1.3
 ;; Keywords: OO, lisp
+;; Obsolete-since: 28.1
 
 ;; This file is part of GNU Emacs.
 
@@ -222,7 +223,7 @@ not an indication of new features or bug fixes."
        )))
 
 (defun inversion-check-version (version incompatible-version
-                                minimum &rest reserved)
+                                minimum &rest _reserved)
   "Check that a given version meets the minimum requirement.
 VERSION, INCOMPATIBLE-VERSION and MINIMUM are of similar format to
 return entries of `inversion-decode-version', or a classic version
@@ -329,7 +330,7 @@ Return nil if everything is ok.  Return an error string 
otherwise."
      (t "Inversion version check failed."))))
 
 (defun inversion-require (package version &optional file directory
-                                 &rest reserved)
+                                 &rest _reserved)
   "Declare that you need PACKAGE with at least VERSION.
 PACKAGE might be found in FILE.  (See `require'.)
 Throws an error if VERSION is incompatible with what is installed.
@@ -453,7 +454,7 @@ If it is a URL, wget will be used for download.
 Optional argument VERSION will restrict the list of available versions
 to the file matching VERSION exactly, or nil."
 ;;DIRECTORY should also allow a URL:
-;; \"http://ftp1.sourceforge.net/PACKAGE\";
+;; \"https://ftp1.sourceforge.net/PACKAGE\";
 ;; but then I can get file listings easily.
   (if (symbolp package) (setq package (symbol-name package)))
   (directory-files directory t
@@ -524,31 +525,6 @@ The package should have VERSION available for download."
 
          (copy-file (cdr (car files)) dest))))))
 
-;;; How we upgrade packages in Emacs has yet to be ironed out.
-
-;; (defun inversion-upgrade-package (package &optional directory)
-;;   "Try to upgrade PACKAGE in DIRECTORY is available."
-;;   (interactive "sPackage to upgrade: ")
-;;   (if (stringp package) (setq package (intern package)))
-;;   (if (not directory)
-;;       ;; Hope that the package maintainer specified.
-;;       (setq directory (symbol-value (or (intern-soft
-;;                                      (concat (symbol-name package)
-;;                                              "-url"))
-;;                                     (intern-soft
-;;                                      (concat (symbol-name package)
-;;                                              "-directory"))))))
-;;   (let ((files (inversion-locate-package-files-and-split
-;;             package directory))
-;;     (cver (inversion-package-version package))
-;;     (newer nil))
-;;     (mapc (lambda (f)
-;;         (if (inversion-< cver (inversion-decode-version (car f)))
-;;             (setq newer (cons f newer))))
-;;         files)
-;;     newer
-;;     ))
-
 (provide 'inversion)
 
 ;;; inversion.el ends here
diff --git a/lisp/obsolete/iswitchb.el b/lisp/obsolete/iswitchb.el
index 58cada1..7ffee76 100644
--- a/lisp/obsolete/iswitchb.el
+++ b/lisp/obsolete/iswitchb.el
@@ -1,4 +1,4 @@
-;;; iswitchb.el --- switch between buffers using substrings
+;;; iswitchb.el --- switch between buffers using substrings  -*- 
lexical-binding: t; -*-
 
 ;; Copyright (C) 1996-1997, 2000-2021 Free Software Foundation, Inc.
 
@@ -258,8 +258,7 @@
   "Non-nil if searching of buffer names should ignore case.
 If this is non-nil but the user input has any upper case letters, matching
 is temporarily case sensitive."
-  :type 'boolean
-  :group 'iswitchb)
+  :type 'boolean)
 
 (defcustom iswitchb-buffer-ignore
   '("^ ")
@@ -267,8 +266,7 @@ is temporarily case sensitive."
 For example, traditional behavior is not to list buffers whose names begin
 with a space, for which the regexp is `^ '.  See the source file for
 example functions that filter buffer names."
-  :type '(repeat (choice regexp function))
-  :group 'iswitchb)
+  :type '(repeat (choice regexp function)))
 (put 'iswitchb-buffer-ignore 'risky-local-variable t)
 
 (defcustom iswitchb-max-to-show nil
@@ -277,8 +275,7 @@ If this value is N, and N is greater than the number of 
matching
 buffers, the first N/2 and the last N/2 matching buffers are
 shown.  This can greatly speed up iswitchb if you have a
 multitude of buffers open."
-  :type '(choice (const :tag "Show all" nil) integer)
-  :group 'iswitchb)
+  :type '(choice (const :tag "Show all" nil) integer))
 
 (defcustom iswitchb-use-virtual-buffers nil
   "If non-nil, refer to past buffers when none match.
@@ -289,8 +286,7 @@ enabled if this variable is configured to a non-nil value."
   :set (function
        (lambda (sym value)
          (if value (recentf-mode 1))
-         (set sym value)))
-  :group 'iswitchb)
+         (set sym value))))
 
 (defvar iswitchb-virtual-buffers nil)
 
@@ -299,8 +295,7 @@ enabled if this variable is configured to a non-nil value."
 The most useful values are `iswitchb-completion-help', which pops up a
 window with completion alternatives, or `iswitchb-next-match' or
 `iswitchb-prev-match', which cycle the buffer list."
-  :type 'hook
-  :group 'iswitchb)
+  :type 'hook)
 
 ;; Examples for setting the value of iswitchb-buffer-ignore
 ;;(defun iswitchb-ignore-c-mode (name)
@@ -318,7 +313,7 @@ Possible values:
 `otherwindow'  Show new buffer in another window (same frame)
 `display'      Display buffer in another window without switching to it
 `otherframe'   Show new buffer in another frame
-`maybe-frame'  If a buffer is visible in another frame, prompt to ask if you
+`maybe-frame'  If a buffer is visible in another frame, prompt to ask if
                you want to see the buffer in the same window of the current
                frame or in the other frame.
 `always-frame'  If a buffer is visible in another frame, raise that
@@ -328,46 +323,38 @@ Possible values:
                   (const display)
                   (const otherframe)
                   (const maybe-frame)
-                  (const always-frame))
-    :group 'iswitchb)
+                  (const always-frame)))
 
 (defcustom iswitchb-regexp nil
   "Non-nil means that `iswitchb' will do regexp matching.
 Value can be toggled within `iswitchb' using `iswitchb-toggle-regexp'."
-  :type 'boolean
-  :group 'iswitchb)
+  :type 'boolean)
 
 (defcustom iswitchb-newbuffer t
   "Non-nil means create new buffer if no buffer matches substring.
 See also `iswitchb-prompt-newbuffer'."
-  :type 'boolean
-  :group 'iswitchb)
+  :type 'boolean)
 
 (defcustom iswitchb-prompt-newbuffer t
   "Non-nil means prompt user to confirm before creating new buffer.
 See also `iswitchb-newbuffer'."
-  :type 'boolean
-  :group 'iswitchb)
+  :type 'boolean)
 
 (defcustom iswitchb-use-faces t
   "Non-nil means use font-lock faces for showing first match."
-  :type 'boolean
-  :group 'iswitchb)
+  :type 'boolean)
 
 (defcustom iswitchb-use-frame-buffer-list nil
   "Non-nil means use the currently selected frame's buffer list."
-  :type 'boolean
-  :group 'iswitchb)
+  :type 'boolean)
 
 (defcustom iswitchb-make-buflist-hook  nil
   "Hook to run when list of matching buffers is created."
-  :type 'hook
-  :group 'iswitchb)
+  :type 'hook)
 
 (defcustom iswitchb-delim ","
   "Delimiter to put between buffer names when displaying results."
-  :type 'string
-  :group 'iswitchb)
+  :type 'string)
 
 (defcustom iswitchb-all-frames 'visible
   "Argument to pass to `walk-windows' when iswitchb is finding buffers.
@@ -375,8 +362,7 @@ See documentation of `walk-windows' for useful values."
   :type '(choice (const :tag "Selected frame only" nil)
                 (const :tag "All existing frames" t)
                 (const :tag "All visible frames" visible)
-                (const :tag "All frames on this terminal" 0))
-  :group 'iswitchb)
+                (const :tag "All frames on this terminal" 0)))
 
 (defcustom iswitchb-minibuffer-setup-hook nil
   "Iswitchb-specific customization of minibuffer setup.
@@ -387,37 +373,32 @@ For instance:
          \\='\(lambda () (set (make-local-variable \\='max-mini-window-height) 
3)))
 will constrain the minibuffer to a maximum height of 3 lines when
 iswitchb is running."
-  :type 'hook
-  :group 'iswitchb)
+  :type 'hook)
 
 (defface iswitchb-single-match
   '((t
      (:inherit font-lock-comment-face)))
   "Iswitchb face for single matching buffer name."
-  :version "22.1"
-  :group 'iswitchb)
+  :version "22.1")
 
 (defface iswitchb-current-match
   '((t
      (:inherit font-lock-function-name-face)))
   "Iswitchb face for current matching buffer name."
-  :version "22.1"
-  :group 'iswitchb)
+  :version "22.1")
 
 (defface iswitchb-virtual-matches
   '((t
      (:inherit font-lock-builtin-face)))
   "Iswitchb face for matching virtual buffer names.
 See also `iswitchb-use-virtual-buffers'."
-  :version "22.1"
-  :group 'iswitchb)
+  :version "22.1")
 
 (defface iswitchb-invalid-regexp
   '((t
      (:inherit font-lock-warning-face)))
   "Iswitchb face for indicating invalid regexp. "
-  :version "22.1"
-  :group 'iswitchb)
+  :version "22.1")
 
 ;; Do we need the variable iswitchb-use-mycompletion?
 
@@ -465,18 +446,18 @@ interfere with other minibuffer usage.")
 (defvar iswitchb-mode-map
   (let ((map (make-sparse-keymap)))
     (set-keymap-parent map minibuffer-local-map)
-    (define-key map "?" 'iswitchb-completion-help)
-    (define-key map "\C-s" 'iswitchb-next-match)
-    (define-key map "\C-r" 'iswitchb-prev-match)
-    (define-key map [?\C-.] 'iswitchb-next-match)
-    (define-key map [?\C-,] 'iswitchb-prev-match)
-    (define-key map "\t" 'iswitchb-complete)
-    (define-key map "\C-j" 'iswitchb-select-buffer-text)
-    (define-key map "\C-t" 'iswitchb-toggle-regexp)
-    (define-key map "\C-x\C-f" 'iswitchb-find-file)
-    (define-key map "\C-c" 'iswitchb-toggle-case)
-    (define-key map "\C-k" 'iswitchb-kill-buffer)
-    (define-key map "\C-m" 'iswitchb-exit-minibuffer)
+    (define-key map "?" #'iswitchb-completion-help)
+    (define-key map "\C-s" #'iswitchb-next-match)
+    (define-key map "\C-r" #'iswitchb-prev-match)
+    (define-key map [?\C-.] #'iswitchb-next-match)
+    (define-key map [?\C-,] #'iswitchb-prev-match)
+    (define-key map "\t" #'iswitchb-complete)
+    (define-key map "\C-j" #'iswitchb-select-buffer-text)
+    (define-key map "\C-t" #'iswitchb-toggle-regexp)
+    (define-key map "\C-x\C-f" #'iswitchb-find-file)
+    (define-key map "\C-c" #'iswitchb-toggle-case)
+    (define-key map "\C-k" #'iswitchb-kill-buffer)
+    (define-key map "\C-m" #'iswitchb-exit-minibuffer)
     map)
   "Minibuffer keymap for `iswitchb-buffer'.")
 
@@ -596,17 +577,17 @@ the selection process begins.  Used by isearchb.el."
   (let ((map (copy-keymap minibuffer-local-map))
        buf-sel iswitchb-final-text
        icomplete-mode)  ; prevent icomplete starting up
-    (define-key map "?" 'iswitchb-completion-help)
-    (define-key map "\C-s" 'iswitchb-next-match)
-    (define-key map "\C-r" 'iswitchb-prev-match)
-    (define-key map "\t" 'iswitchb-complete)
-    (define-key map "\C-j" 'iswitchb-select-buffer-text)
-    (define-key map "\C-t" 'iswitchb-toggle-regexp)
-    (define-key map "\C-x\C-f" 'iswitchb-find-file)
-    (define-key map "\C-n" 'iswitchb-toggle-ignore)
-    (define-key map "\C-c" 'iswitchb-toggle-case)
-    (define-key map "\C-k" 'iswitchb-kill-buffer)
-    (define-key map "\C-m" 'iswitchb-exit-minibuffer)
+    (define-key map "?" #'iswitchb-completion-help)
+    (define-key map "\C-s" #'iswitchb-next-match)
+    (define-key map "\C-r" #'iswitchb-prev-match)
+    (define-key map "\t" #'iswitchb-complete)
+    (define-key map "\C-j" #'iswitchb-select-buffer-text)
+    (define-key map "\C-t" #'iswitchb-toggle-regexp)
+    (define-key map "\C-x\C-f" #'iswitchb-find-file)
+    (define-key map "\C-n" #'iswitchb-toggle-ignore)
+    (define-key map "\C-c" #'iswitchb-toggle-case)
+    (define-key map "\C-k" #'iswitchb-kill-buffer)
+    (define-key map "\C-m" #'iswitchb-exit-minibuffer)
     (setq iswitchb-mode-map map)
     (run-hooks 'iswitchb-define-mode-map-hook)
 
@@ -946,9 +927,9 @@ If `iswitchb-change-word-sub' cannot be found in WORD, 
return nil."
           (if iswitchb-regexp
               subs
             (regexp-quote subs)))
-    (setq res (mapcar 'iswitchb-word-matching-substring lis))
+    (setq res (mapcar #'iswitchb-word-matching-substring lis))
     (setq res (delq nil res)) ;; remove any nil elements (shouldn't happen)
-    (setq alist (mapcar 'iswitchb-makealist res)) ;; could use an  OBARRAY
+    (setq alist (mapcar #'iswitchb-makealist res)) ;; could use an  OBARRAY
 
     ;; try-completion returns t if there is an exact match.
     (let ((completion-ignore-case (iswitchb-case)))
@@ -1148,43 +1129,6 @@ For details of keybindings, do `\\[describe-function] 
iswitchb'."
   (setq iswitchb-method 'otherframe)
   (iswitchb))
 
-;;; XEmacs hack for showing default buffer
-
-;; The first time we enter the minibuffer, Emacs puts up the default
-;; buffer to switch to, but XEmacs doesn't -- presumably there is a
-;; subtle difference in the two versions of post-command-hook.  The
-;; default is shown for both whenever we delete all of our text
-;; though, indicating its just a problem the first time we enter the
-;; function.  To solve this, we use another entry hook for emacs to
-;; show the default the first time we enter the minibuffer.
-
-(defun iswitchb-init-XEmacs-trick ()
-  "Display default buffer when first entering minibuffer.
-This is a hack for XEmacs, and should really be handled by `iswitchb-exhibit'."
-  (if (iswitchb-entryfn-p)
-      (progn
-       (iswitchb-exhibit)
-       (goto-char (point-min)))))
-
-;; add this hook for XEmacs only.
-(if (featurep 'xemacs)
-    (add-hook 'iswitchb-minibuffer-setup-hook
-             'iswitchb-init-XEmacs-trick))
-
-;;; XEmacs / backspace key
-;; For some reason, if the backspace key is pressed in XEmacs, the
-;; line gets confused, so I've added a simple key definition to make
-;; backspace act like the normal delete key.
-
-(defun iswitchb-xemacs-backspacekey ()
-  "Bind backspace to `backward-delete-char'."
-  (define-key iswitchb-mode-map '[backspace] 'backward-delete-char)
-  (define-key iswitchb-mode-map '[(meta backspace)] 'backward-kill-word))
-
-(if (featurep 'xemacs)
-    (add-hook 'iswitchb-define-mode-map-hook
-             'iswitchb-xemacs-backspacekey))
-
 ;;; ICOMPLETE TYPE CODE
 
 (defun iswitchb-exhibit ()
@@ -1214,18 +1158,6 @@ Copied from `icomplete-exhibit' with two changes:
          (insert (iswitchb-completions
                   contents))))))
 
-(defvar most-len)
-(defvar most-is-exact)
-
-(defun iswitchb-output-completion (com)
-  (if (= (length com) most-len)
-      ;; Most is one exact match,
-      ;; note that and leave out
-      ;; for later indication:
-      (ignore
-       (setq most-is-exact t))
-    (substring com most-len)))
-
 (defun iswitchb-completions (name)
   "Return the string that is displayed after the user's text.
 Modified from `icomplete-completions'."
@@ -1273,7 +1205,7 @@ Modified from `icomplete-completions'."
                          iswitchb-virtual-buffers)))
          (setq head (cdr head)))
        (setq iswitchb-virtual-buffers (nreverse iswitchb-virtual-buffers)
-             comps (mapcar 'car iswitchb-virtual-buffers))
+             comps (mapcar #'car iswitchb-virtual-buffers))
        (let ((comp comps))
          (while comp
            (put-text-property 0 (length (car comp))
@@ -1316,15 +1248,11 @@ Modified from `icomplete-completions'."
                        (nreverse res))
                      (list "...")
                      (nthcdr (- (length comps)
-                                (/ iswitchb-max-to-show 2)) comps))))
+                                (/ iswitchb-max-to-show 2))
+                             comps))))
           (let* (
-                 ;;(most (try-completion name candidates predicate))
-                 (most nil)
-                 (most-len (length most))
-                 most-is-exact
                  (alternatives
-                  (mapconcat (if most 'iswitchb-output-completion
-                               'identity) comps iswitchb-delim)))
+                  (mapconcat #'identity comps iswitchb-delim)))
 
             (concat
 
@@ -1338,17 +1266,9 @@ Modified from `icomplete-completions'."
                          close-bracket-determined))
              ;; end of partial matches...
 
-             ;; think this bit can be ignored.
-             (and (> most-len (length name))
-                  (concat open-bracket-determined
-                          (substring most (length name))
-                          close-bracket-determined))
-
              ;; list all alternatives
              open-bracket-prospects
-             (if most-is-exact
-                 (concat iswitchb-delim alternatives)
-               alternatives)
+             alternatives
              close-bracket-prospects))))))
 
 (defun iswitchb-minibuffer-setup ()
@@ -1356,8 +1276,8 @@ Modified from `icomplete-completions'."
 Copied from `icomplete-minibuffer-setup-hook'."
   (when (iswitchb-entryfn-p)
     (set (make-local-variable 'iswitchb-use-mycompletion) t)
-    (add-hook 'pre-command-hook 'iswitchb-pre-command nil t)
-    (add-hook 'post-command-hook 'iswitchb-post-command nil t)
+    (add-hook 'pre-command-hook #'iswitchb-pre-command nil t)
+    (add-hook 'post-command-hook #'iswitchb-post-command nil t)
     (run-hooks 'iswitchb-minibuffer-setup-hook)))
 
 (defun iswitchb-pre-command ()
@@ -1416,10 +1336,10 @@ See the variable `iswitchb-case' for details."
 
 Iswitchb mode is a global minor mode that enables switching
 between buffers using substrings.  See `iswitchb' for details."
-  nil nil iswitchb-global-map :global t :group 'iswitchb
+  nil nil iswitchb-global-map :global t
   (if iswitchb-mode
-      (add-hook 'minibuffer-setup-hook 'iswitchb-minibuffer-setup)
-    (remove-hook 'minibuffer-setup-hook 'iswitchb-minibuffer-setup)))
+      (add-hook 'minibuffer-setup-hook #'iswitchb-minibuffer-setup)
+    (remove-hook 'minibuffer-setup-hook #'iswitchb-minibuffer-setup)))
 
 (provide 'iswitchb)
 
diff --git a/lisp/obsolete/landmark.el b/lisp/obsolete/landmark.el
index ae15109..cc4fd19 100644
--- a/lisp/obsolete/landmark.el
+++ b/lisp/obsolete/landmark.el
@@ -163,51 +163,50 @@
 
 (defcustom landmark-mode-hook nil
   "If non-nil, its value is called on entry to Landmark mode."
-  :type 'hook
-  :group 'landmark)
+  :type 'hook)
 
 (defvar landmark-mode-map
   (let ((map (make-sparse-keymap)))
     ;; Key bindings for cursor motion.
-    (define-key map "y" 'landmark-move-nw)             ; y
-    (define-key map "u" 'landmark-move-ne)             ; u
-    (define-key map "b" 'landmark-move-sw)             ; b
-    (define-key map "n" 'landmark-move-se)             ; n
-    (define-key map "h" 'backward-char)                ; h
-    (define-key map "l" 'forward-char)         ; l
-    (define-key map "j" 'landmark-move-down)           ; j
-    (define-key map "k" 'landmark-move-up)             ; k
-
-    (define-key map [kp-7] 'landmark-move-nw)
-    (define-key map [kp-9] 'landmark-move-ne)
-    (define-key map [kp-1] 'landmark-move-sw)
-    (define-key map [kp-3] 'landmark-move-se)
-    (define-key map [kp-4] 'backward-char)
-    (define-key map [kp-6] 'forward-char)
-    (define-key map [kp-2] 'landmark-move-down)
-    (define-key map [kp-8] 'landmark-move-up)
-
-    (define-key map "\C-n" 'landmark-move-down)                ; C-n
-    (define-key map "\C-p" 'landmark-move-up)          ; C-p
+    (define-key map "y" #'landmark-move-nw)            ; y
+    (define-key map "u" #'landmark-move-ne)            ; u
+    (define-key map "b" #'landmark-move-sw)            ; b
+    (define-key map "n" #'landmark-move-se)            ; n
+    (define-key map "h" #'backward-char)               ; h
+    (define-key map "l" #'forward-char)                ; l
+    (define-key map "j" #'landmark-move-down)          ; j
+    (define-key map "k" #'landmark-move-up)            ; k
+
+    (define-key map [kp-7] #'landmark-move-nw)
+    (define-key map [kp-9] #'landmark-move-ne)
+    (define-key map [kp-1] #'landmark-move-sw)
+    (define-key map [kp-3] #'landmark-move-se)
+    (define-key map [kp-4] #'backward-char)
+    (define-key map [kp-6] #'forward-char)
+    (define-key map [kp-2] #'landmark-move-down)
+    (define-key map [kp-8] #'landmark-move-up)
+
+    (define-key map "\C-n" #'landmark-move-down)               ; C-n
+    (define-key map "\C-p" #'landmark-move-up)         ; C-p
 
     ;; Key bindings for entering Human moves.
-    (define-key map "X" 'landmark-human-plays)         ; X
-    (define-key map "x" 'landmark-human-plays)         ; x
-
-    (define-key map " " 'landmark-start-robot)         ; SPC
-    (define-key map [down-mouse-1] 'landmark-start-robot)
-    (define-key map [drag-mouse-1] 'landmark-click)
-    (define-key map [mouse-1] 'landmark-click)
-    (define-key map [down-mouse-2] 'landmark-click)
-    (define-key map [mouse-2] 'landmark-mouse-play)
-    (define-key map [drag-mouse-2] 'landmark-mouse-play)
-
-    (define-key map [remap previous-line] 'landmark-move-up)
-    (define-key map [remap next-line] 'landmark-move-down)
-    (define-key map [remap beginning-of-line] 'landmark-beginning-of-line)
-    (define-key map [remap end-of-line] 'landmark-end-of-line)
-    (define-key map [remap undo] 'landmark-human-takes-back)
-    (define-key map [remap advertised-undo] 'landmark-human-takes-back)
+    (define-key map "X" #'landmark-human-plays)                ; X
+    (define-key map "x" #'landmark-human-plays)                ; x
+
+    (define-key map " " #'landmark-start-robot)                ; SPC
+    (define-key map [down-mouse-1] #'landmark-start-robot)
+    (define-key map [drag-mouse-1] #'landmark-click)
+    (define-key map [mouse-1] #'landmark-click)
+    (define-key map [down-mouse-2] #'landmark-click)
+    (define-key map [mouse-2] #'landmark-mouse-play)
+    (define-key map [drag-mouse-2] #'landmark-mouse-play)
+
+    (define-key map [remap previous-line] #'landmark-move-up)
+    (define-key map [remap next-line] #'landmark-move-down)
+    (define-key map [remap beginning-of-line] #'landmark-beginning-of-line)
+    (define-key map [remap end-of-line] #'landmark-end-of-line)
+    (define-key map [remap undo] #'landmark-human-takes-back)
+    (define-key map [remap advertised-undo] #'landmark-human-takes-back)
     map)
   "Local keymap to use in Landmark mode.")
 
@@ -219,14 +218,12 @@
 (defface landmark-font-lock-face-O '((((class color)) :foreground "red")
                               (t :weight bold))
   "Face to use for Emacs's O."
-  :version "22.1"
-  :group 'landmark)
+  :version "22.1")
 
 (defface landmark-font-lock-face-X '((((class color)) :foreground "green")
                               (t :weight bold))
   "Face to use for your X."
-  :version "22.1"
-  :group 'landmark)
+  :version "22.1")
 
 (defvar landmark-font-lock-keywords
   '(("O" . 'landmark-font-lock-face-O)
@@ -1132,12 +1129,10 @@ this program to add a random element to the way moves 
were made.")
   "If non-nil, print \"One moment please\" when a new board is generated.
 The drawback of this is you don't see how many moves the last run took
 because it is overwritten by \"One moment please\"."
-  :type 'boolean
-  :group 'landmark)
+  :type 'boolean)
 (defcustom landmark-output-moves t
   "If non-nil, output number of moves so far on a move-by-move basis."
-  :type 'boolean
-  :group 'landmark)
+  :type 'boolean)
 
 
 (defun landmark-weights-debug ()
@@ -1153,7 +1148,7 @@ because it is overwritten by \"One moment please\"."
 
 (defun landmark-print-distance ()
   (insert (format "tree: %S \n" (landmark-calc-distance-of-robot-from 
'landmark-tree)))
-  (mapc 'landmark-print-distance-int landmark-directions))
+  (mapc #'landmark-print-distance-int landmark-directions))
 
 
 ;;(setq direction 'landmark-n)
@@ -1166,10 +1161,10 @@ because it is overwritten by \"One moment please\"."
 
 (defun landmark-nslify-wts ()
   (interactive)
-  (let ((l (apply 'append (mapcar 'landmark-nslify-wts-int 
landmark-directions))))
+  (let ((l (apply #'append (mapcar #'landmark-nslify-wts-int 
landmark-directions))))
     (insert (format "set data_value WTS \n %s \n" l))
     (insert (format "/* max: %S min: %S */"
-                 (eval (cons 'max l)) (eval (cons 'min l))))))
+                 (apply #'max l) (apply #'min l)))))
 
 (defun landmark-print-wts-int (direction)
   (mapc (lambda (target-direction)
@@ -1184,7 +1179,7 @@ because it is overwritten by \"One moment please\"."
   (interactive)
   (with-current-buffer "*landmark-wts*"
     (insert "==============================\n")
-    (mapc 'landmark-print-wts-int landmark-directions)))
+    (mapc #'landmark-print-wts-int landmark-directions)))
 
 (defun landmark-print-moves (moves)
   (interactive)
@@ -1204,7 +1199,7 @@ because it is overwritten by \"One moment please\"."
   (interactive)
   (with-current-buffer "*landmark-y,s,noise*"
     (insert "==============================\n")
-    (mapc 'landmark-print-y-s-noise-int landmark-directions)))
+    (mapc #'landmark-print-y-s-noise-int landmark-directions)))
 
 (defun landmark-print-smell-int (direction)
   (insert (format "%S: smell: %S \n"
@@ -1216,7 +1211,7 @@ because it is overwritten by \"One moment please\"."
   (with-current-buffer "*landmark-smell*"
     (insert "==============================\n")
     (insert (format "tree: %S \n" (get 'z 't)))
-    (mapc 'landmark-print-smell-int landmark-directions)))
+    (mapc #'landmark-print-smell-int landmark-directions)))
 
 (defun landmark-print-w0-int (direction)
   (insert (format "%S: w0: %S \n"
@@ -1227,7 +1222,7 @@ because it is overwritten by \"One moment please\"."
   (interactive)
   (with-current-buffer "*landmark-w0*"
     (insert "==============================\n")
-    (mapc 'landmark-print-w0-int landmark-directions)))
+    (mapc #'landmark-print-w0-int landmark-directions)))
 
 (defun landmark-blackbox ()
   (with-current-buffer "*landmark-blackbox*"
@@ -1252,36 +1247,31 @@ because it is overwritten by \"One moment please\"."
 
 (defun landmark-print-wts-blackbox ()
   (interactive)
-  (mapc 'landmark-print-wts-int landmark-directions))
+  (mapc #'landmark-print-wts-int landmark-directions))
 
 ;;;_  - learning parameters
 (defcustom landmark-bound 0.005
   "The maximum that w0j may be."
-  :type 'number
-  :group 'landmark)
+  :type 'number)
 (defcustom landmark-c 1.0
   "A factor applied to modulate the increase in wij.
 Used in the function landmark-update-normal-weights."
-  :type 'number
-  :group 'landmark)
+  :type 'number)
 (defcustom landmark-c-naught 0.5
   "A factor applied to modulate the increase in w0j.
 Used in the function landmark-update-naught-weights."
-  :type 'number
-  :group 'landmark)
+  :type 'number)
 (defvar landmark-initial-w0 0.0)
 (defvar landmark-initial-wij 0.0)
 (defcustom landmark-no-payoff 0
   "The amount of simulation cycles that have occurred with no movement.
 Used to move the robot when he is stuck in a rut for some reason."
-  :type 'integer
-  :group 'landmark)
+  :type 'integer)
 (defcustom landmark-max-stall-time 2
   "The maximum number of cycles that the robot can remain stuck in a place.
 After this limit is reached, landmark-random-move is called to
 push him out of it."
-  :type 'integer
-  :group 'landmark)
+  :type 'integer)
 
 
 ;;;_ + Randomizing functions
@@ -1346,7 +1336,8 @@ push him out of it."
   (put 'landmark-e    'y (/ landmark-board-height 2))
   (put 'landmark-e    'sym 4)
 
-  (mapc 'landmark-plot-internal '(landmark-n landmark-s landmark-e landmark-w 
landmark-tree)))
+  (mapc #'landmark-plot-internal
+        '(landmark-n landmark-s landmark-e landmark-w landmark-tree)))
 
 
 
@@ -1434,7 +1425,7 @@ push him out of it."
 ;;;_ + Functions to move robot
 
 (defun landmark-confidence-for (target-direction)
-  (apply '+
+  (apply #'+
         (get target-direction 'w0)
         (mapcar (lambda (direction)
                   (*
@@ -1494,13 +1485,13 @@ push him out of it."
        (landmark-random-move)
       (progn
        (landmark-calc-confidences)
-       (mapc 'landmark-y landmark-directions)
+       (mapc #'landmark-y landmark-directions)
        (landmark-move)))
 
     (landmark-calc-payoff)
 
-    (mapc 'landmark-update-normal-weights landmark-directions)
-    (mapc 'landmark-update-naught-weights landmark-directions)
+    (mapc #'landmark-update-normal-weights landmark-directions)
+    (mapc #'landmark-update-naught-weights landmark-directions)
     (if landmark-debug
        (landmark-weights-debug)))
   (landmark-terminate-game nil))
@@ -1536,8 +1527,8 @@ If the game is finished, this command requests for 
another game."
 
               (landmark-calc-payoff)
 
-              (mapc 'landmark-update-normal-weights landmark-directions)
-              (mapc 'landmark-update-naught-weights landmark-directions)
+              (mapc #'landmark-update-normal-weights landmark-directions)
+              (mapc #'landmark-update-naught-weights landmark-directions)
               (landmark-amble-robot)
               )))))))
 
@@ -1576,7 +1567,7 @@ If the game is finished, this command requests for 
another game."
 
   (if (not save-weights)
       (progn
-       (mapc 'landmark-fix-weights-for landmark-directions)
+       (mapc #'landmark-fix-weights-for landmark-directions)
        (dolist (direction landmark-directions)
           (put direction 'w0 landmark-initial-w0)))
     (message "Weights preserved for this run."))
@@ -1618,7 +1609,7 @@ If the game is finished, this command requests for 
another game."
 ;;;_ + landmark-test-run ()
 
 ;;;###autoload
-(defalias 'landmark-repeat 'landmark-test-run)
+(defalias 'landmark-repeat #'landmark-test-run)
 ;;;###autoload
 (defun landmark-test-run ()
   "Run 100 Landmark games, each time saving the weights from the previous 
game."
@@ -1670,13 +1661,13 @@ Use \\[describe-mode] for more info."
     (if landmark-one-moment-please
        (message "One moment, please..."))
     (landmark-start-game landmark-n landmark-m)
-    (eval (cons 'landmark-init
-               (cond
-                ((= parg 1)  '(t nil))
-                ((= parg 2)  '(t t))
-                ((= parg 3)  '(nil t))
-                ((= parg 4)  '(nil nil))
-                (t '(nil t))))))))
+    (apply #'landmark-init
+          (cond
+           ((= parg 1)  '(t nil))
+           ((= parg 2)  '(t t))
+           ((= parg 3)  '(nil t))
+           ((= parg 4)  '(nil nil))
+           (t '(nil t)))))))
 
 
 ;;;_ + Local variables
diff --git a/lisp/obsolete/lazy-lock.el b/lisp/obsolete/lazy-lock.el
index e1a0191..34bf85f 100644
--- a/lisp/obsolete/lazy-lock.el
+++ b/lisp/obsolete/lazy-lock.el
@@ -1,4 +1,4 @@
-;;; lazy-lock.el --- lazy demand-driven fontification for fast Font Lock mode
+;;; lazy-lock.el --- lazy demand-driven fontification for fast Font Lock mode  
-*- lexical-binding: t; -*-
 
 ;; Copyright (C) 1994-1998, 2001-2021 Free Software Foundation, Inc.
 
@@ -270,30 +270,14 @@
 (eval-when-compile (require 'cl-lib))
 
 (eval-when-compile
- ;; We use this to preserve or protect things when modifying text properties.
- (defmacro save-buffer-state (varlist &rest body)
-   "Bind variables according to VARLIST and eval BODY restoring buffer state."
-   `(let* (,@(append varlist
-                  '((modified (buffer-modified-p))
-                    (buffer-undo-list t)
-                    (inhibit-read-only t)
-                    (inhibit-point-motion-hooks t)
-                    (inhibit-modification-hooks t)
-                    deactivate-mark
-                    buffer-file-name
-                    buffer-file-truename)))
-     ,@body
-     (when (and (not modified) (buffer-modified-p))
-       (restore-buffer-modified-p nil))))
- (put 'save-buffer-state 'lisp-indent-function 1)
  ;;
  ;; We use this for clarity and speed.  Naughty but nice.
  (defmacro do-while (test &rest body)
    "(do-while TEST BODY...): eval BODY... and repeat if TEST yields non-nil.
 The order of execution is thus BODY, TEST, BODY, TEST and so on
 until TEST returns nil."
-   `(while (progn ,@body ,test)))
- (put 'do-while 'lisp-indent-function (get 'while 'lisp-indent-function)))
+   (declare (indent 1) (debug t))
+   `(while (progn ,@body ,test))))
 
 (defgroup lazy-lock nil
   "Font Lock support mode to fontify lazily."
@@ -326,8 +310,7 @@ The value of this variable is used when Lazy Lock mode is 
turned on."
                                      (symbol :tag "name"))
                               (radio :tag "Size"
                                      (const :tag "none" nil)
-                                     (integer :tag "size")))))
-  :group 'lazy-lock)
+                                     (integer :tag "size"))))))
 
 (defcustom lazy-lock-defer-on-the-fly t
   "If non-nil, means fontification after a change should be deferred.
@@ -346,8 +329,7 @@ The value of this variable is used when Lazy Lock mode is 
turned on."
                 (set :menu-tag "mode specific" :tag "modes"
                      :value (not)
                      (const :tag "Except" not)
-                     (repeat :inline t (symbol :tag "mode"))))
-  :group 'lazy-lock)
+                     (repeat :inline t (symbol :tag "mode")))))
 
 (defcustom lazy-lock-defer-on-scrolling nil
   "If non-nil, means fontification after a scroll should be deferred.
@@ -371,8 +353,7 @@ makes little sense if `lazy-lock-defer-contextually' is 
non-nil.)
 The value of this variable is used when Lazy Lock mode is turned on."
   :type '(choice (const :tag "never" nil)
                 (const :tag "always" t)
-                (other :tag "eventually" eventually))
-  :group 'lazy-lock)
+                (other :tag "eventually" eventually)))
 
 (defcustom lazy-lock-defer-contextually 'syntax-driven
   "If non-nil, means deferred fontification should be syntactically true.
@@ -389,8 +370,7 @@ buffer mode's syntax table, i.e., only if 
`font-lock-keywords-only' is nil.
 The value of this variable is used when Lazy Lock mode is turned on."
   :type '(choice (const :tag "never" nil)
                 (const :tag "always" t)
-                (other :tag "syntax-driven" syntax-driven))
-  :group 'lazy-lock)
+                (other :tag "syntax-driven" syntax-driven)))
 
 (defcustom lazy-lock-defer-time 0.25
   "Time in seconds to delay before beginning deferred fontification.
@@ -401,8 +381,7 @@ variables `lazy-lock-defer-on-the-fly', 
`lazy-lock-defer-on-scrolling' and
 
 The value of this variable is used when Lazy Lock mode is turned on."
   :type '(choice (const :tag "never" nil)
-                (number :tag "seconds"))
-  :group 'lazy-lock)
+                (number :tag "seconds")))
 
 (defcustom lazy-lock-stealth-time 30
   "Time in seconds to delay before beginning stealth fontification.
@@ -411,16 +390,14 @@ If nil, means stealth fontification is never performed.
 
 The value of this variable is used when Lazy Lock mode is turned on."
   :type '(choice (const :tag "never" nil)
-                (number :tag "seconds"))
-  :group 'lazy-lock)
+                (number :tag "seconds")))
 
 (defcustom lazy-lock-stealth-lines (if font-lock-maximum-decoration 100 250)
   "Maximum size of a chunk of stealth fontification.
 Each iteration of stealth fontification can fontify this number of lines.
 To speed up input response during stealth fontification, at the cost of stealth
 taking longer to fontify, you could reduce the value of this variable."
-  :type '(integer :tag "lines")
-  :group 'lazy-lock)
+  :type '(integer :tag "lines"))
 
 (defcustom lazy-lock-stealth-load
   (if (condition-case nil (load-average) (error)) 200)
@@ -435,8 +412,7 @@ See also `lazy-lock-stealth-nice'."
   :type (if (condition-case nil (load-average) (error))
            '(choice (const :tag "never" nil)
                     (integer :tag "load"))
-         '(const :format "%t: unsupported\n" nil))
-  :group 'lazy-lock)
+         '(const :format "%t: unsupported\n" nil)))
 
 (defcustom lazy-lock-stealth-nice 0.125
   "Time in seconds to pause between chunks of stealth fontification.
@@ -447,14 +423,12 @@ To reduce machine load during stealth fontification, at 
the cost of stealth
 taking longer to fontify, you could increase the value of this variable.
 See also `lazy-lock-stealth-load'."
   :type '(choice (const :tag "never" nil)
-                (number :tag "seconds"))
-  :group 'lazy-lock)
+                (number :tag "seconds")))
 
 (defcustom lazy-lock-stealth-verbose
   (and (not lazy-lock-defer-contextually) (not (null font-lock-verbose)))
   "If non-nil, means stealth fontification should show status messages."
-  :type 'boolean
-  :group 'lazy-lock)
+  :type 'boolean)
 
 ;; User Functions:
 
@@ -580,30 +554,30 @@ verbosity is controlled via the variable 
`lazy-lock-stealth-verbose'."
   ;; Add hook if lazy-lock.el is fontifying on scrolling or is deferring.
   (when (or fontifying defer-change defer-scroll defer-context)
     (add-hook 'window-scroll-functions (if defer-scroll
-                                          'lazy-lock-defer-after-scroll
-                                        'lazy-lock-fontify-after-scroll)
+                                          #'lazy-lock-defer-after-scroll
+                                        #'lazy-lock-fontify-after-scroll)
              nil t))
   ;;
   ;; Add hook if lazy-lock.el is fontifying and is not deferring changes.
   (when (and fontifying (not defer-change) (not defer-context))
-    (add-hook 'before-change-functions 'lazy-lock-arrange-before-change nil t))
+    (add-hook 'before-change-functions #'lazy-lock-arrange-before-change nil 
t))
   ;;
   ;; Replace Font Lock mode hook.
-  (remove-hook 'after-change-functions 'font-lock-after-change-function t)
+  (remove-hook 'after-change-functions #'font-lock-after-change-function t)
   (add-hook 'after-change-functions
            (cond ((and defer-change defer-context)
-                  'lazy-lock-defer-rest-after-change)
+                  #'lazy-lock-defer-rest-after-change)
                  (defer-change
-                  'lazy-lock-defer-line-after-change)
+                  #'lazy-lock-defer-line-after-change)
                  (defer-context
-                  'lazy-lock-fontify-rest-after-change)
+                  #'lazy-lock-fontify-rest-after-change)
                  (t
-                  'lazy-lock-fontify-line-after-change))
+                  #'lazy-lock-fontify-line-after-change))
            nil t)
   ;;
   ;; Add package-specific hook.
-  (add-hook 'outline-view-change-hook 'lazy-lock-fontify-after-visage nil t)
-  (add-hook 'hs-hide-hook 'lazy-lock-fontify-after-visage nil t))
+  (add-hook 'outline-view-change-hook #'lazy-lock-fontify-after-visage nil t)
+  (add-hook 'hs-hide-hook #'lazy-lock-fontify-after-visage nil t))
 
 (defun lazy-lock-install-timers (dtime stime)
   ;; Schedule or re-schedule the deferral and stealth timers.
@@ -616,13 +590,13 @@ verbosity is controlled via the variable 
`lazy-lock-stealth-verbose'."
       (when (cdr defer)
        (cancel-timer (cdr defer)))
       (setcar lazy-lock-timers (cons dtime (and dtime
-             (run-with-idle-timer dtime t 'lazy-lock-fontify-after-defer))))))
+             (run-with-idle-timer dtime t #'lazy-lock-fontify-after-defer))))))
   (unless (eq stime (car (cdr lazy-lock-timers)))
     (let ((stealth (cdr lazy-lock-timers)))
       (when (cdr stealth)
        (cancel-timer (cdr stealth)))
       (setcdr lazy-lock-timers (cons stime (and stime
-             (run-with-idle-timer stime t 'lazy-lock-fontify-after-idle)))))))
+             (run-with-idle-timer stime t #'lazy-lock-fontify-after-idle)))))))
 
 (defun lazy-lock-unstall ()
   ;;
@@ -640,21 +614,21 @@ verbosity is controlled via the variable 
`lazy-lock-stealth-verbose'."
          (save-restriction
            (widen)
            (lazy-lock-fontify-region (point-min) (point-max))))))
-    (add-hook 'after-change-functions 'font-lock-after-change-function nil t))
+    (add-hook 'after-change-functions #'font-lock-after-change-function nil t))
   ;;
   ;; Remove the text properties.
   (lazy-lock-after-unfontify-buffer)
   ;;
   ;; Remove the fontification hooks.
-  (remove-hook 'window-scroll-functions 'lazy-lock-fontify-after-scroll t)
-  (remove-hook 'window-scroll-functions 'lazy-lock-defer-after-scroll t)
-  (remove-hook 'before-change-functions 'lazy-lock-arrange-before-change t)
-  (remove-hook 'after-change-functions 'lazy-lock-fontify-line-after-change t)
-  (remove-hook 'after-change-functions 'lazy-lock-fontify-rest-after-change t)
-  (remove-hook 'after-change-functions 'lazy-lock-defer-line-after-change t)
-  (remove-hook 'after-change-functions 'lazy-lock-defer-rest-after-change t)
-  (remove-hook 'outline-view-change-hook 'lazy-lock-fontify-after-visage t)
-  (remove-hook 'hs-hide-hook 'lazy-lock-fontify-after-visage t))
+  (remove-hook 'window-scroll-functions #'lazy-lock-fontify-after-scroll t)
+  (remove-hook 'window-scroll-functions #'lazy-lock-defer-after-scroll t)
+  (remove-hook 'before-change-functions #'lazy-lock-arrange-before-change t)
+  (remove-hook 'after-change-functions #'lazy-lock-fontify-line-after-change t)
+  (remove-hook 'after-change-functions #'lazy-lock-fontify-rest-after-change t)
+  (remove-hook 'after-change-functions #'lazy-lock-defer-line-after-change t)
+  (remove-hook 'after-change-functions #'lazy-lock-defer-rest-after-change t)
+  (remove-hook 'outline-view-change-hook #'lazy-lock-fontify-after-visage t)
+  (remove-hook 'hs-hide-hook #'lazy-lock-fontify-after-visage t))
 
 ;; Hook functions.
 
@@ -682,7 +656,7 @@ verbosity is controlled via the variable 
`lazy-lock-stealth-verbose'."
   ;; result in an unnecessary trigger after this if we did not cancel it now.
   (set-window-redisplay-end-trigger window nil))
 
-(defun lazy-lock-defer-after-scroll (window window-start)
+(defun lazy-lock-defer-after-scroll (window _window-start)
   ;; Called from `window-scroll-functions'.
   ;; Defer fontification following the scroll.  Save the current buffer so that
   ;; we subsequently fontify in all windows showing the buffer.
@@ -750,7 +724,7 @@ verbosity is controlled via the variable 
`lazy-lock-stealth-verbose'."
 (defalias 'lazy-lock-fontify-line-after-change
   ;; Called from `after-change-functions'.
   ;; Fontify the current change.
-  'font-lock-after-change-function)
+  #'font-lock-after-change-function)
 
 (defun lazy-lock-fontify-rest-after-change (beg end old-len)
   ;; Called from `after-change-functions'.
@@ -758,29 +732,29 @@ verbosity is controlled via the variable 
`lazy-lock-stealth-verbose'."
   ;; buffer.  Save the current buffer so that we subsequently fontify in all
   ;; windows showing the buffer.
   (lazy-lock-fontify-line-after-change beg end old-len)
-  (save-buffer-state nil
+  (with-silent-modifications
     (unless (memq (current-buffer) lazy-lock-buffers)
       (push (current-buffer) lazy-lock-buffers))
     (save-restriction
       (widen)
       (remove-text-properties end (point-max) '(lazy-lock nil)))))
 
-(defun lazy-lock-defer-line-after-change (beg end old-len)
+(defun lazy-lock-defer-line-after-change (beg end _old-len)
   ;; Called from `after-change-functions'.
   ;; Defer fontification of the current change.  Save the current buffer so
   ;; that we subsequently fontify in all windows showing the buffer.
-  (save-buffer-state nil
+  (with-silent-modifications
     (unless (memq (current-buffer) lazy-lock-buffers)
       (push (current-buffer) lazy-lock-buffers))
     (remove-text-properties (max (1- beg) (point-min))
                            (min (1+ end) (point-max))
                            '(lazy-lock nil))))
 
-(defun lazy-lock-defer-rest-after-change (beg end old-len)
+(defun lazy-lock-defer-rest-after-change (beg _end _old-len)
   ;; Called from `after-change-functions'.
   ;; Defer fontification of the rest of the buffer.  Save the current buffer so
   ;; that we subsequently fontify in all windows showing the buffer.
-  (save-buffer-state nil
+  (with-silent-modifications
     (unless (memq (current-buffer) lazy-lock-buffers)
       (push (current-buffer) lazy-lock-buffers))
     (save-restriction
@@ -809,10 +783,10 @@ verbosity is controlled via the variable 
`lazy-lock-stealth-verbose'."
        (setq lazy-lock-buffers (cdr lazy-lock-buffers)))))
   ;; Add hook if fontification should now be defer-driven in this buffer.
   (when (and lazy-lock-mode lazy-lock-defer-on-scrolling
-            (memq 'lazy-lock-fontify-after-scroll window-scroll-functions)
+            (memq #'lazy-lock-fontify-after-scroll window-scroll-functions)
             (not (or (input-pending-p) (lazy-lock-unfontified-p))))
-    (remove-hook 'window-scroll-functions 'lazy-lock-fontify-after-scroll t)
-    (add-hook 'window-scroll-functions 'lazy-lock-defer-after-scroll nil t)))
+    (remove-hook 'window-scroll-functions #'lazy-lock-fontify-after-scroll t)
+    (add-hook 'window-scroll-functions #'lazy-lock-defer-after-scroll nil t)))
 
 (defun lazy-lock-fontify-after-idle ()
   ;; Called from `timer-idle-list'.
@@ -868,14 +842,14 @@ verbosity is controlled via the variable 
`lazy-lock-stealth-verbose'."
   ;; Called from `font-lock-after-fontify-buffer'.
   ;; Mark the current buffer as fontified.
   ;; This is a conspiracy hack between lazy-lock.el and font-lock.el.
-  (save-buffer-state nil
+  (with-silent-modifications
     (add-text-properties (point-min) (point-max) '(lazy-lock t))))
 
 (defun lazy-lock-after-unfontify-buffer ()
   ;; Called from `font-lock-after-unfontify-buffer'.
   ;; Mark the current buffer as unfontified.
   ;; This is a conspiracy hack between lazy-lock.el and font-lock.el.
-  (save-buffer-state nil
+  (with-silent-modifications
     (remove-text-properties (point-min) (point-max) '(lazy-lock nil))))
 
 ;; Fontification functions.
@@ -888,27 +862,27 @@ verbosity is controlled via the variable 
`lazy-lock-stealth-verbose'."
     (widen)
     (when (setq beg (text-property-any beg end 'lazy-lock nil))
       (save-excursion
-       (save-match-data
-         (save-buffer-state
-          (next)
-          ;; Find successive unfontified regions between BEG and END.
-          (condition-case data
-              (do-while beg
-                        (setq next (or (text-property-any beg end 'lazy-lock 
t) end))
-         ;; Make sure the region end points are at beginning of line.
-                        (goto-char beg)
-                        (unless (bolp)
-                          (beginning-of-line)
-                          (setq beg (point)))
-                        (goto-char next)
-                        (unless (bolp)
-                          (forward-line)
-                          (setq next (point)))
-                    ;; Fontify the region, then flag it as fontified.
-                        (font-lock-fontify-region beg next)
-                        (add-text-properties beg next '(lazy-lock t))
-                        (setq beg (text-property-any next end 'lazy-lock nil)))
-            ((error quit) (message "Fontifying region...%s" data)))))))))
+       (with-silent-modifications
+         (let ((inhibit-point-motion-hooks t))
+           ;; Find successive unfontified regions between BEG and END.
+           (condition-case data
+               (do-while beg
+                 (let ((next (or (text-property-any beg end 'lazy-lock t)
+                                 end)))
+                   ;; Make sure the region end points are at beginning of line.
+                   (goto-char beg)
+                   (unless (bolp)
+                     (beginning-of-line)
+                     (setq beg (point)))
+                   (goto-char next)
+                   (unless (bolp)
+                     (forward-line)
+                     (setq next (point)))
+                   ;; Fontify the region, then flag it as fontified.
+                   (font-lock-fontify-region beg next)
+                   (add-text-properties beg next '(lazy-lock t))
+                   (setq beg (text-property-any next end 'lazy-lock nil))))
+             ((error quit) (message "Fontifying region...%s" data)))))))))
 
 (defun lazy-lock-fontify-chunk ()
   ;; Fontify the nearest chunk, for stealth, in the current buffer.
@@ -1036,8 +1010,8 @@ verbosity is controlled via the variable 
`lazy-lock-stealth-verbose'."
 
 ;; Install ourselves:
 
-(add-hook 'window-size-change-functions 'lazy-lock-fontify-after-resize)
-(add-hook 'redisplay-end-trigger-functions 'lazy-lock-fontify-after-trigger)
+(add-hook 'window-size-change-functions #'lazy-lock-fontify-after-resize)
+(add-hook 'redisplay-end-trigger-functions #'lazy-lock-fontify-after-trigger)
 
 (unless (assq 'lazy-lock-mode minor-mode-alist)
   (setq minor-mode-alist (append minor-mode-alist '((lazy-lock-mode nil)))))
diff --git a/lisp/obsolete/longlines.el b/lisp/obsolete/longlines.el
index f274dfb..9676d6b 100644
--- a/lisp/obsolete/longlines.el
+++ b/lisp/obsolete/longlines.el
@@ -1,4 +1,4 @@
-;;; longlines.el --- automatically wrap long lines   -*- coding:utf-8 -*-
+;;; longlines.el --- automatically wrap long lines   -*- lexical-binding: t; 
-*-
 
 ;; Copyright (C) 2000-2001, 2004-2021 Free Software Foundation, Inc.
 
@@ -48,7 +48,6 @@
 Otherwise, you can perform filling using `fill-paragraph' or
 `auto-fill-mode'.  In any case, the soft newlines will be removed
 when the file is saved to disk."
-  :group 'longlines
   :type 'boolean)
 
 (defcustom longlines-wrap-follows-window-size nil
@@ -60,7 +59,6 @@ with differing widths.
 If the value is an integer, that specifies the distance from the
 right edge of the window at which wrapping occurs.  For any other
 non-nil value, wrapping occurs 2 characters from the right edge."
-  :group 'longlines
   :type 'boolean)
 
 (defcustom longlines-show-hard-newlines nil
@@ -68,13 +66,11 @@ non-nil value, wrapping occurs 2 characters from the right 
edge."
 \(The variable `longlines-show-effect' controls what they look like.)
 You can also enable the display temporarily, using the command
 `longlines-show-hard-newlines'."
-  :group 'longlines
   :type 'boolean)
 
 (defcustom longlines-show-effect (propertize "¶\n" 'face 'escape-glyph)
   "A string to display when showing hard newlines.
 This is used when `longlines-show-hard-newlines' is on."
-  :group 'longlines
   :type 'string)
 
 ;;; Internal variables
@@ -110,23 +106,23 @@ always call `fill-paragraph' to fill individual 
paragraphs.
 
 If the variable `longlines-show-hard-newlines' is non-nil, hard
 newlines are indicated with a symbol."
-  :group 'longlines :lighter " ll"
+  :lighter " ll"
   (if longlines-mode
       ;; Turn on longlines mode
       (progn
         (use-hard-newlines 1 'never)
         (set (make-local-variable 'require-final-newline) nil)
         (add-to-list 'buffer-file-format 'longlines)
-        (add-hook 'change-major-mode-hook 'longlines-mode-off nil t)
-       (add-hook 'before-revert-hook 'longlines-before-revert-hook nil t)
+        (add-hook 'change-major-mode-hook #'longlines-mode-off nil t)
+       (add-hook 'before-revert-hook #'longlines-before-revert-hook nil t)
         (make-local-variable 'buffer-substring-filters)
         (make-local-variable 'longlines-auto-wrap)
        (set (make-local-variable 'isearch-search-fun-function)
-            'longlines-search-function)
+            #'longlines-search-function)
        (set (make-local-variable 'replace-search-function)
-            'longlines-search-forward)
+            #'longlines-search-forward)
        (set (make-local-variable 'replace-re-search-function)
-            'longlines-re-search-forward)
+            #'longlines-re-search-forward)
         (add-to-list 'buffer-substring-filters 'longlines-encode-string)
         (when longlines-wrap-follows-window-size
          (let ((dw (if (and (integerp longlines-wrap-follows-window-size)
@@ -138,7 +134,7 @@ newlines are indicated with a symbol."
            (set (make-local-variable 'fill-column)
                 (- (window-width) dw)))
           (add-hook 'window-configuration-change-hook
-                    'longlines-window-change-function nil t))
+                    #'longlines-window-change-function nil t))
         (let ((buffer-undo-list t)
               (inhibit-read-only t)
              (inhibit-modification-hooks t)
@@ -160,21 +156,22 @@ newlines are indicated with a symbol."
 
        ;; Hacks to make longlines play nice with various modes.
        (cond ((eq major-mode 'mail-mode)
-              (add-hook 'mail-setup-hook 'longlines-decode-buffer nil t)
+              (declare-function mail-indent-citation "sendmail" ())
+              (add-hook 'mail-setup-hook #'longlines-decode-buffer nil t)
               (or mail-citation-hook
-                  (add-hook 'mail-citation-hook 'mail-indent-citation nil t))
-              (add-hook 'mail-citation-hook 'longlines-decode-region nil t))
+                  (add-hook 'mail-citation-hook #'mail-indent-citation nil t))
+              (add-hook 'mail-citation-hook #'longlines-decode-region nil t))
              ((eq major-mode 'message-mode)
-              (add-hook 'message-setup-hook 'longlines-decode-buffer nil t)
+              (add-hook 'message-setup-hook #'longlines-decode-buffer nil t)
               (make-local-variable 'message-indent-citation-function)
               (if (not (listp message-indent-citation-function))
                   (setq message-indent-citation-function
                         (list message-indent-citation-function)))
-              (add-to-list 'message-indent-citation-function
-                           'longlines-decode-region t)))
+              (add-hook 'message-indent-citation-function
+                        #'longlines-decode-region t t)))
 
-       (add-hook 'after-change-functions 'longlines-after-change-function nil 
t)
-       (add-hook 'post-command-hook 'longlines-post-command-function nil t)
+       (add-hook 'after-change-functions #'longlines-after-change-function nil 
t)
+       (add-hook 'post-command-hook #'longlines-post-command-function nil t)
         (when longlines-auto-wrap
           (auto-fill-mode 0)))
     ;; Turn off longlines mode
@@ -190,12 +187,12 @@ newlines are indicated with a symbol."
            (widen)
            (longlines-encode-region (point-min) (point-max))
            (setq longlines-decoded nil))))
-    (remove-hook 'change-major-mode-hook 'longlines-mode-off t)
-    (remove-hook 'after-change-functions 'longlines-after-change-function t)
-    (remove-hook 'post-command-hook 'longlines-post-command-function t)
-    (remove-hook 'before-revert-hook 'longlines-before-revert-hook t)
+    (remove-hook 'change-major-mode-hook #'longlines-mode-off t)
+    (remove-hook 'after-change-functions #'longlines-after-change-function t)
+    (remove-hook 'post-command-hook #'longlines-post-command-function t)
+    (remove-hook 'before-revert-hook #'longlines-before-revert-hook t)
     (remove-hook 'window-configuration-change-hook
-                 'longlines-window-change-function t)
+                 #'longlines-window-change-function t)
     (when longlines-wrap-follows-window-size
       (kill-local-variable 'fill-column))
     (kill-local-variable 'isearch-search-fun-function)
@@ -482,17 +479,17 @@ This is called by `window-configuration-change-hook'."
 ;;; Loading and saving
 
 (defun longlines-before-revert-hook ()
-  (add-hook 'after-revert-hook 'longlines-after-revert-hook nil t)
+  (add-hook 'after-revert-hook #'longlines-after-revert-hook nil t)
   (longlines-mode 0))
 
 (defun longlines-after-revert-hook ()
-  (remove-hook 'after-revert-hook 'longlines-after-revert-hook t)
+  (remove-hook 'after-revert-hook #'longlines-after-revert-hook t)
   (longlines-mode 1))
 
 (add-to-list
  'format-alist
  (list 'longlines "Automatically wrap long lines." nil nil
-       'longlines-encode-region t nil))
+       #'longlines-encode-region t nil))
 
 ;;; Unloading
 
diff --git a/lisp/obsolete/mailpost.el b/lisp/obsolete/mailpost.el
index 2f74faf..5b3a76e 100644
--- a/lisp/obsolete/mailpost.el
+++ b/lisp/obsolete/mailpost.el
@@ -1,4 +1,4 @@
-;;; mailpost.el --- RMAIL coupler to /usr/uci/post mailer
+;;; mailpost.el --- RMAIL coupler to /usr/uci/post mailer  -*- 
lexical-binding: t; -*-
 
 ;; This is in the public domain
 ;; since Delp distributed it in 1986 without a copyright notice.
@@ -76,7 +76,7 @@ site-init."
                (with-current-buffer errbuf
                  (erase-buffer))))
          (with-file-modes 384 (setq temfile (make-temp-file ",rpost")))
-         (apply 'call-process
+         (apply #'call-process
                 (append (list (if (boundp 'post-mail-program)
                                   post-mail-program
                                 "/usr/uci/lib/mh/post")
diff --git a/lisp/obsolete/mantemp.el b/lisp/obsolete/mantemp.el
index 287a5a7..97e70f2 100644
--- a/lisp/obsolete/mantemp.el
+++ b/lisp/obsolete/mantemp.el
@@ -1,4 +1,4 @@
-;;; mantemp.el --- create manual template instantiations from g++ 2.7.2 output
+;;; mantemp.el --- create manual template instantiations from g++ 2.7.2 output 
 -*- lexical-binding: t; -*-
 
 ;; Copyright (C) 1996, 2001-2021 Free Software Foundation, Inc.
 
diff --git a/lisp/obsolete/meese.el b/lisp/obsolete/meese.el
index 81739df..7443bac 100644
--- a/lisp/obsolete/meese.el
+++ b/lisp/obsolete/meese.el
@@ -1,4 +1,4 @@
-;;; meese.el --- protect the impressionable young minds of America
+;;; meese.el --- protect the impressionable young minds of America  -*- 
lexical-binding: t; -*-
 
 ;; This is in the public domain on account of being distributed since
 ;; 1985 or 1986 without a copyright notice.
diff --git a/lisp/obsolete/messcompat.el b/lisp/obsolete/messcompat.el
index fa73dc7..be25239 100644
--- a/lisp/obsolete/messcompat.el
+++ b/lisp/obsolete/messcompat.el
@@ -1,4 +1,4 @@
-;;; messcompat.el --- making message mode compatible with mail mode
+;;; messcompat.el --- making message mode compatible with mail mode  -*- 
lexical-binding: t; -*-
 
 ;; Copyright (C) 1996-2021 Free Software Foundation, Inc.
 
diff --git a/lisp/obsolete/metamail.el b/lisp/obsolete/metamail.el
index ef97e8a..7223723 100644
--- a/lisp/obsolete/metamail.el
+++ b/lisp/obsolete/metamail.el
@@ -1,4 +1,4 @@
-;;; metamail.el --- Metamail interface for GNU Emacs
+;;; metamail.el --- Metamail interface for GNU Emacs  -*- lexical-binding: t; 
-*-
 
 ;; Copyright (C) 1993, 1996, 2001-2021 Free Software Foundation, Inc.
 
@@ -44,13 +44,11 @@
 
 (defcustom metamail-program-name "metamail"
   "Metamail program name."
-  :type 'string
-  :group 'metamail)
+  :type 'string)
 
 (defcustom metamail-mailer-name "emacs"
   "Mailer name set to MM_MAILER environment variable."
-  :type 'string
-  :group 'metamail)
+  :type 'string)
 
 (defvar metamail-environment '("KEYHEADS=*" "MM_QUIET=1")
   "Environment variables passed to `metamail'.
@@ -65,8 +63,7 @@ It is not expected to be altered globally by `set' or `setq'.
 Instead, change its value temporary using `let' or `let*' form.
 `-m MAILER' argument is automatically generated from the
 `metamail-mailer-name' variable."
-  :type '(repeat (string :tag "Switch"))
-  :group 'metamail)
+  :type '(repeat (string :tag "Switch")))
 
 ;;;###autoload
 (defun metamail-interpret-header ()
@@ -193,7 +190,7 @@ redisplayed as output is inserted."
                       (list "-m" (or metamail-mailer-name "emacs"))
                       (list metafile))))
       ;; `metamail' may not delete the temporary file!
-      (condition-case error
+      (condition-case nil
          (delete-file metafile)
        (error nil))
       )))
diff --git a/lisp/obsolete/mouse-sel.el b/lisp/obsolete/mouse-sel.el
index 608596e..36d9dc6 100644
--- a/lisp/obsolete/mouse-sel.el
+++ b/lisp/obsolete/mouse-sel.el
@@ -1,4 +1,4 @@
-;;; mouse-sel.el --- multi-click selection support
+;;; mouse-sel.el --- multi-click selection support  -*- lexical-binding: t; -*-
 
 ;; Copyright (C) 1993-1995, 2001-2021 Free Software Foundation, Inc.
 
@@ -146,20 +146,17 @@
 If non-nil, \\[mouse-select] and \\[mouse-extend] will leave point at the end
 of the region nearest to where the mouse last was.
 If nil, point will always be placed at the beginning of the region."
-  :type 'boolean
-  :group 'mouse-sel)
+  :type 'boolean)
 
 (defcustom mouse-sel-cycle-clicks t
   "If non-nil, \\[mouse-select] cycles the click-counts after 4 clicks."
-  :type 'boolean
-  :group 'mouse-sel)
+  :type 'boolean)
 
 (defcustom mouse-sel-default-bindings t
   "Control mouse bindings."
   :type '(choice (const :tag "none" nil)
                 (const :tag "cut and paste" interprogram-cut-paste)
-                (other :tag "default bindings" t))
-  :group 'mouse-sel)
+                (other :tag "default bindings" t)))
 
 ;;=== Key bindings ========================================================
 
@@ -216,14 +213,13 @@ the mouse position (or point, if `mouse-yank-at-point' is 
non-nil).
 - mouse-2 while selecting or extending copies selection to the
 kill ring; mouse-1 or mouse-3 kills it."
   :global t
-  :group 'mouse-sel
   (if mouse-sel-mode
       (progn
        ;; If mouse-2 has never been done by the user, initialize the
        ;; `event-kind' property to ensure that `follow-link' clicks
        ;; are interpreted correctly.
        (put 'mouse-2 'event-kind 'mouse-click)
-       (add-hook 'x-lost-selection-functions 'mouse-sel-lost-selection-hook)
+       (add-hook 'x-lost-selection-functions #'mouse-sel-lost-selection-hook)
        (when mouse-sel-default-bindings
          ;; Save original bindings and replace them with new ones.
          (setq mouse-sel-original-bindings
@@ -240,7 +236,7 @@ kill ring; mouse-1 or mouse-3 kills it."
                           #'mouse-sel--ignore))))
 
     ;; Restore original bindings
-    (remove-hook 'x-lost-selection-functions 'mouse-sel-lost-selection-hook)
+    (remove-hook 'x-lost-selection-functions #'mouse-sel-lost-selection-hook)
     (dolist (binding mouse-sel-original-bindings)
       (global-set-key (car binding) (cdr binding)))
     ;; Restore the old values of these variables,
diff --git a/lisp/obsolete/nnir.el b/lisp/obsolete/nnir.el
index 147efed..f2ea5c6 100644
--- a/lisp/obsolete/nnir.el
+++ b/lisp/obsolete/nnir.el
@@ -228,8 +228,7 @@ with three items unique to nnir summary buffers:
 
 If nil this will use `gnus-summary-line-format'."
   :version "24.1"
-  :type '(choice (const :tag "gnus-summary-line-format" nil) string)
-  :group 'nnir)
+  :type '(choice (const :tag "gnus-summary-line-format" nil) string))
 
 
 (defcustom nnir-ignored-newsgroups ""
@@ -237,8 +236,7 @@ If nil this will use `gnus-summary-line-format'."
 Any newsgroup in the active file matching this regexp will be
 skipped when searching."
   :version "24.1"
-  :type '(regexp)
-  :group 'nnir)
+  :type '(regexp))
 
 (defcustom nnir-imap-default-search-key "whole message"
   "The default IMAP search key for an nnir search.
@@ -246,19 +244,16 @@ Must be one of the keys in `nnir-imap-search-arguments'.  
To use
 raw imap queries by default set this to \"imap\"."
   :version "24.1"
   :type `(choice ,@(mapcar (lambda (elem) (list 'const (car elem)))
-                          nnir-imap-search-arguments))
-  :group 'nnir)
+                          nnir-imap-search-arguments)))
 
 (defcustom nnir-swish++-configuration-file
   (expand-file-name "~/Mail/swish++.conf")
   "Configuration file for swish++."
-  :type '(file)
-  :group 'nnir)
+  :type '(file))
 
 (defcustom nnir-swish++-program "search"
   "Name of swish++ search executable."
-  :type '(string)
-  :group 'nnir)
+  :type '(string))
 
 (defcustom nnir-swish++-additional-switches '()
   "A list of strings, to be given as additional arguments to swish++.
@@ -267,8 +262,7 @@ Note that this should be a list.  I.e., do NOT use the 
following:
     (setq nnir-swish++-additional-switches \"-i -w\") ; wrong
 Instead, use this:
     (setq nnir-swish++-additional-switches \\='(\"-i\" \"-w\"))"
-  :type '(repeat (string))
-  :group 'nnir)
+  :type '(repeat (string)))
 
 (defcustom nnir-swish++-remove-prefix (concat (getenv "HOME") "/Mail/")
   "The prefix to remove from swish++ file names to get group names.
@@ -277,37 +271,23 @@ expression.
 
 This variable is very similar to `nnir-namazu-remove-prefix', except
 that it is for swish++, not Namazu."
-  :type '(regexp)
-  :group 'nnir)
+  :type '(regexp))
 
 ;; Swish-E.
-;; URL: http://swish-e.org/
-;; Variables `nnir-swish-e-index-file', `nnir-swish-e-program' and
+;; URL: http://swish-e.org/ [dead link?]
+;; Variables `nnir-swish-e-index-files', `nnir-swish-e-program' and
 ;; `nnir-swish-e-additional-switches'
 
-(make-obsolete-variable 'nnir-swish-e-index-file
-                       'nnir-swish-e-index-files "Emacs 23.1")
-(defcustom nnir-swish-e-index-file
-  (expand-file-name "~/Mail/index.swish-e")
-  "Index file for swish-e.
-This could be a server parameter.
-It is never consulted once `nnir-swish-e-index-files', which should be
-used instead, has been customized."
-  :type '(file)
-  :group 'nnir)
-
 (defcustom nnir-swish-e-index-files
-  (list nnir-swish-e-index-file)
+  (list (expand-file-name "~/Mail/index.swish-e"))
   "List of index files for swish-e.
 This could be a server parameter."
-  :type '(repeat (file))
-  :group 'nnir)
+  :type '(repeat (file)))
 
 (defcustom nnir-swish-e-program "swish-e"
   "Name of swish-e search executable.
 This cannot be a server parameter."
-  :type '(string)
-  :group 'nnir)
+  :type '(string))
 
 (defcustom nnir-swish-e-additional-switches '()
   "A list of strings, to be given as additional arguments to swish-e.
@@ -318,8 +298,7 @@ Instead, use this:
     (setq nnir-swish-e-additional-switches \\='(\"-i\" \"-w\"))
 
 This could be a server parameter."
-  :type '(repeat (string))
-  :group 'nnir)
+  :type '(repeat (string)))
 
 (defcustom nnir-swish-e-remove-prefix (concat (getenv "HOME") "/Mail/")
   "The prefix to remove from swish-e file names to get group names.
@@ -330,15 +309,13 @@ This variable is very similar to 
`nnir-namazu-remove-prefix', except
 that it is for swish-e, not Namazu.
 
 This could be a server parameter."
-  :type '(regexp)
-  :group 'nnir)
+  :type '(regexp))
 
-;; HyREX engine, see <URL:http://ls6-www.cs.uni-dortmund.de/>
+;; HyREX engine, see <URL:http://ls6-www.cs.uni-dortmund.de/> [dead link?]
 
 (defcustom nnir-hyrex-program "nnir-search"
   "Name of the nnir-search executable."
-  :type '(string)
-  :group 'nnir)
+  :type '(string))
 
 (defcustom nnir-hyrex-additional-switches '()
   "A list of strings, to be given as additional arguments for nnir-search.
@@ -346,13 +323,11 @@ Note that this should be a list.  I.e., do NOT use the 
following:
     (setq nnir-hyrex-additional-switches \"-ddl ddl.xml -c nnir\") ; wrong !
 Instead, use this:
     (setq nnir-hyrex-additional-switches \\='(\"-ddl\" \"ddl.xml\" \"-c\" 
\"nnir\"))"
-  :type '(repeat (string))
-  :group 'nnir)
+  :type '(repeat (string)))
 
 (defcustom nnir-hyrex-index-directory (getenv "HOME")
   "Index directory for HyREX."
-  :type '(directory)
-  :group 'nnir)
+  :type '(directory))
 
 (defcustom nnir-hyrex-remove-prefix (concat (getenv "HOME") "/Mail/")
   "The prefix to remove from HyREX file names to get group names.
@@ -364,20 +339,17 @@ setting:  (setq nnir-hyrex-remove-prefix 
\"/home/john/Mail/\")
 Note the trailing slash.  Removing this prefix gives \"mail/misc/42\".
 `nnir' knows to remove the \"/42\" and to replace \"/\" with \".\" to
 arrive at the correct group name, \"mail.misc\"."
-  :type '(directory)
-  :group 'nnir)
+  :type '(directory))
 
 ;; Namazu engine, see <URL:http://www.namazu.org/>
 
 (defcustom nnir-namazu-program "namazu"
   "Name of Namazu search executable."
-  :type '(string)
-  :group 'nnir)
+  :type '(string))
 
 (defcustom nnir-namazu-index-directory (expand-file-name "~/Mail/namazu/")
   "Index directory for Namazu."
-  :type '(directory)
-  :group 'nnir)
+  :type '(directory))
 
 (defcustom nnir-namazu-additional-switches '()
   "A list of strings, to be given as additional arguments to namazu.
@@ -388,8 +360,7 @@ Note that this should be a list.  I.e., do NOT use the 
following:
     (setq nnir-namazu-additional-switches \"-i -w\") ; wrong
 Instead, use this:
     (setq nnir-namazu-additional-switches \\='(\"-i\" \"-w\"))"
-  :type '(repeat (string))
-  :group 'nnir)
+  :type '(repeat (string)))
 
 (defcustom nnir-namazu-remove-prefix (concat (getenv "HOME") "/Mail/")
   "The prefix to remove from Namazu file names to get group names.
@@ -401,14 +372,12 @@ setting:  (setq nnir-namazu-remove-prefix 
\"/home/john/Mail/\")
 Note the trailing slash.  Removing this prefix gives \"mail/misc/42\".
 `nnir' knows to remove the \"/42\" and to replace \"/\" with \".\" to
 arrive at the correct group name, \"mail.misc\"."
-  :type '(directory)
-  :group 'nnir)
+  :type '(directory))
 
 (defcustom nnir-notmuch-program "notmuch"
   "Name of notmuch search executable."
   :version "24.1"
-  :type '(string)
-  :group 'nnir)
+  :type '(string))
 
 (defcustom nnir-notmuch-additional-switches '()
   "A list of strings, to be given as additional arguments to notmuch.
@@ -418,8 +387,7 @@ Note that this should be a list.  I.e., do NOT use the 
following:
 Instead, use this:
     (setq nnir-notmuch-additional-switches \\='(\"-i\" \"-w\"))"
   :version "24.1"
-  :type '(repeat (string))
-  :group 'nnir)
+  :type '(repeat (string)))
 
 (defcustom nnir-notmuch-remove-prefix
   (regexp-quote (or (getenv "MAILDIR") (expand-file-name "~/Mail")))
@@ -430,8 +398,7 @@ expression.
 This variable is very similar to `nnir-namazu-remove-prefix', except
 that it is for notmuch, not Namazu."
   :version "27.1"
-  :type '(regexp)
-  :group 'nnir)
+  :type '(regexp))
 
 (defcustom nnir-notmuch-filter-group-names-function nil
   "Whether and how to use Gnus group names as \"path:\" search terms.
@@ -457,7 +424,7 @@ like so:
   `((imap    nnir-run-imap
              ((criteria
               "Imap Search in"                   ; Prompt
-              ,(mapcar 'car nnir-imap-search-arguments) ; alist for completing
+              ,(mapcar #'car nnir-imap-search-arguments) ; alist for completing
               nil                                ; allow any user input
               nil                                ; initial value
               nnir-imap-search-argument-history  ; the history to use
@@ -495,7 +462,6 @@ Add an entry here when adding a new search engine.")
 (defcustom nnir-method-default-engines  '((nnimap . imap))
   "Alist of default search engines keyed by server method."
   :version "27.1"
-  :group 'nnir
   :type `(repeat (cons (choice (const nnimap) (const nntp) (const nnspool)
                               (const nneething) (const nndir) (const nnmbox)
                               (const nnml) (const nnmh) (const nndraft)
@@ -573,7 +539,7 @@ extensions."
           (or groups (gnus-server-get-active srv nnir-ignored-newsgroups))))
       (message "Opening server %s" server)
       (apply
-       'vconcat
+       #'vconcat
        (catch 'found
          (mapcar
           #'(lambda (group)
@@ -1214,7 +1180,7 @@ construct path: search terms (see the variable
       (error "No directory found in method specification of server %s"
             server))
     (apply
-     'vconcat
+     #'vconcat
      (mapcar (lambda (x)
               (let ((group x)
                     artlist)
@@ -1247,7 +1213,7 @@ construct path: search terms (see the variable
                       (error "Cannot locate directory for group"))
                     (save-excursion
                       (apply
-                       'call-process "find" nil t
+                       #'call-process "find" nil t
                        "find" group "-maxdepth" "1" "-type" "f"
                        "-name" "[0-9]*" "-exec"
                        "grep"
@@ -1260,7 +1226,8 @@ construct path: search terms (see the variable
                     (let* ((path (split-string
                                   (buffer-substring
                                    (point)
-                                   (line-end-position)) "/" t))
+                                   (line-end-position))
+                                  "/" t))
                            (art (string-to-number (car (last path)))))
                       (while (string= "." (car path))
                         (setq path (cdr path)))
@@ -1359,7 +1326,7 @@ Query for the specs, or use SPECS."
         (query-spec
          (or (cdr (assq 'nnir-query-spec specs))
              (apply
-              'append
+              #'append
               (list (cons 'query
                           (read-string "Query: " nil 'nnir-search-history)))
               (when nnir-extra-parms
@@ -1370,7 +1337,7 @@ Query for the specs, or use SPECS."
     (list (cons 'nnir-query-spec query-spec)
          (cons 'nnir-group-spec group-spec))))
 
-(define-obsolete-function-alias 'nnir-get-active 'gnus-server-get-active 
"28.1")
+(define-obsolete-function-alias 'nnir-get-active #'gnus-server-get-active 
"28.1")
 
 ;; The end.
 (provide 'nnir)
diff --git a/lisp/obsolete/old-emacs-lock.el b/lisp/obsolete/old-emacs-lock.el
index 07bccd9..90ff93e 100644
--- a/lisp/obsolete/old-emacs-lock.el
+++ b/lisp/obsolete/old-emacs-lock.el
@@ -1,4 +1,4 @@
-;;; emacs-lock.el --- prevents you from exiting Emacs if a buffer is locked
+;;; emacs-lock.el --- prevents you from exiting Emacs if a buffer is locked  
-*- lexical-binding: t; -*-
 
 ;; Copyright (C) 1994, 1997, 2001-2021 Free Software Foundation, Inc.
 
@@ -90,12 +90,12 @@ If the buffer is locked, signal error and display its name."
       (setq emacs-lock-from-exiting t)))
 
 (unless noninteractive
-  (add-hook 'kill-emacs-hook 'check-emacs-lock))
-(add-hook 'kill-buffer-hook 'emacs-lock-check-buffer-lock)
-(add-hook 'shell-mode-hook 'emacs-lock-was-buffer-locked)
-(add-hook 'shell-mode-hook 'emacs-lock-shell-sentinel)
-(add-hook 'telnet-mode-hook 'emacs-lock-was-buffer-locked)
-(add-hook 'telnet-mode-hook 'emacs-lock-shell-sentinel)
+  (add-hook 'kill-emacs-hook #'check-emacs-lock))
+(add-hook 'kill-buffer-hook #'emacs-lock-check-buffer-lock)
+(add-hook 'shell-mode-hook #'emacs-lock-was-buffer-locked)
+(add-hook 'shell-mode-hook #'emacs-lock-shell-sentinel)
+(add-hook 'telnet-mode-hook #'emacs-lock-was-buffer-locked)
+(add-hook 'telnet-mode-hook #'emacs-lock-shell-sentinel)
 
 (provide 'emacs-lock)
 
diff --git a/lisp/obsolete/otodo-mode.el b/lisp/obsolete/otodo-mode.el
index 58c385a..add17b2 100644
--- a/lisp/obsolete/otodo-mode.el
+++ b/lisp/obsolete/otodo-mode.el
@@ -1,4 +1,4 @@
-;;; todo-mode.el --- major mode for editing TODO list files
+;;; todo-mode.el --- major mode for editing TODO list files  -*- 
lexical-binding: t; -*-
 
 ;; Copyright (C) 1997, 1999, 2001-2021 Free Software Foundation, Inc.
 
@@ -280,26 +280,21 @@ every day and it may also be marked on every day of the 
calendar.
 Using \"&%%(equal (calendar-current-date) date)\" instead will only
 show and mark todo entries for today, but may slow down processing of
 the diary file somewhat."
-  :type 'string
-  :group 'todo)
+  :type 'string)
 (defcustom todo-file-do    (locate-user-emacs-file "todo-do" ".todo-do")
   "TODO mode list file."
   :version "24.4"                       ; added locate-user-emacs-file
-  :type 'file
-  :group 'todo)
+  :type 'file)
 (defcustom todo-file-done  (locate-user-emacs-file "todo-done" ".todo-done")
   "TODO mode archive file."
   :version "24.4"                       ; added locate-user-emacs-file
-  :type 'file
-  :group 'todo)
+  :type 'file)
 (defcustom todo-mode-hook  nil
   "TODO mode hooks."
-  :type 'hook
-  :group 'todo)
+  :type 'hook)
 (defcustom todo-edit-mode-hook nil
   "TODO Edit mode hooks."
-  :type 'hook
-  :group 'todo)
+  :type 'hook)
 (defcustom todo-insert-threshold 0
   "TODO mode insertion accuracy.
 
@@ -314,8 +309,7 @@ your item just before that point.  If you set the threshold 
to,
 e.g. 8, it will stop as soon as the window size drops below that
 amount and will insert the item in the approximate center of that
 window."
-  :type 'integer
-  :group 'todo)
+  :type 'integer)
 (defvar todo-edit-buffer " *TODO Edit*"
   "TODO Edit buffer name.")
 (defcustom todo-file-top (locate-user-emacs-file "todo-top" ".todo-top")
@@ -324,32 +318,26 @@ window."
 Not in TODO format, but diary compatible.
 Automatically generated when `todo-save-top-priorities' is non-nil."
   :version "24.4"                       ; added locate-user-emacs-file
-  :type 'string
-  :group 'todo)
+  :type 'string)
 
 (defcustom todo-print-function 'ps-print-buffer-with-faces
   "Function to print the current buffer."
-  :type 'symbol
-  :group 'todo)
+  :type 'symbol)
 (defcustom todo-show-priorities 1
   "Default number of priorities to show by \\[todo-top-priorities].
 0 means show all entries."
-  :type 'integer
-  :group 'todo)
+  :type 'integer)
 (defcustom todo-print-priorities 0
   "Default number of priorities to print by \\[todo-print].
 0 means print all entries."
-  :type 'integer
-  :group 'todo)
+  :type 'integer)
 (defcustom todo-remove-separator t
   "Non-nil to remove category separators in\
 \\[todo-top-priorities] and \\[todo-print]."
-  :type 'boolean
-  :group 'todo)
+  :type 'boolean)
 (defcustom todo-save-top-priorities-too t
   "Non-nil makes `todo-save' automatically save top-priorities in 
`todo-file-top'."
-  :type 'boolean
-  :group 'todo)
+  :type 'boolean)
 
 ;; Thanks for the ISO time stamp format go to Karl Eichwalder <ke@suse.de>
 ;; My format string for the appt.el package is "%3b %2d, %y, %02I:%02M%p".
@@ -358,17 +346,14 @@ Automatically generated when `todo-save-top-priorities' 
is non-nil."
   "%:y-%02m-%02d %02H:%02M"
   "TODO mode time string format for done entries.
 For details see the variable `time-stamp-format'."
-  :type 'string
-  :group 'todo)
+  :type 'string)
 
 (defcustom todo-entry-prefix-function 'todo-entry-timestamp-initials
   "Function producing text to insert at start of todo entry."
-  :type 'symbol
-  :group 'todo)
+  :type 'symbol)
 (defcustom todo-initials (or (getenv "INITIALS") (user-login-name))
   "Initials of todo item author."
-  :type 'string
-  :group 'todo)
+  :type 'string)
 
 (defun todo-entry-timestamp-initials ()
   "Prepend timestamp and your initials to the head of a TODO entry."
@@ -395,25 +380,25 @@ Use `todo-categories' instead.")
 (defvar todo-mode-map
   (let ((map (make-keymap)))
     (suppress-keymap map t)
-    (define-key map "+" 'todo-forward-category)
-    (define-key map "-" 'todo-backward-category)
-    (define-key map "d" 'todo-file-item) ;done/delete
-    (define-key map "e" 'todo-edit-item)
-    (define-key map "E" 'todo-edit-multiline)
-    (define-key map "f" 'todo-file-item)
-    (define-key map "i" 'todo-insert-item)
-    (define-key map "I" 'todo-insert-item-here)
-    (define-key map "j" 'todo-jump-to-category)
-    (define-key map "k" 'todo-delete-item)
-    (define-key map "l" 'todo-lower-item)
-    (define-key map "n" 'todo-forward-item)
-    (define-key map "p" 'todo-backward-item)
-    (define-key map "P" 'todo-print)
-    (define-key map "q" 'todo-quit)
-    (define-key map "r" 'todo-raise-item)
-    (define-key map "s" 'todo-save)
-    (define-key map "S" 'todo-save-top-priorities)
-    (define-key map "t" 'todo-top-priorities)
+    (define-key map "+" #'todo-forward-category)
+    (define-key map "-" #'todo-backward-category)
+    (define-key map "d" #'todo-file-item) ;done/delete
+    (define-key map "e" #'todo-edit-item)
+    (define-key map "E" #'todo-edit-multiline)
+    (define-key map "f" #'todo-file-item)
+    (define-key map "i" #'todo-insert-item)
+    (define-key map "I" #'todo-insert-item-here)
+    (define-key map "j" #'todo-jump-to-category)
+    (define-key map "k" #'todo-delete-item)
+    (define-key map "l" #'todo-lower-item)
+    (define-key map "n" #'todo-forward-item)
+    (define-key map "p" #'todo-backward-item)
+    (define-key map "P" #'todo-print)
+    (define-key map "q" #'todo-quit)
+    (define-key map "r" #'todo-raise-item)
+    (define-key map "s" #'todo-save)
+    (define-key map "S" #'todo-save-top-priorities)
+    (define-key map "t" #'todo-top-priorities)
     map)
   "TODO mode keymap.")
 
@@ -451,7 +436,7 @@ Use `todo-categories' instead.")
       (search-forward-regexp (concat "^" todo-category-end))
       (narrow-to-region begin (line-beginning-position))
       (goto-char (point-min)))))
-(defalias 'todo-cat-slct 'todo-category-select)
+(defalias 'todo-cat-slct #'todo-category-select)
 
 (defun todo-forward-category ()
   "Go forward to TODO list of next category."
@@ -459,7 +444,7 @@ Use `todo-categories' instead.")
   (setq todo-category-number
         (mod (1+ todo-category-number) (length todo-categories)))
   (todo-category-select))
-(defalias 'todo-cmd-forw 'todo-forward-category)
+(defalias 'todo-cmd-forw #'todo-forward-category)
 
 (defun todo-backward-category ()
   "Go back to TODO list of previous category."
@@ -467,14 +452,14 @@ Use `todo-categories' instead.")
   (setq todo-category-number
         (mod (1- todo-category-number) (length todo-categories)))
   (todo-category-select))
-(defalias 'todo-cmd-back 'todo-backward-category)
+(defalias 'todo-cmd-back #'todo-backward-category)
 
 (defun todo-backward-item ()
   "Select previous entry of TODO list."
   (interactive)
   (search-backward-regexp (concat "^" (regexp-quote todo-prefix)) nil t)
   (message ""))
-(defalias 'todo-cmd-prev 'todo-backward-item)
+(defalias 'todo-cmd-prev #'todo-backward-item)
 
 (defun todo-forward-item (&optional count)
   "Select COUNT-th next entry of TODO list."
@@ -485,7 +470,7 @@ Use `todo-categories' instead.")
                          nil 'goto-end count)
   (beginning-of-line)
   (message ""))
-(defalias 'todo-cmd-next 'todo-forward-item)
+(defalias 'todo-cmd-next #'todo-forward-item)
 
 (defun todo-save ()
   "Save the TODO list."
@@ -494,7 +479,7 @@ Use `todo-categories' instead.")
     (save-restriction
       (save-buffer)))
   (if todo-save-top-priorities-too (todo-save-top-priorities)))
-(defalias 'todo-cmd-save 'todo-save)
+(defalias 'todo-cmd-save #'todo-save)
 
 (defun todo-quit ()
   "Done with TODO list for now."
@@ -503,7 +488,7 @@ Use `todo-categories' instead.")
   (todo-save)
   (message "")
   (bury-buffer))
-(defalias 'todo-cmd-done 'todo-quit)
+(defalias 'todo-cmd-done #'todo-quit)
 
 (defun todo-edit-item ()
   "Edit current TODO list entry."
@@ -518,7 +503,7 @@ Use `todo-categories' instead.")
            (todo-backward-item)
            (message ""))))
     (error "No TODO list entry to edit")))
-(defalias 'todo-cmd-edit 'todo-edit-item)
+(defalias 'todo-cmd-edit #'todo-edit-item)
 
 (defun todo-edit-multiline ()
   "Set up a buffer for editing a multiline TODO list entry."
@@ -622,7 +607,7 @@ category."
           (category (if arg (todo-completing-read) current-category)))
       (todo-add-item-non-interactively new-item category))))
 
-(defalias 'todo-cmd-inst 'todo-insert-item)
+(defalias 'todo-cmd-inst #'todo-insert-item)
 
 (defun todo-insert-item-here ()
   "Insert a new TODO list entry directly above the entry at point.
@@ -650,7 +635,7 @@ If point is on an empty line, insert the entry there."
       (setq todo-previous-answer
             (y-or-n-p (format-message "More important than `%s'? " item)))))
   todo-previous-answer)
-(defalias 'todo-ask-p 'todo-more-important-p)
+(defalias 'todo-ask-p #'todo-more-important-p)
 
 (defun todo-delete-item ()
   "Delete current TODO list entry."
@@ -664,7 +649,7 @@ If point is on an empty line, insert the entry there."
           (todo-backward-item))
         (message ""))
     (error "No TODO list entry to delete")))
-(defalias 'todo-cmd-kill 'todo-delete-item)
+(defalias 'todo-cmd-kill #'todo-delete-item)
 
 (defun todo-raise-item ()
   "Raise priority of current entry."
@@ -677,7 +662,7 @@ If point is on an empty line, insert the entry there."
           (insert item "\n"))
         (message ""))
     (error "No TODO list entry to raise")))
-(defalias 'todo-cmd-rais 'todo-raise-item)
+(defalias 'todo-cmd-rais #'todo-raise-item)
 
 (defun todo-lower-item ()
   "Lower priority of current entry."
@@ -691,7 +676,7 @@ If point is on an empty line, insert the entry there."
           (insert item "\n"))
         (message ""))
     (error "No TODO list entry to lower")))
-(defalias 'todo-cmd-lowr 'todo-lower-item)
+(defalias 'todo-cmd-lowr #'todo-lower-item)
 
 (defun todo-file-item (&optional comment)
   "File the current TODO list entry away, annotated with an optional COMMENT."
diff --git a/lisp/obsolete/patcomp.el b/lisp/obsolete/patcomp.el
index 8545f07..2c35cb0 100644
--- a/lisp/obsolete/patcomp.el
+++ b/lisp/obsolete/patcomp.el
@@ -1,4 +1,4 @@
-;;; patcomp.el --- used by patch files to update Emacs releases
+;;; patcomp.el --- used by patch files to update Emacs releases  -*- 
lexical-binding: t; -*-
 
 ;; This file is part of GNU Emacs.
 
diff --git a/lisp/obsolete/pc-mode.el b/lisp/obsolete/pc-mode.el
index d4c90c2..cf0bc28 100644
--- a/lisp/obsolete/pc-mode.el
+++ b/lisp/obsolete/pc-mode.el
@@ -1,4 +1,4 @@
-;;; pc-mode.el --- emulate certain key bindings used on PCs
+;;; pc-mode.el --- emulate certain key bindings used on PCs  -*- 
lexical-binding: t; -*-
 
 ;; Copyright (C) 1995, 2001-2021 Free Software Foundation, Inc.
 
@@ -40,16 +40,16 @@ C-Escape does list-buffers."
   (define-key function-key-map [delete] "\C-d")
   (define-key function-key-map [M-delete] [?\M-d])
   (define-key function-key-map [C-delete] [?\M-d])
-  (global-set-key [C-M-delete] 'kill-sexp)
-  (global-set-key [C-backspace] 'backward-kill-word)
-  (global-set-key [M-backspace] 'undo)
+  (global-set-key [C-M-delete] #'kill-sexp)
+  (global-set-key [C-backspace] #'backward-kill-word)
+  (global-set-key [M-backspace] #'undo)
 
-  (global-set-key [C-escape] 'list-buffers)
+  (global-set-key [C-escape] #'list-buffers)
 
-  (global-set-key [home] 'beginning-of-line)
-  (global-set-key [end] 'end-of-line)
-  (global-set-key [C-home] 'beginning-of-buffer)
-  (global-set-key [C-end] 'end-of-buffer))
+  (global-set-key [home] #'beginning-of-line)
+  (global-set-key [end] #'end-of-line)
+  (global-set-key [C-home] #'beginning-of-buffer)
+  (global-set-key [C-end] #'end-of-buffer))
 
 (provide 'pc-mode)
 
diff --git a/lisp/obsolete/pc-select.el b/lisp/obsolete/pc-select.el
index 3f18488..5982875 100644
--- a/lisp/obsolete/pc-select.el
+++ b/lisp/obsolete/pc-select.el
@@ -1,4 +1,4 @@
-;;; pc-select.el --- emulate mark, cut, copy and paste from Motif
+;;; pc-select.el --- emulate mark, cut, copy and paste from Motif  -*- 
lexical-binding: t; -*-
 ;;;                 (or MAC GUI or MS-windoze (bah)) look-and-feel
 ;;;                 including key bindings.
 
@@ -94,25 +94,21 @@ The scroll commands normally generate an error if you try 
to scroll
 past the top or bottom of the buffer.  This is annoying when selecting
 text with these commands.  If you set this variable to non-nil, these
 errors are suppressed."
-  :type 'boolean
-  :group 'pc-select)
+  :type 'boolean)
 
 (defcustom pc-select-selection-keys-only nil
   "Non-nil means only bind the basic selection keys when started.
 Other keys that emulate pc-behavior will be untouched.
 This gives mostly Emacs-like behavior with only the selection keys enabled."
-  :type 'boolean
-  :group 'pc-select)
+  :type 'boolean)
 
 (defcustom pc-select-meta-moves-sexps nil
   "Non-nil means move sexp-wise with Meta key, otherwise move word-wise."
-  :type 'boolean
-  :group 'pc-select)
+  :type 'boolean)
 
 (defcustom pc-selection-mode-hook nil
   "The hook to run when PC Selection mode is toggled."
-  :type 'hook
-  :group 'pc-select)
+  :type 'hook)
 
 (defvar pc-select-saved-settings-alist nil
   "The values of the variables before PC Selection mode was toggled on.
@@ -320,7 +316,6 @@ but before calling PC Selection mode):
   ;; FIXME: bring pc-bindings-mode here ?
   nil nil nil
 
-  :group 'pc-select
   :global t
 
   (if pc-selection-mode
diff --git a/lisp/obsolete/pgg-def.el b/lisp/obsolete/pgg-def.el
index 4250938..4d30e32 100644
--- a/lisp/obsolete/pgg-def.el
+++ b/lisp/obsolete/pgg-def.el
@@ -1,4 +1,4 @@
-;;; pgg-def.el --- functions/macros for defining PGG functions
+;;; pgg-def.el --- functions/macros for defining PGG functions  -*- 
lexical-binding: t; -*-
 
 ;; Copyright (C) 1999, 2002-2021 Free Software Foundation, Inc.
 
@@ -32,47 +32,39 @@
 
 (defcustom pgg-default-scheme 'gpg
   "Default PGP scheme."
-  :group 'pgg
   :type '(choice (const :tag "GnuPG" gpg)
                 (const :tag "PGP 5" pgp5)
                 (const :tag "PGP" pgp)))
 
 (defcustom pgg-default-user-id (user-login-name)
   "User ID of your default identity."
-  :group 'pgg
   :type 'string)
 
 (defcustom pgg-default-keyserver-address "subkeys.pgp.net"
   "Host name of keyserver."
-  :group 'pgg
   :type 'string)
 
 (defcustom pgg-query-keyserver nil
   "Whether PGG queries keyservers for missing keys when verifying messages."
   :version "22.1"
-  :group 'pgg
   :type 'boolean)
 
 (defcustom pgg-encrypt-for-me t
   "If t, encrypt all outgoing messages with user's public key."
-  :group 'pgg
   :type 'boolean)
 
 (defcustom pgg-cache-passphrase t
   "If t, cache passphrase."
-  :group 'pgg
   :type 'boolean)
 
 (defcustom pgg-passphrase-cache-expiry 16
   "How many seconds the passphrase is cached.
 Whether the passphrase is cached at all is controlled by
 `pgg-cache-passphrase'."
-  :group 'pgg
   :type 'integer)
 
 (defcustom pgg-passphrase-coding-system nil
   "Coding system to encode passphrase."
-  :group 'pgg
   :type 'coding-system)
 
 (defvar pgg-messages-coding-system nil
diff --git a/lisp/obsolete/pgg-gpg.el b/lisp/obsolete/pgg-gpg.el
index 90255fe..d06a485 100644
--- a/lisp/obsolete/pgg-gpg.el
+++ b/lisp/obsolete/pgg-gpg.el
@@ -1,4 +1,4 @@
-;;; pgg-gpg.el --- GnuPG support for PGG.
+;;; pgg-gpg.el --- GnuPG support for PGG.  -*- lexical-binding: t; -*-
 
 ;; Copyright (C) 1999-2000, 2002-2021 Free Software Foundation, Inc.
 
@@ -37,23 +37,19 @@
 
 (defcustom pgg-gpg-program "gpg"
   "The GnuPG executable."
-  :group 'pgg-gpg
   :type 'string)
 
 (defcustom pgg-gpg-extra-args nil
   "Extra arguments for every GnuPG invocation."
-  :group 'pgg-gpg
   :type '(repeat (string :tag "Argument")))
 
 (defcustom pgg-gpg-recipient-argument "--recipient"
   "GnuPG option to specify recipient."
-  :group 'pgg-gpg
   :type '(choice (const :tag "New `--recipient' option" "--recipient")
                 (const :tag "Old `--remote-user' option" "--remote-user")))
 
 (defcustom pgg-gpg-use-agent t
   "Whether to use gnupg agent for key caching."
-  :group 'pgg-gpg
   :type 'boolean)
 
 (defvar pgg-gpg-user-id nil
@@ -97,7 +93,7 @@
                         passphrase-with-newline
                         (coding-system-change-eol-conversion
                          pgg-passphrase-coding-system 'unix)))
-                 (pgg-clear-string passphrase-with-newline))
+                 (clear-string passphrase-with-newline))
              (setq encoded-passphrase-with-new-line passphrase-with-newline
                    passphrase-with-newline nil))
            (process-send-string process encoded-passphrase-with-new-line))
@@ -125,9 +121,9 @@
            (if (= 127 exit-status)
                (error "%s could not be found" program))))
       (if passphrase-with-newline
-         (pgg-clear-string passphrase-with-newline))
+         (clear-string passphrase-with-newline))
       (if encoded-passphrase-with-new-line
-         (pgg-clear-string encoded-passphrase-with-new-line))
+         (clear-string encoded-passphrase-with-new-line))
       (if (and process (eq 'run (process-status process)))
          (interrupt-process process))
       (if (file-exists-p output-file-name)
diff --git a/lisp/obsolete/pgg-parse.el b/lisp/obsolete/pgg-parse.el
index edb5d4f..2c76365 100644
--- a/lisp/obsolete/pgg-parse.el
+++ b/lisp/obsolete/pgg-parse.el
@@ -1,4 +1,4 @@
-;;; pgg-parse.el --- OpenPGP packet parsing
+;;; pgg-parse.el --- OpenPGP packet parsing  -*- lexical-binding: t; -*-
 
 ;; Copyright (C) 1999, 2002-2021 Free Software Foundation, Inc.
 
@@ -44,14 +44,12 @@
 (defcustom pgg-parse-public-key-algorithm-alist
   '((1 . RSA) (2 . RSA-E) (3 . RSA-S) (16 . ELG-E) (17 . DSA) (20 . ELG))
   "Alist of the assigned number to the public key algorithm."
-  :group 'pgg-parse
   :type '(repeat
          (cons (sexp :tag "Number") (sexp :tag "Type"))))
 
 (defcustom pgg-parse-symmetric-key-algorithm-alist
   '((1 . IDEA) (2 . 3DES) (4 . CAST5) (5 . SAFER-SK128))
   "Alist of the assigned number to the symmetric key algorithm."
-  :group 'pgg-parse
   :type '(repeat
          (cons (sexp :tag "Number") (sexp :tag "Type"))))
 
@@ -59,7 +57,6 @@
   '((1 . MD5) (2 . SHA1) (3 . RIPEMD160) (5 . MD2) (8 . SHA256) (9 . SHA384)
     (10 . SHA512))
   "Alist of the assigned number to the cryptographic hash algorithm."
-  :group 'pgg-parse
   :type '(repeat
          (cons (sexp :tag "Number") (sexp :tag "Type"))))
 
@@ -68,7 +65,6 @@
     (1 . ZIP)
     (2 . ZLIB))
   "Alist of the assigned number to the compression algorithm."
-  :group 'pgg-parse
   :type '(repeat
          (cons (sexp :tag "Number") (sexp :tag "Type"))))
 
@@ -87,13 +83,11 @@
     (48 . "Certification revocation signature")
     (64 . "Timestamp signature."))
   "Alist of the assigned number to the signature type."
-  :group 'pgg-parse
   :type '(repeat
          (cons (sexp :tag "Number") (sexp :tag "Type"))))
 
 (defcustom pgg-ignore-packet-checksum t; XXX
   "If non-nil checksum of each ascii armored packet will be ignored."
-  :group 'pgg-parse
   :type 'boolean)
 
 (defvar pgg-armor-header-lines
@@ -148,7 +142,7 @@
   ;; `(string-to-number-list (pgg-read-body-string ,ptag))
   )
 
-(defalias 'pgg-skip-bytes 'forward-char)
+(defalias 'pgg-skip-bytes #'forward-char)
 
 (defmacro pgg-skip-header (ptag)
   `(pgg-skip-bytes (nth 2 ,ptag)))
@@ -345,7 +339,7 @@
     ;; 100 to 110 = internal or user-defined
     ))
 
-(defun pgg-parse-signature-packet (ptag)
+(defun pgg-parse-signature-packet (_ptag)
   (let* ((signature-version (pgg-byte-after))
         (result (list (cons 'version signature-version)))
         hashed-material field n)
@@ -411,7 +405,7 @@
                       pgg-parse-hash-algorithm-alist)))
     result))
 
-(defun pgg-parse-public-key-encrypted-session-key-packet (ptag)
+(defun pgg-parse-public-key-encrypted-session-key-packet (_ptag)
   (let (result)
     (pgg-set-alist result
                   'version (pgg-read-byte))
@@ -425,7 +419,7 @@
                              pgg-parse-public-key-algorithm-alist)))
     result))
 
-(defun pgg-parse-symmetric-key-encrypted-session-key-packet (ptag)
+(defun pgg-parse-symmetric-key-encrypted-session-key-packet (_ptag)
   (let (result)
     (pgg-set-alist result
                   'version
@@ -436,7 +430,7 @@
                              pgg-parse-symmetric-key-algorithm-alist)))
     result))
 
-(defun pgg-parse-public-key-packet (ptag)
+(defun pgg-parse-public-key-packet (_ptag)
   (let* ((key-version (pgg-read-byte))
         (result (list (cons 'version key-version)))
         field)
diff --git a/lisp/obsolete/pgg-pgp.el b/lisp/obsolete/pgg-pgp.el
index e02032a..665be0b 100644
--- a/lisp/obsolete/pgg-pgp.el
+++ b/lisp/obsolete/pgg-pgp.el
@@ -1,4 +1,4 @@
-;;; pgg-pgp.el --- PGP 2.* and 6.* support for PGG.
+;;; pgg-pgp.el --- PGP 2.* and 6.* support for PGG.  -*- lexical-binding: t; 
-*-
 
 ;; Copyright (C) 1999-2000, 2002-2021 Free Software Foundation, Inc.
 
@@ -35,23 +35,19 @@
 
 (defcustom pgg-pgp-program "pgp"
   "PGP 2.* and 6.* executable."
-  :group 'pgg-pgp
   :type 'string)
 
 (defcustom pgg-pgp-shell-file-name "/bin/sh"
   "File name to load inferior shells from.
 Bourne shell or its equivalent \(not tcsh) is needed for \"2>\"."
-  :group 'pgg-pgp
   :type 'string)
 
 (defcustom pgg-pgp-shell-command-switch "-c"
   "Switch used to have the shell execute its command line argument."
-  :group 'pgg-pgp
   :type 'string)
 
 (defcustom pgg-pgp-extra-args nil
   "Extra arguments for every PGP invocation."
-  :group 'pgg-pgp
   :type '(choice
          (const :tag "None" nil)
          (string :tag "Arguments")))
@@ -112,7 +108,7 @@ Bourne shell or its equivalent \(not tcsh) is needed for 
\"2>\"."
          (delete-file errors-file-name)
        (file-error nil)))))
 
-(defun pgg-pgp-lookup-key (string &optional type)
+(defun pgg-pgp-lookup-key (string &optional _type)
   "Search keys associated with STRING."
   (let ((args (list "+batchmode" "+language=en" "-kv" string)))
     (with-current-buffer (get-buffer-create pgg-output-buffer)
@@ -133,7 +129,7 @@ Bourne shell or its equivalent \(not tcsh) is needed for 
\"2>\"."
 (defun pgg-pgp-encrypt-region (start end recipients &optional sign passphrase)
   "Encrypt the current region between START and END."
   (let* ((pgg-pgp-user-id (or pgg-pgp-user-id pgg-default-user-id))
-        (passphrase (or passphrase
+        (_passphrase (or passphrase
                         (when sign
                           (pgg-read-passphrase
                            (format "PGP passphrase for %s: "
@@ -143,10 +139,11 @@ Bourne shell or its equivalent \(not tcsh) is needed for 
\"2>\"."
          (concat
           "+encrypttoself=off +verbose=1 +batchmode +language=us -fate "
            (if (or recipients pgg-encrypt-for-me)
-               (mapconcat 'shell-quote-argument
+               (mapconcat #'shell-quote-argument
                           (append recipients
                                   (if pgg-encrypt-for-me
-                                      (list pgg-pgp-user-id))) " "))
+                                      (list pgg-pgp-user-id)))
+                          " "))
            (if sign (concat " -s -u " (shell-quote-argument 
pgg-pgp-user-id))))))
     (pgg-pgp-process-region start end nil pgg-pgp-program args)
     (pgg-process-when-success nil)))
@@ -203,6 +200,7 @@ passphrase cache or user."
   (let* ((orig-file (pgg-make-temp-file "pgg"))
         (args "+verbose=1 +batchmode +language=us"))
     (with-file-modes 448
+      (defvar jam-zcat-filename-list)
       (let ((coding-system-for-write 'binary)
             jka-compr-compression-info-list jam-zcat-filename-list)
         (write-region start end orig-file)))
diff --git a/lisp/obsolete/pgg-pgp5.el b/lisp/obsolete/pgg-pgp5.el
index 42ff1ca..d952317 100644
--- a/lisp/obsolete/pgg-pgp5.el
+++ b/lisp/obsolete/pgg-pgp5.el
@@ -1,4 +1,4 @@
-;;; pgg-pgp5.el --- PGP 5.* support for PGG.
+;;; pgg-pgp5.el --- PGP 5.* support for PGG.  -*- lexical-binding: t; -*-
 
 ;; Copyright (C) 1999-2000, 2002-2021 Free Software Foundation, Inc.
 
@@ -35,38 +35,31 @@
 
 (defcustom pgg-pgp5-pgpe-program "pgpe"
   "PGP 5.* `pgpe' executable."
-  :group 'pgg-pgp5
   :type 'string)
 
 (defcustom pgg-pgp5-pgps-program "pgps"
   "PGP 5.* `pgps' executable."
-  :group 'pgg-pgp5
   :type 'string)
 
 (defcustom pgg-pgp5-pgpk-program "pgpk"
   "PGP 5.* `pgpk' executable."
-  :group 'pgg-pgp5
   :type 'string)
 
 (defcustom pgg-pgp5-pgpv-program "pgpv"
   "PGP 5.* `pgpv' executable."
-  :group 'pgg-pgp5
   :type 'string)
 
 (defcustom pgg-pgp5-shell-file-name "/bin/sh"
   "File name to load inferior shells from.
 Bourne shell or its equivalent \(not tcsh) is needed for \"2>\"."
-  :group 'pgg-pgp5
   :type 'string)
 
 (defcustom pgg-pgp5-shell-command-switch "-c"
   "Switch used to have the shell execute its command line argument."
-  :group 'pgg-pgp5
   :type 'string)
 
 (defcustom pgg-pgp5-extra-args nil
   "Extra arguments for every PGP 5.* invocation."
-  :group 'pgg-pgp5
   :type '(choice
          (const :tag "None" nil)
          (string :tag "Arguments")))
@@ -128,7 +121,7 @@ Bourne shell or its equivalent \(not tcsh) is needed for 
\"2>\"."
          (delete-file errors-file-name)
        (file-error nil)))))
 
-(defun pgg-pgp5-lookup-key (string &optional type)
+(defun pgg-pgp5-lookup-key (string &optional _type)
   "Search keys associated with STRING."
   (let ((args (list "+language=en" "-l" string)))
     (with-current-buffer (get-buffer-create pgg-output-buffer)
@@ -145,7 +138,7 @@ Bourne shell or its equivalent \(not tcsh) is needed for 
\"2>\"."
 (defun pgg-pgp5-encrypt-region (start end recipients &optional sign passphrase)
   "Encrypt the current region between START and END."
   (let* ((pgg-pgp5-user-id (or pgg-pgp5-user-id pgg-default-user-id))
-        (passphrase (or passphrase
+        (_passphrase (or passphrase
                         (when sign
                           (pgg-read-passphrase
                            (format "PGP passphrase for %s: "
@@ -209,6 +202,7 @@ Bourne shell or its equivalent \(not tcsh) is needed for 
\"2>\"."
   (let ((orig-file (pgg-make-temp-file "pgg"))
        (args '("+verbose=1" "+batchmode=1" "+language=us")))
     (with-file-modes 448
+      (defvar jam-zcat-filename-list)   ;Not sure where this comes from.
       (let ((coding-system-for-write 'binary)
            jka-compr-compression-info-list jam-zcat-filename-list)
        (write-region start end orig-file)))
diff --git a/lisp/obsolete/pgg.el b/lisp/obsolete/pgg.el
index ec93eeb..5ed5993 100644
--- a/lisp/obsolete/pgg.el
+++ b/lisp/obsolete/pgg.el
@@ -1,4 +1,4 @@
-;;; pgg.el --- glue for the various PGP implementations.
+;;; pgg.el --- glue for the various PGP implementations.  -*- lexical-binding: 
t; -*-
 
 ;; Copyright (C) 1999-2000, 2002-2021 Free Software Foundation, Inc.
 
@@ -27,99 +27,19 @@
 
 (require 'pgg-def)
 (require 'pgg-parse)
-(autoload 'run-at-time "timer")
 
 (eval-when-compile (require 'cl-lib))
 
 ;;; @ utility functions
 ;;;
 
-(eval-when-compile
-  (when (featurep 'xemacs)
-    (defmacro pgg-run-at-time-1 (time repeat function args)
-      (if (condition-case nil
-             (let ((delete-itimer 'delete-itimer)
-                   (itimer-driver-start 'itimer-driver-start)
-                   (itimer-value 'itimer-value)
-                   (start-itimer 'start-itimer))
-               (unless (or (symbol-value 'itimer-process)
-                           (symbol-value 'itimer-timer))
-                 (funcall itimer-driver-start))
-               ;; Check whether there is a bug to which the difference of
-               ;; the present time and the time when the itimer driver was
-               ;; woken up is subtracted from the initial itimer value.
-               (let* ((inhibit-quit t)
-                      (ctime (current-time))
-                      (itimer-timer-last-wakeup
-                       (prog1
-                           ctime
-                         (setcar ctime (1- (car ctime)))))
-                      (itimer-list nil)
-                      (itimer (funcall start-itimer "pgg-run-at-time"
-                                       'ignore 5)))
-                 (sleep-for 0.1) ;; Accept the timeout interrupt.
-                 (prog1
-                     (> (funcall itimer-value itimer) 0)
-                   (funcall delete-itimer itimer))))
-           (error nil))
-         `(let ((time ,time))
-            (apply #'start-itimer "pgg-run-at-time"
-                   ,function (if time (max time 1e-9) 1e-9)
-                   ,repeat nil t ,args))
-       `(let ((time ,time)
-              (itimers (list nil)))
-          (setcar
-           itimers
-           (apply #'start-itimer "pgg-run-at-time"
-                  (lambda (itimers repeat function &rest args)
-                    (let ((itimer (car itimers)))
-                      (if repeat
-                          (progn
-                            (set-itimer-function
-                             itimer
-                             (lambda (itimer repeat function &rest args)
-                               (set-itimer-restart itimer repeat)
-                               (set-itimer-function itimer function)
-                               (set-itimer-function-arguments itimer args)
-                               (apply function args)))
-                            (set-itimer-function-arguments
-                             itimer
-                             (append (list itimer repeat function) args)))
-                        (set-itimer-function
-                         itimer
-                         (lambda (itimer function &rest args)
-                           (delete-itimer itimer)
-                           (apply function args)))
-                        (set-itimer-function-arguments
-                         itimer
-                         (append (list itimer function) args)))))
-                  1e-9 (if time (max time 1e-9) 1e-9)
-                  nil t itimers ,repeat ,function ,args)))))))
-
-(eval-and-compile
-  (if (featurep 'xemacs)
-      (progn
-       (defun pgg-run-at-time (time repeat function &rest args)
-         "Emulating function run as `run-at-time'.
-TIME should be nil meaning now, or a number of seconds from now.
-Return an itimer object which can be used in either `delete-itimer'
-or `cancel-timer'."
-         (pgg-run-at-time-1 time repeat function args))
-       (defun pgg-cancel-timer (timer)
-         "Emulate cancel-timer for xemacs."
-         (let ((delete-itimer 'delete-itimer))
-           (funcall delete-itimer timer))))
-    (defalias 'pgg-run-at-time 'run-at-time)
-    (defalias 'pgg-cancel-timer 'cancel-timer)))
-
 (defun pgg-invoke (func scheme &rest args)
   (progn
     (require (intern (format "pgg-%s" scheme)))
-    (apply 'funcall (intern (format "pgg-%s-%s" scheme func)) args)))
-
-(put 'pgg-save-coding-system 'lisp-indent-function 2)
+    (apply #'funcall (intern (format "pgg-%s-%s" scheme func)) args)))
 
 (defmacro pgg-save-coding-system (start end &rest body)
+  (declare (indent 2) (debug t))
   `(if (called-interactively-p 'interactive)
        (let ((buffer (current-buffer)))
         (with-temp-buffer
@@ -209,23 +129,16 @@ regulate cache behavior."
   (let* ((key (if notruncate key (pgg-truncate-key-identifier key)))
          (interned-timer-key (intern-soft key pgg-pending-timers))
          (old-timer (symbol-value interned-timer-key))
-         new-timer)
+         ) ;; new-timer
     (when old-timer
         (cancel-timer old-timer)
         (unintern interned-timer-key pgg-pending-timers))
     (set (intern key pgg-passphrase-cache)
          passphrase)
     (set (intern key pgg-pending-timers)
-         (pgg-run-at-time pgg-passphrase-cache-expiry nil
-                           #'pgg-remove-passphrase-from-cache
-                           key notruncate))))
-
-(if (fboundp 'clear-string)
-    (defalias 'pgg-clear-string 'clear-string)
-  (defun pgg-clear-string (string)
-    (fillarray string ?_)))
-
-(declare-function pgg-clear-string "pgg" (string))
+         (run-at-time pgg-passphrase-cache-expiry nil
+                      #'pgg-remove-passphrase-from-cache
+                      key notruncate))))
 
 (defun pgg-remove-passphrase-from-cache (key &optional notruncate)
   "Omit passphrase associated with KEY in time-limited passphrase cache.
@@ -245,10 +158,10 @@ regulate cache behavior."
          (interned-timer-key (intern-soft key pgg-pending-timers))
          (old-timer (symbol-value interned-timer-key)))
     (when passphrase
-      (pgg-clear-string passphrase)
+      (clear-string passphrase)
       (unintern key pgg-passphrase-cache))
     (when old-timer
-      (pgg-cancel-timer old-timer)
+      (cancel-timer old-timer)
       (unintern interned-timer-key pgg-pending-timers))))
 
 (defmacro pgg-convert-lbt-region (start end lbt)
@@ -265,9 +178,8 @@ regulate cache behavior."
        (while (re-search-forward "\r$" pgg-conversion-end t)
          (replace-match ""))))))
 
-(put 'pgg-as-lbt 'lisp-indent-function 3)
-
 (defmacro pgg-as-lbt (start end lbt &rest body)
+  (declare (indent 3) (debug t))
   `(let ((inhibit-read-only t)
         buffer-read-only
         buffer-undo-list)
@@ -277,9 +189,8 @@ regulate cache behavior."
      (push nil buffer-undo-list)
      (ignore-errors (undo))))
 
-(put 'pgg-process-when-success 'lisp-indent-function 0)
-
 (defmacro pgg-process-when-success (&rest body)
+  (declare (indent 0) (debug t))
   `(with-current-buffer pgg-output-buffer
      (if (zerop (buffer-size)) nil ,@body t)))
 
@@ -377,7 +288,7 @@ passphrase cache or user."
 If optional PASSPHRASE is not specified, it will be obtained from the
 passphrase cache or user."
   (interactive "r")
-  (let* ((buf (current-buffer))
+  (let* (;; (buf (current-buffer))
         (status
          (pgg-save-coding-system start end
            (pgg-invoke "decrypt-region" (or pgg-scheme pgg-default-scheme)
diff --git a/lisp/obsolete/rcompile.el b/lisp/obsolete/rcompile.el
index 29931d9..d7020f0 100644
--- a/lisp/obsolete/rcompile.el
+++ b/lisp/obsolete/rcompile.el
@@ -1,4 +1,4 @@
-;;; rcompile.el --- run a compilation on a remote machine
+;;; rcompile.el --- run a compilation on a remote machine  -*- 
lexical-binding: t; -*-
 
 ;; Copyright (C) 1993-1994, 2001-2021 Free Software Foundation, Inc.
 
@@ -76,14 +76,12 @@
 
 (defcustom remote-compile-host nil
   "Host for remote compilations."
-  :type '(choice string (const nil))
-  :group 'remote-compile)
+  :type '(choice string (const nil)))
 
 (defcustom remote-compile-user nil
   "User for remote compilations.
 nil means use the value returned by \\[user-login-name]."
-  :type '(choice string (const nil))
-  :group 'remote-compile)
+  :type '(choice string (const nil)))
 
 (defcustom remote-compile-run-before nil
   "Command to run before compilation.
@@ -91,18 +89,15 @@ This can be used for setting up environment variables,
 since rsh does not invoke the shell as a login shell and files like .login
 \(tcsh) and .bash_profile \(bash) are not run.
 nil means run no commands."
-  :type '(choice string (const nil))
-  :group 'remote-compile)
+  :type '(choice string (const nil)))
 
 (defcustom remote-compile-prompt-for-host nil
   "Non-nil means prompt for host if not available from filename."
-  :type 'boolean
-  :group 'remote-compile)
+  :type 'boolean)
 
 (defcustom remote-compile-prompt-for-user nil
   "Non-nil means prompt for user if not available from filename."
-  :type 'boolean
-  :group 'remote-compile)
+  :type 'boolean)
 
 ;;;; internal variables
 
@@ -123,7 +118,7 @@ nil means run no commands."
   "Compile the current buffer's directory on HOST.  Log in as USER.
 See \\[compile]."
   (interactive
-   (let (host user command prompt l l-host l-user)
+   (let (host user command prompt) ;; l l-host l-user
      (setq prompt (if (stringp remote-compile-host)
                       (format "Compile on host (default %s): "
                               remote-compile-host)
@@ -153,7 +148,7 @@ See \\[compile]."
          (setq remote-compile-user user))
         ((null remote-compile-user)
          (setq remote-compile-user (user-login-name))))
-  (let* (localname ;; Pacify byte-compiler.
+  (let* (;; localname ;; Pacify byte-compiler.
          (compile-command
           (format "%s %s -l %s \"(%scd %s; %s)\""
                  remote-shell-program
diff --git a/lisp/obsolete/s-region.el b/lisp/obsolete/s-region.el
index bcb5279..4d4c39e 100644
--- a/lisp/obsolete/s-region.el
+++ b/lisp/obsolete/s-region.el
@@ -1,4 +1,4 @@
-;;; s-region.el --- set region using shift key
+;;; s-region.el --- set region using shift key  -*- lexical-binding: t; -*-
 
 ;; Copyright (C) 1994-1995, 2001-2021 Free Software Foundation, Inc.
 
@@ -112,11 +112,11 @@ to global keymap."
        [M-next] [M-previous] [M-home] [M-end]))
 
 (or (global-key-binding [C-insert])
-    (global-set-key [C-insert] 'copy-region-as-kill))
+    (global-set-key [C-insert] #'copy-region-as-kill))
 (or (global-key-binding [S-delete])
-    (global-set-key [S-delete] 'kill-region))
+    (global-set-key [S-delete] #'kill-region))
 (or (global-key-binding [S-insert])
-    (global-set-key [S-insert] 'yank))
+    (global-set-key [S-insert] #'yank))
 
 (provide 's-region)
 
diff --git a/lisp/obsolete/sb-image.el b/lisp/obsolete/sb-image.el
index 53ecfb7..e9a507f 100644
--- a/lisp/obsolete/sb-image.el
+++ b/lisp/obsolete/sb-image.el
@@ -1,4 +1,4 @@
-;;; sb-image --- Image management for speedbar
+;;; sb-image --- Image management for speedbar  -*- lexical-binding: t; -*-
 
 ;; Copyright (C) 1999-2003, 2005-2019, 2021 Free Software Foundation,
 ;; Inc.
diff --git a/lisp/obsolete/sregex.el b/lisp/obsolete/sregex.el
index ac5f62d..96d6b7a 100644
--- a/lisp/obsolete/sregex.el
+++ b/lisp/obsolete/sregex.el
@@ -1,4 +1,4 @@
-;;; sregex.el --- symbolic regular expressions
+;;; sregex.el --- symbolic regular expressions  -*- lexical-binding: t; -*-
 
 ;; Copyright (C) 1997-1998, 2000-2021 Free Software Foundation, Inc.
 
@@ -246,15 +246,15 @@
 (defvar sregex--current-sregex nil)
 (defun sregex-info () nil)
 (defmacro sregex-save-match-data (&rest forms) (cons 'save-match-data forms))
-(defun sregex-replace-match (r &optional f l str subexp x)
+(defun sregex-replace-match (r &optional f l str subexp _x)
   (replace-match r f l str subexp))
-(defun sregex-match-string (c &optional i x) (match-string c i))
-(defun sregex-match-string-no-properties (count &optional in-string sregex)
+(defun sregex-match-string (c &optional i _x) (match-string c i))
+(defun sregex-match-string-no-properties (count &optional in-string _sregex)
   (match-string-no-properties count in-string))
-(defun sregex-match-beginning (count &optional sregex) (match-beginning count))
-(defun sregex-match-end (count &optional sregex) (match-end count))
-(defun sregex-match-data (&optional sregex) (match-data))
-(defun sregex-backref-num (n &optional sregex) n)
+(defun sregex-match-beginning (count &optional _sregex) (match-beginning 
count))
+(defun sregex-match-end (count &optional _sregex) (match-end count))
+(defun sregex-match-data (&optional _sregex) (match-data))
+(defun sregex-backref-num (n &optional _sregex) n)
 
 
 (defun sregex (&rest exps)
@@ -525,23 +525,23 @@ has one of the following forms:
           (concat "\\(?:" re "\\)")
         re))))
 
-(defun sregex--group (exps combine) (concat "\\(" (sregex--sequence exps nil) 
"\\)"))
+(defun sregex--group (exps _combine) (concat "\\(" (sregex--sequence exps nil) 
"\\)"))
 
-(defun sregex--backref (exps combine) (concat "\\" (int-to-string (car exps))))
-(defun sregex--opt (exps combine) (concat (sregex--sequence exps 'suffix) "?"))
-(defun sregex--0+ (exps combine) (concat (sregex--sequence exps 'suffix) "*"))
-(defun sregex--1+ (exps combine) (concat (sregex--sequence exps 'suffix) "+"))
+(defun sregex--backref (exps _combine) (concat "\\" (int-to-string (car 
exps))))
+(defun sregex--opt (exps _combine) (concat (sregex--sequence exps 'suffix) 
"?"))
+(defun sregex--0+ (exps _combine) (concat (sregex--sequence exps 'suffix) "*"))
+(defun sregex--1+ (exps _combine) (concat (sregex--sequence exps 'suffix) "+"))
 
-(defun sregex--char (exps combine) (sregex--char-aux nil exps))
-(defun sregex--not-char (exps combine) (sregex--char-aux t exps))
+(defun sregex--char (exps _combine) (sregex--char-aux nil exps))
+(defun sregex--not-char (exps _combine) (sregex--char-aux t exps))
 
-(defun sregex--syntax (exps combine) (format "\\s%c" (car exps)))
-(defun sregex--not-syntax (exps combine) (format "\\S%c" (car exps)))
+(defun sregex--syntax (exps _combine) (format "\\s%c" (car exps)))
+(defun sregex--not-syntax (exps _combine) (format "\\S%c" (car exps)))
 
 (defun sregex--regex (exps combine)
   (if combine (concat "\\(?:" (car exps) "\\)") (car exps)))
 
-(defun sregex--repeat (exps combine)
+(defun sregex--repeat (exps _combine)
   (let* ((min (or (pop exps) 0))
         (minstr (number-to-string min))
         (max (pop exps)))
diff --git a/lisp/obsolete/starttls.el b/lisp/obsolete/starttls.el
index 451c7eb..926248d 100644
--- a/lisp/obsolete/starttls.el
+++ b/lisp/obsolete/starttls.el
@@ -1,4 +1,4 @@
-;;; starttls.el --- STARTTLS functions
+;;; starttls.el --- STARTTLS functions  -*- lexical-binding: t; -*-
 
 ;; Copyright (C) 1999-2021 Free Software Foundation, Inc.
 
@@ -126,28 +126,24 @@
 This program is used when GnuTLS is used, i.e. when
 `starttls-use-gnutls' is non-nil."
   :version "22.1"
-  :type 'string
-  :group 'starttls)
+  :type 'string)
 
 (defcustom starttls-program "starttls"
   "The program to run in a subprocess to open an TLSv1 connection.
 This program is used when the `starttls' command is used,
 i.e. when `starttls-use-gnutls' is nil."
-  :type 'string
-  :group 'starttls)
+  :type 'string)
 
 (defcustom starttls-use-gnutls (not (executable-find starttls-program))
   "Whether to use GnuTLS instead of the `starttls' command."
   :version "22.1"
-  :type 'boolean
-  :group 'starttls)
+  :type 'boolean)
 
 (defcustom starttls-extra-args nil
   "Extra arguments to `starttls-program'.
 These apply when the `starttls' command is used, i.e. when
 `starttls-use-gnutls' is nil."
-  :type '(repeat string)
-  :group 'starttls)
+  :type '(repeat string))
 
 (defcustom starttls-extra-arguments nil
   "Extra arguments to `starttls-gnutls-program'.
@@ -157,14 +153,12 @@ For example, non-TLS compliant servers may require
 \(\"--protocols\" \"ssl3\").  Invoke \"gnutls-cli --help\" to
 find out which parameters are available."
   :version "22.1"
-  :type '(repeat string)
-  :group 'starttls)
+  :type '(repeat string))
 
 (defcustom starttls-process-connection-type nil
   "Value for `process-connection-type' to use when starting STARTTLS process."
   :version "22.1"
-  :type 'boolean
-  :group 'starttls)
+  :type 'boolean)
 
 (defcustom starttls-connect "- Simple Client Mode:\n\n"
   "Regular expression indicating successful connection.
@@ -173,8 +167,7 @@ The default is what GnuTLS's \"gnutls-cli\" outputs."
   ;; in the application read/write phase.  If the logic, or the string
   ;; itself, is modified, this must be updated.
   :version "22.1"
-  :type 'regexp
-  :group 'starttls)
+  :type 'regexp)
 
 (defcustom starttls-failure "\\*\\*\\* Handshake has failed"
   "Regular expression indicating failed TLS handshake.
@@ -182,8 +175,7 @@ The default is what GnuTLS's \"gnutls-cli\" outputs."
   ;; GnuTLS cli.c:do_handshake() prints this string on failure.  If the
   ;; logic, or the string itself, is modified, this must be updated.
   :version "22.1"
-  :type 'regexp
-  :group 'starttls)
+  :type 'regexp)
 
 (defcustom starttls-success "- Compression: "
   "Regular expression indicating completed TLS handshakes.
@@ -193,8 +185,7 @@ The default is what GnuTLS's \"gnutls-cli\" outputs."
   ;; last.  If that logic, or the string itself, is modified, this
   ;; must be updated.
   :version "22.1"
-  :type 'regexp
-  :group 'starttls)
+  :type 'regexp)
 
 (defun starttls-negotiate-gnutls (process)
   "Negotiate TLS on PROCESS opened by `open-starttls-stream'.
@@ -296,9 +287,8 @@ GnuTLS requires a port number."
                            starttls-gnutls-program
                          starttls-program))))
 
-(defalias 'starttls-any-program-available 'starttls-available-p)
-(make-obsolete 'starttls-any-program-available 'starttls-available-p
-              "2011-08-02")
+(define-obsolete-function-alias 'starttls-any-program-available
+  #'starttls-available-p "24.1")
 
 (provide 'starttls)
 
diff --git a/lisp/obsolete/sup-mouse.el b/lisp/obsolete/sup-mouse.el
index f3db27f..4e312e9 100644
--- a/lisp/obsolete/sup-mouse.el
+++ b/lisp/obsolete/sup-mouse.el
@@ -1,4 +1,4 @@
-;;; sup-mouse.el --- supdup mouse support for lisp machines
+;;; sup-mouse.el --- supdup mouse support for lisp machines  -*- 
lexical-binding: t; -*-
 
 ;; Copyright (C) 1985-1986, 2001-2021 Free Software Foundation, Inc.
 
diff --git a/lisp/obsolete/terminal.el b/lisp/obsolete/terminal.el
index bde656d..dbfc79b 100644
--- a/lisp/obsolete/terminal.el
+++ b/lisp/obsolete/terminal.el
@@ -1,4 +1,4 @@
-;;; terminal.el --- terminal emulator for GNU Emacs
+;;; terminal.el --- terminal emulator for GNU Emacs  -*- lexical-binding: t; 
-*-
 
 ;; Copyright (C) 1986-1989, 1993-1994, 2001-2021 Free Software
 ;; Foundation, Inc.
@@ -32,7 +32,7 @@
 
 ;; For information on US government censorship of the Internet, and
 ;; what you can do to bring back freedom of the press, see the web
-;; site http://www.vtw.org/
+;; site https://www.eff.org/ [used to be vtw.org but that link is dead]
 
 ;;; Code:
 
@@ -58,22 +58,19 @@ to the emulator program itself.  Type this character twice 
to send
 it through the emulator.  Type ? after typing it for a list of
 possible commands.
 This variable is local to each terminal-emulator buffer."
-  :type 'character
-  :group 'terminal)
+  :type 'character)
 
 (defcustom terminal-scrolling t ;;>> Setting this to t sort-of defeats my 
whole aim in writing this package...
   "If non-nil, the terminal-emulator will losingly `scroll' when output occurs
 past the bottom of the screen.  If nil, output will win and `wrap' to the top
 of the screen.
 This variable is local to each terminal-emulator buffer."
-  :type 'boolean
-  :group 'terminal)
+  :type 'boolean)
 
 (defcustom terminal-more-processing t
   "If non-nil, do more-processing.
 This variable is local to each terminal-emulator buffer."
-  :type 'boolean
-  :group 'terminal)
+  :type 'boolean)
 
 ;; If you are the sort of loser who uses scrolling without more breaks
 ;; and expects to actually see anything, you should probably set this to
@@ -84,8 +81,7 @@ terminal-emulator before a screen redisplay is forced.
 Set this to a large value for greater throughput,
 set it smaller for more frequent updates but overall slower
 performance."
-  :type 'integer
-  :group 'terminal)
+  :type 'integer)
 
 (defvar terminal-more-break-insertion
   "*** More break -- Press space to continue ***")
@@ -94,7 +90,7 @@ performance."
 (if terminal-meta-map
     nil
   (let ((map (make-sparse-keymap)))
-    (define-key map [t] 'te-pass-through)
+    (define-key map [t] #'te-pass-through)
     (setq terminal-meta-map map)))
 
 (defvar terminal-map nil)
@@ -104,8 +100,8 @@ performance."
     ;; Prevent defining [menu-bar] as te-pass-through
     ;; so we allow the global menu bar to be visible.
     (define-key map [menu-bar] (make-sparse-keymap))
-    (define-key map [t] 'te-pass-through)
-    (define-key map [switch-frame] 'handle-switch-frame)
+    (define-key map [t] #'te-pass-through)
+    (define-key map [switch-frame] #'handle-switch-frame)
     (define-key map "\e" terminal-meta-map)
     ;;(define-key map "\C-l"
     ;;  (lambda () (interactive) (te-pass-through) (redraw-display)))
@@ -115,22 +111,22 @@ performance."
 (if terminal-escape-map
     nil
   (let ((map (make-sparse-keymap)))
-    (define-key map [t] 'undefined)
+    (define-key map [t] #'undefined)
     (let ((s "0"))
       (while (<= (aref s 0) ?9)
-       (define-key map s 'digit-argument)
+       (define-key map s #'digit-argument)
        (aset s 0 (1+ (aref s 0)))))
-    (define-key map "b" 'switch-to-buffer)
-    (define-key map "o" 'other-window)
-    (define-key map "e" 'te-set-escape-char)
-    (define-key map "\C-l" 'redraw-display)
-    (define-key map "\C-o" 'te-flush-pending-output)
-    (define-key map "m" 'te-toggle-more-processing)
-    (define-key map "x" 'te-escape-extended-command)
+    (define-key map "b" #'switch-to-buffer)
+    (define-key map "o" #'other-window)
+    (define-key map "e" #'te-set-escape-char)
+    (define-key map "\C-l" #'redraw-display)
+    (define-key map "\C-o" #'te-flush-pending-output)
+    (define-key map "m" #'te-toggle-more-processing)
+    (define-key map "x" #'te-escape-extended-command)
     ;;>> What use is this?  Why is it in the default terminal-emulator map?
-    (define-key map "w" 'te-edit)
-    (define-key map "?" 'te-escape-help)
-    (define-key map (char-to-string help-char) 'te-escape-help)
+    (define-key map "w" #'te-edit)
+    (define-key map "?" #'te-escape-help)
+    (define-key map (char-to-string help-char) #'te-escape-help)
     (setq terminal-escape-map map)))
 
 (defvar te-escape-command-alist nil)
@@ -161,14 +157,14 @@ performance."
 (if terminal-more-break-map
     nil
   (let ((map (make-sparse-keymap)))
-    (define-key map [t] 'te-more-break-unread)
-    (define-key map (char-to-string help-char) 'te-more-break-help)
-    (define-key map " " 'te-more-break-resume)
-    (define-key map "\C-l" 'redraw-display)
-    (define-key map "\C-o" 'te-more-break-flush-pending-output)
+    (define-key map [t] #'te-more-break-unread)
+    (define-key map (char-to-string help-char) #'te-more-break-help)
+    (define-key map " " #'te-more-break-resume)
+    (define-key map "\C-l" #'redraw-display)
+    (define-key map "\C-o" #'te-more-break-flush-pending-output)
     ;;>>> this isn't right
-    ;(define-key map "\^?" 'te-more-break-flush-pending-output) ;DEL
-    (define-key map "\r" 'te-more-break-advance-one-line)
+    ;(define-key map "\^?" #'te-more-break-flush-pending-output) ;DEL
+    (define-key map "\r" #'te-more-break-advance-one-line)
 
     (setq terminal-more-break-map map)))
 
@@ -525,7 +521,7 @@ lets you type a terminal emulator command."
 (if terminal-edit-map
     nil
   (setq terminal-edit-map (make-sparse-keymap))
-  (define-key terminal-edit-map "\C-c\C-c" 'terminal-cease-edit))
+  (define-key terminal-edit-map "\C-c\C-c" #'terminal-cease-edit))
 
 ;; Terminal Edit mode is suitable only for specially formatted data.
 (put 'terminal-edit-mode 'mode-class 'special)
@@ -1140,10 +1136,10 @@ subprocess started."
                             ;; Then finally start the program we wanted.
                             (format "%s; exec %s"
                                     te-stty-string
-                                    (mapconcat 'te-quote-arg-for-sh
+                                    (mapconcat #'te-quote-arg-for-sh
                                                (cons program args) " "))))
-       (set-process-filter te-process 'te-filter)
-       (set-process-sentinel te-process 'te-sentinel))
+       (set-process-filter te-process #'te-filter)
+       (set-process-sentinel te-process #'te-sentinel))
     (error (fundamental-mode)
           (signal (car err) (cdr err))))
   (setq inhibit-quit t)                        ;sport death
@@ -1151,8 +1147,8 @@ subprocess started."
   (run-hooks 'terminal-mode-hook)
   (message "Entering Emacs terminal-emulator...  Type %s %s for help"
           (single-key-description terminal-escape-char)
-          (mapconcat 'single-key-description
-                     (where-is-internal 'te-escape-help terminal-escape-map t)
+          (mapconcat #'single-key-description
+                     (where-is-internal #'te-escape-help terminal-escape-map t)
                      " ")))
 
 
@@ -1292,7 +1288,7 @@ in the directory specified by `te-terminfo-directory'."
                           (directory-file-name te-terminfo-directory))
                   process-environment)))
        (set-process-sentinel (start-process "tic" nil "tic" file-name)
-                             'te-tic-sentinel))))
+                             #'te-tic-sentinel))))
     (directory-file-name te-terminfo-directory))
 
 (defun te-create-termcap ()
diff --git a/lisp/obsolete/tls.el b/lisp/obsolete/tls.el
index 67a497f..5cba18d 100644
--- a/lisp/obsolete/tls.el
+++ b/lisp/obsolete/tls.el
@@ -1,4 +1,4 @@
-;;; tls.el --- TLS/SSL support via wrapper around GnuTLS
+;;; tls.el --- TLS/SSL support via wrapper around GnuTLS  -*- lexical-binding: 
t; -*-
 
 ;; Copyright (C) 1996-1999, 2002-2021 Free Software Foundation, Inc.
 
@@ -70,8 +70,7 @@
 Client data stream begins after the last character this matches.
 The default matches the output of \"gnutls-cli\" (version 2.0.1)."
   :version "22.2"
-  :type 'regexp
-  :group 'tls)
+  :type 'regexp)
 
 (defcustom tls-program
   '("gnutls-cli --x509cafile %t -p %p %h"
@@ -104,22 +103,19 @@ successful negotiation."
          (repeat :inline t :tag "Other" (string)))
     (list :tag "List of commands"
          (repeat :tag "Command" (string))))
-  :version "26.1"                       ; remove s_client
-  :group 'tls)
+  :version "26.1")
 
 (defcustom tls-process-connection-type nil
   "Value for `process-connection-type' to use when starting TLS process."
   :version "22.1"
-  :type 'boolean
-  :group 'tls)
+  :type 'boolean)
 
 (defcustom tls-success "- Handshake was completed\\|SSL handshake has read "
   "Regular expression indicating completed TLS handshakes.
 The default is what GnuTLS's \"gnutls-cli\" outputs."
 ;; or OpenSSL's \"openssl s_client\"
   :version "22.1"
-  :type 'regexp
-  :group 'tls)
+  :type 'regexp)
 
 (defcustom tls-checktrust nil
   "Indicate if certificates should be checked against trusted root certs.
@@ -137,8 +133,7 @@ consider trustworthy, e.g.:
   :type '(choice (const :tag "Always" t)
                 (const :tag "Never" nil)
                 (const :tag "Ask" ask))
-  :version "23.1" ;; No Gnus
-  :group 'tls)
+  :version "23.1")
 
 (defcustom tls-untrusted
   "- Peer's certificate is NOT trusted\\|Verify return code: \\([^0] \\|.[^ 
]\\)"
@@ -147,8 +142,7 @@ The default is what GnuTLS's \"gnutls-cli\" returns in the 
event of
 unsuccessful verification."
 ;; or OpenSSL's \"openssl s_client\"
   :type 'regexp
-  :version "23.1" ;; No Gnus
-  :group 'tls)
+  :version "23.1")
 
 (defcustom tls-hostmismatch
   "# The hostname in the certificate does NOT match"
@@ -158,20 +152,13 @@ name of the host you are connecting to, gnutls-cli issues 
a
 warning to this effect.  There is no such feature in openssl.  Set
 this to nil if you want to ignore host name mismatches."
   :type 'regexp
-  :version "23.1" ;; No Gnus
-  :group 'tls)
+  :version "23.1")
 
 (defcustom tls-certtool-program "certtool"
   "Name of GnuTLS certtool.
 Used by `tls-certificate-information'."
   :version "22.1"
-  :type 'string
-  :group 'tls)
-
-(defalias 'tls-format-message
-  (if (fboundp 'format-message) 'format-message
-    ;; for Emacs < 25, and XEmacs, don't worry about quote translation.
-    'format))
+  :type 'string)
 
 (defun tls-certificate-information (der)
   "Parse X.509 certificate in DER format into an assoc list."
@@ -272,7 +259,7 @@ Fourth arg PORT is an integer specifying a port to connect 
to."
                             (message "The certificate presented by `%s' is \
 NOT trusted." host))
                        (not (yes-or-no-p
-                             (tls-format-message "\
+                             (format-message "\
 The certificate presented by `%s' is NOT trusted. Accept anyway? " host)))))
                  (and tls-hostmismatch
                       (save-excursion
diff --git a/lisp/obsolete/tpu-edt.el b/lisp/obsolete/tpu-edt.el
index 78d88cf..1340618 100644
--- a/lisp/obsolete/tpu-edt.el
+++ b/lisp/obsolete/tpu-edt.el
@@ -1,4 +1,4 @@
-;;; tpu-edt.el --- Emacs emulating TPU emulating EDT
+;;; tpu-edt.el --- Emacs emulating TPU emulating EDT  -*- lexical-binding: t; 
-*-
 
 ;; Copyright (C) 1993-1995, 2000-2021 Free Software Foundation, Inc.
 
@@ -289,18 +289,15 @@
 ;;;
 (defcustom tpu-kill-buffers-silently nil
   "If non-nil, TPU-edt kills modified buffers without asking."
-  :type 'boolean
-  :group 'tpu)
+  :type 'boolean)
 
 (defcustom tpu-percent-scroll 75
   "Percentage of the screen to scroll for next/previous screen commands."
-  :type 'integer
-  :group 'tpu)
+  :type 'integer)
 
 (defcustom tpu-pan-columns 16
   "Number of columns the tpu-pan functions scroll left or right."
-  :type 'integer
-  :group 'tpu)
+  :type 'integer)
 
 
 ;;;
@@ -313,17 +310,17 @@
     ;; that term/*.el does its job to map the escape sequence to the right
     ;; key-symbol.
 
-    (define-key map [up]    'tpu-move-to-beginning)    ; up-arrow
-    (define-key map [down]  'tpu-move-to-end)          ; down-arrow
-    (define-key map [right] 'end-of-line)              ; right-arrow
-    (define-key map [left]  'beginning-of-line)                ; left-arrow
+    (define-key map [up]    #'tpu-move-to-beginning)   ; up-arrow
+    (define-key map [down]  #'tpu-move-to-end)         ; down-arrow
+    (define-key map [right] #'end-of-line)             ; right-arrow
+    (define-key map [left]  #'beginning-of-line)               ; left-arrow
 
     ;; (define-key map [find]   nil)                   ; Find
     ;; (define-key map [insert] nil)                   ; Insert Here
-    (define-key map [delete] 'tpu-store-text)          ; Remove
-    (define-key map [select] 'tpu-unselect)            ; Select
-    (define-key map [prior]  'tpu-previous-window)     ; Prev Screen
-    (define-key map [next]   'tpu-next-window)         ; Next Screen
+    (define-key map [delete] #'tpu-store-text)         ; Remove
+    (define-key map [select] #'tpu-unselect)           ; Select
+    (define-key map [prior]  #'tpu-previous-window)    ; Prev Screen
+    (define-key map [next]   #'tpu-next-window)                ; Next Screen
 
     ;; (define-key map [f1] nil)                       ; F1
     ;; (define-key map [f2] nil)                       ; F2
@@ -339,45 +336,45 @@
     ;; (define-key map [f12] nil)                      ; F12
     ;; (define-key map [f13] nil)                      ; F13
     ;; (define-key map [f14] nil)                      ; F14
-    (define-key map [help] 'describe-bindings)         ; HELP
+    (define-key map [help] #'describe-bindings)                ; HELP
     ;; (define-key map [menu] nil)                     ; DO
-    (define-key map [f17] 'tpu-drop-breadcrumb)                ; F17
+    (define-key map [f17] #'tpu-drop-breadcrumb)       ; F17
     ;; (define-key map [f18] nil)                      ; F18
     ;; (define-key map [f19] nil)                      ; F19
     ;; (define-key map [f20] nil)                      ; F20
 
-    (define-key map [kp-f1] 'keyboard-quit)            ; PF1
-    (define-key map [kp-f2] 'help-for-help)            ; PF2
-    (define-key map [kp-f3] 'tpu-search)               ; PF3
-    (define-key map [kp-f4] 'tpu-undelete-lines)       ; PF4
-    (define-key map [kp-0] 'open-line)                 ; KP0
-    (define-key map [kp-1] 'tpu-change-case)           ; KP1
-    (define-key map [kp-2] 'tpu-delete-to-eol)         ; KP2
-    (define-key map [kp-3] 'tpu-special-insert)                ; KP3
-    (define-key map [kp-4] 'tpu-move-to-end)           ; KP4
-    (define-key map [kp-5] 'tpu-move-to-beginning)     ; KP5
-    (define-key map [kp-6] 'tpu-paste)                 ; KP6
-    (define-key map [kp-7] 'execute-extended-command)  ; KP7
-    (define-key map [kp-8] 'tpu-fill)                  ; KP8
-    (define-key map [kp-9] 'tpu-replace)               ; KP9
-    (define-key map [kp-subtract] 'tpu-undelete-words) ; KP-
-    (define-key map [kp-separator] 'tpu-undelete-char) ; KP,
-    (define-key map [kp-decimal] 'tpu-unselect)                ; KP.
-    (define-key map [kp-enter] 'tpu-substitute)                ; KPenter
+    (define-key map [kp-f1] #'keyboard-quit)           ; PF1
+    (define-key map [kp-f2] #'help-for-help)           ; PF2
+    (define-key map [kp-f3] #'tpu-search)              ; PF3
+    (define-key map [kp-f4] #'tpu-undelete-lines)      ; PF4
+    (define-key map [kp-0] #'open-line)                        ; KP0
+    (define-key map [kp-1] #'tpu-change-case)          ; KP1
+    (define-key map [kp-2] #'tpu-delete-to-eol)                ; KP2
+    (define-key map [kp-3] #'tpu-special-insert)       ; KP3
+    (define-key map [kp-4] #'tpu-move-to-end)          ; KP4
+    (define-key map [kp-5] #'tpu-move-to-beginning)    ; KP5
+    (define-key map [kp-6] #'tpu-paste)                        ; KP6
+    (define-key map [kp-7] #'execute-extended-command) ; KP7
+    (define-key map [kp-8] #'tpu-fill)                 ; KP8
+    (define-key map [kp-9] #'tpu-replace)              ; KP9
+    (define-key map [kp-subtract] #'tpu-undelete-words)        ; KP-
+    (define-key map [kp-separator] #'tpu-undelete-char)        ; KP,
+    (define-key map [kp-decimal] #'tpu-unselect)       ; KP.
+    (define-key map [kp-enter] #'tpu-substitute)       ; KPenter
 
     ;;
-    (define-key map "\C-A" 'tpu-toggle-overwrite-mode) ; ^A
+    (define-key map "\C-A" #'tpu-toggle-overwrite-mode)        ; ^A
     ;; (define-key map "\C-B" nil)                     ; ^B
     ;; (define-key map "\C-C" nil)                     ; ^C
     ;; (define-key map "\C-D" nil)                     ; ^D
     ;; (define-key map "\C-E" nil)                     ; ^E
-    (define-key map "\C-F" 'set-visited-file-name)     ; ^F
-    (define-key map "\C-g" 'keyboard-quit)             ; safety first
-    (define-key map "\C-h" 'delete-other-windows)      ; BS
-    (define-key map "\C-i" 'other-window)              ; TAB
+    (define-key map "\C-F" #'set-visited-file-name)    ; ^F
+    (define-key map "\C-g" #'keyboard-quit)            ; safety first
+    (define-key map "\C-h" #'delete-other-windows)     ; BS
+    (define-key map "\C-i" #'other-window)             ; TAB
     ;; (define-key map "\C-J" nil)                     ; ^J
-    (define-key map "\C-K" 'tpu-define-macro-key)      ; ^K
-    (define-key map "\C-l" 'downcase-region)           ; ^L
+    (define-key map "\C-K" #'tpu-define-macro-key)     ; ^K
+    (define-key map "\C-l" #'downcase-region)          ; ^L
     ;; (define-key map "\C-M" nil)                     ; ^M
     ;; (define-key map "\C-N" nil)                     ; ^N
     ;; (define-key map "\C-O" nil)                     ; ^O
@@ -385,104 +382,104 @@
     ;; (define-key map "\C-Q" nil)                     ; ^Q
     ;; (define-key map "\C-R" nil)                     ; ^R
     ;; (define-key map "\C-S" nil)                     ; ^S
-    (define-key map "\C-T" 'tpu-toggle-control-keys)   ; ^T
-    (define-key map "\C-u" 'upcase-region)             ; ^U
+    (define-key map "\C-T" #'tpu-toggle-control-keys)  ; ^T
+    (define-key map "\C-u" #'upcase-region)            ; ^U
     ;; (define-key map "\C-V" nil)                     ; ^V
-    (define-key map "\C-w" 'tpu-write-current-buffers) ; ^W
+    (define-key map "\C-w" #'tpu-write-current-buffers)        ; ^W
     ;; (define-key map "\C-X" nil)                     ; ^X
     ;; (define-key map "\C-Y" nil)                     ; ^Y
     ;; (define-key map "\C-Z" nil)                     ; ^Z
-    (define-key map " " 'undo)                         ; SPC
+    (define-key map " " #'undo)                                ; SPC
     ;; (define-key map "!" nil)                                ; !
     ;; (define-key map "#" nil)                                ; #
-    (define-key map "$" 'tpu-add-at-eol)               ; $
-    (define-key map "%" 'tpu-goto-percent)             ; %
+    (define-key map "$" #'tpu-add-at-eol)              ; $
+    (define-key map "%" #'tpu-goto-percent)            ; %
     ;; (define-key map "&" nil)                                ; &
     ;; (define-key map "(" nil)                                ; (
     ;; (define-key map ")" nil)                                ; )
-    (define-key map "*" 'tpu-toggle-regexp)            ; *
+    (define-key map "*" #'tpu-toggle-regexp)           ; *
     ;; (define-key map "+" nil)                                ; +
-    (define-key map "," 'tpu-goto-breadcrumb)          ; ,
-    (define-key map "-" 'negative-argument)            ; -
-    (define-key map "." 'tpu-drop-breadcrumb)          ; .
-    (define-key map "/" 'tpu-emacs-replace)            ; /
-    (define-key map "0" 'digit-argument)               ; 0
-    (define-key map "1" 'digit-argument)               ; 1
-    (define-key map "2" 'digit-argument)               ; 2
-    (define-key map "3" 'digit-argument)               ; 3
-    (define-key map "4" 'digit-argument)               ; 4
-    (define-key map "5" 'digit-argument)               ; 5
-    (define-key map "6" 'digit-argument)               ; 6
-    (define-key map "7" 'digit-argument)               ; 7
-    (define-key map "8" 'digit-argument)               ; 8
-    (define-key map "9" 'digit-argument)               ; 9
+    (define-key map "," #'tpu-goto-breadcrumb)         ; ,
+    (define-key map "-" #'negative-argument)           ; -
+    (define-key map "." #'tpu-drop-breadcrumb)         ; .
+    (define-key map "/" #'tpu-emacs-replace)           ; /
+    (define-key map "0" #'digit-argument)              ; 0
+    (define-key map "1" #'digit-argument)              ; 1
+    (define-key map "2" #'digit-argument)              ; 2
+    (define-key map "3" #'digit-argument)              ; 3
+    (define-key map "4" #'digit-argument)              ; 4
+    (define-key map "5" #'digit-argument)              ; 5
+    (define-key map "6" #'digit-argument)              ; 6
+    (define-key map "7" #'digit-argument)              ; 7
+    (define-key map "8" #'digit-argument)              ; 8
+    (define-key map "9" #'digit-argument)              ; 9
     ;; (define-key map ":" nil)                                ; :
-    (define-key map ";" 'tpu-trim-line-ends)           ; ;
+    (define-key map ";" #'tpu-trim-line-ends)          ; ;
     ;; (define-key map "<" nil)                                ; <
     ;; (define-key map "=" nil)                                ; =
     ;; (define-key map ">" nil)                                ; >
-    (define-key map "?" 'tpu-spell-check)              ; ?
-    ;; (define-key map "A" 'tpu-toggle-newline-and-indent) ; A
-    ;; (define-key map "B" 'tpu-next-buffer)           ; B
-    ;; (define-key map "C" 'repeat-complex-command)    ; C
-    ;; (define-key map "D" 'shell-command)             ; D
-    ;; (define-key map "E" 'tpu-exit)                  ; E
-    ;; (define-key map "F" 'tpu-cursor-free-mode)      ; F
-    ;; (define-key map "G" 'tpu-get)                   ; G
+    (define-key map "?" #'tpu-spell-check)             ; ?
+    ;; (define-key map "A" #'tpu-toggle-newline-and-indent) ; A
+    ;; (define-key map "B" #'tpu-next-buffer)          ; B
+    ;; (define-key map "C" #'repeat-complex-command)   ; C
+    ;; (define-key map "D" #'shell-command)            ; D
+    ;; (define-key map "E" #'tpu-exit)                 ; E
+    ;; (define-key map "F" #'tpu-cursor-free-mode)     ; F
+    ;; (define-key map "G" #'tpu-get)                  ; G
     ;; (define-key map "H" nil)                                ; H
-    ;; (define-key map "I" 'tpu-include)               ; I
-    ;; (define-key map "K" 'tpu-kill-buffer)           ; K
-    (define-key map "L" 'tpu-what-line)                        ; L
-    ;; (define-key map "M" 'buffer-menu)               ; M
-    ;; (define-key map "N" 'tpu-next-file-buffer)      ; N
-    ;; (define-key map "O" 'occur)                     ; O
-    (define-key map "P" 'lpr-buffer)                   ; P
-    ;; (define-key map "Q" 'tpu-quit)                  ; Q
-    ;; (define-key map "R" 'tpu-toggle-rectangle)      ; R
-    ;; (define-key map "S" 'replace)                   ; S
-    ;; (define-key map "T" 'tpu-line-to-top-of-window) ; T
-    ;; (define-key map "U" 'undo)                      ; U
-    ;; (define-key map "V" 'tpu-version)               ; V
-    ;; (define-key map "W" 'save-buffer)               ; W
-    ;; (define-key map "X" 'tpu-save-all-buffers-kill-emacs) ; X
-    ;; (define-key map "Y" 'copy-region-as-kill)       ; Y
-    ;; (define-key map "Z" 'suspend-emacs)             ; Z
-    (define-key map "[" 'blink-matching-open)          ; [
+    ;; (define-key map "I" #'tpu-include)              ; I
+    ;; (define-key map "K" #'tpu-kill-buffer)          ; K
+    (define-key map "L" #'tpu-what-line)               ; L
+    ;; (define-key map "M" #'buffer-menu)              ; M
+    ;; (define-key map "N" #'tpu-next-file-buffer)     ; N
+    ;; (define-key map "O" #'occur)                    ; O
+    (define-key map "P" #'lpr-buffer)                  ; P
+    ;; (define-key map "Q" #'tpu-quit)                 ; Q
+    ;; (define-key map "R" #'tpu-toggle-rectangle)     ; R
+    ;; (define-key map "S" #'replace)                  ; S
+    ;; (define-key map "T" #'tpu-line-to-top-of-window)        ; T
+    ;; (define-key map "U" #'undo)                     ; U
+    ;; (define-key map "V" #'tpu-version)              ; V
+    ;; (define-key map "W" #'save-buffer)              ; W
+    ;; (define-key map "X" #'tpu-save-all-buffers-kill-emacs) ; X
+    ;; (define-key map "Y" #'copy-region-as-kill)      ; Y
+    ;; (define-key map "Z" #'suspend-emacs)            ; Z
+    (define-key map "[" #'blink-matching-open)         ; [
     ;; (define-key map "\\" nil)                       ; \
-    (define-key map "]" 'blink-matching-open)          ; ]
-    (define-key map "^" 'tpu-add-at-bol)               ; ^
-    (define-key map "_" 'split-window-below)           ; -
-    (define-key map "`" 'what-line)                    ; `
-    (define-key map "a" 'tpu-toggle-newline-and-indent)        ; a
-    (define-key map "b" 'tpu-next-buffer)              ; b
-    (define-key map "c" 'repeat-complex-command)       ; c
-    (define-key map "d" 'shell-command)                        ; d
-    (define-key map "e" 'tpu-exit)                     ; e
-    (define-key map "f" 'tpu-cursor-free-mode)         ; f
-    (define-key map "g" 'tpu-get)                      ; g
+    (define-key map "]" #'blink-matching-open)         ; ]
+    (define-key map "^" #'tpu-add-at-bol)              ; ^
+    (define-key map "_" #'split-window-below)          ; -
+    (define-key map "`" #'what-line)                   ; `
+    (define-key map "a" #'tpu-toggle-newline-and-indent)       ; a
+    (define-key map "b" #'tpu-next-buffer)             ; b
+    (define-key map "c" #'repeat-complex-command)      ; c
+    (define-key map "d" #'shell-command)                       ; d
+    (define-key map "e" #'tpu-exit)                    ; e
+    (define-key map "f" #'tpu-cursor-free-mode)                ; f
+    (define-key map "g" #'tpu-get)                     ; g
     ;; (define-key map "h" nil)                                ; h
-    (define-key map "i" 'tpu-include)                  ; i
-    (define-key map "k" 'tpu-kill-buffer)              ; k
-    (define-key map "l" 'goto-line)                    ; l
-    (define-key map "m" 'buffer-menu)                  ; m
-    (define-key map "n" 'tpu-next-file-buffer)         ; n
-    (define-key map "o" 'occur)                                ; o
-    (define-key map "p" 'lpr-region)                   ; p
-    (define-key map "q" 'tpu-quit)                     ; q
-    (define-key map "r" 'tpu-toggle-rectangle)         ; r
-    (define-key map "s" 'replace)                      ; s
-    (define-key map "t" 'tpu-line-to-top-of-window)    ; t
-    (define-key map "u" 'undo)                         ; u
-    (define-key map "v" 'tpu-version)                  ; v
-    (define-key map "w" 'save-buffer)                  ; w
-    (define-key map "x" 'tpu-save-all-buffers-kill-emacs) ; x
-    (define-key map "y" 'copy-region-as-kill)          ; y
-    (define-key map "z" 'suspend-emacs)                        ; z
+    (define-key map "i" #'tpu-include)                 ; i
+    (define-key map "k" #'tpu-kill-buffer)             ; k
+    (define-key map "l" #'goto-line)                   ; l
+    (define-key map "m" #'buffer-menu)                 ; m
+    (define-key map "n" #'tpu-next-file-buffer)                ; n
+    (define-key map "o" #'occur)                               ; o
+    (define-key map "p" #'lpr-region)                  ; p
+    (define-key map "q" #'tpu-quit)                    ; q
+    (define-key map "r" #'tpu-toggle-rectangle)                ; r
+    (define-key map "s" #'replace)                     ; s
+    (define-key map "t" #'tpu-line-to-top-of-window)   ; t
+    (define-key map "u" #'undo)                                ; u
+    (define-key map "v" #'tpu-version)                 ; v
+    (define-key map "w" #'save-buffer)                 ; w
+    (define-key map "x" #'tpu-save-all-buffers-kill-emacs) ; x
+    (define-key map "y" #'copy-region-as-kill)         ; y
+    (define-key map "z" #'suspend-emacs)                       ; z
     ;; (define-key map "{" nil)                                ; {
-    (define-key map "|" 'split-window-right)           ; |
+    (define-key map "|" #'split-window-right)          ; |
     ;; (define-key map "}" nil)                                ; }
-    (define-key map "~" 'exchange-point-and-mark)      ; ~
-    (define-key map "\177" 'delete-window)             ; <X]
+    (define-key map "~" #'exchange-point-and-mark)     ; ~
+    (define-key map "\177" #'delete-window)            ; <X]
     map)
   "Maps the function keys on the VT100 keyboard preceded by PF1.
 GOLD is the ASCII 7-bit escape sequence <ESC>OP.")
@@ -492,12 +489,12 @@ GOLD is the ASCII 7-bit escape sequence <ESC>OP.")
 
     ;; Previously defined in CSI-map.  We now presume that term/*.el does
     ;; its job to map the escape sequence to the right key-symbol.
-    (define-key map [find]   'tpu-search)              ; Find
-    (define-key map [insert] 'tpu-paste)               ; Insert Here
-    (define-key map [delete] 'tpu-cut)                 ; Remove
-    (define-key map [select] 'tpu-select)              ; Select
-    (define-key map [prior]  'tpu-scroll-window-down)  ; Prev Screen
-    (define-key map [next]   'tpu-scroll-window-up)    ; Next Screen
+    (define-key map [find]   #'tpu-search)             ; Find
+    (define-key map [insert] #'tpu-paste)              ; Insert Here
+    (define-key map [delete] #'tpu-cut)                        ; Remove
+    (define-key map [select] #'tpu-select)             ; Select
+    (define-key map [prior]  #'tpu-scroll-window-down) ; Prev Screen
+    (define-key map [next]   #'tpu-scroll-window-up)   ; Next Screen
 
     ;; (define-key map [f1] nil)                       ; F1
     ;; (define-key map [f2] nil)                       ; F2
@@ -508,14 +505,14 @@ GOLD is the ASCII 7-bit escape sequence <ESC>OP.")
     ;; (define-key map [f7] nil)                       ; F7
     ;; (define-key map [f8] nil)                       ; F8
     ;; (define-key map [f9] nil)                       ; F9
-    (define-key map [f10] 'tpu-exit)                   ; F10
-    (define-key map [f11] 'tpu-insert-escape)          ; F11 (ESC)
-    (define-key map [f12] 'tpu-next-beginning-of-line) ; F12 (BS)
-    (define-key map [f13] 'tpu-delete-previous-word)   ; F13 (LF)
-    (define-key map [f14] 'tpu-toggle-overwrite-mode)  ; F14
-    (define-key map [help] 'tpu-help)                  ; HELP
-    (define-key map [menu] 'execute-extended-command)  ; DO
-    (define-key map [f17] 'tpu-goto-breadcrumb)                ; F17
+    (define-key map [f10] #'tpu-exit)                  ; F10
+    (define-key map [f11] #'tpu-insert-escape)         ; F11 (ESC)
+    (define-key map [f12] #'tpu-next-beginning-of-line)        ; F12 (BS)
+    (define-key map [f13] #'tpu-delete-previous-word)  ; F13 (LF)
+    (define-key map [f14] #'tpu-toggle-overwrite-mode) ; F14
+    (define-key map [help] #'tpu-help)                 ; HELP
+    (define-key map [menu] #'execute-extended-command) ; DO
+    (define-key map [f17] #'tpu-goto-breadcrumb)       ; F17
     ;; (define-key map [f18] nil)                      ; F18
     ;; (define-key map [f19] nil)                      ; F19
     ;; (define-key map [f20] nil)                      ; F20
@@ -525,28 +522,28 @@ GOLD is the ASCII 7-bit escape sequence <ESC>OP.")
     ;; its job to map the escape sequence to the right key-symbol.
     (define-key map [kp-f1] tpu-gold-map)              ; GOLD map
     ;;
-    (define-key map [up]    'tpu-previous-line)                ; up
-    (define-key map [down]  'tpu-next-line)            ; down
-    (define-key map [right] 'tpu-forward-char)         ; right
-    (define-key map [left]  'tpu-backward-char)                ; left
-
-    (define-key map [kp-f2] 'tpu-help)                 ; PF2
-    (define-key map [kp-f3] 'tpu-search-again)         ; PF3
-    (define-key map [kp-f4] 'tpu-delete-current-line)  ; PF4
-    (define-key map [kp-0] 'tpu-line)                  ; KP0
-    (define-key map [kp-1] 'tpu-word)                  ; KP1
-    (define-key map [kp-2] 'tpu-end-of-line)           ; KP2
-    (define-key map [kp-3] 'tpu-char)                  ; KP3
-    (define-key map [kp-4] 'tpu-advance-direction)     ; KP4
-    (define-key map [kp-5] 'tpu-backup-direction)      ; KP5
-    (define-key map [kp-6] 'tpu-cut)                   ; KP6
-    (define-key map [kp-7] 'tpu-page)                  ; KP7
-    (define-key map [kp-8] 'tpu-scroll-window)         ; KP8
-    (define-key map [kp-9] 'tpu-append-region)         ; KP9
-    (define-key map [kp-subtract] 'tpu-delete-current-word) ; KP-
-    (define-key map [kp-separator] 'tpu-delete-current-char) ; KP,
-    (define-key map [kp-decimal] 'tpu-select)          ; KP.
-    (define-key map [kp-enter] 'newline)               ; KPenter
+    (define-key map [up]    #'tpu-previous-line)               ; up
+    (define-key map [down]  #'tpu-next-line)           ; down
+    (define-key map [right] #'tpu-forward-char)                ; right
+    (define-key map [left]  #'tpu-backward-char)               ; left
+
+    (define-key map [kp-f2] #'tpu-help)                        ; PF2
+    (define-key map [kp-f3] #'tpu-search-again)                ; PF3
+    (define-key map [kp-f4] #'tpu-delete-current-line) ; PF4
+    (define-key map [kp-0] #'tpu-line)                 ; KP0
+    (define-key map [kp-1] #'tpu-word)                 ; KP1
+    (define-key map [kp-2] #'tpu-end-of-line)          ; KP2
+    (define-key map [kp-3] #'tpu-char)                 ; KP3
+    (define-key map [kp-4] #'tpu-advance-direction)    ; KP4
+    (define-key map [kp-5] #'tpu-backup-direction)     ; KP5
+    (define-key map [kp-6] #'tpu-cut)                  ; KP6
+    (define-key map [kp-7] #'tpu-page)                 ; KP7
+    (define-key map [kp-8] #'tpu-scroll-window)                ; KP8
+    (define-key map [kp-9] #'tpu-append-region)                ; KP9
+    (define-key map [kp-subtract] #'tpu-delete-current-word) ; KP-
+    (define-key map [kp-separator] #'tpu-delete-current-char) ; KP,
+    (define-key map [kp-decimal] #'tpu-select)         ; KP.
+    (define-key map [kp-enter] #'newline)              ; KPenter
 
     map)
   "TPU-edt global keymap.")
@@ -883,7 +880,7 @@ With argument, fill and justify."
 if no region is selected."
   (interactive)
   (let ((m (tpu-mark)))
-    (apply 'ispell-region
+    (apply #'ispell-region
            (if m
                (if (> m (point)) (list (point) m)
                  (list m (point)))
@@ -970,14 +967,14 @@ and the total number of lines in the buffer."
 ;;;###autoload
 (define-minor-mode tpu-edt-mode
   "Toggle TPU/edt emulation on or off."
-  :global t :group 'tpu
+  :global t
   (if tpu-edt-mode (tpu-edt-on) (tpu-edt-off)))
 
-(defalias 'TPU-EDT-MODE 'tpu-edt-mode)
+(defalias 'TPU-EDT-MODE #'tpu-edt-mode)
 
 ;;;###autoload
-(defalias 'tpu-edt 'tpu-edt-on)
-(defalias 'TPU-EDT 'tpu-edt-on)
+(defalias 'tpu-edt #'tpu-edt-on)
+(defalias 'TPU-EDT #'tpu-edt-on)
 
 ;; Note:  The following functions have no `tpu-' prefix.  This is unavoidable.
 ;;        The real TPU/edt editor has interactive commands with these names,
@@ -985,42 +982,42 @@ and the total number of lines in the buffer."
 ;;        to work.  Therefore it really is necessary to define these functions,
 ;;        even in cases where they redefine existing Emacs functions.
 
-(defalias 'exit 'tpu-exit)
-(defalias 'EXIT 'tpu-exit)
+(defalias 'exit #'tpu-exit)
+(defalias 'EXIT #'tpu-exit)
 
-(defalias 'Get 'tpu-get)
-(defalias 'GET 'tpu-get)
+(defalias 'Get #'tpu-get)
+(defalias 'GET #'tpu-get)
 
-(defalias 'include 'tpu-include)
-(defalias 'INCLUDE 'tpu-include)
+(defalias 'include #'tpu-include)
+(defalias 'INCLUDE #'tpu-include)
 
-(defalias 'quit 'tpu-quit)
-(defalias 'QUIT 'tpu-quit)
+(defalias 'quit #'tpu-quit)
+(defalias 'QUIT #'tpu-quit)
 
-(defalias 'spell 'tpu-spell-check)
-(defalias 'SPELL 'tpu-spell-check)
+(defalias 'spell #'tpu-spell-check)
+(defalias 'SPELL #'tpu-spell-check)
 
-(defalias 'what\ line 'tpu-what-line)
-(defalias 'WHAT\ LINE 'tpu-what-line)
+(defalias 'what\ line #'tpu-what-line)
+(defalias 'WHAT\ LINE #'tpu-what-line)
 
-(defalias 'replace 'tpu-lm-replace)
-(defalias 'REPLACE 'tpu-lm-replace)
+(defalias 'replace #'tpu-lm-replace)
+(defalias 'REPLACE #'tpu-lm-replace)
 
-(defalias 'help 'tpu-help)
-(defalias 'HELP 'tpu-help)
+(defalias 'help #'tpu-help)
+(defalias 'HELP #'tpu-help)
 
-(defalias 'set\ cursor\ free 'tpu-set-cursor-free)
-(defalias 'SET\ CURSOR\ FREE 'tpu-set-cursor-free)
+(defalias 'set\ cursor\ free #'tpu-set-cursor-free)
+(defalias 'SET\ CURSOR\ FREE #'tpu-set-cursor-free)
 
-(defalias 'set\ cursor\ bound 'tpu-set-cursor-bound)
-(defalias 'SET\ CURSOR\ BOUND 'tpu-set-cursor-bound)
+(defalias 'set\ cursor\ bound #'tpu-set-cursor-bound)
+(defalias 'SET\ CURSOR\ BOUND #'tpu-set-cursor-bound)
 
-(defalias 'set\ scroll\ margins 'tpu-set-scroll-margins)
-(defalias 'SET\ SCROLL\ MARGINS 'tpu-set-scroll-margins)
+(defalias 'set\ scroll\ margins #'tpu-set-scroll-margins)
+(defalias 'SET\ SCROLL\ MARGINS #'tpu-set-scroll-margins)
 
 ;; Real TPU error messages end in periods.
 ;; Define this to avoid openly flouting Emacs coding standards.
-(defalias 'tpu-error 'error)
+(defalias 'tpu-error #'error)
 
 
 ;;;
@@ -1227,7 +1224,7 @@ and the total number of lines in the buffer."
   "Bind a set of keystrokes to a single key, or key combination."
   (interactive)
   (setq tpu-saved-control-r (global-key-binding "\C-r"))
-  (global-set-key "\C-r" 'tpu-end-define-macro-key)
+  (global-set-key "\C-r" #'tpu-end-define-macro-key)
   (start-kbd-macro nil))
 
 
@@ -1361,18 +1358,18 @@ If an argument is specified, don't set the search 
direction."
   (if (not arg) (setq tpu-searching-forward tpu-advance))
   (cond (tpu-searching-forward
         (cond (tpu-regexp-p
-               (fset 'tpu-emacs-search 're-search-forward)
-               (fset 'tpu-emacs-rev-search 're-search-backward))
+               (fset 'tpu-emacs-search #'re-search-forward)
+               (fset 'tpu-emacs-rev-search #'re-search-backward))
               (t
-               (fset 'tpu-emacs-search 'search-forward)
-               (fset 'tpu-emacs-rev-search 'search-backward))))
+               (fset 'tpu-emacs-search #'search-forward)
+               (fset 'tpu-emacs-rev-search #'search-backward))))
        (t
         (cond (tpu-regexp-p
-               (fset 'tpu-emacs-search 're-search-backward)
-               (fset 'tpu-emacs-rev-search 're-search-forward))
+               (fset 'tpu-emacs-search #'re-search-backward)
+               (fset 'tpu-emacs-rev-search #'re-search-forward))
               (t
-               (fset 'tpu-emacs-search 'search-backward)
-               (fset 'tpu-emacs-rev-search 'search-forward))))))
+               (fset 'tpu-emacs-search #'search-backward)
+               (fset 'tpu-emacs-rev-search #'search-forward))))))
 
 (defun tpu-search-internal (pat &optional quiet)
   "Search for a string or regular expression."
@@ -2203,18 +2200,18 @@ Accepts a prefix argument for the number of 
tpu-pan-columns to scroll."
 ;; Standard Emacs settings under xterm in function-key-map map
 ;; "\eOM" to [kp-enter] and [kp-enter] to RET, but since the output of the map
 ;; is not fed back into the map, the key stays as kp-enter :-(.
-(define-key minibuffer-local-map [kp-enter] 'exit-minibuffer)
+(define-key minibuffer-local-map [kp-enter] #'exit-minibuffer)
 ;; These are not necessary because they are inherited.
 ;; (define-key minibuffer-local-ns-map [kp-enter] 'exit-minibuffer)
 ;; (define-key minibuffer-local-completion-map [kp-enter] 'exit-minibuffer)
-(define-key minibuffer-local-must-match-map [kp-enter] 
'minibuffer-complete-and-exit)
+(define-key minibuffer-local-must-match-map [kp-enter] 
#'minibuffer-complete-and-exit)
 
 
 ;;;
 ;;;  Minibuffer map additions to set search direction
 ;;;
-(define-key minibuffer-local-map [kp-4] 'tpu-search-forward-exit)  ;KP4
-(define-key minibuffer-local-map [kp-5] 'tpu-search-backward-exit) ;KP5
+(define-key minibuffer-local-map [kp-4] #'tpu-search-forward-exit)  ;KP4
+(define-key minibuffer-local-map [kp-5] #'tpu-search-backward-exit) ;KP5
 
 
 ;;;
@@ -2223,19 +2220,19 @@ Accepts a prefix argument for the number of 
tpu-pan-columns to scroll."
 
 (defvar tpu-control-keys-map
   (let ((map (make-sparse-keymap)))
-  (define-key map "\C-\\" 'quoted-insert)                ; ^\
-  (define-key map "\C-a" 'tpu-toggle-overwrite-mode)     ; ^A
-  (define-key map "\C-b" 'repeat-complex-command)        ; ^B
-  (define-key map "\C-e" 'tpu-current-end-of-line)       ; ^E
-  (define-key map "\C-h" 'tpu-next-beginning-of-line)    ; ^H (BS)
-  (define-key map "\C-j" 'tpu-delete-previous-word)      ; ^J (LF)
-  (define-key map "\C-k" 'tpu-define-macro-key)          ; ^K
-  (define-key map "\C-l" 'tpu-insert-formfeed)           ; ^L (FF)
-  (define-key map "\C-r" 'recenter)                      ; ^R
-  (define-key map "\C-u" 'tpu-delete-to-bol)             ; ^U
-  (define-key map "\C-v" 'tpu-quoted-insert)             ; ^V
-  (define-key map "\C-w" 'redraw-display)                ; ^W
-  (define-key map "\C-z" 'tpu-exit)                      ; ^Z
+  (define-key map "\C-\\" #'quoted-insert)                ; ^\
+  (define-key map "\C-a" #'tpu-toggle-overwrite-mode)     ; ^A
+  (define-key map "\C-b" #'repeat-complex-command)        ; ^B
+  (define-key map "\C-e" #'tpu-current-end-of-line)       ; ^E
+  (define-key map "\C-h" #'tpu-next-beginning-of-line)    ; ^H (BS)
+  (define-key map "\C-j" #'tpu-delete-previous-word)      ; ^J (LF)
+  (define-key map "\C-k" #'tpu-define-macro-key)          ; ^K
+  (define-key map "\C-l" #'tpu-insert-formfeed)           ; ^L (FF)
+  (define-key map "\C-r" #'recenter)                      ; ^R
+  (define-key map "\C-u" #'tpu-delete-to-bol)             ; ^U
+  (define-key map "\C-v" #'tpu-quoted-insert)             ; ^V
+  (define-key map "\C-w" #'redraw-display)                ; ^W
+  (define-key map "\C-z" #'tpu-exit)                      ; ^Z
   map))
 
 (defun tpu-set-control-keys ()
@@ -2285,18 +2282,18 @@ Accepts a prefix argument for the number of 
tpu-pan-columns to scroll."
 (defun tpu-arrow-history nil
   "Modify minibuffer maps to use arrows for history recall."
   (interactive)
-  (dolist (cur (where-is-internal 'tpu-previous-line))
-    (define-key read-expression-map cur 'tpu-previous-history-element)
-    (define-key minibuffer-local-map cur 'tpu-previous-history-element)
+  (dolist (cur (where-is-internal #'tpu-previous-line))
+    (define-key read-expression-map cur #'tpu-previous-history-element)
+    (define-key minibuffer-local-map cur #'tpu-previous-history-element)
     ;; These are inherited anyway.  --Stef
     ;; (define-key minibuffer-local-ns-map cur 'tpu-previous-history-element)
     ;; (define-key minibuffer-local-completion-map cur 
'tpu-previous-history-element)
     ;; (define-key minibuffer-local-must-match-map cur 
'tpu-previous-history-element)
     )
 
-  (dolist (cur (where-is-internal 'tpu-next-line))
-    (define-key read-expression-map cur 'tpu-next-history-element)
-    (define-key minibuffer-local-map cur 'tpu-next-history-element)
+  (dolist (cur (where-is-internal #'tpu-next-line))
+    (define-key read-expression-map cur #'tpu-next-history-element)
+    (define-key minibuffer-local-map cur #'tpu-next-history-element)
     ;; These are inherited anyway.  --Stef
     ;; (define-key minibuffer-local-ns-map cur 'tpu-next-history-element)
     ;; (define-key minibuffer-local-completion-map cur 
'tpu-next-history-element)
@@ -2382,7 +2379,7 @@ If FILE is nil, try to load a default file.  The default 
file names are
   (use-global-map global-map)
   ;; Then do the normal TPU setup.
   (transient-mark-mode t)
-  (add-hook 'post-command-hook 'tpu-search-highlight)
+  (add-hook 'post-command-hook #'tpu-search-highlight)
   (tpu-set-mode-line t)
   (tpu-advance-direction)
   ;; set page delimiter, display line truncation, and scrolling like TPU
@@ -2406,7 +2403,7 @@ If FILE is nil, try to load a default file.  The default 
file names are
   "Turn off TPU/edt emulation.  Note that the keypad is left on."
   (interactive)
   (tpu-reset-control-keys nil)
-  (remove-hook 'post-command-hook 'tpu-search-highlight)
+  (remove-hook 'post-command-hook #'tpu-search-highlight)
   (tpu-set-mode-line nil)
   (while tpu-edt-old-global-values
     (let ((varval (pop tpu-edt-old-global-values)))
diff --git a/lisp/obsolete/tpu-extras.el b/lisp/obsolete/tpu-extras.el
index 10b9c89..f375e05 100644
--- a/lisp/obsolete/tpu-extras.el
+++ b/lisp/obsolete/tpu-extras.el
@@ -1,4 +1,4 @@
-;;; tpu-extras.el --- scroll margins and free cursor mode for TPU-edt
+;;; tpu-extras.el --- scroll margins and free cursor mode for TPU-edt  -*- 
lexical-binding: t; -*-
 
 ;; Copyright (C) 1993-1995, 2000-2021 Free Software Foundation, Inc.
 
@@ -144,12 +144,12 @@ the previous line when starting from a line beginning."
 ;;;  Hooks  --  Set cursor free in picture mode.
 ;;;             Clean up when writing a file from cursor free mode.
 
-(add-hook 'picture-mode-hook 'tpu-set-cursor-free)
+(add-hook 'picture-mode-hook #'tpu-set-cursor-free)
 
 (defun tpu-trim-line-ends-if-needed ()
   "Eliminate whitespace at ends of lines, if the cursor is free."
   (if (and (buffer-modified-p) tpu-cursor-free-mode) (tpu-trim-line-ends)))
-(add-hook 'before-save-hook 'tpu-trim-line-ends-if-needed)
+(add-hook 'before-save-hook #'tpu-trim-line-ends-if-needed)
 
 
 ;;;  Utility routines for implementing scroll margins
@@ -368,34 +368,22 @@ A repeat count means scroll that many sections."
      (and (< (point) top) (recenter (min beg top-margin))))))
 
 ;; Advise the newline, newline-and-indent, and do-auto-fill functions.
-(defadvice newline (around tpu-respect-bottom-scroll-margin activate disable)
+(defun tpu--respect-bottom-scroll-margin (orig-fun &optional &rest args)
   "Respect `tpu-bottom-scroll-margin'."
   (let ((beg (tpu-current-line))
-        (num (prefix-numeric-value (ad-get-arg 0))))
-    ad-do-it
+        (num (prefix-numeric-value (car args))))
+    (apply orig-fun args)
     (tpu-bottom-check beg num)))
 
-(defadvice newline-and-indent (around tpu-respect-bottom-scroll-margin)
-  "Respect `tpu-bottom-scroll-margin'."
-  (let ((beg (tpu-current-line)))
-    ad-do-it
-    (tpu-bottom-check beg 1)))
-
-(defadvice do-auto-fill (around tpu-respect-bottom-scroll-margin)
-  "Respect `tpu-bottom-scroll-margin'."
-  (let ((beg (tpu-current-line)))
-    ad-do-it
-    (tpu-bottom-check beg 1)))
-
-
 ;;;  Function to set scroll margins
 
 ;;;###autoload
-(defun tpu-set-scroll-margins (top bottom)
+(defun tpu-set-scroll-margins (top bottom &optional emit-msg)
   "Set scroll margins."
   (interactive
    "sEnter top scroll margin (N lines or N%% or RETURN for current value): \
-\nsEnter bottom scroll margin (N lines or N%% or RETURN for current value): ")
+\nsEnter bottom scroll margin (N lines or N%% or RETURN for current value): \
+\np")
   ;; set top scroll margin
   (or (string= top "")
       (setq tpu-top-scroll-margin
@@ -411,10 +399,9 @@ A repeat count means scroll that many sections."
              (/ (1- (+ (* (string-to-number bottom) 100) (window-height)))
                 (window-height)))))
   (dolist (f '(newline newline-and-indent do-auto-fill))
-    (ad-enable-advice f 'around 'tpu-respect-bottom-scroll-margin)
-    (ad-activate f))
+    (advice-add f :around #'tpu--respect-bottom-scroll-margin))
   ;; report scroll margin settings if running interactively
-  (and (called-interactively-p 'interactive)
+  (and emit-msg
        (message "Scroll margins set.  Top = %s%%, Bottom = %s%%"
                tpu-top-scroll-margin tpu-bottom-scroll-margin)))
 
diff --git a/lisp/obsolete/tpu-mapper.el b/lisp/obsolete/tpu-mapper.el
index 2735820..d23068a 100644
--- a/lisp/obsolete/tpu-mapper.el
+++ b/lisp/obsolete/tpu-mapper.el
@@ -1,4 +1,4 @@
-;;; tpu-mapper.el --- create a TPU-edt X-windows keymap file
+;;; tpu-mapper.el --- create a TPU-edt X-windows keymap file  -*- 
lexical-binding: t; -*-
 
 ;; Copyright (C) 1993-1995, 2001-2021 Free Software Foundation, Inc.
 
diff --git a/lisp/obsolete/url-ns.el b/lisp/obsolete/url-ns.el
index fff3be9..b62ad82 100644
--- a/lisp/obsolete/url-ns.el
+++ b/lisp/obsolete/url-ns.el
@@ -1,4 +1,4 @@
-;;; url-ns.el --- Various netscape-ish functions for proxy definitions
+;;; url-ns.el --- Various netscape-ish functions for proxy definitions  -*- 
lexical-binding: t; -*-
 
 ;; Copyright (C) 1997-1999, 2004-2021 Free Software Foundation, Inc.
 
@@ -55,9 +55,9 @@
     (if (or (/= (length netc) (length ipc))
            (/= (length ipc) (length maskc)))
        nil
-      (setq netc (mapcar 'string-to-number netc)
-           ipc (mapcar 'string-to-number ipc)
-           maskc (mapcar 'string-to-number maskc))
+      (setq netc (mapcar #'string-to-number netc)
+           ipc (mapcar #'string-to-number ipc)
+           maskc (mapcar #'string-to-number maskc))
       (and
        (= (logand (nth 0 netc) (nth 0 maskc))
          (logand (nth 0 ipc)  (nth 0 maskc)))
@@ -79,24 +79,23 @@
   (if (not (and (file-exists-p file)
                (file-readable-p file)))
       (message "Could not open %s for reading" file)
-    (save-excursion
-      (let ((false nil)
-           (true t))
-       (setq url-ns-user-prefs (make-hash-table :size 13 :test 'equal))
-       (set-buffer (get-buffer-create " *ns-parse*"))
-       (erase-buffer)
-       (insert-file-contents file)
-       (goto-char (point-min))
-       (while (re-search-forward "^//" nil t)
-         (replace-match ";;"))
-       (goto-char (point-min))
-       (while (re-search-forward "^user_pref(" nil t)
-         (replace-match "(url-ns-set-user-pref "))
-       (goto-char (point-min))
-       (while (re-search-forward "\"," nil t)
-         (replace-match "\""))
-       (goto-char (point-min))
-       (eval-buffer)))))
+    (setq url-ns-user-prefs (make-hash-table :size 13 :test 'equal))
+    (with-current-buffer (get-buffer-create " *ns-parse*")
+      (erase-buffer)
+      (insert-file-contents file)
+      (goto-char (point-min))
+      (while (re-search-forward "^//" nil t)
+       (replace-match ";;"))
+      (goto-char (point-min))
+      (while (re-search-forward "^user_pref(" nil t)
+       (replace-match "(url-ns-set-user-pref "))
+      (goto-char (point-min))
+      (while (re-search-forward "\"," nil t)
+       (replace-match "\""))
+      (goto-char (point-min))
+      (with-suppressed-warnings ((lexical true false))
+       (dlet ((false nil) (true t))
+         (eval-buffer))))))
 
 (defun url-ns-set-user-pref (key val)
   (puthash key val url-ns-user-prefs))
diff --git a/lisp/obsolete/vc-arch.el b/lisp/obsolete/vc-arch.el
index 80a2094..cfbf981 100644
--- a/lisp/obsolete/vc-arch.el
+++ b/lisp/obsolete/vc-arch.el
@@ -26,7 +26,7 @@
 
 ;; The home page of the Arch version control system is at
 ;;
-;;      http://www.gnuarch.org/
+;;      https://www.gnu.org/software/gnu-arch/
 ;;
 ;; This is derived from vc-mcvs.el as follows:
 ;; - cp vc-mcvs.el vc-arch.el and then M-% mcvs RET arch RET
@@ -81,8 +81,7 @@ If nil, use the value of `vc-diff-switches'.  If t, use no 
switches."
                 (const :tag "None" t)
                 (string :tag "Argument String")
                 (repeat :tag "Argument List" :value ("") string))
-  :version "23.1"
-  :group 'vc-arch)
+  :version "23.1")
 
 (define-obsolete-variable-alias 'vc-arch-command 'vc-arch-program "23.1")
 
@@ -92,8 +91,7 @@ If nil, use the value of `vc-diff-switches'.  If t, use no 
switches."
       (setq candidates (cdr candidates)))
     (or (car candidates) "tla"))
   "Name of the Arch executable."
-  :type 'string
-  :group 'vc-arch)
+  :type 'string)
 
 ;; Clear up the cache to force vc-call to check again and discover
 ;; new functions when we reload this file.
@@ -341,7 +339,7 @@ CALLBACK expects (ENTRIES &optional MORE-TO-COME); see
                      ("--" . permissions-changed)
                      ("-/" . permissions-changed) ;directory
                      ))
-        (state-map-regexp (regexp-opt (mapcar 'car state-map) t))
+        (state-map-regexp (regexp-opt (mapcar #'car state-map) t))
         (entry-regexp (concat "^" state-map-regexp " \\(.*\\)$"))
         result)
     (goto-char (point-min))
@@ -387,8 +385,7 @@ CALLBACK expects (ENTRIES &optional MORE-TO-COME); see
 (defcustom vc-arch-mode-line-rewrite
   '(("\\`.*--\\(.*--.*\\)--\\(v?\\).*-\\([0-9]+\\)\\'" . "\\2\\3[\\1]"))
   "Rewrite rules to shorten Arch's revision names on the mode-line."
-  :type '(repeat (cons regexp string))
-  :group 'vc-arch)
+  :type '(repeat (cons regexp string)))
 
 (defun vc-arch-mode-line-string (file)
   "Return a string for `vc-mode-line' to put in the mode line for FILE."
@@ -420,7 +417,7 @@ CALLBACK expects (ENTRIES &optional MORE-TO-COME); see
          ;; The .rej file is obsolete.
          (condition-case nil (delete-file rej) (error nil))
          ;; Remove the hook so that it is not called multiple times.
-         (remove-hook 'after-save-hook 'vc-arch-delete-rej-if-obsolete t))))))
+         (remove-hook 'after-save-hook #'vc-arch-delete-rej-if-obsolete t))))))
 
 (defun vc-arch-find-file-hook ()
   (let ((rej (concat buffer-file-name ".rej")))
@@ -433,7 +430,7 @@ CALLBACK expects (ENTRIES &optional MORE-TO-COME); see
                (condition-case nil (delete-file rej) (error nil))
              (smerge-mode 1)
              (add-hook 'after-save-hook
-                       'vc-arch-delete-rej-if-obsolete nil t)
+                       #'vc-arch-delete-rej-if-obsolete nil t)
              (message "There are unresolved conflicts in this file")))
        (message "There are unresolved conflicts in %s"
                 (file-name-nondirectory rej))))))
@@ -488,11 +485,11 @@ CALLBACK expects (ENTRIES &optional MORE-TO-COME); see
 (defun vc-arch-rename-file (old new)
   (vc-arch-command nil 0 new "mv" (file-relative-name old)))
 
-(defalias 'vc-arch-responsible-p 'vc-arch-root)
+(defalias 'vc-arch-responsible-p #'vc-arch-root)
 
 (defun vc-arch-command (buffer okstatus file &rest flags)
   "A wrapper around `vc-do-command' for use in vc-arch.el."
-  (apply 'vc-do-command (or buffer "*vc*") okstatus vc-arch-program file 
flags))
+  (apply #'vc-do-command (or buffer "*vc*") okstatus vc-arch-program file 
flags))
 
 ;;; Completion of versions and revisions.
 
@@ -571,7 +568,7 @@ CALLBACK expects (ENTRIES &optional MORE-TO-COME); see
                         (when (string-match "-\\([0-9]+\\)\\'" f)
                           (cons (string-to-number (match-string 1 f)) f)))
                       (directory-files dir nil nil 'nosort)))
-               'car-less-than-car))
+               #'car-less-than-car))
         (subdirs nil))
     (when (cddr revs)
       (dotimes (_i (/ (length revs) 2))
@@ -600,26 +597,26 @@ CALLBACK expects (ENTRIES &optional MORE-TO-COME); see
     (let* ((archives (directory-files rl-dir 'full
                                       directory-files-no-dot-files-regexp))
            (categories
-            (apply 'append
+            (apply #'append
                    (mapcar (lambda (dir)
                              (when (file-directory-p dir)
                                (directory-files
                                 dir 'full 
directory-files-no-dot-files-regexp)))
                            archives)))
            (branches
-            (apply 'append
+            (apply #'append
                    (mapcar (lambda (dir)
                              (when (file-directory-p dir)
                                (directory-files
                                 dir 'full 
directory-files-no-dot-files-regexp)))
                            categories)))
            (versions
-            (apply 'append
+            (apply #'append
                    (mapcar (lambda (dir)
                              (when (file-directory-p dir)
                                (directory-files dir 'full "--.*--")))
                            branches))))
-      (mapc 'vc-arch-trim-one-revlib versions))
+      (mapc #'vc-arch-trim-one-revlib versions))
     ))
 
 (defvar vc-arch-extra-menu-map
diff --git a/lisp/obsolete/vi.el b/lisp/obsolete/vi.el
index eee00b4..91baa4d 100644
--- a/lisp/obsolete/vi.el
+++ b/lisp/obsolete/vi.el
@@ -1,4 +1,4 @@
-;;; vi.el --- major mode for emulating "vi" editor under GNU Emacs
+;;; vi.el --- major mode for emulating "vi" editor under GNU Emacs  -*- 
lexical-binding: t; -*-
 
 ;; This file is in the public domain because the authors distributed it
 ;; without a copyright notice before the US signed the Bern Convention.
@@ -48,7 +48,7 @@
 (defvar vi-mode-old-case-fold)
 
 (if (null (where-is-internal 'vi-switch-mode (current-local-map)))
-    (define-key ctl-x-map "~" 'vi-switch-mode))
+    (define-key ctl-x-map "~" #'vi-switch-mode))
 
 (defvar vi-tilde-map nil
   "Keymap used for \\[vi-switch-mode] prefix key.  Link to various major 
modes.")
@@ -56,24 +56,24 @@
 (if vi-tilde-map
     nil
   (setq vi-tilde-map (make-keymap))
-  (define-key vi-tilde-map "a" 'abbrev-mode)
-  (define-key vi-tilde-map "c" 'c-mode)
-  (define-key vi-tilde-map "d" 'vi-debugging)
-  (define-key vi-tilde-map "e" 'emacs-lisp-mode)
-  (define-key vi-tilde-map "f" 'auto-fill-mode)
-  (define-key vi-tilde-map "g" 'prolog-mode)
-  (define-key vi-tilde-map "h" 'hanoi)
-  (define-key vi-tilde-map "i" 'info-mode)
-  (define-key vi-tilde-map "l" 'lisp-mode)
-  (define-key vi-tilde-map "n" 'nroff-mode)
-  (define-key vi-tilde-map "o" 'overwrite-mode)
-  (define-key vi-tilde-map "O" 'outline-mode)
-  (define-key vi-tilde-map "P" 'picture-mode)
-  (define-key vi-tilde-map "r" 'vi-readonly-mode)
-  (define-key vi-tilde-map "t" 'text-mode)
-  (define-key vi-tilde-map "v" 'vi-mode)
-  (define-key vi-tilde-map "x" 'tex-mode)
-  (define-key vi-tilde-map "~" 'vi-back-to-old-mode))
+  (define-key vi-tilde-map "a" #'abbrev-mode)
+  (define-key vi-tilde-map "c" #'c-mode)
+  (define-key vi-tilde-map "d" #'vi-debugging)
+  (define-key vi-tilde-map "e" #'emacs-lisp-mode)
+  (define-key vi-tilde-map "f" #'auto-fill-mode)
+  (define-key vi-tilde-map "g" #'prolog-mode)
+  (define-key vi-tilde-map "h" #'hanoi)
+  ;; (define-key vi-tilde-map "i" #'info-mode)
+  (define-key vi-tilde-map "l" #'lisp-mode)
+  (define-key vi-tilde-map "n" #'nroff-mode)
+  (define-key vi-tilde-map "o" #'overwrite-mode)
+  (define-key vi-tilde-map "O" #'outline-mode)
+  (define-key vi-tilde-map "P" #'picture-mode)
+  (define-key vi-tilde-map "r" #'vi-readonly-mode)
+  (define-key vi-tilde-map "t" #'text-mode)
+  (define-key vi-tilde-map "v" #'vi-mode)
+  (define-key vi-tilde-map "x" #'tex-mode)
+  (define-key vi-tilde-map "~" #'vi-back-to-old-mode))
 
 (defun vi-switch-mode (arg mode-char)
   "Switch the major mode of current buffer as specified by the following char 
\\{vi-tilde-map}"
@@ -123,143 +123,143 @@ command extensions.")
 (put 'vi-undefined 'suppress-keymap t)
 (if vi-com-map nil
   (setq vi-com-map (make-keymap))
-;;(fillarray vi-com-map 'vi-undefined)
-  (define-key vi-com-map "\C-@" 'vi-mark-region) ; extension
-  (define-key vi-com-map "\C-a" 'vi-ask-for-info)  ; extension
-  (define-key vi-com-map "\C-b" 'vi-backward-windowful)
-  (define-key vi-com-map "\C-c" 'vi-do-old-mode-C-c-command) ; extension
-  (define-key vi-com-map "\C-d" 'vi-scroll-down-window)
-  (define-key vi-com-map "\C-e" 'vi-expose-line-below)
-  (define-key vi-com-map "\C-f" 'vi-forward-windowful)
-  (define-key vi-com-map "\C-g" 'keyboard-quit)
-  (define-key vi-com-map "\C-i" 'indent-relative-first-indent-point) ; TAB
-  (define-key vi-com-map "\C-j" 'vi-next-line) ; LFD
-  (define-key vi-com-map "\C-k" 'vi-kill-line) ; extension
-  (define-key vi-com-map "\C-l" 'recenter)
-  (define-key vi-com-map "\C-m" 'vi-next-line-first-nonwhite) ; RET
-  (define-key vi-com-map "\C-n" 'vi-next-line)
-  (define-key vi-com-map "\C-o" 'vi-split-open-line)
-  (define-key vi-com-map "\C-p" 'previous-line)
-  (define-key vi-com-map "\C-q" 'vi-query-replace) ; extension
-  (define-key vi-com-map "\C-r" 'vi-isearch-backward) ; modification
-  (define-key vi-com-map "\C-s" 'vi-isearch-forward)  ; extension
-  (define-key vi-com-map "\C-t" 'vi-transpose-objects) ; extension
-  (define-key vi-com-map "\C-u" 'vi-scroll-up-window)
-  (define-key vi-com-map "\C-v" 'scroll-up-command) ; extension
-  (define-key vi-com-map "\C-w" 'vi-kill-region)   ; extension
+;;(fillarray vi-com-map #'vi-undefined)
+  (define-key vi-com-map "\C-@" #'vi-mark-region) ; extension
+  (define-key vi-com-map "\C-a" #'vi-ask-for-info)  ; extension
+  (define-key vi-com-map "\C-b" #'vi-backward-windowful)
+  (define-key vi-com-map "\C-c" #'vi-do-old-mode-C-c-command) ; extension
+  (define-key vi-com-map "\C-d" #'vi-scroll-down-window)
+  (define-key vi-com-map "\C-e" #'vi-expose-line-below)
+  (define-key vi-com-map "\C-f" #'vi-forward-windowful)
+  (define-key vi-com-map "\C-g" #'keyboard-quit)
+  (define-key vi-com-map "\C-i" #'indent-relative-first-indent-point) ; TAB
+  (define-key vi-com-map "\C-j" #'vi-next-line) ; LFD
+  (define-key vi-com-map "\C-k" #'vi-kill-line) ; extension
+  (define-key vi-com-map "\C-l" #'recenter)
+  (define-key vi-com-map "\C-m" #'vi-next-line-first-nonwhite) ; RET
+  (define-key vi-com-map "\C-n" #'vi-next-line)
+  (define-key vi-com-map "\C-o" #'vi-split-open-line)
+  (define-key vi-com-map "\C-p" #'previous-line)
+  (define-key vi-com-map "\C-q" #'vi-query-replace) ; extension
+  (define-key vi-com-map "\C-r" #'vi-isearch-backward) ; modification
+  (define-key vi-com-map "\C-s" #'vi-isearch-forward)  ; extension
+  (define-key vi-com-map "\C-t" #'vi-transpose-objects) ; extension
+  (define-key vi-com-map "\C-u" #'vi-scroll-up-window)
+  (define-key vi-com-map "\C-v" #'scroll-up-command) ; extension
+  (define-key vi-com-map "\C-w" #'vi-kill-region)   ; extension
   (define-key vi-com-map "\C-x" 'Control-X-prefix) ; extension
-  (define-key vi-com-map "\C-y" 'vi-expose-line-above)
-  (define-key vi-com-map "\C-z" 'suspend-emacs)
+  (define-key vi-com-map "\C-y" #'vi-expose-line-above)
+  (define-key vi-com-map "\C-z" #'suspend-emacs)
 
   (define-key vi-com-map "\e"   'ESC-prefix); C-[ (ESC)
-  (define-key vi-com-map "\C-\\" 'vi-unimplemented)
-  (define-key vi-com-map "\C-]" 'find-tag)
-  (define-key vi-com-map "\C-^" 'vi-locate-def)  ; extension
-  (define-key vi-com-map "\C-_" 'vi-undefined)
-
-  (define-key vi-com-map " " 'forward-char)
-  (define-key vi-com-map "!"  'vi-operator)
-  (define-key vi-com-map "\"" 'vi-char-argument)
-  (define-key vi-com-map "#"  'universal-argument) ; extension
-  (define-key vi-com-map "$"  'end-of-line)
-  (define-key vi-com-map "%"  'vi-find-matching-paren)
-  (define-key vi-com-map "&"  'vi-unimplemented)
-  (define-key vi-com-map "'"  'vi-goto-line-mark)
-  (define-key vi-com-map "("  'backward-sexp)
-  (define-key vi-com-map ")"  'forward-sexp)
-  (define-key vi-com-map "*"  'vi-name-last-change-or-macro) ; extension
-  (define-key vi-com-map "+"  'vi-next-line-first-nonwhite)
-  (define-key vi-com-map ","  'vi-reverse-last-find-char)
-  (define-key vi-com-map "-"  'vi-previous-line-first-nonwhite)
-  (define-key vi-com-map "."  'vi-redo-last-change-command)
-  (define-key vi-com-map "/"  'vi-search-forward)
-  (define-key vi-com-map "0"  'beginning-of-line)
-
-  (define-key vi-com-map "1"  'vi-digit-argument)
-  (define-key vi-com-map "2"  'vi-digit-argument)
-  (define-key vi-com-map "3"  'vi-digit-argument)
-  (define-key vi-com-map "4"  'vi-digit-argument)
-  (define-key vi-com-map "5"  'vi-digit-argument)
-  (define-key vi-com-map "6"  'vi-digit-argument)
-  (define-key vi-com-map "7"  'vi-digit-argument)
-  (define-key vi-com-map "8"  'vi-digit-argument)
-  (define-key vi-com-map "9"  'vi-digit-argument)
-
-  (define-key vi-com-map ":"  'vi-ex-cmd)
-  (define-key vi-com-map ";"  'vi-repeat-last-find-char)
-  (define-key vi-com-map "<"  'vi-operator)
-  (define-key vi-com-map "="  'vi-operator)
-  (define-key vi-com-map ">"  'vi-operator)
-  (define-key vi-com-map "?"  'vi-search-backward)
-  (define-key vi-com-map "@"  'vi-call-named-change-or-macro) ; extension
-
-  (define-key vi-com-map "A"  'vi-append-at-end-of-line)
-  (define-key vi-com-map "B"  'vi-backward-blank-delimited-word)
-  (define-key vi-com-map "C"  'vi-change-rest-of-line)
-  (define-key vi-com-map "D"  'vi-kill-line)
-  (define-key vi-com-map "E"  'vi-end-of-blank-delimited-word)
-  (define-key vi-com-map "F"  'vi-backward-find-char)
-  (define-key vi-com-map "G"  'vi-goto-line)
-  (define-key vi-com-map "H"  'vi-home-window-line)
-  (define-key vi-com-map "I"  'vi-insert-before-first-nonwhite)
-  (define-key vi-com-map "J"  'vi-join-lines)
-  (define-key vi-com-map "K"  'vi-undefined)
-  (define-key vi-com-map "L"  'vi-last-window-line)
-  (define-key vi-com-map "M"  'vi-middle-window-line)
-  (define-key vi-com-map "N"  'vi-reverse-last-search)
-  (define-key vi-com-map "O"  'vi-open-above)
-  (define-key vi-com-map "P"  'vi-put-before)
-  (define-key vi-com-map "Q"  'vi-quote-words) ; extension
-  (define-key vi-com-map "R"  'vi-replace-chars)
-  (define-key vi-com-map "S"  'vi-substitute-lines)
-  (define-key vi-com-map "T"  'vi-backward-upto-char)
-  (define-key vi-com-map "U"  'vi-unimplemented)
-  (define-key vi-com-map "V"  'vi-undefined)
-  (define-key vi-com-map "W"  'vi-forward-blank-delimited-word)
-  (define-key vi-com-map "X"  'call-last-kbd-macro) ; modification/extension
-  (define-key vi-com-map "Y"  'vi-yank-line)
+  (define-key vi-com-map "\C-\\" #'vi-unimplemented)
+  (define-key vi-com-map "\C-]" #'xref-find-definitions)
+  (define-key vi-com-map "\C-^" #'vi-locate-def)  ; extension
+  (define-key vi-com-map "\C-_" #'vi-undefined)
+
+  (define-key vi-com-map " "  #'forward-char)
+  (define-key vi-com-map "!"  #'vi-operator)
+  (define-key vi-com-map "\"" #'vi-char-argument)
+  (define-key vi-com-map "#"  #'universal-argument) ; extension
+  (define-key vi-com-map "$"  #'end-of-line)
+  (define-key vi-com-map "%"  #'vi-find-matching-paren)
+  (define-key vi-com-map "&"  #'vi-unimplemented)
+  (define-key vi-com-map "'"  #'vi-goto-line-mark)
+  (define-key vi-com-map "("  #'backward-sexp)
+  (define-key vi-com-map ")"  #'forward-sexp)
+  (define-key vi-com-map "*"  #'vi-name-last-change-or-macro) ; extension
+  (define-key vi-com-map "+"  #'vi-next-line-first-nonwhite)
+  (define-key vi-com-map ","  #'vi-reverse-last-find-char)
+  (define-key vi-com-map "-"  #'vi-previous-line-first-nonwhite)
+  (define-key vi-com-map "."  #'vi-redo-last-change-command)
+  (define-key vi-com-map "/"  #'vi-search-forward)
+  (define-key vi-com-map "0"  #'beginning-of-line)
+
+  (define-key vi-com-map "1"  #'vi-digit-argument)
+  (define-key vi-com-map "2"  #'vi-digit-argument)
+  (define-key vi-com-map "3"  #'vi-digit-argument)
+  (define-key vi-com-map "4"  #'vi-digit-argument)
+  (define-key vi-com-map "5"  #'vi-digit-argument)
+  (define-key vi-com-map "6"  #'vi-digit-argument)
+  (define-key vi-com-map "7"  #'vi-digit-argument)
+  (define-key vi-com-map "8"  #'vi-digit-argument)
+  (define-key vi-com-map "9"  #'vi-digit-argument)
+
+  (define-key vi-com-map ":"  #'vi-ex-cmd)
+  (define-key vi-com-map ";"  #'vi-repeat-last-find-char)
+  (define-key vi-com-map "<"  #'vi-operator)
+  (define-key vi-com-map "="  #'vi-operator)
+  (define-key vi-com-map ">"  #'vi-operator)
+  (define-key vi-com-map "?"  #'vi-search-backward)
+  (define-key vi-com-map "@"  #'vi-call-named-change-or-macro) ; extension
+
+  (define-key vi-com-map "A"  #'vi-append-at-end-of-line)
+  (define-key vi-com-map "B"  #'vi-backward-blank-delimited-word)
+  (define-key vi-com-map "C"  #'vi-change-rest-of-line)
+  (define-key vi-com-map "D"  #'vi-kill-line)
+  (define-key vi-com-map "E"  #'vi-end-of-blank-delimited-word)
+  (define-key vi-com-map "F"  #'vi-backward-find-char)
+  (define-key vi-com-map "G"  #'vi-goto-line)
+  (define-key vi-com-map "H"  #'vi-home-window-line)
+  (define-key vi-com-map "I"  #'vi-insert-before-first-nonwhite)
+  (define-key vi-com-map "J"  #'vi-join-lines)
+  (define-key vi-com-map "K"  #'vi-undefined)
+  (define-key vi-com-map "L"  #'vi-last-window-line)
+  (define-key vi-com-map "M"  #'vi-middle-window-line)
+  (define-key vi-com-map "N"  #'vi-reverse-last-search)
+  (define-key vi-com-map "O"  #'vi-open-above)
+  (define-key vi-com-map "P"  #'vi-put-before)
+  (define-key vi-com-map "Q"  #'vi-quote-words) ; extension
+  (define-key vi-com-map "R"  #'vi-replace-chars)
+  (define-key vi-com-map "S"  #'vi-substitute-lines)
+  (define-key vi-com-map "T"  #'vi-backward-upto-char)
+  (define-key vi-com-map "U"  #'vi-unimplemented)
+  (define-key vi-com-map "V"  #'vi-undefined)
+  (define-key vi-com-map "W"  #'vi-forward-blank-delimited-word)
+  (define-key vi-com-map "X"  #'call-last-kbd-macro) ; modification/extension
+  (define-key vi-com-map "Y"  #'vi-yank-line)
   (define-key vi-com-map "Z" (make-sparse-keymap)) ;allow below prefix command
-  (define-key vi-com-map "ZZ" 'vi-save-all-and-exit)
-
-  (define-key vi-com-map "["  'vi-unimplemented)
-  (define-key vi-com-map "\\" 'vi-operator) ; extension for vi-narrow-op
-  (define-key vi-com-map "]"  'vi-unimplemented)
-  (define-key vi-com-map "^"  'back-to-indentation)
-  (define-key vi-com-map "_"  'vi-undefined)
-  (define-key vi-com-map "`"  'vi-goto-char-mark)
-
-  (define-key vi-com-map "a"  'vi-insert-after)
-  (define-key vi-com-map "b"  'backward-word)
-  (define-key vi-com-map "c"  'vi-operator)
-  (define-key vi-com-map "d"  'vi-operator)
-  (define-key vi-com-map "e"  'vi-end-of-word)
-  (define-key vi-com-map "f"  'vi-forward-find-char)
-  (define-key vi-com-map "g"  'vi-beginning-of-buffer) ; extension
-  (define-key vi-com-map "h"  'backward-char)
-  (define-key vi-com-map "i"  'vi-insert-before)
-  (define-key vi-com-map "j"  'vi-next-line)
-  (define-key vi-com-map "k"  'previous-line)
-  (define-key vi-com-map "l"  'forward-char)
-  (define-key vi-com-map "m"  'vi-set-mark)
-  (define-key vi-com-map "n"  'vi-repeat-last-search)
-  (define-key vi-com-map "o"  'vi-open-below)
-  (define-key vi-com-map "p"  'vi-put-after)
-  (define-key vi-com-map "q"  'vi-replace)
-  (define-key vi-com-map "r"  'vi-replace-1-char)
-  (define-key vi-com-map "s"  'vi-substitute-chars)
-  (define-key vi-com-map "t"  'vi-forward-upto-char)
-  (define-key vi-com-map "u"  'undo)
-  (define-key vi-com-map "v"  'vi-verify-spelling)
-  (define-key vi-com-map "w"  'vi-forward-word)
-  (define-key vi-com-map "x"  'vi-kill-char)
-  (define-key vi-com-map "y"  'vi-operator)
-  (define-key vi-com-map "z"  'vi-adjust-window)
-
-  (define-key vi-com-map "{"  'backward-paragraph)
-  (define-key vi-com-map "|"  'vi-goto-column)
-  (define-key vi-com-map "}"  'forward-paragraph)
-  (define-key vi-com-map "~"  'vi-change-case)
-  (define-key vi-com-map "\177" 'delete-backward-char))
+  (define-key vi-com-map "ZZ" #'vi-save-all-and-exit)
+
+  (define-key vi-com-map "["  #'vi-unimplemented)
+  (define-key vi-com-map "\\" #'vi-operator) ; extension for vi-narrow-op
+  (define-key vi-com-map "]"  #'vi-unimplemented)
+  (define-key vi-com-map "^"  #'back-to-indentation)
+  (define-key vi-com-map "_"  #'vi-undefined)
+  (define-key vi-com-map "`"  #'vi-goto-char-mark)
+
+  (define-key vi-com-map "a"  #'vi-insert-after)
+  (define-key vi-com-map "b"  #'backward-word)
+  (define-key vi-com-map "c"  #'vi-operator)
+  (define-key vi-com-map "d"  #'vi-operator)
+  (define-key vi-com-map "e"  #'vi-end-of-word)
+  (define-key vi-com-map "f"  #'vi-forward-find-char)
+  (define-key vi-com-map "g"  #'vi-beginning-of-buffer) ; extension
+  (define-key vi-com-map "h"  #'backward-char)
+  (define-key vi-com-map "i"  #'vi-insert-before)
+  (define-key vi-com-map "j"  #'vi-next-line)
+  (define-key vi-com-map "k"  #'previous-line)
+  (define-key vi-com-map "l"  #'forward-char)
+  (define-key vi-com-map "m"  #'vi-set-mark)
+  (define-key vi-com-map "n"  #'vi-repeat-last-search)
+  (define-key vi-com-map "o"  #'vi-open-below)
+  (define-key vi-com-map "p"  #'vi-put-after)
+  (define-key vi-com-map "q"  #'vi-replace)
+  (define-key vi-com-map "r"  #'vi-replace-1-char)
+  (define-key vi-com-map "s"  #'vi-substitute-chars)
+  (define-key vi-com-map "t"  #'vi-forward-upto-char)
+  (define-key vi-com-map "u"  #'undo)
+  (define-key vi-com-map "v"  #'vi-verify-spelling)
+  (define-key vi-com-map "w"  #'vi-forward-word)
+  (define-key vi-com-map "x"  #'vi-kill-char)
+  (define-key vi-com-map "y"  #'vi-operator)
+  (define-key vi-com-map "z"  #'vi-adjust-window)
+
+  (define-key vi-com-map "{"  #'backward-paragraph)
+  (define-key vi-com-map "|"  #'vi-goto-column)
+  (define-key vi-com-map "}"  #'forward-paragraph)
+  (define-key vi-com-map "~"  #'vi-change-case)
+  (define-key vi-com-map "\177" #'delete-backward-char))
 
 (put 'backward-char 'point-moving-unit 'char)
 (put 'vi-next-line 'point-moving-unit 'line)
@@ -1182,7 +1182,7 @@ SPECIAL FEATURE: char argument can be used to specify 
shift amount(1-9)."
 (defun vi-narrow-op (motion-command arg)
   "Narrow to region specified by MOTION-COMMAND with ARG."
   (let* ((range (vi-effective-range motion-command arg))
-        (begin (car range)) (end (cdr range)) reg)
+        (begin (car range)) (end (cdr range)))
     (if (= begin end)
        nil                             ; point not moved, abort op
       (narrow-to-region begin end))))
diff --git a/lisp/obsolete/vip.el b/lisp/obsolete/vip.el
index 08085e5..16906b6 100644
--- a/lisp/obsolete/vip.el
+++ b/lisp/obsolete/vip.el
@@ -1,4 +1,4 @@
-;;; vip.el --- a VI Package for GNU Emacs
+;;; vip.el --- a VI Package for GNU Emacs  -*- lexical-binding: t; -*-
 
 ;; Copyright (C) 1986-1988, 1992-1993, 1998, 2001-2021 Free Software
 ;; Foundation, Inc.
@@ -95,13 +95,11 @@
 
 (defcustom vip-shift-width 8
   "The number of columns shifted by > and < command."
-  :type 'integer
-  :group 'vip)
+  :type 'integer)
 
 (defcustom vip-re-replace nil
   "If t then do regexp replace, if nil then do string replace."
-  :type 'boolean
-  :group 'vip)
+  :type 'boolean)
 
 (defvar vip-d-char nil
   "The character remembered by the vi \"r\" command.")
@@ -120,13 +118,11 @@
 
 (defcustom vip-search-wrap-around t
   "If t, search wraps around."
-  :type 'boolean
-  :group 'vip)
+  :type 'boolean)
 
 (defcustom vip-re-search nil
   "If t, search is reg-exp search, otherwise vanilla search."
-  :type 'boolean
-  :group 'vip)
+  :type 'boolean)
 
 (defvar vip-s-string nil
   "Last vip search string.")
@@ -136,24 +132,20 @@
 
 (defcustom vip-case-fold-search nil
   "If t, search ignores cases."
-  :type 'boolean
-  :group 'vip)
+  :type 'boolean)
 
 (defcustom vip-re-query-replace nil
   "If t then do regexp replace, if nil then do string replace."
-  :type 'boolean
-  :group 'vip)
+  :type 'boolean)
 
 (defcustom vip-open-with-indent nil
   "If t, indent when open a new line."
-  :type 'boolean
-  :group 'vip)
+  :type 'boolean)
 
 (defcustom vip-help-in-insert-mode nil
   "If t then C-h is bound to help-command in insert mode.
 If nil then it is bound to `delete-backward-char'."
-  :type 'boolean
-  :group 'vip)
+  :type 'boolean)
 
 (defvar vip-quote-string "> "
   "String inserted at the beginning of region.")
@@ -169,131 +161,131 @@ If nil then it is bound to `delete-backward-char'."
 
 (defvar vip-mode-map
   (let ((map (make-keymap)))
-    (define-key map "\C-a" 'beginning-of-line)
-    (define-key map "\C-b" 'vip-scroll-back)
-    (define-key map "\C-c" 'vip-ctl-c)
-    (define-key map "\C-d" 'vip-scroll-up)
-    (define-key map "\C-e" 'vip-scroll-up-one)
-    (define-key map "\C-f" 'vip-scroll)
-    (define-key map "\C-g" 'vip-keyboard-quit)
-    (define-key map "\C-h" 'help-command)
-    (define-key map "\C-m" 'vip-scroll-back)
-    (define-key map "\C-n" 'vip-other-window)
-    (define-key map "\C-o" 'vip-open-line-at-point)
-    (define-key map "\C-u" 'vip-scroll-down)
-    (define-key map "\C-x" 'vip-ctl-x)
-    (define-key map "\C-y" 'vip-scroll-down-one)
-    (define-key map "\C-z" 'vip-change-mode-to-emacs)
-    (define-key map "\e" 'vip-ESC)
-
-    (define-key map [?\S-\ ] 'vip-scroll-back)
-    (define-key map " " 'vip-scroll)
-    (define-key map "!" 'vip-command-argument)
-    (define-key map "\"" 'vip-command-argument)
-    (define-key map "#" 'vip-command-argument)
-    (define-key map "$" 'vip-goto-eol)
-    (define-key map "%" 'vip-paren-match)
-    (define-key map "&" 'vip-nil)
-    (define-key map "'" 'vip-goto-mark-and-skip-white)
-    (define-key map "(" 'vip-backward-sentence)
-    (define-key map ")" 'vip-forward-sentence)
-    (define-key map "*" 'call-last-kbd-macro)
-    (define-key map "+" 'vip-next-line-at-bol)
-    (define-key map "," 'vip-repeat-find-opposite)
-    (define-key map "-" 'vip-previous-line-at-bol)
-    (define-key map "." 'vip-repeat)
-    (define-key map "/" 'vip-search-forward)
-
-    (define-key map "0" 'vip-beginning-of-line)
-    (define-key map "1" 'vip-digit-argument)
-    (define-key map "2" 'vip-digit-argument)
-    (define-key map "3" 'vip-digit-argument)
-    (define-key map "4" 'vip-digit-argument)
-    (define-key map "5" 'vip-digit-argument)
-    (define-key map "6" 'vip-digit-argument)
-    (define-key map "7" 'vip-digit-argument)
-    (define-key map "8" 'vip-digit-argument)
-    (define-key map "9" 'vip-digit-argument)
-
-    (define-key map ":" 'vip-ex)
-    (define-key map ";" 'vip-repeat-find)
-    (define-key map "<" 'vip-command-argument)
-    (define-key map "=" 'vip-command-argument)
-    (define-key map ">" 'vip-command-argument)
-    (define-key map "?" 'vip-search-backward)
-    (define-key map "@" 'vip-nil)
-
-    (define-key map "A" 'vip-Append)
-    (define-key map "B" 'vip-backward-Word)
-    (define-key map "C" 'vip-ctl-c-equivalent)
-    (define-key map "D" 'vip-kill-line)
-    (define-key map "E" 'vip-end-of-Word)
-    (define-key map "F" 'vip-find-char-backward)
-    (define-key map "G" 'vip-goto-line)
-    (define-key map "H" 'vip-window-top)
-    (define-key map "I" 'vip-Insert)
-    (define-key map "J" 'vip-join-lines)
-    (define-key map "K" 'vip-kill-buffer)
-    (define-key map "L" 'vip-window-bottom)
-    (define-key map "M" 'vip-window-middle)
-    (define-key map "N" 'vip-search-Next)
-    (define-key map "O" 'vip-Open-line)
-    (define-key map "P" 'vip-Put-back)
-    (define-key map "Q" 'vip-query-replace)
-    (define-key map "R" 'vip-replace-string)
-    (define-key map "S" 'vip-switch-to-buffer-other-window)
-    (define-key map "T" 'vip-goto-char-backward)
-    (define-key map "U" 'vip-nil)
-    (define-key map "V" 'vip-find-file-other-window)
-    (define-key map "W" 'vip-forward-Word)
-    (define-key map "X" 'vip-ctl-x-equivalent)
-    (define-key map "Y" 'vip-yank-line)
-    (define-key map "ZZ" 'save-buffers-kill-emacs)
-
-    (define-key map "[" 'vip-nil)
-    (define-key map "\\" 'vip-escape-to-emacs)
-    (define-key map "]" 'vip-nil)
-    (define-key map "^" 'vip-bol-and-skip-white)
-    (define-key map "_" 'vip-nil)
-    (define-key map "`" 'vip-goto-mark)
-
-    (define-key map "a" 'vip-append)
-    (define-key map "b" 'vip-backward-word)
-    (define-key map "c" 'vip-command-argument)
-    (define-key map "d" 'vip-command-argument)
-    (define-key map "e" 'vip-end-of-word)
-    (define-key map "f" 'vip-find-char-forward)
-    (define-key map "g" 'vip-info-on-file)
-    (define-key map "h" 'vip-backward-char)
-    (define-key map "i" 'vip-insert)
-    (define-key map "j" 'vip-next-line)
-    (define-key map "k" 'vip-previous-line)
-    (define-key map "l" 'vip-forward-char)
-    (define-key map "m" 'vip-mark-point)
-    (define-key map "n" 'vip-search-next)
-    (define-key map "o" 'vip-open-line)
-    (define-key map "p" 'vip-put-back)
-    (define-key map "q" 'vip-nil)
-    (define-key map "r" 'vip-replace-char)
-    (define-key map "s" 'vip-switch-to-buffer)
-    (define-key map "t" 'vip-goto-char-forward)
-    (define-key map "u" 'vip-undo)
-    (define-key map "v" 'vip-find-file)
-    (define-key map "w" 'vip-forward-word)
-    (define-key map "x" 'vip-delete-char)
-    (define-key map "y" 'vip-command-argument)
-    (define-key map "zH" 'vip-line-to-top)
-    (define-key map "zM" 'vip-line-to-middle)
-    (define-key map "zL" 'vip-line-to-bottom)
-    (define-key map "z\C-m" 'vip-line-to-top)
-    (define-key map "z." 'vip-line-to-middle)
-    (define-key map "z-" 'vip-line-to-bottom)
-
-    (define-key map "{" 'vip-backward-paragraph)
-    (define-key map "|" 'vip-goto-col)
-    (define-key map "}" 'vip-forward-paragraph)
-    (define-key map "~" 'vip-nil)
-    (define-key map "\177" 'vip-delete-backward-char)
+    (define-key map "\C-a" #'beginning-of-line)
+    (define-key map "\C-b" #'vip-scroll-back)
+    (define-key map "\C-c" #'vip-ctl-c)
+    (define-key map "\C-d" #'vip-scroll-up)
+    (define-key map "\C-e" #'vip-scroll-up-one)
+    (define-key map "\C-f" #'vip-scroll)
+    (define-key map "\C-g" #'vip-keyboard-quit)
+    (define-key map "\C-h" #'help-command)
+    (define-key map "\C-m" #'vip-scroll-back)
+    (define-key map "\C-n" #'vip-other-window)
+    (define-key map "\C-o" #'vip-open-line-at-point)
+    (define-key map "\C-u" #'vip-scroll-down)
+    (define-key map "\C-x" #'vip-ctl-x)
+    (define-key map "\C-y" #'vip-scroll-down-one)
+    (define-key map "\C-z" #'vip-change-mode-to-emacs)
+    (define-key map "\e" #'vip-ESC)
+
+    (define-key map [?\S-\ ] #'vip-scroll-back)
+    (define-key map " " #'vip-scroll)
+    (define-key map "!" #'vip-command-argument)
+    (define-key map "\"" #'vip-command-argument)
+    (define-key map "#" #'vip-command-argument)
+    (define-key map "$" #'vip-goto-eol)
+    (define-key map "%" #'vip-paren-match)
+    (define-key map "&" #'vip-nil)
+    (define-key map "'" #'vip-goto-mark-and-skip-white)
+    (define-key map "(" #'vip-backward-sentence)
+    (define-key map ")" #'vip-forward-sentence)
+    (define-key map "*" #'call-last-kbd-macro)
+    (define-key map "+" #'vip-next-line-at-bol)
+    (define-key map "," #'vip-repeat-find-opposite)
+    (define-key map "-" #'vip-previous-line-at-bol)
+    (define-key map "." #'vip-repeat)
+    (define-key map "/" #'vip-search-forward)
+
+    (define-key map "0" #'vip-beginning-of-line)
+    (define-key map "1" #'vip-digit-argument)
+    (define-key map "2" #'vip-digit-argument)
+    (define-key map "3" #'vip-digit-argument)
+    (define-key map "4" #'vip-digit-argument)
+    (define-key map "5" #'vip-digit-argument)
+    (define-key map "6" #'vip-digit-argument)
+    (define-key map "7" #'vip-digit-argument)
+    (define-key map "8" #'vip-digit-argument)
+    (define-key map "9" #'vip-digit-argument)
+
+    (define-key map ":" #'vip-ex)
+    (define-key map ";" #'vip-repeat-find)
+    (define-key map "<" #'vip-command-argument)
+    (define-key map "=" #'vip-command-argument)
+    (define-key map ">" #'vip-command-argument)
+    (define-key map "?" #'vip-search-backward)
+    (define-key map "@" #'vip-nil)
+
+    (define-key map "A" #'vip-Append)
+    (define-key map "B" #'vip-backward-Word)
+    (define-key map "C" #'vip-ctl-c-equivalent)
+    (define-key map "D" #'vip-kill-line)
+    (define-key map "E" #'vip-end-of-Word)
+    (define-key map "F" #'vip-find-char-backward)
+    (define-key map "G" #'vip-goto-line)
+    (define-key map "H" #'vip-window-top)
+    (define-key map "I" #'vip-Insert)
+    (define-key map "J" #'vip-join-lines)
+    (define-key map "K" #'vip-kill-buffer)
+    (define-key map "L" #'vip-window-bottom)
+    (define-key map "M" #'vip-window-middle)
+    (define-key map "N" #'vip-search-Next)
+    (define-key map "O" #'vip-Open-line)
+    (define-key map "P" #'vip-Put-back)
+    (define-key map "Q" #'vip-query-replace)
+    (define-key map "R" #'vip-replace-string)
+    (define-key map "S" #'vip-switch-to-buffer-other-window)
+    (define-key map "T" #'vip-goto-char-backward)
+    (define-key map "U" #'vip-nil)
+    (define-key map "V" #'vip-find-file-other-window)
+    (define-key map "W" #'vip-forward-Word)
+    (define-key map "X" #'vip-ctl-x-equivalent)
+    (define-key map "Y" #'vip-yank-line)
+    (define-key map "ZZ" #'save-buffers-kill-emacs)
+
+    (define-key map "[" #'vip-nil)
+    (define-key map "\\" #'vip-escape-to-emacs)
+    (define-key map "]" #'vip-nil)
+    (define-key map "^" #'vip-bol-and-skip-white)
+    (define-key map "_" #'vip-nil)
+    (define-key map "`" #'vip-goto-mark)
+
+    (define-key map "a" #'vip-append)
+    (define-key map "b" #'vip-backward-word)
+    (define-key map "c" #'vip-command-argument)
+    (define-key map "d" #'vip-command-argument)
+    (define-key map "e" #'vip-end-of-word)
+    (define-key map "f" #'vip-find-char-forward)
+    (define-key map "g" #'vip-info-on-file)
+    (define-key map "h" #'vip-backward-char)
+    (define-key map "i" #'vip-insert)
+    (define-key map "j" #'vip-next-line)
+    (define-key map "k" #'vip-previous-line)
+    (define-key map "l" #'vip-forward-char)
+    (define-key map "m" #'vip-mark-point)
+    (define-key map "n" #'vip-search-next)
+    (define-key map "o" #'vip-open-line)
+    (define-key map "p" #'vip-put-back)
+    (define-key map "q" #'vip-nil)
+    (define-key map "r" #'vip-replace-char)
+    (define-key map "s" #'vip-switch-to-buffer)
+    (define-key map "t" #'vip-goto-char-forward)
+    (define-key map "u" #'vip-undo)
+    (define-key map "v" #'vip-find-file)
+    (define-key map "w" #'vip-forward-word)
+    (define-key map "x" #'vip-delete-char)
+    (define-key map "y" #'vip-command-argument)
+    (define-key map "zH" #'vip-line-to-top)
+    (define-key map "zM" #'vip-line-to-middle)
+    (define-key map "zL" #'vip-line-to-bottom)
+    (define-key map "z\C-m" #'vip-line-to-top)
+    (define-key map "z." #'vip-line-to-middle)
+    (define-key map "z-" #'vip-line-to-bottom)
+
+    (define-key map "{" #'vip-backward-paragraph)
+    (define-key map "|" #'vip-goto-col)
+    (define-key map "}" #'vip-forward-paragraph)
+    (define-key map "~" #'vip-nil)
+    (define-key map "\177" #'vip-delete-backward-char)
     map))
 
 (defun vip-version ()
@@ -306,8 +298,8 @@ If nil then it is bound to `delete-backward-char'."
 ;;;###autoload
 (defun vip-setup ()
   "Set up bindings for C-x 7 and C-z that are useful for VIP users."
-  (define-key ctl-x-map "7" 'vip-buffer-in-two-windows)
-  (global-set-key "\C-z" 'vip-change-mode-to-vi))
+  (define-key ctl-x-map "7" #'vip-buffer-in-two-windows)
+  (global-set-key "\C-z" #'vip-change-mode-to-vi))
 
 (defmacro vip-loop (count body)
   "(COUNT BODY) Execute BODY COUNT times."
@@ -375,13 +367,13 @@ No message."
                                             vip-emacs-local-map)))
               (vip-change-mode-line "Insert")
               (use-local-map vip-insert-local-map)
-              (define-key vip-insert-local-map "\e" 'vip-change-mode-to-vi)
-              (define-key vip-insert-local-map "\C-z" 'vip-ESC)
+              (define-key vip-insert-local-map "\e" #'vip-change-mode-to-vi)
+              (define-key vip-insert-local-map "\C-z" #'vip-ESC)
               (define-key vip-insert-local-map "\C-h"
-                (if vip-help-in-insert-mode 'help-command
-                  'delete-backward-char))
+                (if vip-help-in-insert-mode #'help-command
+                  #'delete-backward-char))
               (define-key vip-insert-local-map "\C-w"
-                'vip-delete-backward-word))
+                #'vip-delete-backward-word))
              ((eq new-mode 'emacs-mode)
               (vip-change-mode-line "Emacs:")
               (use-local-map vip-emacs-local-map)))
@@ -461,13 +453,13 @@ Type `n' to quit this window for now.\n")
 ARG is used as the prefix value for the executed command.  If
 EVENTS is a list of events, which become the beginning of the command."
   (interactive "P")
-  (let (com key (old-map (current-local-map)))
+  (let (com (old-map (current-local-map)))
     (if events (setq unread-command-events
                      (append events unread-command-events)))
     (setq prefix-arg arg)
     (use-local-map vip-emacs-local-map)
     (unwind-protect
-       (setq com (key-binding (setq key (read-key-sequence nil))))
+       (setq com (key-binding (read-key-sequence nil)))
       (use-local-map old-map))
     (command-execute com prefix-arg)
     (setq prefix-arg nil)  ;; reset prefix arg
@@ -617,7 +609,7 @@ obtained so far, and COM is the command part obtained so 
far."
 (defun vip-command-argument (arg)
   "Accept a motion command as an argument."
   (interactive "P")
-  (condition-case conditions
+  (condition-case nil
       (vip-prefix-arg-com
        last-command-event
        (cond ((null arg) nil)
@@ -918,11 +910,11 @@ each line in the region."
 
 (defun vip-read-string (prompt &optional init)
   (setq vip-save-minibuffer-local-map (copy-keymap minibuffer-local-map))
-  (define-key minibuffer-local-map "\C-h" 'backward-char)
-  (define-key minibuffer-local-map "\C-w" 'backward-word)
-  (define-key minibuffer-local-map "\e" 'exit-minibuffer)
+  (define-key minibuffer-local-map "\C-h" #'backward-char)
+  (define-key minibuffer-local-map "\C-w" #'backward-word)
+  (define-key minibuffer-local-map "\e" #'exit-minibuffer)
   (let (str)
-    (condition-case conditions
+    (condition-case nil
        (setq str (read-string prompt init))
       (quit
        (setq minibuffer-local-map vip-save-minibuffer-local-map)
@@ -2651,7 +2643,7 @@ a token has type \(command, address, end-mark) and value."
          (progn
            (with-output-to-temp-buffer " *delete text*"
              (princ (buffer-substring (point) (mark))))
-           (condition-case conditions
+           (condition-case nil
                (vip-read-string "[Hit return to continue] ")
              (quit
               (save-excursion (kill-buffer " *delete text*"))
@@ -2759,7 +2751,7 @@ a token has type \(command, address, end-mark) and value."
          (progn
            (with-output-to-temp-buffer " *text*"
              (princ (buffer-substring (point) (mark))))
-           (condition-case conditions
+           (condition-case nil
                (progn
                  (vip-read-string "[Hit return to continue] ")
                  (ex-line-subr com (point) (mark)))
@@ -2829,12 +2821,9 @@ a token has type \(command, address, end-mark) and 
value."
        (define-key ex-map char
          (or (lookup-key vip-mode-map char) 'vip-nil)))
     (define-key vip-mode-map char
-      (eval
-       (list 'quote
-            (cons 'lambda
-                  (list '(count)
-                        '(interactive "p")
-                        (list 'execute-kbd-macro string 'count))))))))
+      (lambda (count)
+       (interactive "p")
+       (execute-kbd-macro string count)))))
 
 (defun ex-unmap ()
   "ex unmap"
@@ -2892,10 +2881,7 @@ a token has type \(command, address, end-mark) and 
value."
        (with-no-warnings
          (insert-file file)))))
 
-(defun ex-set ()
-  (eval (list 'setq
-             (read-variable "Variable: ")
-             (eval (read-minibuffer "Value: ")))))
+(defalias 'ex-set #'set-variable)
 
 (defun ex-shell ()
   "ex shell"
@@ -2935,7 +2921,7 @@ vip-s-string"
            (setq ex-addresses (cons (car ex-addresses) ex-addresses)))))
     ;(setq G opt-g)
     (let ((beg (car ex-addresses)) (end (car (cdr ex-addresses)))
-         (cont t) eol-mark)
+         eol-mark) ;;(cont t)
       (save-excursion
        (vip-enlarge-region beg end)
        (let ((limit (save-excursion
diff --git a/lisp/obsolete/ws-mode.el b/lisp/obsolete/ws-mode.el
index d1ced86..235a1d7 100644
--- a/lisp/obsolete/ws-mode.el
+++ b/lisp/obsolete/ws-mode.el
@@ -41,144 +41,144 @@
 (defvar wordstar-C-k-map
   (let ((map (make-keymap)))
     (define-key map " " ())
-    (define-key map "0" 'ws-set-marker-0)
-    (define-key map "1" 'ws-set-marker-1)
-    (define-key map "2" 'ws-set-marker-2)
-    (define-key map "3" 'ws-set-marker-3)
-    (define-key map "4" 'ws-set-marker-4)
-    (define-key map "5" 'ws-set-marker-5)
-    (define-key map "6" 'ws-set-marker-6)
-    (define-key map "7" 'ws-set-marker-7)
-    (define-key map "8" 'ws-set-marker-8)
-    (define-key map "9" 'ws-set-marker-9)
-    (define-key map "b" 'ws-begin-block)
-    (define-key map "\C-b" 'ws-begin-block)
-    (define-key map "c" 'ws-copy-block)
-    (define-key map "\C-c" 'ws-copy-block)
-    (define-key map "d" 'save-buffers-kill-emacs)
-    (define-key map "\C-d" 'save-buffers-kill-emacs)
-    (define-key map "f" 'find-file)
-    (define-key map "\C-f" 'find-file)
-    (define-key map "h" 'ws-show-markers)
-    (define-key map "\C-h" 'ws-show-markers)
-    (define-key map "i" 'ws-indent-block)
-    (define-key map "\C-i" 'ws-indent-block)
-    (define-key map "k" 'ws-end-block)
-    (define-key map "\C-k" 'ws-end-block)
-    (define-key map "p" 'ws-print-block)
-    (define-key map "\C-p" 'ws-print-block)
-    (define-key map "q" 'kill-emacs)
-    (define-key map "\C-q" 'kill-emacs)
-    (define-key map "r" 'insert-file)
-    (define-key map "\C-r" 'insert-file)
-    (define-key map "s" 'save-some-buffers)
-    (define-key map "\C-s" 'save-some-buffers)
-    (define-key map "t" 'ws-mark-word)
-    (define-key map "\C-t" 'ws-mark-word)
-    (define-key map "u" 'ws-exdent-block)
-    (define-key map "\C-u" 'keyboard-quit)
-    (define-key map "v" 'ws-move-block)
-    (define-key map "\C-v" 'ws-move-block)
-    (define-key map "w" 'ws-write-block)
-    (define-key map "\C-w" 'ws-write-block)
-    (define-key map "x" 'save-buffers-kill-emacs)
-    (define-key map "\C-x" 'save-buffers-kill-emacs)
-    (define-key map "y" 'ws-delete-block)
-    (define-key map "\C-y" 'ws-delete-block)
+    (define-key map "0" #'ws-set-marker-0)
+    (define-key map "1" #'ws-set-marker-1)
+    (define-key map "2" #'ws-set-marker-2)
+    (define-key map "3" #'ws-set-marker-3)
+    (define-key map "4" #'ws-set-marker-4)
+    (define-key map "5" #'ws-set-marker-5)
+    (define-key map "6" #'ws-set-marker-6)
+    (define-key map "7" #'ws-set-marker-7)
+    (define-key map "8" #'ws-set-marker-8)
+    (define-key map "9" #'ws-set-marker-9)
+    (define-key map "b" #'ws-begin-block)
+    (define-key map "\C-b" #'ws-begin-block)
+    (define-key map "c" #'ws-copy-block)
+    (define-key map "\C-c" #'ws-copy-block)
+    (define-key map "d" #'save-buffers-kill-emacs)
+    (define-key map "\C-d" #'save-buffers-kill-emacs)
+    (define-key map "f" #'find-file)
+    (define-key map "\C-f" #'find-file)
+    (define-key map "h" #'ws-show-markers)
+    (define-key map "\C-h" #'ws-show-markers)
+    (define-key map "i" #'ws-indent-block)
+    (define-key map "\C-i" #'ws-indent-block)
+    (define-key map "k" #'ws-end-block)
+    (define-key map "\C-k" #'ws-end-block)
+    (define-key map "p" #'ws-print-block)
+    (define-key map "\C-p" #'ws-print-block)
+    (define-key map "q" #'kill-emacs)
+    (define-key map "\C-q" #'kill-emacs)
+    (define-key map "r" #'insert-file)
+    (define-key map "\C-r" #'insert-file)
+    (define-key map "s" #'save-some-buffers)
+    (define-key map "\C-s" #'save-some-buffers)
+    (define-key map "t" #'ws-mark-word)
+    (define-key map "\C-t" #'ws-mark-word)
+    (define-key map "u" #'ws-exdent-block)
+    (define-key map "\C-u" #'keyboard-quit)
+    (define-key map "v" #'ws-move-block)
+    (define-key map "\C-v" #'ws-move-block)
+    (define-key map "w" #'ws-write-block)
+    (define-key map "\C-w" #'ws-write-block)
+    (define-key map "x" #'save-buffers-kill-emacs)
+    (define-key map "\C-x" #'save-buffers-kill-emacs)
+    (define-key map "y" #'ws-delete-block)
+    (define-key map "\C-y" #'ws-delete-block)
     map))
 
 (defvar wordstar-C-o-map
   (let ((map (make-keymap)))
     (define-key map " " ())
-    (define-key map "c" 'wordstar-center-line)
-    (define-key map "\C-c" 'wordstar-center-line)
-    (define-key map "b" 'switch-to-buffer)
-    (define-key map "\C-b" 'switch-to-buffer)
-    (define-key map "j" 'justify-current-line)
-    (define-key map "\C-j" 'justify-current-line)
-    (define-key map "k" 'kill-buffer)
-    (define-key map "\C-k" 'kill-buffer)
-    (define-key map "l" 'list-buffers)
-    (define-key map "\C-l" 'list-buffers)
-    (define-key map "m" 'auto-fill-mode)
-    (define-key map "\C-m" 'auto-fill-mode)
-    (define-key map "r" 'set-fill-column)
-    (define-key map "\C-r" 'set-fill-column)
-    (define-key map "\C-u" 'keyboard-quit)
-    (define-key map "wd" 'delete-other-windows)
-    (define-key map "wh" 'split-window-right)
-    (define-key map "wo" 'other-window)
-    (define-key map "wv" 'split-window-below)
+    (define-key map "c" #'wordstar-center-line)
+    (define-key map "\C-c" #'wordstar-center-line)
+    (define-key map "b" #'switch-to-buffer)
+    (define-key map "\C-b" #'switch-to-buffer)
+    (define-key map "j" #'justify-current-line)
+    (define-key map "\C-j" #'justify-current-line)
+    (define-key map "k" #'kill-buffer)
+    (define-key map "\C-k" #'kill-buffer)
+    (define-key map "l" #'list-buffers)
+    (define-key map "\C-l" #'list-buffers)
+    (define-key map "m" #'auto-fill-mode)
+    (define-key map "\C-m" #'auto-fill-mode)
+    (define-key map "r" #'set-fill-column)
+    (define-key map "\C-r" #'set-fill-column)
+    (define-key map "\C-u" #'keyboard-quit)
+    (define-key map "wd" #'delete-other-windows)
+    (define-key map "wh" #'split-window-right)
+    (define-key map "wo" #'other-window)
+    (define-key map "wv" #'split-window-below)
     map))
 
 (defvar wordstar-C-q-map
   (let ((map (make-keymap)))
     (define-key map " " ())
-    (define-key map "0" 'ws-find-marker-0)
-    (define-key map "1" 'ws-find-marker-1)
-    (define-key map "2" 'ws-find-marker-2)
-    (define-key map "3" 'ws-find-marker-3)
-    (define-key map "4" 'ws-find-marker-4)
-    (define-key map "5" 'ws-find-marker-5)
-    (define-key map "6" 'ws-find-marker-6)
-    (define-key map "7" 'ws-find-marker-7)
-    (define-key map "8" 'ws-find-marker-8)
-    (define-key map "9" 'ws-find-marker-9)
-    (define-key map "a" 'ws-query-replace)
-    (define-key map "\C-a" 'ws-query-replace)
-    (define-key map "b" 'ws-goto-block-begin)
-    (define-key map "\C-b" 'ws-goto-block-begin)
-    (define-key map "c" 'end-of-buffer)
-    (define-key map "\C-c" 'end-of-buffer)
-    (define-key map "d" 'end-of-line)
-    (define-key map "\C-d" 'end-of-line)
-    (define-key map "f" 'ws-search)
-    (define-key map "\C-f" 'ws-search)
-    (define-key map "k" 'ws-goto-block-end)
-    (define-key map "\C-k" 'ws-goto-block-end)
-    (define-key map "l" 'ws-undo)
-    (define-key map "\C-l" 'ws-undo)
-    (define-key map "p" 'ws-last-cursorp)
-    (define-key map "\C-p" 'ws-last-cursorp)
-    (define-key map "r" 'beginning-of-buffer)
-    (define-key map "\C-r" 'beginning-of-buffer)
-    (define-key map "s" 'beginning-of-line)
-    (define-key map "\C-s" 'beginning-of-line)
-    (define-key map "\C-u" 'keyboard-quit)
-    (define-key map "w" 'ws-last-error)
-    (define-key map "\C-w" 'ws-last-error)
-    (define-key map "y" 'ws-kill-eol)
-    (define-key map "\C-y" 'ws-kill-eol)
-    (define-key map "\177" 'ws-kill-bol)
+    (define-key map "0" #'ws-find-marker-0)
+    (define-key map "1" #'ws-find-marker-1)
+    (define-key map "2" #'ws-find-marker-2)
+    (define-key map "3" #'ws-find-marker-3)
+    (define-key map "4" #'ws-find-marker-4)
+    (define-key map "5" #'ws-find-marker-5)
+    (define-key map "6" #'ws-find-marker-6)
+    (define-key map "7" #'ws-find-marker-7)
+    (define-key map "8" #'ws-find-marker-8)
+    (define-key map "9" #'ws-find-marker-9)
+    (define-key map "a" #'ws-query-replace)
+    (define-key map "\C-a" #'ws-query-replace)
+    (define-key map "b" #'ws-goto-block-begin)
+    (define-key map "\C-b" #'ws-goto-block-begin)
+    (define-key map "c" #'end-of-buffer)
+    (define-key map "\C-c" #'end-of-buffer)
+    (define-key map "d" #'end-of-line)
+    (define-key map "\C-d" #'end-of-line)
+    (define-key map "f" #'ws-search)
+    (define-key map "\C-f" #'ws-search)
+    (define-key map "k" #'ws-goto-block-end)
+    (define-key map "\C-k" #'ws-goto-block-end)
+    (define-key map "l" #'ws-undo)
+    (define-key map "\C-l" #'ws-undo)
+    ;; (define-key map "p" #'ws-last-cursorp)
+    ;; (define-key map "\C-p" #'ws-last-cursorp)
+    (define-key map "r" #'beginning-of-buffer)
+    (define-key map "\C-r" #'beginning-of-buffer)
+    (define-key map "s" #'beginning-of-line)
+    (define-key map "\C-s" #'beginning-of-line)
+    (define-key map "\C-u" #'keyboard-quit)
+    (define-key map "w" #'ws-last-error)
+    (define-key map "\C-w" #'ws-last-error)
+    (define-key map "y" #'ws-kill-eol)
+    (define-key map "\C-y" #'ws-kill-eol)
+    (define-key map "\177" #'ws-kill-bol)
     map))
 
 (defvar wordstar-mode-map
   (let ((map (make-keymap)))
-    (define-key map "\C-a" 'backward-word)
-    (define-key map "\C-b" 'fill-paragraph)
-    (define-key map "\C-c" 'scroll-up-command)
-    (define-key map "\C-d" 'forward-char)
-    (define-key map "\C-e" 'previous-line)
-    (define-key map "\C-f" 'forward-word)
-    (define-key map "\C-g" 'delete-char)
-    (define-key map "\C-h" 'backward-char)
-    (define-key map "\C-i" 'indent-for-tab-command)
-    (define-key map "\C-j" 'help-for-help)
+    (define-key map "\C-a" #'backward-word)
+    (define-key map "\C-b" #'fill-paragraph)
+    (define-key map "\C-c" #'scroll-up-command)
+    (define-key map "\C-d" #'forward-char)
+    (define-key map "\C-e" #'previous-line)
+    (define-key map "\C-f" #'forward-word)
+    (define-key map "\C-g" #'delete-char)
+    (define-key map "\C-h" #'backward-char)
+    (define-key map "\C-i" #'indent-for-tab-command)
+    (define-key map "\C-j" #'help-for-help)
     (define-key map "\C-k" wordstar-C-k-map)
-    (define-key map "\C-l" 'ws-repeat-search)
-    (define-key map "\C-n" 'open-line)
+    (define-key map "\C-l" #'ws-repeat-search)
+    (define-key map "\C-n" #'open-line)
     (define-key map "\C-o" wordstar-C-o-map)
-    (define-key map "\C-p" 'quoted-insert)
+    (define-key map "\C-p" #'quoted-insert)
     (define-key map "\C-q" wordstar-C-q-map)
-    (define-key map "\C-r" 'scroll-down-command)
-    (define-key map "\C-s" 'backward-char)
-    (define-key map "\C-t" 'kill-word)
-    (define-key map "\C-u" 'keyboard-quit)
-    (define-key map "\C-v" 'overwrite-mode)
-    (define-key map "\C-w" 'scroll-down-line)
-    (define-key map "\C-x" 'next-line)
-    (define-key map "\C-y" 'kill-complete-line)
-    (define-key map "\C-z" 'scroll-up-line)
+    (define-key map "\C-r" #'scroll-down-command)
+    (define-key map "\C-s" #'backward-char)
+    (define-key map "\C-t" #'kill-word)
+    (define-key map "\C-u" #'keyboard-quit)
+    (define-key map "\C-v" #'overwrite-mode)
+    (define-key map "\C-w" #'scroll-down-line)
+    (define-key map "\C-x" #'next-line)
+    (define-key map "\C-y" #'kill-complete-line)
+    (define-key map "\C-z" #'scroll-up-line)
     map))
 
 ;; wordstar-C-j-map not yet implemented
diff --git a/lisp/obsolete/yow.el b/lisp/obsolete/yow.el
index 76485f9..ca8de4f 100644
--- a/lisp/obsolete/yow.el
+++ b/lisp/obsolete/yow.el
@@ -1,4 +1,4 @@
-;;; yow.el --- quote random zippyisms
+;;; yow.el --- quote random zippyisms  -*- lexical-binding: t; -*-
 
 ;; Copyright (C) 1993-1995, 2000-2021 Free Software Foundation, Inc.
 
@@ -39,8 +39,7 @@
 
 (defcustom yow-file (expand-file-name "yow.lines" data-directory)
    "File containing pertinent pinhead phrases."
-  :type 'file
-  :group 'yow)
+  :type 'file)
 
 (defconst yow-load-message "Am I CONSING yet?...")
 (defconst yow-after-load-message "I have SEEN the CONSING!!")
diff --git a/lisp/org/ob-clojure.el b/lisp/org/ob-clojure.el
index df2d691..9834509 100644
--- a/lisp/org/ob-clojure.el
+++ b/lisp/org/ob-clojure.el
@@ -38,7 +38,7 @@
 
 ;; For SLIME, the best way to install these components is by following
 ;; the directions as set out by Phil Hagelberg (Technomancy) on the
-;; web page: http://technomancy.us/126
+;; web page: https://technomancy.us/126
 
 ;;; Code:
 (require 'ob)
diff --git a/lisp/org/ob-comint.el b/lisp/org/ob-comint.el
index 18d4f3c..b14849d 100644
--- a/lisp/org/ob-comint.el
+++ b/lisp/org/ob-comint.el
@@ -44,7 +44,7 @@
 BUFFER is checked with `org-babel-comint-buffer-livep'.  BODY is
 executed inside the protection of `save-excursion' and
 `save-match-data'."
-  (declare (indent 1))
+  (declare (indent 1) (debug t))
   `(progn
      (unless (org-babel-comint-buffer-livep ,buffer)
        (error "Buffer %s does not exist or has no process" ,buffer))
@@ -53,7 +53,6 @@ executed inside the protection of `save-excursion' and
         (save-excursion
           (let ((comint-input-filter (lambda (_input) nil)))
             ,@body))))))
-(def-edebug-spec org-babel-comint-in-buffer (form body))
 
 (defmacro org-babel-comint-with-output (meta &rest body)
   "Evaluate BODY in BUFFER and return process output.
@@ -67,7 +66,7 @@ elements are optional.
 
 This macro ensures that the filter is removed in case of an error
 or user `keyboard-quit' during execution of body."
-  (declare (indent 1))
+  (declare (indent 1) (debug (sexp body)))
   (let ((buffer (nth 0 meta))
        (eoe-indicator (nth 1 meta))
        (remove-echo (nth 2 meta))
@@ -112,7 +111,6 @@ or user `keyboard-quit' during execution of body."
                     string-buffer))
           (setq string-buffer (substring string-buffer (match-end 0))))
         (split-string string-buffer comint-prompt-regexp)))))
-(def-edebug-spec org-babel-comint-with-output (sexp body))
 
 (defun org-babel-comint-input-command (buffer cmd)
   "Pass CMD to BUFFER.
diff --git a/lisp/org/ob-core.el b/lisp/org/ob-core.el
index 1343410..b1fd694 100644
--- a/lisp/org/ob-core.el
+++ b/lisp/org/ob-core.el
@@ -1100,7 +1100,7 @@ end-header-args -- point at the end of the header-args
 body ------------- string holding the body of the code block
 beg-body --------- point at the beginning of the body
 end-body --------- point at the end of the body"
-  (declare (indent 1))
+  (declare (indent 1) (debug t))
   (let ((tempvar (make-symbol "file")))
     `(let* ((case-fold-search t)
            (,tempvar ,file)
@@ -1139,7 +1139,6 @@ end-body --------- point at the end of the body"
               (goto-char end-block)))))
        (unless visited-p (kill-buffer to-be-removed))
        (goto-char point))))
-(def-edebug-spec org-babel-map-src-blocks (form body))
 
 ;;;###autoload
 (defmacro org-babel-map-inline-src-blocks (file &rest body)
@@ -1354,7 +1353,7 @@ the `org-mode-hook'."
        (goto-char (match-beginning 0))
        (org-babel-hide-hash)
        (goto-char (match-end 0))))))
-(add-hook 'org-mode-hook 'org-babel-hide-all-hashes)
+(add-hook 'org-mode-hook #'org-babel-hide-all-hashes)
 
 (defun org-babel-hash-at-point (&optional point)
   "Return the value of the hash at POINT.
@@ -1372,7 +1371,7 @@ This can be called with `\\[org-ctrl-c-ctrl-c]'."
 Add `org-babel-hide-result' as an invisibility spec for hiding
 portions of results lines."
   (add-to-invisibility-spec '(org-babel-hide-result . t)))
-(add-hook 'org-mode-hook 'org-babel-result-hide-spec)
+(add-hook 'org-mode-hook #'org-babel-result-hide-spec)
 
 (defvar org-babel-hide-result-overlays nil
   "Overlays hiding results.")
@@ -1443,11 +1442,11 @@ portions of results lines."
        (push ov org-babel-hide-result-overlays)))))
 
 ;; org-tab-after-check-for-cycling-hook
-(add-hook 'org-tab-first-hook 'org-babel-hide-result-toggle-maybe)
+(add-hook 'org-tab-first-hook #'org-babel-hide-result-toggle-maybe)
 ;; Remove overlays when changing major mode
 (add-hook 'org-mode-hook
          (lambda () (add-hook 'change-major-mode-hook
-                         'org-babel-show-result-all 'append 'local)))
+                         #'org-babel-show-result-all 'append 'local)))
 
 (defun org-babel-params-from-properties (&optional lang no-eval)
   "Retrieve source block parameters specified as properties.
@@ -3075,8 +3074,7 @@ Emacs shutdown."))
 
 (defmacro org-babel-result-cond (result-params scalar-form &rest table-forms)
   "Call the code to parse raw string results according to RESULT-PARAMS."
-  (declare (indent 1)
-          (debug (form form &rest form)))
+  (declare (indent 1) (debug t))
   (org-with-gensyms (params)
     `(let ((,params ,result-params))
        (unless (member "none" ,params)
@@ -3093,7 +3091,6 @@ Emacs shutdown."))
                      (not (member "table" ,params))))
             ,scalar-form
           ,@table-forms)))))
-(def-edebug-spec org-babel-result-cond (form form body))
 
 (defun org-babel-temp-file (prefix &optional suffix)
   "Create a temporary file in the `org-babel-temporary-directory'.
@@ -3136,7 +3133,7 @@ of `org-babel-temporary-directory'."
                    org-babel-temporary-directory
                  "[directory not defined]"))))))
 
-(add-hook 'kill-emacs-hook 'org-babel-remove-temporary-directory)
+(add-hook 'kill-emacs-hook #'org-babel-remove-temporary-directory)
 
 (defun org-babel-one-header-arg-safe-p (pair safe-list)
   "Determine if the PAIR is a safe babel header arg according to SAFE-LIST.
diff --git a/lisp/org/ob-lilypond.el b/lisp/org/ob-lilypond.el
index fbdd905..47397e6 100644
--- a/lisp/org/ob-lilypond.el
+++ b/lisp/org/ob-lilypond.el
@@ -220,7 +220,7 @@ If error in compilation, attempt to mark the error in 
lilypond org file."
 FILE-NAME is full path to lilypond (.ly) file."
   (message "Compiling LilyPond...")
   (let ((arg-1 org-babel-lilypond-ly-command) ;program
-        (arg-2 nil)                    ;infile
+        ;; (arg-2 nil)                    ;infile
         (arg-3 "*lilypond*")           ;buffer
        (arg-4 t)                      ;display
        (arg-5 (if org-babel-lilypond-gen-png  "--png"  "")) ;&rest...
@@ -231,10 +231,10 @@ FILE-NAME is full path to lilypond (.ly) file."
         (arg-10 (concat "--output=" (file-name-sans-extension file-name)))
         (arg-11 file-name))
     (if test
-        `(,arg-1 ,arg-2 ,arg-3 ,arg-4 ,arg-5 ,arg-6
+        `(,arg-1 ,nil ,arg-3 ,arg-4 ,arg-5 ,arg-6 ;; arg-2
                  ,arg-7 ,arg-8 ,arg-9 ,arg-10 ,arg-11)
       (call-process
-       arg-1 arg-2 arg-3 arg-4 arg-5 arg-6
+       arg-1 nil arg-3 arg-4 arg-5 arg-6 ;; arg-2
        arg-7 arg-8 arg-9 arg-10 arg-11))))
 
 (defun org-babel-lilypond-check-for-compile-error (file-name &optional test)
diff --git a/lisp/org/ob-ocaml.el b/lisp/org/ob-ocaml.el
index 0aa91af..5fd6d1e 100644
--- a/lisp/org/ob-ocaml.el
+++ b/lisp/org/ob-ocaml.el
@@ -32,7 +32,7 @@
 
 ;;; Requirements:
 
-;; - tuareg-mode :: http://www-rocq.inria.fr/~acohen/tuareg/
+;; - tuareg-mode :: https://www-rocq.inria.fr/~acohen/tuareg/
 
 ;;; Code:
 (require 'ob)
diff --git a/lisp/org/ob-tangle.el b/lisp/org/ob-tangle.el
index 3c3943c..aa0373a 100644
--- a/lisp/org/ob-tangle.el
+++ b/lisp/org/ob-tangle.el
@@ -150,7 +150,7 @@ represented in the file."
   "Open FILE into a temporary buffer execute BODY there like
 `progn', then kill the FILE buffer returning the result of
 evaluating BODY."
-  (declare (indent 1))
+  (declare (indent 1) (debug t))
   (let ((temp-path (make-symbol "temp-path"))
        (temp-result (make-symbol "temp-result"))
        (temp-file (make-symbol "temp-file"))
@@ -164,7 +164,6 @@ evaluating BODY."
         (setf ,temp-result (progn ,@body)))
        (unless ,visited-p (kill-buffer ,temp-file))
        ,temp-result)))
-(def-edebug-spec org-babel-with-temp-filebuffer (form body))
 
 ;;;###autoload
 (defun org-babel-tangle-file (file &optional target-file lang-re)
diff --git a/lisp/org/ol-gnus.el b/lisp/org/ol-gnus.el
index 71051bc..2d51447 100644
--- a/lisp/org/ol-gnus.el
+++ b/lisp/org/ol-gnus.el
@@ -198,11 +198,11 @@ If `org-store-link' was called with a prefix arg the 
meaning of
               (to (mail-fetch-field "To"))
               (from (mail-fetch-field "From"))
               (subject (mail-fetch-field "Subject"))
-              newsgroup xarchive)      ;those are always nil for gcc
+              ) ;; newsgroup xarchive  ;those are always nil for gcc
           (unless gcc (error "Can not create link: No Gcc header found"))
           (org-link-store-props :type "gnus" :from from :subject subject
                                 :message-id id :group gcc :to to)
-          (let ((link (org-gnus-article-link gcc newsgroup id xarchive))
+          (let ((link (org-gnus-article-link gcc nil id nil)) ;;newsgroup 
xarchive
                 (description (org-link-email-description)))
             (org-link-add-props :link link :description description)
             link)))))))
diff --git a/lisp/org/ol.el b/lisp/org/ol.el
index 994e30f..38e2dd6 100644
--- a/lisp/org/ol.el
+++ b/lisp/org/ol.el
@@ -591,7 +591,7 @@ handle this as a special case.
 
 When the function does handle the link, it must return a non-nil value.
 If it decides that it is not responsible for this link, it must return
-nil to indicate that that Org can continue with other options like
+nil to indicate that Org can continue with other options like
 exact and fuzzy text search.")
 
 
@@ -1467,7 +1467,7 @@ non-nil."
            (move-beginning-of-line 2)
            (set-mark (point)))))
     (setq org-store-link-plist nil)
-    (let (link cpltxt desc description search custom-id agenda-link)
+    (let (link cpltxt desc search custom-id agenda-link) ;; description
       (cond
        ;; Store a link using an external link type, if any function is
        ;; available. If more than one can generate a link from current
@@ -1598,7 +1598,7 @@ non-nil."
                      'org-create-file-search-functions))
        (setq link (concat "file:" (abbreviate-file-name buffer-file-name)
                           "::" search))
-       (setq cpltxt (or description link)))
+       (setq cpltxt (or link))) ;; description
 
        ((and (buffer-file-name (buffer-base-buffer)) (derived-mode-p 
'org-mode))
        (org-with-limited-levels
diff --git a/lisp/org/org-agenda.el b/lisp/org/org-agenda.el
index 99e5464..8a4aa2b 100644
--- a/lisp/org/org-agenda.el
+++ b/lisp/org/org-agenda.el
@@ -2090,6 +2090,7 @@ Note that functions in this alist don't need to be 
quoted."
 If STRING is non-nil, the text property will be fetched from position 0
 in that string.  If STRING is nil, it will be fetched from the beginning
 of the current line."
+  (declare (debug t))
   (org-with-gensyms (marker)
     `(let ((,marker (get-text-property (if ,string 0 (point-at-bol))
                                       'org-hd-marker ,string)))
@@ -2097,7 +2098,6 @@ of the current line."
         (save-excursion
           (goto-char ,marker)
           ,@body)))))
-(def-edebug-spec org-agenda-with-point-at-orig-entry (form body))
 
 (defun org-add-agenda-custom-command (entry)
   "Replace or add a command in `org-agenda-custom-commands'.
@@ -3224,6 +3224,15 @@ s   Search for keywords                 M   Like m, but 
only TODO entries
 (defvar org-agenda-overriding-cmd nil)
 (defvar org-agenda-overriding-arguments nil)
 (defvar org-agenda-overriding-cmd-arguments nil)
+
+(defun org-let (list &rest body) ;FIXME: So many kittens are suffering here.
+  (declare (indent 1))
+  (eval (cons 'let (cons list body))))
+
+(defun org-let2 (list1 list2 &rest body) ;FIXME: Where did our karma go?
+  (declare (indent 2))
+  (eval (cons 'let (cons list1 (list (cons 'let (cons list2 body)))))))
+
 (defun org-agenda-run-series (name series)
   "Run agenda NAME as a SERIES of agenda commands."
   (org-let (nth 1 series) '(org-agenda-prepare name))
diff --git a/lisp/org/org-clock.el b/lisp/org/org-clock.el
index 2073b33..251ad97 100644
--- a/lisp/org/org-clock.el
+++ b/lisp/org/org-clock.el
@@ -911,17 +911,17 @@ If CLOCK-SOUND is non-nil, it overrides 
`org-clock-sound'."
 
 (defmacro org-with-clock-position (clock &rest forms)
   "Evaluate FORMS with CLOCK as the current active clock."
+  (declare (indent 1) (debug t))
   `(with-current-buffer (marker-buffer (car ,clock))
      (org-with-wide-buffer
       (goto-char (car ,clock))
       (beginning-of-line)
       ,@forms)))
-(def-edebug-spec org-with-clock-position (form body))
-(put 'org-with-clock-position 'lisp-indent-function 1)
 
 (defmacro org-with-clock (clock &rest forms)
   "Evaluate FORMS with CLOCK as the current active clock.
 This macro also protects the current active clock from being altered."
+  (declare (indent 1) (debug t))
   `(org-with-clock-position ,clock
      (let ((org-clock-start-time (cdr ,clock))
           (org-clock-total-time)
@@ -932,8 +932,6 @@ This macro also protects the current active clock from 
being altered."
                                  (org-back-to-heading t)
                                  (point-marker))))
        ,@forms)))
-(def-edebug-spec org-with-clock (form body))
-(put 'org-with-clock 'lisp-indent-function 1)
 
 (defsubst org-clock-clock-in (clock &optional resume start-time)
   "Clock in to the clock located by CLOCK.
@@ -2241,7 +2239,7 @@ have priority."
                  ((>= month 7) 3)
                  ((>= month 4) 2)
                  (t 1)))
-        m1 h1 d1 month1 y1 shiftedy shiftedm shiftedq)
+        h1 d1 month1 y1 shiftedy shiftedm shiftedq) ;; m1
     (cond
      ((string-match "\\`[0-9]+\\'" skey)
       (setq y (string-to-number skey) month 1 d 1 key 'year))
@@ -2344,7 +2342,7 @@ have priority."
                  (`interactive (org-read-date nil t nil "Range end? "))
                  (`untilnow (current-time))
                  (_ (encode-time 0
-                                 (or m1 m)
+                                 m ;; (or m1 m)
                                  (or h1 h)
                                  (or d1 d)
                                  (or month1 month)
@@ -2391,7 +2389,7 @@ the currently selected interval size."
        (user-error "Line needs a :block definition before this command works")
       (let* ((b (match-beginning 1)) (e (match-end 1))
             (s (match-string 1))
-            block shift ins y mw d date wp m)
+            block shift ins y mw d date wp) ;; m
        (cond
         ((equal s "yesterday") (setq s "today-1"))
         ((equal s "lastweek") (setq s "thisweek-1"))
@@ -2416,7 +2414,7 @@ the currently selected interval size."
          (cond
           (d (setq ins (format-time-string
                         "%Y-%m-%d"
-                        (encode-time 0 0 0 (+ d n) m y))))
+                        (encode-time 0 0 0 (+ d n) nil y)))) ;; m
           ((and wp (string-match "w\\|W" wp) mw (> (length wp) 0))
            (require 'cal-iso)
            (setq date (calendar-gregorian-from-absolute
diff --git a/lisp/org/org-crypt.el b/lisp/org/org-crypt.el
index caf9de9..103baeb 100644
--- a/lisp/org/org-crypt.el
+++ b/lisp/org/org-crypt.el
@@ -284,6 +284,8 @@ Assume `epg-context' is set."
         nil)))
     (_ nil)))
 
+(defvar org--matcher-tags-todo-only)
+
 ;;;###autoload
 (defun org-encrypt-entries ()
   "Encrypt all top-level entries in the current buffer."
diff --git a/lisp/org/org-element.el b/lisp/org/org-element.el
index b7319d6..31f5f78 100644
--- a/lisp/org/org-element.el
+++ b/lisp/org/org-element.el
@@ -4206,6 +4206,7 @@ looking into captions:
    (lambda (b)
      (and (org-element-map b \\='latex-snippet #\\='identity nil t) b))
    nil nil nil t)"
+  (declare (indent 2))
   ;; Ensure TYPES and NO-RECURSION are a list, even of one element.
   (let* ((types (if (listp types) types (list types)))
         (no-recursion (if (listp no-recursion) no-recursion
@@ -4299,7 +4300,6 @@ looking into captions:
        (funcall --walk-tree data)
        ;; Return value in a proper order.
        (nreverse --acc)))))
-(put 'org-element-map 'lisp-indent-function 2)
 
 ;; The following functions are internal parts of the parser.
 ;;
diff --git a/lisp/org/org-install.el b/lisp/org/org-install.el
index 5835959..d521d81 100644
--- a/lisp/org/org-install.el
+++ b/lisp/org/org-install.el
@@ -1,4 +1,4 @@
-;;; org-install.el --- backward compatibility file for obsolete configuration
+;;; org-install.el --- backward compatibility file for obsolete configuration  
-*- lexical-binding: t -*-
 ;;
 ;;; Code:
 ;;
diff --git a/lisp/org/org-macs.el b/lisp/org/org-macs.el
index 56afdf6..58d3fd3 100644
--- a/lisp/org/org-macs.el
+++ b/lisp/org/org-macs.el
@@ -627,18 +627,10 @@ program is needed for, so that the error message can be 
more informative."
   (let ((message-log-max nil))
     (apply #'message args)))
 
-(defun org-let (list &rest body)
-  (eval (cons 'let (cons list body))))
-(put 'org-let 'lisp-indent-function 1)
-
-(defun org-let2 (list1 list2 &rest body)
-  (eval (cons 'let (cons list1 (list (cons 'let (cons list2 body)))))))
-(put 'org-let2 'lisp-indent-function 2)
-
 (defun org-eval (form)
   "Eval FORM and return result."
   (condition-case error
-      (eval form)
+      (eval form t)
     (error (format "%%![Error: %s]" error))))
 
 (defvar org-outline-regexp) ; defined in org.el
@@ -877,7 +869,8 @@ delimiting S."
                    (let ((width (plist-get props :width)))
                      (and (wholenump width) width)))
                   (`(image . ,_)
-                   (ceiling (car (image-size spec))))
+                    (and (fboundp 'image-size)
+                         (ceiling (car (image-size spec)))))
                   ((pred stringp)
                    ;; Displayed string could contain invisible parts,
                    ;; but no nested display.
@@ -1241,31 +1234,29 @@ Return 0. if S is not recognized as a valid value."
 When ADDITIONAL-KEYS is not nil, also include SPC and DEL in the
 allowed keys for scrolling, as expected in the export dispatch
 window."
-  (let ((scrlup (if additional-keys '(?\s 22) 22))
-       (scrldn (if additional-keys `(?\d 134217846) 134217846)))
-    (eval
-     `(cl-case ,key
-       ;; C-n
-       (14 (if (not (pos-visible-in-window-p (point-max)))
-               (ignore-errors (scroll-up 1))
-             (message "End of buffer")
-             (sit-for 1)))
-       ;; C-p
-       (16 (if (not (pos-visible-in-window-p (point-min)))
-               (ignore-errors (scroll-down 1))
-             (message "Beginning of buffer")
-             (sit-for 1)))
-       ;; SPC or
-       (,scrlup
-        (if (not (pos-visible-in-window-p (point-max)))
-            (scroll-up nil)
-          (message "End of buffer")
-          (sit-for 1)))
-       ;; DEL
-       (,scrldn (if (not (pos-visible-in-window-p (point-min)))
-                    (scroll-down nil)
-                  (message "Beginning of buffer")
-                  (sit-for 1)))))))
+  (let ((scrlup (if additional-keys '(?\s ?\C-v) ?\C-v))
+       (scrldn (if additional-keys `(?\d ?\M-v) ?\M-v)))
+    (pcase key
+      (?\C-n (if (not (pos-visible-in-window-p (point-max)))
+             (ignore-errors (scroll-up 1))
+           (message "End of buffer")
+           (sit-for 1)))
+      (?\C-p (if (not (pos-visible-in-window-p (point-min)))
+             (ignore-errors (scroll-down 1))
+           (message "Beginning of buffer")
+           (sit-for 1)))
+      ;; SPC or
+      ((guard (memq key scrlup))
+       (if (not (pos-visible-in-window-p (point-max)))
+          (scroll-up nil)
+        (message "End of buffer")
+        (sit-for 1)))
+      ;; DEL
+      ((guard (memq key scrldn))
+       (if (not (pos-visible-in-window-p (point-min)))
+          (scroll-down nil)
+        (message "Beginning of buffer")
+        (sit-for 1))))))
 
 (provide 'org-macs)
 
diff --git a/lisp/org/org-pcomplete.el b/lisp/org/org-pcomplete.el
index 29d9d58..d8a4937 100644
--- a/lisp/org/org-pcomplete.el
+++ b/lisp/org/org-pcomplete.el
@@ -239,11 +239,11 @@ When completing for #+STARTUP, for example, this function 
returns
   (require 'ox)
   (pcomplete-here
    (and org-export-exclude-tags
-       (list (mapconcat 'identity org-export-exclude-tags " ")))))
+       (list (mapconcat #'identity org-export-exclude-tags " ")))))
 
 (defun pcomplete/org-mode/file-option/filetags ()
   "Complete arguments for the #+FILETAGS file option."
-  (pcomplete-here (and org-file-tags (mapconcat 'identity org-file-tags " "))))
+  (pcomplete-here (and org-file-tags (mapconcat #'identity org-file-tags " 
"))))
 
 (defun pcomplete/org-mode/file-option/language ()
   "Complete arguments for the #+LANGUAGE file option."
@@ -264,13 +264,13 @@ When completing for #+STARTUP, for example, this function 
returns
   (require 'ox)
   (pcomplete-here
    (and org-export-select-tags
-       (list (mapconcat 'identity org-export-select-tags " ")))))
+       (list (mapconcat #'identity org-export-select-tags " ")))))
 
 (defun pcomplete/org-mode/file-option/startup ()
   "Complete arguments for the #+STARTUP file option."
   (while (pcomplete-here
          (let ((opts (pcomplete-uniquify-list
-                      (mapcar 'car org-startup-options))))
+                      (mapcar #'car org-startup-options))))
            ;; Some options are mutually exclusive, and shouldn't be completed
            ;; against if certain other options have already been seen.
            (dolist (arg pcomplete-args)
@@ -340,7 +340,8 @@ When completing for #+STARTUP, for example, this function 
returns
   "Complete against TeX-style HTML entity names."
   (require 'org-entities)
   (while (pcomplete-here
-         (pcomplete-uniquify-list (remove nil (mapcar 'car-safe org-entities)))
+         (pcomplete-uniquify-list
+          (remove nil (mapcar #'car-safe org-entities)))
          (substring pcomplete-stub 1))))
 
 (defun pcomplete/org-mode/todo ()
diff --git a/lisp/org/org-protocol.el b/lisp/org/org-protocol.el
index 74043f8..726c1ca 100644
--- a/lisp/org/org-protocol.el
+++ b/lisp/org/org-protocol.el
@@ -535,7 +535,7 @@ The location for a browser's bookmark should look like this:
         encodeURIComponent(location.href)"
   ;; As we enter this function for a match on our protocol, the return value
   ;; defaults to nil.
-  (let ((result nil)
+  (let (;; (result nil)
        (f (org-protocol-sanitize-uri
            (plist-get (org-protocol-parse-parameters fname nil '(:url))
                       :url))))
@@ -586,7 +586,7 @@ The location for a browser's bookmark should look like this:
               (if (file-exists-p the-file)
                   (message "%s: permission denied!" the-file)
                 (message "%s: no such file or directory." the-file))))))
-      result)))
+      nil))) ;; FIXME: Really?
 
 
 ;;; Core functions:
diff --git a/lisp/org/org-tempo.el b/lisp/org/org-tempo.el
index 36b8614..c121b8e 100644
--- a/lisp/org/org-tempo.el
+++ b/lisp/org/org-tempo.el
@@ -65,7 +65,7 @@ just like `org-structure-template-alist'.  The tempo snippet
 \"<KEY\" will be expanded using the KEYWORD value.  For example
 \"<L\" at the beginning of a line is expanded to \"#+latex:\".
 
-Do not use \"I\" as a KEY, as it it reserved for expanding
+Do not use \"I\" as a KEY, as it is reserved for expanding
 \"#+include\"."
   :group 'org-tempo
   :type '(repeat (cons (string :tag "Key")
diff --git a/lisp/org/org-version.el b/lisp/org/org-version.el
index 25b3354..8871ef7 100644
--- a/lisp/org/org-version.el
+++ b/lisp/org/org-version.el
@@ -1,4 +1,4 @@
-;;; org-version.el --- autogenerated file, do not edit
+;;; org-version.el --- autogenerated file, do not edit  -*- lexical-binding: t 
-*-
 ;;
 ;;; Code:
 ;;;###autoload
diff --git a/lisp/org/org.el b/lisp/org/org.el
index e6a5cca..cebe173 100644
--- a/lisp/org/org.el
+++ b/lisp/org/org.el
@@ -4757,8 +4757,8 @@ This is for getting out of special buffers like capture.")
 ;; Other stuff we need.
 (require 'time-date)
 (unless (fboundp 'time-subtract) (defalias 'time-subtract 'subtract-time))
-(require 'easymenu)
-(require 'overlay)
+(when (< emacs-major-version 28)  ; preloaded in Emacs 28
+  (require 'easymenu))
 
 (require 'org-entities)
 (require 'org-faces)
@@ -20318,7 +20318,7 @@ unless optional argument NO-INHERITANCE is non-nil."
 
 (defun org-point-at-end-of-empty-headline ()
   "If point is at the end of an empty headline, return t, else nil.
-If the heading only contains a TODO keyword, it is still still considered
+If the heading only contains a TODO keyword, it is still considered
 empty."
   (let ((case-fold-search nil))
     (and (looking-at "[ \t]*$")
diff --git a/lisp/org/ox-odt.el b/lisp/org/ox-odt.el
index 2d550d9..a076d15 100644
--- a/lisp/org/ox-odt.el
+++ b/lisp/org/ox-odt.el
@@ -2111,7 +2111,8 @@ SHORT-CAPTION are strings."
         (caption (let ((c (org-export-get-caption element-or-parent)))
                    (and c (org-export-data c info))))
         ;; FIXME: We don't use short-caption for now
-        (short-caption nil))
+        ;; (short-caption nil)
+        )
     (when (or label caption)
       (let* ((default-category
               (cl-case (org-element-type element)
@@ -2159,7 +2160,7 @@ SHORT-CAPTION are strings."
                           "<text:sequence text:ref-name=\"%s\" 
text:name=\"%s\" text:formula=\"ooow:%s+1\" 
style:num-format=\"1\">%s</text:sequence>"
                           label counter counter seqno))
                   (?c . ,(or caption "")))))
-              short-caption))
+              nil)) ;; short-caption
            ;; Case 2: Handle Label reference.
            (reference
             (let* ((fmt (cddr (assoc-string label-style org-odt-label-styles 
t)))
@@ -2362,14 +2363,14 @@ used as a communication channel."
         ;; If yes, note down its contents.  It will go in to frame
         ;; description.  This quite useful for debugging.
         (desc (and replaces (org-element-property :value replaces)))
-        width height)
+        ) ;; width height
     (cond
      ((eq embed-as 'character)
-      (org-odt--render-image/formula "InlineFormula" href width height
+      (org-odt--render-image/formula "InlineFormula" href nil nil ;; width 
height
                                     nil nil title desc))
      (t
       (let* ((equation (org-odt--render-image/formula
-                       "CaptionedDisplayFormula" href width height
+                       "CaptionedDisplayFormula" href nil nil ;; width height
                        captions nil title desc))
             (label
              (let* ((org-odt-category-map-alist
diff --git a/lisp/org/ox-texinfo.el b/lisp/org/ox-texinfo.el
index cf08054..6e8d0d6 100644
--- a/lisp/org/ox-texinfo.el
+++ b/lisp/org/ox-texinfo.el
@@ -1627,6 +1627,22 @@ Return output file's name."
     (org-export-to-file 'texinfo outfile
       async subtreep visible-only body-only ext-plist)))
 
+(defun org-texinfo-export-to-texinfo-batch ()
+  "Export Org file INFILE to Texinfo file OUTFILE, in batch mode.
+Overwrites existing output file.
+Usage: emacs -batch -f org-texinfo-export-to-texinfo-batch INFILE OUTFILE"
+  (or noninteractive (user-error "Batch mode use only"))
+  (let ((infile (pop command-line-args-left))
+       (outfile (pop command-line-args-left))
+       (org-export-coding-system org-texinfo-coding-system)
+        (make-backup-files nil))
+    (unless (file-readable-p infile)
+      (message "File `%s' not readable" infile)
+      (kill-emacs 1))
+    (with-temp-buffer
+      (insert-file-contents infile)
+      (org-export-to-file 'texinfo outfile))))
+
 ;;;###autoload
 (defun org-texinfo-export-to-info
   (&optional async subtreep visible-only body-only ext-plist)
diff --git a/lisp/org/ox.el b/lisp/org/ox.el
index 050a809..36ecf01 100644
--- a/lisp/org/ox.el
+++ b/lisp/org/ox.el
@@ -2706,9 +2706,9 @@ a list of footnote definitions or in the widened buffer."
               (and (or (eq (org-element-type f) 'footnote-definition)
                        (eq (org-element-property :type f) 'inline))
                    (org-element-property :label f)))))
-         seen)
+         ) ;; seen
       (dolist (l (funcall list-labels tree))
-       (cond ((member l seen))
+       (cond ;; ((member l seen))
              ((member l known-definitions) (push l defined))
              (t (push l undefined)))))
     ;; Complete MISSING-DEFINITIONS by finding the definition of every
diff --git a/lisp/outline.el b/lisp/outline.el
index 57909b3..79029a6 100644
--- a/lisp/outline.el
+++ b/lisp/outline.el
@@ -175,23 +175,43 @@ in the file it applies to.")
                                   outline-mode-menu-bar-map))))))
     map))
 
+(defvar outline-mode-cycle-map
+  (let ((map (make-sparse-keymap)))
+    (let ((tab-binding `(menu-item
+                         "" outline-cycle
+                         ;; Only takes effect if point is on a heading.
+                         :filter ,(lambda (cmd)
+                                    (when (outline-on-heading-p) cmd)))))
+      (define-key map [tab]       tab-binding)
+      (define-key map (kbd "TAB") tab-binding)
+      (define-key map (kbd "<backtab>") #'outline-cycle-buffer))
+    map)
+  "Keymap used by `outline-mode-map' and `outline-minor-mode-cycle'.")
+
 (defvar outline-mode-map
   (let ((map (make-sparse-keymap)))
+    (set-keymap-parent map outline-mode-cycle-map)
     (define-key map "\C-c" outline-mode-prefix-map)
     (define-key map [menu-bar] outline-mode-menu-bar-map)
-    ;; Only takes effect if point is on a heading.
-    (define-key map (kbd "TAB")
-      `(menu-item "" outline-cycle
-                  :filter ,(lambda (cmd)
-                             (when (outline-on-heading-p) cmd))))
-    (define-key map (kbd "<backtab>") #'outline-cycle-buffer)
     map))
 
 (defvar outline-font-lock-keywords
   '(
     ;; Highlight headings according to the level.
     (eval . (list (concat "^\\(?:" outline-regexp "\\).+")
-                 0 '(outline-font-lock-face) nil t)))
+                  0 '(if outline-minor-mode
+                         (if outline-minor-mode-cycle
+                             (if outline-minor-mode-highlight
+                                 (list 'face (outline-font-lock-face)
+                                       'keymap outline-mode-cycle-map)
+                               (list 'face nil
+                                     'keymap outline-mode-cycle-map)))
+                       (outline-font-lock-face))
+                  (when outline-minor-mode
+                    (pcase outline-minor-mode-highlight
+                      ('override t)
+                      ('append 'append)))
+                  t)))
   "Additional expressions to highlight in Outline mode.")
 
 (defface outline-1
@@ -305,6 +325,50 @@ After that, changing the prefix key requires manipulating 
keymaps."
          (define-key outline-minor-mode-map val outline-mode-prefix-map)
          (set-default sym val)))
 
+(defcustom outline-minor-mode-cycle nil
+  "Enable cycling of headings in `outline-minor-mode'.
+When enabled, it puts a keymap with cycling keys on heading lines.
+When point is on a heading line, then typing `TAB' cycles between `hide all',
+`headings only' and `show all' (`outline-cycle').  Typing `S-TAB' on
+a heading line cycles the whole buffer (`outline-cycle-buffer').
+Typing these keys anywhere outside heading lines uses their default bindings."
+  :type 'boolean
+  :version "28.1")
+;;;###autoload(put 'outline-minor-mode-cycle 'safe-local-variable 'booleanp)
+
+(defcustom outline-minor-mode-highlight nil
+  "Highlight headings in `outline-minor-mode' using font-lock keywords.
+Non-nil value works well only when outline font-lock keywords
+don't conflict with the major mode's font-lock keywords.
+When t, it puts outline faces only if there are no major mode's faces
+on headings.  When `override', it completely overwrites major mode's
+faces with outline faces.  When `append', it tries to append outline
+faces to major mode's faces."
+  :type '(choice (const :tag "No highlighting" nil)
+                 (const :tag "Overwrite major mode faces" override)
+                 (const :tag "Append outline faces to major mode faces" append)
+                 (const :tag "Highlight separately from major mode faces" t))
+  :version "28.1")
+;;;###autoload(put 'outline-minor-mode-highlight 'safe-local-variable 
'booleanp)
+
+(defun outline-minor-mode-highlight-buffer ()
+  ;; Fallback to overlays when font-lock is unsupported.
+  (save-excursion
+    (goto-char (point-min))
+    (let ((regexp (concat "^\\(?:" outline-regexp "\\).*$")))
+      (while (re-search-forward regexp nil t)
+        (let ((overlay (make-overlay (match-beginning 0)
+                                     (match-end 0))))
+          (overlay-put overlay 'outline-overlay t)
+          (when (or (eq outline-minor-mode-highlight 'override)
+                    (and (eq outline-minor-mode-highlight t)
+                         (goto-char (match-beginning 0))
+                         (not (get-text-property (point) 'face))))
+            (overlay-put overlay 'face (outline-font-lock-face)))
+          (when outline-minor-mode-cycle
+            (overlay-put overlay 'keymap outline-mode-cycle-map)))
+        (goto-char (match-end 0))))))
+
 ;;;###autoload
 (define-minor-mode outline-minor-mode
   "Toggle Outline minor mode.
@@ -314,6 +378,12 @@ See the command `outline-mode' for more information on 
this mode."
                    (cons outline-minor-mode-prefix outline-mode-prefix-map))
   (if outline-minor-mode
       (progn
+        (when (or outline-minor-mode-cycle outline-minor-mode-highlight)
+          (if (and global-font-lock-mode (font-lock-specified-p major-mode))
+              (progn
+                (font-lock-add-keywords nil outline-font-lock-keywords t)
+                (font-lock-flush))
+            (outline-minor-mode-highlight-buffer)))
        ;; Turn off this mode if we change major modes.
        (add-hook 'change-major-mode-hook
                  (lambda () (outline-minor-mode -1))
@@ -321,6 +391,11 @@ See the command `outline-mode' for more information on 
this mode."
         (setq-local line-move-ignore-invisible t)
        ;; Cause use of ellipses for invisible text.
        (add-to-invisibility-spec '(outline . t)))
+    (when (or outline-minor-mode-cycle outline-minor-mode-highlight)
+      (if font-lock-fontified
+          (font-lock-remove-keywords nil outline-font-lock-keywords))
+      (remove-overlays nil nil 'outline-overlay t)
+      (font-lock-flush))
     (setq line-move-ignore-invisible nil)
     ;; Cause use of ellipses for invisible text.
     (remove-from-invisibility-spec '(outline . t))
diff --git a/lisp/pcmpl-gnu.el b/lisp/pcmpl-gnu.el
index dd964e3..6c68645 100644
--- a/lisp/pcmpl-gnu.el
+++ b/lisp/pcmpl-gnu.el
@@ -106,7 +106,7 @@
     (while (pcomplete-here (completion-table-in-turn
                             (pcmpl-gnu-make-rule-names)
                             (pcomplete-entries))
-                           nil 'identity))))
+                           nil #'identity))))
 
 (defun pcmpl-gnu-makefile-names ()
   "Return a list of possible makefile names."
@@ -336,7 +336,7 @@ Return the new list."
                          (pcomplete-match-string 1 0)))))
     (unless saw-option
       (pcomplete-here
-       (mapcar 'char-to-string
+       (mapcar #'char-to-string
               (string-to-list
                "01234567ABCFGIKLMNOPRSTUVWXZbcdfghiklmoprstuvwxz")))
       (if (pcomplete-match "[xt]" 'first 1)
@@ -355,7 +355,7 @@ Return the new list."
                      (pcmpl-gnu-with-file-buffer
                       file (mapcar #'tar-header-name tar-parse-info)))))
              (pcomplete-entries))
-           nil 'identity))))
+           nil #'identity))))
 
 ;;;###autoload
 
@@ -391,7 +391,7 @@ Return the new list."
                (string= prec "-execdir"))
            (while (pcomplete-here* (funcall 
pcomplete-command-completion-function)
                                    (pcomplete-arg 'last) t))))
-    (while (pcomplete-here (pcomplete-dirs) nil 'identity))))
+    (while (pcomplete-here (pcomplete-dirs) nil #'identity))))
 
 ;;;###autoload
 (defalias 'pcomplete/gdb 'pcomplete/xargs)
diff --git a/lisp/pcmpl-linux.el b/lisp/pcmpl-linux.el
index 2f42dbd..39d4add 100644
--- a/lisp/pcmpl-linux.el
+++ b/lisp/pcmpl-linux.el
@@ -31,11 +31,6 @@
 
 (require 'pcomplete)
 
-;; Unused.
-;;; (defgroup pcmpl-linux nil
-;;;   "Functions for dealing with GNU/Linux completions."
-;;;   :group 'pcomplete)
-
 ;; Functions:
 
 ;;;###autoload
@@ -50,20 +45,20 @@
   (while (pcomplete-here
          (if (file-directory-p "/proc")
               (directory-files "/proc" nil "\\`[0-9]+\\'"))
-         nil 'identity)))
+         nil #'identity)))
 
 ;;;###autoload
 (defun pcomplete/umount ()
   "Completion for GNU/Linux `umount'."
   (pcomplete-opt "hVafrnvt(pcmpl-linux-fs-types)")
   (while (pcomplete-here (pcmpl-linux-mounted-directories)
-                        nil 'identity)))
+                        nil #'identity)))
 
 ;;;###autoload
 (defun pcomplete/mount ()
   "Completion for GNU/Linux `mount'."
   (pcomplete-opt "hVanfFrsvwt(pcmpl-linux-fs-types)o?L?U?")
-  (while (pcomplete-here (pcomplete-entries) nil 'identity)))
+  (while (pcomplete-here (pcomplete-entries) nil #'identity)))
 
 (defconst pcmpl-linux-fs-modules-path-format "/lib/modules/%s/kernel/fs/")
 
diff --git a/lisp/pcmpl-unix.el b/lisp/pcmpl-unix.el
index 70273b9..c1aaf82 100644
--- a/lisp/pcmpl-unix.el
+++ b/lisp/pcmpl-unix.el
@@ -77,7 +77,7 @@ being via `pcmpl-ssh-known-hosts-file'."
   (let ((pcomplete-help "(fileutils)rm invocation"))
     (pcomplete-opt "dfirRv")
     (while (pcomplete-here (pcomplete-all-entries) nil
-                          'expand-file-name))))
+                          #'expand-file-name))))
 
 ;;;###autoload
 (defun pcomplete/xargs ()
diff --git a/lisp/pcmpl-x.el b/lisp/pcmpl-x.el
index 61d8866..fd14710 100644
--- a/lisp/pcmpl-x.el
+++ b/lisp/pcmpl-x.el
@@ -27,7 +27,7 @@
 (require 'pcomplete)
 
 
-;;;; tlmgr - http://www.tug.org/texlive/tlmgr.html
+;;;; tlmgr - https://www.tug.org/texlive/tlmgr.html
 
 (defcustom pcmpl-x-tlmgr-program "tlmgr"
   "Name of the tlmgr program."
@@ -301,7 +301,8 @@ long options."
          "nst" "ntd" "nto" "nvf" "obi" "obs" "ofp" "osh" "ovf" "par"
          "pch" "pck" "pia" "pin" "pow" "prc" "pre" "pro" "rch" "ret"
          "rng" "rpt" "rvl" "sig" "spa" "stl" "stu" "stv" "sus" "tai"
-         "tes" "thr" "ucp" "use" "voi" "zdi") (match-string 2 cur)))
+         "tes" "thr" "ucp" "use" "voi" "zdi")
+       (match-string 2 cur)))
      ((string-match "\\`-[LIn]\\([^;]+;\\)*\\([^;]*\\)\\'" cur)
       (pcomplete-here (pcomplete-dirs) (match-string 2 cur)))
      ((string-match "\\`-[Ee]\\(.*\\)\\'" cur)
diff --git a/lisp/play/5x5.el b/lisp/play/5x5.el
index 891a5f6..3630c19 100644
--- a/lisp/play/5x5.el
+++ b/lisp/play/5x5.el
@@ -179,6 +179,7 @@ GRID is the grid of positions to click.")
 
 (define-derived-mode 5x5-mode special-mode "5x5"
   "A mode for playing `5x5'."
+  :interactive nil
   (setq buffer-read-only t
         truncate-lines   t)
   (buffer-disable-undo))
@@ -221,7 +222,7 @@ Quit current game           \\[5x5-quit-game]"
 
 (defun 5x5-new-game ()
   "Start a new game of `5x5'."
-  (interactive)
+  (interactive nil 5x5-mode)
   (when (if (called-interactively-p 'interactive)
            (5x5-y-or-n-p "Start a new game? ") t)
     (setq 5x5-x-pos (/ 5x5-grid-size 2)
@@ -234,7 +235,7 @@ Quit current game           \\[5x5-quit-game]"
 
 (defun 5x5-quit-game ()
   "Quit the current game of `5x5'."
-  (interactive)
+  (interactive nil 5x5-mode)
   (kill-buffer 5x5-buffer-name))
 
 (defun 5x5-make-new-grid ()
@@ -782,7 +783,7 @@ Solutions are sorted from least to greatest Hamming weight."
 Argument N is ignored."
   ;; For the time being n is ignored, the idea was to use some numeric
   ;; argument to show a limited amount of positions.
-  (interactive "P")
+  (interactive "P" 5x5-mode)
   (5x5-log-init)
   (let ((solutions (5x5-solver 5x5-grid)))
     (setq 5x5-solver-output
@@ -805,7 +806,7 @@ list. The list of solution is ordered by number of strokes, 
so
 rotating left just after calling `5x5-solve-suggest' will show
 the solution with second least number of strokes, while rotating
 right will show the solution with greatest number of strokes."
-  (interactive "P")
+  (interactive "P" 5x5-mode)
   (let ((len  (length 5x5-solver-output)))
     (when (>= len 3)
       (setq n (if (integerp n) n 1)
@@ -839,7 +840,7 @@ right will show the solution with greatest number of 
strokes."
 If N is not supplied, rotate by 1.  Similar to function
 `5x5-solve-rotate-left' except that rotation is right instead of
 lest."
-  (interactive "P")
+  (interactive "P" 5x5-mode)
   (setq n
        (if (integerp n) (- n)
          -1))
@@ -851,7 +852,7 @@ lest."
 
 (defun 5x5-flip-current ()
   "Make a move on the current cursor location."
-  (interactive)
+  (interactive nil 5x5-mode)
   (setq 5x5-grid (5x5-make-move 5x5-grid 5x5-y-pos 5x5-x-pos))
   (5x5-made-move)
   (unless 5x5-cracking
@@ -863,61 +864,61 @@ lest."
 
 (defun 5x5-up ()
   "Move up."
-  (interactive)
+  (interactive nil 5x5-mode)
   (unless (zerop 5x5-y-pos)
     (cl-decf 5x5-y-pos)
     (5x5-position-cursor)))
 
 (defun 5x5-down ()
   "Move down."
-  (interactive)
+  (interactive nil 5x5-mode)
   (unless (= 5x5-y-pos (1- 5x5-grid-size))
     (cl-incf 5x5-y-pos)
     (5x5-position-cursor)))
 
 (defun 5x5-left ()
   "Move left."
-  (interactive)
+  (interactive nil 5x5-mode)
   (unless (zerop 5x5-x-pos)
     (cl-decf 5x5-x-pos)
     (5x5-position-cursor)))
 
 (defun 5x5-right ()
   "Move right."
-  (interactive)
+  (interactive nil 5x5-mode)
   (unless (= 5x5-x-pos (1- 5x5-grid-size))
     (cl-incf 5x5-x-pos)
     (5x5-position-cursor)))
 
 (defun 5x5-bol ()
   "Move to beginning of line."
-  (interactive)
+  (interactive nil 5x5-mode)
   (setq 5x5-x-pos 0)
   (5x5-position-cursor))
 
 (defun 5x5-eol ()
   "Move to end of line."
-  (interactive)
+  (interactive nil 5x5-mode)
   (setq 5x5-x-pos (1- 5x5-grid-size))
   (5x5-position-cursor))
 
 (defun 5x5-first ()
   "Move to the first cell."
-  (interactive)
+  (interactive nil 5x5-mode)
   (setq 5x5-x-pos 0
         5x5-y-pos 0)
   (5x5-position-cursor))
 
 (defun 5x5-last ()
   "Move to the last cell."
-  (interactive)
+  (interactive nil 5x5-mode)
   (setq 5x5-x-pos (1- 5x5-grid-size)
         5x5-y-pos (1- 5x5-grid-size))
   (5x5-position-cursor))
 
 (defun 5x5-randomize ()
   "Randomize the grid."
-  (interactive)
+  (interactive nil 5x5-mode)
   (when (5x5-y-or-n-p "Start a new game with a random grid? ")
     (setq 5x5-x-pos (/ 5x5-grid-size 2)
           5x5-y-pos (/ 5x5-grid-size 2)
diff --git a/lisp/play/blackbox.el b/lisp/play/blackbox.el
index 61b0878..13bcdcc 100644
--- a/lisp/play/blackbox.el
+++ b/lisp/play/blackbox.el
@@ -274,45 +274,45 @@ a reflection."
     ))
 
 (defun bb-right (count)
-  (interactive "p")
+  (interactive "p" blackbox-mode)
   (while (and (> count 0) (< bb-x 8))
     (forward-char 2)
     (setq bb-x (1+ bb-x))
     (setq count (1- count))))
 
 (defun bb-left (count)
-  (interactive "p")
+  (interactive "p" blackbox-mode)
   (while (and (> count 0) (> bb-x -1))
     (backward-char 2)
     (setq bb-x (1- bb-x))
     (setq count (1- count))))
 
 (defun bb-up (count)
-  (interactive "p")
+  (interactive "p" blackbox-mode)
   (while (and (> count 0) (> bb-y -1))
     (with-no-warnings (previous-line))
     (setq bb-y (1- bb-y))
     (setq count (1- count))))
 
 (defun bb-down (count)
-  (interactive "p")
+  (interactive "p" blackbox-mode)
   (while (and (> count 0) (< bb-y 8))
     (with-no-warnings (next-line))
     (setq bb-y (1+ bb-y))
     (setq count (1- count))))
 
 (defun bb-eol ()
-  (interactive)
+  (interactive nil blackbox-mode)
   (setq bb-x 8)
   (bb-goto (cons bb-x bb-y)))
 
 (defun bb-bol ()
-  (interactive)
+  (interactive nil blackbox-mode)
   (setq bb-x -1)
   (bb-goto (cons bb-x bb-y)))
 
 (defun bb-romp ()
-  (interactive)
+  (interactive nil blackbox-mode)
   (cond
    ((and
      (or (= bb-x -1) (= bb-x 8))
@@ -379,7 +379,7 @@ a reflection."
 
 (defun bb-done ()
   "Finish the game and report score."
-  (interactive)
+  (interactive nil blackbox-mode)
   (let (bogus-balls)
     (cond
      ((not (= (length bb-balls-placed) (length bb-board)))
diff --git a/lisp/play/bubbles.el b/lisp/play/bubbles.el
index dc93ef9..50f65a1 100644
--- a/lisp/play/bubbles.el
+++ b/lisp/play/bubbles.el
@@ -772,117 +772,46 @@ static char * dot3d_xpm[] = {
 
 (defun bubbles-set-graphics-theme-ascii ()
   "Set graphics theme to `ascii'."
-  (interactive)
+  (interactive nil bubbles-mode)
   (setq bubbles-graphics-theme 'ascii)
   (bubbles--update-faces-or-images))
 
 (defun bubbles-set-graphics-theme-circles ()
   "Set graphics theme to `circles'."
-  (interactive)
+  (interactive nil bubbles-mode)
   (setq bubbles-graphics-theme 'circles)
   (bubbles--initialize-images)
   (bubbles--update-faces-or-images))
 
 (defun bubbles-set-graphics-theme-squares ()
   "Set graphics theme to `squares'."
-  (interactive)
+  (interactive nil bubbles-mode)
   (setq bubbles-graphics-theme 'squares)
   (bubbles--initialize-images)
   (bubbles--update-faces-or-images))
 
 (defun bubbles-set-graphics-theme-diamonds ()
   "Set graphics theme to `diamonds'."
-  (interactive)
+  (interactive nil bubbles-mode)
   (setq bubbles-graphics-theme 'diamonds)
   (bubbles--initialize-images)
   (bubbles--update-faces-or-images))
 
 (defun bubbles-set-graphics-theme-balls ()
   "Set graphics theme to `balls'."
-  (interactive)
+  (interactive nil bubbles-mode)
   (setq bubbles-graphics-theme 'balls)
   (bubbles--initialize-images)
   (bubbles--update-faces-or-images))
 
 (defun bubbles-set-graphics-theme-emacs ()
   "Set graphics theme to `emacs'."
-  (interactive)
+  (interactive nil bubbles-mode)
   (setq bubbles-graphics-theme 'emacs)
   (bubbles--initialize-images)
   (bubbles--update-faces-or-images))
 
-;; game theme menu
-(defvar bubbles-game-theme-menu
-  (let ((menu (make-sparse-keymap "Game Theme")))
-    (define-key menu [bubbles-set-game-userdefined]
-      (list 'menu-item "User defined" 'bubbles-set-game-userdefined
-            :button '(:radio . (eq bubbles-game-theme 'user-defined))))
-    (define-key menu [bubbles-set-game-hard]
-      (list 'menu-item "Hard" 'bubbles-set-game-hard
-            :button '(:radio . (eq bubbles-game-theme 'hard))))
-    (define-key menu [bubbles-set-game-difficult]
-      (list 'menu-item "Difficult" 'bubbles-set-game-difficult
-            :button '(:radio . (eq bubbles-game-theme 'difficult))))
-    (define-key menu [bubbles-set-game-medium]
-      (list 'menu-item "Medium" 'bubbles-set-game-medium
-            :button '(:radio . (eq bubbles-game-theme 'medium))))
-    (define-key menu [bubbles-set-game-easy]
-      (list 'menu-item "Easy" 'bubbles-set-game-easy
-            :button '(:radio . (eq bubbles-game-theme 'easy))))
-    menu)
-  "Map for bubbles game theme menu.")
-
-;; graphics theme menu
-(defvar bubbles-graphics-theme-menu
-  (let ((menu (make-sparse-keymap "Graphics Theme")))
-    (define-key menu [bubbles-set-graphics-theme-ascii]
-      (list 'menu-item "ASCII" 'bubbles-set-graphics-theme-ascii
-            :button '(:radio . (eq bubbles-graphics-theme 'ascii))))
-    (define-key menu [bubbles-set-graphics-theme-emacs]
-      (list 'menu-item "Emacs" 'bubbles-set-graphics-theme-emacs
-            :button '(:radio . (eq bubbles-graphics-theme 'emacs))))
-    (define-key menu [bubbles-set-graphics-theme-balls]
-      (list 'menu-item "Balls" 'bubbles-set-graphics-theme-balls
-            :button '(:radio . (eq bubbles-graphics-theme 'balls))))
-    (define-key menu [bubbles-set-graphics-theme-diamonds]
-      (list 'menu-item "Diamonds" 'bubbles-set-graphics-theme-diamonds
-            :button '(:radio . (eq bubbles-graphics-theme 'diamonds))))
-    (define-key menu [bubbles-set-graphics-theme-squares]
-      (list 'menu-item "Squares" 'bubbles-set-graphics-theme-squares
-            :button '(:radio . (eq bubbles-graphics-theme 'squares))))
-    (define-key menu [bubbles-set-graphics-theme-circles]
-      (list 'menu-item "Circles" 'bubbles-set-graphics-theme-circles
-            :button '(:radio . (eq bubbles-graphics-theme 'circles))))
-    menu)
-    "Map for bubbles graphics theme menu.")
-
-;; menu
-(defvar bubbles-menu
-  (let ((menu (make-sparse-keymap "Bubbles")))
-    (define-key menu [bubbles-quit]
-      (list 'menu-item "Quit" 'bubbles-quit))
-    (define-key menu [bubbles]
-      (list 'menu-item "New game" 'bubbles))
-    (define-key menu [bubbles-separator-1]
-      '("--"))
-    (define-key menu [bubbles-save-settings]
-      (list 'menu-item "Save all settings" 'bubbles-save-settings))
-    (define-key menu [bubbles-customize]
-      (list 'menu-item "Edit all settings" 'bubbles-customize))
-    (define-key menu [bubbles-game-theme-menu]
-      (list 'menu-item "Game Theme" bubbles-game-theme-menu))
-    (define-key menu [bubbles-graphics-theme-menu]
-      (list 'menu-item "Graphics Theme" bubbles-graphics-theme-menu
-            :enable 'bubbles--playing))
-    (define-key menu [bubbles-separator-2]
-      '("--"))
-    (define-key menu [bubbles-undo]
-      (list 'menu-item "Undo last move" 'bubbles-undo
-            :enable '(and bubbles--playing (listp buffer-undo-list))))
-    menu)
-  "Map for bubbles menu.")
-
-;; bubbles mode map
+
 (defvar bubbles-mode-map
   (let ((map (make-sparse-keymap 'bubbles-mode-map)))
     ;; (suppress-keymap map t)
@@ -897,12 +826,59 @@ static char * dot3d_xpm[] = {
     (define-key map "n" 'next-line)
     (define-key map "f" 'forward-char)
     (define-key map "b" 'backward-char)
-    ;; bind menu to mouse
-    (define-key map [down-mouse-3] bubbles-menu)
-    ;; Put menu in menu-bar
-    (define-key map [menu-bar Bubbles] (cons "Bubbles" bubbles-menu))
     map)
-  "Mode map for bubbles.")
+  "Mode map for `bubbles'.")
+
+(easy-menu-define bubbles-menu bubbles-mode-map
+  "Menu for `bubbles'."
+  '("Bubbles"
+    ["Undo last move" bubbles-undo
+     :enable '(and bubbles--playing (listp buffer-undo-list))]
+    "---"
+    ("Graphics Theme"
+     :enable bubbles--playing
+     ["Circles" bubbles-set-graphics-theme-circles
+      :style radio
+      :selected (eq bubbles-graphics-theme 'circles)]
+     ["Squares" bubbles-set-graphics-theme-squares
+      :style radio
+      :selected (eq bubbles-graphics-theme 'squares)]
+     ["Diamonds" bubbles-set-graphics-theme-diamonds
+      :style radio
+      :selected (eq bubbles-graphics-theme 'diamonds)]
+     ["Balls" bubbles-set-graphics-theme-balls
+      :style radio
+      :selected (eq bubbles-graphics-theme 'balls)]
+     ["Emacs" bubbles-set-graphics-theme-emacs
+      :style radio
+      :selected (eq bubbles-graphics-theme 'emacs)]
+     ["ASCII" bubbles-set-graphics-theme-ascii
+      :style radio
+      :selected (eq bubbles-graphics-theme 'ascii)])
+    ("Game Theme"
+     ["Easy" bubbles-set-game-easy
+      :style radio
+      :selected (eq bubbles-game-theme 'easy)]
+     ["Medium" bubbles-set-game-medium
+      :style radio
+      :selected (eq bubbles-game-theme 'medium)]
+     ["Difficult" bubbles-set-game-difficult
+      :style radio
+      :selected (eq bubbles-game-theme 'difficult)]
+     ["Hard" bubbles-set-game-hard
+      :style radio
+      :selected (eq bubbles-game-theme 'hard)]
+     ["User defined" bubbles-set-game-userdefined
+      :style radio
+      :selected (eq bubbles-game-theme 'user-defined)])
+    ["Edit all settings" bubbles-customize]
+    ["Save all settings" bubbles-save-settings]
+    "---"
+    ["New game" bubbles]
+    ["Quit" bubbles-quit]))
+
+;; bind menu to mouse
+(define-key bubbles-mode-map [down-mouse-3] bubbles-menu)
 
 (define-derived-mode bubbles-mode nil "Bubbles"
   "Major mode for playing bubbles.
@@ -938,7 +914,7 @@ columns on its right towards the left.
 
 (defun bubbles-quit ()
   "Quit Bubbles."
-  (interactive)
+  (interactive nil bubbles-mode)
   (message "bubbles-quit")
   (bury-buffer))
 
@@ -1189,7 +1165,7 @@ Use optional parameter POS instead of point if given."
 
 (defun bubbles-plop ()
   "Remove active bubbles region."
-  (interactive)
+  (interactive nil bubbles-mode)
   (when (and bubbles--playing
              (> bubbles--neighborhood-score 0))
     (setq bubbles--save-data (list bubbles--score (buffer-string)))
@@ -1273,7 +1249,7 @@ Use optional parameter POS instead of point if given."
 
 (defun bubbles-undo ()
   "Undo last move."
-  (interactive)
+  (interactive nil bubbles-mode)
   (when bubbles--save-data
     (let ((inhibit-read-only t)
           (pos (point)))
diff --git a/lisp/play/decipher.el b/lisp/play/decipher.el
index 524ca81..47ed6e2 100644
--- a/lisp/play/decipher.el
+++ b/lisp/play/decipher.el
@@ -1,4 +1,4 @@
-;;; decipher.el --- cryptanalyze monoalphabetic substitution ciphers
+;;; decipher.el --- cryptanalyze monoalphabetic substitution ciphers  -*- 
lexical-binding: t; -*-
 ;;
 ;; Copyright (C) 1995-1996, 2001-2021 Free Software Foundation, Inc.
 ;;
@@ -71,7 +71,7 @@
 ;; Emacs commands.
 ;;
 ;; Decipher supports Font Lock mode.  To use it, you can also add
-;;     (add-hook 'decipher-mode-hook 'turn-on-font-lock)
+;;     (add-hook 'decipher-mode-hook #'turn-on-font-lock)
 ;; See the variable `decipher-font-lock-keywords' if you want to customize
 ;; the faces used.  I'd like to thank Simon Marshall for his help in making
 ;; Decipher work well with Font Lock.
@@ -84,6 +84,8 @@
 ;; 1. The consonant-line shortcut
 ;; 2. More functions for analyzing ciphertext
 
+;;; Code:
+
 ;;;===================================================================
 ;;; Variables:
 ;;;===================================================================
@@ -139,20 +141,20 @@ the tail of the list."
 (defvar decipher-mode-map
   (let ((map (make-keymap)))
     (suppress-keymap map)
-    (define-key map "A" 'decipher-show-alphabet)
-    (define-key map "C" 'decipher-complete-alphabet)
-    (define-key map "D" 'decipher-digram-list)
-    (define-key map "F" 'decipher-frequency-count)
-    (define-key map "M" 'decipher-make-checkpoint)
-    (define-key map "N" 'decipher-adjacency-list)
-    (define-key map "R" 'decipher-restore-checkpoint)
-    (define-key map "U" 'decipher-undo)
-    (define-key map " " 'decipher-keypress)
-    (define-key map [remap undo] 'decipher-undo)
-    (define-key map [remap advertised-undo] 'decipher-undo)
+    (define-key map "A" #'decipher-show-alphabet)
+    (define-key map "C" #'decipher-complete-alphabet)
+    (define-key map "D" #'decipher-digram-list)
+    (define-key map "F" #'decipher-frequency-count)
+    (define-key map "M" #'decipher-make-checkpoint)
+    (define-key map "N" #'decipher-adjacency-list)
+    (define-key map "R" #'decipher-restore-checkpoint)
+    (define-key map "U" #'decipher-undo)
+    (define-key map " " #'decipher-keypress)
+    (define-key map [remap undo] #'decipher-undo)
+    (define-key map [remap advertised-undo] #'decipher-undo)
     (let ((key ?a))
       (while (<= key ?z)
-       (define-key map (vector key) 'decipher-keypress)
+       (define-key map (vector key) #'decipher-keypress)
        (cl-incf key)))
     map)
   "Keymap for Decipher mode.")
@@ -161,24 +163,21 @@ the tail of the list."
 (defvar decipher-stats-mode-map
   (let ((map (make-keymap)))
     (suppress-keymap map)
-    (define-key map "D" 'decipher-digram-list)
-    (define-key map "F" 'decipher-frequency-count)
-    (define-key map "N" 'decipher-adjacency-list)
+    (define-key map "D" #'decipher-digram-list)
+    (define-key map "F" #'decipher-frequency-count)
+    (define-key map "N" #'decipher-adjacency-list)
     map)
-"Keymap for Decipher-Stats mode.")
+  "Keymap for Decipher-Stats mode.")
 
 
-(defvar decipher-mode-syntax-table nil
-  "Decipher mode syntax table")
-
-(if decipher-mode-syntax-table
-    ()
+(defvar decipher-mode-syntax-table
   (let ((table (make-syntax-table))
         (c ?0))
     (while (<= c ?9)
       (modify-syntax-entry c "_" table) ;Digits are not part of words
       (cl-incf c))
-    (setq decipher-mode-syntax-table table)))
+    table)
+  "Decipher mode syntax table")
 
 (defvar-local decipher-alphabet nil)
 ;; This is an alist containing entries (PLAIN-CHAR . CIPHER-CHAR),
@@ -214,7 +213,6 @@ list of such cons cells.")
 (defvar decipher--freqs)
 
 ;;;===================================================================
-;;; Code:
 ;;;===================================================================
 ;; Main entry points:
 ;;--------------------------------------------------------------------
@@ -256,7 +254,7 @@ ABCDEFGHIJKLMNOPQRSTUVWXYZ   -*-decipher-*-\n)\n\n")
   (decipher-mode))
 
 ;;;###autoload
-(defun decipher-mode ()
+(define-derived-mode decipher-mode nil "Decipher"
   "Major mode for decrypting monoalphabetic substitution ciphers.
 Lower-case letters enter plaintext.
 Upper-case letters are commands.
@@ -272,16 +270,10 @@ The most useful commands are:
   Show adjacency list for current letter (lists letters appearing next to it)
 \\[decipher-make-checkpoint]  Save the current cipher alphabet (checkpoint)
 \\[decipher-restore-checkpoint]  Restore a saved cipher alphabet (checkpoint)"
-  (interactive)
-  (kill-all-local-variables)
   (setq buffer-undo-list  t             ;Disable undo
-        indent-tabs-mode  nil           ;Do not use tab characters
-        major-mode       'decipher-mode
-        mode-name        "Decipher")
+        indent-tabs-mode  nil)          ;Do not use tab characters
   (if decipher-force-uppercase
       (setq case-fold-search nil))      ;Case is significant when searching
-  (use-local-map decipher-mode-map)
-  (set-syntax-table decipher-mode-syntax-table)
   (unless (= (point-min) (point-max))
     (decipher-read-alphabet))
   (setq-local font-lock-defaults
@@ -291,7 +283,6 @@ The most useful commands are:
             (lambda () (setq buffer-read-only nil
                              buffer-undo-list nil))
             nil t)
-  (run-mode-hooks 'decipher-mode-hook)
   (setq buffer-read-only t))
 (put 'decipher-mode 'mode-class 'special)
 
@@ -301,7 +292,7 @@ The most useful commands are:
 
 (defun decipher-keypress ()
   "Enter a plaintext or ciphertext character."
-  (interactive)
+  (interactive nil decipher-mode)
   (let ((decipher-function 'decipher-set-map)
         buffer-read-only)               ;Make buffer writable
     (save-excursion
@@ -314,10 +305,10 @@ The most useful commands are:
                ((= ?> first-char)
                 nil)
                ((= ?\( first-char)
-                (setq decipher-function 'decipher-alphabet-keypress)
+                (setq decipher-function #'decipher-alphabet-keypress)
                 t)
                ((= ?\) first-char)
-                (setq decipher-function 'decipher-alphabet-keypress)
+                (setq decipher-function #'decipher-alphabet-keypress)
                 nil)
                (t
                 (error "Bad location")))))
@@ -355,7 +346,7 @@ The most useful commands are:
 
 (defun decipher-undo ()
   "Undo a change in Decipher mode."
-  (interactive)
+  (interactive nil decipher-mode)
   ;; If we don't get all the way thru, make last-command indicate that
   ;; for the following command.
   (setq this-command t)
@@ -456,7 +447,7 @@ The most useful commands are:
       (decipher-insert plain-char)
       (setq case-fold-search t          ;Case is not significant
             cipher-string    (downcase cipher-string))
-      (let ((font-lock-fontify-region-function 'ignore))
+      (let ((font-lock-fontify-region-function #'ignore))
         ;; insert-and-inherit will pick the right face automatically
         (while (search-forward-regexp "^:" nil t)
           (setq bound (point-at-eol))
@@ -496,7 +487,7 @@ The most useful commands are:
 This records the current alphabet so you can return to it later.
 You may have any number of checkpoints.
 Type `\\[decipher-restore-checkpoint]' to restore a checkpoint."
-  (interactive "sCheckpoint description: ")
+  (interactive "sCheckpoint description: " decipher-mode)
   (or (stringp desc)
       (setq desc ""))
   (let (alphabet
@@ -523,7 +514,7 @@ If point is not on a checkpoint line, moves to the first 
checkpoint line.
 If point is on a checkpoint, restores that checkpoint.
 
 Type `\\[decipher-make-checkpoint]' to make a checkpoint."
-  (interactive)
+  (interactive nil decipher-mode)
   (beginning-of-line)
   (if (looking-at "%!\\([A-Z ]+\\)!")
       ;; Restore this checkpoint:
@@ -551,7 +542,7 @@ Type `\\[decipher-make-checkpoint]' to make a checkpoint."
 This fills any blanks in the cipher alphabet with the unused letters
 in alphabetical order.  Use this when you have a keyword cipher and
 you have determined the keyword."
-  (interactive)
+  (interactive nil decipher-mode)
   (let ((cipher-char ?A)
         (ptr decipher-alphabet)
         buffer-read-only                ;Make buffer writable
@@ -568,7 +559,7 @@ you have determined the keyword."
 
 (defun decipher-show-alphabet ()
   "Display the current cipher alphabet in the message line."
-  (interactive)
+  (interactive nil decipher-mode)
   (message "%s"
    (mapconcat (lambda (a)
                 (concat
@@ -581,7 +572,7 @@ you have determined the keyword."
   "Reprocess the buffer using the alphabet from the top.
 This regenerates all deciphered plaintext and clears the undo list.
 You should use this if you edit the ciphertext."
-  (interactive)
+  (interactive nil decipher-mode)
   (message "Reprocessing buffer...")
   (let (alphabet
         buffer-read-only                ;Make buffer writable
@@ -625,13 +616,13 @@ You should use this if you edit the ciphertext."
 
 (defun decipher-frequency-count ()
   "Display the frequency count in the statistics buffer."
-  (interactive)
+  (interactive nil decipher-mode)
   (decipher-analyze)
   (decipher-display-regexp "^A" "^[A-Z][A-Z]"))
 
 (defun decipher-digram-list ()
   "Display the list of digrams in the statistics buffer."
-  (interactive)
+  (interactive nil decipher-mode)
   (decipher-analyze)
   (decipher-display-regexp "[A-Z][A-Z] +[0-9]" "^$"))
 
@@ -648,7 +639,7 @@ words, and ends 3 words (`*' represents a space).  X comes 
before 8
 different letters, after 7 different letters, and is next to a total
 of 11 different letters.  It occurs 14 times, making up 9% of the
 ciphertext."
-  (interactive (list (upcase (following-char))))
+  (interactive (list (upcase (following-char))) decipher-mode)
   (decipher-analyze)
   (let (start end)
     (with-current-buffer (decipher-stats-buffer)
@@ -868,12 +859,12 @@ Creates the statistics buffer if it doesn't exist."
         (aset decipher--after  i (make-vector 27 0))))
     (if decipher-ignore-spaces
         (progn
-          (decipher-loop-no-breaks 'decipher--analyze)
+          (decipher-loop-no-breaks #'decipher--analyze)
           ;; The first character of ciphertext was marked as following a space:
           (let ((i 26))
             (while (>= (cl-decf i) 0)
               (aset (aref decipher--after  i) 26 0))))
-      (decipher-loop-with-breaks 'decipher--analyze))
+      (decipher-loop-with-breaks #'decipher--analyze))
     (message "Processing results...")
     (setcdr (last decipher--digram-list 2) nil)   ;Delete the phony "* " digram
     ;; Sort the digram list by frequency and alphabetical order:
@@ -954,18 +945,12 @@ Creates the statistics buffer if it doesn't exist."
 ;; Statistics Buffer:
 ;;====================================================================
 
-(defun decipher-stats-mode ()
+(define-derived-mode decipher-stats-mode nil "Decipher-Stats"
   "Major mode for displaying ciphertext statistics."
-  (interactive)
-  (kill-all-local-variables)
   (setq buffer-read-only  t
         buffer-undo-list  t             ;Disable undo
         case-fold-search  nil           ;Case is significant when searching
-        indent-tabs-mode  nil           ;Do not use tab characters
-        major-mode       'decipher-stats-mode
-        mode-name        "Decipher-Stats")
-  (use-local-map decipher-stats-mode-map)
-  (run-mode-hooks 'decipher-stats-mode-hook))
+        indent-tabs-mode  nil))         ;Do not use tab characters
 (put 'decipher-stats-mode 'mode-class 'special)
 
 ;;--------------------------------------------------------------------
@@ -1001,9 +986,8 @@ if it can't, it signals an error."
     (let ((stats-name (concat "*" (buffer-name) "*")))
       (setq decipher-stats-buffer
             (if (eq 'decipher-stats-mode
-                    (cdr-safe (assoc 'major-mode
-                                     (buffer-local-variables
-                                      (get-buffer stats-name)))))
+                    (buffer-local-value 'major-mode
+                                        (get-buffer stats-name)))
                 ;; We just lost track of the statistics buffer:
                 (get-buffer stats-name)
               (generate-new-buffer stats-name))))
diff --git a/lisp/play/doctor.el b/lisp/play/doctor.el
index 46fd852..bf923f4 100644
--- a/lisp/play/doctor.el
+++ b/lisp/play/doctor.el
@@ -1583,7 +1583,7 @@ Hack on previous word, setting global variable 
DOCTOR-OWNER to correct result."
                           E-mail: jo@samaritans.org or\, at your option\,
                           anonymous E-mail: samaritans@anon.twwells.com\ \.
                            or find a Befrienders crisis center at
-                          http://www.befrienders.org/\ \.
+                           https://www.befrienders.org/\ \.
                           (doc$ doctor--please) (doc$ doctor--continue) \.)))
        (t (doctor-type (doc$ doctor--deathlst)))))
 
diff --git a/lisp/play/gomoku.el b/lisp/play/gomoku.el
index 8db40d7..0a45885 100644
--- a/lisp/play/gomoku.el
+++ b/lisp/play/gomoku.el
@@ -28,39 +28,36 @@
 ;; RULES:
 ;;
 ;; Gomoku is a game played between two players on a rectangular board.  Each
-;; player, in turn, marks a free square of its choice. The winner is the first
+;; player, in turn, marks a free square of its choice.  The winner is the first
 ;; one to mark five contiguous squares in any direction (horizontally,
 ;; vertically or diagonally).
 ;;
 ;; I have been told that, in "The TRUE Gomoku", some restrictions are made
 ;; about the squares where one may play, or else there is a known forced win
-;; for the first player. This program has no such restriction, but it does not
+;; for the first player.  This program has no such restriction, but it does not
 ;; know about the forced win, nor do I.
-;; See http://renju.se/rif/r1rulhis.htm for more information.
-
+;; See https://renju.se/rif/r1rulhis.htm for more information.
 
 ;; There are two main places where you may want to customize the program: key
-;; bindings and board display. These features are commented in the code. Go
+;; bindings and board display.  These features are commented in the code.  Go
 ;; and see.
 
-
 ;; HOW TO USE:
 ;;
-;; The command "M-x gomoku" displays a
-;; board, the size of which depends on the size of the current window. The
-;; size of the board is easily modified by giving numeric arguments to the
-;; gomoku command and/or by customizing the displaying parameters.
+;; The command `M-x gomoku' displays a board, the size of which depends on the
+;; size of the current window.  The size of the board is easily modified by
+;; giving numeric arguments to the gomoku command and/or by customizing the
+;; displaying parameters.
 ;;
-;; Emacs plays when it is its turn. When it is your turn, just put the cursor
+;; Emacs plays when it is its turn.  When it is your turn, just put the cursor
 ;; on the square where you want to play and hit RET, or X, or whatever key you
-;; bind to the command gomoku-human-plays. When it is your turn, Emacs is
+;; bind to the command `gomoku-human-plays'.  When it is your turn, Emacs is
 ;; idle: you may switch buffers, read your mail, ... Just come back to the
 ;; *Gomoku* buffer and resume play.
 
-
 ;; ALGORITHM:
 ;;
-;; The algorithm is briefly described in section "THE SCORE TABLE". Some
+;; The algorithm is briefly described in section "THE SCORE TABLE".  Some
 ;; parameters may be modified if you want to change the style exhibited by the
 ;; program.
 
@@ -86,13 +83,15 @@ One useful value to include is `turn-on-font-lock' to 
highlight the pieces."
   "Name of the Gomoku buffer.")
 
 ;; You may change these values if you have a small screen or if the squares
-;; look rectangular, but spacings SHOULD be at least 2 (MUST BE at least 1).
+;; look rectangular.
 
 (defconst gomoku-square-width 4
-  "Horizontal spacing between squares on the Gomoku board.")
+  "Horizontal spacing between squares on the Gomoku board.
+SHOULD be at least 2 (MUST BE at least 1).")
 
 (defconst gomoku-square-height 2
-  "Vertical spacing between squares on the Gomoku board.")
+  "Vertical spacing between squares on the Gomoku board.
+SHOULD be at least 2 (MUST BE at least 1).")
 
 (defconst gomoku-x-offset 3
   "Number of columns between the Gomoku board and the side of the window.")
@@ -270,13 +269,13 @@ Other useful commands:\n
 ;; internested 5-tuples of contiguous squares (called qtuples).
 ;;
 ;; The aim of the program is to fill one qtuple with its O's while preventing
-;; you from filling another one with your X's. To that effect, it computes a
-;; score for every qtuple, with better qtuples having better scores. Of
+;; you from filling another one with your X's.  To that effect, it computes a
+;; score for every qtuple, with better qtuples having better scores.  Of
 ;; course, the score of a qtuple (taken in isolation) is just determined by
-;; its contents as a set, i.e. not considering the order of its elements. The
+;; its contents as a set, i.e. not considering the order of its elements.  The
 ;; highest score is given to the "OOOO" qtuples because playing in such a
-;; qtuple is winning the game. Just after this comes the "XXXX" qtuple because
-;; not playing in it is just losing the game, and so on. Note that a
+;; qtuple is winning the game.  Just after this comes the "XXXX" qtuple because
+;; not playing in it is just losing the game, and so on.  Note that a
 ;; "polluted" qtuple, i.e. one containing at least one X and at least one O,
 ;; has score zero because there is no more any point in playing in it, from
 ;; both an attacking and a defending point of view.
@@ -284,11 +283,11 @@ Other useful commands:\n
 ;; Given the score of every qtuple, the score of a given free square on the
 ;; board is just the sum of the scores of all the qtuples to which it belongs,
 ;; because playing in that square is playing in all its containing qtuples at
-;; once. And it is that function which takes into account the internesting of
+;; once.  And it is that function which takes into account the internesting of
 ;; the qtuples.
 ;;
 ;; This algorithm is rather simple but anyway it gives a not so dumb level of
-;; play. It easily extends to "n-dimensional Gomoku", where a win should not
+;; play.  It easily extends to "n-dimensional Gomoku", where a win should not
 ;; be obtained with as few as 5 contiguous marks: 6 or 7 (depending on n !)
 ;; should be preferred.
 
@@ -323,8 +322,8 @@ Other useful commands:\n
 ;; because "a" mainly belongs to six "XX" qtuples (the others are less
 ;; important) while "b" belongs to one "XXX" and one "XX" qtuples.  Other
 ;; conditions are required to obtain sensible moves, but the previous example
-;; should illustrate the point. If you manage to improve on these values,
-;; please send me a note. Thanks.
+;; should illustrate the point.  If you manage to improve on these values,
+;; please send me a note.  Thanks.
 
 
 ;; As we chose values 0, 1 and 6 to denote empty, X and O squares, the
@@ -343,9 +342,9 @@ Other useful commands:\n
 
 ;; If you do not modify drastically the previous constants, the only way for a
 ;; square to have a score higher than gomoku-OOOOscore is to belong to a "OOOO"
-;; qtuple, thus to be a winning move. Similarly, the only way for a square to
+;; qtuple, thus to be a winning move.  Similarly, the only way for a square to
 ;; have a score between gomoku-XXXXscore and gomoku-OOOOscore is to belong to 
a "XXXX"
-;; qtuple. We may use these considerations to detect when a given move is
+;; qtuple.  We may use these considerations to detect when a given move is
 ;; winning or losing.
 
 (defconst gomoku-winning-threshold gomoku-OOOOscore
@@ -357,8 +356,8 @@ Other useful commands:\n
 
 (defun gomoku-strongest-square ()
   "Compute index of free square with highest score, or nil if none."
-  ;; We just have to loop other all squares. However there are two problems:
-  ;; 1/ The SCORE-TABLE only gives correct scores to free squares. To speed
+  ;; We just have to loop other all squares.  However there are two problems:
+  ;; 1/ The SCORE-TABLE only gives correct scores to free squares.  To speed
   ;;   up future searches, we set the score of padding or occupied squares
   ;;   to -1 whenever we meet them.
   ;; 2/ We want to choose randomly between equally good moves.
@@ -378,7 +377,7 @@ Other useful commands:\n
                  best-square square
                  score-max   score)
            (aset gomoku-score-table square -1))) ; no: kill it !
-       ;; If score is equally good, choose randomly. But first check freedom:
+       ;; If score is equally good, choose randomly.  But first check freedom:
        ((not (zerop (aref gomoku-board square)))
        (aset gomoku-score-table square -1))
        ((zerop (random (setq count (1+ count))))
@@ -392,11 +391,11 @@ Other useful commands:\n
 ;;;
 
 ;; At initialization the board is empty so that every qtuple amounts for
-;; gomoku-nil-score. Therefore, the score of any square is gomoku-nil-score 
times the number
-;; of qtuples that pass through it. This number is 3 in a corner and 20 if you
-;; are sufficiently far from the sides. As computing the number is time
+;; gomoku-nil-score.  Therefore, the score of any square is gomoku-nil-score 
times the number
+;; of qtuples that pass through it.  This number is 3 in a corner and 20 if you
+;; are sufficiently far from the sides.  As computing the number is time
 ;; consuming, we initialize every square with 20*gomoku-nil-score and then only
-;; consider squares at less than 5 squares from one side. We speed this up by
+;; consider squares at less than 5 squares from one side.  We speed this up by
 ;; taking symmetry into account.
 ;; Also, as it is likely that successive games will be played on a board with
 ;; same size, it is a good idea to save the initial SCORE-TABLE configuration.
@@ -451,7 +450,7 @@ Other useful commands:\n
   "Return the number of qtuples containing square I,J."
   ;; This function is complicated because we have to deal
   ;; with ugly cases like 3 by 6 boards, but it works.
-  ;; If you have a simpler (and correct) solution, send it to me. Thanks !
+  ;; If you have a simpler (and correct) solution, send it to me.  Thanks !
   (let ((left  (min 4 (1- i)))
        (right (min 4 (- gomoku-board-width i)))
        (up    (min 4 (1- j)))
@@ -477,9 +476,9 @@ Other useful commands:\n
 ;;;
 
 ;; We do not provide functions for computing the SCORE-TABLE given the
-;; contents of the BOARD. This would involve heavy nested loops, with time
-;; proportional to the size of the board. It is better to update the
-;; SCORE-TABLE after each move. Updating needs not modify more than 36
+;; contents of the BOARD.  This would involve heavy nested loops, with time
+;; proportional to the size of the board.  It is better to update the
+;; SCORE-TABLE after each move.  Updating needs not modify more than 36
 ;; squares: it is done in constant time.
 
 (defun gomoku-update-score-table (square dval)
@@ -782,7 +781,7 @@ Use \\[describe-mode] for more info."
 
 (defun gomoku-emacs-plays ()
   "Compute Emacs next move and play it."
-  (interactive)
+  (interactive nil gomoku-mode)
   (gomoku-switch-to-window)
   (cond
    (gomoku-emacs-is-computing
@@ -815,7 +814,7 @@ Use \\[describe-mode] for more info."
 ;; pixels, event's (X . Y) is a character's top-left corner.
 (defun gomoku-click (click)
   "Position at the square where you click."
-  (interactive "e")
+  (interactive "e" gomoku-mode)
   (and (windowp (posn-window (setq click (event-end click))))
        (numberp (posn-point click))
        (select-window (posn-window click))
@@ -844,7 +843,7 @@ Use \\[describe-mode] for more info."
 
 (defun gomoku-mouse-play (click)
   "Play at the square where you click."
-  (interactive "e")
+  (interactive "e" gomoku-mode)
   (if (gomoku-click click)
       (gomoku-human-plays)))
 
@@ -852,7 +851,7 @@ Use \\[describe-mode] for more info."
   "Signal to the Gomoku program that you have played.
 You must have put the cursor on the square where you want to play.
 If the game is finished, this command requests for another game."
-  (interactive)
+  (interactive nil gomoku-mode)
   (gomoku-switch-to-window)
   (cond
    (gomoku-emacs-is-computing
@@ -880,7 +879,7 @@ If the game is finished, this command requests for another 
game."
 
 (defun gomoku-human-takes-back ()
   "Signal to the Gomoku program that you wish to take back your last move."
-  (interactive)
+  (interactive nil gomoku-mode)
   (gomoku-switch-to-window)
   (cond
    (gomoku-emacs-is-computing
@@ -904,7 +903,7 @@ If the game is finished, this command requests for another 
game."
 
 (defun gomoku-human-resigns ()
   "Signal to the Gomoku program that you may want to resign."
-  (interactive)
+  (interactive nil gomoku-mode)
   (gomoku-switch-to-window)
   (cond
    (gomoku-emacs-is-computing
@@ -1162,20 +1161,20 @@ If the game is finished, this command requests for 
another game."
 ;; the screen.
 (defun gomoku-move-right ()
   "Move point right one column on the Gomoku board."
-  (interactive)
+  (interactive nil gomoku-mode)
   (when (< (gomoku-point-x) gomoku-board-width)
     (forward-char gomoku-square-width)))
 
 (defun gomoku-move-left ()
   "Move point left one column on the Gomoku board."
-  (interactive)
+  (interactive nil gomoku-mode)
   (when (> (gomoku-point-x) 1)
     (backward-char gomoku-square-width)))
 
 ;; previous-line and next-line don't work right with intangible newlines
 (defun gomoku-move-down ()
   "Move point down one row on the Gomoku board."
-  (interactive)
+  (interactive nil gomoku-mode)
   (when (< (gomoku-point-y) gomoku-board-height)
     (let ((column (current-column)))
       (forward-line gomoku-square-height)
@@ -1183,7 +1182,7 @@ If the game is finished, this command requests for 
another game."
 
 (defun gomoku-move-up ()
   "Move point up one row on the Gomoku board."
-  (interactive)
+  (interactive nil gomoku-mode)
   (when (> (gomoku-point-y) 1)
     (let ((column (current-column)))
       (forward-line (- gomoku-square-height))
@@ -1191,36 +1190,36 @@ If the game is finished, this command requests for 
another game."
 
 (defun gomoku-move-ne ()
   "Move point North East on the Gomoku board."
-  (interactive)
+  (interactive nil gomoku-mode)
   (gomoku-move-up)
   (gomoku-move-right))
 
 (defun gomoku-move-se ()
   "Move point South East on the Gomoku board."
-  (interactive)
+  (interactive nil gomoku-mode)
   (gomoku-move-down)
   (gomoku-move-right))
 
 (defun gomoku-move-nw ()
   "Move point North West on the Gomoku board."
-  (interactive)
+  (interactive nil gomoku-mode)
   (gomoku-move-up)
   (gomoku-move-left))
 
 (defun gomoku-move-sw ()
   "Move point South West on the Gomoku board."
-  (interactive)
+  (interactive nil gomoku-mode)
   (gomoku-move-down)
   (gomoku-move-left))
 
 (defun gomoku-beginning-of-line ()
   "Move point to first square on the Gomoku board row."
-  (interactive)
+  (interactive nil gomoku-mode)
   (move-to-column gomoku-x-offset))
 
 (defun gomoku-end-of-line ()
   "Move point to last square on the Gomoku board row."
-  (interactive)
+  (interactive nil gomoku-mode)
   (move-to-column (+ gomoku-x-offset
                     (* gomoku-square-width (1- gomoku-board-width)))))
 
diff --git a/lisp/play/handwrite.el b/lisp/play/handwrite.el
index 98da26c..cc05823 100644
--- a/lisp/play/handwrite.el
+++ b/lisp/play/handwrite.el
@@ -90,7 +90,8 @@
     (define-key map [handwrite] '("Write by hand" . handwrite))
     map))
 (fset 'menu-bar-handwrite-map menu-bar-handwrite-map)
-
+(make-obsolete 'menu-bar-handwrite-map nil "28.1")
+(make-obsolete-variable 'menu-bar-handwrite-map nil "28.1")
 
 ;; User definable variables
 
diff --git a/lisp/play/morse.el b/lisp/play/morse.el
index 8e09c22..91dc687 100644
--- a/lisp/play/morse.el
+++ b/lisp/play/morse.el
@@ -146,7 +146,7 @@
   "NATO phonetic alphabet.
 See “International Code of Signals” (INTERCO), United States
 Edition, 1969 Edition (Revised 2003) available from National
-Geospatial-Intelligence Agency at URL `http://www.nga.mil/'")
+Geospatial-Intelligence Agency at URL `https://www.nga.mil/'")
 
 ;;;###autoload
 (defun morse-region (beg end)
diff --git a/lisp/play/snake.el b/lisp/play/snake.el
index bed7cea..29effa2 100644
--- a/lisp/play/snake.el
+++ b/lisp/play/snake.el
@@ -336,38 +336,38 @@ Argument SNAKE-BUFFER is the name of the buffer."
 
 (defun snake-move-left ()
   "Make the snake move left."
-  (interactive)
+  (interactive nil snake-mode)
   (when (zerop (snake-final-x-velocity))
     (push '(-1 0) snake-velocity-queue)))
 
 (defun snake-move-right ()
   "Make the snake move right."
-  (interactive)
+  (interactive nil snake-mode)
   (when (zerop (snake-final-x-velocity))
     (push '(1 0) snake-velocity-queue)))
 
 (defun snake-move-up ()
   "Make the snake move up."
-  (interactive)
+  (interactive nil snake-mode)
   (when (zerop (snake-final-y-velocity))
     (push '(0 -1) snake-velocity-queue)))
 
 (defun snake-move-down ()
   "Make the snake move down."
-  (interactive)
+  (interactive nil snake-mode)
   (when (zerop (snake-final-y-velocity))
     (push '(0 1) snake-velocity-queue)))
 
 (defun snake-end-game ()
   "Terminate the current game."
-  (interactive)
+  (interactive nil snake-mode)
   (gamegrid-kill-timer)
   (use-local-map snake-null-map)
   (gamegrid-add-score snake-score-file snake-score))
 
 (defun snake-start-game ()
   "Start a new game of Snake."
-  (interactive)
+  (interactive nil snake-mode)
   (snake-reset-game)
   (snake-set-dot)
   (use-local-map snake-mode-map)
@@ -375,7 +375,7 @@ Argument SNAKE-BUFFER is the name of the buffer."
 
 (defun snake-pause-game ()
   "Pause (or resume) the current game."
-  (interactive)
+  (interactive nil snake-mode)
   (setq snake-paused (not snake-paused))
   (message (and snake-paused "Game paused (press p to resume)")))
 
@@ -386,6 +386,7 @@ Argument SNAKE-BUFFER is the name of the buffer."
 
 (define-derived-mode snake-mode special-mode "Snake"
   "A mode for playing Snake."
+  :interactive nil
 
   (add-hook 'kill-buffer-hook 'gamegrid-kill-timer nil t)
 
diff --git a/lisp/play/tetris.el b/lisp/play/tetris.el
index 05e4ffe..f43aa47 100644
--- a/lisp/play/tetris.el
+++ b/lisp/play/tetris.el
@@ -506,7 +506,7 @@ Drops the shape one square, testing for collision."
 
 (defun tetris-move-bottom ()
   "Drop the shape to the bottom of the playing area."
-  (interactive)
+  (interactive nil tetris-mode)
   (unless tetris-paused
     (let ((hit nil))
       (tetris-erase-shape)
@@ -519,7 +519,7 @@ Drops the shape one square, testing for collision."
 
 (defun tetris-move-left ()
   "Move the shape one square to the left."
-  (interactive)
+  (interactive nil tetris-mode)
   (unless tetris-paused
     (tetris-erase-shape)
     (setq tetris-pos-x (1- tetris-pos-x))
@@ -529,7 +529,7 @@ Drops the shape one square, testing for collision."
 
 (defun tetris-move-right ()
   "Move the shape one square to the right."
-  (interactive)
+  (interactive nil tetris-mode)
   (unless tetris-paused
     (tetris-erase-shape)
     (setq tetris-pos-x (1+ tetris-pos-x))
@@ -539,7 +539,7 @@ Drops the shape one square, testing for collision."
 
 (defun tetris-move-down ()
   "Move the shape one square to the bottom."
-  (interactive)
+  (interactive nil tetris-mode)
   (unless tetris-paused
     (tetris-erase-shape)
     (setq tetris-pos-y (1+ tetris-pos-y))
@@ -549,7 +549,7 @@ Drops the shape one square, testing for collision."
 
 (defun tetris-rotate-prev ()
   "Rotate the shape clockwise."
-  (interactive)
+  (interactive nil tetris-mode)
   (unless tetris-paused
       (tetris-erase-shape)
       (setq tetris-rot (% (+ 1 tetris-rot)
@@ -561,7 +561,7 @@ Drops the shape one square, testing for collision."
 
 (defun tetris-rotate-next ()
   "Rotate the shape anticlockwise."
-  (interactive)
+  (interactive nil tetris-mode)
   (unless tetris-paused
         (tetris-erase-shape)
         (setq tetris-rot (% (+ 3 tetris-rot)
@@ -573,14 +573,14 @@ Drops the shape one square, testing for collision."
 
 (defun tetris-end-game ()
   "Terminate the current game."
-  (interactive)
+  (interactive nil tetris-mode)
   (gamegrid-kill-timer)
   (use-local-map tetris-null-map)
   (gamegrid-add-score tetris-score-file tetris-score))
 
 (defun tetris-start-game ()
   "Start a new game of Tetris."
-  (interactive)
+  (interactive nil tetris-mode)
   (tetris-reset-game)
   (use-local-map tetris-mode-map)
   (let ((period (or (tetris-get-tick-period)
@@ -589,7 +589,7 @@ Drops the shape one square, testing for collision."
 
 (defun tetris-pause-game ()
   "Pause (or resume) the current game."
-  (interactive)
+  (interactive nil tetris-mode)
   (setq tetris-paused (not tetris-paused))
   (message (and tetris-paused "Game paused (press p to resume)")))
 
@@ -600,6 +600,7 @@ Drops the shape one square, testing for collision."
 
 (define-derived-mode tetris-mode nil "Tetris"
   "A mode for playing Tetris."
+  :interactive nil
 
   (add-hook 'kill-buffer-hook 'gamegrid-kill-timer nil t)
 
diff --git a/lisp/plstore.el b/lisp/plstore.el
index 4653366..4ca5886 100644
--- a/lisp/plstore.el
+++ b/lisp/plstore.el
@@ -1,4 +1,5 @@
 ;;; plstore.el --- secure plist store -*- lexical-binding: t -*-
+
 ;; Copyright (C) 2011-2021 Free Software Foundation, Inc.
 
 ;; Author: Daiki Ueno <ueno@gnu.org>
@@ -19,7 +20,7 @@
 ;; You should have received a copy of the GNU General Public License
 ;; along with GNU Emacs.  If not, see <https://www.gnu.org/licenses/>.
 
-;;; Commentary
+;;; Commentary:
 
 ;; Plist based data store providing search and partial encryption.
 ;;
diff --git a/lisp/printing.el b/lisp/printing.el
index 2f234b7..b9a2e33 100644
--- a/lisp/printing.el
+++ b/lisp/printing.el
@@ -103,14 +103,14 @@ Please send all bug fixes and enhancements to
 ;; For example, after previewing a PostScript file, *Printing Command Output*
 ;; will have the following entry:
 ;;
-;;    /usr/X11R6/bin/gv ("/home/user/example/file.ps")
+;;    /usr/bin/gv ("/home/user/example/file.ps")
 ;;    Exit status: 0
 ;;
 ;; In the example above, the previewing was successful.  If during previewing,
 ;; you quit gv execution (by typing C-g during Emacs session), the log entry
 ;; would be:
 ;;
-;;    /usr/X11R6/bin/gv ("/home/user/example/file.ps")
+;;    /usr/bin/gv ("/home/user/example/file.ps")
 ;;    Exit status: Quit
 ;;
 ;; So, if something goes wrong, a good place to take a look is the buffer
@@ -264,7 +264,7 @@ Please send all bug fixes and enhancements to
 ;;    Also the gsprint utility comes together with gsview distribution.
 ;;
 ;;    For more information about gsprint see
-;;    `http://www.cs.wisc.edu/~ghost/gsview/gsprint.htm'.
+;;    `https://www.cs.wisc.edu/~ghost/gsview/gsprint.htm'.
 ;;
 ;;    As an example of gsprint declaration:
 ;;
@@ -950,18 +950,18 @@ Please send all bug fixes and enhancements to
 ;; * For GNU or Unix system:
 ;;
 ;;    gs, gv         
`https://www.gnu.org/software/ghostscript/ghostscript.html'
-;;    enscript       `http://people.ssh.fi/mtr/genscript/'
+;;    enscript       `https://people.ssh.fi/mtr/genscript/'
 ;;    psnup          `http://www.knackered.org/angus/psutils/'
-;;    mpage          `http://www.mesa.nl/pub/mpage/'
+;;    mpage          `https://www.mesa.nl/pub/mpage/'
 ;;
 ;; * For Windows system:
 ;;
 ;;    gswin32, gsview32
 ;;                   
`https://www.gnu.org/software/ghostscript/ghostscript.html'
-;;    gsprint        `http://www.cs.wisc.edu/~ghost/gsview/gsprint.htm'.
-;;    enscript       `http://people.ssh.fi/mtr/genscript/'
+;;    gsprint        `https://www.cs.wisc.edu/~ghost/gsview/gsprint.htm'.
+;;    enscript       `https://people.ssh.fi/mtr/genscript/'
 ;;    psnup          `http://gnuwin32.sourceforge.net/packages/psutils.htm'
-;;    redmon         `http://www.cs.wisc.edu/~ghost/redmon/'
+;;    redmon         `http://www.ghostgum.com.au/software/redmon.htm'
 ;;
 ;;
 ;; Acknowledgments
@@ -1014,7 +1014,6 @@ Please send all bug fixes and enhancements to
 
 (require 'lpr)
 (require 'ps-print)
-(require 'easymenu)
 
 (and (string< ps-print-version "6.6.4")
      (error "`printing' requires `ps-print' package version 6.6.4 or later"))
@@ -1521,22 +1520,19 @@ Examples:
 Useful links:
 
 * Information about the print command (print.exe)
-  `http://www.computerhope.com/printhlp.htm'
+  `https://www.computerhope.com/printhlp.htm'
 
 * RedMon - Redirection Port Monitor (redpr.exe)
-  `http://www.cs.wisc.edu/~ghost/redmon/index.htm'
+  `http://www.ghostgum.com.au/software/redmon.htm'
 
 * Redirection Port Monitor (redpr.exe on-line help)
-  `http://www.cs.wisc.edu/~ghost/redmon/en/redmon.htm'
+  `https://www.cs.wisc.edu/~ghost/redmon/en/redmon.htm'
 
 * UNIX man pages: lpr (or type `man lpr')
-  `http://bama.ua.edu/cgi-bin/man-cgi?lpr'
-  `http://www.mediacollege.com/cgi-bin/man/page.cgi?section=all&topic=lpr'
+  `https://linux.die.net/man/1/lpr-cups'
 
 * UNIX man pages: lp (or type `man lp')
-  `http://bama.ua.edu/cgi-bin/man-cgi?lp'
-  `http://www.mediacollege.com/cgi-bin/man/page.cgi?section=all&topic=lp'
-"
+  `https://linux.die.net/man/1/lp'"
   :type '(repeat
          (list :tag "Text Printer"
                (symbol :tag "Printer Symbol Name")
@@ -1761,30 +1757,28 @@ are not printed.
 Useful links:
 
 * GSPRINT - Ghostscript print to Windows printer
-  `http://www.cs.wisc.edu/~ghost/gsview/gsprint.htm'
+  `https://www.cs.wisc.edu/~ghost/gsview/gsprint.htm'
 
 * Introduction to Ghostscript
-  `http://www.cs.wisc.edu/~ghost/doc/intro.htm'
+  `https://www.cs.wisc.edu/~ghost/doc/intro.htm'
 
 * How to use Ghostscript
-  `http://www.cs.wisc.edu/~ghost/doc/cvs/Use.htm'
+  `https://www.cs.wisc.edu/~ghost/doc/cvs/Use.htm'
 
 * Information about the print command (print.exe)
-  `http://www.computerhope.com/printhlp.htm'
+  `https://www.computerhope.com/printhlp.htm'
 
 * RedMon - Redirection Port Monitor (redpr.exe)
-  `http://www.cs.wisc.edu/~ghost/redmon/index.htm'
+  `http://www.ghostgum.com.au/software/redmon.htm'
 
 * Redirection Port Monitor (redpr.exe on-line help)
-  `http://www.cs.wisc.edu/~ghost/redmon/en/redmon.htm'
+  `https://www.cs.wisc.edu/~ghost/redmon/en/redmon.htm'
 
 * UNIX man pages: lpr (or type `man lpr')
-  `http://bama.ua.edu/cgi-bin/man-cgi?lpr'
-  `http://www.mediacollege.com/cgi-bin/man/page.cgi?section=all&topic=lpr'
+  `https://linux.die.net/man/1/lpr-cups'
 
 * UNIX man pages: lp (or type `man lp')
-  `http://bama.ua.edu/cgi-bin/man-cgi?lp'
-  `http://www.mediacollege.com/cgi-bin/man/page.cgi?section=all&topic=lp'
+  `https://linux.die.net/man/1/lp'
 
 * GNU utilities for w32 (cp.exe)
   `http://unxutils.sourceforge.net/'
@@ -1874,28 +1868,28 @@ Useful links:
   `https://www.gnu.org/software/gv/manual/gv.html'
 
 * GSview Help
-  `http://www.cs.wisc.edu/~ghost/gsview/gsviewen.htm'
+  `https://www.cs.wisc.edu/~ghost/gsview/gsviewen.htm'
 
 * GSview Help - Common Problems
-  `http://www.cs.wisc.edu/~ghost/gsview/gsviewen.htm#Common_Problems'
+  `https://www.cs.wisc.edu/~ghost/gsview/gsviewen.htm#Common_Problems'
 
 * GSview Readme (compilation & installation)
-  `http://www.cs.wisc.edu/~ghost/gsview/Readme.htm'
+  `https://www.cs.wisc.edu/~ghost/gsview/Readme.htm'
 
 * GSview (main site)
-  `http://www.cs.wisc.edu/~ghost/gsview/index.htm'
+  `https://www.cs.wisc.edu/~ghost/gsview/index.htm'
 
 * Ghostscript, Ghostview and GSview
-  `http://www.cs.wisc.edu/~ghost/'
+  `https://www.cs.wisc.edu/~ghost/'
 
 * Ghostview
-  `http://www.cs.wisc.edu/~ghost/gv/index.htm'
+  `https://www.cs.wisc.edu/~ghost/gv/index.htm'
 
 * gv 3.5, June 1997
-  `http://www.cs.wisc.edu/~ghost/gv/gv_doc/gv.html'
+  `http://pages.cs.wisc.edu/~ghost/gv/gv_doc/gv.html'
 
 * MacGSView (Mac OS)
-  `http://www.cs.wisc.edu/~ghost/macos/index.htm'
+  `http://pages.cs.wisc.edu/~ghost/macos/index.htm'
 "
   :type '(string :tag "Ghostview Utility"))
 
@@ -1911,16 +1905,16 @@ See also `pr-path-alist'.
 Useful links:
 
 * Ghostscript, Ghostview and GSview
-  `http://www.cs.wisc.edu/~ghost/'
+  `https://www.cs.wisc.edu/~ghost/'
 
 * Introduction to Ghostscript
-  `http://www.cs.wisc.edu/~ghost/doc/intro.htm'
+  `https://www.cs.wisc.edu/~ghost/doc/intro.htm'
 
 * How to use Ghostscript
-  `http://www.cs.wisc.edu/~ghost/doc/cvs/Use.htm'
+  `https://www.cs.wisc.edu/~ghost/doc/cvs/Use.htm'
 
 * Printer compatibility
-  `http://www.cs.wisc.edu/~ghost/doc/printer.htm'
+  `https://www.cs.wisc.edu/~ghost/doc/printer.htm'
 "
   :type '(string :tag "Ghostscript Utility"))
 
@@ -1955,13 +1949,13 @@ To see ghostscript documentation for more information:
 Useful links:
 
 * Introduction to Ghostscript
-  `http://www.cs.wisc.edu/~ghost/doc/intro.htm'
+  `https://www.cs.wisc.edu/~ghost/doc/intro.htm'
 
 * How to use Ghostscript
-  `http://www.cs.wisc.edu/~ghost/doc/cvs/Use.htm'
+  `https://www.cs.wisc.edu/~ghost/doc/cvs/Use.htm'
 
 * Printer compatibility
-  `http://www.cs.wisc.edu/~ghost/doc/printer.htm'
+  `https://www.cs.wisc.edu/~ghost/doc/printer.htm'
 "
   :type '(repeat (string :tag "Ghostscript Switch")))
 
@@ -2408,11 +2402,10 @@ Examples:
 Useful links:
 
 * mpage download (GNU or Unix)
-  `http://www.mesa.nl/pub/mpage/'
+  `https://www.mesa.nl/pub/mpage/'
 
 * mpage documentation (GNU or Unix - or type `man mpage')
-  `http://www.cs.umd.edu/faq/guides/manual_unix/node48.html'
-  `http://www.rt.com/man/mpage.1.html'
+  `https://linux.die.net/man/1/mpage'
 
 * psnup (Windows, GNU or Unix)
   `http://www.knackered.org/angus/psutils/'
@@ -2422,14 +2415,13 @@ Useful links:
   `http://gnuwin32.sourceforge.net/packages/psutils.htm'
 
 * psnup documentation (GNU or Unix - or type `man psnup')
-  `http://linux.about.com/library/cmd/blcmdl1_psnup.htm'
-  `http://amath.colorado.edu/computing/software/man/psnup.html'
+  `https://linux.die.net/man/1/psnup'
 
 * GNU Enscript (Windows, GNU or Unix)
-  `http://people.ssh.com/mtr/genscript/'
+  `https://people.ssh.com/mtr/genscript/'
 
 * GNU Enscript documentation (Windows, GNU or Unix)
-  `http://people.ssh.com/mtr/genscript/enscript.man.html'
+  `https://people.ssh.com/mtr/genscript/enscript.man.html'
   (on GNU or Unix, type `man enscript')
 "
   :type '(repeat
diff --git a/lisp/progmodes/antlr-mode.el b/lisp/progmodes/antlr-mode.el
index e5b9ac0..2a4b348 100644
--- a/lisp/progmodes/antlr-mode.el
+++ b/lisp/progmodes/antlr-mode.el
@@ -1,4 +1,4 @@
-;;; antlr-mode.el --- major mode for ANTLR grammar files
+;;; antlr-mode.el --- major mode for ANTLR grammar files  -*- lexical-binding: 
t; -*-
 
 ;; Copyright (C) 1999-2021 Free Software Foundation, Inc.
 
@@ -33,7 +33,7 @@
 ;; the manual style, follow all commands mentioned in the documentation of
 ;; `antlr-mode'.  ANTLR is a LL(k)-based recognition tool which generates
 ;; lexers, parsers and tree transformers in Java, C++ or Sather and can be
-;; found at <http://www.antlr.org/>.
+;; found at <https://www.antlr.org/>.
 
 ;; Bug fixes, bug reports, improvements, and suggestions for the newest version
 ;; are strongly appreciated.
@@ -84,98 +84,17 @@
 
 (eval-when-compile (require 'cl-lib))
 
-(require 'easymenu)
+(when (< emacs-major-version 28)  ; preloaded in Emacs 28
+  (require 'easymenu))
 (require 'cc-mode)
 
-;; Just to get the rid of the byte compiler warning.  The code for
-;; this function and its friends are too complex for their own good.
-(declare-function cond-emacs-xemacs-macfn "antlr-mode" (args &optional msg))
-
-;; General Emacs/XEmacs-compatibility compile-time macros
-(eval-when-compile
-  (defmacro cond-emacs-xemacs (&rest args)
-    (cond-emacs-xemacs-macfn
-     args "`cond-emacs-xemacs' must return exactly one element"))
-  (defun cond-emacs-xemacs-macfn (args &optional msg)
-    (if (atom args) args
-      (and (eq (car args) :@) (null msg) ; (:@ ...spliced...)
-          (setq args (cdr args)
-                msg "(:@ ....) must return exactly one element"))
-      (let ((ignore (if (featurep 'xemacs) :EMACS :XEMACS))
-           (mode :BOTH) code)
-       (while (consp args)
-         (if (memq (car args) '(:EMACS :XEMACS :BOTH)) (setq mode (pop args)))
-         (if (atom args)
-             (or args (error "Used selector %s without elements" mode))
-           (or (eq ignore mode)
-               (push (cond-emacs-xemacs-macfn (car args)) code))
-           (pop args)))
-       (cond (msg (if (or args (cdr code)) (error msg) (car code)))
-             ((or (null args) (eq ignore mode)) (nreverse code))
-             (t (nconc (nreverse code) args))))))
-  ;; Emacs/XEmacs-compatibility `defun': remove interactive "_" for Emacs, use
-  ;; existing functions when they are `fboundp', provide shortcuts if they are
-  ;; known to be defined in a specific Emacs branch (for short .elc)
-  (defmacro defunx (name arglist &rest definition)
-    (let ((xemacsp (featurep 'xemacs)) reuses)
-      (while (memq (car definition)
-                  '(:try :emacs-and-try :xemacs-and-try))
-       (if (eq (pop definition) (if xemacsp :xemacs-and-try :emacs-and-try))
-           (setq reuses (car definition)
-                 definition nil)
-         (push (pop definition) reuses)))
-      (if (and reuses (symbolp reuses))
-         `(defalias ',name ',reuses)
-       (let* ((docstring (if (stringp (car definition)) (pop definition)))
-              (spec (and (not xemacsp)
-                         (eq (car-safe (car definition)) 'interactive)
-                         (null (cddar definition))
-                         (cadar definition))))
-         (if (and (stringp spec)
-                  (not (string-equal spec ""))
-                  (eq (aref spec 0) ?_))
-             (setq definition
-                   (cons (if (string-equal spec "_")
-                             '(interactive)
-                           `(interactive ,(substring spec 1)))
-                         (cdr definition))))
-         (if (null reuses)
-             `(defun ,name ,arglist ,docstring
-                ,@(cond-emacs-xemacs-macfn definition))
-           ;; no dynamic docstring in this case
-           `(eval-and-compile          ; no warnings in Emacs
-              (defalias ',name
-                (cond ,@(mapcar (lambda (func) `((fboundp ',func) ',func))
-                                (nreverse reuses))
-                      (t ,(if definition
-                              `(lambda ,arglist ,docstring
-                                 ,@(cond-emacs-xemacs-macfn definition))
-                            'ignore))))))))))
-  (defmacro ignore-errors-x (&rest body)
-    (let ((specials '((scan-sexps . 4) (scan-lists . 5)))
-         spec nils)
-      (if (and (featurep 'xemacs)
-              (null (cdr body)) (consp (car body))
-              (setq spec (assq (caar body) specials))
-              (>= (setq nils (- (cdr spec) (length (car body)))) 0))
-         `(,@(car body) ,@(make-list nils nil) t)
-       `(ignore-errors ,@body)))))
-
 ;; More compile-time-macros
 (eval-when-compile
   (defmacro save-buffer-state-x (&rest body) ; similar to EMACS/lazy-lock.el
-    (let ((modified (with-no-warnings (gensym 
"save-buffer-state-x-modified-"))))
-      `(let ((,modified (buffer-modified-p)))
-        (unwind-protect
-            (let ((buffer-undo-list t) (inhibit-read-only t)
-                  ,@(unless (featurep 'xemacs)
-                      '((inhibit-point-motion-hooks t) deactivate-mark))
-                  (inhibit-modification-hooks t)
-                  buffer-file-name buffer-file-truename)
-              ,@body)
-          (and (not ,modified) (buffer-modified-p)
-               (set-buffer-modified-p nil)))))))
-(put 'save-buffer-state-x 'lisp-indent-function 0)
+    (declare (debug t) (indent 0))
+    `(let ((inhibit-point-motion-hooks t))
+       (with-silent-modifications
+         ,@body))))
 
 (defvar outline-level)
 (defvar imenu-use-markers)
@@ -188,7 +107,7 @@
 ;; Additional to the `defalias' below, we must set `antlr-c-forward-sws' to
 ;; `c-forward-syntactic-ws' when `c-forward-sws' is not defined after requiring
 ;; cc-mode.
-(defalias 'antlr-c-forward-sws 'c-forward-sws)
+(defalias 'antlr-c-forward-sws #'c-forward-sws)
 
 
 ;;;;##########################################################################
@@ -231,7 +150,6 @@ value of `antlr-language' if the first group in the string 
matched by
 REGEXP in `antlr-language-limit-n-regexp' is one of the OPTION-VALUEs.
 An OPTION-VALUE of nil denotes the fallback element.  MODELINE-STRING is
 also displayed in the mode line next to \"Antlr\"."
-  :group 'antlr
   :type '(repeat (group :value (java-mode "")
                        (function :tag "Major mode")
                        (string :tag "Mode line string")
@@ -245,7 +163,6 @@ also displayed in the mode line next to \"Antlr\"."
 Looks like \(LIMIT . REGEXP).  Search for REGEXP from the beginning of
 the buffer to LIMIT and use the first group in the matched string to set
 the language according to `antlr-language-alist'."
-  :group 'antlr
   :type '(cons (choice :tag "Limit" (const :tag "No" nil) (integer :value 0))
               regexp))
 
@@ -259,7 +176,6 @@ the language according to `antlr-language-alist'."
 If nil, the actions with their surrounding braces are hidden.  If a
 number, do not hide the braces, only hide the contents if its length is
 greater than this number."
-  :group 'antlr
   :type '(choice (const :tag "Completely hidden" nil)
                 (integer :tag "Hidden if longer than" :value 3)))
 
@@ -268,7 +184,6 @@ greater than this number."
 If nil, no continuation line of a block comment is changed.  If t, they
 are changed according to `c-indentation-line'.  When not nil and not t,
 they are only changed by \\[antlr-indent-command]."
-  :group 'antlr
   :type '(radio (const :tag "No" nil)
                (const :tag "Always" t)
                (sexp :tag "With TAB" :format "%t" :value tab)))
@@ -282,7 +197,6 @@ The first element whose MAJOR-MODE is nil or equal to 
`major-mode' and
 whose REGEXP is nil or matches variable `buffer-file-name' is used to
 set `tab-width' and `indent-tabs-mode'.  This is useful to support both
 ANTLR's and Java's indentation styles.  Used by `antlr-set-tabs'."
-  :group 'antlr
   :type '(repeat (group :value (antlr-mode nil 8 nil)
                        (choice (const :tag "All" nil)
                                (function :tag "Major mode"))
@@ -294,14 +208,12 @@ ANTLR's and Java's indentation styles.  Used by 
`antlr-set-tabs'."
   "If non-nil, cc-mode indentation style used for `antlr-mode'.
 See `c-set-style' and for details, where the most interesting part in
 `c-style-alist' is the value of `c-basic-offset'."
-  :group 'antlr
   :type '(choice (const nil) regexp))
 
 (defcustom antlr-indent-item-regexp
   "[]}):;|&]" ; & is local ANTLR extension (SGML's and-connector)
   "Regexp matching lines which should be indented by one TAB less.
 See `antlr-indent-line' and command \\[antlr-indent-command]."
-  :group 'antlr
   :type 'regexp)
 
 (defcustom antlr-indent-at-bol-alist
@@ -316,7 +228,6 @@ If `antlr-language' equals to a MODE, the line starting at 
the first
 non-whitespace is matched by the corresponding REGEXP, and the line is
 part of a header action, indent the line at column 0 instead according
 to the normal rules of `antlr-indent-line'."
-  :group 'antlr
   :type '(repeat (cons (function :tag "Major mode") regexp)))
 
 ;; adopt indentation to cc-engine
@@ -337,7 +248,6 @@ to the normal rules of `antlr-indent-line'."
   "Non-nil, if the major mode menu should include option submenus.
 If nil, the menu just includes a command to insert options.  Otherwise,
 it includes four submenus to insert file/grammar/rule/subrule options."
-  :group 'antlr
   :type 'boolean)
 
 (defcustom antlr-tool-version 20701
@@ -349,7 +259,6 @@ version correct option values when using 
\\[antlr-insert-option].
 Don't use a number smaller than 20600 since the stored history of
 Antlr's options starts with v2.06.00, see `antlr-options-alists'.  You
 can make this variable buffer-local."
-  :group 'antlr
   :type 'integer)
 
 (defcustom antlr-options-auto-colon t
@@ -358,7 +267,6 @@ A `:' is only inserted if this value is non-nil, if a rule 
or subrule
 option is inserted with \\[antlr-insert-option], if there was no rule or
 subrule options section before, and if a `:' is not already present
 after the section, ignoring whitespace, comments and the init action."
-  :group 'antlr
   :type 'boolean)
 
 (defcustom antlr-options-style nil
@@ -369,7 +277,6 @@ identifier.
 
 The only style symbol used in the default value of `antlr-options-alist'
 is `language-as-string'.  See also `antlr-read-value'."
-  :group 'antlr
   :type '(repeat (symbol :tag "Style symbol")))
 
 (defcustom antlr-options-push-mark t
@@ -380,7 +287,6 @@ number, only set mark if point was outside the options area 
before and
 the number of lines between point and the insert position is greater
 than this value.  Otherwise, only set mark if point was outside the
 options area before."
-  :group 'antlr
   :type '(radio (const :tag "No" nil)
                (const :tag "Always" t)
                (integer :tag "Lines between" :value 10)
@@ -391,7 +297,6 @@ options area before."
 This string is only used if the option to insert did not exist before
 or if there was no `=' after it.  In other words, the spacing around an
 existing `=' won't be changed when changing an option value."
-  :group 'antlr
   :type 'string)
 
 
@@ -576,13 +481,11 @@ AS-STRING is non-nil and is either t or a symbol which is 
a member of
   "Command used in \\[antlr-run-tool] to run the Antlr tool.
 This variable should include all options passed to Antlr except the
 option \"-glib\" which is automatically suggested if necessary."
-  :group 'antlr
   :type 'string)
 
 (defcustom antlr-ask-about-save t
   "If not nil, \\[antlr-run-tool] asks which buffers to save.
 Otherwise, it saves all modified buffers before running without asking."
-  :group 'antlr
   :type 'boolean)
 
 (defcustom antlr-makefile-specification
@@ -604,7 +507,6 @@ Then, GEN-VAR is a string with the name of the variable 
which contains
 the file names of all makefile rules.  GEN-VAR-FORMAT is a format string
 producing the variable of each target with substitution COUNT/%d where
 COUNT starts with 1.  GEN-SEP is used to separate long variable values."
-  :group 'antlr
   :type '(list (string :tag "Rule separator")
               (choice
                (const :tag "Direct targets" nil)
@@ -683,7 +585,6 @@ DIRECTORY is the name of the current directory.")
   "Non-nil, if a \"Index\" menu should be added to the menubar.
 If it is a string, it is used instead \"Index\".  Requires package
 imenu."
-  :group 'antlr
   :type '(choice (const :tag "No menu" nil)
                 (const :tag "Index menu" t)
                 (string :tag "Other menu name")))
@@ -719,9 +620,7 @@ imenu."
 (easy-menu-define antlr-mode-menu antlr-mode-map
   "Major mode menu."
   `("Antlr"
-    ,@(if (cond-emacs-xemacs
-           :EMACS antlr-options-use-submenus
-           :XEMACS antlr-options-use-submenus)
+    ,@(if antlr-options-use-submenus
          `(("Insert File Option"
             :filter ,(lambda (x) (antlr-options-menu-filter 1 x)))
            ("Insert Grammar Option"
@@ -780,7 +679,6 @@ bound to `antlr-language'.  For example, with value
   ((java-mode . 2) (c++-mode . 0))
 Java actions are fontified with level 2 and C++ actions are not
 fontified at all."
-  :group 'antlr
   :type '(choice (const :tag "None" none)
                 (const :tag "Inherit" inherit)
                 (const :tag "Default" nil)
@@ -824,62 +722,49 @@ in the grammar's actions and semantic predicates, see
 
 (defface antlr-default '((t nil))
   "Face to prevent strings from language dependent highlighting.
-Do not change."
-  :group 'antlr)
+Do not change.")
 
 (defface antlr-keyword
-  (cond-emacs-xemacs
-   '((((class color) (background light))
-      (:foreground "black" :EMACS :weight bold :XEMACS :bold t))
-     (t :inherit font-lock-keyword-face)))
-  "ANTLR keywords."
-  :group 'antlr)
+  '((((class color) (background light))
+     (:foreground "black" :weight bold))
+    (t :inherit font-lock-keyword-face))
+  "ANTLR keywords.")
 
 (defface antlr-syntax
-  (cond-emacs-xemacs
-   '((((class color) (background light))
-      (:foreground "black" :EMACS :weight bold :XEMACS :bold t))
-     (t :inherit font-lock-constant-face)))
-  "ANTLR syntax symbols like :, |, (, ), ...."
-  :group 'antlr)
+  '((((class color) (background light))
+     (:foreground "black" :weight bold))
+    (t :inherit font-lock-constant-face))
+  "ANTLR syntax symbols like :, |, (, ), ....")
 
 (defface antlr-ruledef
-  (cond-emacs-xemacs
-   '((((class color) (background light))
-      (:foreground "blue" :EMACS :weight bold :XEMACS :bold t))
-     (t :inherit font-lock-function-name-face)))
-  "ANTLR rule references (definition)."
-  :group 'antlr)
+  '((((class color) (background light))
+     (:foreground "blue" :weight bold))
+    (t :inherit font-lock-function-name-face))
+  "ANTLR rule references (definition).")
 
 (defface antlr-tokendef
-  (cond-emacs-xemacs
-   '((((class color) (background light))
-      (:foreground "blue" :EMACS :weight bold :XEMACS :bold t))
-     (t :inherit font-lock-function-name-face)))
-  "ANTLR token references (definition)."
-  :group 'antlr)
+  '((((class color) (background light))
+     (:foreground "blue" :weight bold))
+    (t :inherit font-lock-function-name-face))
+  "ANTLR token references (definition).")
 
 (defface antlr-ruleref
   '((((class color) (background light)) (:foreground "blue4"))
     (t :inherit font-lock-type-face))
-  "ANTLR rule references (usage)."
-  :group 'antlr)
+  "ANTLR rule references (usage).")
 
 (defface antlr-tokenref
   '((((class color) (background light)) (:foreground "orange4"))
     (t :inherit font-lock-type-face))
-  "ANTLR token references (usage)."
-  :group 'antlr)
+  "ANTLR token references (usage).")
 
 (defface antlr-literal
-  (cond-emacs-xemacs
-   '((((class color) (background light))
-      (:foreground "brown4" :EMACS :weight bold :XEMACS :bold t))
-     (t :inherit font-lock-string-face)))
+  '((((class color) (background light))
+     (:foreground "brown4" :weight bold))
+    (t :inherit font-lock-string-face))
   "ANTLR special literal tokens.
 It is used to highlight strings matched by the first regexp group of
-`antlr-font-lock-literal-regexp'."
-  :group 'antlr)
+`antlr-font-lock-literal-regexp'.")
 
 (defcustom antlr-font-lock-literal-regexp "\"\\(\\sw\\(\\sw\\|-\\)*\\)\""
   "Regexp matching literals with special syntax highlighting, or nil.
@@ -887,7 +772,6 @@ If nil, there is no special syntax highlighting for some 
literals.
 Otherwise, it should be a regular expression which must contain a regexp
 group.  The string matched by the first group is highlighted with
 `antlr-font-lock-literal-face'."
-  :group 'antlr
   :type '(choice (const :tag "None" nil) regexp))
 
 (defvar antlr-class-header-regexp
@@ -895,50 +779,48 @@ group.  The string matched by the first group is 
highlighted with
   "Regexp matching class headers.")
 
 (defvar antlr-font-lock-additional-keywords
-  (cond-emacs-xemacs
-   `((antlr-invalidate-context-cache)
-     ("\\$setType[ \t]*(\\([A-Za-z\300-\326\330-\337]\\sw*\\))"
-      (1 'antlr-tokendef))
-     ("\\$\\sw+" (0 'antlr-keyword))
-     ;; the tokens are already fontified as string/docstrings:
-     (,(lambda (limit)
-        (if antlr-font-lock-literal-regexp
-            (antlr-re-search-forward antlr-font-lock-literal-regexp limit)))
-      (1 'antlr-literal t)
-      :XEMACS (0 nil))                 ; XEmacs bug workaround
-     (,(lambda (limit)
-        (antlr-re-search-forward antlr-class-header-regexp limit))
-      (1 'antlr-keyword)
-      (2 'antlr-ruledef)
-      (3 'antlr-keyword)
-      (4 (if (member (match-string 4) '("Lexer" "Parser" "TreeParser"))
-             'antlr-keyword
-           'font-lock-type-face)))
-     (,(lambda (limit)
-        (antlr-re-search-forward
-         "\\<\\(header\\|options\\|tokens\\|exception\\|catch\\|returns\\)\\>"
-         limit))
+  `((antlr-invalidate-context-cache)
+    ("\\$setType[ \t]*(\\([A-Za-z\300-\326\330-\337]\\sw*\\))"
+     (1 'antlr-tokendef))
+    ("\\$\\sw+" (0 'antlr-keyword))
+    ;; the tokens are already fontified as string/docstrings:
+    (,(lambda (limit)
+       (if antlr-font-lock-literal-regexp
+           (antlr-re-search-forward antlr-font-lock-literal-regexp limit)))
+     (1 'antlr-literal t))
+    (,(lambda (limit)
+       (antlr-re-search-forward antlr-class-header-regexp limit))
+     (1 'antlr-keyword)
+     (2 'antlr-ruledef)
+     (3 'antlr-keyword)
+     (4 (if (member (match-string 4) '("Lexer" "Parser" "TreeParser"))
+            'antlr-keyword
+          'font-lock-type-face)))
+    (,(lambda (limit)
+       (antlr-re-search-forward
+        "\\<\\(header\\|options\\|tokens\\|exception\\|catch\\|returns\\)\\>"
+        limit))
      (1 'antlr-keyword))
-     (,(lambda (limit)
-        (antlr-re-search-forward
-         "^\\(private\\|public\\|protected\\)\\>[ \t]*\\(\\(\\sw+[ 
\t]*\\(:\\)?\\)\\)?"
-         limit))
-     (1 'font-lock-type-face)          ; not XEmacs's java level-3 fruit salad
+    (,(lambda (limit)
+       (antlr-re-search-forward
+        "^\\(private\\|public\\|protected\\)\\>[ \t]*\\(\\(\\sw+[ 
\t]*\\(:\\)?\\)\\)?"
+        limit))
+     (1 'font-lock-type-face)  ; not XEmacs's java level-3 fruit salad
      (3 (if (antlr-upcase-p (char-after (match-beginning 3)))
             'antlr-tokendef
           'antlr-ruledef)
         nil t)
      (4 'antlr-syntax nil t))
-     (,(lambda (limit)
-        (antlr-re-search-forward "^\\(\\sw+\\)[ \t]*\\(:\\)?" limit))
+    (,(lambda (limit)
+       (antlr-re-search-forward "^\\(\\sw+\\)[ \t]*\\(:\\)?" limit))
      (1 (if (antlr-upcase-p (char-after (match-beginning 0)))
             'antlr-tokendef
           'antlr-ruledef)
         nil t)
      (2 'antlr-syntax nil t))
-     (,(lambda (limit)
-        ;; v:ruleref and v:"literal" is allowed...
-        (antlr-re-search-forward "\\(\\sw+\\)[ \t]*\\([=:]\\)?" limit))
+    (,(lambda (limit)
+       ;; v:ruleref and v:"literal" is allowed...
+       (antlr-re-search-forward "\\(\\sw+\\)[ \t]*\\([=:]\\)?" limit))
      (1 (if (match-beginning 2)
            (if (eq (char-after (match-beginning 2)) ?=)
                 'antlr-default
@@ -947,9 +829,9 @@ group.  The string matched by the first group is 
highlighted with
               'antlr-tokenref
             'antlr-ruleref)))
      (2 'antlr-default nil t))
-     (,(lambda (limit)
-        (antlr-re-search-forward "[|&:;(~]\\|)\\([*+?]\\|=>\\)?" limit))
-     (0 'antlr-syntax))))
+    (,(lambda (limit)
+       (antlr-re-search-forward "[|&:;(~]\\|)\\([*+?]\\|=>\\)?" limit))
+     (0 'antlr-syntax)))
   "Font-lock keywords for ANTLR's normal grammar code.
 See `antlr-font-lock-keywords-alist' for the keywords of actions.")
 
@@ -1015,35 +897,6 @@ Used for `antlr-slow-syntactic-context'.")
 ;;;  Syntax functions -- Emacs vs XEmacs dependent, part 1
 ;;;===========================================================================
 
-;; From help.el (XEmacs-21.1), without `copy-syntax-table'
-(defmacro antlr-with-syntax-table (syntab &rest body)
-  "Evaluate BODY with the syntax table SYNTAB."
-  `(let ((stab (syntax-table)))
-     (unwind-protect
-        (progn (set-syntax-table ,syntab) ,@body)
-       (set-syntax-table stab))))
-(put 'antlr-with-syntax-table 'lisp-indent-function 1)
-(put 'antlr-with-syntax-table 'edebug-form-spec '(form body))
-
-(defunx antlr-default-directory ()
-  :xemacs-and-try default-directory
-  "Return `default-directory'."
-  default-directory)
-
-;; Check Emacs-21.1 simple.el, `shell-command'.
-(defunx antlr-read-shell-command (prompt &optional initial-input history)
-  :xemacs-and-try read-shell-command
-  "Read a string from the minibuffer, using `shell-command-history'."
-  (read-from-minibuffer prompt initial-input nil nil
-                       (or history 'shell-command-history)))
-
-(defunx antlr-with-displaying-help-buffer (thunk &optional _name)
-  :xemacs-and-try with-displaying-help-buffer
-  "Make a help buffer and call `thunk' there."
-  (with-output-to-temp-buffer "*Help*"
-    (save-excursion (funcall thunk))))
-
-
 ;;;===========================================================================
 ;;;  Context cache
 ;;;===========================================================================
@@ -1056,26 +909,18 @@ Used for `antlr-slow-syntactic-context'.")
 ;;;(defvar antlr-statistics-cache 0)
 ;;;(defvar antlr-statistics-inval 0)
 
-(defunx antlr-invalidate-context-cache (&rest _dummies)
+(defun antlr-invalidate-context-cache (&rest _dummies)
 ;; checkdoc-params: (dummies)
   "Invalidate context cache for syntactical context information."
-  :XEMACS                              ; XEmacs bug workaround
-  (with-current-buffer (get-buffer-create " ANTLR XEmacs bug workaround")
-    (buffer-syntactic-context-depth)
-    nil)
-  :EMACS
 ;;;  (cl-incf antlr-statistics-inval)
   (setq antlr-slow-context-cache nil))
 
-(defunx antlr-syntactic-context ()
+(defun antlr-syntactic-context ()
   "Return some syntactic context information.
 Return `string' if point is within a string, `block-comment' or
 `comment' is point is within a comment or the depth within all
 parenthesis-syntax delimiters at point otherwise.
 WARNING: this may alter `match-data'."
-  :XEMACS
-  (or (buffer-syntactic-context) (buffer-syntactic-context-depth))
-  :EMACS
   (let ((orig (point)) diff state
        ;; Arg, Emacs's (buffer-modified-tick) changes with font-lock.  Use
        ;; hack that `loudly' is bound during font-locking => cache use will
@@ -1094,9 +939,9 @@ WARNING: this may alter `match-data'."
       (if (>= orig antlr-slow-cache-diff-threshold)
          (beginning-of-defun)
        (goto-char (point-min)))
-;;;      (cond ((and diff (< diff 0)) (cl-incf antlr-statistics-full-neg))
-;;;        ((and diff (>= diff 3000)) (cl-incf antlr-statistics-full-diff))
-;;;        (t (cl-incf antlr-statistics-full-other)))
+      ;; (cond ((and diff (< diff 0)) (cl-incf antlr-statistics-full-neg))
+      ;;       ((and diff (>= diff 3000)) (cl-incf antlr-statistics-full-diff))
+      ;;       (t (cl-incf antlr-statistics-full-other)))
       (setq state (parse-partial-sexp (point) orig)))
     (goto-char orig)
     (if antlr-slow-context-cache
@@ -1108,52 +953,52 @@ WARNING: this may alter `match-data'."
          ((nth 4 state) 'comment)      ; block-comment? -- we don't care
          (t (car state)))))
 
-;;;  (cl-incf (aref antlr-statistics 2))
-;;;  (unless (and (eq (current-buffer)
-;;;               (caar antlr-slow-context-cache))
-;;;           (eq (buffer-modified-tick)
-;;;               (cdar antlr-slow-context-cache)))
-;;;    (cl-incf (aref antlr-statistics 1))
-;;;    (setq antlr-slow-context-cache nil))
-;;;  (let* ((orig (point))
-;;;     (base (cadr antlr-slow-context-cache))
-;;;     (curr (cddr antlr-slow-context-cache))
-;;;     (state (cond ((eq orig (car curr)) (cdr curr))
-;;;                  ((eq orig (car base)) (cdr base))))
-;;;     diff diff2)
-;;;    (unless state
-;;;      (cl-incf (aref antlr-statistics 3))
-;;;      (when curr
-;;;    (if (< (setq diff  (abs (- orig (car curr))))
-;;;           (setq diff2 (abs (- orig (car base)))))
-;;;        (setq state curr)
-;;;      (setq state base
-;;;            diff  diff2))
-;;;    (if (or (>= (1+ diff) (point)) (>= diff 3000))
-;;;        (setq state nil)))          ; start from bod/bob
-;;;      (if state
-;;;      (setq state
-;;;            (parse-partial-sexp (car state) orig nil nil (cdr state)))
-;;;    (if (>= orig 3000) (beginning-of-defun) (goto-char (point-min)))
-;;;    (cl-incf (aref antlr-statistics 4))
-;;;    (setq cw (list orig (point) base curr))
-;;;    (setq state (parse-partial-sexp (point) orig)))
-;;;      (goto-char orig)
-;;;      (if antlr-slow-context-cache
-;;;      (setcdr (cdr antlr-slow-context-cache) (cons orig state))
-;;;    (setq antlr-slow-context-cache
-;;;          (cons (cons (current-buffer) (buffer-modified-tick))
-;;;                (cons (cons orig state) (cons orig state))))))
-;;;    (cond ((nth 3 state) 'string)
-;;;      ((nth 4 state) 'comment)      ; block-comment? -- we don't care
-;;;      (t (car state)))))
-
-;;;    (beginning-of-defun)
-;;;    (let ((state (parse-partial-sexp (point) orig)))
-;;;      (goto-char orig)
-;;;      (cond ((nth 3 state) 'string)
-;;;        ((nth 4 state) 'comment)    ; block-comment? -- we don't care
-;;;        (t (car state))))))
+;;  (cl-incf (aref antlr-statistics 2))
+;;  (unless (and (eq (current-buffer)
+;;                (caar antlr-slow-context-cache))
+;;            (eq (buffer-modified-tick)
+;;                (cdar antlr-slow-context-cache)))
+;;    (cl-incf (aref antlr-statistics 1))
+;;    (setq antlr-slow-context-cache nil))
+;;  (let* ((orig (point))
+;;      (base (cadr antlr-slow-context-cache))
+;;      (curr (cddr antlr-slow-context-cache))
+;;      (state (cond ((eq orig (car curr)) (cdr curr))
+;;                   ((eq orig (car base)) (cdr base))))
+;;      diff diff2)
+;;    (unless state
+;;      (cl-incf (aref antlr-statistics 3))
+;;      (when curr
+;;     (if (< (setq diff  (abs (- orig (car curr))))
+;;            (setq diff2 (abs (- orig (car base)))))
+;;         (setq state curr)
+;;       (setq state base
+;;             diff  diff2))
+;;     (if (or (>= (1+ diff) (point)) (>= diff 3000))
+;;         (setq state nil)))          ; start from bod/bob
+;;      (if state
+;;       (setq state
+;;             (parse-partial-sexp (car state) orig nil nil (cdr state)))
+;;     (if (>= orig 3000) (beginning-of-defun) (goto-char (point-min)))
+;;     (cl-incf (aref antlr-statistics 4))
+;;     (setq cw (list orig (point) base curr))
+;;     (setq state (parse-partial-sexp (point) orig)))
+;;      (goto-char orig)
+;;      (if antlr-slow-context-cache
+;;       (setcdr (cdr antlr-slow-context-cache) (cons orig state))
+;;     (setq antlr-slow-context-cache
+;;           (cons (cons (current-buffer) (buffer-modified-tick))
+;;                 (cons (cons orig state) (cons orig state))))))
+;;    (cond ((nth 3 state) 'string)
+;;       ((nth 4 state) 'comment)      ; block-comment? -- we don't care
+;;       (t (car state)))))
+
+;;    (beginning-of-defun)
+;;    (let ((state (parse-partial-sexp (point) orig)))
+;;      (goto-char orig)
+;;      (cond ((nth 3 state) 'string)
+;;         ((nth 4 state) 'comment)    ; block-comment? -- we don't care
+;;         (t (car state))))))
 
 
 ;;;===========================================================================
@@ -1207,7 +1052,7 @@ strings and actions/semantic predicates."
 (defsubst antlr-skip-sexps (count)
   "Skip the next COUNT balanced expressions and the comments after it.
 Return position before the comments after the last expression."
-  (goto-char (or (ignore-errors-x (scan-sexps (point) count)) (point-max)))
+  (goto-char (or (ignore-errors (scan-sexps (point) count)) (point-max)))
   (prog1 (point)
     (antlr-c-forward-sws)))
 
@@ -1229,7 +1074,8 @@ See `antlr-font-lock-additional-keywords', 
`antlr-language' and
                                    antlr-font-lock-keywords-alist))
                         (if (eq antlr-font-lock-maximum-decoration 'inherit)
                             font-lock-maximum-decoration
-                          antlr-font-lock-maximum-decoration)))))))
+                          antlr-font-lock-maximum-decoration)))
+                 t))))
 
 
 ;;;===========================================================================
@@ -1246,10 +1092,9 @@ IF TOKENREFS-ONLY is non-nil, just return alist with 
tokenref names."
   (let ((items nil)
        (classes nil)
        (continue t))
-    ;; Using `imenu-progress-message' would require imenu for compilation, but
-    ;; nobody is missing these messages.  The generic imenu function searches
-    ;; backward, which is slower and more likely not to work during editing.
-    (antlr-with-syntax-table antlr-action-syntax-table
+    ;; The generic imenu function searches backward, which is slower
+    ;; and more likely not to work during editing.
+    (with-syntax-table antlr-action-syntax-table
       (antlr-invalidate-context-cache)
       (goto-char (point-min))
       (antlr-skip-file-prelude t)
@@ -1393,37 +1238,37 @@ Move to the beginning of the current rule if point is 
inside a rule."
 A grammar class header and the file prelude are also considered as a
 rule."
   (save-excursion
-    (antlr-with-syntax-table antlr-action-syntax-table
+    (with-syntax-table antlr-action-syntax-table
       (not (antlr-outside-rule-p)))))
 
-(defunx antlr-end-of-rule (&optional arg)
+(defun antlr-end-of-rule (&optional arg)
   "Move forward to next end of rule.  Do it ARG [default: 1] many times.
 A grammar class header and the file prelude are also considered as a
 rule.  Negative argument ARG means move back to ARGth preceding end of
 rule.  If ARG is zero, run `antlr-end-of-body'."
-  (interactive "_p")
+  (interactive "^p")
   (if (zerop arg)
       (antlr-end-of-body)
-    (antlr-with-syntax-table antlr-action-syntax-table
+    (with-syntax-table antlr-action-syntax-table
       (antlr-next-rule arg nil))))
 
-(defunx antlr-beginning-of-rule (&optional arg)
+(defun antlr-beginning-of-rule (&optional arg)
   "Move backward to preceding beginning of rule.  Do it ARG many times.
 A grammar class header and the file prelude are also considered as a
 rule.  Negative argument ARG means move forward to ARGth next beginning
 of rule.  If ARG is zero, run `antlr-beginning-of-body'."
-  (interactive "_p")
+  (interactive "^p")
   (if (zerop arg)
       (antlr-beginning-of-body)
-    (antlr-with-syntax-table antlr-action-syntax-table
+    (with-syntax-table antlr-action-syntax-table
       (antlr-next-rule (- arg) t))))
 
-(defunx antlr-end-of-body (&optional msg)
+(defun antlr-end-of-body (&optional msg)
   "Move to position after the `;' of the current rule.
 A grammar class header is also considered as a rule.  With optional
 prefix arg MSG, move to `:'."
-  (interactive "_")
-  (antlr-with-syntax-table antlr-action-syntax-table
+  (interactive "^")
+  (with-syntax-table antlr-action-syntax-table
     (let ((orig (point)))
       (if (antlr-outside-rule-p)
          (error "Outside an ANTLR rule"))
@@ -1441,9 +1286,9 @@ prefix arg MSG, move to `:'."
            (error msg))
          (antlr-c-forward-sws))))))
 
-(defunx antlr-beginning-of-body ()
+(defun antlr-beginning-of-body ()
   "Move to the first element after the `:' of the current rule."
-  (interactive "_")
+  (interactive "^")
   (antlr-end-of-body "Class headers and the file prelude are without `:'"))
 
 
@@ -1459,7 +1304,7 @@ If non-nil, TRANSFORM is used on literals instead of 
`downcase-region'."
   (let ((literals 0))
     (save-excursion
       (goto-char (point-min))
-      (antlr-with-syntax-table antlr-action-syntax-table
+      (with-syntax-table antlr-action-syntax-table
        (antlr-invalidate-context-cache)
        (while (antlr-re-search-forward "\"\\(\\sw\\(\\sw\\|-\\)*\\)\"" nil)
          (funcall transform (match-beginning 0) (match-end 0))
@@ -1488,10 +1333,10 @@ Display a message unless optional argument SILENT is 
non-nil."
          (antlr-hide-actions 0 t)
          (save-excursion
            (goto-char (point-min))
-           (antlr-with-syntax-table antlr-action-syntax-table
+           (with-syntax-table antlr-action-syntax-table
              (antlr-invalidate-context-cache)
              (while (antlr-re-search-forward regexp nil)
-               (let ((beg (ignore-errors-x (scan-sexps (point) -1))))
+               (let ((beg (ignore-errors (scan-sexps (point) -1))))
                  (when beg
                    (if diff            ; braces are visible
                        (if (> (point) (+ beg diff))
@@ -1684,7 +1529,7 @@ like \(AREA . PLACE), see `antlr-option-location'."
              (cond ((null pos) 'error)
                    ((looking-at "options[ \t\n]*{")
                     (goto-char (match-end 0))
-                    (setq pos (ignore-errors-x (scan-lists (point) 1 1)))
+                    (setq pos (ignore-errors (scan-lists (point) 1 1)))
                     (antlr-option-location orig min0 max0
                                            (point)
                                            (if pos (1- pos) (point-max))
@@ -1709,7 +1554,7 @@ is undefined."
   (widen)
   (if (eq requested 1)
       1
-    (antlr-with-syntax-table antlr-action-syntax-table
+    (with-syntax-table antlr-action-syntax-table
       (antlr-invalidate-context-cache)
       (let* ((orig (point))
             (outsidep (antlr-outside-rule-p))
@@ -2087,7 +1932,7 @@ its export vocabulary is used as an import vocabulary."
   (unless buffer-file-name
     (error "Grammar buffer does not visit a file"))
   (let (classes export-vocabs import-vocabs superclasses default-vocab)
-    (antlr-with-syntax-table antlr-action-syntax-table
+    (with-syntax-table antlr-action-syntax-table
       (goto-char (point-min))
       (while (antlr-re-search-forward antlr-class-header-regexp nil)
        ;; parse class definition --------------------------------------------
@@ -2240,9 +2085,9 @@ Use prefix argument ARG to return \(COMMAND FILE SAVED)."
       (setq glibs (car (antlr-superclasses-glibs
                        supers
                        (car (antlr-directory-dependencies
-                             (antlr-default-directory)))))))
-    (list (antlr-read-shell-command "Run Antlr on current file with: "
-                                   (concat antlr-tool-command glibs " "))
+                             default-directory))))))
+    (list (read-shell-command "Run Antlr on current file with: "
+                             (concat antlr-tool-command glibs " "))
          buffer-file-name
          supers)))
 
@@ -2264,7 +2109,7 @@ Also insert strings PRE and POST before and after the 
variable."
   "Insert Makefile rules in the current buffer at point.
 IN-MAKEFILE is non-nil, if the current buffer is the Makefile.  See
 command `antlr-show-makefile-rules' for detail."
-  (let* ((dirname (antlr-default-directory))
+  (let* ((dirname default-directory)
         (deps0 (antlr-directory-dependencies dirname))
         (classes (car deps0))          ; CLASS -> (FILE . EVOCAB) ...
         (deps (cdr deps0))             ; FILE -> (c . s) (ev . iv) . LANGUAGE
@@ -2343,7 +2188,9 @@ commentary with value `antlr-help-unknown-file-text' is 
added.  The
 *Help* buffer always starts with the text in `antlr-help-rules-intro'."
   (interactive)
   (if (null (derived-mode-p 'makefile-mode))
-      (antlr-with-displaying-help-buffer 'antlr-insert-makefile-rules)
+      (with-output-to-temp-buffer "*Help*"
+        (save-excursion
+          (antlr-insert-makefile-rules)))
     (push-mark)
     (antlr-insert-makefile-rules t)))
 
@@ -2386,7 +2233,7 @@ to a lesser extent, `antlr-tab-offset-alist'."
       (skip-chars-forward " \t")
       (setq boi (point))
       ;; check syntax at beginning of indentation ----------------------------
-      (antlr-with-syntax-table antlr-action-syntax-table
+      (with-syntax-table antlr-action-syntax-table
        (antlr-invalidate-context-cache)
        (setq syntax (antlr-syntactic-context))
        (cond ((symbolp syntax)
@@ -2482,7 +2329,7 @@ ANTLR's syntax and influences the auto indentation, see
   (interactive "*P")
   (if (or arg
          (save-excursion (skip-chars-backward " \t") (not (bolp)))
-         (antlr-with-syntax-table antlr-action-syntax-table
+         (with-syntax-table antlr-action-syntax-table
            (antlr-invalidate-context-cache)
            (let ((context (antlr-syntactic-context)))
              (not (and (numberp context)
@@ -2525,7 +2372,7 @@ ANTLR's syntax and influences the auto indentation, see
     (while settings
       (when (boundp (car settings))
        (ignore-errors
-         (set (car settings) (eval (cadr settings)))))
+         (set (car settings) (eval (cadr settings) t))))
       (setq settings (cddr settings)))))
 
 (defun antlr-language-option (search)
@@ -2572,20 +2419,11 @@ the default language."
                    (cadr (assq antlr-language antlr-language-alist)))))
   ;; indentation, for the C engine -------------------------------------------
   (setq c-buffer-is-cc-mode antlr-language)
-  (cond ((fboundp 'c-init-language-vars-for) ; cc-mode 5.30.5+
-        (c-init-language-vars-for antlr-language))
-       ((fboundp 'c-init-c-language-vars) ; cc-mode 5.30 to 5.30.4
-        (c-init-c-language-vars)       ; not perfect, but OK
-        (setq c-recognize-knr-p nil))
-       ((fboundp 'c-init-language-vars) ; cc-mode 5.29
-        (let ((init-fn 'c-init-language-vars))
-          (funcall init-fn)))          ; is a function in v5.29
-       (t                              ; cc-mode upto 5.28
-        (antlr-c-init-language-vars))) ; do it myself
+  (c-init-language-vars-for antlr-language)
   (c-basic-common-init antlr-language (or antlr-indent-style "gnu"))
   (set (make-local-variable 'outline-regexp) "[^#\n\^M]")
-  (set (make-local-variable 'outline-level) 'c-outline-level) ;TODO: define own
-  (set (make-local-variable 'indent-line-function) 'antlr-indent-line)
+  (set (make-local-variable 'outline-level) #'c-outline-level) ;TODO: define 
own
+  (set (make-local-variable 'indent-line-function) #'antlr-indent-line)
   (set (make-local-variable 'indent-region-function) nil)      ; too lazy
   (setq comment-start "// "
        comment-end ""
@@ -2595,7 +2433,7 @@ the default language."
   (when (featurep 'xemacs)
     (easy-menu-add antlr-mode-menu))
   (set (make-local-variable 'imenu-create-index-function)
-       'antlr-imenu-create-index-function)
+       #'antlr-imenu-create-index-function)
   (set (make-local-variable 'imenu-generic-expression) t) ; fool stupid test
   (and antlr-imenu-name                        ; there should be a global 
variable...
        (fboundp 'imenu-add-to-menubar)
@@ -2625,6 +2463,6 @@ Used in `antlr-mode'.  Also a useful function in 
`java-mode-hook'."
 
 (provide 'antlr-mode)
 
-;;; Local IspellPersDict: .ispell_antlr
+;; Local IspellPersDict: .ispell_antlr
 
 ;;; antlr-mode.el ends here
diff --git a/lisp/progmodes/asm-mode.el b/lisp/progmodes/asm-mode.el
index 99b2ec6..2f7d7bf 100644
--- a/lisp/progmodes/asm-mode.el
+++ b/lisp/progmodes/asm-mode.el
@@ -73,19 +73,19 @@
     ;; Note that the comment character isn't set up until asm-mode is called.
     (define-key map ":"                'asm-colon)
     (define-key map "\C-c;"    'comment-region)
-    (define-key map [menu-bar asm-mode] (cons "Asm" (make-sparse-keymap)))
-    (define-key map [menu-bar asm-mode comment-region]
-      '(menu-item "Comment Region" comment-region
-                 :help "Comment or uncomment each line in the region"))
-    (define-key map [menu-bar asm-mode newline-and-indent]
-      '(menu-item "Insert Newline and Indent" newline-and-indent
-                 :help "Insert a newline, then indent according to major 
mode"))
-    (define-key map [menu-bar asm-mode asm-colon]
-      '(menu-item "Insert Colon" asm-colon
-                 :help "Insert a colon; if it follows a label, delete the 
label's indentation"))
     map)
   "Keymap for Asm mode.")
 
+(easy-menu-define asm-mode-menu asm-mode-map
+  "Menu for Asm mode."
+  '("Asm"
+    ["Insert Colon" asm-colon
+     :help "Insert a colon; if it follows a label, delete the label's 
indentation"]
+    ["Insert Newline and Indent" newline-and-indent
+     :help "Insert a newline, then indent according to major mode"]
+    ["Comment Region" comment-region
+     :help "Comment or uncomment each line in the region"]))
+
 (defconst asm-font-lock-keywords
   (append
    '(("^\\(\\(\\sw\\|\\s_\\)+\\)\\>:?[ \t]*\\(\\sw+\\(\\.\\sw+\\)*\\)?"
diff --git a/lisp/progmodes/bug-reference.el b/lisp/progmodes/bug-reference.el
index a759394..4d4becf 100644
--- a/lisp/progmodes/bug-reference.el
+++ b/lisp/progmodes/bug-reference.el
@@ -73,8 +73,7 @@ so that it is considered safe, see `enable-local-variables'.")
   "Regular expression matching bug references.
 The second subexpression should match the bug reference (usually a number)."
   :type 'regexp
-  :version "24.3"                      ; previously defconst
-  :group 'bug-reference)
+  :version "24.3")                     ; previously defconst
 
 ;;;###autoload
 (put 'bug-reference-bug-regexp 'safe-local-variable 'stringp)
diff --git a/lisp/progmodes/cc-align.el b/lisp/progmodes/cc-align.el
index d14ef17..51d51de 100644
--- a/lisp/progmodes/cc-align.el
+++ b/lisp/progmodes/cc-align.el
@@ -274,8 +274,10 @@ statement-block-intro, statement-case-intro, 
arglist-intro."
   (save-excursion
     (beginning-of-line)
     (backward-up-list 1)
+    (forward-char)
     (skip-chars-forward " \t" (c-point 'eol))
-    (vector (1+ (current-column)))))
+    (if (eolp) (skip-chars-backward " \t"))
+    (vector (current-column))))
 
 (defun c-lineup-arglist-close-under-paren (langelem)
   "Line up a line under the enclosing open paren.
@@ -1145,7 +1147,8 @@ Works with brace-list-intro."
                                                             ; the line.
           (save-excursion              ; "{" earlier on the line
             (goto-char (c-langelem-pos
-                        (assq 'brace-list-intro c-syntactic-context)))
+                        (assq 'brace-list-entry
+                              c-syntactic-context)))
             (and
              (eq (c-backward-token-2
                   1 nil
diff --git a/lisp/progmodes/cc-cmds.el b/lisp/progmodes/cc-cmds.el
index 33a0360..1754436 100644
--- a/lisp/progmodes/cc-cmds.el
+++ b/lisp/progmodes/cc-cmds.el
@@ -1639,7 +1639,7 @@ No indentation or other \"electric\" behavior is 
performed."
   ;;
   ;; This function might do hidden buffer changes.
   (save-excursion
-    (let* (kluge-start
+    (let* (knr-start knr-res
           decl-result brace-decl-p
           (start (point))
           (paren-state (c-parse-state))
@@ -1670,63 +1670,39 @@ No indentation or other \"electric\" behavior is 
performed."
                    (not (looking-at c-defun-type-name-decl-key))))))
        'at-function-end)
        (t
-       ;; Find the start of the current declaration.  NOTE: If we're in the
-       ;; variables after a "struct/eval" type block, we don't get to the
-       ;; real declaration here - we detect and correct for this later.
-
-       ;;If we're in the parameters' parens, move back out of them.
-       (if least-enclosing (goto-char least-enclosing))
-       ;; Kluge so that c-beginning-of-decl-1 won't go back if we're already
-       ;; at a declaration.
-       (if (or (and (eolp) (not (eobp))) ; EOL is matched by "\\s>"
-               (not (looking-at
-"\\([;#]\\|\\'\\|\\s(\\|\\s)\\|\\s\"\\|\\s\\\\|\\s$\\|\\s<\\|\\s>\\|\\s!\\)")))
-           (forward-char))
-       (setq kluge-start (point))
-       ;; First approximation as to whether the current "header" we're in is
-       ;; one followed by braces.
-       (setq brace-decl-p
-             (save-excursion
-               (and (c-syntactic-re-search-forward "[;{]" nil t t)
-                    (or (eq (char-before) ?\{)
-                        (and c-recognize-knr-p
-                             ;; Might have stopped on the
-                             ;; ';' in a K&R argdecl.  In
-                             ;; that case the declaration
-                             ;; should contain a block.
-                             (c-in-knr-argdecl))))))
-       (setq decl-result
-             (car (c-beginning-of-decl-1
-                   ;; NOTE: If we're in a K&R region, this might be the start
-                   ;; of a parameter declaration, not the actual function.
-                   ;; It might also leave us at a label or "label" like
-                   ;; "private:".
-                   (and least-enclosing ; LIMIT for c-b-of-decl-1
-                        (c-safe-position least-enclosing paren-state)))))
-
-       ;; Has the declaration we've gone back to got braces?
-       (if (or (eq decl-result 'label)
-               (looking-at c-protection-key))
-           (setq brace-decl-p nil))
-
-       (cond
-        ((or (eq decl-result 'label)   ; e.g. "private:" or invalid syntax.
-             (= (point) kluge-start))  ; might be BOB or unbalanced parens.
-         'outwith-function)
-        ((eq decl-result 'same)
-         (if brace-decl-p
-             (if (eq (point) start)
-                 'at-header
+       (if (and least-enclosing
+                (eq (char-after least-enclosing) ?\())
+           (c-go-list-forward least-enclosing))
+       (c-forward-syntactic-ws)
+       (setq knr-start (point))
+       (if (c-syntactic-re-search-forward "{" nil t t)
+           (progn
+             (backward-char)
+             (cond
+              ((or (progn
+                     (c-backward-syntactic-ws)
+                     (<= (point) start))
+                   (and c-recognize-knr-p
+                        (and (setq knr-res (c-in-knr-argdecl))
+                             (<= knr-res knr-start))))
                'in-header)
-           'outwith-function))
-        ((eq decl-result 'previous)
-         (if (and (not brace-decl-p)
-                  (c-in-function-trailer-p))
-             'at-function-end
-           'outwith-function))
-        (t (error
-            "c-where-wrt-brace-construct: c-beginning-of-decl-1 returned %s"
-            decl-result))))))))
+              ((and knr-res
+                    (goto-char knr-res)
+                    (c-backward-syntactic-ws))) ; Always returns nil.
+              ((and (eq (char-before) ?\))
+                    (c-go-list-backward))
+               (c-syntactic-skip-backward "^;" start t)
+               (if (eq (point) start)
+                   (if (progn (c-backward-syntactic-ws)
+                              (memq (char-before) '(?\; ?} nil)))
+                       (if (progn (c-forward-syntactic-ws)
+                                  (eq (point) start))
+                           'at-header
+                         'outwith-function)
+                     'in-header)
+                 'outwith-function))
+              (t 'outwith-function)))
+         'outwith-function))))))
 
 (defun c-backward-to-nth-BOF-{ (n where)
   ;; Skip to the opening brace of the Nth function before point.  If
@@ -1749,9 +1725,11 @@ No indentation or other \"electric\" behavior is 
performed."
     (goto-char (c-least-enclosing-brace (c-parse-state)))
     (setq n (1- n)))
    ((eq where 'in-header)
-    (c-syntactic-re-search-forward "{")
-    (backward-char)
-    (setq n (1- n)))
+    (let ((encl-paren (c-least-enclosing-brace (c-parse-state))))
+      (if encl-paren (goto-char encl-paren))
+      (c-syntactic-re-search-forward "{" nil t t)
+      (backward-char)
+      (setq n (1- n))))
    ((memq where '(at-header outwith-function at-function-end in-trailer))
     (c-syntactic-skip-backward "^}")
     (when (eq (char-before) ?\})
@@ -1965,21 +1943,24 @@ defun."
     ;; The actual movement is done below.
     (setq n (1- n)))
    ((memq where '(at-function-end outwith-function at-header in-header))
-    (when (c-syntactic-re-search-forward "{" nil 'eob)
+    (if (eq where 'in-header)
+       (let ((pos (c-least-enclosing-brace (c-parse-state))))
+         (if pos (c-go-list-forward pos))))
+    (when (c-syntactic-re-search-forward "{" nil 'eob t)
       (backward-char)
       (forward-sexp)
       (setq n (1- n))))
    (t (error "c-forward-to-nth-EOF-\\;-or-}: `where' is %s" where)))
 
-  (when (c-in-function-trailer-p)
-    (c-syntactic-re-search-forward ";" nil 'eob t))
-
   ;; Each time round the loop, go forward to a "}" at the outermost level.
   (while (and (> n 0) (not (eobp)))
     (when (c-syntactic-re-search-forward "{" nil 'eob)
       (backward-char)
       (forward-sexp)
       (setq n (1- n))))
+
+  (when (c-in-function-trailer-p)
+    (c-syntactic-re-search-forward ";" nil 'eob t))
   n)
 
 (defun c-end-of-defun (&optional arg)
diff --git a/lisp/progmodes/cc-defs.el b/lisp/progmodes/cc-defs.el
index 38fe23b..536e676 100644
--- a/lisp/progmodes/cc-defs.el
+++ b/lisp/progmodes/cc-defs.el
@@ -691,14 +691,16 @@ whitespace.
 
 LIMIT sets an upper limit of the forward movement, if specified.  If
 LIMIT or the end of the buffer is reached inside a comment or
-preprocessor directive, the point will be left there.
+preprocessor directive, the point will be left there.  If point starts
+on the wrong side of LIMIT, it stays unchanged.
 
 Note that this function might do hidden buffer changes.  See the
 comment at the start of cc-engine.el for more info."
   (if limit
-      `(save-restriction
-        (narrow-to-region (point-min) (or ,limit (point-max)))
-        (c-forward-sws))
+      `(when (< (point) (or ,limit (point-max)))
+        (save-restriction
+          (narrow-to-region (point-min) (or ,limit (point-max)))
+          (c-forward-sws)))
     '(c-forward-sws)))
 
 (defmacro c-backward-syntactic-ws (&optional limit)
@@ -710,14 +712,16 @@ whitespace.
 
 LIMIT sets a lower limit of the backward movement, if specified.  If
 LIMIT is reached inside a line comment or preprocessor directive then
-the point is moved into it past the whitespace at the end.
+the point is moved into it past the whitespace at the end.  If point
+starts on the wrong side of LIMIT, it stays unchanged.
 
 Note that this function might do hidden buffer changes.  See the
 comment at the start of cc-engine.el for more info."
   (if limit
-      `(save-restriction
-        (narrow-to-region (or ,limit (point-min)) (point-max))
-        (c-backward-sws))
+      `(when (> (point) (or ,limit (point-min)))
+        (save-restriction
+          (narrow-to-region (or ,limit (point-min)) (point-max))
+          (c-backward-sws)))
     '(c-backward-sws)))
 
 (defmacro c-forward-sexp (&optional count)
diff --git a/lisp/progmodes/cc-engine.el b/lisp/progmodes/cc-engine.el
index 484624b..cc9833a 100644
--- a/lisp/progmodes/cc-engine.el
+++ b/lisp/progmodes/cc-engine.el
@@ -1184,6 +1184,15 @@ comment at the start of cc-engine.el for more info."
                           ;; suitable error.
                           (setq pre-stmt-found t)
                           (throw 'loop nil))
+                        ;; Handle C++'s `constexpr', etc.
+                        (if (save-excursion
+                              (and (looking-at c-block-stmt-hangon-key)
+                                   (progn
+                                     (c-backward-syntactic-ws lim)
+                                     (c-safe (c-backward-sexp) t))
+                                   (looking-at c-block-stmt-2-key)
+                                   (setq pos (point))))
+                            (goto-char pos))
                         (cond
                          ;; Have we moved into a macro?
                          ((and (not macro-start)
@@ -2665,7 +2674,7 @@ comment at the start of cc-engine.el for more info."
 ;; One of the above "near" caches is associated with each of these functions.
 ;;
 ;; When searching this cache, these functions first seek an exact match, then
-;; a "close" match from the assiciated near cache.  If neither of these
+;; a "close" match from the associated near cache.  If neither of these
 ;; succeed, the nearest preceding entry in the far cache is used.
 ;;
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
@@ -3784,12 +3793,14 @@ mhtml-mode."
                     (point)))
             (bra                       ; Position of "{".
              ;; Don't start scanning in the middle of a CPP construct unless
-             ;; it contains HERE - these constructs, in Emacs, are "commented
-             ;; out" with category properties.
-             (if (eq (c-get-char-property macro-start-or-from 'category)
-                       'c-cpp-delimiter)
-                   macro-start-or-from
-                 from))
+             ;; it contains HERE.
+             (if (and (not (eq macro-start-or-from from))
+                      (< macro-start-or-from here) ; Might not be needed.
+                      (progn (goto-char macro-start-or-from)
+                             (c-end-of-macro)
+                             (>= (point) here)))
+                 from
+               macro-start-or-from))
             ce)                        ; Position of "}"
        (or upper-lim (setq upper-lim from))
 
@@ -4319,38 +4330,29 @@ mhtml-mode."
       (setq c-state-nonlit-pos-cache-limit (1- here)))
   (c-truncate-lit-pos-cache here)
 
-  ;; `c-state-cache':
-  ;; Case 1: if `here' is in a literal containing point-min, everything
-  ;; becomes (or is already) nil.
-  (if (or (null c-state-cache-good-pos)
-         (< here (c-state-get-min-scan-pos)))
-      (setq c-state-cache nil
-           c-state-cache-good-pos nil
-           c-state-min-scan-pos nil)
-
-    ;; Truncate `c-state-cache' and set `c-state-cache-good-pos' to a value
-    ;; below `here'.  To maintain its consistency, we may need to insert a new
-    ;; brace pair.
-    (let ((here-bol (c-point 'bol here))
-         too-high-pa  ; recorded {/(/[ next above or just below here, or nil.
-         dropped-cons)           ; was the last removed element a brace pair?
-      ;; The easy bit - knock over-the-top bits off `c-state-cache'.
-      (while (and c-state-cache
-                 (>= (c-state-cache-top-paren) here))
-       (setq dropped-cons (consp (car c-state-cache))
-             too-high-pa (c-state-cache-top-lparen)
-             c-state-cache (cdr c-state-cache)))
-
-      ;; Do we need to add in an earlier brace pair, having lopped one off?
-      (if (and dropped-cons
-              (<= too-high-pa here))
-         (c-append-lower-brace-pair-to-state-cache too-high-pa here here-bol))
-      (if (and c-state-cache-good-pos (< here c-state-cache-good-pos))
-         (setq c-state-cache-good-pos
-               (or (save-excursion
-                     (goto-char here)
-                     (c-literal-start))
-                   here)))))
+  (cond
+   ;; `c-state-cache':
+   ;; Case 1: if `here' is in a literal containing point-min, everything
+   ;; becomes (or is already) nil.
+   ((or (null c-state-cache-good-pos)
+       (< here (c-state-get-min-scan-pos)))
+    (setq c-state-cache nil
+         c-state-cache-good-pos nil
+         c-state-min-scan-pos nil))
+
+   ;; Case 2: `here' is below `c-state-cache-good-pos', so we need to amend
+   ;; the entire `c-state-cache' data.
+   ((< here c-state-cache-good-pos)
+    (let* ((res (c-remove-stale-state-cache-backwards here))
+          (good-pos (car res))
+          (scan-backward-pos (cadr res))
+          (scan-forward-p (car (cddr res))))
+      (if scan-backward-pos
+         (c-append-lower-brace-pair-to-state-cache scan-backward-pos here))
+      (setq c-state-cache-good-pos
+           (if scan-forward-p
+               (c-append-to-state-cache good-pos here)
+             good-pos)))))
 
   ;; The brace-pair desert marker:
   (when (car c-state-brace-pair-desert)
@@ -8298,7 +8300,7 @@ comment at the start of cc-engine.el for more info."
   ;; o - nil if no name is found;
   ;; o - 'template if it's an identifier ending with an angle bracket
   ;;   arglist;
-  ;; o - 'operator of it's an operator identifier;
+  ;; o - 'operator if it's an operator identifier;
   ;; o - t if it's some other kind of name.
   ;;
   ;; This function records identifier ranges on
@@ -8318,6 +8320,7 @@ comment at the start of cc-engine.el for more info."
        (lim+ (c-determine-+ve-limit 500)))
     (while
        (and
+        (< (point) lim+)
         (looking-at c-identifier-key)
 
         (progn
@@ -8367,23 +8370,28 @@ comment at the start of cc-engine.el for more info."
                          ;; '*', '&' or a name followed by ":: *",
                          ;; where each can be followed by a sequence
                          ;; of `c-opt-type-modifier-key'.
-                         (while (cond ((looking-at "[*&]")
-                                       (goto-char (match-end 0))
-                                       t)
-                                      ((looking-at c-identifier-start)
-                                       (and (c-forward-name)
-                                            (looking-at "::")
-                                            (progn
-                                              (goto-char (match-end 0))
-                                              (c-forward-syntactic-ws lim+)
-                                              (eq (char-after) ?*))
-                                            (progn
-                                              (forward-char)
-                                              t))))
+                         (while
+                             (and
+                              (< (point) lim+)
+                              (cond ((looking-at "[*&]")
+                                     (goto-char (match-end 0))
+                                     t)
+                                    ((looking-at c-identifier-start)
+                                     (and (c-forward-name)
+                                          (looking-at "::")
+                                          (progn
+                                            (goto-char (match-end 0))
+                                            (c-forward-syntactic-ws lim+)
+                                            (eq (char-after) ?*))
+                                          (progn
+                                            (forward-char)
+                                            t)))))
                            (while (progn
                                     (c-forward-syntactic-ws lim+)
                                     (setq pos (point))
-                                    (looking-at c-opt-type-modifier-key))
+                                    (and
+                                     (<= (point) lim+)
+                                     (looking-at c-opt-type-modifier-key)))
                              (goto-char (match-end 1))))))
 
                       ((looking-at c-overloadable-operators-regexp)
@@ -8429,6 +8437,9 @@ comment at the start of cc-engine.el for more info."
               ;; Maybe an angle bracket arglist.
               (when (let (c-last-identifier-range)
                       (c-forward-<>-arglist nil))
+                ;; <> arglists can legitimately be very long, so recalculate
+                ;; `lim+'.
+                (setq lim+ (c-determine-+ve-limit 500))
 
                 (c-forward-syntactic-ws lim+)
                 (unless (eq (char-after) ?\()
@@ -11419,7 +11430,9 @@ comment at the start of cc-engine.el for more info."
               ;; also might be part of a declarator expression.  Currently
               ;; there's no such language.
               (not (or (looking-at c-symbol-start)
-                       (looking-at c-type-decl-prefix-key))))))
+                       (looking-at c-type-decl-prefix-key)
+                       (and (eq (char-after) ?{)
+                            (not (c-looking-at-statement-block))))))))
 
            ;; In Pike a list of modifiers may be followed by a brace
            ;; to make them apply to many identifiers.  Note that the
@@ -11826,15 +11839,17 @@ comment at the start of cc-engine.el for more info."
   ;; POINT, or nil if there is no such position, or we do not know it.  LIM is
   ;; a backward search limit.
   ;;
-  ;; The determination of whether the brace starts a brace list is solely by
-  ;; the context of the brace, not by its contents.
+  ;; The determination of whether the brace starts a brace list is mainly by
+  ;; the context of the brace, not by its contents.  In exceptional
+  ;; circumstances (e.g. "struct A {" in C++ Mode), the contents are examined,
+  ;; too.
   ;;
   ;; Here, "brace list" does not include the body of an enum.
   (save-excursion
     (let ((start (point))
          (braceassignp 'dontknow)
          inexpr-brace-list bufpos macro-start res pos after-type-id-pos
-         in-paren parens-before-brace
+         pos2 in-paren parens-before-brace
          paren-state paren-pos)
 
       (setq res (c-backward-token-2 1 t lim))
@@ -11850,12 +11865,16 @@ comment at the start of cc-engine.el for more info."
                 (goto-char paren-pos)
                 (setq braceassignp 'c++-noassign
                       in-paren 'in-paren))
-               ((looking-at c-pre-id-bracelist-key)
+               ((looking-at c-pre-brace-non-bracelist-key)
                 (setq braceassignp nil))
                ((looking-at c-return-key))
                ((and (looking-at c-symbol-start)
                      (not (looking-at c-keywords-regexp)))
-                (setq after-type-id-pos (point)))
+                (if (save-excursion
+                      (and (zerop (c-backward-token-2 1 t lim))
+                           (looking-at c-pre-id-bracelist-key)))
+                    (setq braceassignp 'c++-noassign)
+                  (setq after-type-id-pos (point))))
                ((eq (char-after) ?\()
                 (setq parens-before-brace t)
                 nil)
@@ -11869,8 +11888,13 @@ comment at the start of cc-engine.el for more info."
                        (eq (char-after paren-pos) ?\()
                        (setq in-paren 'in-paren)
                        (goto-char paren-pos)))
-                 ((looking-at c-pre-id-bracelist-key))
+                 ((looking-at c-pre-brace-non-bracelist-key))
                  ((looking-at c-return-key))
+                 ((and (looking-at c-symbol-start)
+                       (not (looking-at c-keywords-regexp))
+                       (save-excursion
+                         (and (zerop (c-backward-token-2 1 t lim))
+                              (looking-at c-pre-id-bracelist-key)))))
                  (t (setq after-type-id-pos (point))
                     nil))))
          (setq braceassignp 'c++-noassign))
@@ -11955,8 +11979,12 @@ comment at the start of cc-engine.el for more info."
        (cond
         (braceassignp
          ;; We've hit the beginning of the aggregate list.
-         (c-beginning-of-statement-1 containing-sexp)
-         (cons (point) (or in-paren inexpr-brace-list)))
+         (setq pos2 (point))
+         (cons
+          (if (eq (c-beginning-of-statement-1 containing-sexp) 'same)
+              (point)
+            pos2)
+          (or in-paren inexpr-brace-list)))
         ((and after-type-id-pos
               (save-excursion
                 (when (eq (char-after) ?\;)
@@ -11968,34 +11996,36 @@ comment at the start of cc-engine.el for more info."
                              (c-get-char-property (point) 'syntax-table))
                     (c-go-list-forward nil after-type-id-pos)
                     (c-forward-syntactic-ws)))
-                (and
-                 (or (not (looking-at c-class-key))
-                     (save-excursion
-                       (goto-char (match-end 1))
-                       (c-forward-syntactic-ws)
-                       (not (eq (point) after-type-id-pos))))
-                 (progn
-                   (setq res
-                         (c-forward-decl-or-cast-1
-                          (save-excursion (c-backward-syntactic-ws) (point))
-                          nil nil))
-                   (and (consp res)
-                        (cond
-                         ((eq (car res) after-type-id-pos))
-                         ((> (car res) after-type-id-pos) nil)
-                         (t
-                          (catch 'find-decl
-                            (save-excursion
-                              (goto-char (car res))
-                              (c-do-declarators
-                               (point-max) t nil nil
-                               (lambda (id-start _id-end _tok _not-top _func 
_init)
-                                 (cond
-                                  ((> id-start after-type-id-pos)
-                                   (throw 'find-decl nil))
-                                  ((eq id-start after-type-id-pos)
-                                   (throw 'find-decl t)))))
-                              nil)))))))))
+                (if (and (not (eq (point) after-type-id-pos))
+                         (or (not (looking-at c-class-key))
+                             (save-excursion
+                               (goto-char (match-end 1))
+                               (c-forward-syntactic-ws)
+                               (not (eq (point) after-type-id-pos)))))
+                    (progn
+                      (setq res
+                            (c-forward-decl-or-cast-1 (c-point 'bosws)
+                                                      nil nil))
+                      (and (consp res)
+                           (cond
+                            ((eq (car res) after-type-id-pos))
+                            ((> (car res) after-type-id-pos) nil)
+                            (t
+                             (catch 'find-decl
+                               (save-excursion
+                                 (goto-char (car res))
+                                 (c-do-declarators
+                                  (point-max) t nil nil
+                                  (lambda (id-start _id-end _tok _not-top 
_func _init)
+                                    (cond
+                                     ((> id-start after-type-id-pos)
+                                      (throw 'find-decl nil))
+                                     ((eq id-start after-type-id-pos)
+                                      (throw 'find-decl t)))))
+                                 nil))))))
+                  (save-excursion
+                    (goto-char start)
+                    (not (c-looking-at-statement-block))))))
          (cons bufpos (or in-paren inexpr-brace-list)))
         ((or (eq (char-after) ?\;)
              ;; Brace lists can't contain a semicolon, so we're done.
@@ -12145,33 +12175,31 @@ comment at the start of cc-engine.el for more info."
 (defun c-looking-at-statement-block ()
   ;; Point is at an opening brace.  If this is a statement block (i.e. the
   ;; elements in the block are terminated by semicolons, or the block is
-  ;; empty, or the block contains a keyword) return non-nil.  Otherwise,
-  ;; return nil.
+  ;; empty, or the block contains a characteristic keyword, or there is a
+  ;; nested statement block) return non-nil.  Otherwise, return nil.
   (let ((here (point)))
     (prog1
        (if (c-go-list-forward)
            (let ((there (point)))
              (backward-char)
-             (c-syntactic-skip-backward "^;," here t)
+             (c-syntactic-skip-backward "^;" here t)
              (cond
-              ((eq (char-before) ?\;) t)
-              ((eq (char-before) ?,) nil)
-              (t                       ; We're at (1+ here).
-               (cond
-                ((progn (c-forward-syntactic-ws)
-                        (eq (point) (1- there))))
-                ((c-syntactic-re-search-forward c-keywords-regexp there t))
-                ((c-syntactic-re-search-forward "{" there t t)
-                 (backward-char)
-                 (c-looking-at-statement-block))
-                (t nil)))))
+              ((eq (char-before) ?\;))
+              ((progn (c-forward-syntactic-ws)
+                      (eq (point) (1- there))))
+              ((c-syntactic-re-search-forward
+                c-stmt-block-only-keywords-regexp there t))
+              ((c-syntactic-re-search-forward "{" there t t)
+               (backward-char)
+               (c-looking-at-statement-block))
+              (t nil)))
          (forward-char)
          (cond
-          ((c-syntactic-re-search-forward "[;,]" nil t t)
-           (eq (char-before) ?\;))
+          ((c-syntactic-re-search-forward ";" nil t t))
           ((progn (c-forward-syntactic-ws)
                   (eobp)))
-          ((c-syntactic-re-search-forward c-keywords-regexp nil t t))
+          ((c-syntactic-re-search-forward c-stmt-block-only-keywords-regexp
+                                          nil t t))
           ((c-syntactic-re-search-forward "{" nil t t)
            (backward-char)
            (c-looking-at-statement-block))
diff --git a/lisp/progmodes/cc-langs.el b/lisp/progmodes/cc-langs.el
index 0747938..fa4e730 100644
--- a/lisp/progmodes/cc-langs.el
+++ b/lisp/progmodes/cc-langs.el
@@ -3098,6 +3098,36 @@ Note that Java specific rules are currently applied to 
tell this from
   t (c-make-keywords-re t (c-lang-const c-keywords)))
 (c-lang-defvar c-keywords-regexp (c-lang-const c-keywords-regexp))
 
+(c-lang-defconst c-stmt-block-only-keywords
+  "All keywords which unambiguously signify a statement block (as opposed to
+   a brace list) when occurring inside braces."
+  t (c--set-difference
+     (c-lang-const c-keywords)
+     (append (c-lang-const c-primary-expr-kwds)
+            (c-lang-const c-constant-kwds)
+            `(,@(when (c-major-mode-is 'c++-mode)
+                  '("typeid" "dynamic_cast" "static_cast" "const_cast"
+                    "reinterpret_cast" "alignof")))
+            (c-lang-const c-type-modifier-prefix-kwds)
+            (c-lang-const c-overloadable-operators)
+            (c-lang-const c-template-typename-kwds)
+            `(,@(when (c-major-mode-is 'c++-mode)
+                  '("reflexpr")))
+            `(,@(when (c-major-mode-is '(c-mode c++-mode))
+                  '("sizeof")))
+            (c-lang-const c-pre-lambda-tokens)
+            (c-lang-const c-block-decls-with-vars)
+            (c-lang-const c-primitive-type-kwds))
+     :test 'string-equal))
+
+(c-lang-defconst c-stmt-block-only-keywords-regexp
+  ;; A regexp matching a keyword in `c-stmt-block-only-keywords'.  Such a
+  ;; match can start and end only at token boundaries.
+  t (concat "\\(^\\|\\=\\|[^" (c-lang-const c-symbol-chars) "]\\)"
+           (c-make-keywords-re t (c-lang-const c-stmt-block-only-keywords))))
+(c-lang-defvar c-stmt-block-only-keywords-regexp
+  (c-lang-const c-stmt-block-only-keywords-regexp))
+
 (c-lang-defconst c-keyword-member-alist
   ;; An alist with all the keywords in the cars.  The cdr for each
   ;; keyword is a list of the symbols for the `*-kwds' lists that
@@ -3650,13 +3680,25 @@ list."
   c t)
 (c-lang-defvar c-recognize-knr-p (c-lang-const c-recognize-knr-p))
 
+(c-lang-defconst c-pre-id-bracelist-kwds
+  "Keywords which, preceding an identifier and brace, signify a bracelist.
+This is only used in c++-mode."
+  t nil
+  c++ '("new" "throw"))
+
 (c-lang-defconst c-pre-id-bracelist-key
-  "A regexp matching tokens which, preceding an identifier, signify a 
bracelist.
-"
-  t regexp-unmatchable
-  c++ "new\\([^[:alnum:]_$]\\|$\\)\\|&&?\\(\\S.\\|$\\)")
+  ;; A regexp matching keywords which, preceding an identifier and brace,
+  ;; signify a bracelist.  Only used in c++-mode.
+  t (c-make-keywords-re t (c-lang-const c-pre-id-bracelist-kwds)))
 (c-lang-defvar c-pre-id-bracelist-key (c-lang-const c-pre-id-bracelist-key))
 
+(c-lang-defconst c-pre-brace-non-bracelist-key
+  "A regexp matching tokens which, preceding a brace, make it a non-bracelist."
+  t regexp-unmatchable
+  c++ "&&?\\(\\S.\\|$\\)")
+(c-lang-defvar c-pre-brace-non-bracelist-key
+  (c-lang-const c-pre-brace-non-bracelist-key))
+
 (c-lang-defconst c-recognize-typeless-decls
   "Non-nil means function declarations without return type should be
 recognized.  That can introduce an ambiguity with parenthesized macro
diff --git a/lisp/progmodes/cfengine.el b/lisp/progmodes/cfengine.el
index f516664..472788d 100644
--- a/lisp/progmodes/cfengine.el
+++ b/lisp/progmodes/cfengine.el
@@ -69,7 +69,6 @@
 
 (defcustom cfengine-indent 2
   "Size of a CFEngine indentation step in columns."
-  :group 'cfengine
   :type 'integer)
 
 (defcustom cfengine-cf-promises
@@ -86,7 +85,6 @@ Used for syntax discovery and checking.  Set to nil to disable
 the `compile-command' override.  In that case, the ElDoc support
 will use a fallback syntax definition."
   :version "24.4"
-  :group 'cfengine
   :type '(choice file (const nil)))
 
 (defcustom cfengine-parameters-indent '(promise pname 2)
@@ -145,7 +143,6 @@ bundle agent rcfiles
 }
 "
   :version "24.4"
-  :group 'cfengine
   :type '(list
           (choice (const :tag "Anchor at beginning of promise" promise)
                   (const :tag "Anchor at beginning of line" bol))
@@ -799,7 +796,6 @@ bundle agent rcfiles
 
 (defcustom cfengine-mode-abbrevs nil
   "Abbrevs for CFEngine2 mode."
-  :group 'cfengine
   :type '(repeat (list (string :tag "Name")
                       (string :tag "Expansion")
                       (choice  :tag "Hook" (const nil) function))))
@@ -991,13 +987,11 @@ Intended as the value of `indent-line-function'."
     (if (> (- (point-max) pos) (point))
        (goto-char (- (point-max) pos)))))
 
-;; This doesn't work too well in Emacs 21.2.  See 22.1 development
-;; code.
 (defun cfengine-fill-paragraph (&optional justify)
   "Fill `paragraphs' in Cfengine code."
   (interactive "P")
   (or (if (fboundp 'fill-comment-paragraph)
-         (fill-comment-paragraph justify) ; post Emacs 21.3
+          (fill-comment-paragraph justify)
        ;; else do nothing in a comment
        (nth 4 (parse-partial-sexp (save-excursion
                                     (beginning-of-defun)
diff --git a/lisp/progmodes/cmacexp.el b/lisp/progmodes/cmacexp.el
index 1a45b1c..820867a 100644
--- a/lisp/progmodes/cmacexp.el
+++ b/lisp/progmodes/cmacexp.el
@@ -99,13 +99,11 @@
 
 (defcustom c-macro-shrink-window-flag nil
   "Non-nil means shrink the *Macroexpansion* window to fit its contents."
-  :type 'boolean
-  :group 'c-macro)
+  :type 'boolean)
 
 (defcustom c-macro-prompt-flag nil
   "Non-nil makes `c-macro-expand' prompt for preprocessor arguments."
-  :type 'boolean
-  :group 'c-macro)
+  :type 'boolean)
 
 (defcustom c-macro-preprocessor
   (cond ;; Solaris has it in an unusual place.
@@ -129,13 +127,11 @@
 
 If you change this, be sure to preserve the `-C' (don't strip comments)
 option, or to set an equivalent one."
-  :type 'string
-  :group 'c-macro)
+  :type 'string)
 
 (defcustom c-macro-cppflags ""
   "Preprocessor flags used by `c-macro-expand'."
-  :type 'string
-  :group 'c-macro)
+  :type 'string)
 
 (defconst c-macro-buffer-name "*Macroexpansion*")
 
diff --git a/lisp/progmodes/compile.el b/lisp/progmodes/compile.el
index 48b5ee9..7a02c3a 100644
--- a/lisp/progmodes/compile.el
+++ b/lisp/progmodes/compile.el
@@ -2844,8 +2844,9 @@ and overlay is highlighted between MK and END-MK."
     (when (and (not pre-existing) w)
       (compilation-set-window-height w))
 
-    (if from-compilation-buffer
-        ;; If the compilation buffer window was selected,
+    (if (or from-compilation-buffer
+            (eq w (selected-window)))
+        ;; If the compilation buffer window is selected,
         ;; keep the compilation buffer in this window;
         ;; display the source in another window.
         (let ((pop-up-windows t))
@@ -3040,12 +3041,7 @@ TRUE-DIRNAME is the `file-truename' of DIRNAME, if 
given."
            ;; Get the specified directory from FILE.
            (spec-directory
              (if (cdr file)
-                 ;; This function is active in `compilation-filter'.
-                 ;; There could be problems to call `file-truename'
-                 ;; for remote compilation processes.
-                (if (file-remote-p default-directory)
-                    (concat comint-file-name-prefix (cdr file))
-                  (file-truename (concat comint-file-name-prefix (cdr 
file)))))))
+                (file-truename (concat comint-file-name-prefix (cdr file))))))
 
        ;; Check for a comint-file-name-prefix and prepend it if appropriate.
        ;; (This is very useful for compilation-minor-mode in an rlogin-mode
diff --git a/lisp/progmodes/cperl-mode.el b/lisp/progmodes/cperl-mode.el
index a70e8e3..7612f8d 100644
--- a/lisp/progmodes/cperl-mode.el
+++ b/lisp/progmodes/cperl-mode.el
@@ -92,6 +92,7 @@
        (concat msg ": ")))))
 
 (eval-when-compile (require 'cl-lib))
+(require 'facemenu)
 
 (defvar msb-menu-cond)
 (defvar gud-perldb-history)
@@ -440,12 +441,6 @@ after reload."
   :type 'boolean
   :group 'cperl-speed)
 
-(defcustom cperl-imenu-addback nil
-  "Not-nil means add backreferences to generated `imenu's.
-May require patched `imenu' and `imenu-go'.  Obsolete."
-  :type 'boolean
-  :group 'cperl-help-system)
-
 (defcustom cperl-max-help-size 66
   "Non-nil means shrink-wrapping of info-buffer allowed up to these percents."
   :type '(choice integer (const nil))
@@ -659,8 +654,8 @@ Run Perl/Tools/Insert-spaces-if-needed to fix your lazy 
typing.
 
 Switch auto-help on/off with Perl/Tools/Auto-help.
 
-Though with contemporary Emaxen CPerl mode should maintain the correct
-parsing of Perl even when editing, sometimes it may be lost.  Fix this by
+Though CPerl mode should maintain the correct parsing of Perl even when
+editing, sometimes it may be lost.  Fix this by
 
   \\[normal-mode]
 
@@ -676,63 +671,20 @@ micro-docs on what I know about CPerl problems.")
   "Description of problems in CPerl mode.
 `fill-paragraph' on a comment may leave the point behind the
 paragraph.  It also triggers a bug in some versions of Emacs (CPerl tries
-to detect it and bulk out).
-
-See documentation of a variable `cperl-problems-old-emaxen' for the
-problems which disappear if you upgrade Emacs to a reasonably new
-version (20.3 for Emacs).")
+to detect it and bulk out).")
 
 (defvar cperl-problems-old-emaxen 'please-ignore-this-line
-  "Description of problems in CPerl mode specific for older Emacs versions.
-
-Emacs had a _very_ restricted syntax parsing engine until version
-20.1.  Most problems below are corrected starting from this version of
-Emacs, and all of them should be fixed in version 20.3.  (Or apply
-patches to Emacs 19.33/34 - see tips.)
-
-Note that even with newer Emacsen in some very rare cases the details
-of interaction of `font-lock' and syntaxification may be not cleaned
-up yet.  You may get slightly different colors basing on the order of
-fontification and syntaxification.  Say, the initial faces is correct,
-but editing the buffer breaks this.
-
-Even with older Emacsen CPerl mode tries to corrects some Emacs
-misunderstandings, however, for efficiency reasons the degree of
-correction is different for different operations.  The partially
-corrected problems are: POD sections, here-documents, regexps.  The
-operations are: highlighting, indentation, electric keywords, electric
-braces.
-
-This may be confusing, since the regexp s#//#/#; may be highlighted
-as a comment, but it will be recognized as a regexp by the indentation
-code.  Or the opposite case, when a POD section is highlighted, but
-may break the indentation of the following code (though indentation
-should work if the balance of delimiters is not broken by POD).
-
-The main trick (to make $ a \"backslash\") makes constructions like
-${aaa} look like unbalanced braces.  The only trick I can think of is
-to insert it as $ {aaa} (valid in perl5, not in perl4).
-
-Similar problems arise in regexps, when /(\\s|$)/ should be rewritten
-as /($|\\s)/.  Note that such a transposition is not always possible.
-
-The solution is to upgrade your Emacs or patch an older one.  Note
-that Emacs 20.2 has some bugs related to `syntax-table' text
-properties.  Patches are available on the main CPerl download site,
-and on CPAN.
-
-If these bugs cannot be fixed on your machine (say, you have an inferior
-environment and cannot recompile), you may still disable all the fancy stuff
-via `cperl-use-syntax-table-text-property'.")
+  "This used to contain a description of problems in CPerl mode
+specific for very old Emacs versions.  This is no longer relevant
+and has been removed.")
+(make-obsolete-variable 'cperl-problems-old-emaxen nil "28.1")
 
 (defvar cperl-praise 'please-ignore-this-line
   "Advantages of CPerl mode.
 
 0) It uses the newest `syntax-table' property ;-);
 
-1) It does 99% of Perl syntax correct (as opposed to 80-90% in Perl
-mode - but the latter number may have improved too in last years) even
-with old Emaxen which do not support `syntax-table' property.
+1) It does 99% of Perl syntax correct.
 
 When using `syntax-table' property for syntax assist hints, it should
 handle 99.995% of lines correct - or somesuch.  It automatically
@@ -813,8 +765,7 @@ the settings present before the switch.
 9) When doing indentation of control constructs, may correct
 line-breaks/spacing between elements of the construct.
 
-10) Uses a linear-time algorithm for indentation of regions (on Emaxen with
-capable syntax engines).
+10) Uses a linear-time algorithm for indentation of regions.
 
 11) Syntax-highlight, indentation, sexp-recognition inside regular expressions.
 ")
@@ -838,8 +789,8 @@ syntax-parsing routines, and marks them up so that either
 
     A1) CPerl may work around these deficiencies (for big chunks, mostly
         PODs and HERE-documents), or
-    A2) On capable Emaxen CPerl will use improved syntax-handling
-       which reads mark-up hints directly.
+    A2) CPerl will use improved syntax-handling which reads mark-up
+        hints directly.
 
     The scan in case A2 is much more comprehensive, thus may be slower.
 
@@ -957,22 +908,12 @@ In regular expressions (including character classes):
 
 
 (defun cperl-make-indent (column &optional minimum keep)
-  "Makes indent of the current line the requested amount.
-Unless KEEP, removes the old indentation.  Works around a bug in ancient
-versions of Emacs."
-  (let ((prop (get-text-property (point) 'syntax-type)))
-    (or keep
-       (delete-horizontal-space))
-    (indent-to column minimum)
-    ;; In old versions (e.g., 19.33) `indent-to' would not inherit properties
-    (and prop
-        (> (current-column) 0)
-        (save-excursion
-          (beginning-of-line)
-          (or (get-text-property (point) 'syntax-type)
-              (and (looking-at "\\=[ \t]")
-                     (put-text-property (point) (match-end 0)
-                                        'syntax-type prop)))))))
+  "Indent from point with tabs and spaces until COLUMN is reached.
+MINIMUM is like in `indent-to', which see.
+Unless KEEP, removes the old indentation."
+  (or keep
+      (delete-horizontal-space))
+  (indent-to column minimum))
 
 ;; Probably it is too late to set these guys already, but it can help later:
 
@@ -1019,9 +960,12 @@ versions of Emacs."
   "Abbrev table in use in CPerl mode buffers."
   :parents (list cperl-mode-electric-keywords-abbrev-table))
 
-(when (boundp 'edit-var-mode-alist)
-  ;; FIXME: What package uses this?
-  (add-to-list 'edit-var-mode-alist '(perl-mode (regexp . "^cperl-"))))
+;; ;; TODO: Commented out as we don't know what it is used for.  If
+;; ;;       there are no bug reports about this for Emacs 28.1, this
+;; ;;       can probably be removed.  (Code search online reveals nothing.)
+;; (when (boundp 'edit-var-mode-alist)
+;;   ;; FIXME: What package uses this?
+;;   (add-to-list 'edit-var-mode-alist '(perl-mode (regexp . "^cperl-"))))
 
 (defvar cperl-mode-map
   (let ((map (make-sparse-keymap)))
@@ -1091,172 +1035,314 @@ versions of Emacs."
     map)
   "Keymap used in CPerl mode.")
 
-(defvar cperl-menu)
 (defvar cperl-lazy-installed)
 (defvar cperl-old-style nil)
-(condition-case nil
-    (progn
-      (require 'easymenu)
-      (easy-menu-define
-       cperl-menu cperl-mode-map "Menu for CPerl mode"
-       '("Perl"
-        ["Beginning of function" beginning-of-defun t]
-        ["End of function" end-of-defun t]
-        ["Mark function" mark-defun t]
-        ["Indent expression" cperl-indent-exp t]
-         ["Fill paragraph/comment" fill-paragraph t]
-        "----"
-        ["Line up a construction" cperl-lineup (use-region-p)]
-        ["Invert if/unless/while etc" cperl-invert-if-unless t]
-        ("Regexp"
-         ["Beautify" cperl-beautify-regexp
-          cperl-use-syntax-table-text-property]
-         ["Beautify one level deep" (cperl-beautify-regexp 1)
-          cperl-use-syntax-table-text-property]
-         ["Beautify a group" cperl-beautify-level
-          cperl-use-syntax-table-text-property]
-         ["Beautify a group one level deep" (cperl-beautify-level 1)
-          cperl-use-syntax-table-text-property]
-         ["Contract a group" cperl-contract-level
-          cperl-use-syntax-table-text-property]
-         ["Contract groups" cperl-contract-levels
-          cperl-use-syntax-table-text-property]
-         "----"
-         ["Find next interpolated" cperl-next-interpolated-REx
-          (next-single-property-change (point-min) 'REx-interpolated)]
-         ["Find next interpolated (no //o)"
-          cperl-next-interpolated-REx-0
-          (or (text-property-any (point-min) (point-max) 'REx-interpolated t)
-              (text-property-any (point-min) (point-max) 'REx-interpolated 1))]
-         ["Find next interpolated (neither //o nor whole-REx)"
-          cperl-next-interpolated-REx-1
-          (text-property-any (point-min) (point-max) 'REx-interpolated t)])
-        ["Insert spaces if needed to fix style" cperl-find-bad-style t]
-        ["Refresh \"hard\" constructions" cperl-find-pods-heres t]
-        "----"
-        ["Indent region" cperl-indent-region (use-region-p)]
-        ["Comment region" cperl-comment-region (use-region-p)]
-        ["Uncomment region" cperl-uncomment-region (use-region-p)]
-        "----"
-        ["Run" mode-compile (fboundp 'mode-compile)]
-        ["Kill" mode-compile-kill (and (fboundp 'mode-compile-kill)
-                                       (get-buffer "*compilation*"))]
-        ["Next error" next-error (get-buffer "*compilation*")]
-        ["Check syntax" cperl-check-syntax (fboundp 'mode-compile)]
-        "----"
-        ["Debugger" cperl-db t]
-        "----"
-        ("Tools"
-         ["Imenu" imenu (fboundp 'imenu)]
-         ["Imenu on Perl Info" cperl-imenu-on-info (featurep 'imenu)]
-         "----"
-         ["Ispell PODs" cperl-pod-spell
-          ;; Better not to update syntaxification here:
-          ;; debugging syntaxification can be broken by this???
-          (or
-           (get-text-property (point-min) 'in-pod)
-           (< (progn
-                (and cperl-syntaxify-for-menu
-                     (cperl-update-syntaxification (point-max)))
-                (next-single-property-change (point-min) 'in-pod nil 
(point-max)))
-              (point-max)))]
-         ["Ispell HERE-DOCs" cperl-here-doc-spell
-          (< (progn
-               (and cperl-syntaxify-for-menu
-                    (cperl-update-syntaxification (point-max)))
-               (next-single-property-change (point-min) 'here-doc-group nil 
(point-max)))
-             (point-max))]
-         ["Narrow to this HERE-DOC" cperl-narrow-to-here-doc
-          (eq 'here-doc  (progn
-               (and cperl-syntaxify-for-menu
-                    (cperl-update-syntaxification (point)))
-               (get-text-property (point) 'syntax-type)))]
-         ["Select this HERE-DOC or POD section"
-          cperl-select-this-pod-or-here-doc
-          (memq (progn
-                  (and cperl-syntaxify-for-menu
-                       (cperl-update-syntaxification (point)))
-                  (get-text-property (point) 'syntax-type))
-                '(here-doc pod))]
-         "----"
-         ["CPerl pretty print (experimental)" cperl-ps-print
-          (fboundp 'ps-extend-face-list)]
-         "----"
-         ["Syntaxify region" cperl-find-pods-heres-region
-          (use-region-p)]
-         ["Profile syntaxification" cperl-time-fontification t]
-         ["Debug errors in delayed fontification" cperl-emulate-lazy-lock t]
-         ["Debug unwind for syntactic scan" cperl-toggle-set-debug-unwind t]
-         ["Debug backtrace on syntactic scan (BEWARE!!!)"
-          (cperl-toggle-set-debug-unwind nil t) t]
-         "----"
-         ["Class Hierarchy from TAGS" cperl-tags-hier-init t]
-         ;;["Update classes" (cperl-tags-hier-init t) tags-table-list]
-         ("Tags"
-          ;; ["Create tags for current file" cperl-etags t]
-          ;; ["Add tags for current file" (cperl-etags t) t]
-          ;; ["Create tags for Perl files in directory" (cperl-etags nil t) t]
-          ;; ["Add tags for Perl files in directory" (cperl-etags t t) t]
-          ;; ["Create tags for Perl files in (sub)directories"
-          ;;  (cperl-etags nil 'recursive) t]
-          ;; ["Add tags for Perl files in (sub)directories"
-          ;;  (cperl-etags t 'recursive) t])
-          ;; ;;? cperl-write-tags (&optional file erase recurse dir inbuffer)
-          ["Create tags for current file" (cperl-write-tags nil t) t]
-          ["Add tags for current file" (cperl-write-tags) t]
-          ["Create tags for Perl files in directory"
-           (cperl-write-tags nil t nil t) t]
-          ["Add tags for Perl files in directory"
-           (cperl-write-tags nil nil nil t) t]
-          ["Create tags for Perl files in (sub)directories"
-           (cperl-write-tags nil t t t) t]
-          ["Add tags for Perl files in (sub)directories"
-           (cperl-write-tags nil nil t t) t]))
-        ("Perl docs"
-         ["Define word at point" imenu-go-find-at-position
-          (fboundp 'imenu-go-find-at-position)]
-         ["Help on function" cperl-info-on-command t]
-         ["Help on function at point" cperl-info-on-current-command t]
-         ["Help on symbol at point" cperl-get-help t]
-         ["Perldoc" cperl-perldoc t]
-         ["Perldoc on word at point" cperl-perldoc-at-point t]
-         ["View manpage of POD in this file" cperl-build-manpage t]
-         ["Auto-help on" cperl-lazy-install
-          (not cperl-lazy-installed)]
-         ["Auto-help off" cperl-lazy-unstall
-          cperl-lazy-installed])
-        ("Toggle..."
-         ["Auto newline" cperl-toggle-auto-newline t]
-         ["Electric parens" cperl-toggle-electric t]
-         ["Electric keywords" cperl-toggle-abbrev t]
-         ["Fix whitespace on indent" cperl-toggle-construct-fix t]
-         ["Auto-help on Perl constructs" cperl-toggle-autohelp t]
-         ["Auto fill" auto-fill-mode t])
-        ("Indent styles..."
-         ["CPerl" (cperl-set-style "CPerl") t]
-         ["PBP" (cperl-set-style  "PBP") t]
-         ["PerlStyle" (cperl-set-style "PerlStyle") t]
-         ["GNU" (cperl-set-style "GNU") t]
-         ["C++" (cperl-set-style "C++") t]
-         ["K&R" (cperl-set-style "K&R") t]
-         ["BSD" (cperl-set-style "BSD") t]
-         ["Whitesmith" (cperl-set-style "Whitesmith") t]
-         ["Memorize Current" (cperl-set-style "Current") t]
-         ["Memorized" (cperl-set-style-back) cperl-old-style])
-        ("Micro-docs"
-         ["Tips" (describe-variable 'cperl-tips) t]
-         ["Problems" (describe-variable 'cperl-problems) t]
-         ["Speed" (describe-variable 'cperl-speed) t]
-         ["Praise" (describe-variable 'cperl-praise) t]
-         ["Faces" (describe-variable 'cperl-tips-faces) t]
-          ["CPerl mode" (describe-function 'cperl-mode) t]))))
-  (error nil))
+(easy-menu-define cperl-menu cperl-mode-map
+  "Menu for CPerl mode."
+  '("Perl"
+    ["Beginning of function" beginning-of-defun t]
+    ["End of function" end-of-defun t]
+    ["Mark function" mark-defun t]
+    ["Indent expression" cperl-indent-exp t]
+    ["Fill paragraph/comment" fill-paragraph t]
+    "----"
+    ["Line up a construction" cperl-lineup (use-region-p)]
+    ["Invert if/unless/while etc" cperl-invert-if-unless t]
+    ("Regexp"
+     ["Beautify" cperl-beautify-regexp
+      cperl-use-syntax-table-text-property]
+     ["Beautify one level deep" (cperl-beautify-regexp 1)
+      cperl-use-syntax-table-text-property]
+     ["Beautify a group" cperl-beautify-level
+      cperl-use-syntax-table-text-property]
+     ["Beautify a group one level deep" (cperl-beautify-level 1)
+      cperl-use-syntax-table-text-property]
+     ["Contract a group" cperl-contract-level
+      cperl-use-syntax-table-text-property]
+     ["Contract groups" cperl-contract-levels
+      cperl-use-syntax-table-text-property]
+     "----"
+     ["Find next interpolated" cperl-next-interpolated-REx
+      (next-single-property-change (point-min) 'REx-interpolated)]
+     ["Find next interpolated (no //o)"
+      cperl-next-interpolated-REx-0
+      (or (text-property-any (point-min) (point-max) 'REx-interpolated t)
+          (text-property-any (point-min) (point-max) 'REx-interpolated 1))]
+     ["Find next interpolated (neither //o nor whole-REx)"
+      cperl-next-interpolated-REx-1
+      (text-property-any (point-min) (point-max) 'REx-interpolated t)])
+    ["Insert spaces if needed to fix style" cperl-find-bad-style t]
+    ["Refresh \"hard\" constructions" cperl-find-pods-heres t]
+    "----"
+    ["Indent region" cperl-indent-region (use-region-p)]
+    ["Comment region" cperl-comment-region (use-region-p)]
+    ["Uncomment region" cperl-uncomment-region (use-region-p)]
+    "----"
+    ["Run" mode-compile (fboundp 'mode-compile)]
+    ["Kill" mode-compile-kill (and (fboundp 'mode-compile-kill)
+                                   (get-buffer "*compilation*"))]
+    ["Next error" next-error (get-buffer "*compilation*")]
+    ["Check syntax" cperl-check-syntax (fboundp 'mode-compile)]
+    "----"
+    ["Debugger" cperl-db t]
+    "----"
+    ("Tools"
+     ["Imenu" imenu (fboundp 'imenu)]
+     ["Imenu on Perl Info" cperl-imenu-on-info (featurep 'imenu)]
+     "----"
+     ["Ispell PODs" cperl-pod-spell
+      ;; Better not to update syntaxification here:
+      ;; debugging syntaxification can be broken by this???
+      (or
+       (get-text-property (point-min) 'in-pod)
+       (< (progn
+            (and cperl-syntaxify-for-menu
+                 (cperl-update-syntaxification (point-max)))
+            (next-single-property-change (point-min) 'in-pod nil (point-max)))
+          (point-max)))]
+     ["Ispell HERE-DOCs" cperl-here-doc-spell
+      (< (progn
+           (and cperl-syntaxify-for-menu
+                (cperl-update-syntaxification (point-max)))
+           (next-single-property-change (point-min) 'here-doc-group nil 
(point-max)))
+         (point-max))]
+     ["Narrow to this HERE-DOC" cperl-narrow-to-here-doc
+      (eq 'here-doc  (progn
+                       (and cperl-syntaxify-for-menu
+                            (cperl-update-syntaxification (point)))
+                       (get-text-property (point) 'syntax-type)))]
+     ["Select this HERE-DOC or POD section"
+      cperl-select-this-pod-or-here-doc
+      (memq (progn
+              (and cperl-syntaxify-for-menu
+                   (cperl-update-syntaxification (point)))
+              (get-text-property (point) 'syntax-type))
+            '(here-doc pod))]
+     "----"
+     ["CPerl pretty print (experimental)" cperl-ps-print
+      (fboundp 'ps-extend-face-list)]
+     "----"
+     ["Syntaxify region" cperl-find-pods-heres-region
+      (use-region-p)]
+     ["Profile syntaxification" cperl-time-fontification t]
+     ["Debug errors in delayed fontification" cperl-emulate-lazy-lock t]
+     ["Debug unwind for syntactic scan" cperl-toggle-set-debug-unwind t]
+     ["Debug backtrace on syntactic scan (BEWARE!!!)"
+      (cperl-toggle-set-debug-unwind nil t) t]
+     "----"
+     ["Class Hierarchy from TAGS" cperl-tags-hier-init t]
+     ;;["Update classes" (cperl-tags-hier-init t) tags-table-list]
+     ("Tags"
+      ;; ["Create tags for current file" cperl-etags t]
+      ;; ["Add tags for current file" (cperl-etags t) t]
+      ;; ["Create tags for Perl files in directory" (cperl-etags nil t) t]
+      ;; ["Add tags for Perl files in directory" (cperl-etags t t) t]
+      ;; ["Create tags for Perl files in (sub)directories"
+      ;;  (cperl-etags nil 'recursive) t]
+      ;; ["Add tags for Perl files in (sub)directories"
+      ;;  (cperl-etags t 'recursive) t])
+      ;; ;;? cperl-write-tags (&optional file erase recurse dir inbuffer)
+      ["Create tags for current file" (cperl-write-tags nil t) t]
+      ["Add tags for current file" (cperl-write-tags) t]
+      ["Create tags for Perl files in directory"
+       (cperl-write-tags nil t nil t) t]
+      ["Add tags for Perl files in directory"
+       (cperl-write-tags nil nil nil t) t]
+      ["Create tags for Perl files in (sub)directories"
+       (cperl-write-tags nil t t t) t]
+      ["Add tags for Perl files in (sub)directories"
+       (cperl-write-tags nil nil t t) t]))
+    ("Perl docs"
+     ["Define word at point" imenu-go-find-at-position
+      (fboundp 'imenu-go-find-at-position)]
+     ["Help on function" cperl-info-on-command t]
+     ["Help on function at point" cperl-info-on-current-command t]
+     ["Help on symbol at point" cperl-get-help t]
+     ["Perldoc" cperl-perldoc t]
+     ["Perldoc on word at point" cperl-perldoc-at-point t]
+     ["View manpage of POD in this file" cperl-build-manpage t]
+     ["Auto-help on" cperl-lazy-install
+      (not cperl-lazy-installed)]
+     ["Auto-help off" cperl-lazy-unstall
+      cperl-lazy-installed])
+    ("Toggle..."
+     ["Auto newline" cperl-toggle-auto-newline t]
+     ["Electric parens" cperl-toggle-electric t]
+     ["Electric keywords" cperl-toggle-abbrev t]
+     ["Fix whitespace on indent" cperl-toggle-construct-fix t]
+     ["Auto-help on Perl constructs" cperl-toggle-autohelp t]
+     ["Auto fill" auto-fill-mode t])
+    ("Indent styles..."
+     ["CPerl" (cperl-set-style "CPerl") t]
+     ["PBP" (cperl-set-style  "PBP") t]
+     ["PerlStyle" (cperl-set-style "PerlStyle") t]
+     ["GNU" (cperl-set-style "GNU") t]
+     ["C++" (cperl-set-style "C++") t]
+     ["K&R" (cperl-set-style "K&R") t]
+     ["BSD" (cperl-set-style "BSD") t]
+     ["Whitesmith" (cperl-set-style "Whitesmith") t]
+     ["Memorize Current" (cperl-set-style "Current") t]
+     ["Memorized" (cperl-set-style-back) cperl-old-style])
+    ("Micro-docs"
+     ["Tips" (describe-variable 'cperl-tips) t]
+     ["Problems" (describe-variable 'cperl-problems) t]
+     ["Speed" (describe-variable 'cperl-speed) t]
+     ["Praise" (describe-variable 'cperl-praise) t]
+     ["Faces" (describe-variable 'cperl-tips-faces) t]
+     ["CPerl mode" (describe-function 'cperl-mode) t])))
 
 (autoload 'c-macro-expand "cmacexp"
   "Display the result of expanding all C macros occurring in the region.
 The expansion is entirely correct because it uses the C preprocessor."
   t)
 
+
+;;; Perl Grammar Components
+;;
+;; The following regular expressions are building blocks for a
+;; minimalistic Perl grammar, to be used instead of individual (and
+;; not always consistent) literal regular expressions.
+
+(defconst cperl--basic-identifier-regexp
+  (rx (sequence (or alpha "_") (* (or word "_"))))
+  "A regular expression for the name of a \"basic\" Perl variable.
+Neither namespace separators nor sigils are included.  As is,
+this regular expression applies to labels,subroutine calls where
+the ampersand sigil is not required, and names of subroutine
+attributes.")
+
+(defconst cperl--label-regexp
+  (rx-to-string
+   `(sequence
+     symbol-start
+     (regexp ,cperl--basic-identifier-regexp)
+     (0+ space)
+     ":"))
+  "A regular expression for a Perl label.
+By convention, labels are uppercase alphabetics, but this isn't
+enforced.")
+
+(defconst cperl--normal-identifier-regexp
+  (rx-to-string
+   `(or
+     (sequence
+      (1+ (sequence
+           (opt (regexp ,cperl--basic-identifier-regexp))
+           "::"))
+      (opt (regexp ,cperl--basic-identifier-regexp)))
+     (regexp ,cperl--basic-identifier-regexp)))
+  "A regular expression for a Perl variable name with optional namespace.
+Examples are `foo`, `Some::Module::VERSION`, and `::` (yes, that
+is a legal variable name).")
+
+(defconst cperl--special-identifier-regexp
+  (rx-to-string
+   `(or
+     (1+ digit)                          ; $0, $1, $2, ...
+     (sequence "^" (any "A-Z" "]^_?\\")) ; $^V
+     (sequence "{" (0+ space)            ; ${^MATCH}
+               "^" (any "A-Z" "]^_?\\")
+               (0+ (any "A-Z" "_" digit))
+               (0+ space) "}")
+     (in "!\"$%&'()+,-./:;<=>?@\\]^_`|~")))   ; $., $|, $", ... but not $^ or 
${
+  "The list of Perl \"punctuation\" variables, as listed in perlvar.")
+
+(defconst cperl--ws-regexp
+  (rx-to-string
+   '(or space "\n"))
+  "Regular expression for a single whitespace in Perl.")
+
+(defconst cperl--eol-comment-regexp
+  (rx-to-string
+   '(sequence "#" (0+ (not (in "\n"))) "\n"))
+  "Regular expression for a single end-of-line comment in Perl")
+
+(defconst cperl--ws-or-comment-regexp
+  (rx-to-string
+   `(1+
+     (or
+      (regexp ,cperl--ws-regexp)
+      (regexp ,cperl--eol-comment-regexp))))
+  "Regular expression for a sequence of whitespace and comments in Perl.")
+
+(defconst cperl--ows-regexp
+  (rx-to-string
+   `(opt (regexp ,cperl--ws-or-comment-regexp)))
+  "Regular expression for optional whitespaces or comments in Perl")
+
+(defconst cperl--version-regexp
+  (rx-to-string
+   `(or
+     (sequence (opt "v")
+              (>= 2 (sequence (1+ digit) "."))
+              (1+ digit)
+              (opt (sequence "_" (1+ word))))
+     (sequence (1+ digit)
+              (opt (sequence "." (1+ digit)))
+              (opt (sequence "_" (1+ word))))))
+  "A sequence for recommended version number schemes in Perl.")
+
+(defconst cperl--package-regexp
+  (rx-to-string
+   `(sequence
+     "package" ; FIXME: the "class" and "role" keywords need to be
+               ; recognized soon...ish.
+     (regexp ,cperl--ws-or-comment-regexp)
+     (group (regexp ,cperl--normal-identifier-regexp))
+     (opt
+      (sequence
+       (regexp ,cperl--ws-or-comment-regexp)
+       (group (regexp ,cperl--version-regexp))))))
+  "A regular expression for package NAME VERSION in Perl.
+Contains two groups for the package name and version.")
+
+(defconst cperl--package-for-imenu-regexp
+  (rx-to-string
+   `(sequence
+     (regexp ,cperl--package-regexp)
+     (regexp ,cperl--ows-regexp)
+     (group (or ";" "{"))))
+  "A regular expression to collect package names for `imenu`.
+Catches \"package NAME;\", \"package NAME VERSION;\", \"package
+NAME BLOCK\" and \"package NAME VERSION BLOCK.\" Contains three
+groups: Two from `cperl--package-regexp` for the package name and
+version, and a third to detect \"package BLOCK\" syntax.")
+
+(defconst cperl--sub-name-regexp
+  (rx-to-string
+   `(sequence
+     (optional (sequence (group (or "my" "state" "our"))
+                        (regexp ,cperl--ws-or-comment-regexp)))
+     "sub" ; FIXME: the "method" and maybe "fun" keywords need to be
+           ; recognized soon...ish.
+     (regexp ,cperl--ws-or-comment-regexp)
+     (group (regexp ,cperl--normal-identifier-regexp))))
+  "A regular expression to detect a subroutine start.
+Contains two groups: One for to distinguish lexical from
+\"normal\" subroutines and one for the subroutine name.")
+
+(defconst cperl--pod-heading-regexp
+  (rx-to-string
+   `(sequence
+     line-start "=head"
+     (group (in "1-4"))
+     (1+ (in " \t"))
+     (group (1+ (not (in "\n"))))
+     line-end)) ; that line-end seems to be redundant?
+  "A regular expression to detect a POD heading.
+Contains two groups: One for the heading level, and one for the
+heading text.")
+
+(defconst cperl--imenu-entries-regexp
+  (rx-to-string
+   `(or
+     (regexp ,cperl--package-for-imenu-regexp) ; 1..3
+     (regexp ,cperl--sub-name-regexp)         ; 4..5
+     (regexp ,cperl--pod-heading-regexp)))     ; 6..7
+  "A regular expression to collect stuff that goes into the `imenu` index.
+Covers packages, subroutines, and POD headings.")
+
+
 ;; These two must be unwound, otherwise take exponential time
 (defconst cperl-maybe-white-and-comment-rex "[ \t\n]*\\(#[^\n]*\n[ \t\n]*\\)*"
 "Regular expression to match optional whitespace with interspersed comments.
@@ -1268,8 +1354,7 @@ Should contain exactly one group.")
 Should contain exactly one group.")
 
 
-;; Is incorporated in `cperl-imenu--function-name-regexp-perl'
-;; `cperl-outline-regexp', `defun-prompt-regexp'.
+;; Is incorporated in `cperl-outline-regexp', `defun-prompt-regexp'.
 ;; Details of groups in this may be used in several functions; see comments
 ;; near mentioned above variable(s)...
 ;; sub($$):lvalue{}  sub:lvalue{} Both allowed...
@@ -1396,13 +1481,15 @@ the last)."
 (defvar cperl-font-lock-multiline nil)
 (defvar cperl-font-locking nil)
 
-;; NB as it stands the code in cperl-mode assumes this only has one
-;; element. Since XEmacs 19 support has been dropped, this could all be 
simplified.
-(defvar cperl-compilation-error-regexp-alist
+(defvar cperl-compilation-error-regexp-list
   ;; This look like a paranoiac regexp: could anybody find a better one? 
(which WORKS).
-  '(("^[^\n]* \\(file\\|at\\) \\([^ \t\n]+\\) [^\n]*line \\([0-9]+\\)[\\., \n]"
-     2 3))
-  "Alist that specifies how to match errors in perl output.")
+  '("^[^\n]* \\(file\\|at\\) \\([^ \t\n]+\\) [^\n]*line \\([0-9]+\\)[\\., \n]"
+    2 3)
+  "List that specifies how to match errors in Perl output.")
+
+(defvar cperl-compilation-error-regexp-alist)
+(make-obsolete-variable 'cperl-compilation-error-regexp-alist
+                        'cperl-compilation-error-regexp-list "28.1")
 
 (defvar compilation-error-regexp-alist)
 
@@ -1512,8 +1599,7 @@ span the needed amount of lines.
 
 Variables `cperl-pod-here-scan', `cperl-pod-here-fontify',
 `cperl-pod-face', `cperl-pod-head-face' control processing of POD and
-here-docs sections.  With capable Emaxen results of scan are used
-for indentation too, otherwise they are used for highlighting only.
+here-docs sections.  Results of scan are used for indentation too.
 
 Variables controlling indentation style:
  `cperl-tab-always-indent'
@@ -1639,19 +1725,18 @@ or as help on variables `cperl-tips', `cperl-problems',
   (setq-local imenu-sort-function nil)
   (setq-local vc-rcs-header cperl-vc-rcs-header)
   (setq-local vc-sccs-header cperl-vc-sccs-header)
-  (cond ((boundp 'compilation-error-regexp-alist-alist);; xemacs 20.x
-         (setq-local compilation-error-regexp-alist-alist
-                     (cons (cons 'cperl (car 
cperl-compilation-error-regexp-alist))
-                           compilation-error-regexp-alist-alist))
-        (if (fboundp 'compilation-build-compilation-error-regexp-alist)
-            (let ((f 'compilation-build-compilation-error-regexp-alist))
-              (funcall f))
-          (make-local-variable 'compilation-error-regexp-alist)
-          (push 'cperl compilation-error-regexp-alist)))
-       ((boundp 'compilation-error-regexp-alist);; xemacs 19.x
-         (setq-local compilation-error-regexp-alist
-                     (append cperl-compilation-error-regexp-alist
-                             compilation-error-regexp-alist))))
+  (when (boundp 'compilation-error-regexp-alist-alist)
+    ;; The let here is just a compatibility kludge for the obsolete
+    ;; variable `cperl-compilation-error-regexp-alist'.  It can be removed
+    ;; when that variable is removed.
+    (let ((regexp (if (boundp 'cperl-compilation-error-regexp-alist)
+                           (car cperl-compilation-error-regexp-alist)
+                         cperl-compilation-error-regexp-list)))
+      (setq-local compilation-error-regexp-alist-alist
+                  (cons (cons 'cperl regexp)
+                        compilation-error-regexp-alist-alist)))
+    (make-local-variable 'compilation-error-regexp-alist)
+    (push 'cperl compilation-error-regexp-alist))
   (setq-local font-lock-defaults
               '((cperl-load-font-lock-keywords
                  cperl-load-font-lock-keywords-1
@@ -1665,12 +1750,12 @@ or as help on variables `cperl-tips', `cperl-problems',
     (setq-local syntax-propertize-function
                 (lambda (start end)
                   (goto-char start)
-                  ;; Even if cperl-fontify-syntaxically has already gone
+                  ;; Even if cperl-fontify-syntactically has already gone
                   ;; beyond `start', syntax-propertize has just removed
                   ;; syntax-table properties between start and end, so we have
                   ;; to re-apply them.
                   (setq cperl-syntax-done-to start)
-                  (cperl-fontify-syntaxically end))))
+                  (cperl-fontify-syntactically end))))
   (setq cperl-font-lock-multiline t) ; Not localized...
   (setq-local font-lock-multiline t)
   (setq-local font-lock-fontify-region-function
@@ -3842,21 +3927,24 @@ the sections using `cperl-pod-head-face', 
`cperl-pod-face',
                      bb (char-after (1- (match-beginning b1))) ; tmp holder
                      ;; bb == "Not a stringy"
                      bb (if (eq b1 10) ; user variables/whatever
-                            (and (memq bb (append "$@%*#_:-&>" nil)) ; $#y)
-                                 (cond ((eq bb ?-) (eq c ?s)) ; -s file test
-                                       ((eq bb ?\:) ; $opt::s
-                                        (eq (char-after
-                                             (- (match-beginning b1) 2))
-                                            ?\:))
-                                       ((eq bb ?\>) ; $foo->s
-                                        (eq (char-after
-                                             (- (match-beginning b1) 2))
-                                            ?\-))
-                                       ((eq bb ?\&)
-                                        (not (eq (char-after ; &&m/blah/
-                                                  (- (match-beginning b1) 2))
-                                                 ?\&)))
-                                       (t t)))
+                             (or
+                              ; false positive: "y_" has no word boundary
+                              (save-match-data (looking-at "_"))
+                             (and (memq bb (append "$@%*#_:-&>" nil)) ; $#y)
+                                  (cond ((eq bb ?-) (eq c ?s)) ; -s file test
+                                        ((eq bb ?\:) ; $opt::s
+                                         (eq (char-after
+                                              (- (match-beginning b1) 2))
+                                             ?\:))
+                                        ((eq bb ?\>) ; $foo->s
+                                         (eq (char-after
+                                              (- (match-beginning b1) 2))
+                                             ?\-))
+                                        ((eq bb ?\&)
+                                         (not (eq (char-after ; &&m/blah/
+                                                   (- (match-beginning b1) 2))
+                                                  ?\&)))
+                                        (t t))))
                           ;; <file> or <$file>
                           (and (eq c ?\<)
                                ;; Do not stringify <FH>, <$fh> :
@@ -5188,117 +5276,80 @@ indentation and initial hashes.  Behaves usually 
outside of comment."
          ;; Previous space could have gone:
          (or (memq (preceding-char) '(?\s ?\t)) (insert " "))))))
 
-(defun cperl-imenu-addback (lst &optional isback name)
-  ;; We suppose that the lst is a DAG, unless the first element only
-  ;; loops back, and ISBACK is set.  Thus this function cannot be
-  ;; applied twice without ISBACK set.
-  (cond ((not cperl-imenu-addback) lst)
-       (t
-        (or name
-            (setq name "+++BACK+++"))
-        (mapc (lambda (elt)
-                (if (and (listp elt) (listp (cdr elt)))
-                    (progn
-                      ;; In the other order it goes up
-                      ;; one level only ;-(
-                      (setcdr elt (cons (cons name lst)
-                                        (cdr elt)))
-                      (cperl-imenu-addback (cdr elt) t name))))
-              (if isback (cdr lst) lst))
-        lst)))
-
-(defun cperl-imenu--create-perl-index (&optional regexp)
-  (require 'imenu)                     ; May be called from TAGS creator
-  (let ((index-alist '()) (index-pack-alist '()) (index-pod-alist '())
+(defun cperl-imenu--create-perl-index ()
+  "Implement `imenu-create-index-function` for CPerl mode.
+This function relies on syntaxification to exclude lines which
+look like declarations but actually are part of a string, a
+comment, or POD."
+  (interactive) ; We'll remove that at some point
+  (goto-char (point-min))
+  (cperl-update-syntaxification (point-max))
+  (let ((case-fold-search nil)
+       (index-alist '())
+       (index-package-alist '())
+       (index-pod-alist '())
+       (index-sub-alist '())
        (index-unsorted-alist '())
-       (index-meth-alist '()) meth
-       packages ends-ranges p marker is-proto
-        is-pack index index1 name (end-range 0) package)
-    (goto-char (point-min))
-    (cperl-update-syntaxification (point-max))
-    ;; Search for the function
-    (progn ;;save-match-data
-      (while (re-search-forward
-             (or regexp cperl-imenu--function-name-regexp-perl)
-             nil t)
-       ;; 2=package-group, 5=package-name 8=sub-name
+       (package-stack '())                 ; for package NAME BLOCK
+       (current-package "(main)")
+       (current-package-end (point-max)))   ; end of package scope
+    ;; collect index entries
+    (while (re-search-forward cperl--imenu-entries-regexp nil t)
+      ;; First, check whether we have left the scope of previously
+      ;; recorded packages, and if so, eliminate them from the stack.
+      (while (< current-package-end (point))
+       (setq current-package (pop package-stack))
+       (setq current-package-end (pop package-stack)))
+      (let ((state (syntax-ppss))
+           name marker) ; for the "current" entry
        (cond
-        ((and                          ; Skip some noise if building tags
-          (match-beginning 5)          ; package name
-          ;;(eq (char-after (match-beginning 2)) ?p) ; package
-          (not (save-match-data
-                 (looking-at "[ \t\n]*;")))) ; Plain text word 'package'
-         nil)
-        ((and
-          (or (match-beginning 2)
-              (match-beginning 8))             ; package or sub
-          ;; Skip if quoted (will not skip multi-line ''-strings :-():
-          (null (get-text-property (match-beginning 1) 'syntax-table))
-          (null (get-text-property (match-beginning 1) 'syntax-type))
-          (null (get-text-property (match-beginning 1) 'in-pod)))
-         (setq is-pack (match-beginning 2))
-         ;; (if (looking-at "([^()]*)[ \t\n\f]*")
-         ;;    (goto-char (match-end 0)))      ; Messes what follows
-         (setq meth nil
-               p (point))
-         (while (and ends-ranges (>= p (car ends-ranges)))
-           ;; delete obsolete entries
-           (setq ends-ranges (cdr ends-ranges) packages (cdr packages)))
-         (setq package (or (car packages) "")
-               end-range (or (car ends-ranges) 0))
-         (if is-pack                   ; doing "package"
-             (progn
-               (if (match-beginning 5) ; named package
-                   (setq name (buffer-substring (match-beginning 5)
-                                                (match-end 5))
-                         name (progn
-                                (set-text-properties 0 (length name) nil name)
-                                name)
-                         package (concat name "::")
-                         name (concat "package " name))
-                 ;; Support nameless packages
-                 (setq name "package;" package ""))
-               (setq end-range
-                     (save-excursion
-                       (parse-partial-sexp (point) (point-max) -1) (point))
-                     ends-ranges (cons end-range ends-ranges)
-                     packages (cons package packages)))
-           (setq is-proto
-                 (or (eq (following-char) ?\;)
-                     (eq 0 (get-text-property (point) 'attrib-group)))))
-         ;; Skip this function name if it is a prototype declaration.
-         (if (and is-proto (not is-pack)) nil
-           (or is-pack
-               (setq name
-                     (buffer-substring (match-beginning 8) (match-end 8)))
-               (set-text-properties 0 (length name) nil name))
-           (setq marker (make-marker))
-           (set-marker marker (match-end (if is-pack 2 8)))
-           (cond (is-pack nil)
-                 ((string-match "[:']" name)
-                  (setq meth t))
-                 ((> p end-range) nil)
-                 (t
-                  (setq name (concat package name) meth t)))
-           (setq index (cons name marker))
-           (if is-pack
-               (push index index-pack-alist)
-             (push index index-alist))
-           (if meth (push index index-meth-alist))
-           (push index index-unsorted-alist)))
-        ((match-beginning 16)          ; POD section
-         (setq name (buffer-substring (match-beginning 17) (match-end 17))
-               marker (make-marker))
-         (set-marker marker (match-beginning 17))
-         (set-text-properties 0 (length name) nil name)
-         (setq name (concat (make-string
-                             (* 3 (- (char-after (match-beginning 16)) ?1))
-                             ?\ )
-                            name)
-               index (cons name marker))
-         (setq index1 (cons (concat "=" name) (cdr index)))
-         (push index index-pod-alist)
-         (push index1 index-unsorted-alist)))))
+        ((nth 3 state) nil)            ; matched in a string, so skip
+        ((match-string 1)              ; found a package name!
+         (unless (nth 4 state)         ; skip if in a comment
+           (setq name (match-string-no-properties 1)
+                 marker (copy-marker (match-end 1)))
+           (if  (string= (match-string 3) ";")
+               (setq current-package name)  ; package NAME;
+             ;; No semicolon, therefore we have: package NAME BLOCK.
+             ;; Stash the current package, because we need to restore
+             ;; it after the end of BLOCK.
+             (push current-package-end package-stack)
+             (push current-package package-stack)
+             ;; record the current name and its scope
+             (setq current-package name)
+             (setq current-package-end (save-excursion
+                                         (goto-char (match-beginning 3))
+                                         (forward-sexp)
+                                         (point)))
+           (push (cons name marker) index-package-alist)
+           (push (cons (concat "package " name) marker) 
index-unsorted-alist))))
+        ((match-string 5)              ; found a sub name!
+         (unless (nth 4 state)         ; skip if in a comment
+           (setq name (match-string-no-properties 5)
+                 marker (copy-marker (match-end 5)))
+           ;; Qualify the sub name with the package if it doesn't
+           ;; already have one, and if it isn't lexically scoped.
+           ;; "my" and "state" subs are lexically scoped, but "our"
+           ;; are just lexical aliases to package subs.
+           (if (and (null (string-match "::" name))
+                    (or (null (match-string 4))
+                        (string-equal (match-string 4) "our")))
+             (setq name (concat current-package "::" name)))
+           (let ((index (cons name marker)))
+             (push index index-alist)
+             (push index index-sub-alist)
+             (push index index-unsorted-alist))))
+        ((match-string 6)              ; found a POD heading!
+         (when (get-text-property (match-beginning 6) 'in-pod)
+           (setq name (concat (make-string
+                               (* 3 (- (char-after (match-beginning 6)) ?1))
+                               ?\ )
+                              (match-string-no-properties 7))
+                 marker (copy-marker (match-beginning 7)))
+           (push (cons name marker) index-pod-alist)
+           (push (cons (concat "=" name) marker) index-unsorted-alist)))
+        (t (error "Unidentified match: %s" (match-string 0))))))
+    ;; Now format the collected stuff
     (setq index-alist
          (if (default-value 'imenu-sort-function)
              (sort index-alist (default-value 'imenu-sort-function))
@@ -5307,14 +5358,14 @@ indentation and initial hashes.  Behaves usually 
outside of comment."
         (push (cons "+POD headers+..."
                     (nreverse index-pod-alist))
               index-alist))
-    (and (or index-pack-alist index-meth-alist)
-        (let ((lst index-pack-alist) hier-list pack elt group name)
-          ;; Remove "package ", reverse and uniquify.
+    (and (or index-package-alist index-sub-alist)
+        (let ((lst index-package-alist) hier-list pack elt group name)
+          ;; reverse and uniquify.
           (while lst
-            (setq elt (car lst) lst (cdr lst) name (substring (car elt) 8))
+            (setq elt (car lst) lst (cdr lst) name (car elt))
             (if (assoc name hier-list) nil
               (setq hier-list (cons (cons name (cdr elt)) hier-list))))
-          (setq lst index-meth-alist)
+          (setq lst index-sub-alist)
           (while lst
             (setq elt (car lst) lst (cdr lst))
             (cond ((string-match "\\(::\\|'\\)[_a-zA-Z0-9]+$" (car elt))
@@ -5342,17 +5393,18 @@ indentation and initial hashes.  Behaves usually 
outside of comment."
           (push (cons "+Hierarchy+..."
                       hier-list)
                 index-alist)))
-    (and index-pack-alist
+    (and index-package-alist
         (push (cons "+Packages+..."
-                    (nreverse index-pack-alist))
+                    (nreverse index-package-alist))
               index-alist))
-    (and (or index-pack-alist index-pod-alist
+    (and (or index-package-alist index-pod-alist
             (default-value 'imenu-sort-function))
         index-unsorted-alist
         (push (cons "+Unsorted List+..."
                     (nreverse index-unsorted-alist))
               index-alist))
-    (cperl-imenu-addback index-alist)))
+    ;; Finally, return the whole collection
+    index-alist))
 
 
 ;; Suggested by Mark A. Hershberger
@@ -5415,120 +5467,79 @@ indentation and initial hashes.  Behaves usually 
outside of comment."
            (cons
             (concat
              "\\(^\\|[^$@%&\\]\\)\\<\\("
-              ;; FIXME: Use regexp-opt.
-             (mapconcat
-              #'identity
+              (regexp-opt
               (append
                 cperl-sub-keywords
                 '("if" "until" "while" "elsif" "else"
-                 "given" "when" "default" "break"
-                 "unless" "for"
-                 "try" "catch" "finally"
-                "foreach" "continue" "exit" "die" "last" "goto" "next"
-                "redo" "return" "local" "exec"
-                 "do" "dump"
-                 "use" "our"
-                "require" "package" "eval" "evalbytes" "my" "state"
-                 "BEGIN" "END" "CHECK" "INIT" "UNITCHECK"))
-              "\\|")                   ; Flow control
+                  "given" "when" "default" "break"
+                  "unless" "for"
+                  "try" "catch" "finally"
+                  "foreach" "continue" "exit" "die" "last" "goto" "next"
+                  "redo" "return" "local" "exec"
+                  "do" "dump"
+                  "use" "our"
+                  "require" "package" "eval" "evalbytes" "my" "state"
+                  "BEGIN" "END" "CHECK" "INIT" "UNITCHECK"))) ; Flow control
              "\\)\\>") 2)              ; was "\\)[ \n\t;():,|&]"
                                        ; In what follows we use `type' style
                                        ; for overwritable builtins
            (list
             (concat
              "\\(^\\|[^$@%&\\]\\)\\<\\("
-              ;; FIXME: Use regexp-opt.
-             ;; "CORE" "__FILE__" "__LINE__" "__SUB__" "abs" "accept" "alarm"
-             ;; "and" "atan2" "bind" "binmode" "bless" "caller"
-             ;; "chdir" "chmod" "chown" "chr" "chroot" "close"
-             ;; "closedir" "cmp" "connect" "continue" "cos" "crypt"
-             ;; "dbmclose" "dbmopen" "die" "dump" "endgrent"
-             ;; "endhostent" "endnetent" "endprotoent" "endpwent"
-             ;; "endservent" "eof" "eq" "exec" "exit" "exp" "fc" "fcntl"
-             ;; "fileno" "flock" "fork" "formline" "ge" "getc"
-             ;; "getgrent" "getgrgid" "getgrnam" "gethostbyaddr"
-             ;; "gethostbyname" "gethostent" "getlogin"
-             ;; "getnetbyaddr" "getnetbyname" "getnetent"
-             ;; "getpeername" "getpgrp" "getppid" "getpriority"
-             ;; "getprotobyname" "getprotobynumber" "getprotoent"
-             ;; "getpwent" "getpwnam" "getpwuid" "getservbyname"
-             ;; "getservbyport" "getservent" "getsockname"
-             ;; "getsockopt" "glob" "gmtime" "gt" "hex" "index" "int"
-             ;; "ioctl" "join" "kill" "lc" "lcfirst" "le" "length"
-             ;; "link" "listen" "localtime" "lock" "log" "lstat" "lt"
-             ;; "mkdir" "msgctl" "msgget" "msgrcv" "msgsnd" "ne"
-             ;; "not" "oct" "open" "opendir" "or" "ord" "pack" "pipe"
-             ;; "quotemeta" "rand" "read" "readdir" "readline"
-             ;; "readlink" "readpipe" "recv" "ref" "rename" "require"
-             ;; "reset" "reverse" "rewinddir" "rindex" "rmdir" "seek"
-             ;; "seekdir" "select" "semctl" "semget" "semop" "send"
-             ;; "setgrent" "sethostent" "setnetent" "setpgrp"
-             ;; "setpriority" "setprotoent" "setpwent" "setservent"
-             ;; "setsockopt" "shmctl" "shmget" "shmread" "shmwrite"
-             ;; "shutdown" "sin" "sleep" "socket" "socketpair"
-             ;; "sprintf" "sqrt" "srand" "stat" "substr" "symlink"
-             ;; "syscall" "sysopen" "sysread" "sysseek" "system" "syswrite" 
"tell"
-             ;; "telldir" "time" "times" "truncate" "uc" "ucfirst"
-             ;; "umask" "unlink" "unpack" "utime" "values" "vec"
-             ;; "wait" "waitpid" "wantarray" "warn" "write" "x" "xor"
-             "a\\(bs\\|ccept\\|tan2\\|larm\\|nd\\)\\|"
-             "b\\(in\\(d\\|mode\\)\\|less\\)\\|"
-             "c\\(h\\(r\\(\\|oot\\)\\|dir\\|mod\\|own\\)\\|aller\\|rypt\\|"
-             "lose\\(\\|dir\\)\\|mp\\|o\\(s\\|n\\(tinue\\|nect\\)\\)\\)\\|"
-             "CORE\\|d\\(ie\\|bm\\(close\\|open\\)\\|ump\\)\\|"
-             "e\\(x\\(p\\|it\\|ec\\)\\|q\\|nd\\(p\\(rotoent\\|went\\)\\|"
-             "hostent\\|servent\\|netent\\|grent\\)\\|of\\)\\|"
-             "f\\(ileno\\|c\\(ntl\\)?\\|lock\\|or\\(k\\|mline\\)\\)\\|"
-             "g\\(t\\|lob\\|mtime\\|e\\(\\|t\\(p\\(pid\\|r\\(iority\\|"
-             "oto\\(byn\\(ame\\|umber\\)\\|ent\\)\\)\\|eername\\|w"
-             "\\(uid\\|ent\\|nam\\)\\|grp\\)\\|host\\(by\\(addr\\|name\\)\\|"
-             "ent\\)\\|s\\(erv\\(by\\(port\\|name\\)\\|ent\\)\\|"
-             
"ock\\(name\\|opt\\)\\)\\|c\\|login\\|net\\(by\\(addr\\|name\\)\\|"
-             "ent\\)\\|gr\\(ent\\|nam\\|gid\\)\\)\\)\\)\\|"
-             "hex\\|i\\(n\\(t\\|dex\\)\\|octl\\)\\|join\\|kill\\|"
-             "l\\(i\\(sten\\|nk\\)\\|stat\\|c\\(\\|first\\)\\|t\\|e"
-             
"\\(\\|ngth\\)\\|o\\(c\\(altime\\|k\\)\\|g\\)\\)\\|m\\(sg\\(rcv\\|snd\\|"
-             "ctl\\|get\\)\\|kdir\\)\\|n\\(e\\|ot\\)\\|o\\(pen\\(\\|dir\\)\\|"
-             "r\\(\\|d\\)\\|ct\\)\\|p\\(ipe\\|ack\\)\\|quotemeta\\|"
-             "r\\(index\\|and\\|mdir\\|e\\(quire\\|ad\\(pipe\\|\\|lin"
-             "\\(k\\|e\\)\\|dir\\)\\|set\\|cv\\|verse\\|f\\|winddir\\|name"
-             "\\)\\)\\|s\\(printf\\|qrt\\|rand\\|tat\\|ubstr\\|e\\(t\\(p\\(r"
-             "\\(iority\\|otoent\\)\\|went\\|grp\\)\\|hostent\\|s\\(ervent\\|"
-             "ockopt\\)\\|netent\\|grent\\)\\|ek\\(\\|dir\\)\\|lect\\|"
-             "m\\(ctl\\|op\\|get\\)\\|nd\\)\\|h\\(utdown\\|m\\(read\\|ctl\\|"
-             
"write\\|get\\)\\)\\|y\\(s\\(read\\|call\\|open\\|tem\\|write\\|seek\\)\\|"
-             "mlink\\)\\|in\\|leep\\|ocket\\(pair\\|\\)\\)\\|t\\(runcate\\|"
-             "ell\\(\\|dir\\)\\|ime\\(\\|s\\)\\)\\|u\\(c\\(\\|first\\)\\|"
-             "time\\|mask\\|n\\(pack\\|link\\)\\)\\|v\\(alues\\|ec\\)\\|"
-             "w\\(a\\(rn\\|it\\(pid\\|\\)\\|ntarray\\)\\|rite\\)\\|"
-             "x\\(\\|or\\)\\|__\\(FILE\\|LINE\\|PACKAGE\\|SUB\\)__"
-             "\\)\\>") 2 'font-lock-type-face)
+              (regexp-opt
+               '("CORE" "__FILE__" "__LINE__" "__SUB__" "__PACKAGE__"
+                 "abs" "accept" "alarm" "and" "atan2"
+                 "bind" "binmode" "bless" "caller"
+                 "chdir" "chmod" "chown" "chr" "chroot" "close"
+                 "closedir" "cmp" "connect" "continue" "cos" "crypt"
+                 "dbmclose" "dbmopen" "die" "dump" "endgrent"
+                 "endhostent" "endnetent" "endprotoent" "endpwent"
+                 "endservent" "eof" "eq" "exec" "exit" "exp" "fc" "fcntl"
+                 "fileno" "flock" "fork" "formline" "ge" "getc"
+                 "getgrent" "getgrgid" "getgrnam" "gethostbyaddr"
+                 "gethostbyname" "gethostent" "getlogin"
+                 "getnetbyaddr" "getnetbyname" "getnetent"
+                 "getpeername" "getpgrp" "getppid" "getpriority"
+                 "getprotobyname" "getprotobynumber" "getprotoent"
+                 "getpwent" "getpwnam" "getpwuid" "getservbyname"
+                 "getservbyport" "getservent" "getsockname"
+                 "getsockopt" "glob" "gmtime" "gt" "hex" "index" "int"
+                 "ioctl" "join" "kill" "lc" "lcfirst" "le" "length"
+                 "link" "listen" "localtime" "lock" "log" "lstat" "lt"
+                 "mkdir" "msgctl" "msgget" "msgrcv" "msgsnd" "ne"
+                 "not" "oct" "open" "opendir" "or" "ord" "pack" "pipe"
+                 "quotemeta" "rand" "read" "readdir" "readline"
+                 "readlink" "readpipe" "recv" "ref" "rename" "require"
+                 "reset" "reverse" "rewinddir" "rindex" "rmdir" "seek"
+                 "seekdir" "select" "semctl" "semget" "semop" "send"
+                 "setgrent" "sethostent" "setnetent" "setpgrp"
+                 "setpriority" "setprotoent" "setpwent" "setservent"
+                 "setsockopt" "shmctl" "shmget" "shmread" "shmwrite"
+                 "shutdown" "sin" "sleep" "socket" "socketpair"
+                 "sprintf" "sqrt" "srand" "stat" "substr" "symlink"
+                 "syscall" "sysopen" "sysread" "sysseek" "system" "syswrite" 
"tell"
+                 "telldir" "time" "times" "truncate" "uc" "ucfirst"
+                 "umask" "unlink" "unpack" "utime" "values" "vec"
+                 "wait" "waitpid" "wantarray" "warn" "write" "x" "xor"))
+              "\\)\\>")
+             2 'font-lock-type-face)
            ;; In what follows we use `other' style
            ;; for nonoverwritable builtins
-           ;; Somehow 's', 'm' are not auto-generated???
            (list
             (concat
              "\\(^\\|[^$@%&\\]\\)\\<\\("
-             ;; "AUTOLOAD" "BEGIN" "CHECK" "DESTROY" "END" "INIT" "UNITCHECK" 
"__END__" "chomp"
-             ;; "break" "chop" "default" "defined" "delete" "do" "each" "else" 
"elsif"
-             ;; "eval" "evalbytes" "exists" "for" "foreach" "format" "given" 
"goto"
-             ;; "grep" "if" "keys" "last" "local" "map" "my" "next"
-             ;; "no" "our" "package" "pop" "pos" "print" "printf" "prototype" 
"push"
-             ;; "q" "qq" "qw" "qx" "redo" "return" "say" "scalar" "shift"
-             ;; "sort" "splice" "split" "state" "study" "sub" "tie" "tr"
-             ;; "undef" "unless" "unshift" "untie" "until" "use"
-             ;; "when" "while" "y"
-             
"AUTOLOAD\\|BEGIN\\|\\(UNIT\\)?CHECK\\|break\\|c\\(atch\\|ho\\(p\\|mp\\)\\)\\|d\\(e\\(f\\(inally\\|ault\\|ined\\)\\|lete\\)\\|"
-             
"o\\)\\|DESTROY\\|e\\(ach\\|val\\(bytes\\)?\\|xists\\|ls\\(e\\|if\\)\\)\\|"
-             
"END\\|for\\(\\|each\\|mat\\)\\|g\\(iven\\|rep\\|oto\\)\\|INIT\\|if\\|keys\\|"
-             "l\\(ast\\|ocal\\)\\|m\\(ap\\|y\\)\\|n\\(ext\\|o\\)\\|our\\|"
-             
"p\\(ackage\\|rototype\\|rint\\(\\|f\\)\\|ush\\|o\\(p\\|s\\)\\)\\|"
-             
"q\\(\\|q\\|w\\|x\\|r\\)\\|re\\(turn\\|do\\)\\|s\\(ay\\|pli\\(ce\\|t\\)\\|"
-             
"calar\\|t\\(ate\\|udy\\)\\|ub\\|hift\\|ort\\)\\|t\\(ry?\\|ied?\\)\\|"
-             "u\\(se\\|n\\(shift\\|ti\\(l\\|e\\)\\|def\\|less\\)\\)\\|"
-             "wh\\(en\\|ile\\)\\|y\\|__\\(END\\|DATA\\)__" ;__DATA__ added 
manually
-             "\\|[sm]"                 ; Added manually
-             "\\)\\>")
+              (regexp-opt
+               '("AUTOLOAD" "BEGIN" "CHECK" "DESTROY" "END" "INIT" "UNITCHECK"
+                 "__END__" "__DATA__" "break" "catch" "chomp" "chop" "default"
+                 "defined" "delete" "do" "each" "else" "elsif" "eval"
+                 "evalbytes" "exists" "finally" "for" "foreach" "format" 
"given"
+                 "goto" "grep" "if" "keys" "last" "local" "m" "map" "my" "next"
+                 "no" "our" "package" "pop" "pos" "print" "printf" "prototype"
+                 "push" "q" "qq" "qr" "qw" "qx" "redo" "return" "s" "say" 
"scalar"
+                 "shift" "sort" "splice" "split" "state" "study" "sub" "tie"
+                 "tied" "tr" "try" "undef" "unless" "unshift" "untie" "until"
+                 "use" "when" "while" "y"))
+              "\\)\\>")
             2 ''cperl-nonoverridable-face) ; unbound as var, so: doubly quoted
            ;;          (mapconcat #'identity
            ;;                     '("#endif" "#else" "#ifdef" "#ifndef" "#if"
@@ -6694,9 +6705,9 @@ One may build such TAGS files from CPerl mode menu."
                        (or (nthcdr 2 elt)
                            ;; Only in one file
                            (setcdr elt (cdr (nth 1 elt))))))
-           to l1 l2 l3)
+           to) ;; l1 l2 l3
        ;; (setq cperl-hierarchy '(() () ())) ; Would write into '() later!
-       (setq cperl-hierarchy (list l1 l2 l3))
+       (setq cperl-hierarchy (list () () ())) ;; (list l1 l2 l3)
        (or tags-table-list
            (call-interactively 'visit-tags-table))
        (mapc
@@ -6713,9 +6724,7 @@ One may build such TAGS files from CPerl mode menu."
        (cperl-tags-treeify to 1)
        (setcar (nthcdr 2 cperl-hierarchy)
                (cperl-menu-to-keymap (cons '("+++UPDATE+++" . -999) (cdr to))))
-       (message "Updating list of classes: done, requesting display...")
-       ;;(cperl-imenu-addback (nth 2 cperl-hierarchy))
-       ))
+       (message "Updating list of classes: done, requesting display...")))
   (or (nth 2 cperl-hierarchy)
       (error "No items found"))
   (setq update
@@ -6744,7 +6753,7 @@ One may build such TAGS files from CPerl mode menu."
                         "\\)\\(::\\)?"))
         (packages (cdr (nth 1 to)))
         (methods (cdr (nth 2 to)))
-        l1 head cons1 cons2 ord writeto recurse
+        head cons1 cons2 ord writeto recurse ;; l1
         root-packages root-functions
         (move-deeper
           (lambda (elt)
@@ -6764,7 +6773,7 @@ One may build such TAGS files from CPerl mode menu."
                    (setq root-functions (cons elt root-functions)))
                   (t
                    (setq root-packages (cons elt root-packages)))))))
-    (setcdr to l1)                     ; Init to dynamic space
+    (setcdr to nil) ;; l1              ; Init to dynamic space
     (setq writeto to)
     (setq ord 1)
     (mapc move-deeper packages)
@@ -8387,7 +8396,7 @@ do extra unwind via `cperl-unwind-to-safe'."
     (setq end (point)))
   (font-lock-default-fontify-region beg end loudly))
 
-(defun cperl-fontify-syntaxically (end)
+(defun cperl-fontify-syntactically (end)
   ;; Some vars for debugging only
   ;; (message "Syntaxifying...")
   (let ((dbg (point)) (iend end) (idone cperl-syntax-done-to)
diff --git a/lisp/progmodes/cpp.el b/lisp/progmodes/cpp.el
index b2c2e8d..6602a79 100644
--- a/lisp/progmodes/cpp.el
+++ b/lisp/progmodes/cpp.el
@@ -53,8 +53,7 @@
 
 (defcustom cpp-config-file (convert-standard-filename ".cpp.el")
   "File name to save cpp configuration."
-  :type 'file
-  :group 'cpp)
+  :type 'file)
 
 (define-widget 'cpp-face 'lazy
   "Either a face or the special symbol `invisible'."
@@ -62,13 +61,11 @@
 
 (defcustom cpp-known-face 'invisible
   "Face used for known cpp symbols."
-  :type 'cpp-face
-  :group 'cpp)
+  :type 'cpp-face)
 
 (defcustom cpp-unknown-face 'highlight
   "Face used for unknown cpp symbols."
-  :type 'cpp-face
-  :group 'cpp)
+  :type 'cpp-face)
 
 (defcustom cpp-face-type 'light
   "Indicate what background face type you prefer.
@@ -76,18 +73,15 @@ Can be either light or dark for color screens, mono for 
monochrome
 screens, and none if you don't use a window system and don't have
 a color-capable display."
   :options '(light dark mono nil)
-  :type 'symbol
-  :group 'cpp)
+  :type 'symbol)
 
 (defcustom cpp-known-writable t
   "Non-nil means you are allowed to modify the known conditionals."
-  :type 'boolean
-  :group 'cpp)
+  :type 'boolean)
 
 (defcustom cpp-unknown-writable t
   "Non-nil means you are allowed to modify the unknown conditionals."
-  :type 'boolean
-  :group 'cpp)
+  :type 'boolean)
 
 (defcustom cpp-edit-list nil
   "Alist of cpp macros and information about how they should be displayed.
@@ -101,15 +95,13 @@ Each entry is a list with the following elements:
                       (cpp-face :tag "False")
                       (choice (const :tag "True branch writable" t)
                               (const :tag "False branch writable" nil)
-                              (const :tag "Both branches writable" both))))
-  :group 'cpp)
+                               (const :tag "Both branches writable" both)))))
 
 (defcustom cpp-message-min-time-interval 1.0
   "Minimum time interval in seconds for `cpp-progress-message' messages.
 If nil, `cpp-progress-message' prints no progress messages."
   :type '(choice (const :tag "Disable progress messages" nil)
                  float)
-  :group 'cpp
   :version "26.1")
 
 (defvar-local cpp-overlay-list nil
@@ -153,36 +145,31 @@ or a cons cell (background-color . COLOR)."
                :value-type (choice face
                                    (const invisible)
                                    (cons (const background-color)
-                                         (string :tag "Color"))))
-  :group 'cpp)
+                                          (string :tag "Color")))))
 
 (defcustom cpp-face-light-name-list
   '("light gray" "light blue" "light cyan" "light yellow" "light pink"
     "pale green" "beige" "orange" "magenta" "violet" "medium purple"
     "turquoise")
   "Background colors useful with dark foreground colors."
-  :type '(repeat string)
-  :group 'cpp)
+  :type '(repeat string))
 
 (defcustom cpp-face-dark-name-list
   '("dim gray" "blue" "cyan" "yellow" "red"
     "dark green" "brown" "dark orange" "dark khaki" "dark violet" "purple"
     "dark turquoise")
   "Background colors useful with light foreground colors."
-  :type '(repeat string)
-  :group 'cpp)
+  :type '(repeat string))
 
 (defcustom cpp-face-light-list nil
   "Alist of names and faces to be used for light backgrounds."
   :type '(repeat (cons string (choice face
-                                     (cons (const background-color) string))))
-  :group 'cpp)
+                                      (cons (const background-color) 
string)))))
 
 (defcustom cpp-face-dark-list nil
   "Alist of names and faces to be used for dark backgrounds."
   :type '(repeat (cons string (choice face
-                                     (cons (const background-color) string))))
-  :group 'cpp)
+                                      (cons (const background-color) 
string)))))
 
 (defcustom cpp-face-mono-list
   '(("bold" . bold)
@@ -190,15 +177,13 @@ or a cons cell (background-color . COLOR)."
     ("italic" . italic)
     ("underline" . underline))
   "Alist of names and faces to be used for monochrome screens."
-  :type '(repeat (cons string face))
-  :group 'cpp)
+  :type '(repeat (cons string face)))
 
 (defcustom cpp-face-none-list
    '(("default" . default)
      ("invisible" . invisible))
    "Alist of names and faces available even if you don't use a window system."
-  :type '(repeat (cons string cpp-face))
-  :group 'cpp)
+  :type '(repeat (cons string cpp-face)))
 
 (defvar cpp-face-all-list
   (append cpp-face-light-list
diff --git a/lisp/progmodes/cwarn.el b/lisp/progmodes/cwarn.el
index 042030d..63b344b 100644
--- a/lisp/progmodes/cwarn.el
+++ b/lisp/progmodes/cwarn.el
@@ -128,8 +128,7 @@ on one of three forms:
 
 See variable `cwarn-font-lock-feature-keywords-alist' for available
 features."
-  :type '(repeat sexp)
-  :group 'cwarn)
+  :type '(repeat sexp))
 
 (defcustom cwarn-font-lock-feature-keywords-alist
   '((assign    . cwarn-font-lock-assignment-keywords)
@@ -142,15 +141,13 @@ keyword list."
   :type '(alist :key-type (choice (const assign)
                                  (const semicolon)
                                  (const reference))
-               :value-type (sexp :tag "Value"))
-  :group 'cwarn)
+                :value-type (sexp :tag "Value")))
 
 (defcustom cwarn-verbose t
   "When nil, CWarn mode will not generate any messages.
 
 Currently, messages are generated when the mode is activated and
 deactivated."
-  :group 'cwarn
   :type 'boolean)
 
 (defcustom cwarn-mode-text " CWarn"
@@ -158,13 +155,11 @@ deactivated."
 
 \(When the string is not empty, make sure that it has a leading space.)"
   :tag "CWarn mode text"                ; To separate it from `global-...'
-  :group 'cwarn
   :type 'string)
 
 (defcustom cwarn-load-hook nil
   "Functions to run when CWarn mode is first loaded."
   :tag "Load Hook"
-  :group 'cwarn
   :type 'hook)
 (make-obsolete-variable 'cwarn-load-hook
                         "use `with-eval-after-load' instead." "28.1")
diff --git a/lisp/progmodes/dcl-mode.el b/lisp/progmodes/dcl-mode.el
index 8943d8b..14eefdc 100644
--- a/lisp/progmodes/dcl-mode.el
+++ b/lisp/progmodes/dcl-mode.el
@@ -93,12 +93,11 @@ Presently this includes some syntax, .OP.erators, and 
\"f$\" lexicals.")
 (defcustom dcl-basic-offset 4
   "Number of columns to indent a block in DCL.
 A block is the commands between THEN-ELSE-ENDIF and between the commands
-dcl-block-begin-regexp and dcl-block-end-regexp.
+`dcl-block-begin-regexp' and `dcl-block-end-regexp'.
 
 The meaning of this variable may be changed if
-dcl-calc-command-indent-function is set to a function."
-  :type 'integer
-  :group 'dcl)
+`dcl-calc-command-indent-function' is set to a function."
+  :type 'integer)
 
 
 (defcustom dcl-continuation-offset 6
@@ -106,9 +105,8 @@ dcl-calc-command-indent-function is set to a function."
 A continuation line is a line that follows a line ending with `-'.
 
 The meaning of this variable may be changed if
-dcl-calc-cont-indent-function is set to a function."
-  :type 'integer
-  :group 'dcl)
+`dcl-calc-cont-indent-function' is set to a function."
+  :type 'integer)
 
 
 (defcustom dcl-margin-offset 8
@@ -117,37 +115,32 @@ The first command line in a file or after a SUBROUTINE 
statement is indented
 this much.  Other command lines are indented the same number of columns as
 the preceding command line.
 A command line is a line that starts with `$'."
-  :type 'integer
-  :group 'dcl)
+  :type 'integer)
 
 
 (defcustom dcl-margin-label-offset 2
   "Number of columns to indent a margin label in DCL.
 A margin label is a label that doesn't begin or end a block, i.e. it
-doesn't match dcl-block-begin-regexp or dcl-block-end-regexp."
-  :type 'integer
-  :group 'dcl)
+doesn't match `dcl-block-begin-regexp' or `dcl-block-end-regexp'."
+  :type 'integer)
 
 
 (defcustom dcl-comment-line-regexp "^\\$!"
   "Regexp describing the start of a comment line in DCL.
 Comment lines are not indented."
-  :type 'regexp
-  :group 'dcl)
+  :type 'regexp)
 
 
 (defcustom dcl-block-begin-regexp "loop[0-9]*:"
   "Regexp describing a command that begins an indented block in DCL.
 Set to nil to only indent at THEN-ELSE-ENDIF."
-  :type 'regexp
-  :group 'dcl)
+  :type 'regexp)
 
 
 (defcustom dcl-block-end-regexp "endloop[0-9]*:"
   "Regexp describing a command that ends an indented block in DCL.
 Set to nil to only indent at THEN-ELSE-ENDIF."
-  :type 'regexp
-  :group 'dcl)
+  :type 'regexp)
 
 
 (defcustom dcl-calc-command-indent-function nil
@@ -176,10 +169,9 @@ If this variable is nil, the indentation is calculated as
 CUR-INDENT + EXTRA-INDENT.
 
 This package includes two functions suitable for this:
-  dcl-calc-command-indent-multiple
-  dcl-calc-command-indent-hang"
-  :type '(choice (const nil) function)
-  :group 'dcl)
+  `dcl-calc-command-indent-multiple'
+  `dcl-calc-command-indent-hang'"
+  :type '(choice (const nil) function))
 
 
 (defcustom dcl-calc-cont-indent-function 'dcl-calc-cont-indent-relative
@@ -195,9 +187,8 @@ If this variable is nil, the indentation is calculated as
 CUR-INDENT + EXTRA-INDENT.
 
 This package includes one function suitable for this:
-  dcl-calc-cont-indent-relative"
-  :type 'function
-  :group 'dcl)
+  `dcl-calc-cont-indent-relative'"
+  :type 'function)
 
 
 (defcustom dcl-tab-always-indent t
@@ -206,50 +197,41 @@ If t, pressing TAB always indents the current line.
 If nil, pressing TAB indents the current line if point is at the left margin.
 Data lines (i.e. lines not part of a command line or continuation line) are
 never indented."
-  :type 'boolean
-  :group 'dcl)
+  :type 'boolean)
 
 
 (defcustom dcl-electric-characters t
   "Non-nil means reindent immediately when a label, ELSE or ENDIF is inserted."
-  :type 'boolean
-  :group 'dcl)
+  :type 'boolean)
 
 
 (defcustom dcl-tempo-comma ", "
   "Text to insert when a comma is needed in a template, in DCL mode."
-  :type 'string
-  :group 'dcl)
+  :type 'string)
 
 (defcustom dcl-tempo-left-paren "("
   "Text to insert when a left parenthesis is needed in a template in DCL."
-  :type 'string
-  :group 'dcl)
+  :type 'string)
 
 
 (defcustom dcl-tempo-right-paren ")"
   "Text to insert when a right parenthesis is needed in a template in DCL."
-  :type 'string
-  :group 'dcl)
+  :type 'string)
 
 ; I couldn't decide what looked best, so I'll let you decide...
 ; Remember, you can also customize this with imenu-submenu-name-format.
 (defcustom dcl-imenu-label-labels "Labels"
   "Imenu menu title for sub-listing with label names."
-  :type 'string
-  :group 'dcl)
+  :type 'string)
 (defcustom dcl-imenu-label-goto "GOTO"
   "Imenu menu title for sub-listing with GOTO statements."
-  :type 'string
-  :group 'dcl)
+  :type 'string)
 (defcustom dcl-imenu-label-gosub "GOSUB"
   "Imenu menu title for sub-listing with GOSUB statements."
-  :type 'string
-  :group 'dcl)
+  :type 'string)
 (defcustom dcl-imenu-label-call "CALL"
   "Imenu menu title for sub-listing with CALL statements."
-  :type 'string
-  :group 'dcl)
+  :type 'string)
 
 (defcustom dcl-imenu-generic-expression
   `((nil "^\\$[ \t]*\\([A-Za-z0-9_$]+\\):[ \t]+SUBROUTINE\\b" 1)
@@ -263,14 +245,12 @@ never indented."
 The default includes SUBROUTINE labels in the main listing and
 sub-listings for other labels, CALL, GOTO and GOSUB statements.
 See `imenu-generic-expression' for details."
-  :type '(repeat (sexp :tag "Imenu Expression"))
-  :group 'dcl)
+  :type '(repeat (sexp :tag "Imenu Expression")))
 
 
 (defcustom dcl-mode-hook nil
   "Hook called by `dcl-mode'."
-  :type 'hook
-  :group 'dcl)
+  :type 'hook)
 
 
 ;;; *** Global variables ****************************************************
@@ -306,64 +286,43 @@ See `imenu-generic-expression' for details."
     (define-key map "\C-c\C-o"         'dcl-set-option)
     (define-key map "\C-c\C-f"         'tempo-forward-mark)
     (define-key map "\C-c\C-b"         'tempo-backward-mark)
-
-    (define-key map [menu-bar]         (make-sparse-keymap))
-    (define-key map [menu-bar dcl]
-      (cons "DCL" (make-sparse-keymap "DCL")))
-
-    ;; Define these in bottom-up order
-    (define-key map [menu-bar dcl tempo-backward-mark]
-      '("Previous template mark" . tempo-backward-mark))
-    (define-key map [menu-bar dcl tempo-forward-mark]
-      '("Next template mark" . tempo-forward-mark))
-    (define-key map [menu-bar dcl tempo-complete-tag]
-      '("Complete template tag" . tempo-complete-tag))
-    (define-key map [menu-bar dcl dcl-separator-tempo]
-      '("--"))
-    (define-key map [menu-bar dcl dcl-save-all-options]
-      '("Save all options" . dcl-save-all-options))
-    (define-key map [menu-bar dcl dcl-save-nondefault-options]
-      '("Save changed options" . dcl-save-nondefault-options))
-    (define-key map [menu-bar dcl dcl-set-option]
-      '("Set option" . dcl-set-option))
-    (define-key map [menu-bar dcl dcl-separator-option]
-      '("--"))
-    (define-key map [menu-bar dcl dcl-delete-indentation]
-      '("Delete indentation" . dcl-delete-indentation))
-    (define-key map [menu-bar dcl dcl-split-line]
-      '("Split line" . dcl-split-line))
-    (define-key map [menu-bar dcl dcl-indent-command]
-      '("Indent command" . dcl-indent-command))
-    (define-key map [menu-bar dcl dcl-tab]
-      '("Indent line/insert tab" . dcl-tab))
-    (define-key map [menu-bar dcl dcl-back-to-indentation]
-      '("Back to indentation" . dcl-back-to-indentation))
-    (define-key map [menu-bar dcl dcl-forward-command]
-      '("End of statement" . dcl-forward-command))
-    (define-key map [menu-bar dcl dcl-backward-command]
-      '("Beginning of statement" . dcl-backward-command))
-    (define-key map [menu-bar dcl dcl-separator-movement]
-      '("--"))
-    (define-key map [menu-bar dcl imenu]
-      '("Buffer index menu" . imenu))
     map)
   "Keymap used in DCL-mode buffers.")
 
+(easy-menu-define dcl-mode-menu dcl-mode-map
+  "Menu for DCL-mode buffers."
+  '("DCL"
+    ["Buffer index menu" imenu]
+    "---"
+    ["Beginning of statement" dcl-backward-command]
+    ["End of statement" dcl-forward-command]
+    ["Back to indentation" dcl-back-to-indentation]
+    ["Indent line/insert tab" dcl-tab]
+    ["Indent command" dcl-indent-command]
+    ["Split line" dcl-split-line]
+    ["Delete indentation" dcl-delete-indentation]
+    "---"
+    ["Set option" dcl-set-option]
+    ["Save changed options" dcl-save-nondefault-options]
+    ["Save all options" dcl-save-all-options]
+    "---"
+    ["Complete template tag" tempo-complete-tag]
+    ["Next template mark" tempo-forward-mark]
+    ["Previous template mark" tempo-backward-mark]))
+
 (defcustom dcl-ws-r
   "\\([ \t]*-[ \t]*\\(!.*\\)*\n\\)*[ \t]*"
   "Regular expression describing white space in a DCL command line.
 White space is any number of continued lines with only space,tab,endcomment
 followed by space or tab."
-  :type 'regexp
-  :group 'dcl)
+  :type 'regexp)
 
 
 (defcustom dcl-label-r
   "[a-zA-Z0-9_$]*:\\([ \t!]\\|$\\)"
   "Regular expression describing a label.
 A label is a name followed by a colon followed by white-space or end-of-line."
-  :type 'regexp
-  :group 'dcl)
+  :type 'regexp)
 
 
 (defcustom dcl-cmd-r
@@ -373,8 +332,7 @@ A line starting with $, optionally followed by continuation 
lines,
 followed by the end of the command line.
 A continuation line is any characters followed by `-',
 optionally followed by a comment, followed by a newline."
-  :type 'regexp
-  :group 'dcl)
+  :type 'regexp)
 
 
 (defcustom dcl-command-regexp
@@ -384,21 +342,19 @@ A line starting with $, optionally followed by 
continuation lines,
 followed by the end of the command line.
 A continuation line is any characters followed by `-',
 optionally followed by a comment, followed by a newline."
-  :type 'regexp
-  :group 'dcl)
+  :type 'regexp)
 
 
 (defcustom dcl-electric-reindent-regexps
   (list "endif" "else" dcl-label-r)
   "Regexps that can trigger an electric reindent.
 A list of regexps that will trigger a reindent if the last letter
-is defined as dcl-electric-character.
+is defined as `dcl-electric-character'.
 
 E.g.: if this list contains `endif', the key `f' is defined as
-dcl-electric-character and you have just typed the `f' in
+`dcl-electric-character' and you have just typed the `f' in
 `endif', the line will be reindented."
-  :type '(repeat regexp)
-  :group 'dcl)
+  :type '(repeat regexp))
 
 
 (defvar dcl-option-alist
@@ -420,7 +376,7 @@ dcl-electric-character and you have just typed the `f' in
     (comment-start curval)
     (comment-start-skip curval)
     )
-  "Options and default values for dcl-set-option.
+  "Options and default values for `dcl-set-option'.
 
 An alist with option variables and functions or keywords to get a
 default value for the option.
@@ -434,8 +390,8 @@ toggle       the opposite of the current value (for t/nil)")
   (mapcar (lambda (option-assoc)
            (format "%s" (car option-assoc)))
          dcl-option-alist)
-  "The history list for dcl-set-option.
-Preloaded with all known option names from dcl-option-alist")
+  "The history list for `dcl-set-option'.
+Preloaded with all known option names from `dcl-option-alist'")
 
 
 ;; Must be defined after dcl-cmd-r
@@ -899,7 +855,7 @@ Returns one of the following symbols:
 
 ;;;---------------------------------------------------------------------------
 (defun dcl-show-line-type ()
-  "Test dcl-get-line-type."
+  "Test `dcl-get-line-type'."
   (interactive)
   (let ((type (dcl-get-line-type)))
     (cond
@@ -944,8 +900,7 @@ $ if cond
 $ then
 $   if cond
 $   then
-$       ! etc
-"
+$       ! etc"
   ;; calculate indentation if it's an interesting indent-type,
   ;; otherwise return nil to get the default indentation
   (let ((indent))
@@ -974,8 +929,7 @@ $ xxx
 
 If you use this function you will probably want to add \"then\" to
 dcl-electric-reindent-regexps and define the key \"n\" as
-dcl-electric-character.
-"
+dcl-electric-character."
   (let ((case-fold-search t))
     (save-excursion
       (cond
@@ -1018,17 +972,17 @@ see if the current lines should be indented.
 Analyze the current line to see if it should be `outdented'.
 
 Calculate the indentation of the current line, either with the default
-method or by calling dcl-calc-command-indent-function if it is
+method or by calling `dcl-calc-command-indent-function' if it is
 non-nil.
 
 If the current line should be outdented, calculate its indentation,
 either with the default method or by calling
-dcl-calc-command-indent-function if it is non-nil.
+`dcl-calc-command-indent-function' if it is non-nil.
 
 
 Rules for default indentation:
 
-If it is the first line in the buffer, indent dcl-margin-offset.
+If it is the first line in the buffer, indent `dcl-margin-offset'.
 
 Go to the previous command line with a command on it.
 Find out how much it is indented (cur-indent).
@@ -1036,7 +990,7 @@ Look at the first word on the line to see if the 
indentation should be
 adjusted.  Skip margin-label, continuations and comments while looking for
 the first word.  Save this buffer position as `last-point'.
 If the first word after a label is SUBROUTINE, set extra-indent to
-dcl-margin-offset.
+`dcl-margin-offset'.
 
 First word  extra-indent
 THEN        +dcl-basic-offset
@@ -1193,8 +1147,7 @@ Indented lines will align with either:
 * the innermost nonclosed parenthesis
   $ if ((a.eq.b .and. -
          d.eq.c .or. f$function(xxxx, -
-                                yyy)))
-"
+                                yyy)))"
   (let ((case-fold-search t)
        indent)
     (save-excursion
@@ -1374,7 +1327,7 @@ Adjusts indentation on the current line.  Data lines are 
not indented."
 
 ;;;-------------------------------------------------------------------------
 (defun dcl-indent-command ()
-  "Indents the complete command line that point is on.
+  "Indent the complete command line that point is on.
 This includes continuation lines."
   (interactive "*")
   (let ((type (dcl-get-line-type)))
@@ -1421,7 +1374,7 @@ the lines indentation; otherwise insert a tab."
 
 ;;;-------------------------------------------------------------------------
 (defun dcl-electric-character (arg)
-  "Inserts a character and indents if necessary.
+  "Insert a character and indent if necessary.
 Insert a character if the user gave a numeric argument or the flag
 `dcl-electric-characters' is not set.  If an argument was given,
 insert that many characters.
@@ -1835,8 +1788,8 @@ Set or update the value of VAR in the current buffers
 
 ;;;-------------------------------------------------------------------------
 (defun dcl-save-all-options ()
-  "Save all dcl-mode options for this buffer.
-Saves or updates all dcl-mode related options in a `Local Variables:'
+  "Save all `dcl-mode' options for this buffer.
+Saves or updates all `dcl-mode' related options in a `Local Variables:'
 section at the end of the current buffer."
   (interactive "*")
   (mapcar (lambda (option-assoc)
diff --git a/lisp/progmodes/ebnf-abn.el b/lisp/progmodes/ebnf-abn.el
index 9e570b6..2a37110 100644
--- a/lisp/progmodes/ebnf-abn.el
+++ b/lisp/progmodes/ebnf-abn.el
@@ -1,4 +1,4 @@
-;;; ebnf-abn.el --- parser for ABNF (Augmented BNF)
+;;; ebnf-abn.el --- parser for ABNF (Augmented BNF)  -*- lexical-binding: t; 
-*-
 
 ;; Copyright (C) 2001-2021 Free Software Foundation, Inc.
 
@@ -39,10 +39,6 @@
 ;;
 ;;     See the URL:
 ;;     `https://www.ietf.org/rfc/rfc2234.txt'
-;;     or
-;;     `http://www.faqs.org/rfcs/rfc2234.html'
-;;     or
-;;     `http://www.rnp.br/ietf/rfc/rfc2234.txt'
 ;;     ("Augmented BNF for Syntax Specifications: ABNF").
 ;;
 ;;
diff --git a/lisp/progmodes/ebnf-bnf.el b/lisp/progmodes/ebnf-bnf.el
index 93ebfe8..e6717cb 100644
--- a/lisp/progmodes/ebnf-bnf.el
+++ b/lisp/progmodes/ebnf-bnf.el
@@ -1,4 +1,4 @@
-;;; ebnf-bnf.el --- parser for EBNF
+;;; ebnf-bnf.el --- parser for EBNF  -*- lexical-binding: t; -*-
 
 ;; Copyright (C) 1999-2021 Free Software Foundation, Inc.
 
diff --git a/lisp/progmodes/ebnf-dtd.el b/lisp/progmodes/ebnf-dtd.el
index 66e5dd0..93bae5a 100644
--- a/lisp/progmodes/ebnf-dtd.el
+++ b/lisp/progmodes/ebnf-dtd.el
@@ -1,4 +1,4 @@
-;;; ebnf-dtd.el --- parser for DTD (Data Type Description for XML)
+;;; ebnf-dtd.el --- parser for DTD (Data Type Description for XML)  -*- 
lexical-binding: t; -*-
 
 ;; Copyright (C) 2001-2021 Free Software Foundation, Inc.
 
diff --git a/lisp/progmodes/ebnf-ebx.el b/lisp/progmodes/ebnf-ebx.el
index 389049e..5d85419 100644
--- a/lisp/progmodes/ebnf-ebx.el
+++ b/lisp/progmodes/ebnf-ebx.el
@@ -1,4 +1,4 @@
-;;; ebnf-ebx.el --- parser for EBNF used to specify XML (EBNFX)
+;;; ebnf-ebx.el --- parser for EBNF used to specify XML (EBNFX)  -*- 
lexical-binding: t; -*-
 
 ;; Copyright (C) 2001-2021 Free Software Foundation, Inc.
 
diff --git a/lisp/progmodes/ebnf-iso.el b/lisp/progmodes/ebnf-iso.el
index d25ff3e..b4532c7 100644
--- a/lisp/progmodes/ebnf-iso.el
+++ b/lisp/progmodes/ebnf-iso.el
@@ -1,4 +1,4 @@
-;;; ebnf-iso.el --- parser for ISO EBNF
+;;; ebnf-iso.el --- parser for ISO EBNF  -*- lexical-binding: t; -*-
 
 ;; Copyright (C) 1999-2021 Free Software Foundation, Inc.
 
@@ -38,7 +38,7 @@
 ;; ---------------
 ;;
 ;;     See the URL:
-;;     `http://www.cl.cam.ac.uk/~mgk25/iso-ebnf.html'
+;;     `https://www.cl.cam.ac.uk/~mgk25/iso-ebnf.html'
 ;;     ("International Standard of the ISO EBNF Notation").
 ;;
 ;;
diff --git a/lisp/progmodes/ebnf-otz.el b/lisp/progmodes/ebnf-otz.el
index b724d75..84e59cc 100644
--- a/lisp/progmodes/ebnf-otz.el
+++ b/lisp/progmodes/ebnf-otz.el
@@ -1,4 +1,4 @@
-;;; ebnf-otz.el --- syntactic chart OpTimiZer
+;;; ebnf-otz.el --- syntactic chart OpTimiZer  -*- lexical-binding: t; -*-
 
 ;; Copyright (C) 1999-2021 Free Software Foundation, Inc.
 
diff --git a/lisp/progmodes/ebnf-yac.el b/lisp/progmodes/ebnf-yac.el
index 2765d03..5abf1de 100644
--- a/lisp/progmodes/ebnf-yac.el
+++ b/lisp/progmodes/ebnf-yac.el
@@ -1,4 +1,4 @@
-;;; ebnf-yac.el --- parser for Yacc/Bison
+;;; ebnf-yac.el --- parser for Yacc/Bison  -*- lexical-binding: t; -*-
 
 ;; Copyright (C) 1999-2021 Free Software Foundation, Inc.
 
diff --git a/lisp/progmodes/ebnf2ps.el b/lisp/progmodes/ebnf2ps.el
index b376423..7092d2c 100644
--- a/lisp/progmodes/ebnf2ps.el
+++ b/lisp/progmodes/ebnf2ps.el
@@ -330,7 +330,7 @@ Please send all bug fixes and enhancements to
 ;;                     ("Augmented BNF for Syntax Specifications: ABNF").
 ;;
 ;;    `iso-ebnf'       ebnf2ps recognizes the syntax described in the URL:
-;;                     `http://www.cl.cam.ac.uk/~mgk25/iso-ebnf.html'
+;;                     `https://www.cl.cam.ac.uk/~mgk25/iso-ebnf.html'
 ;;                     ("International Standard of the ISO EBNF Notation").
 ;;                     The following variables *ONLY* have effect with this
 ;;                     setting:
@@ -1783,7 +1783,7 @@ Valid values are:
                (\"Augmented BNF for Syntax Specifications: ABNF\").
 
    `iso-ebnf'  ebnf2ps recognizes the syntax described in the URL:
-               `http://www.cl.cam.ac.uk/~mgk25/iso-ebnf.html'
+                `https://www.cl.cam.ac.uk/~mgk25/iso-ebnf.html'
                (\"International Standard of the ISO EBNF Notation\").
                The following variables *ONLY* have effect with this
                setting:
@@ -2920,7 +2920,7 @@ See `ebnf-style-database' documentation."
        value
       (and (car value) (ebnf-apply-style1 (car value)))
       (while (setq value (cdr value))
-       (set (caar value) (eval (cdar value)))))))
+       (set (caar value) (eval (cdar value) t))))))
 
 
 (defun ebnf-check-style-values (values)
@@ -5487,7 +5487,7 @@ killed after process termination."
                      (ebnf-shape-value ebnf-chart-shape
                                        ebnf-terminal-shape-alist))
              (format "/UserArrow{%s}def\n"
-                     (let ((arrow (eval ebnf-user-arrow)))
+                     (let ((arrow (eval ebnf-user-arrow t)))
                        (if (stringp arrow)
                            arrow
                          "")))
@@ -6290,7 +6290,7 @@ killed after process termination."
 (defun ebnf-log-header (format-str &rest args)
   (when ebnf-log
     (apply
-     'ebnf-log
+     #'ebnf-log
      (concat
       "\n\n===============================================================\n\n"
       format-str)
diff --git a/lisp/progmodes/ebrowse.el b/lisp/progmodes/ebrowse.el
index a174d48..cafdb3b 100644
--- a/lisp/progmodes/ebrowse.el
+++ b/lisp/progmodes/ebrowse.el
@@ -35,7 +35,6 @@
 
 (require 'cl-lib)
 (require 'seq)
-(require 'easymenu)
 (require 'view)
 (require 'ebuff-menu)
 
@@ -3185,8 +3184,8 @@ MEMBER-NAME is the name of the member found."
     (let* ((start (point))
           (name (progn (skip-chars-forward "a-zA-Z0-9_")
                        (buffer-substring start (point))))
-          class)
-      (list class name))))
+          ) ;; class
+      (list nil name)))) ;; class
 
 
 (defun ebrowse-tags-choose-class (_tree header name initial-class-name)
diff --git a/lisp/progmodes/elisp-mode.el b/lisp/progmodes/elisp-mode.el
index 3121530..8ade718 100644
--- a/lisp/progmodes/elisp-mode.el
+++ b/lisp/progmodes/elisp-mode.el
@@ -46,150 +46,123 @@ It has `lisp-mode-abbrev-table' as its parent."
   "Syntax table used in `emacs-lisp-mode'.")
 
 (defvar emacs-lisp-mode-map
-  (let ((map (make-sparse-keymap))
-       (menu-map (make-sparse-keymap "Emacs-Lisp"))
-       (lint-map (make-sparse-keymap))
-       (prof-map (make-sparse-keymap))
-       (tracing-map (make-sparse-keymap)))
+  (let ((map (make-sparse-keymap)))
     (set-keymap-parent map lisp-mode-shared-map)
     (define-key map "\e\t" 'completion-at-point)
     (define-key map "\e\C-x" 'eval-defun)
     (define-key map "\e\C-q" 'indent-pp-sexp)
-    (bindings--define-key map [menu-bar emacs-lisp]
-      (cons "Emacs-Lisp" menu-map))
-    (bindings--define-key menu-map [eldoc]
-      '(menu-item "Auto-Display Documentation Strings" eldoc-mode
-                 :button (:toggle . (bound-and-true-p eldoc-mode))
-                 :help "Display the documentation string for the item under 
cursor"))
-    (bindings--define-key menu-map [checkdoc]
-      '(menu-item "Check Documentation Strings" checkdoc
-                 :help "Check documentation strings for style requirements"))
-    (bindings--define-key menu-map [re-builder]
-      '(menu-item "Construct Regexp" re-builder
-                 :help "Construct a regexp interactively"))
-    (bindings--define-key menu-map [tracing] (cons "Tracing" tracing-map))
-    (bindings--define-key tracing-map [tr-a]
-      '(menu-item "Untrace All" untrace-all
-                 :help "Untrace all currently traced functions"))
-    (bindings--define-key tracing-map [tr-uf]
-      '(menu-item "Untrace Function..." untrace-function
-                 :help "Untrace function, and possibly activate all remaining 
advice"))
-    (bindings--define-key tracing-map [tr-sep] menu-bar-separator)
-    (bindings--define-key tracing-map [tr-q]
-      '(menu-item "Trace Function Quietly..." trace-function-background
-                 :help "Trace the function with trace output going quietly to 
a buffer"))
-    (bindings--define-key tracing-map [tr-f]
-      '(menu-item "Trace Function..." trace-function
-                 :help "Trace the function given as an argument"))
-    (bindings--define-key menu-map [profiling] (cons "Profiling" prof-map))
-    (bindings--define-key prof-map [prof-restall]
-      '(menu-item "Remove Instrumentation for All Functions" elp-restore-all
-                 :help "Restore the original definitions of all functions 
being profiled"))
-    (bindings--define-key prof-map [prof-restfunc]
-      '(menu-item "Remove Instrumentation for Function..." elp-restore-function
-                 :help "Restore an instrumented function to its original 
definition"))
-
-    (bindings--define-key prof-map [sep-rem] menu-bar-separator)
-    (bindings--define-key prof-map [prof-resall]
-      '(menu-item "Reset Counters for All Functions" elp-reset-all
-                 :help "Reset the profiling information for all functions 
being profiled"))
-    (bindings--define-key prof-map [prof-resfunc]
-      '(menu-item "Reset Counters for Function..." elp-reset-function
-                 :help "Reset the profiling information for a function"))
-    (bindings--define-key prof-map [prof-res]
-      '(menu-item "Show Profiling Results" elp-results
-                 :help "Display current profiling results"))
-    (bindings--define-key prof-map [prof-pack]
-      '(menu-item "Instrument Package..." elp-instrument-package
-                 :help "Instrument for profiling all function that start with 
a prefix"))
-    (bindings--define-key prof-map [prof-func]
-      '(menu-item "Instrument Function..." elp-instrument-function
-                 :help "Instrument a function for profiling"))
-    ;; Maybe this should be in a separate submenu from the ELP stuff?
-    (bindings--define-key prof-map [sep-natprof] menu-bar-separator)
-    (bindings--define-key prof-map [prof-natprof-stop]
-      '(menu-item "Stop Native Profiler" profiler-stop
-                 :help "Stop recording profiling information"
-                 :enable (and (featurep 'profiler)
-                              (profiler-running-p))))
-    (bindings--define-key prof-map [prof-natprof-report]
-      '(menu-item "Show Profiler Report" profiler-report
-                 :help "Show the current profiler report"
-                 :enable (and (featurep 'profiler)
-                              (profiler-running-p))))
-    (bindings--define-key prof-map [prof-natprof-start]
-      '(menu-item "Start Native Profiler..." profiler-start
-                 :help "Start recording profiling information"))
-
-    (bindings--define-key menu-map [lint] (cons "Linting" lint-map))
-    (bindings--define-key lint-map [lint-di]
-      '(menu-item "Lint Directory..." elint-directory
-                 :help "Lint a directory"))
-    (bindings--define-key lint-map [lint-f]
-      '(menu-item "Lint File..." elint-file
-                 :help "Lint a file"))
-    (bindings--define-key lint-map [lint-b]
-      '(menu-item "Lint Buffer" elint-current-buffer
-                 :help "Lint the current buffer"))
-    (bindings--define-key lint-map [lint-d]
-      '(menu-item "Lint Defun" elint-defun
-                 :help "Lint the function at point"))
-    (bindings--define-key menu-map [edebug-defun]
-      '(menu-item "Instrument Function for Debugging" edebug-defun
-                 :help "Evaluate the top level form point is in, stepping 
through with Edebug"
-                 :keys "C-u C-M-x"))
-    (bindings--define-key menu-map [separator-byte] menu-bar-separator)
-    (bindings--define-key menu-map [disas]
-      '(menu-item "Disassemble Byte Compiled Object..." disassemble
-                 :help "Print disassembled code for OBJECT in a buffer"))
-    (bindings--define-key menu-map [byte-recompile]
-      '(menu-item "Byte-recompile Directory..." byte-recompile-directory
-                 :help "Recompile every `.el' file in DIRECTORY that needs 
recompilation"))
-    (bindings--define-key menu-map [emacs-byte-compile-and-load]
-      '(menu-item "Byte-compile and Load" emacs-lisp-byte-compile-and-load
-                 :help "Byte-compile the current file (if it has changed), 
then load compiled code"))
-    (bindings--define-key menu-map [byte-compile]
-      '(menu-item "Byte-compile This File" emacs-lisp-byte-compile
-                 :help "Byte compile the file containing the current buffer"))
-    (bindings--define-key menu-map [separator-eval] menu-bar-separator)
-    (bindings--define-key menu-map [ielm]
-      '(menu-item "Interactive Expression Evaluation" ielm
-                 :help "Interactively evaluate Emacs Lisp expressions"))
-    (bindings--define-key menu-map [eval-buffer]
-      '(menu-item "Evaluate Buffer" eval-buffer
-                 :help "Execute the current buffer as Lisp code"))
-    (bindings--define-key menu-map [eval-region]
-      '(menu-item "Evaluate Region" eval-region
-                 :help "Execute the region as Lisp code"
-                 :enable mark-active))
-    (bindings--define-key menu-map [eval-sexp]
-      '(menu-item "Evaluate Last S-expression" eval-last-sexp
-                 :help "Evaluate sexp before point; print value in echo area"))
-    (bindings--define-key menu-map [separator-format] menu-bar-separator)
-    (bindings--define-key menu-map [comment-region]
-      '(menu-item "Comment Out Region" comment-region
-                 :help "Comment or uncomment each line in the region"
-                 :enable mark-active))
-    (bindings--define-key menu-map [indent-region]
-      '(menu-item "Indent Region" indent-region
-                 :help "Indent each nonblank line in the region"
-                 :enable mark-active))
-    (bindings--define-key menu-map [indent-line]
-      '(menu-item "Indent Line" lisp-indent-line))
     map)
   "Keymap for Emacs Lisp mode.
 All commands in `lisp-mode-shared-map' are inherited by this map.")
 
+(easy-menu-define emacs-lisp-mode-menu emacs-lisp-mode-map
+  "Menu for Emacs Lisp mode."
+  '("Emacs-Lisp"
+    ["Indent Line" lisp-indent-line]
+    ["Indent Region" indent-region
+     :help "Indent each nonblank line in the region"
+     :active mark-active]
+    ["Comment Out Region" comment-region
+     :help "Comment or uncomment each line in the region"
+     :active mark-active]
+    "---"
+    ["Evaluate Last S-expression" eval-last-sexp
+     :help "Evaluate sexp before point; print value in echo area"]
+    ["Evaluate Region" eval-region
+     :help "Execute the region as Lisp code"
+     :active mark-active]
+    ["Evaluate Buffer" eval-buffer
+     :help "Execute the current buffer as Lisp code"]
+    ["Interactive Expression Evaluation" ielm
+     :help "Interactively evaluate Emacs Lisp expressions"]
+    "---"
+    ["Byte-compile This File" emacs-lisp-byte-compile
+     :help "Byte compile the file containing the current buffer"]
+    ["Byte-compile and Load" emacs-lisp-byte-compile-and-load
+     :help "Byte-compile the current file (if it has changed), then load 
compiled code"]
+    ["Byte-recompile Directory..." byte-recompile-directory
+     :help "Recompile every `.el' file in DIRECTORY that needs recompilation"]
+    ["Disassemble Byte Compiled Object..." disassemble
+     :help "Print disassembled code for OBJECT in a buffer"]
+    "---"
+    ["Instrument Function for Debugging" edebug-defun
+     :help "Evaluate the top level form point is in, stepping through with 
Edebug"
+     :keys "C-u C-M-x"]
+    ("Navigation"
+     ["Forward Sexp" forward-sexp
+      :help "Go to the next s-expression"]
+     ["Backward Sexp" backward-sexp
+      :help "Go to the previous s-expression"]
+     ["Beginning Of Defun" beginning-of-defun
+      :help "Go to the start of the current function definition"]
+     ["Up List" up-list
+      :help "Go one level up and forward"])
+    ("Linting"
+     ["Lint Defun" elint-defun
+      :help "Lint the function at point"]
+     ["Lint Buffer" elint-current-buffer
+      :help "Lint the current buffer"]
+     ["Lint File..." elint-file
+      :help "Lint a file"]
+     ["Lint Directory..." elint-directory
+      :help "Lint a directory"])
+    ("Profiling"
+     ;; Maybe this should be in a separate submenu from the ELP stuff?
+     ["Start Native Profiler..." profiler-start
+      :help "Start recording profiling information"]
+     ["Show Profiler Report" profiler-report
+      :help "Show the current profiler report"
+      :active (and (featurep 'profiler)
+                   (profiler-running-p))]
+     ["Stop Native Profiler" profiler-stop
+      :help "Stop recording profiling information"
+      :active (and (featurep 'profiler)
+                   (profiler-running-p))]
+     "---"
+     ["Instrument Function..." elp-instrument-function
+      :help "Instrument a function for profiling"]
+     ["Instrument Package..." elp-instrument-package
+      :help "Instrument for profiling all function that start with a prefix"]
+     ["Show Profiling Results" elp-results
+      :help "Display current profiling results"]
+     ["Reset Counters for Function..." elp-reset-function
+      :help "Reset the profiling information for a function"]
+     ["Reset Counters for All Functions" elp-reset-all
+      :help "Reset the profiling information for all functions being profiled"]
+     "---"
+     ["Remove Instrumentation for All Functions" elp-restore-all
+      :help "Restore the original definitions of all functions being profiled"]
+     ["Remove Instrumentation for Function..." elp-restore-function
+      :help "Restore an instrumented function to its original definition"])
+    ("Tracing"
+     ["Trace Function..." trace-function
+      :help "Trace the function given as an argument"]
+     ["Trace Function Quietly..." trace-function-background
+      :help "Trace the function with trace output going quietly to a buffer"]
+     "---"
+     ["Untrace All" untrace-all
+      :help "Untrace all currently traced functions"]
+     ["Untrace Function..." untrace-function
+      :help "Untrace function, and possibly activate all remaining advice"])
+    ["Construct Regexp" re-builder
+     :help "Construct a regexp interactively"]
+    ["Check Documentation Strings" checkdoc
+     :help "Check documentation strings for style requirements"]
+    ["Auto-Display Documentation Strings" eldoc-mode
+     :help "Display the documentation string for the item under cursor"
+     :style toggle
+     :selected (bound-and-true-p eldoc-mode)]))
+
 (defun emacs-lisp-byte-compile ()
   "Byte compile the file containing the current buffer."
-  (interactive)
+  (interactive nil emacs-lisp-mode)
   (if buffer-file-name
       (byte-compile-file buffer-file-name)
     (error "The buffer must be saved in a file first")))
 
 (defun emacs-lisp-byte-compile-and-load ()
   "Byte-compile the current file (if it has changed), then load compiled code."
-  (interactive)
+  (interactive nil emacs-lisp-mode)
   (or buffer-file-name
       (error "The buffer must be saved in a file first"))
   (require 'bytecomp)
@@ -557,6 +530,7 @@ functions are annotated with \"<f>\" via the
                     ((elisp--expect-function-p beg)
                      (list nil obarray
                            :predicate #'fboundp
+                           :company-kind #'elisp--company-kind
                            :company-doc-buffer #'elisp--company-doc-buffer
                            :company-docsig #'elisp--company-doc-string
                            :company-location #'elisp--company-location))
@@ -570,6 +544,7 @@ functions are annotated with \"<f>\" via the
                                             (symbol-plist sym)))
                            :annotation-function
                            (lambda (str) (if (fboundp (intern-soft str)) " 
<f>"))
+                           :company-kind #'elisp--company-kind
                            :company-doc-buffer #'elisp--company-doc-buffer
                            :company-docsig #'elisp--company-doc-string
                            :company-location #'elisp--company-location))
@@ -580,6 +555,11 @@ functions are annotated with \"<f>\" via the
                                                  obarray
                                                  #'boundp
                                                  'strict))
+                           :company-kind
+                           (lambda (s)
+                             (if (test-completion s 
elisp--local-variables-completion-table)
+                                 'value
+                               'variable))
                            :company-doc-buffer #'elisp--company-doc-buffer
                            :company-docsig #'elisp--company-doc-string
                            :company-location #'elisp--company-location)))
@@ -626,11 +606,13 @@ functions are annotated with \"<f>\" via the
                                       (looking-at "\\_<let\\*?\\_>"))))
                         (list t obarray
                               :predicate #'boundp
+                              :company-kind (lambda (_) 'variable)
                               :company-doc-buffer #'elisp--company-doc-buffer
                               :company-docsig #'elisp--company-doc-string
                               :company-location #'elisp--company-location))
                        (_ (list nil obarray
                                 :predicate #'fboundp
+                                :company-kind #'elisp--company-kind
                                 :company-doc-buffer #'elisp--company-doc-buffer
                                 :company-docsig #'elisp--company-doc-string
                                 :company-location #'elisp--company-location
@@ -646,6 +628,16 @@ functions are annotated with \"<f>\" via the
                                        " " (cadr table-etc)))
                     (cddr table-etc)))))))))
 
+(defun elisp--company-kind (str)
+  (let ((sym (intern-soft str)))
+    (cond
+     ((or (macrop sym) (special-form-p sym)) 'keyword)
+     ((fboundp sym) 'function)
+     ((boundp sym) 'variable)
+     ((featurep sym) 'module)
+     ((facep sym) 'color)
+     (t 'text))))
+
 (defun lisp-completion-at-point (&optional _predicate)
   (declare (obsolete elisp-completion-at-point "25.1"))
   (elisp-completion-at-point))
@@ -904,7 +896,13 @@ non-nil result supersedes the xrefs produced by
             (point-marker)))))))
 
 (cl-defmethod xref-location-group ((l xref-elisp-location))
-  (xref-elisp-location-file l))
+  (let ((file (xref-elisp-location-file l)))
+    (defvar find-function-C-source-directory)
+    (if (and find-function-C-source-directory
+             (string-match-p "\\`src/" file))
+        (concat find-function-C-source-directory
+                (substring file 3))
+      file)))
 
 (defun elisp-load-path-roots ()
   (if (boundp 'package-user-dir)
@@ -914,35 +912,31 @@ non-nil result supersedes the xrefs produced by
 ;;; Elisp Interaction mode
 
 (defvar lisp-interaction-mode-map
-  (let ((map (make-sparse-keymap))
-       (menu-map (make-sparse-keymap "Lisp-Interaction")))
+  (let ((map (make-sparse-keymap)))
     (set-keymap-parent map lisp-mode-shared-map)
     (define-key map "\e\C-x" 'eval-defun)
     (define-key map "\e\C-q" 'indent-pp-sexp)
     (define-key map "\e\t" 'completion-at-point)
     (define-key map "\n" 'eval-print-last-sexp)
-    (bindings--define-key map [menu-bar lisp-interaction]
-      (cons "Lisp-Interaction" menu-map))
-    (bindings--define-key menu-map [eval-defun]
-      '(menu-item "Evaluate Defun" eval-defun
-                 :help "Evaluate the top-level form containing point, or after 
point"))
-    (bindings--define-key menu-map [eval-print-last-sexp]
-      '(menu-item "Evaluate and Print" eval-print-last-sexp
-                 :help "Evaluate sexp before point; print value into current 
buffer"))
-    (bindings--define-key menu-map [edebug-defun-lisp-interaction]
-      '(menu-item "Instrument Function for Debugging" edebug-defun
-                 :help "Evaluate the top level form point is in, stepping 
through with Edebug"
-                 :keys "C-u C-M-x"))
-    (bindings--define-key menu-map [indent-pp-sexp]
-      '(menu-item "Indent or Pretty-Print" indent-pp-sexp
-                 :help "Indent each line of the list starting just after 
point, or prettyprint it"))
-    (bindings--define-key menu-map [complete-symbol]
-      '(menu-item "Complete Lisp Symbol" completion-at-point
-                 :help "Perform completion on Lisp symbol preceding point"))
     map)
   "Keymap for Lisp Interaction mode.
 All commands in `lisp-mode-shared-map' are inherited by this map.")
 
+(easy-menu-define lisp-interaction-mode-menu lisp-interaction-mode-map
+  "Menu for Lisp Interaction mode."
+  '("Lisp-Interaction"
+    ["Complete Lisp Symbol" completion-at-point
+     :help "Perform completion on Lisp symbol preceding point"]
+    ["Indent or Pretty-Print" indent-pp-sexp
+     :help "Indent each line of the list starting just after point, or 
prettyprint it"]
+    ["Instrument Function for Debugging" edebug-defun
+     :help "Evaluate the top level form point is in, stepping through with 
Edebug"
+     :keys "C-u C-M-x"]
+    ["Evaluate and Print" eval-print-last-sexp
+     :help "Evaluate sexp before point; print value into current buffer"]
+    ["Evaluate Defun" eval-defun
+     :help "Evaluate the top-level form containing point, or after point"]))
+
 (define-derived-mode lisp-interaction-mode emacs-lisp-mode "Lisp Interaction"
   "Major mode for typing and evaluating Lisp forms.
 Like Lisp mode except that \\[eval-print-last-sexp] evals the Lisp expression
@@ -1336,6 +1330,7 @@ if it already has a value.)
 Return the result of evaluation."
   ;; FIXME: the print-length/level bindings should only be applied while
   ;; printing, not while evaluating.
+  (defvar elisp--eval-defun-result)
   (let ((debug-on-error eval-expression-debug-on-error)
        (print-length eval-expression-print-length)
        (print-level eval-expression-print-level)
@@ -1351,19 +1346,22 @@ Return the result of evaluation."
           (end-of-defun)
           (beginning-of-defun)
           (setq beg (point))
-          (setq form (read (current-buffer)))
+          (setq form (funcall load-read-function (current-buffer)))
           (setq end (point)))
         ;; Alter the form if necessary.
         (let ((form (eval-sexp-add-defvars
                      (elisp--eval-defun-1
-                      (macroexpand
-                       `(setq elisp--eval-defun-result ,form))))))
+                      (macroexpand form)))))
           (eval-region beg end standard-output
                        (lambda (_ignore)
                          ;; Skipping to the end of the specified region
                          ;; will make eval-region return.
                          (goto-char end)
-                         form)))))
+                         ;; This `setq' needs to be added *after* passing
+                         ;; form through `elisp--eval-defun-1' since it
+                         ;; would otherwise "hide" forms like `defvar's and
+                         ;; thus defeat their special treatment.
+                         `(setq elisp--eval-defun-result ,form))))))
     (let ((str (eval-expression-print-format elisp--eval-defun-result)))
       (if str (princ str)))
     elisp--eval-defun-result))
@@ -1396,6 +1394,7 @@ which see."
   (interactive "P")
   (cond (edebug-it
         (require 'edebug)
+        (defvar edebug-all-defs)
         (eval-defun (not edebug-all-defs)))
        (t
         (if (null eval-expression-debug-on-error)
diff --git a/lisp/progmodes/etags.el b/lisp/progmodes/etags.el
index 869529a..13717b1 100644
--- a/lisp/progmodes/etags.el
+++ b/lisp/progmodes/etags.el
@@ -836,11 +836,7 @@ If no tags table is loaded, do nothing and return nil."
   "Read a tag name, with defaulting and completion."
   (let* ((completion-ignore-case (find-tag--completion-ignore-case))
         (default (find-tag--default))
-        (spec (completing-read (if default
-                                   (format "%s (default %s): "
-                                           (substring string 0 (string-match 
"[ :]+\\'" string))
-                                           default)
-                                 string)
+        (spec (completing-read (format-prompt string default)
                                (tags-lazy-completion-table)
                                nil nil nil nil default)))
     (if (equal spec "")
@@ -899,7 +895,7 @@ onto a ring and may be popped back to with \\[pop-tag-mark].
 Contrast this with the ring of marks gone to by the command.
 
 See documentation of variable `tags-file-name'."
-  (interactive (find-tag-interactive "Find tag: "))
+  (interactive (find-tag-interactive "Find tag"))
 
   (setq find-tag-history (cons tagname find-tag-history))
   ;; Save the current buffer's value of `find-tag-hook' before
@@ -971,7 +967,7 @@ Contrast this with the ring of marks gone to by the command.
 
 See documentation of variable `tags-file-name'."
   (declare (obsolete xref-find-definitions "25.1"))
-  (interactive (find-tag-interactive "Find tag: "))
+  (interactive (find-tag-interactive "Find tag"))
   (let* ((buf (find-tag-noselect tagname next-p regexp-p))
         (pos (with-current-buffer buf (point))))
     (condition-case nil
@@ -1000,7 +996,7 @@ Contrast this with the ring of marks gone to by the 
command.
 
 See documentation of variable `tags-file-name'."
   (declare (obsolete xref-find-definitions-other-window "25.1"))
-  (interactive (find-tag-interactive "Find tag other window: "))
+  (interactive (find-tag-interactive "Find tag other window"))
 
   ;; This hair is to deal with the case where the tag is found in the
   ;; selected window's buffer; without the hair, point is moved in both
@@ -1041,7 +1037,7 @@ Contrast this with the ring of marks gone to by the 
command.
 
 See documentation of variable `tags-file-name'."
   (declare (obsolete xref-find-definitions-other-frame "25.1"))
-  (interactive (find-tag-interactive "Find tag other frame: "))
+  (interactive (find-tag-interactive "Find tag other frame"))
   (let ((pop-up-frames t))
     (with-suppressed-warnings ((obsolete find-tag-other-window))
       (find-tag-other-window tagname next-p))))
@@ -1065,7 +1061,7 @@ Contrast this with the ring of marks gone to by the 
command.
 
 See documentation of variable `tags-file-name'."
   (declare (obsolete xref-find-apropos "25.1"))
-  (interactive (find-tag-interactive "Find tag regexp: " t))
+  (interactive (find-tag-interactive "Find tag regexp" t))
   ;; We go through find-tag-other-window to do all the display hair there.
   (funcall (if other-window 'find-tag-other-window 'find-tag)
           regexp next-p t))
@@ -1604,11 +1600,11 @@ that do nothing."
 
 ;; This might be a neat idea, but it's too hairy at the moment.
 ;;(defmacro tags-with-syntax (&rest body)
+;;  (declare (debug t))
 ;;   `(with-syntax-table
 ;;        (with-current-buffer (find-file-noselect (file-of-tag))
 ;;          (syntax-table))
 ;;      ,@body))
-;;(put 'tags-with-syntax 'edebug-form-spec '(&rest form))
 
 ;; exact file name match, i.e. searched tag must match complete file
 ;; name including directories parts if there are some.
diff --git a/lisp/progmodes/executable.el b/lisp/progmodes/executable.el
index fa5724a..85e9b4b 100644
--- a/lisp/progmodes/executable.el
+++ b/lisp/progmodes/executable.el
@@ -54,41 +54,31 @@
   "Base functionality for executable interpreter scripts."
   :group 'processes)
 
-;; This used to default to `other', but that doesn't seem to have any
-;; significance.  fx 2000-02-11.
-(defcustom executable-insert t         ; 'other
+(defcustom executable-insert t
   "Non-nil means offer to add a magic number to a file.
 This takes effect when you switch to certain major modes,
 including Shell-script mode (`sh-mode').
 When you type \\[executable-set-magic], it always offers to add or
 update the magic number."
-;;;   :type '(choice (const :tag "off" nil)
-;;;             (const :tag "on" t)
-;;;             symbol)
-  :type 'boolean
-  :group 'executable)
-
+  :type 'boolean)
 
 (defcustom executable-query 'function
   "If non-nil, ask user before changing an existing magic number.
 When this is `function', only ask when called non-interactively."
   :type '(choice (const :tag "Don't Ask" nil)
                 (const :tag "Ask when non-interactive" function)
-                (other :tag "Ask" t))
-  :group 'executable)
+                 (other :tag "Ask" t)))
 
 
 (defcustom executable-magicless-file-regexp 
"/[Mm]akefile$\\|/\\.\\(z?profile\\|bash_profile\\|z?login\\|bash_login\\|z?logout\\|bash_logout\\|.+shrc\\|esrc\\|rcrc\\|[kz]shenv\\)$"
   "On files with this kind of name no magic is inserted or changed."
-  :type 'regexp
-  :group 'executable)
+  :type 'regexp)
 
 (defcustom executable-prefix "#!"
   "Interpreter magic number prefix inserted when there was no magic number.
 Use of `executable-prefix-env' is preferable to this option."
   :version "26.1"                       ; deprecated
-  :type 'string
-  :group 'executable)
+  :type 'string)
 
 (defcustom executable-prefix-env nil
   "If non-nil, use \"/usr/bin/env\" in interpreter magic number.
@@ -96,8 +86,7 @@ If this variable is non-nil, the interpreter magic number 
inserted
 by `executable-set-magic' will be \"#!/usr/bin/env INTERPRETER\",
 otherwise it will be \"#!/path/to/INTERPRETER\"."
   :version "26.1"
-  :type 'boolean
-  :group 'executable)
+  :type 'boolean)
 
 (defcustom executable-chmod 73
   "After saving, if the file is not executable, set this mode.
@@ -105,8 +94,7 @@ This mode passed to `set-file-modes' is taken absolutely 
when negative, or
 relative to the files existing modes.  Do nothing if this is nil.
 Typical values are 73 (+x) or -493 (rwxr-xr-x)."
   :type '(choice integer
-                (const nil))
-  :group 'executable)
+                 (const nil)))
 
 
 (defvar executable-command nil)
@@ -114,8 +102,7 @@ Typical values are 73 (+x) or -493 (rwxr-xr-x)."
 (defcustom executable-self-display "tail"
   "Command you use with argument `-n+2' to make text files self-display.
 Note that the like of `more' doesn't work too well under Emacs \\[shell]."
-  :type 'string
-  :group 'executable)
+  :type 'string)
 
 (make-obsolete-variable 'executable-self-display nil "25.1" 'set)
 
diff --git a/lisp/progmodes/flymake.el b/lisp/progmodes/flymake.el
index 5d96c62..8481a27 100644
--- a/lisp/progmodes/flymake.el
+++ b/lisp/progmodes/flymake.el
@@ -284,17 +284,17 @@ If set to nil, don't suppress any zero counters."
 (defmacro flymake-log (level msg &rest args)
   "Log, at level LEVEL, the message MSG formatted with ARGS.
 LEVEL is passed to `display-warning', which is used to display
-the warning.  If this form is included in a byte-compiled file,
+the warning.  If this form is included in a file,
 the generated warning contains an indication of the file that
 generated it."
-  (let* ((compile-file (and (boundp 'byte-compile-current-file)
-                            (symbol-value 'byte-compile-current-file)))
-         (sublog (if (and
-                      compile-file
-                      (not load-file-name))
+  (let* ((file (if (fboundp 'macroexp-file-name)
+                   (macroexp-file-name)
+                 (and (not load-file-name)
+                      (bound-and-true-p byte-compile-current-file))))
+         (sublog (if file
                      (intern
                       (file-name-nondirectory
-                       (file-name-sans-extension compile-file))))))
+                       (file-name-sans-extension file))))))
     `(flymake--log-1 ,level ',sublog ,msg ,@args)))
 
 (defun flymake-error (text &rest args)
@@ -483,7 +483,7 @@ Currently, Flymake may provide these keyword-value pairs:
 
 * `:recent-changes', a list of recent changes since the last time
   the backend function was called for the buffer.  An empty list
-  indicates that no changes have been reocrded.  If it is the
+  indicates that no changes have been recorded.  If it is the
   first time that this backend function is called for this
   activation of `flymake-mode', then this argument isn't provided
   at all (i.e. it's not merely nil).
@@ -1198,7 +1198,6 @@ default) no filter is applied."
   '(" " flymake-mode-line-title flymake-mode-line-exception
     flymake-mode-line-counters)
   "Mode line construct for customizing Flymake information."
-  :group 'flymake
   :type '(repeat (choice string symbol)))
 
 (defcustom flymake-mode-line-counter-format
@@ -1210,7 +1209,6 @@ default) no filter is applied."
 This is a suitable place for placing the `flymake-error-counter',
 `flymake-warning-counter' and `flymake-note-counter' constructs.
 Separating each of these with space is not necessary."
-  :group 'flymake
   :type '(repeat (choice string symbol)))
 
 (defvar flymake-mode-line-title '(:eval (flymake--mode-line-title))
diff --git a/lisp/progmodes/grep.el b/lisp/progmodes/grep.el
index d6ee8bb..8c9a1b5 100644
--- a/lisp/progmodes/grep.el
+++ b/lisp/progmodes/grep.el
@@ -88,9 +88,9 @@ To make grep highlight matches even into a pipe, you need the 
option
 `always' that forces grep to use `--color=always' to unconditionally
 output escape sequences.
 
-In interactive usage, the actual value of this variable is set up
-by `grep-compute-defaults' when the default value is `auto-detect'.
-To change the default value, use \\[customize] or call the function
+If the value is `auto-detect' (the default), `grep' will call
+`grep-compute-defaults' to compute the value.  To change the
+default value, use \\[customize] or call the function
 `grep-apply-setting'."
   :type '(choice (const :tag "Do not highlight matches with grep markers" nil)
                 (const :tag "Highlight matches with grep markers" t)
@@ -279,57 +279,39 @@ See `compilation-error-screen-columns'."
     (define-key map "}" 'compilation-next-file)
     (define-key map "\t" 'compilation-next-error)
     (define-key map [backtab] 'compilation-previous-error)
-
-    ;; Set up the menu-bar
-    (define-key map [menu-bar grep]
-      (cons "Grep" (make-sparse-keymap "Grep")))
-
-    (define-key map [menu-bar grep grep-find-toggle-abbreviation]
-      '(menu-item "Toggle command abbreviation"
-                  grep-find-toggle-abbreviation
-                  :help "Toggle showing verbose command options"))
-    (define-key map [menu-bar grep compilation-separator3] '("----"))
-    (define-key map [menu-bar grep compilation-kill-compilation]
-      '(menu-item "Kill Grep" kill-compilation
-                 :help "Kill the currently running grep process"))
-    (define-key map [menu-bar grep compilation-separator2] '("----"))
-    (define-key map [menu-bar grep compilation-compile]
-      '(menu-item
-        "Compile..." compile
-       :help
-        "Compile the program including the current buffer.  Default: run 
`make'"))
-    (define-key map [menu-bar grep compilation-rgrep]
-      '(menu-item "Recursive grep..." rgrep
-                 :help "User-friendly recursive grep in directory tree"))
-    (define-key map [menu-bar grep compilation-lgrep]
-      '(menu-item "Local grep..." lgrep
-                 :help "User-friendly grep in a directory"))
-    (define-key map [menu-bar grep compilation-grep-find]
-      '(menu-item "Grep via Find..." grep-find
-                 :help "Run grep via find, with user-specified args"))
-    (define-key map [menu-bar grep compilation-grep]
-      '(menu-item
-        "Another grep..." grep
-       :help
-        "Run grep, with user-specified args, and collect output in a buffer."))
-    (define-key map [menu-bar grep compilation-recompile]
-      '(menu-item "Repeat grep" recompile
-                 :help "Run grep again"))
-    (define-key map [menu-bar grep compilation-separator1] '("----"))
-    (define-key map [menu-bar grep compilation-first-error]
-      '(menu-item
-        "First Match" first-error
-       :help "Restart at the first match, visit corresponding location"))
-    (define-key map [menu-bar grep compilation-previous-error]
-      '(menu-item "Previous Match" previous-error
-                 :help "Visit the previous match and corresponding location"))
-    (define-key map [menu-bar grep compilation-next-error]
-      '(menu-item "Next Match" next-error
-                 :help "Visit the next match and corresponding location"))
     map)
   "Keymap for grep buffers.
 `compilation-minor-mode-map' is a cdr of this.")
 
+(easy-menu-define grep-menu-map grep-mode-map
+  "Menu for grep buffers."
+  '("Grep"
+    ["Next Match" next-error
+     :help "Visit the next match and corresponding location"]
+    ["Previous Match" previous-error
+     :help "Visit the previous match and corresponding location"]
+    ["First Match" first-error
+     :help "Restart at the first match, visit corresponding location"]
+    "----"
+    ["Repeat grep" recompile
+     :help "Run grep again"]
+    ["Another grep..." grep
+     :help "Run grep, with user-specified args, and collect output in a 
buffer."]
+    ["Grep via Find..." grep-find
+     :help "Run grep via find, with user-specified args"]
+    ["Local grep..." lgrep
+     :help "User-friendly grep in a directory"]
+    ["Recursive grep..." rgrep
+     :help "User-friendly recursive grep in directory tree"]
+    ["Compile..." compile
+     :help "Compile the program including the current buffer.  Default: run 
`make'"]
+    "----"
+    ["Kill Grep" kill-compilation
+     :help "Kill the currently running grep process"]
+    "----"
+    ["Toggle command abbreviation" grep-find-toggle-abbreviation
+     :help "Toggle showing verbose command options"]))
+
 (defvar grep-mode-tool-bar-map
   ;; When bootstrapping, tool-bar-map is not properly initialized yet,
   ;; so don't do anything.
@@ -933,7 +915,10 @@ list is empty)."
                                  (if current-prefix-arg default grep-command)
                                  'grep-history
                                  (if current-prefix-arg nil default))))))
-
+  ;; If called non-interactively, also compute the defaults if we
+  ;; haven't already.
+  (when (eq grep-highlight-matches 'auto-detect)
+    (grep-compute-defaults))
   (grep--save-buffers)
   ;; Setting process-setup-function makes exit-message-function work
   ;; even when async processes aren't supported.
diff --git a/lisp/progmodes/gud.el b/lisp/progmodes/gud.el
index eb114ac..b105cba 100644
--- a/lisp/progmodes/gud.el
+++ b/lisp/progmodes/gud.el
@@ -64,8 +64,7 @@ pdb (Python), and jdb."
 
 (defcustom gud-key-prefix "\C-x\C-a"
   "Prefix of all GUD commands valid in C buffers."
-  :type 'key-sequence
-  :group 'gud)
+  :type 'key-sequence)
 
 (global-set-key (vconcat gud-key-prefix "\C-l") 'gud-refresh)
 ;; (define-key ctl-x-map " " 'gud-break); backward compatibility hack
@@ -1074,8 +1073,7 @@ The file names should be absolute, or relative to the 
directory
 containing the executable being debugged."
   :type '(choice (const :tag "Current Directory" nil)
                 (repeat :value ("")
-                        directory))
-  :group 'gud)
+                         directory)))
 
 (defun gud-dbx-massage-args (_file args)
   (nconc (let ((directories gud-dbx-directories)
@@ -1380,8 +1378,7 @@ The file names should be absolute, or relative to the 
directory
 containing the executable being debugged."
   :type '(choice (const :tag "Current Directory" nil)
                 (repeat :value ("")
-                        directory))
-  :group 'gud)
+                         directory)))
 
 (defun gud-xdb-massage-args (_file args)
   (nconc (let ((directories gud-xdb-directories)
@@ -1563,8 +1560,7 @@ into one that invokes an Emacs-enabled debugging session.
 
 (defcustom gud-perldb-command-name "perl -d"
   "Default command to execute a Perl script under debugger."
-  :type 'string
-  :group 'gud)
+  :type 'string)
 
 ;;;###autoload
 (defun perldb (command-line)
@@ -1677,8 +1673,7 @@ and source-file directory for your debugger."
   (if (executable-find "pdb") "pdb" "python -m pdb")
   "Command that executes the Python debugger."
   :version "27.1"
-  :type 'string
-  :group 'gud)
+  :type 'string)
 
 ;;;###autoload
 (defun pdb (command-line)
@@ -1759,8 +1754,7 @@ directory and source-file directory for your debugger."
   "File name for executing the Guile debugger.
 This should be an executable on your path, or an absolute file name."
   :version "25.1"
-  :type 'string
-  :group 'gud)
+  :type 'string)
 
 ;;;###autoload
 (defun guiler (command-line)
@@ -1883,8 +1877,7 @@ and source-file directory for your debugger."
 
 (defcustom gud-jdb-command-name "jdb"
   "Command that executes the Java debugger."
-  :type 'string
-  :group 'gud)
+  :type 'string)
 
 (defcustom gud-jdb-use-classpath t
   "If non-nil, search for Java source files in classpath directories.
@@ -1899,8 +1892,7 @@ and parsing all Java files for class information.
 
 Set to nil to use `gud-jdb-directories' to scan java sources for
 class information on jdb startup (original method)."
-  :type 'boolean
-  :group 'gud)
+  :type 'boolean)
 
 (defvar gud-jdb-classpath nil
   "Java/jdb classpath directories list.
@@ -2584,7 +2576,6 @@ Commands:
 
 (defcustom gud-chdir-before-run t
   "Non-nil if GUD should `cd' to the debugged executable."
-  :group 'gud
   :type 'boolean)
 
 ;; Perform initializations common to all debuggers.
@@ -3419,7 +3410,6 @@ Treats actions as defuns."
                                        python-mode)
   "List of modes for which to enable GUD tooltips."
   :type '(repeat (symbol :tag "Major mode"))
-  :group 'gud
   :group 'tooltip)
 
 (defcustom gud-tooltip-display
@@ -3431,13 +3421,11 @@ Forms in the list are combined with AND.  The default 
is to display
 only tooltips in the buffer containing the overlay arrow."
   :type 'sexp
   :risky t
-  :group 'gud
   :group 'tooltip)
 
 (defcustom gud-tooltip-echo-area nil
   "Use the echo area instead of frames for GUD tooltips."
   :type 'boolean
-  :group 'gud
   :group 'tooltip)
 
 (make-obsolete-variable 'gud-tooltip-echo-area
diff --git a/lisp/progmodes/hideif.el b/lisp/progmodes/hideif.el
index 923f85f..6f1a878 100644
--- a/lisp/progmodes/hideif.el
+++ b/lisp/progmodes/hideif.el
@@ -1743,10 +1743,10 @@ first arg will be `hif-etc'."
 (defun hide-ifdef-guts ()
   "Does most of the work of `hide-ifdefs'.
 It does not do the work that's pointless to redo on a recursive entry."
-  ;; (message "hide-ifdef-guts")
   (save-excursion
     (let* ((case-fold-search t) ; Ignore case for `hide-ifdef-header-regexp'
            (expand-header (and hide-ifdef-expand-reinclusion-protection
+                               (buffer-file-name)
                                (string-match hide-ifdef-header-regexp
                                              (buffer-file-name))
                                (zerop hif-recurse-level)))
diff --git a/lisp/progmodes/hideshow.el b/lisp/progmodes/hideshow.el
index 73d09e0..81ba0d8 100644
--- a/lisp/progmodes/hideshow.el
+++ b/lisp/progmodes/hideshow.el
@@ -232,13 +232,11 @@
 
 (defcustom hs-hide-comments-when-hiding-all t
   "Hide the comments too when you do an `hs-hide-all'."
-  :type 'boolean
-  :group 'hideshow)
+  :type 'boolean)
 
 (defcustom hs-minor-mode-hook nil
   "Hook called when hideshow minor mode is activated or deactivated."
   :type 'hook
-  :group 'hideshow
   :version "21.1")
 
 (defcustom hs-isearch-open 'code
@@ -254,8 +252,7 @@ This has effect only if `search-invisible' is set to 
`open'."
   :type '(choice (const :tag "open only code blocks" code)
                  (const :tag "open only comment blocks" comment)
                  (const :tag "open both code and comment blocks" t)
-                 (const :tag "don't open any of them" nil))
-  :group 'hideshow)
+                 (const :tag "don't open any of them" nil)))
 
 ;;;###autoload
 (defvar hs-special-modes-alist
diff --git a/lisp/progmodes/icon.el b/lisp/progmodes/icon.el
index 933cb33..e9a21d4a 100644
--- a/lisp/progmodes/icon.el
+++ b/lisp/progmodes/icon.el
@@ -1,4 +1,4 @@
-;;; icon.el --- mode for editing Icon code
+;;; icon.el --- mode for editing Icon code  -*- lexical-binding: t -*-
 
 ;; Copyright (C) 1989, 2001-2021 Free Software Foundation, Inc.
 
@@ -31,53 +31,48 @@
   "Abbrev table in use in Icon-mode buffers.")
 (define-abbrev-table 'icon-mode-abbrev-table ())
 
-(defvar icon-mode-map ()
-  "Keymap used in Icon mode.")
-(if icon-mode-map
-    ()
+(defvar icon-mode-map
   (let ((map (make-sparse-keymap "Icon")))
-    (setq icon-mode-map (make-sparse-keymap))
-    (define-key icon-mode-map "{" 'electric-icon-brace)
-    (define-key icon-mode-map "}" 'electric-icon-brace)
-    (define-key icon-mode-map "\e\C-h" 'mark-icon-function)
-    (define-key icon-mode-map "\e\C-a" 'beginning-of-icon-defun)
-    (define-key icon-mode-map "\e\C-e" 'end-of-icon-defun)
-    (define-key icon-mode-map "\e\C-q" 'indent-icon-exp)
-    (define-key icon-mode-map "\177" 'backward-delete-char-untabify)
-
-    (define-key icon-mode-map [menu-bar] (make-sparse-keymap "Icon"))
-    (define-key icon-mode-map [menu-bar icon]
-      (cons "Icon" map))
-    (define-key map [beginning-of-icon-defun] '("Beginning of function" . 
beginning-of-icon-defun))
-    (define-key map [end-of-icon-defun] '("End of function" . 
end-of-icon-defun))
-    (define-key map [comment-region] '("Comment Out Region" . comment-region))
-    (define-key map [indent-region] '("Indent Region" . indent-region))
-    (define-key map [indent-line] '("Indent Line" . icon-indent-command))
-    (put 'eval-region 'menu-enable 'mark-active)
-    (put 'comment-region 'menu-enable 'mark-active)
-    (put 'indent-region 'menu-enable 'mark-active)))
-
-(defvar icon-mode-syntax-table nil
-  "Syntax table in use in Icon-mode buffers.")
+    (define-key map "{" 'electric-icon-brace)
+    (define-key map "}" 'electric-icon-brace)
+    (define-key map "\e\C-h" 'mark-icon-function)
+    (define-key map "\e\C-a" 'beginning-of-icon-defun)
+    (define-key map "\e\C-e" 'end-of-icon-defun)
+    (define-key map "\e\C-q" 'indent-icon-exp)
+    (define-key map "\177" 'backward-delete-char-untabify)
+    map)
+  "Keymap used in Icon mode.")
 
-(if icon-mode-syntax-table
-    ()
-  (setq icon-mode-syntax-table (make-syntax-table))
-  (modify-syntax-entry ?\\ "\\" icon-mode-syntax-table)
-  (modify-syntax-entry ?# "<" icon-mode-syntax-table)
-  (modify-syntax-entry ?\n ">" icon-mode-syntax-table)
-  (modify-syntax-entry ?$ "." icon-mode-syntax-table)
-  (modify-syntax-entry ?/ "." icon-mode-syntax-table)
-  (modify-syntax-entry ?* "." icon-mode-syntax-table)
-  (modify-syntax-entry ?+ "." icon-mode-syntax-table)
-  (modify-syntax-entry ?- "." icon-mode-syntax-table)
-  (modify-syntax-entry ?= "." icon-mode-syntax-table)
-  (modify-syntax-entry ?% "." icon-mode-syntax-table)
-  (modify-syntax-entry ?< "." icon-mode-syntax-table)
-  (modify-syntax-entry ?> "." icon-mode-syntax-table)
-  (modify-syntax-entry ?& "." icon-mode-syntax-table)
-  (modify-syntax-entry ?| "." icon-mode-syntax-table)
-  (modify-syntax-entry ?\' "\"" icon-mode-syntax-table))
+(easy-menu-define icon-mode-menu icon-mode-map
+  "Menu for Icon mode."
+  '("Icon"
+    ["Beginning of function" beginning-of-icon-defun]
+    ["Comment Out Region" comment-region
+     :enable mark-active]
+    ["End of function" end-of-icon-defun]
+    ["Indent Line" icon-indent-command]
+    ["Indent Region" indent-region
+     :enable mark-active]))
+
+(defvar icon-mode-syntax-table
+  (let ((table (make-syntax-table)))
+    (modify-syntax-entry ?\\ "\\" table)
+    (modify-syntax-entry ?# "<" table)
+    (modify-syntax-entry ?\n ">" table)
+    (modify-syntax-entry ?$ "." table)
+    (modify-syntax-entry ?/ "." table)
+    (modify-syntax-entry ?* "." table)
+    (modify-syntax-entry ?+ "." table)
+    (modify-syntax-entry ?- "." table)
+    (modify-syntax-entry ?= "." table)
+    (modify-syntax-entry ?% "." table)
+    (modify-syntax-entry ?< "." table)
+    (modify-syntax-entry ?> "." table)
+    (modify-syntax-entry ?& "." table)
+    (modify-syntax-entry ?| "." table)
+    (modify-syntax-entry ?\' "\"" table)
+    table)
+  "Syntax table in use in Icon-mode buffers.")
 
 (defgroup icon nil
   "Mode for editing Icon code."
@@ -86,42 +81,35 @@
 
 (defcustom icon-indent-level 4
   "Indentation of Icon statements with respect to containing block."
-  :type 'integer
-  :group 'icon)
+  :type 'integer)
 
 (defcustom icon-brace-imaginary-offset 0
   "Imagined indentation of an Icon open brace that actually follows a 
statement."
-  :type 'integer
-  :group 'icon)
+  :type 'integer)
 
 (defcustom icon-brace-offset 0
   "Extra indentation for braces, compared with other text in same context."
-  :type 'integer
-  :group 'icon)
+  :type 'integer)
 
 (defcustom icon-continued-statement-offset 4
   "Extra indent for Icon lines not starting new statements."
-  :type 'integer
-  :group 'icon)
+  :type 'integer)
 
 (defcustom icon-continued-brace-offset 0
   "Extra indent for Icon substatements that start with open-braces.
 This is in addition to `icon-continued-statement-offset'."
-  :type 'integer
-  :group 'icon)
+  :type 'integer)
 
 (defcustom icon-auto-newline nil
   "Non-nil means automatically newline before and after braces Icon code.
 This applies when braces are inserted."
-  :type 'boolean
-  :group 'icon)
+  :type 'boolean)
 
 (defcustom icon-tab-always-indent t
   "Non-nil means TAB in Icon mode should always reindent the current line.
 It will then reindent, regardless of where in the line point is
 when the TAB command is used."
-  :type 'boolean
-  :group 'icon)
+  :type 'boolean)
 
 (defvar icon-imenu-generic-expression
       '((nil "^[ \t]*procedure[ \t]+\\(\\sw+\\)[ \t]*("  1))
@@ -209,12 +197,11 @@ with no args, if that value is non-nil."
        (progn
          (insert last-command-event)
          (icon-indent-line)
-         (if icon-auto-newline
-             (progn
-               (newline)
-               ;; (newline) may have done auto-fill
-               (setq insertpos (- (point) 2))
-               (icon-indent-line)))
+          (when icon-auto-newline
+            (newline)
+            ;; (newline) may have done auto-fill
+            (setq insertpos (- (point) 2))
+            (icon-indent-line))
          (save-excursion
            (if insertpos (goto-char (1+ insertpos)))
            (delete-char -1))))
diff --git a/lisp/progmodes/idlw-complete-structtag.el 
b/lisp/progmodes/idlw-complete-structtag.el
index 25bc5ad..6d2d402 100644
--- a/lisp/progmodes/idlw-complete-structtag.el
+++ b/lisp/progmodes/idlw-complete-structtag.el
@@ -1,4 +1,4 @@
-;;; idlw-complete-structtag.el --- Completion of structure tags.
+;;; idlw-complete-structtag.el --- Completion of structure tags.  -*- 
lexical-binding: t; -*-
 
 ;; Copyright (C) 2001-2021 Free Software Foundation, Inc.
 
@@ -100,12 +100,11 @@
 (defvar idlwave-sint-structtags nil)
 
 ;; Create the sintern type for structure talks
-(declare-function idlwave-sintern-structtag "idlw-complete-structtag" t t)
-(idlwave-new-sintern-type 'structtag)
+(idlwave-new-sintern-type structtag)
 
 ;; Hook the plugin into idlwave
-(add-to-list 'idlwave-complete-special 'idlwave-complete-structure-tag)
-(add-hook 'idlwave-update-rinfo-hook 'idlwave-structtag-reset)
+(add-hook 'idlwave-complete-functions #'idlwave-complete-structure-tag)
+(add-hook 'idlwave-update-rinfo-hook #'idlwave-structtag-reset)
 
 ;;; The main code follows below
 (defvar idlwave-completion-help-info)
diff --git a/lisp/progmodes/idlw-help.el b/lisp/progmodes/idlw-help.el
index 2e7b0aa..db76df9 100644
--- a/lisp/progmodes/idlw-help.el
+++ b/lisp/progmodes/idlw-help.el
@@ -1,4 +1,4 @@
-;;; idlw-help.el --- HTML Help code for IDLWAVE
+;;; idlw-help.el --- HTML Help code for IDLWAVE  -*- lexical-binding: t; -*-
 
 ;; Copyright (C) 2000-2021 Free Software Foundation, Inc.
 ;;
@@ -50,7 +50,6 @@
 
 (defcustom idlwave-html-help-pre-v6 nil
   "Whether pre or post-v6.0 IDL help documents are being used."
-  :group 'idlwave-online-help
   :type 'boolean)
 
 (defvar idlwave-html-link-sep
@@ -60,7 +59,6 @@
   "The directory, relative to `idlwave-system-directory', where the IDL
 HTML help files live, for IDL 6.2 and later.  This location, if found,
 is used in preference to the old `idlwave-html-help-location'."
-  :group 'idlwave-online-help
   :type 'directory)
 
 (defcustom idlwave-html-help-location
@@ -69,7 +67,6 @@ is used in preference to the old 
`idlwave-html-help-location'."
     "/usr/local/etc/")
   "The directory where the idl_html_help/ dir lives.  Obsolete for IDL
 6.2 or later (see `idlwave-html-system-help-location')."
-  :group 'idlwave-online-help
   :type 'directory)
 
 (defvar idlwave-help-use-hh nil
@@ -77,18 +74,15 @@ is used in preference to the old 
`idlwave-html-help-location'."
 
 (defcustom idlwave-help-use-assistant t
   "Whether to use the IDL Assistant as the help browser."
-  :group 'idlwave-online-help
   :type 'boolean)
 
 (defcustom idlwave-help-browser-function browse-url-browser-function
   "Function to use to display HTML help.
 Defaults to `browse-url-browser-function', which see."
-  :group 'idlwave-online-help
   :type 'function)
 
 (defcustom idlwave-help-browser-generic-program browse-url-generic-program
   "Program to run if using `browse-url-generic-program'."
-  :group 'idlwave-online-help
   :type '(choice (const nil) string))
 
 ;; AFAICS, never used since it was introduced in 2004.
@@ -96,7 +90,6 @@ Defaults to `browse-url-browser-function', which see."
   (if (boundp 'browse-url-generic-args)
       browse-url-generic-args "")
   "Program args to use if using `browse-url-generic-program'."
-  :group 'idlwave-online-help
   :type '(repeat string))
 
 (defcustom idlwave-help-browser-is-local nil
@@ -106,7 +99,6 @@ external programs.  If the browser name contains \"-w3\", it 
is
 assumed to be local to Emacs.  For other local browsers, this variable
 must be explicitly set non-nil in order for the variable
 `idlwave-help-use-dedicated-frame' to function."
-  :group 'idlwave-online-help
   :type 'boolean)
 
 (defvar idlwave-help-directory ""
@@ -114,7 +106,6 @@ must be explicitly set non-nil in order for the variable
 
 (defcustom idlwave-help-use-dedicated-frame t
   "Non-nil means, use a separate frame for Online Help if possible."
-  :group 'idlwave-online-help
   :type 'boolean)
 
 (defcustom idlwave-help-frame-parameters
@@ -123,14 +114,12 @@ must be explicitly set non-nil in order for the variable
 See also `idlwave-help-use-dedicated-frame'.
 If you do not set the frame width here, the value specified in
 `idlw-help.el' will be used."
-  :group 'idlwave-online-help
   :type '(repeat
          (cons symbol sexp)))
 
 (defcustom idlwave-max-popup-menu-items 20
   "Maximum number of items per pane in popup menus.
 Currently only used for class selection during completion help."
-  :group 'idlwave-online-help
   :type 'integer)
 
 (defcustom idlwave-extra-help-function 'idlwave-help-with-source
@@ -158,12 +147,10 @@ The default value for this function is 
`idlwave-help-with-source' which
 loads the routine source file into the help buffer.  If you try to write
 a different function which accesses a special help file or so, it is
 probably a good idea to still call this function as a fallback."
-  :group 'idlwave-online-help
   :type 'symbol)
 
 (defcustom idlwave-help-fontify-source-code nil
   "Non-nil means, fontify source code displayed as help like normal code."
-  :group 'idlwave-online-help
   :type 'boolean)
 
 (defcustom idlwave-help-source-try-header t
@@ -173,7 +160,6 @@ help text.  When this variable is non-nil, we try to find a 
description of
 the help item in the first routine doclib header above the routine definition.
 If the variable is nil, or if we cannot find/parse the header, the routine
 definition is displayed instead."
-  :group 'idlwave-online-help
   :type 'boolean)
 
 
@@ -181,20 +167,17 @@ definition is displayed instead."
   "A regexp for the heading word to search for in doclib headers
 which specifies the `name' section.  Can be used for localization
 support."
-  :group 'idlwave-online-help
   :type 'regexp)
 
 (defcustom idlwave-help-doclib-keyword "KEYWORD"
   "A regexp for the heading word to search for in doclib headers
 which specifies the `keywords' section.  Can be used for localization
 support."
-  :group 'idlwave-online-help
   :type 'regexp)
 
 (defface idlwave-help-link
   '((t :inherit link))
-  "Face for highlighting links into IDLWAVE online help."
-  :group 'idlwave-online-help)
+  "Face for highlighting links into IDLWAVE online help.")
 
 (defvar idlwave-help-activate-links-aggressively nil
   "Obsolete variable.")
@@ -219,20 +202,20 @@ support."
 
 (defvar idlwave-help-mode-map
   (let ((map (make-sparse-keymap)))
-    (define-key map "q" 'idlwave-help-quit)
-    (define-key map "w" 'widen)
+    (define-key map "q" #'idlwave-help-quit)
+    (define-key map "w" #'widen)
     (define-key map "\C-m" (lambda (arg)
                              (interactive "p")
                              (scroll-up arg)))
-    (define-key map " " 'scroll-up-command)
-    (define-key map [?\S-\ ] 'scroll-down-command)
-    (define-key map [delete] 'scroll-down-command)
-    (define-key map "h" 'idlwave-help-find-header)
-    (define-key map "H" 'idlwave-help-find-first-header)
-    (define-key map "." 'idlwave-help-toggle-header-match-and-def)
-    (define-key map "F" 'idlwave-help-fontify)
-    (define-key map "\M-?" 'idlwave-help-return-to-calling-frame)
-    (define-key map "x" 'idlwave-help-return-to-calling-frame)
+    (define-key map " " #'scroll-up-command)
+    (define-key map [?\S-\ ] #'scroll-down-command)
+    (define-key map [delete] #'scroll-down-command)
+    (define-key map "h" #'idlwave-help-find-header)
+    (define-key map "H" #'idlwave-help-find-first-header)
+    (define-key map "." #'idlwave-help-toggle-header-match-and-def)
+    (define-key map "F" #'idlwave-help-fontify)
+    (define-key map "\M-?" #'idlwave-help-return-to-calling-frame)
+    (define-key map "x" #'idlwave-help-return-to-calling-frame)
     map)
   "The keymap used in `idlwave-help-mode'.")
 
@@ -374,7 +357,7 @@ It collects and prints the diagnostics messages."
       (setq idlwave-last-context-help-pos marker)
       (idlwave-do-context-help1 arg)
       (if idlwave-help-diagnostics
-         (message "%s" (mapconcat 'identity
+         (message "%s" (mapconcat #'identity
                                   (nreverse idlwave-help-diagnostics)
                                   "; "))))))
 
@@ -384,6 +367,12 @@ It collects and prints the diagnostics messages."
 (defvar idlwave-system-variables-alist)
 (defvar idlwave-executive-commands-alist)
 (defvar idlwave-system-class-info)
+(defvar idlwave-query-class)
+(defvar idlwave-force-class-query)
+(defvar idlw-help-name)
+(defvar idlw-help-kwd)
+(defvar idlw-help-link)
+
 (defun idlwave-do-context-help1 (&optional arg)
   "The work-horse version of `idlwave-context-help', which see."
   (save-excursion
@@ -549,16 +538,16 @@ It collects and prints the diagnostics messages."
        (setq mod1 (append (list t) module))))
       (if mod3
          (condition-case nil
-             (apply 'idlwave-online-help mod1)
+             (apply #'idlwave-online-help mod1)
            (error (condition-case nil
-                      (apply 'idlwave-online-help mod2)
-                    (error (apply 'idlwave-online-help mod3)))))
+                      (apply #'idlwave-online-help mod2)
+                    (error (apply #'idlwave-online-help mod3)))))
        (if mod2
            (condition-case nil
-               (apply 'idlwave-online-help mod1)
-             (error (apply 'idlwave-online-help mod2)))
+               (apply #'idlwave-online-help mod1)
+             (error (apply #'idlwave-online-help mod2)))
          (if mod1
-             (apply 'idlwave-online-help mod1)
+             (apply #'idlwave-online-help mod1)
            (error "Don't know which item to show help for")))))))
 
 (defun idlwave-do-mouse-completion-help (ev)
@@ -660,7 +649,7 @@ Those words in `idlwave-completion-help-links' have links.  
The
                 (props (list 'face 'idlwave-help-link))
                 (info idlwave-completion-help-info) ; global passed in
                 (what (nth 0 info))  ; what was completed, or a func
-                (class (nth 3 info)) ; any class
+                ;; (class (nth 3 info)) ; any class
                 word beg end doit)
            (goto-char (point-min))
            (re-search-forward "possible completions are:" nil t)
@@ -685,7 +674,7 @@ Those words in `idlwave-completion-help-links' have links.  
The
 
 ;; Arrange for this function to be called after completion
 (add-hook 'idlwave-completion-setup-hook
-         'idlwave-highlight-linked-completions)
+         #'idlwave-highlight-linked-completions)
 
 (defvar idlwave-help-return-frame nil
   "The frame to return to from the help frame.")
@@ -947,7 +936,7 @@ This function can be used as `idlwave-extra-help-function'."
     (point)))
 
 
-(defun idlwave-help-find-routine-definition (name type class keyword)
+(defun idlwave-help-find-routine-definition (name type class _keyword)
   "Find the definition of routine CLASS::NAME in current buffer.
 Returns the point of match if successful, nil otherwise.
 KEYWORD is ignored."
@@ -967,7 +956,7 @@ KEYWORD is ignored."
 
 (defvar idlwave-doclib-start)
 (defvar idlwave-doclib-end)
-(defun idlwave-help-find-in-doc-header (name type class keyword
+(defun idlwave-help-find-in-doc-header (name _type class keyword
                                             &optional exact)
   "Find the requested help in the doc-header above point.
 
@@ -1025,9 +1014,9 @@ If there is a match, we assume it is the keyword 
description."
                   ":[ \t]*$\\)"))
 
         ;; Header start plus name
-        (header-re (concat "\\(" idlwave-doclib-start "\\).*\n"
-                           "\\(^;+.*\n\\)*"
-                           "\\(" name-re "\\)"))
+        ;; (header-re (concat "\\(" idlwave-doclib-start "\\).*\n"
+        ;;                 "\\(^;+.*\n\\)*"
+        ;;                 "\\(" name-re "\\)"))
         ;; A keywords section
         (kwds-re (concat                                   ; forgiving
                   "^;+\\*?[ \t]*"
@@ -1095,8 +1084,8 @@ When DING is non-nil, ring the bell as well."
              (cons string idlwave-help-diagnostics))
        (if ding (ding)))))
 
-(defun idlwave-help-toggle-header-top-and-def (arg)
-  (interactive "P")
+(defun idlwave-help-toggle-header-top-and-def (&optional _arg)
+  (interactive)
   (let (pos)
     (if idlwave-help-in-header
        ;; Header was the last thing displayed
@@ -1119,8 +1108,8 @@ When DING is non-nil, ring the bell as well."
          (goto-char pos)
          (recenter 0)))))
 
-(defun idlwave-help-find-first-header (arg)
-  (interactive "P")
+(defun idlwave-help-find-first-header (&optional _arg)
+  (interactive)
   (let (pos)
     (save-excursion
       (goto-char (point-min))
@@ -1140,8 +1129,8 @@ When DING is non-nil, ring the bell as well."
     (setq idlwave-help-in-header nil)
     (idlwave-help-toggle-header-match-and-def arg 'top)))
 
-(defun idlwave-help-toggle-header-match-and-def (arg &optional top)
-  (interactive "P")
+(defun idlwave-help-toggle-header-match-and-def (&optional _arg top)
+  (interactive)
   (let ((args idlwave-help-args)
        pos)
     (if idlwave-help-in-header
@@ -1150,7 +1139,7 @@ When DING is non-nil, ring the bell as well."
          (setq idlwave-help-in-header nil)
          (setq pos idlwave-help-def-pos))
       ;; Try to display header
-      (setq pos (apply 'idlwave-help-find-in-doc-header
+      (setq pos (apply #'idlwave-help-find-in-doc-header
                       (if top
                           (list (car args) (nth 1 args) (nth 2 args) nil)
                         args)))
@@ -1184,7 +1173,7 @@ Useful when source code is displayed as help.  See the 
option
         (with-no-warnings (font-lock-fontify-buffer))))))
 
 
-(defun idlwave-help-error (name type class keyword)
+(defun idlwave-help-error (name _type class keyword)
   (error "Can't find help on %s%s %s"
         (or (and (or class name) (idlwave-make-full-name class name))
             "<unknown>")
@@ -1272,11 +1261,11 @@ IDL assistant.")
          (delete-process idlwave-help-assistant-socket))
 
       (setq idlwave-help-assistant-process
-           (apply 'start-process
+           (apply #'start-process
                   "IDL_ASSISTANT_PROC" nil command "-server" extra-args))
 
       (set-process-filter idlwave-help-assistant-process
-                         (lambda (proc string)
+                         (lambda (_proc string)
                            (setq port (string-to-number string))))
       (unless (accept-process-output idlwave-help-assistant-process 15)
        (error "Failed binding IDL_ASSISTANT socket"))
diff --git a/lisp/progmodes/idlw-shell.el b/lisp/progmodes/idlw-shell.el
index 4bc5224..134a6c6 100644
--- a/lisp/progmodes/idlw-shell.el
+++ b/lisp/progmodes/idlw-shell.el
@@ -729,7 +729,7 @@ IDL is currently stopped.")
 
 
 (defconst idlwave-shell-halt-messages-re
-  (mapconcat 'identity idlwave-shell-halt-messages "\\|")
+  (mapconcat #'identity idlwave-shell-halt-messages "\\|")
   "The regular expression computed from `idlwave-shell-halt-messages'.")
 
 (defconst idlwave-shell-trace-message-re
@@ -934,8 +934,8 @@ IDL has currently stepped.")
                "[ \t\n]*\\'"))
 
   (when idlwave-shell-query-for-class
-      (add-to-list (make-local-variable 'idlwave-determine-class-special)
-                  'idlwave-shell-get-object-class)
+      (add-hook 'idlwave-determine-class-functions
+               #'idlwave-shell-get-object-class nil t)
       (setq idlwave-store-inquired-class t))
 
   ;; Make sure comint-last-input-end does not go to beginning of
@@ -950,10 +950,10 @@ IDL has currently stepped.")
   (setq idlwave-shell-default-directory default-directory)
   (setq idlwave-shell-hide-output nil)
 
-  (add-hook 'kill-buffer-hook 'idlwave-shell-kill-shell-buffer-confirm
+  (add-hook 'kill-buffer-hook #'idlwave-shell-kill-shell-buffer-confirm
            nil 'local)
-  (add-hook 'kill-buffer-hook 'idlwave-shell-delete-temp-files nil 'local)
-  (add-hook 'kill-emacs-hook 'idlwave-shell-delete-temp-files)
+  (add-hook 'kill-buffer-hook #'idlwave-shell-delete-temp-files nil 'local)
+  (add-hook 'kill-emacs-hook #'idlwave-shell-delete-temp-files)
 
   ;; Set the optional comint variables
   (when idlwave-shell-comint-settings
@@ -962,7 +962,7 @@ IDL has currently stepped.")
        (set (make-local-variable (car entry)) (cdr entry)))))
 
 
-  (unless (memq 'comint-carriage-motion
+  (unless (memq #'comint-carriage-motion
                (default-value 'comint-output-filter-functions))
     ;; Strip those pesky ctrl-m's.
     (add-hook 'comint-output-filter-functions
@@ -976,18 +976,21 @@ IDL has currently stepped.")
                      (while (search-forward "\r" pmark t)
                        (delete-region (point) (line-beginning-position)))))))
                'append 'local)
-    (add-hook 'comint-output-filter-functions 'comint-strip-ctrl-m nil 'local))
+    (add-hook 'comint-output-filter-functions #'comint-strip-ctrl-m nil 
'local))
 
   ;; Python-mode, bundled with many Emacs installs, quite cavalierly
   ;; adds this function to the global default hook.  It interferes
   ;; with overlay-arrows.
-  (remove-hook 'comint-output-filter-functions 'py-pdbtrack-track-stack-file)
+  ;; FIXME: We should fix this interference rather than globally turn it off.
+  (when (fboundp 'py-pdbtrack-track-stack-file)
+    (remove-hook 'comint-output-filter-functions
+                 #'py-pdbtrack-track-stack-file))
 
   ;; IDLWAVE syntax, and turn on abbreviations
   (set (make-local-variable 'comment-start) ";")
   (setq abbrev-mode t)
 
-  (add-hook 'post-command-hook 'idlwave-command-hook nil t)
+  (add-hook 'post-command-hook #'idlwave-command-hook nil t)
 
   ;; Read the command history?
   (when (and idlwave-shell-save-command-history
@@ -1045,7 +1048,7 @@ IDL has currently stepped.")
       (setq idlwave-path-alist old-path-alist))))
 
 (if (not (fboundp 'idl-shell))
-    (fset 'idl-shell 'idlwave-shell))
+    (defalias 'idl-shell #'idlwave-shell))
 
 (defvar idlwave-shell-idl-wframe nil
   "Frame for displaying the IDL shell window.")
@@ -1120,7 +1123,7 @@ See also the variable `idlwave-shell-prompt-pattern'.
        (and idlwave-shell-use-dedicated-frame
             (setq idlwave-shell-idl-wframe (selected-frame)))
        (add-hook 'idlwave-shell-sentinel-hook
-                 'save-buffers-kill-emacs t))
+                 #'save-buffers-kill-emacs t))
 
     ;; A non-nil arg means, we want a dedicated frame.  This will last
     ;; for the current editing session.
@@ -1130,7 +1133,7 @@ See also the variable `idlwave-shell-prompt-pattern'.
     ;; Check if the process still exists.  If not, create it.
     (unless (comint-check-proc (idlwave-shell-buffer))
       (let* ((prg (or idlwave-shell-explicit-file-name "idl"))
-            (buf (apply 'make-comint
+            (buf (apply #'make-comint
                         idlwave-shell-process-name prg nil
                         (if (stringp idlwave-shell-command-line-options)
                             (idlwave-split-string
@@ -1138,8 +1141,8 @@ See also the variable `idlwave-shell-prompt-pattern'.
                           idlwave-shell-command-line-options)))
             (process (get-buffer-process buf)))
        (setq idlwave-idlwave_routine_info-compiled nil)
-       (set-process-filter process 'idlwave-shell-filter)
-       (set-process-sentinel process 'idlwave-shell-sentinel)
+       (set-process-filter process #'idlwave-shell-filter)
+       (set-process-sentinel process #'idlwave-shell-sentinel)
        (set-buffer buf)
        (idlwave-shell-mode)))
     (let ((window (idlwave-display-buffer (idlwave-shell-buffer) nil
@@ -1315,10 +1318,7 @@ See also the variable `idlwave-shell-input-mode-spells'."
     (setq idlwave-shell-char-mode-active 'exit))
    ((string-match (nth 1 idlwave-shell-input-mode-spells) string)
     ;; Set a timer which will soon start the character loop
-    (if (fboundp 'start-itimer)
-       (start-itimer "IDLWAVE Char Mode" 'idlwave-shell-char-mode-loop 0.5
-                     nil nil t 'no-error)
-      (run-at-time 0.5 nil 'idlwave-shell-char-mode-loop 'no-error)))))
+    (run-at-time 0.5 nil #'idlwave-shell-char-mode-loop 'no-error))))
 
 (defvar keyboard-quit)
 (defun idlwave-shell-char-mode-loop (&optional no-error)
@@ -1396,7 +1396,7 @@ Otherwise just move the line.  Move down unless UP is 
non-nil."
   (idlwave-shell-move-or-history nil arg))
 
 (define-obsolete-function-alias 'idlwave-shell-comint-filter
-  'comint-output-filter "25.1")
+  #'comint-output-filter "25.1")
 
 (defun idlwave-shell-is-running ()
   "Return t if the shell process is running."
@@ -1510,13 +1510,12 @@ and then calls `idlwave-shell-send-command' for any 
pending commands."
                                   proc filtered))))))
 
                  ;; Call the post-command hook
-                 (if (listp idlwave-shell-post-command-hook)
-                     (progn
-                       ;;(message "Calling list")
-                       ;;(prin1 idlwave-shell-post-command-hook)
-                       (eval idlwave-shell-post-command-hook))
-                   ;;(message "Calling command function")
-                   (funcall idlwave-shell-post-command-hook))
+                 (if (functionp idlwave-shell-post-command-hook)
+                     ;;(message "Calling command function")
+                     (funcall idlwave-shell-post-command-hook)
+                   ;;(message "Calling list")
+                   ;;(prin1 idlwave-shell-post-command-hook)
+                   (eval idlwave-shell-post-command-hook t))
 
                  ;; Reset to default state for next command.
                  ;; Also we do not want to find this prompt again.
@@ -1690,7 +1689,7 @@ the above."
        (if bp
            (let ((cmd (idlwave-shell-bp-get bp 'cmd)))
              (if cmd ;; Execute any breakpoint command
-                 (if (listp cmd) (eval cmd) (funcall cmd))))
+                 (if (functionp cmd) (funcall cmd) (eval cmd t))))
          ;; A breakpoint that we did not know about - perhaps it was
          ;; set by the user...  Let's update our list.
          (idlwave-shell-bp-query)))
@@ -1819,7 +1818,7 @@ The size is given by 
`idlwave-shell-graphics-window-size'."
   (interactive "P")
   (let ((n (if n (prefix-numeric-value n) 0)))
     (idlwave-shell-send-command
-     (apply 'format "window,%d,xs=%d,ys=%d"
+     (apply #'format "window,%d,xs=%d,ys=%d"
            n idlwave-shell-graphics-window-size)
      nil (idlwave-shell-hide-p 'misc) nil t)))
 
@@ -1891,7 +1890,7 @@ HEAP_GC, /VERBOSE"
     (while (string-match "^PATH:[ \t]*<\\(.*\\)>[ \t]*\n" path-string start)
       (push (match-string 1 path-string) dirs)
       (setq start (match-end 0)))
-    (setq dirs (mapcar 'file-name-as-directory dirs))
+    (setq dirs (mapcar #'file-name-as-directory dirs))
     (if (string-match "^SYSDIR:[ \t]*<\\(.*\\)>[ \t]*\n" path-string)
        (setq sysdir (file-name-as-directory
                      (match-string 1 path-string))))
@@ -1938,13 +1937,14 @@ HEAP_GC, /VERBOSE"
            key (nth 4 specs)
            keys (if (and (stringp key)
                          (not (string-match "\\` *\\'" key)))
-                    (mapcar 'list
+                    (mapcar #'list
                             (delete "" (idlwave-split-string key " +")))))
       (setq name (idlwave-sintern-routine-or-method name class t)
            class (idlwave-sintern-class class t)
            file (if (equal file "") nil file)
            keys (mapcar (lambda (x)
-                          (list (idlwave-sintern-keyword (car x) t))) keys))
+                          (list (idlwave-sintern-keyword (car x) t)))
+                        keys))
 
       ;; In the following ignore routines already defined in buffers,
       ;; assuming that if the buffer stuff differs, it is a "new"
@@ -2053,7 +2053,7 @@ Change the default directory for the process buffer to 
concur."
              (match-string 1 idlwave-shell-command-output)))))
 
 (defvar idlwave-sint-sysvars nil)
-(idlwave-new-sintern-type 'execcomm)
+(idlwave-new-sintern-type execcomm)
 
 (defun idlwave-shell-complete (&optional arg)
   "Do completion in the idlwave-shell buffer.
@@ -2180,7 +2180,7 @@ overlays."
 (defun idlwave-shell-parse-stack-and-display ()
   (let* ((lines (delete "" (idlwave-split-string
                            idlwave-shell-command-output "^%")))
-        (stack (delq nil (mapcar 'idlwave-shell-parse-line lines)))
+        (stack (delq nil (mapcar #'idlwave-shell-parse-line lines)))
         (nmax (1- (length stack)))
         (nmin 0) message)
     (cond
@@ -2710,45 +2710,34 @@ Runs to the last statement and then steps 1 statement.  
Use the .out command."
   (interactive "P")
   (idlwave-shell-print arg 'help))
 
-(defmacro idlwave-shell-mouse-examine (help &optional ev)
-  "Create a function for generic examination of expressions."
-  `(lambda (event)
-     "Expansion function for expression examination."
-     (interactive "e")
-     (let* ((drag-track (fboundp 'mouse-drag-track))
-           (transient-mark-mode t)
-           (tracker
-            ;; Emacs 22 no longer completes the drag with
-            ;; mouse-drag-region, without an additional
-            ;; event.  mouse-drag-track does so.
-            (if drag-track 'mouse-drag-track 'mouse-drag-region)))
-       (funcall tracker event)
-       (idlwave-shell-print (if (region-active-p) '(4) nil)
-                           ,help ,ev))))
-
-;; Begin terrible hack section -- XEmacs tests for button2 explicitly
-;; on drag events, calling drag-n-drop code if detected.  Ughhh...
-(defun idlwave-default-mouse-track-event-is-with-button (_event _n)
-  (declare (obsolete nil "28.1"))
-  t)
-
-(define-obsolete-function-alias 'idlwave-xemacs-hack-mouse-track 'ignore 
"27.1")
+(defun idlwave-shell--mouse-examine (event help &optional ev)
+  "Expansion function for expression examination."
+  (let* ((transient-mark-mode t))
+    (mouse-drag-track event)
+    (idlwave-shell-print (if (region-active-p) '(4) nil)
+                        help ev)))
+
+(define-obsolete-function-alias
+  'idlwave-default-mouse-track-event-is-with-button #'always "28.1")
+
+(define-obsolete-function-alias 'idlwave-xemacs-hack-mouse-track
+  #'ignore "27.1")
 ;;; End terrible hack section
 
 (defun idlwave-shell-mouse-print (event)
   "Print value of variable at the mouse position, with `print'."
   (interactive "e")
-  (funcall (idlwave-shell-mouse-examine nil) event))
+  (idlwave-shell--mouse-examine event nil))
 
 (defun idlwave-shell-mouse-help (event)
   "Print value of variable at the mouse position, with `help'."
   (interactive "e")
-  (funcall (idlwave-shell-mouse-examine 'help) event))
+  (idlwave-shell--mouse-examine event 'help))
 
 (defun idlwave-shell-examine-select (event)
   "Pop-up a list to select from for examining the expression."
   (interactive "e")
-  (funcall (idlwave-shell-mouse-examine nil event) event))
+  (idlwave-shell--mouse-examine event nil event))
 
 (defmacro idlwave-shell-examine (help)
   "Create a function for key-driven expression examination."
@@ -2814,7 +2803,7 @@ from `idlwave-shell-examine-alist' via mini-buffer 
shortcut key."
        (setq beg (region-beginning)
              end (region-end)))
        (t
-       (idlwave-with-special-syntax
+       (with-syntax-table idlwave-find-symbol-syntax-table
         ;; Move to beginning of current or previous expression
         (if (looking-at "\\<\\|(")
             ;; At beginning of expression, don't move backwards unless
@@ -2847,9 +2836,9 @@ from `idlwave-shell-examine-alist' via mini-buffer 
shortcut key."
        (move-overlay idlwave-shell-expression-overlay beg end
                      (current-buffer))
        (add-hook 'pre-command-hook
-                 'idlwave-shell-delete-expression-overlay))
+                 #'idlwave-shell-delete-expression-overlay))
       (add-hook 'pre-command-hook
-               'idlwave-shell-delete-output-overlay)
+               #'idlwave-shell-delete-output-overlay)
 
       ;; Remove empty or comment-only lines
       (while (string-match "\n[ \t]*\\(;.*\\)?\r*\n" expr)
@@ -2881,7 +2870,7 @@ from `idlwave-shell-examine-alist' via mini-buffer 
shortcut key."
 ;;                        "Print")
                        (idlwave-popup-select
                         ev
-                        (mapcar 'car idlwave-shell-examine-alist)
+                        (mapcar #'car idlwave-shell-examine-alist)
                         "Examine with"))
                      idlwave-shell-examine-alist))))
              (setq help (cdr help-cons))
@@ -2916,9 +2905,8 @@ from `idlwave-shell-examine-alist' via mini-buffer 
shortcut key."
   "Variable to hold the win/height pairs for all *Examine* windows.")
 
 (defvar idlwave-shell-examine-map (make-sparse-keymap))
-(define-key idlwave-shell-examine-map "q" 'idlwave-shell-examine-display-quit)
-(define-key idlwave-shell-examine-map "c" 'idlwave-shell-examine-display-clear)
-
+(define-key idlwave-shell-examine-map "q" #'idlwave-shell-examine-display-quit)
+(define-key idlwave-shell-examine-map "c" 
#'idlwave-shell-examine-display-clear)
 
 (defun idlwave-shell-check-compiled-and-display ()
   "Check examine output for warning about undefined procedure/function."
@@ -3347,9 +3335,10 @@ the breakpoint overlays."
                              count nil condition disabled))))))
       (setq idlwave-shell-bp-alist (cdr idlwave-shell-bp-alist))
       ;; Update breakpoint data
-      (if (eq bp-re bp-re54)
-         (mapc 'idlwave-shell-update-bp old-bp-alist)
-       (mapc 'idlwave-shell-update-bp-command-only old-bp-alist))))
+      (mapc (if (eq bp-re bp-re54)
+               #'idlwave-shell-update-bp
+             #'idlwave-shell-update-bp-command-only)
+           old-bp-alist)))
   ;; Update the breakpoint overlays
   (unless no-show (idlwave-shell-update-bp-overlays))
   ;; Return the new list
@@ -3484,7 +3473,7 @@ The actual line number for a breakpoint in IDL may be 
different from
 the line number used with the IDL breakpoint command.
 Looks for a new breakpoint index number in the list.  This is
 considered the new breakpoint if the file name of frame matches."
-  (let ((obp-index (mapcar 'idlwave-shell-bp-get idlwave-shell-old-bp))
+  (let ((obp-index (mapcar #'idlwave-shell-bp-get idlwave-shell-old-bp))
         (bpl idlwave-shell-bp-alist))
     (while (and (member (idlwave-shell-bp-get (car bpl)) obp-index)
                 (setq bpl (cdr bpl))))
@@ -3510,7 +3499,7 @@ considered the new breakpoint if the file name of frame 
matches."
 
 (defvar idlwave-shell-debug-line-map (make-sparse-keymap))
 (define-key idlwave-shell-debug-line-map [mouse-3]
-  'idlwave-shell-mouse-active-bp)
+  #'idlwave-shell-mouse-active-bp)
 
 (defun idlwave-shell-update-bp-overlays ()
   "Update the overlays which mark breakpoints in the source code.
@@ -3532,7 +3521,7 @@ Existing overlays are recycled, in order to minimize 
consumption."
       (setq ov-alist idlwave-shell-bp-overlays
            idlwave-shell-bp-overlays
            (if idlwave-shell-bp-glyph
-               (mapcar 'list (mapcar 'car idlwave-shell-bp-glyph))
+               (mapcar #'list (mapcar #'car idlwave-shell-bp-glyph))
              (list (list 'bp))))
       (while (setq bp (pop bp-list))
        (save-excursion
@@ -3568,7 +3557,7 @@ Existing overlays are recycled, in order to minimize 
consumption."
                             (if help-list
                                 (concat
                                  " - "
-                                 (mapconcat 'identity help-list ", ")))
+                                 (mapconcat #'identity help-list ", ")))
                             (if (and (not count) (not condition))
                                 " (use mouse-3 for breakpoint actions)")))
                 (full-type (if disabled
@@ -3962,73 +3951,73 @@ Otherwise, just expand the file name."
     ;;(define-key map "\M-?" 'comint-dynamic-list-completions)
     ;;(define-key map "\t" 'comint-dynamic-complete)
 
-    (define-key map "\C-w"     'comint-kill-region)
-    (define-key map "\t"       'idlwave-shell-complete)
-    (define-key map "\M-\t"    'idlwave-shell-complete)
-    (define-key map "\C-c\C-s" 'idlwave-shell)
-    (define-key map "\C-c?"    'idlwave-routine-info)
-    (define-key map "\C-g"     'idlwave-keyboard-quit)
-    (define-key map "\M-?"     'idlwave-context-help)
+    (define-key map "\C-w"     #'comint-kill-region)
+    (define-key map "\t"       #'idlwave-shell-complete)
+    (define-key map "\M-\t"    #'idlwave-shell-complete)
+    (define-key map "\C-c\C-s" #'idlwave-shell)
+    (define-key map "\C-c?"    #'idlwave-routine-info)
+    (define-key map "\C-g"     #'idlwave-keyboard-quit)
+    (define-key map "\M-?"     #'idlwave-context-help)
     (define-key map [(control meta ?\?)]
-      'idlwave-help-assistant-help-with-topic)
-    (define-key map "\C-c\C-i" 'idlwave-update-routine-info)
-    (define-key map "\C-c\C-y" 'idlwave-shell-char-mode-loop)
-    (define-key map "\C-c\C-x" 'idlwave-shell-send-char)
-    (define-key map "\C-c="    'idlwave-resolve)
-    (define-key map "\C-c\C-v" 'idlwave-find-module)
-    (define-key map "\C-c\C-k" 'idlwave-kill-autoloaded-buffers)
+      #'idlwave-help-assistant-help-with-topic)
+    (define-key map "\C-c\C-i" #'idlwave-update-routine-info)
+    (define-key map "\C-c\C-y" #'idlwave-shell-char-mode-loop)
+    (define-key map "\C-c\C-x" #'idlwave-shell-send-char)
+    (define-key map "\C-c="    #'idlwave-resolve)
+    (define-key map "\C-c\C-v" #'idlwave-find-module)
+    (define-key map "\C-c\C-k" #'idlwave-kill-autoloaded-buffers)
     (define-key map idlwave-shell-prefix-key
-      'idlwave-shell-debug-map)
-    (define-key map [(up)]  'idlwave-shell-up-or-history)
-    (define-key map [(down)] 'idlwave-shell-down-or-history)
+      #'idlwave-shell-debug-map)
+    (define-key map [(up)]  #'idlwave-shell-up-or-history)
+    (define-key map [(down)] #'idlwave-shell-down-or-history)
     (define-key idlwave-shell-mode-map [(shift mouse-3)]
-      'idlwave-mouse-context-help)
+      #'idlwave-mouse-context-help)
     map)
   "Keymap for `idlwave-mode'.")
 
 (defvar idlwave-shell-electric-debug-mode-map
   (let ((map (make-sparse-keymap)))
     ;; A few extras in the electric debug map
-    (define-key map " " 'idlwave-shell-step)
-    (define-key map "+" 'idlwave-shell-stack-up)
-    (define-key map "=" 'idlwave-shell-stack-up)
-    (define-key map "-" 'idlwave-shell-stack-down)
-    (define-key map "_" 'idlwave-shell-stack-down)
+    (define-key map " " #'idlwave-shell-step)
+    (define-key map "+" #'idlwave-shell-stack-up)
+    (define-key map "=" #'idlwave-shell-stack-up)
+    (define-key map "-" #'idlwave-shell-stack-down)
+    (define-key map "_" #'idlwave-shell-stack-down)
     (define-key map "e" (lambda () (interactive) (idlwave-shell-print '(16))))
-    (define-key map "q" 'idlwave-shell-retall)
+    (define-key map "q" #'idlwave-shell-retall)
     (define-key map "t"
       (lambda () (interactive) (idlwave-shell-send-command "help,/TRACE")))
-    (define-key map [(control ??)]  'idlwave-shell-electric-debug-help)
+    (define-key map [(control ??)]  #'idlwave-shell-electric-debug-help)
     (define-key map "x"
       (lambda (arg) (interactive "P")
         (idlwave-shell-print arg nil nil t)))
     map))
 
 (defvar idlwave-shell-mode-prefix-map (make-sparse-keymap))
-(fset 'idlwave-shell-mode-prefix-map idlwave-shell-mode-prefix-map)
+(defalias 'idlwave-shell-mode-prefix-map idlwave-shell-mode-prefix-map)
 (defvar idlwave-mode-prefix-map (make-sparse-keymap))
-(fset 'idlwave-mode-prefix-map idlwave-mode-prefix-map)
+(defalias 'idlwave-mode-prefix-map idlwave-mode-prefix-map)
 
 (defun idlwave-shell-define-key-both (key hook)
   "Define a key in both the shell and buffer mode maps."
   (define-key idlwave-mode-map key hook)
   (define-key idlwave-shell-mode-map key hook))
-(define-key idlwave-mode-map "\C-c\C-y" 'idlwave-shell-char-mode-loop)
-(define-key idlwave-mode-map "\C-c\C-x" 'idlwave-shell-send-char)
+(define-key idlwave-mode-map "\C-c\C-y" #'idlwave-shell-char-mode-loop)
+(define-key idlwave-mode-map "\C-c\C-x" #'idlwave-shell-send-char)
 
 ;; The mouse bindings for PRINT and HELP
 (idlwave-shell-define-key-both [(shift down-mouse-2)]
-                               'idlwave-shell-mouse-print)
+                               #'idlwave-shell-mouse-print)
 (idlwave-shell-define-key-both [(control meta down-mouse-2)]
-                               'idlwave-shell-mouse-help)
+                               #'idlwave-shell-mouse-help)
 (idlwave-shell-define-key-both [(control shift down-mouse-2)]
-                               'idlwave-shell-examine-select)
+                               #'idlwave-shell-examine-select)
 
 ;; We need to turn off the button release events.
 
-(idlwave-shell-define-key-both [(shift mouse-2)] 'ignore)
-(idlwave-shell-define-key-both [(shift control mouse-2)] 'ignore)
-(idlwave-shell-define-key-both [(control meta mouse-2)] 'ignore)
+(idlwave-shell-define-key-both [(shift mouse-2)] #'ignore)
+(idlwave-shell-define-key-both [(shift control mouse-2)] #'ignore)
+(idlwave-shell-define-key-both [(control meta mouse-2)] #'ignore)
 
 
 ;; The following set of bindings is used to bind the debugging keys.
@@ -4109,8 +4098,8 @@ Otherwise, just expand the file name."
          cmd))))
 
 ; Enter the prefix map in two places.
-(fset 'idlwave-debug-map       idlwave-mode-prefix-map)
-(fset 'idlwave-shell-debug-map idlwave-shell-mode-prefix-map)
+(defalias 'idlwave-debug-map       idlwave-mode-prefix-map)
+(defalias 'idlwave-shell-debug-map idlwave-shell-mode-prefix-map)
 
 ;; The Electric Debug Minor Mode --------------------------------------------
 
@@ -4496,6 +4485,6 @@ static char * file[] = {
   (idlwave-toolbar-toggle))
 
 (if idlwave-shell-use-toolbar
-    (add-hook 'idlwave-shell-mode-hook 'idlwave-toolbar-add-everywhere))
+    (add-hook 'idlwave-shell-mode-hook #'idlwave-toolbar-add-everywhere))
 
 ;;; idlw-shell.el ends here
diff --git a/lisp/progmodes/idlw-toolbar.el b/lisp/progmodes/idlw-toolbar.el
index 4bd0afb..d3f47fc 100644
--- a/lisp/progmodes/idlw-toolbar.el
+++ b/lisp/progmodes/idlw-toolbar.el
@@ -1,4 +1,4 @@
-;;; idlw-toolbar.el --- a debugging toolbar for IDLWAVE
+;;; idlw-toolbar.el --- a debugging toolbar for IDLWAVE  -*- lexical-binding: 
t; -*-
 
 ;; Copyright (C) 1999-2021 Free Software Foundation, Inc.
 
@@ -24,8 +24,8 @@
 
 ;;; Commentary:
 
-;; This file implements a debugging toolbar for IDLWAVE.  It requires
-;; Emacs or XEmacs with toolbar and xpm support.
+;; This file implements a debugging toolbar for IDLWAVE.
+;; It requires toolbar and xpm support.
 
 ;; New versions of IDLWAVE, documentation, and more information
 ;; available from:
@@ -35,22 +35,16 @@
 ;;; Code:
 
 (defun idlwave-toolbar-make-button (image)
-  (if (featurep 'xemacs)
-      (toolbar-make-button-list image)
-    (list 'image :type 'xpm :data image)))
+  (list 'image :type 'xpm :data image))
 
 (defvar idlwave-toolbar)
 (defvar default-toolbar)
 (defvar idlwave-toolbar-is-possible)
 
-(if (not (or (and (featurep 'xemacs)                ; This is XEmacs
-                 (featurep 'xpm)                   ; need xpm
-                 (featurep 'toolbar))              ; ... and the toolbar
-            (and (not (featurep 'xemacs))          ; This is Emacs
-                 (boundp 'tool-bar-button-margin)   ; need toolbar
-                 (fboundp 'image-type-available-p) ; need image stuff
-                 (image-type-available-p 'xpm))    ; need xpm
-            ))
+(if (not (and (boundp 'tool-bar-button-margin)   ; need toolbar
+             (fboundp 'image-type-available-p) ; need image stuff
+             (image-type-available-p 'xpm))    ; need xpm
+        )
     ;; oops - cannot do the toolbar
     (message "Sorry, IDLWAVE xpm toolbar cannot be used on this version of 
Emacs")
 ;; OK, we can define a toolbar
@@ -873,23 +867,12 @@ static char * file[] = {
 
 ;; When the shell exits, arrange to remove the special toolbar everywhere.
 (add-hook 'idlwave-shell-cleanup-hook
-         'idlwave-toolbar-remove-everywhere)
+         #'idlwave-toolbar-remove-everywhere)
 );; End can define toolbar
 
-(defun idlwave-toolbar-add ()
-  "Add the IDLWAVE toolbar if appropriate."
-  (if (and (featurep 'xemacs)    ; This is a noop on Emacs
-          (boundp 'idlwave-toolbar-is-possible)
-          (derived-mode-p 'idlwave-mode 'idlwave-shell-mode))
-      (set-specifier default-toolbar (cons (current-buffer)
-                                          idlwave-toolbar))))
-
-(defun idlwave-toolbar-remove ()
-  "Add the IDLWAVE toolbar if appropriate."
-  (if (and (featurep 'xemacs)    ; This is a noop on Emacs
-          (boundp 'idlwave-toolbar-is-possible)
-           (derived-mode-p 'idlwave-mode 'idlwave-shell-mode))
-      (remove-specifier default-toolbar (current-buffer))))
+(define-obsolete-function-alias 'idlwave-toolbar-add #'ignore "28.1")
+
+(define-obsolete-function-alias 'idlwave-toolbar-remove #'ignore "28.1")
 
 (defvar idlwave-shell-mode-map)
 (defvar idlwave-mode-map)
@@ -898,57 +881,40 @@ static char * file[] = {
   "Add the toolbar in all appropriate buffers."
   (when (boundp 'idlwave-toolbar-is-possible)
 
-    ;; First make sure new buffers will get the toolbar
-    (add-hook 'idlwave-mode-hook 'idlwave-toolbar-add)
     ;; Then add it to all existing buffers
-    (if (featurep 'xemacs)
-       ;; For XEmacs, map over all buffers to add toolbar
-       (save-excursion
-         (mapcar (lambda (buf)
-                   (set-buffer buf)
-                   (idlwave-toolbar-add))
-                 (buffer-list)))
-      ;; For Emacs, add the key definitions to the mode maps
-      (mapc (lambda (x)
-             (let* ((icon (aref x 0))
-                    (func (aref x 1))
-                    (show (aref x 2))
-                    (help (aref x 3))
-                    (key (vector 'tool-bar func))
-                    (def (list 'menu-item
-                               ""
-                               func
-                               :image (symbol-value icon)
-                               :visible show
-                               :help help)))
-               (define-key idlwave-mode-map key def)
-               (define-key idlwave-shell-mode-map key def)))
-           (reverse idlwave-toolbar)))
+    ;; For Emacs, add the key definitions to the mode maps
+    (mapc (lambda (x)
+           (let* ((icon (aref x 0))
+                  (func (aref x 1))
+                  (show (aref x 2))
+                  (help (aref x 3))
+                  (key (vector 'tool-bar func))
+                  (def (list 'menu-item
+                             ""
+                             func
+                             :image (symbol-value icon)
+                             :visible show
+                             :help help)))
+             (define-key idlwave-mode-map key def)
+             (define-key idlwave-shell-mode-map key def)))
+         (reverse idlwave-toolbar))
     (setq idlwave-toolbar-visible t)))
 
 (defun idlwave-toolbar-remove-everywhere ()
   "Remove the toolbar in all appropriate buffers."
   ;; First make sure new buffers won't get the toolbar
   (when idlwave-toolbar-is-possible
-    (remove-hook 'idlwave-mode-hook 'idlwave-toolbar-add)
     ;; Then remove it in all existing buffers.
-    (if (featurep 'xemacs)
-       ;; For XEmacs, map over all buffers to remove toolbar
-       (save-excursion
-         (mapcar (lambda (buf)
-                   (set-buffer buf)
-                   (idlwave-toolbar-remove))
-                 (buffer-list)))
-      ;; For Emacs, remove the key definitions from the mode maps
-      (mapc (lambda (x)
-             (let* (;;(icon (aref x 0))
-                    (func (aref x 1))
-                    ;;(show (aref x 2))
-                    ;;(help (aref x 3))
-                    (key (vector 'tool-bar func)))
-               (define-key idlwave-mode-map key nil)
-               (define-key idlwave-shell-mode-map key nil)))
-           idlwave-toolbar))
+    ;; For Emacs, remove the key definitions from the mode maps
+    (mapc (lambda (x)
+           (let* (;;(icon (aref x 0))
+                  (func (aref x 1))
+                  ;;(show (aref x 2))
+                  ;;(help (aref x 3))
+                  (key (vector 'tool-bar func)))
+             (define-key idlwave-mode-map key nil)
+             (define-key idlwave-shell-mode-map key nil)))
+         idlwave-toolbar)
     (setq idlwave-toolbar-visible nil)))
 
 (defun idlwave-toolbar-toggle (&optional force-on)
@@ -956,11 +922,8 @@ static char * file[] = {
   (if idlwave-toolbar-visible
       (or force-on (idlwave-toolbar-remove-everywhere))
     (idlwave-toolbar-add-everywhere))
-  ;; Now make sure this
-  (if (featurep 'xemacs)
-      nil ; no action necessary, toolbar gets updated automatically
-    ;; On Emacs, redraw the frame to make sure the Toolbar is updated.
-    (redraw-frame)))
+  ;; On Emacs, redraw the frame to make sure the Toolbar is updated.
+  (redraw-frame))
 
 (provide 'idlw-toolbar)
 (provide 'idlwave-toolbar)
diff --git a/lisp/progmodes/idlwave.el b/lisp/progmodes/idlwave.el
index e8e55ae..f53f3f3 100644
--- a/lisp/progmodes/idlwave.el
+++ b/lisp/progmodes/idlwave.el
@@ -1,4 +1,4 @@
-;; idlwave.el --- IDL editing mode for GNU Emacs
+;; idlwave.el --- IDL editing mode for GNU Emacs  -*- lexical-binding: t; -*-
 
 ;; Copyright (C) 1999-2021 Free Software Foundation, Inc.
 
@@ -781,7 +781,7 @@ definitions, use the command `list-abbrevs', for abbrevs 
that move
 point.  Moving point is useful, for example, to place point between
 parentheses of expanded functions.
 
-See `idlwave-check-abbrev'."
+See `idlwave-modify-abbrev'."
   :group 'idlwave-abbrev-and-indent-action
   :type 'boolean)
 
@@ -819,18 +819,19 @@ Has effect only if in abbrev-mode."
 ;; Example actions:
 ;;
 ;;  Capitalize system vars
-;;   (idlwave-action-and-binding idlwave-sysvar '(capitalize-word 1) t)
+;;   (idlwave-action-and-binding idlwave-sysvar
+;;                               (lambda (_) (capitalize-word 1)) t)
 ;;
 ;;  Capitalize procedure name
 ;;   (idlwave-action-and-binding "\\<\\(pro\\|function\\)\\>[ \t]*\\<"
-;;                           '(capitalize-word 1) t)
+;;                               (lambda (_) (capitalize-word 1)) t)
 ;;
 ;;  Capitalize common block name
 ;;   (idlwave-action-and-binding "\\<common\\>[ \t]+\\<"
-;;                           '(capitalize-word 1) t)
+;;                               (lambda (_) (capitalize-word 1)) t)
 ;;  Capitalize label
 ;;   (idlwave-action-and-binding (concat "^[ \t]*" idlwave-label)
-;;                           '(capitalize-word -1) t)
+;;                               (lambda (_) (capitalize-word 1)) t)
 
 (defvar idlwave-indent-action-table nil
   "Associated array containing action lists of search string (car),
@@ -1121,91 +1122,101 @@ As a user, you should not set this to t.")
   
"\\<\\(&&\\|and\\|b\\(egin\\|reak\\)\\|c\\(ase\\|o\\(mpile_opt\\|ntinue\\)\\)\\|do\\|e\\(lse\\|nd\\(case\\|else\\|for\\|if\\|rep\\|switch\\|while\\)?\\|q\\)\\|for\\(ward_function\\)?\\|g\\(oto\\|[et]\\)\\|i\\(f\\|nherits\\)\\|l[et]\\|mod\\|n\\(e\\|ot\\)\\|o\\(n_\\(error\\|ioerror\\)\\|[fr]\\)\\|re\\(peat\\|turn\\)\\|switch\\|then\\|until\\|while\\|xor\\|||\\)\\>")
 
 
-(let* (;; Procedure declarations.  Fontify keyword plus procedure name.
-       ;; Function  declarations.  Fontify keyword plus function  name.
-       (pros-and-functions
-       '("\\<\\(function\\|pro\\)\\>[ \t]+\\(\\sw+\\(::\\sw+\\)?\\)"
-         (1 font-lock-keyword-face)
-         (2 font-lock-function-name-face nil t)))
-
-       ;; Common blocks
-       (common-blocks
-       '("\\<\\(common\\)\\>[ \t]*\\(\\sw+\\)?[ \t]*,?"
-         (1 font-lock-keyword-face)        ; "common"
-         (2 font-lock-constant-face nil t) ; block name
-         ("[ \t]*\\(\\sw+\\)[ ,]*"
-          ;; Start with point after block name and comma
-          nil nil (1 font-lock-variable-name-face))))       ; variable names
-
-       ;; Batch files
-       (batch-files
-       '("^[ \t]*\\(@[^ \t\n]+\\)" (1 font-lock-string-face)))
-
-       ;; Labels
-       (label
-       '("^[ \t]*\\([a-zA-Z]\\sw*:\\)" (1 font-lock-constant-face)))
-
-       ;; The goto statement and its label
-       (goto
-       '("\\(goto\\)[ \t]*,[ \t]*\\([a-zA-Z]\\sw*\\)"
-         (1 font-lock-keyword-face)
-         (2 font-lock-constant-face)))
-
-       ;; Tags in structure definitions.  Note that this definition
-       ;; actually collides with labels, so we have to use the same
-       ;; face.  It also matches named subscript ranges,
-       ;; e.g. vec{bottom:top].  No good way around this.
-       (structtag
-       '("\\<\\([a-zA-Z][a-zA-Z0-9_]*:\\)[^:]" (1 font-lock-constant-face)))
-
-       ;; Structure names
-       (structname
-       '("\\({\\|\\<inherits\\s-\\)\\s-*\\([a-zA-Z][a-zA-Z0-9_]*\\)[},\t \n]"
-         (2 font-lock-function-name-face)))
-
-       ;; Keyword parameters, like /xlog or ,xrange=[]
-       ;; This is anchored to the comma preceding the keyword.
-       ;; Treats continuation lines, works only during whole buffer
-       ;; fontification.  Slow, use it only in fancy fontification.
-       (keyword-parameters
-       '("\\(,\\|[a-zA-Z0-9_](\\)[ \t]*\\(\\$[ \t]*\\(;.*\\)?\n\\([ 
\t]*\\(;.*\\)?\n\\)*[ \t]*\\)?\\(/[a-zA-Z_]\\sw*\\|[a-zA-Z_]\\sw*[ \t]*=\\)"
-         (6 font-lock-constant-face)))
-
-       ;; System variables start with a bang.
-       (system-variables
-       '("\\(![a-zA-Z_0-9]+\\(\\.\\sw+\\)?\\)"
-         (1 font-lock-variable-name-face)))
-
-       ;; Special and unusual operators (not used because too noisy)
-       ;; (special-operators
-       ;;  '("[<>#]" (0 font-lock-keyword-face)))
-
-       ;; All operators (not used because too noisy)
-       ;; (all-operators
-       ;;  '("[-*^#+<>/]" (0 font-lock-keyword-face)))
-
-       ;; Arrows with text property `idlwave-class'
-       (class-arrows
-       '(idlwave-match-class-arrows (0 idlwave-class-arrow-face))))
+(defmacro idlwave--dlet (binders &rest body)
+  "Like `dlet' but without warnings about non-prefixed var names."
+  (declare (indent 1) (debug let))
+  (let ((vars (mapcar (lambda (binder)
+                        (if (consp binder) (car binder) binder))
+                      binders)))
+    `(with-suppressed-warnings ((lexical ,@vars))
+       (dlet ,binders ,@body))))
+
+(idlwave--dlet
+    (;; Procedure declarations.  Fontify keyword plus procedure name.
+     ;; Function  declarations.  Fontify keyword plus function  name.
+     (pros-and-functions
+      '("\\<\\(function\\|pro\\)\\>[ \t]+\\(\\sw+\\(::\\sw+\\)?\\)"
+       (1 font-lock-keyword-face)
+       (2 font-lock-function-name-face nil t)))
+
+     ;; Common blocks
+     (common-blocks
+      '("\\<\\(common\\)\\>[ \t]*\\(\\sw+\\)?[ \t]*,?"
+       (1 font-lock-keyword-face)          ; "common"
+       (2 font-lock-constant-face nil t)   ; block name
+       ("[ \t]*\\(\\sw+\\)[ ,]*"
+        ;; Start with point after block name and comma
+        nil nil (1 font-lock-variable-name-face)))) ; variable names
+
+     ;; Batch files
+     (batch-files
+      '("^[ \t]*\\(@[^ \t\n]+\\)" (1 font-lock-string-face)))
+
+     ;; Labels
+     (label
+      '("^[ \t]*\\([a-zA-Z]\\sw*:\\)" (1 font-lock-constant-face)))
+
+     ;; The goto statement and its label
+     (goto
+      '("\\(goto\\)[ \t]*,[ \t]*\\([a-zA-Z]\\sw*\\)"
+       (1 font-lock-keyword-face)
+       (2 font-lock-constant-face)))
+
+     ;; Tags in structure definitions.  Note that this definition
+     ;; actually collides with labels, so we have to use the same
+     ;; face.  It also matches named subscript ranges,
+     ;; e.g. vec{bottom:top].  No good way around this.
+     (structtag
+      '("\\<\\([a-zA-Z][a-zA-Z0-9_]*:\\)[^:]" (1 font-lock-constant-face)))
+
+     ;; Structure names
+     (structname
+      '("\\({\\|\\<inherits\\s-\\)\\s-*\\([a-zA-Z][a-zA-Z0-9_]*\\)[},\t \n]"
+       (2 font-lock-function-name-face)))
+
+     ;; Keyword parameters, like /xlog or ,xrange=[]
+     ;; This is anchored to the comma preceding the keyword.
+     ;; Treats continuation lines, works only during whole buffer
+     ;; fontification.  Slow, use it only in fancy fontification.
+     (keyword-parameters
+      '("\\(,\\|[a-zA-Z0-9_](\\)[ \t]*\\(\\$[ \t]*\\(;.*\\)?\n\\([ 
\t]*\\(;.*\\)?\n\\)*[ \t]*\\)?\\(/[a-zA-Z_]\\sw*\\|[a-zA-Z_]\\sw*[ \t]*=\\)"
+       (6 font-lock-constant-face)))
+
+     ;; System variables start with a bang.
+     (system-variables
+      '("\\(![a-zA-Z_0-9]+\\(\\.\\sw+\\)?\\)"
+       (1 font-lock-variable-name-face)))
+
+     ;; Special and unusual operators (not used because too noisy)
+     ;; (special-operators
+     ;;  '("[<>#]" (0 font-lock-keyword-face)))
+
+     ;; All operators (not used because too noisy)
+     ;; (all-operators
+     ;;  '("[-*^#+<>/]" (0 font-lock-keyword-face)))
+
+     ;; Arrows with text property `idlwave-class'
+     (class-arrows
+      '(idlwave-match-class-arrows (0 idlwave-class-arrow-face))))
 
   (defconst idlwave-font-lock-keywords-1
     (list pros-and-functions batch-files)
     "Subdued level highlighting for IDLWAVE mode.")
 
   (defconst idlwave-font-lock-keywords-2
-    (mapcar 'symbol-value idlwave-default-font-lock-items)
+    (mapcar #'symbol-value idlwave-default-font-lock-items)
     "Medium level highlighting for IDLWAVE mode.")
 
   (defconst idlwave-font-lock-keywords-3
-       (list pros-and-functions
-             batch-files
-             idlwave-idl-keywords
-             label goto
-             structtag
-             structname
-             common-blocks
-             keyword-parameters
-             system-variables
+    (list pros-and-functions
+         batch-files
+         idlwave-idl-keywords
+         label goto
+         structtag
+         structname
+         common-blocks
+         keyword-parameters
+         system-variables
          class-arrows)
     "Gaudy level highlighting for IDLWAVE mode."))
 
@@ -1312,13 +1323,16 @@ blocks starting with a BEGIN statement.  The matches 
must have associations
    (cons 'call (list (concat "\\(" idlwave-variable "\\) *= *"
                             "\\(" idlwave-method-call "\\s *\\)?"
                             idlwave-identifier
-                            "\\s *(") nil))
+                            "\\s *(")
+                    nil))
    (cons 'call (list (concat
                      "\\(" idlwave-method-call "\\s *\\)?"
                      idlwave-identifier
-                     "\\( *\\($\\|\\$\\)\\|\\s *,\\)") nil))
+                     "\\( *\\($\\|\\$\\)\\|\\s *,\\)")
+                    nil))
    (cons 'assign (list (concat
-                       "\\(" idlwave-variable "\\) *=") nil)))
+                       "\\(" idlwave-variable "\\) *=")
+                      nil)))
 
   "Associated list of statement matching regular expressions.
 Each regular expression matches the start of an IDL statement.
@@ -1333,10 +1347,6 @@ list order matters since matching an assignment 
statement exactly is
 not possible without parsing.  Thus assignment statement become just
 the leftover unidentified statements containing an equal sign.")
 
-;; FIXME: This var seems to only ever be set, but never actually used!
-(defvar idlwave-fill-function 'auto-fill-function
-  "IDL mode auto fill function.")
-
 (defvar idlwave-comment-indent-function 'comment-indent-function
   "IDL mode comment indent function.")
 
@@ -1353,28 +1363,9 @@ Normally a space.")
 
 (defconst idlwave-mode-version "6.1_em22")
 
-(defmacro idlwave-keyword-abbrev (&rest args)
-  "Creates a function for abbrev hooks to call `idlwave-check-abbrev' with 
args."
-  `(lambda ()
-     ,(append '(idlwave-check-abbrev) args)))
-
-;; If I take the time I can replace idlwave-keyword-abbrev with
-;; idlwave-code-abbrev and remove the quoted abbrev check from
-;; idlwave-check-abbrev.  Then, e.g, (idlwave-keyword-abbrev 0 t) becomes
-;; (idlwave-code-abbrev idlwave-check-abbrev 0 t).  In fact I should change
-;; the name of idlwave-check-abbrev to something like idlwave-modify-abbrev.
-
-(defmacro idlwave-code-abbrev (&rest args)
-  "Creates a function for abbrev hooks that ensures abbrevs are not quoted.
-Specifically, if the abbrev is in a comment or string it is unexpanded.
-Otherwise ARGS forms a list that is evaluated."
-  ;; FIXME: it would probably be better to rely on the new :enable-function
-  ;; to enforce the "don't expand in comments or strings".
-  `(lambda ()
-     ,(prin1-to-string args)  ;; Puts the code in the doc string
-     (if (idlwave-quoted)
-         (progn (unexpand-abbrev) nil)
-       ,(append args))))
+(defun idlwave-keyword-abbrev (&rest args)
+  "Create a function for abbrev hooks to call `idlwave-modify-abbrev' with 
args."
+  (lambda () (append #'idlwave-modify-abbrev args)))
 
 (autoload 'idlwave-shell "idlw-shell"
   "Run an inferior IDL, with I/O through buffer `(idlwave-shell-buffer)'." t)
@@ -1388,41 +1379,41 @@ Otherwise ARGS forms a list that is evaluated."
 (autoload 'idlwave-shell-run-region "idlw-shell"
   "Compile and run the region." t)
 
-(fset 'idlwave-debug-map (make-sparse-keymap))
+(defalias 'idlwave-debug-map (make-sparse-keymap))
 
 (defvar idlwave-mode-map
   (let ((map (make-sparse-keymap)))
-    (define-key map "\C-c "    'idlwave-hard-tab)
-    (define-key map [(control tab)] 'idlwave-hard-tab)
-    ;;(define-key map "\C-c\C- " 'idlwave-hard-tab)
-    (define-key map "'"        'idlwave-show-matching-quote)
-    (define-key map "\""       'idlwave-show-matching-quote)
-    (define-key map "\C-g"     'idlwave-keyboard-quit)
-    (define-key map "\C-c;"    'idlwave-toggle-comment-region)
-    (define-key map "\C-\M-a"  'idlwave-beginning-of-subprogram)
-    (define-key map "\C-\M-e"  'idlwave-end-of-subprogram)
-    (define-key map "\C-c{"    'idlwave-beginning-of-block)
-    (define-key map "\C-c}"    'idlwave-end-of-block)
-    (define-key map "\C-c]"    'idlwave-close-block)
-    (define-key map [(meta control h)] 'idlwave-mark-subprogram)
-    (define-key map "\M-\C-n"  'idlwave-forward-block)
-    (define-key map "\M-\C-p"  'idlwave-backward-block)
-    (define-key map "\M-\C-d"  'idlwave-down-block)
-    (define-key map "\M-\C-u"  'idlwave-backward-up-block)
-    (define-key map "\M-\r"    'idlwave-split-line)
-    (define-key map "\M-\C-q"  'idlwave-indent-subprogram)
-    (define-key map "\C-c\C-p" 'idlwave-previous-statement)
-    (define-key map "\C-c\C-n" 'idlwave-next-statement)
-    ;; (define-key map "\r"       'idlwave-newline)
-    ;; (define-key map "\t"       'idlwave-indent-line)
-    (define-key map [(shift iso-lefttab)] 'idlwave-indent-statement)
-    (define-key map "\C-c\C-a" 'idlwave-auto-fill-mode)
-    (define-key map "\M-q"     'idlwave-fill-paragraph)
-    (define-key map "\M-s"     'idlwave-edit-in-idlde)
-    (define-key map "\C-c\C-h" 'idlwave-doc-header)
-    (define-key map "\C-c\C-m" 'idlwave-doc-modification)
-    (define-key map "\C-c\C-c" 'idlwave-case)
-    (define-key map "\C-c\C-d" 'idlwave-debug-map)
+    (define-key map "\C-c "    #'idlwave-hard-tab)
+    (define-key map [(control tab)] #'idlwave-hard-tab)
+    ;;(define-key map "\C-c\C- " #'idlwave-hard-tab)
+    (define-key map "'"        #'idlwave-show-matching-quote)
+    (define-key map "\""       #'idlwave-show-matching-quote)
+    (define-key map "\C-g"     #'idlwave-keyboard-quit)
+    (define-key map "\C-c;"    #'idlwave-toggle-comment-region)
+    (define-key map "\C-\M-a"  #'idlwave-beginning-of-subprogram)
+    (define-key map "\C-\M-e"  #'idlwave-end-of-subprogram)
+    (define-key map "\C-c{"    #'idlwave-beginning-of-block)
+    (define-key map "\C-c}"    #'idlwave-end-of-block)
+    (define-key map "\C-c]"    #'idlwave-close-block)
+    (define-key map [(meta control h)] #'idlwave-mark-subprogram)
+    (define-key map "\M-\C-n"  #'idlwave-forward-block)
+    (define-key map "\M-\C-p"  #'idlwave-backward-block)
+    (define-key map "\M-\C-d"  #'idlwave-down-block)
+    (define-key map "\M-\C-u"  #'idlwave-backward-up-block)
+    (define-key map "\M-\r"    #'idlwave-split-line)
+    (define-key map "\M-\C-q"  #'idlwave-indent-subprogram)
+    (define-key map "\C-c\C-p" #'idlwave-previous-statement)
+    (define-key map "\C-c\C-n" #'idlwave-next-statement)
+    ;; (define-key map "\r"       #'idlwave-newline)
+    ;; (define-key map "\t"       #'idlwave-indent-line)
+    (define-key map [(shift iso-lefttab)] #'idlwave-indent-statement)
+    (define-key map "\C-c\C-a" #'auto-fill-mode)
+    (define-key map "\M-q"     #'idlwave-fill-paragraph)
+    (define-key map "\M-s"     #'idlwave-edit-in-idlde)
+    (define-key map "\C-c\C-h" #'idlwave-doc-header)
+    (define-key map "\C-c\C-m" #'idlwave-doc-modification)
+    (define-key map "\C-c\C-c" #'idlwave-case)
+    (define-key map "\C-c\C-d" #'idlwave-debug-map)
     (when (and (listp idlwave-shell-debug-modifiers)
                (not (equal idlwave-shell-debug-modifiers '())))
       ;; Bind the debug commands also with the special modifiers.
@@ -1431,38 +1422,39 @@ Otherwise ARGS forms a list that is evaluated."
              (delq 'shift (copy-sequence idlwave-shell-debug-modifiers))))
         (define-key map
           (vector (append mods-noshift (list (if shift ?C ?c))))
-          'idlwave-shell-save-and-run)
+          #'idlwave-shell-save-and-run)
         (define-key map
           (vector (append mods-noshift (list (if shift ?B ?b))))
-          'idlwave-shell-break-here)
+          #'idlwave-shell-break-here)
         (define-key map
           (vector (append mods-noshift (list (if shift ?E ?e))))
-          'idlwave-shell-run-region)))
-    (define-key map "\C-c\C-d\C-c" 'idlwave-shell-save-and-run)
-    (define-key map "\C-c\C-d\C-b" 'idlwave-shell-break-here)
-    (define-key map "\C-c\C-d\C-e" 'idlwave-shell-run-region)
-    (define-key map "\C-c\C-f" 'idlwave-for)
-    ;;  (define-key map "\C-c\C-f" 'idlwave-function)
-    ;;  (define-key map "\C-c\C-p" 'idlwave-procedure)
-    (define-key map "\C-c\C-r" 'idlwave-repeat)
-    (define-key map "\C-c\C-w" 'idlwave-while)
-    (define-key map "\C-c\C-k" 'idlwave-kill-autoloaded-buffers)
-    (define-key map "\C-c\C-s" 'idlwave-shell)
-    (define-key map "\C-c\C-l" 'idlwave-shell-recenter-shell-window)
-    (define-key map "\C-c\C-b" 'idlwave-list-buffer-load-path-shadows)
-    (define-key map "\C-c\C-v"   'idlwave-find-module)
-    (define-key map "\C-c\C-t"   'idlwave-find-module-this-file)
-    (define-key map "\C-c?"      'idlwave-routine-info)
-    (define-key map "\M-?"       'idlwave-context-help)
+          #'idlwave-shell-run-region)))
+    (define-key map "\C-c\C-d\C-c" #'idlwave-shell-save-and-run)
+    (define-key map "\C-c\C-d\C-b" #'idlwave-shell-break-here)
+    (define-key map "\C-c\C-d\C-e" #'idlwave-shell-run-region)
+    (define-key map "\C-c\C-f" #'idlwave-for)
+    ;;  (define-key map "\C-c\C-f" #'idlwave-function)
+    ;;  (define-key map "\C-c\C-p" #'idlwave-procedure)
+    (define-key map "\C-c\C-r" #'idlwave-repeat)
+    (define-key map "\C-c\C-w" #'idlwave-while)
+    (define-key map "\C-c\C-k" #'idlwave-kill-autoloaded-buffers)
+    (define-key map "\C-c\C-s" #'idlwave-shell)
+    (define-key map "\C-c\C-l" #'idlwave-shell-recenter-shell-window)
+    (define-key map "\C-c\C-b" #'idlwave-list-buffer-load-path-shadows)
+    (define-key map "\C-c\C-v"   #'idlwave-find-module)
+    (define-key map "\C-c\C-t"   #'idlwave-find-module-this-file)
+    (define-key map "\C-c?"      #'idlwave-routine-info)
+    (define-key map "\M-?"       #'idlwave-context-help)
     (define-key map [(control meta ?\?)]
-      'idlwave-help-assistant-help-with-topic)
+      #'idlwave-help-assistant-help-with-topic)
     ;; Pickup both forms of Esc/Meta binding
-    (define-key map [(meta tab)] 'idlwave-complete)
-    (define-key map [?\e?\t] 'idlwave-complete)
-    (define-key map "\M-\C-i" 'idlwave-complete)
-    (define-key map "\C-c\C-i" 'idlwave-update-routine-info)
-    (define-key map "\C-c="    'idlwave-resolve)
-    (define-key map [(shift mouse-3)] 'idlwave-mouse-context-help)
+    ;; FIXME: Use `completion-at-point'!
+    (define-key map [(meta tab)] #'idlwave-complete)
+    (define-key map [?\e?\t] #'idlwave-complete)
+    (define-key map "\M-\C-i" #'idlwave-complete)
+    (define-key map "\C-c\C-i" #'idlwave-update-routine-info)
+    (define-key map "\C-c="    #'idlwave-resolve)
+    (define-key map [(shift mouse-3)] #'idlwave-mouse-context-help)
     map)
   "Keymap used in IDL mode.")
 
@@ -1501,28 +1493,15 @@ Otherwise ARGS forms a list that is evaluated."
     st)
   "Syntax table that treats symbol characters as word characters.")
 
-(defmacro idlwave-with-special-syntax (&rest body)
-  "Execute BODY with a different syntax table."
-  `(let ((saved-syntax (syntax-table)))
-     (unwind-protect
-        (progn
-          (set-syntax-table idlwave-find-symbol-syntax-table)
-          ,@body)
-       (set-syntax-table saved-syntax))))
-
-;(defmacro idlwave-with-special-syntax1 (&rest body)
-;  "Execute BODY with a different syntax table."
-;  `(let ((saved-syntax (syntax-table)))
-;     (unwind-protect
-;        (progn
-;          (set-syntax-table idlwave-find-symbol-syntax-table)
-;          ,@body)
-;      (set-syntax-table saved-syntax))))
+;;(defmacro idlwave-with-special-syntax (&rest body)
+;;  "Execute BODY with `idlwave-find-symbol-syntax-table'."
+;;  `(with-syntax-table idlwave-find-symbol-syntax-table
+;;     ,@body))
 
 (defun idlwave-action-and-binding (key cmd &optional select)
   "KEY and CMD are made into a key binding and an indent action.
 KEY is a string - same as for the `define-key' function.  CMD is a
-function of no arguments or a list to be evaluated.  CMD is bound to
+function of one argument.  CMD is bound to
 KEY in `idlwave-mode-map' by defining an anonymous function calling
 `self-insert-command' followed by CMD.  If KEY contains more than one
 character a binding will only be set if SELECT is `both'.
@@ -1539,62 +1518,59 @@ Otherwise, if SELECT is non-nil then only an action is 
created.
 
 Some examples:
 No spaces before and 1 after a comma
-   (idlwave-action-and-binding \",\"  \\='(idlwave-surround 0 1))
+   (idlwave-action-and-binding \",\"  (lambda (_) (idlwave-surround 0 1)))
 A minimum of 1 space before and after `=' (see `idlwave-expand-equal').
-   (idlwave-action-and-binding \"=\"  \\='(idlwave-expand-equal -1 -1))
+   (idlwave-action-and-binding \"=\"  (lambda (_) (idlwave-expand-equal -1 
-1)))
 Capitalize system variables - action only
-   (idlwave-action-and-binding idlwave-sysvar \\='(capitalize-word 1) t)"
+   (idlwave-action-and-binding idlwave-sysvar (lambda (_) (capitalize-word 1) 
t))"
   (if (not (equal select 'noaction))
       ;; Add action
       (let* ((table (if select 'idlwave-indent-action-table
                       'idlwave-indent-expand-table))
-            (table-key (regexp-quote key))
-             (cell (assoc table-key (eval table))))
-        (if cell
-            ;; Replace action command
-            (setcdr cell cmd)
-          ;; New action
-          (set table (append (eval table) (list (cons table-key cmd)))))))
+            (table-key (regexp-quote key)))
+        (setf (alist-get table-key (symbol-value table) nil nil #'equal) cmd)))
   ;; Make key binding for action
-  (if (or (and (null select) (= (length key) 1))
-          (equal select 'noaction)
-          (equal select 'both))
+  (if (if (null select) (= (length key) 1)
+        (memq select '(noaction both)))
+      ;; FIXME: Use `post-self-insert-hook'!
       (define-key idlwave-mode-map key
-        `(lambda ()
-           (interactive)
-           (self-insert-command 1)
-           ,(if (listp cmd) cmd (list cmd))))))
+        (lambda ()
+          (interactive)
+          (self-insert-command 1)
+          (if (functionp cmd) (funcall cmd nil) (eval cmd t))))))
 
 ;; Set action and key bindings.
 ;; See description of the function `idlwave-action-and-binding'.
 ;; Automatically add spaces for the following characters
 
 ;; Actions for & are complicated by &&
-(idlwave-action-and-binding "&"  'idlwave-custom-ampersand-surround)
+(idlwave-action-and-binding "&" #'idlwave-custom-ampersand-surround)
 
 ;; Automatically add spaces to equal sign if not keyword.  This needs
 ;; to go ahead of > and <, so >= and <= will be treated correctly
-(idlwave-action-and-binding "="  '(idlwave-expand-equal -1 -1))
+(idlwave-action-and-binding "=" (lambda (_) (idlwave-expand-equal -1 -1)))
 
 ;; Actions for > and < are complicated by >=, <=, and ->...
-(idlwave-action-and-binding "<"  '(idlwave-custom-ltgtr-surround nil))
-(idlwave-action-and-binding ">"  '(idlwave-custom-ltgtr-surround 'gtr))
+(idlwave-action-and-binding "<" (lambda (a) (idlwave-custom-ltgtr-surround nil 
a)))
+(idlwave-action-and-binding ">" (lambda (a) (idlwave-custom-ltgtr-surround t 
a)))
 
-(idlwave-action-and-binding ","  '(idlwave-surround 0 -1 1))
+(idlwave-action-and-binding "," (lambda (a) (idlwave-surround 0 -1 1 a)))
 
 
 ;;;
 ;;; Abbrev Section
 ;;;
-;;; When expanding abbrevs and the abbrev hook moves backward, an extra
-;;; space is inserted (this is the space typed by the user to expanded
-;;; the abbrev).
-;;;
-(defvar idlwave-mode-abbrev-table nil
-  "Abbreviation table used for IDLWAVE mode.")
-(define-abbrev-table 'idlwave-mode-abbrev-table ())
+;; When expanding abbrevs and the abbrev hook moves backward, an extra
+;; space is inserted (this is the space typed by the user to expanded
+;; the abbrev).
+;; FIXME: This can be controlled with `no-self-insert' property.
+;;
+(define-abbrev-table 'idlwave-mode-abbrev-table ()
+  "Abbreviation table used for IDLWAVE mode."
+  :enable-function (lambda () (not (idlwave-quoted))))
 
 (defun idlwave-define-abbrev (name expansion hook &optional noprefix table)
+  ;; FIXME: `table' is never passed.
   "Define-abbrev with backward compatibility.
 
 If NOPREFIX is non-nil, don't prepend prefix character.  Installs into
@@ -1605,8 +1581,8 @@ If NOPREFIX is non-nil, don't prepend prefix character.  
Installs into
                    expansion
                    hook)))
     (condition-case nil
-       (apply 'define-abbrev (append args '(0 t)))
-      (error (apply 'define-abbrev args)))))
+       (apply #'define-abbrev (append args '(0 t)))
+      (error (apply #'define-abbrev args)))))
 
 (condition-case nil
     (modify-syntax-entry (string-to-char idlwave-abbrev-start-char)
@@ -1616,15 +1592,15 @@ If NOPREFIX is non-nil, don't prepend prefix character. 
 Installs into
 ;;
 ;; Templates
 ;;
-(idlwave-define-abbrev "c"   "" (idlwave-code-abbrev idlwave-case))
-(idlwave-define-abbrev "sw"  "" (idlwave-code-abbrev idlwave-switch))
-(idlwave-define-abbrev "f"   "" (idlwave-code-abbrev idlwave-for))
-(idlwave-define-abbrev "fu"  "" (idlwave-code-abbrev idlwave-function))
-(idlwave-define-abbrev "pr"  "" (idlwave-code-abbrev idlwave-procedure))
-(idlwave-define-abbrev "r"   "" (idlwave-code-abbrev idlwave-repeat))
-(idlwave-define-abbrev "w"   "" (idlwave-code-abbrev idlwave-while))
-(idlwave-define-abbrev "i"   "" (idlwave-code-abbrev idlwave-if))
-(idlwave-define-abbrev "elif" "" (idlwave-code-abbrev idlwave-elif))
+(idlwave-define-abbrev "c"    "" #'idlwave-case)
+(idlwave-define-abbrev "sw"   "" #'idlwave-switch)
+(idlwave-define-abbrev "f"    "" #'idlwave-for)
+(idlwave-define-abbrev "fu"   "" #'idlwave-function)
+(idlwave-define-abbrev "pr"   "" #'idlwave-procedure)
+(idlwave-define-abbrev "r"    "" #'idlwave-repeat)
+(idlwave-define-abbrev "w"    "" #'idlwave-while)
+(idlwave-define-abbrev "i"    "" #'idlwave-if)
+(idlwave-define-abbrev "elif" "" #'idlwave-elif)
 ;;
 ;; Keywords, system functions, conversion routines
 ;;
@@ -1639,15 +1615,15 @@ If NOPREFIX is non-nil, don't prepend prefix character. 
 Installs into
 (idlwave-define-abbrev "cc" "complex()"    (idlwave-keyword-abbrev 1))
 (idlwave-define-abbrev "cd" "double()"     (idlwave-keyword-abbrev 1))
 (idlwave-define-abbrev "e"  "else"         (idlwave-keyword-abbrev 0 t))
-(idlwave-define-abbrev "ec" "endcase"      'idlwave-show-begin)
-(idlwave-define-abbrev "es" "endswitch"    'idlwave-show-begin)
-(idlwave-define-abbrev "ee" "endelse"      'idlwave-show-begin)
-(idlwave-define-abbrev "ef" "endfor"       'idlwave-show-begin)
-(idlwave-define-abbrev "ei" "endif else if" 'idlwave-show-begin)
-(idlwave-define-abbrev "el" "endif else"   'idlwave-show-begin)
-(idlwave-define-abbrev "en" "endif"        'idlwave-show-begin)
-(idlwave-define-abbrev "er" "endrep"       'idlwave-show-begin)
-(idlwave-define-abbrev "ew" "endwhile"     'idlwave-show-begin)
+(idlwave-define-abbrev "ec" "endcase"      #'idlwave-show-begin)
+(idlwave-define-abbrev "es" "endswitch"    #'idlwave-show-begin)
+(idlwave-define-abbrev "ee" "endelse"      #'idlwave-show-begin)
+(idlwave-define-abbrev "ef" "endfor"       #'idlwave-show-begin)
+(idlwave-define-abbrev "ei" "endif else if" #'idlwave-show-begin)
+(idlwave-define-abbrev "el" "endif else"   #'idlwave-show-begin)
+(idlwave-define-abbrev "en" "endif"        #'idlwave-show-begin)
+(idlwave-define-abbrev "er" "endrep"       #'idlwave-show-begin)
+(idlwave-define-abbrev "ew" "endwhile"     #'idlwave-show-begin)
 (idlwave-define-abbrev "g"  "goto,"        (idlwave-keyword-abbrev 0 t))
 (idlwave-define-abbrev "h"  "help,"        (idlwave-keyword-abbrev 0))
 (idlwave-define-abbrev "k"  "keyword_set()" (idlwave-keyword-abbrev 1))
@@ -1695,15 +1671,15 @@ If NOPREFIX is non-nil, don't prepend prefix character. 
 Installs into
 (idlwave-define-abbrev "continue"   "continue"  (idlwave-keyword-abbrev 0 t) t)
 (idlwave-define-abbrev "do"         "do"        (idlwave-keyword-abbrev 0 t) t)
 (idlwave-define-abbrev "else"       "else"      (idlwave-keyword-abbrev 0 t) t)
-(idlwave-define-abbrev "end"        "end"       'idlwave-show-begin-check t)
-(idlwave-define-abbrev "endcase"    "endcase"   'idlwave-show-begin-check t)
-(idlwave-define-abbrev "endelse"    "endelse"   'idlwave-show-begin-check t)
-(idlwave-define-abbrev "endfor"     "endfor"    'idlwave-show-begin-check t)
-(idlwave-define-abbrev "endif"      "endif"     'idlwave-show-begin-check t)
-(idlwave-define-abbrev "endrep"     "endrep"    'idlwave-show-begin-check t)
-(idlwave-define-abbrev "endswitch"  "endswitch" 'idlwave-show-begin-check t)
-(idlwave-define-abbrev "endwhi"     "endwhi"    'idlwave-show-begin-check t)
-(idlwave-define-abbrev "endwhile"   "endwhile"  'idlwave-show-begin-check t)
+(idlwave-define-abbrev "end"        "end"       #'idlwave-show-begin-check t)
+(idlwave-define-abbrev "endcase"    "endcase"   #'idlwave-show-begin-check t)
+(idlwave-define-abbrev "endelse"    "endelse"   #'idlwave-show-begin-check t)
+(idlwave-define-abbrev "endfor"     "endfor"    #'idlwave-show-begin-check t)
+(idlwave-define-abbrev "endif"      "endif"     #'idlwave-show-begin-check t)
+(idlwave-define-abbrev "endrep"     "endrep"    #'idlwave-show-begin-check t)
+(idlwave-define-abbrev "endswitch"  "endswitch" #'idlwave-show-begin-check t)
+(idlwave-define-abbrev "endwhi"     "endwhi"    #'idlwave-show-begin-check t)
+(idlwave-define-abbrev "endwhile"   "endwhile"  #'idlwave-show-begin-check t)
 (idlwave-define-abbrev "eq"         "eq"        (idlwave-keyword-abbrev 0 t) t)
 (idlwave-define-abbrev "for"        "for"       (idlwave-keyword-abbrev 0 t) t)
 (idlwave-define-abbrev "function"   "function"  (idlwave-keyword-abbrev 0 t) t)
@@ -1763,7 +1739,7 @@ The main features of this mode are
    Use \\[idlwave-fill-paragraph] to refill a paragraph inside a
    comment.  The indentation of the second line of the paragraph
    relative to the first will be retained.  Use
-   \\[idlwave-auto-fill-mode] to toggle auto-fill mode for these
+   \\[auto-fill-mode] to toggle auto-fill mode for these
    comments.  When the variable `idlwave-fill-comment-line-only' is
    nil, code can also be auto-filled and auto-indented.
 
@@ -1861,7 +1837,7 @@ The main features of this mode are
       (message "Emacs IDLWAVE mode version %s." idlwave-mode-version))
   (setq idlwave-startup-message nil)
 
-  (set (make-local-variable 'indent-line-function) 'idlwave-indent-and-action)
+  (set (make-local-variable 'indent-line-function) #'idlwave-indent-and-action)
 
   (set (make-local-variable idlwave-comment-indent-function)
        #'idlwave-comment-hook)
@@ -1875,7 +1851,7 @@ The main features of this mode are
 
   (setq abbrev-mode t)
 
-  (set (make-local-variable idlwave-fill-function) 'idlwave-auto-fill)
+  (set (make-local-variable 'normal-auto-fill-function) #'idlwave-auto-fill)
   (setq comment-end "")
   (set (make-local-variable 'comment-multi-line) nil)
   (set (make-local-variable 'paragraph-separate)
@@ -1886,26 +1862,27 @@ The main features of this mode are
 
   ;; ChangeLog
   (set (make-local-variable 'add-log-current-defun-function)
-       'idlwave-current-routine-fullname)
+       #'idlwave-current-routine-fullname)
 
   ;; Set tag table list to use IDLTAGS as file name.
   (if (boundp 'tag-table-alist)
-      (add-to-list 'tag-table-alist '("\\.pro$" . "IDLTAGS")))
+      (add-to-list 'tag-table-alist '("\\.pro\\'" . "IDLTAGS")))
 
   ;; Font-lock additions
   (set (make-local-variable 'font-lock-defaults) idlwave-font-lock-defaults)
   (set (make-local-variable 'font-lock-mark-block-function)
-       'idlwave-mark-subprogram)
+       #'idlwave-mark-subprogram)
   (set (make-local-variable 'font-lock-fontify-region-function)
-       'idlwave-font-lock-fontify-region)
+       #'idlwave-font-lock-fontify-region)
 
   ;; Imenu setup
-  (set (make-local-variable 'imenu-create-index-function)
-       'imenu-default-create-index-function)
+  ;;(set (make-local-variable 'imenu-create-index-function)
+  ;;     ;; FIXME: Why set it explicitly to the value it already has?
+  ;;     #'imenu-default-create-index-function)
   (set (make-local-variable 'imenu-extract-index-name-function)
-       'idlwave-unit-name)
+       #'idlwave-unit-name)
   (set (make-local-variable 'imenu-prev-index-position-function)
-       'idlwave-prev-index-position)
+       #'idlwave-prev-index-position)
 
   ;; HideShow setup
   (add-to-list 'hs-special-modes-alist
@@ -1916,12 +1893,12 @@ The main features of this mode are
                     'idlwave-forward-block nil))
 
   ;; Make a local post-command-hook and add our hook to it
-  (add-hook 'post-command-hook 'idlwave-command-hook nil 'local)
+  (add-hook 'post-command-hook #'idlwave-command-hook nil 'local)
 
   ;; Make local hooks for buffer updates
-  (add-hook 'kill-buffer-hook 'idlwave-kill-buffer-update nil 'local)
-  (add-hook 'after-save-hook 'idlwave-save-buffer-update nil 'local)
-  (add-hook 'after-save-hook 'idlwave-revoke-license-to-kill nil 'local)
+  (add-hook 'kill-buffer-hook #'idlwave-kill-buffer-update nil 'local)
+  (add-hook 'after-save-hook #'idlwave-save-buffer-update nil 'local)
+  (add-hook 'after-save-hook #'idlwave-revoke-license-to-kill nil 'local)
 
   ;; Setup directories and file, if necessary
   (idlwave-setup)
@@ -1974,29 +1951,27 @@ The main features of this mode are
 
 ;;; This stuff is experimental
 
-(defvar idlwave-command-hook nil
-  "If non-nil, a list that can be evaluated using `eval'.
+(defvar idlwave--command-function nil
+  "If non-nil, a function called from `post-command-hook'.
 It is evaluated in the lisp function `idlwave-command-hook' which is
 placed in `post-command-hook'.")
 
 (defun idlwave-command-hook ()
   "Command run after every command.
-Evaluates a non-nil value of the *variable* `idlwave-command-hook' and
+Evaluates a non-nil value of the *variable* `idlwave--command-function' and
 sets the variable to zero afterwards."
-  (and idlwave-command-hook
-       (listp idlwave-command-hook)
-       (condition-case nil
-          (eval idlwave-command-hook)
-        (error nil)))
-  (setq idlwave-command-hook nil))
+  (and idlwave--command-function
+       (with-demoted-errors "idlwave-command-hook: %S"
+        (funcall (prog1 idlwave--command-function
+                   (setq idlwave--command-function nil))))))
 
 ;;; End experiment
 
 ;; It would be better to use expand.el for better abbrev handling and
 ;; versatility.
 
-(defun idlwave-check-abbrev (arg &optional reserved)
-  "Reverse abbrev expansion if in comment or string.
+(defun idlwave-modify-abbrev (arg &optional reserved)
+  "Tweak the abbrev we just expanded.
 Argument ARG is the number of characters to move point
 backward if `idlwave-abbrev-move' is non-nil.
 If optional argument RESERVED is non-nil then the expansion
@@ -2006,21 +1981,16 @@ Otherwise, the abbrev will be capitalized if 
`idlwave-abbrev-change-case'
 is non-nil, unless its value is `down' in which case the abbrev will be
 made into all lowercase.
 Returns non-nil if abbrev is left expanded."
-  (if (idlwave-quoted)
-      (progn (unexpand-abbrev)
-             nil)
-    (if (and reserved idlwave-reserved-word-upcase)
-        (upcase-region last-abbrev-location (point))
-      (cond
-       ((equal idlwave-abbrev-change-case 'down)
-        (downcase-region last-abbrev-location (point)))
-       (idlwave-abbrev-change-case
-        (upcase-region last-abbrev-location (point)))))
-    (if (and idlwave-abbrev-move (> arg 0))
-        (if (boundp 'post-command-hook)
-            (setq idlwave-command-hook (list 'backward-char (1+ arg)))
-          (backward-char arg)))
-    t))
+  (if (and reserved idlwave-reserved-word-upcase)
+      (upcase-region last-abbrev-location (point))
+    (cond
+     ((equal idlwave-abbrev-change-case 'down)
+      (downcase-region last-abbrev-location (point)))
+     (idlwave-abbrev-change-case
+      (upcase-region last-abbrev-location (point)))))
+  (if (and idlwave-abbrev-move (> arg 0))
+      (setq idlwave--command-function (lambda () (backward-char (1+ arg)))))
+  t)
 
 (defun idlwave-in-comment ()
   "Return t if point is inside a comment, nil otherwise."
@@ -2047,7 +2017,7 @@ Returns point if comment found and nil otherwise."
            (backward-char 1)
            (point)))))
 
-(define-obsolete-function-alias 'idlwave-region-active-p 'use-region-p "28.1")
+(define-obsolete-function-alias 'idlwave-region-active-p #'use-region-p "28.1")
 
 (defun idlwave-show-matching-quote ()
   "Insert quote and show matching quote if this is end of a string."
@@ -2067,13 +2037,12 @@ Returns point if comment found and nil otherwise."
 (defun idlwave-show-begin-check ()
   "Ensure that the previous word was a token before `idlwave-show-begin'.
 An END token must be preceded by whitespace."
-  (if (not (idlwave-quoted))
-      (if
-         (save-excursion
-           (backward-word-strictly 1)
-           (backward-char 1)
-           (looking-at "[ \t\n\f]"))
-         (idlwave-show-begin))))
+  (if
+      (save-excursion
+       (backward-word-strictly 1)
+       (backward-char 1)
+       (looking-at "[ \t\n\f]"))
+      (idlwave-show-begin)))
 
 (defun idlwave-show-begin ()
   "Find the start of current block and blinks to it for a second.
@@ -2088,7 +2057,7 @@ Also checks if the correct END statement has been used."
         begin-pos end-pos end end1 )
     (if idlwave-reindent-end  (idlwave-indent-line))
     (setq last-abbrev-location (marker-position last-abbrev-marker))
-    (when (and (idlwave-check-abbrev 0 t)
+    (when (and (idlwave-modify-abbrev 0 t)
               idlwave-show-block)
       (save-excursion
        ;; Move inside current block
@@ -2178,11 +2147,11 @@ Also checks if the correct END statement has been used."
        (next-char (char-after (point)))
        (method-invoke (and gtr (eq prev-char ?-)))
        (len (if method-invoke 2 1)))
-    (unless  (eq next-char ?=)
+    (unless (eq next-char ?=)
       ;; Key binding: pad only on left, to save for possible >=/<=
       (idlwave-surround -1 (if (or is-action method-invoke) -1) len))))
 
-(defun idlwave-surround (&optional before after length is-action)
+(defun idlwave-surround (&optional before after length _is-action)
   "Surround the LENGTH characters before point with blanks.
 LENGTH defaults to 1.
 Optional arguments BEFORE and AFTER affect the behavior before and
@@ -2641,7 +2610,7 @@ statement."
       (if st
           (append st (match-end 0))))))
 
-(defun idlwave-expand-equal (&optional before after is-action)
+(defun idlwave-expand-equal (&optional before after _is-action)
   "Pad `=' with spaces.
 Two cases: Assignment statement, and keyword assignment.
 Which case is determined using `idlwave-start-of-substatement' and
@@ -2749,10 +2718,10 @@ If the optional argument EXPAND is non-nil then the 
actions in
         ;; Before indenting, run action routines.
         ;;
         (if (and expand idlwave-do-actions)
-            (mapc 'idlwave-do-action idlwave-indent-expand-table))
+            (mapc #'idlwave-do-action idlwave-indent-expand-table))
         ;;
         (if idlwave-do-actions
-            (mapc 'idlwave-do-action idlwave-indent-action-table))
+            (mapc #'idlwave-do-action idlwave-indent-action-table))
         ;;
         ;; No longer expand abbrevs on the line.  The user can do this
         ;; manually using expand-region-abbrevs.
@@ -2781,18 +2750,19 @@ If the optional argument EXPAND is non-nil then the 
actions in
 (defun idlwave-do-action (action)
   "Perform an action repeatedly on a line.
 ACTION is a list (REG . FUNC).  REG is a regular expression.  FUNC is
-either a function name to be called with `funcall' or a list to be
-evaluated with `eval'.  The action performed by FUNC should leave
-point after the match for REG - otherwise an infinite loop may be
-entered.  FUNC is always passed a final argument of `is-action', so it
+either a function which will be called with one argument `is-action' or
+a list to be evaluated with `eval'.
+The action performed by FUNC should leave point after the match for REG
+- otherwise an infinite loop may be entered.
+FUNC is always passed a final argument of `is-action', so it
 can discriminate between being run as an action, or a key binding."
   (let ((action-key (car action))
         (action-routine (cdr action)))
     (beginning-of-line)
     (while (idlwave-look-at action-key)
-      (if (listp action-routine)
-          (eval (append action-routine '('is-action)))
-        (funcall action-routine 'is-action)))))
+      (if (functionp action-routine)
+          (funcall action-routine 'is-action)
+        (eval (append action-routine '('is-action)) t)))))
 
 (defun idlwave-indent-to (col &optional min)
   "Indent from point with spaces until column COL.
@@ -3053,7 +3023,7 @@ Return value is the beginning of the match or (in case of 
failure) nil."
   (let ((case-fold-search t)
        (search-func (if (> dir 0) 're-search-forward 're-search-backward))
        found)
-    (idlwave-with-special-syntax
+    (with-syntax-table idlwave-find-symbol-syntax-table
      (save-excursion
        (catch 'exit
         (while (funcall search-func key-re limit t)
@@ -3181,7 +3151,7 @@ If successful leaves point after the match, otherwise, 
does not move point."
               (if cont (idlwave-end-of-statement) (end-of-line))
               (point)))
         found)
-    (idlwave-with-special-syntax
+    (with-syntax-table idlwave-find-symbol-syntax-table
      (if beg (idlwave-beginning-of-statement))
      (while (and (setq found (re-search-forward regexp eos t))
                 (idlwave-quoted))))
@@ -3465,25 +3435,7 @@ if `idlwave-auto-fill-split-string' is non-nil."
              (idlwave-indent-line))
            )))))
 
-(defun idlwave-auto-fill-mode (arg)
-  "Toggle auto-fill mode for IDL mode.
-With arg, turn auto-fill mode on if arg is positive.
-In auto-fill mode, inserting a space at a column beyond `fill-column'
-automatically breaks the line at a previous space."
-  (interactive "P")
-  (prog1 (set idlwave-fill-function
-              (if (if (null arg)
-                      (not (symbol-value idlwave-fill-function))
-                    (> (prefix-numeric-value arg) 0))
-                  'idlwave-auto-fill
-                nil))
-    ;; update mode-line
-    (set-buffer-modified-p (buffer-modified-p))))
-
-;(defun idlwave-fill-routine-call ()
-;  "Fill a routine definition or statement, indenting appropriately."
-;  (let ((where (idlwave-where)))))
-
+(define-obsolete-function-alias 'idlwave-auto-fill-mode #'auto-fill-mode 
"28.1")
 
 (defun idlwave-doc-header (&optional nomark)
   "Insert a documentation header at the beginning of the unit.
@@ -3578,6 +3530,7 @@ Calling from a program, arguments are START END."
 (defun idlwave-quoted ()
   "Return t if point is in a comment or quoted string.
 Returns nil otherwise."
+  ;; FIXME: Use (nth 8 (synx-ppss))!
   (and (or (idlwave-in-comment) (idlwave-in-quote)) t))
 
 (defun idlwave-in-quote ()
@@ -3858,7 +3811,7 @@ Intended for `after-save-hook'."
        (setq idlwave-outlawed-buffers
              (delq entry idlwave-outlawed-buffers)))
     ;; Remove this function from the hook.
-    (remove-hook 'after-save-hook 'idlwave-revoke-license-to-kill 'local)))
+    (remove-hook 'after-save-hook #'idlwave-revoke-license-to-kill 'local)))
 
 (defvar idlwave-path-alist)
 (defun idlwave-locate-lib-file (file)
@@ -4098,10 +4051,10 @@ blank lines."
        (set (idlwave-sintern-set name 'class idlwave-sint-classes set))
        (name)))
 
-(defun idlwave-sintern-dir (dir &optional set)
+(defun idlwave-sintern-dir (dir &optional _set)
   (car (or (member dir idlwave-sint-dirs)
           (setq idlwave-sint-dirs (cons dir idlwave-sint-dirs)))))
-(defun idlwave-sintern-libname (name &optional set)
+(defun idlwave-sintern-libname (name &optional _set)
   (car (or (member name idlwave-sint-libnames)
           (setq idlwave-sint-libnames (cons name idlwave-sint-libnames)))))
 
@@ -4169,7 +4122,7 @@ the base of the directory."
 
 ;; Creating new sintern tables
 
-(defun idlwave-new-sintern-type (tag)
+(defmacro idlwave-new-sintern-type (tag)
   "Define a variable and a function to sintern the new type TAG.
 This defines the function `idlwave-sintern-TAG' and the variable
 `idlwave-sint-TAGs'."
@@ -4177,15 +4130,15 @@ This defines the function `idlwave-sintern-TAG' and the 
variable
         (names (concat name "s"))
         (var (intern (concat "idlwave-sint-" names)))
         (func (intern (concat "idlwave-sintern-" name))))
-    (set var nil) ; initial value of the association list
-    (fset func    ; set the function
-         `(lambda (name &optional set)
-            (cond ((not (stringp name)) name)
-                  ((cdr (assoc (downcase name) ,var)))
-                  (set
-                   (setq ,var (cons (cons (downcase name) name) ,var))
-                   name)
-                  (name))))))
+    `(progn
+       (defvar ,var nil)        ; initial value of the association list
+       (defun ,func (name &optional set)
+        (cond ((not (stringp name)) name)
+              ((cdr (assoc (downcase name) ,var)))
+              (set
+               (push (cons (downcase name) name) ,var)
+               name)
+              (name))))))
 
 (defun idlwave-reset-sintern-type (tag)
   "Reset the sintern variable associated with TAG."
@@ -4296,12 +4249,12 @@ will re-read the catalog."
                     "-l" (expand-file-name "~/.emacs")
                     "-l" "idlwave"
                     "-f" "idlwave-rescan-catalog-directories"))
-        (process (apply 'start-process "idlcat"
+        (process (apply #'start-process "idlcat"
                         nil emacs args)))
     (setq idlwave-catalog-process process)
     (set-process-sentinel
      process
-     (lambda (pro why)
+     (lambda (_pro why)
        (when (string-match "finished" why)
         (setq idlwave-routines nil
               idlwave-system-routines nil
@@ -4449,7 +4402,7 @@ information updated immediately, leave NO-CONCATENATE 
nil."
            (setq idlwave-load-rinfo-idle-timer
                  (run-with-idle-timer
                   idlwave-init-rinfo-when-idle-after
-                  nil 'idlwave-load-rinfo-next-step)))
+                  nil #'idlwave-load-rinfo-next-step)))
        (error nil))))
 
 ;;------ XML Help routine info system
@@ -4935,7 +4888,7 @@ Cache to disk for quick recovery."
          (setq idlwave-load-rinfo-idle-timer
                (run-with-idle-timer
                 idlwave-init-rinfo-when-idle-after
-                nil 'idlwave-load-rinfo-next-step))))))
+                nil #'idlwave-load-rinfo-next-step))))))
 
 (defvar idlwave-after-load-rinfo-hook nil)
 
@@ -5109,7 +5062,7 @@ Can run from `after-save-hook'."
                               (error nil)))
                   (push res routine-lists)))))
     ;; Concatenate the individual lists and return the result
-    (apply 'nconc routine-lists)))
+    (apply #'nconc routine-lists)))
 
 (defun idlwave-get-buffer-routine-info ()
   "Scan the current buffer for routine info.  Return (PRO-LIST FUNC-LIST)."
@@ -5185,10 +5138,10 @@ Can run from `after-save-hook'."
           (if args
               (concat
                (if (string= type "function") "(" ", ")
-               (mapconcat 'identity args ", ")
+               (mapconcat #'identity args ", ")
                (if (string= type "function") ")" ""))))
          (if keywords
-             (cons nil (mapcar 'list keywords)) ;No help file
+             (cons nil (mapcar #'list keywords)) ;No help file
            nil))))
 
 
@@ -5246,7 +5199,7 @@ as last time - so no widget will pop up."
                         (cons x (cdr path-entry))
                       (list x))))
                 (idlwave-expand-path idlwave-library-path))
-       (mapcar 'list (idlwave-expand-path idlwave-library-path)))))
+       (mapcar #'list (idlwave-expand-path idlwave-library-path)))))
 
    ;; Ask the shell for the path and then run the widget
    (t
@@ -5314,7 +5267,7 @@ directories and save the routine info.
   (widget-insert "  ")
   (widget-create 'push-button
                 :notify
-                (lambda (&rest ignore)
+                (lambda (&rest _ignore)
                    (let ((path-list (widget-get idlwave-widget :path-dirs)))
                      (dolist (x path-list)
                        (unless (memq 'lib (cdr x))
@@ -5324,7 +5277,7 @@ directories and save the routine info.
   (widget-insert "  ")
   (widget-create 'push-button
                 :notify
-                (lambda (&rest ignore)
+                (lambda (&rest _ignore)
                    (let ((path-list (widget-get idlwave-widget :path-dirs)))
                      (dolist (x path-list)
                        (idlwave-path-alist-remove-flag x 'user))
@@ -5332,7 +5285,7 @@ directories and save the routine info.
                 "Deselect All")
   (widget-insert "  ")
   (widget-create 'push-button
-                :notify (lambda (&rest ignore)
+                :notify (lambda (&rest _ignore)
                           (kill-buffer (current-buffer)))
                 "Quit")
   (widget-insert "\n\n")
@@ -5340,7 +5293,7 @@ directories and save the routine info.
   (widget-insert "Select Directories: \n")
 
   (setq idlwave-widget
-       (apply 'widget-create
+       (apply #'widget-create
               'checklist
               :value  (delq nil (mapcar (lambda (x)
                                           (if (memq 'user (cdr x))
@@ -5352,7 +5305,8 @@ directories and save the routine info.
                         (list 'item
                               (if (memq 'lib (cdr x))
                                   (concat "[LIB] " (car x) )
-                                (car x)))) dirs-list)))
+                                (car x))))
+                      dirs-list)))
   (widget-put idlwave-widget :path-dirs dirs-list)
   (widget-insert "\n")
   (use-local-map widget-keymap)
@@ -5360,14 +5314,14 @@ directories and save the routine info.
   (goto-char (point-min))
   (delete-other-windows))
 
-(defun idlwave-delete-user-catalog-file (&rest ignore)
+(defun idlwave-delete-user-catalog-file (&rest _ignore)
   (if (yes-or-no-p
        (format "Delete file %s " idlwave-user-catalog-file))
       (progn
        (delete-file idlwave-user-catalog-file)
        (message "%s has been deleted" idlwave-user-catalog-file))))
 
-(defun idlwave-widget-scan-user-lib-files (&rest ignore)
+(defun idlwave-widget-scan-user-lib-files (&rest _ignore)
   ;; Call `idlwave-scan-user-lib-files' with data taken from the widget.
   (let* ((widget idlwave-widget)
         (selected-dirs (widget-value widget))
@@ -5517,7 +5471,7 @@ be set to nil to disable library catalog scanning."
     (let ((dirs
           (if idlwave-library-path
               (idlwave-expand-path idlwave-library-path)
-            (mapcar 'car idlwave-path-alist)))
+            (mapcar #'car idlwave-path-alist)))
          (old-libname "")
          dir-entry dir catalog all-routines)
       (if message-base (message "%s" message-base))
@@ -5730,11 +5684,10 @@ end
 (defvar idlwave-completion-help-info nil)
 (defvar idlwave-completion-help-links nil)
 (defvar idlwave-current-obj_new-class nil)
-(defvar idlwave-complete-special nil)
-(defvar method-selector)
-(defvar class-selector)
-(defvar type-selector)
-(defvar super-classes)
+(defvar idlwave--method-selector)
+(defvar idlwave--class-selector)
+(defvar idlwave--type-selector)
+(defvar idlwave--super-classes)
 
 (defun idlwave-complete (&optional arg module class)
   "Complete a function, procedure or keyword name at point.
@@ -5815,8 +5768,7 @@ When we force a method or a method keyword, CLASS can 
specify the class."
       (idlwave-complete-filename))
 
      ;; Check for any special completion functions
-     ((and idlwave-complete-special
-          (idlwave-call-special idlwave-complete-special)))
+     ((run-hook-with-args-until-success 'idlwave-complete-functions))
 
      ((null what)
       (error "Nothing to complete here"))
@@ -5829,22 +5781,26 @@ When we force a method or a method keyword, CLASS can 
specify the class."
      ((eq what 'procedure)
       ;; Complete a procedure name
       (let* ((cw-list (nth 3 where-list))
-            (class-selector (idlwave-determine-class cw-list 'pro))
-            (super-classes (unless (idlwave-explicit-class-listed cw-list)
-                             (idlwave-all-class-inherits class-selector)))
-            (isa (concat "procedure" (if class-selector "-method" "")))
-            (type-selector 'pro))
+            (idlwave--class-selector (idlwave-determine-class cw-list 'pro))
+            (idlwave--super-classes
+             (unless (idlwave-explicit-class-listed cw-list)
+               (idlwave-all-class-inherits idlwave--class-selector)))
+            (isa (concat "procedure"
+                         (if idlwave--class-selector "-method" "")))
+            (idlwave--type-selector 'pro))
        (setq idlwave-completion-help-info
-             (list 'routine nil type-selector class-selector nil 
super-classes))
+             (list 'routine nil
+                   idlwave--type-selector idlwave--class-selector
+                   nil idlwave--super-classes))
        (idlwave-complete-in-buffer
-        'procedure (if class-selector 'method 'routine)
+        'procedure (if idlwave--class-selector 'method 'routine)
         (idlwave-routines) 'idlwave-selector
         (format "Select a %s name%s"
                 isa
-                (if class-selector
+                (if idlwave--class-selector
                     (format " (class is %s)"
-                            (if (eq class-selector t)
-                                "unknown" class-selector))
+                            (if (eq idlwave--class-selector t)
+                                "unknown" idlwave--class-selector))
                   ""))
         isa
         'idlwave-attach-method-classes 'idlwave-add-file-link-selector)))
@@ -5852,22 +5808,25 @@ When we force a method or a method keyword, CLASS can 
specify the class."
      ((eq what 'function)
       ;; Complete a function name
       (let* ((cw-list (nth 3 where-list))
-            (class-selector (idlwave-determine-class cw-list 'fun))
-            (super-classes (unless (idlwave-explicit-class-listed cw-list)
-                             (idlwave-all-class-inherits class-selector)))
-            (isa (concat "function" (if class-selector "-method" "")))
-            (type-selector 'fun))
+            (idlwave--class-selector (idlwave-determine-class cw-list 'fun))
+            (idlwave--super-classes
+             (unless (idlwave-explicit-class-listed cw-list)
+               (idlwave-all-class-inherits idlwave--class-selector)))
+            (isa (concat "function" (if idlwave--class-selector "-method" "")))
+            (idlwave--type-selector 'fun))
        (setq idlwave-completion-help-info
-             (list 'routine nil type-selector class-selector nil 
super-classes))
+             (list 'routine nil
+                   idlwave--type-selector idlwave--class-selector
+                   nil idlwave--super-classes))
        (idlwave-complete-in-buffer
-        'function (if class-selector 'method 'routine)
+        'function (if idlwave--class-selector 'method 'routine)
         (idlwave-routines) 'idlwave-selector
         (format "Select a %s name%s"
                 isa
-                (if class-selector
+                (if idlwave--class-selector
                     (format " (class is %s)"
-                            (if (eq class-selector t)
-                                "unknown" class-selector))
+                            (if (eq idlwave--class-selector t)
+                                "unknown" idlwave--class-selector))
                   ""))
         isa
         'idlwave-attach-method-classes 'idlwave-add-file-link-selector)))
@@ -5880,11 +5839,12 @@ When we force a method or a method keyword, CLASS can 
specify the class."
       ;; Complete a procedure keyword
       (let* ((where (nth 3 where-list))
             (name  (car where))
-            (method-selector name)
-            (type-selector 'pro)
+            (idlwave--method-selector name)
+            (idlwave--type-selector 'pro)
             (class (idlwave-determine-class where 'pro))
-            (class-selector class)
-            (super-classes (idlwave-all-class-inherits class-selector))
+            (idlwave--class-selector class)
+            (idlwave--super-classes (idlwave-all-class-inherits
+                                     idlwave--class-selector))
             (isa (format "procedure%s-keyword" (if class "-method" "")))
             (entry (idlwave-best-rinfo-assq
                     name 'pro class (idlwave-routines)))
@@ -5894,11 +5854,13 @@ When we force a method or a method keyword, CLASS can 
specify the class."
          (error "Nothing known about procedure %s"
                 (idlwave-make-full-name class name)))
        (setq list (idlwave-fix-keywords name 'pro class list
-                                        super-classes system))
+                                        idlwave--super-classes system))
        (unless list (error "No keywords available for procedure %s"
                            (idlwave-make-full-name class name)))
        (setq idlwave-completion-help-info
-             (list 'keyword name type-selector class-selector entry 
super-classes))
+             (list 'keyword name
+                   idlwave--type-selector idlwave--class-selector
+                   entry idlwave--super-classes))
        (idlwave-complete-in-buffer
         'keyword 'keyword list nil
         (format "Select keyword for procedure %s%s"
@@ -5913,11 +5875,12 @@ When we force a method or a method keyword, CLASS can 
specify the class."
       ;; Complete a function keyword
       (let* ((where (nth 3 where-list))
             (name  (car where))
-            (method-selector name)
-            (type-selector 'fun)
+            (idlwave--method-selector name)
+            (idlwave--type-selector 'fun)
             (class (idlwave-determine-class where 'fun))
-            (class-selector class)
-            (super-classes (idlwave-all-class-inherits class-selector))
+            (idlwave--class-selector class)
+            (idlwave--super-classes (idlwave-all-class-inherits
+                                     idlwave--class-selector))
             (isa (format "function%s-keyword" (if class "-method" "")))
             (entry (idlwave-best-rinfo-assq
                     name 'fun class (idlwave-routines)))
@@ -5928,7 +5891,7 @@ When we force a method or a method keyword, CLASS can 
specify the class."
          (error "Nothing known about function %s"
                 (idlwave-make-full-name class name)))
        (setq list (idlwave-fix-keywords name 'fun class list
-                                        super-classes system))
+                                        idlwave--super-classes system))
        ;; OBJ_NEW: Messages mention the proper Init method
        (setq msg-name (if (and (null class)
                                (string= (upcase name) "OBJ_NEW"))
@@ -5938,7 +5901,9 @@ When we force a method or a method keyword, CLASS can 
specify the class."
        (unless list (error "No keywords available for function %s"
                            msg-name))
        (setq idlwave-completion-help-info
-             (list 'keyword name type-selector class-selector nil 
super-classes))
+             (list 'keyword name
+                   idlwave--type-selector idlwave--class-selector
+                   nil idlwave--super-classes))
        (idlwave-complete-in-buffer
         'keyword 'keyword list nil
         (format "Select keyword for function %s%s" msg-name
@@ -5950,7 +5915,9 @@ When we force a method or a method keyword, CLASS can 
specify the class."
 
      (t (error "This should not happen (idlwave-complete)")))))
 
-(defvar idlwave-complete-special nil
+(define-obsolete-variable-alias 'idlwave-complete-special
+  'idlwave-complete-functions "28.1")
+(defvar idlwave-complete-functions nil
   "List of special completion functions.
 These functions are called for each completion.  Each function must
 check if its own special completion context is present.  If yes, it
@@ -5960,6 +5927,7 @@ complete other contexts will be done.  If the function 
returns nil,
 other completions will be tried.")
 
 (defun idlwave-call-special (functions &rest args)
+  (declare (obsolete run-hook-with-args-until-success "28.1"))
   (let ((funcs functions)
        fun ret)
     (catch 'exit
@@ -6002,9 +5970,9 @@ other completions will be tried.")
       (list nil-list nil-list 'procedure nil-list nil))
 
      ((eq what 'procedure-keyword)
-      (let* ((class-selector nil)
-            (super-classes nil)
-            (type-selector 'pro)
+      (let* ((idlwave--class-selector nil)
+            (idlwave--super-classes nil)
+            (idlwave--type-selector 'pro)
             (pro (or module
                      (idlwave-completing-read
                       "Procedure: " (idlwave-routines) 'idlwave-selector))))
@@ -6016,9 +5984,9 @@ other completions will be tried.")
       (list nil-list nil-list 'function nil-list nil))
 
      ((eq what 'function-keyword)
-      (let* ((class-selector nil)
-            (super-classes nil)
-            (type-selector 'fun)
+      (let* ((idlwave--class-selector nil)
+            (idlwave--super-classes nil)
+            (idlwave--type-selector 'fun)
             (func (or module
                       (idlwave-completing-read
                        "Function: " (idlwave-routines) 'idlwave-selector))))
@@ -6031,12 +5999,14 @@ other completions will be tried.")
 
      ((eq what 'procedure-method-keyword)
       (let* ((class (idlwave-determine-class class-list 'pro))
-            (class-selector class)
-            (super-classes (idlwave-all-class-inherits class-selector))
-            (type-selector 'pro)
+            (idlwave--class-selector class)
+            (idlwave--super-classes (idlwave-all-class-inherits
+                                     idlwave--class-selector))
+            (idlwave--type-selector 'pro)
             (pro (or module
                      (idlwave-completing-read
-                      (format "Procedure in %s class: " class-selector)
+                      (format "Procedure in %s class: "
+                              idlwave--class-selector)
                       (idlwave-routines) 'idlwave-selector))))
        (setq pro (idlwave-sintern-method pro))
        (list nil-list nil-list 'procedure-keyword
@@ -6047,12 +6017,14 @@ other completions will be tried.")
 
      ((eq what 'function-method-keyword)
       (let* ((class (idlwave-determine-class class-list 'fun))
-            (class-selector class)
-            (super-classes (idlwave-all-class-inherits class-selector))
-            (type-selector 'fun)
+            (idlwave--class-selector class)
+            (idlwave--super-classes (idlwave-all-class-inherits
+                                     idlwave--class-selector))
+            (idlwave--type-selector 'fun)
             (func (or module
                       (idlwave-completing-read
-                       (format "Function in %s class: " class-selector)
+                       (format "Function in %s class: "
+                               idlwave--class-selector)
                        (idlwave-routines) 'idlwave-selector))))
        (setq func (idlwave-sintern-method func))
        (list nil-list nil-list 'function-keyword
@@ -6069,14 +6041,14 @@ other completions will be tried.")
     (unwind-protect
        (progn
          (setq-default completion-ignore-case t)
-         (apply 'completing-read args))
+         (apply #'completing-read args))
       (setq-default completion-ignore-case old-value))))
 
 (defvar idlwave-shell-default-directory)
 (defun idlwave-complete-filename ()
   "Use the comint stuff to complete a file name."
   (require 'comint)
-  (let* ((comint-file-name-chars "~/A-Za-z0-9+@:_.$#%={}\\-")
+  (dlet ((comint-file-name-chars "~/A-Za-z0-9+@:_.$#%={}\\-")
         (comint-completion-addsuffix nil)
         (default-directory
           (if (and (boundp 'idlwave-shell-default-directory)
@@ -6110,7 +6082,7 @@ other completions will be tried.")
 (defun idlwave-rinfo-assq-any-class (name type class list)
   ;; Return the first matching method on the inheritance list
   (let* ((classes (cons class (idlwave-all-class-inherits class)))
-        class rtn)
+        rtn) ;; class
     (while classes
       (if (setq rtn (idlwave-rinfo-assq name type (pop classes) list))
          (setq classes nil)))
@@ -6127,7 +6099,7 @@ syslib files."
                list))
        syslibp)
     (when (> (length twins) 1)
-      (setq twins (sort twins 'idlwave-routine-entry-compare-twins))
+      (setq twins (sort twins #'idlwave-routine-entry-compare-twins))
       (if (and (null keep-system)
               (eq 'system (car (nth 3 (car twins))))
               (setq syslibp (idlwave-any-syslib (cdr twins)))
@@ -6174,7 +6146,7 @@ If yes, return the index (>=1)."
 TYPE is `fun' or `pro'.
 When TYPE is not specified, both procedures and functions will be considered."
   (if (null method)
-      (mapcar 'car (idlwave-class-alist))
+      (mapcar #'car (idlwave-class-alist))
     (let (rtn)
       (mapc (lambda (x)
              (and (nth 2 x)
@@ -6228,9 +6200,11 @@ INFO is as returned by `idlwave-what-function' or 
`-procedure'."
        (save-excursion (goto-char apos)
                        (looking-at "->[a-zA-Z][a-zA-Z0-9$_]*::")))))
 
-(defvar idlwave-determine-class-special nil
-  "List of special functions for determining class.
-Must accept two arguments: `apos' and `info'.")
+(define-obsolete-variable-alias 'idlwave-determine-class-special
+  'idlwave-determine-class-functions "28.1")
+(defvar idlwave-determine-class-functions nil
+  "Special hook to determine a class.
+The functions should accept one argument, APOS.")
 
 (defun idlwave-determine-class (info type)
   ;; Determine the class of a routine call.
@@ -6275,10 +6249,10 @@ Must accept two arguments: `apos' and `info'.")
 
       ;; Before prompting, try any special class determination routines
       (when (and (eq t class)
-                idlwave-determine-class-special
                 (not force-query))
        (setq special-class
-             (idlwave-call-special idlwave-determine-class-special apos))
+             (run-hook-with-args-until-success
+              'idlwave-determine-class-functions apos))
        (if special-class
            (setq class (idlwave-sintern-class special-class)
                  store idlwave-store-inquired-class)))
@@ -6287,7 +6261,7 @@ Must accept two arguments: `apos' and `info'.")
       (when (and (eq class t)
                 (or force-query query))
        (setq class-alist
-             (mapcar 'list (idlwave-all-method-classes (car info) type)))
+             (mapcar #'list (idlwave-all-method-classes (car info) type)))
        (setq class
              (idlwave-sintern-class
               (cond
@@ -6321,10 +6295,10 @@ Must accept two arguments: `apos' and `info'.")
      (t class))))
 
 (defun idlwave-selector (a)
-  (and (eq (nth 1 a) type-selector)
-       (or (and (nth 2 a) (eq class-selector t))
-          (eq (nth 2 a) class-selector)
-          (memq (nth 2 a) super-classes))))
+  (and (eq (nth 1 a) idlwave--type-selector)
+       (or (and (nth 2 a) (eq idlwave--class-selector t))
+          (eq (nth 2 a) idlwave--class-selector)
+          (memq (nth 2 a) idlwave--super-classes))))
 
 (defun idlwave-add-file-link-selector (a)
   ;; Record a file link, if any, for the tested names during selection.
@@ -6442,7 +6416,7 @@ ARROW:  Location of the arrow"
          func-point
          (cnt 0)
          func arrow-start class)
-      (idlwave-with-special-syntax
+      (with-syntax-table idlwave-find-symbol-syntax-table
        (save-restriction
         (save-excursion
           (narrow-to-region (max 1 (or bound 0)) (point-max))
@@ -6472,7 +6446,7 @@ ARROW:  Location of the arrow"
             (goto-char pos))
           (throw 'exit nil)))))))
 
-(defun idlwave-what-procedure (&optional bound)
+(defun idlwave-what-procedure (&optional _bound)
   ;; Find out if point is within the argument list of a procedure.
   ;; The return value is ("procedure-name" class arrow-pos (point)).
 
@@ -6562,10 +6536,10 @@ This function is not general, can only be used for 
completion stuff."
            (throw 'exit nil)))
         (t (throw 'exit (preceding-char))))))))
 
-(defvar idlwave-complete-after-success-form nil
-  "A form to evaluate after successful completion.")
-(defvar idlwave-complete-after-success-form-force nil
-  "A form to evaluate after completion selection in *Completions* buffer.")
+(defvar idlwave--complete-after-success-function #'ignore
+  "A function to evaluate after successful completion.")
+(defvar idlwave--complete-after-success-force-function #'ignore
+  "A function to evaluate after completion selection in *Completions* buffer.")
 (defconst idlwave-completion-mark (make-marker)
   "A mark pointing to the beginning of the completion string.")
 
@@ -6590,12 +6564,12 @@ accumulate information on matching completions."
       (skip-chars-backward "a-zA-Z0-9_$")
       (setq slash (eq (preceding-char) ?/)
            beg (point)
-           idlwave-complete-after-success-form
-           (list 'idlwave-after-successful-completion
-                 (list 'quote type) slash beg)
-           idlwave-complete-after-success-form-force
-           (list 'idlwave-after-successful-completion
-                 (list 'quote type) slash (list 'quote 'force))))
+           idlwave--complete-after-success-function
+           (lambda () (idlwave-after-successful-completion
+                  type slash beg))
+           idlwave--complete-after-success-force-function
+           (lambda () (idlwave-after-successful-completion
+                  type slash 'force))))
 
     ;; Try a completion
     (setq part (buffer-substring beg end)
@@ -6699,19 +6673,20 @@ accumulate information on matching completions."
   ;; 'class-tag, for class tags, and otherwise for methods.
   ;; SHOW-CLASSES is the value of `idlwave-completion-show-classes'.
   (if (or (null show-classes)           ; don't want to see classes
-         (null class-selector)         ; not a method call
+         (null idlwave--class-selector)         ; not a method call
          (and
-          (stringp class-selector) ; the class is already known
-          (not super-classes)))    ; no possibilities for inheritance
+          (stringp idlwave--class-selector) ; the class is already known
+          (not idlwave--super-classes)))    ; no possibilities for inheritance
       ;; In these cases, we do not have to do anything
       list
     (let* ((do-prop (>= show-classes 0))
           (do-buf (not (= show-classes 0)))
-          (do-dots t)
-          (inherit (if (and (not (eq type 'class-tag)) super-classes)
-                       (cons class-selector super-classes)))
+          ;; (do-dots t)
+          (inherit (if (and (not (eq type 'class-tag)) idlwave--super-classes)
+                       (cons idlwave--class-selector idlwave--super-classes)))
           (max (abs show-classes))
-          (lmax (if do-dots (apply 'max (mapcar 'length list))))
+          (lmax ;; (if do-dots
+                    (apply #'max (mapcar #'length list))) ;;)
          classes nclasses class-info space)
       (mapcar
        (lambda (x)
@@ -6720,13 +6695,14 @@ accumulate information on matching completions."
             ;; Just one class for tags
             (setq classes
                   (list
-                   (idlwave-class-or-superclass-with-tag class-selector x)))
+                   (idlwave-class-or-superclass-with-tag
+                    idlwave--class-selector x)))
           ;; Multiple classes for method or method-keyword
           (setq classes
                 (if (eq type 'kwd)
                     (idlwave-all-method-keyword-classes
-                     method-selector x type-selector)
-                  (idlwave-all-method-classes x type-selector)))
+                     idlwave--method-selector x idlwave--type-selector)
+                  (idlwave-all-method-classes x idlwave--type-selector)))
           (if inherit
               (setq classes
                     (delq nil
@@ -6734,22 +6710,22 @@ accumulate information on matching completions."
                                   classes)))))
         (setq nclasses (length classes))
         ;; Make the separator between item and class-info
-        (if do-dots
-            (setq space (concat " " (make-string (- lmax (length x)) ?.)))
-          (setq space " "))
+        ;; (if do-dots
+        (setq space (concat " " (make-string (- lmax (length x)) ?.)))
+        ;; (setq space " "))
         (if  do-buf
             ;; We do want info in the buffer
             (if (<= nclasses max)
                 (setq class-info (concat
                                   space
-                                  "<" (mapconcat 'identity classes ",") ">"))
+                                  "<" (mapconcat #'identity classes ",") ">"))
               (setq class-info (format "%s<%d classes>" space nclasses)))
           (setq class-info nil))
         (when do-prop
           ;; We do want properties
           (setq x (copy-sequence x))
           (put-text-property 0 (length x)
-                              'help-echo (mapconcat 'identity classes " ")
+                              'help-echo (mapconcat #'identity classes " ")
                               x))
         (if class-info
             (list x class-info)
@@ -6839,7 +6815,7 @@ sort the list before displaying."
                            (nth 2 last-command))
                       (progn
                         (select-window win)
-                        (eval idlwave-complete-after-success-form))
+                        (funcall idlwave--complete-after-success-function))
                     (set-window-start cwin (point-min)))))
          (and message (message "%s" message)))
       (select-window win))))
@@ -6882,7 +6858,7 @@ sort the list before displaying."
                   (skip-chars-backward "a-zA-Z0-9_")
                   (point))))
        (remove-text-properties beg (point) '(face nil))))
-  (eval idlwave-complete-after-success-form-force))
+  (funcall idlwave--complete-after-success-force-function))
 
 (defun idlwave-keyboard-quit ()
   (interactive)
@@ -6990,16 +6966,15 @@ If these don't exist, a letter in the string is 
automatically selected."
 
 (defun idlwave-local-value (var &optional buffer)
   "Return the value of VAR in BUFFER, but only if VAR is local to BUFFER."
-  (with-current-buffer (or buffer (current-buffer))
-    (and (local-variable-p var (current-buffer))
-        (symbol-value var))))
+  (when (local-variable-p var buffer)
+    (buffer-local-value var (or buffer (current-buffer)))))
 
 (defvar idlwave-completion-map nil
   "Keymap for `completion-list-mode' with `idlwave-complete'.")
 
-(defun idlwave-default-choose-completion (&rest args)
-  "Execute `default-choose-completion' and then restore the win-conf."
-  (apply 'idlwave-choose 'default-choose-completion args))
+;; (defun idlwave-default-choose-completion (&rest args)
+;;   "Execute `default-choose-completion' and then restore the win-conf."
+;;   (apply #'idlwave-choose #'default-choose-completion args))
 
 (define-obsolete-function-alias 'idlwave-display-completion-list-emacs
   #'idlwave-display-completion-list-1 "28.1")
@@ -7021,14 +6996,14 @@ If these don't exist, a letter in the string is 
automatically selected."
   "Replace `choose-completion' in OLD-MAP."
   (let ((new-map (copy-keymap old-map)))
     (substitute-key-definition
-     'choose-completion 'idlwave-choose-completion new-map)
-    (define-key new-map [mouse-3] 'idlwave-mouse-completion-help)
+     #'choose-completion #'idlwave-choose-completion new-map)
+    (define-key new-map [mouse-3] #'idlwave-mouse-completion-help)
     new-map))
 
 (defun idlwave-choose-completion (&rest args)
   "Choose the completion that point is in or next to."
   (interactive (list last-nonmenu-event))
-  (apply 'idlwave-choose 'choose-completion args))
+  (apply #'idlwave-choose #'choose-completion args))
 
 (define-obsolete-function-alias 'idlwave-mouse-choose-completion
   #'idlwave-choose-completion "28.1")
@@ -7278,8 +7253,8 @@ class/struct definition."
 (defun idlwave-all-class-tags (class)
   "Return a list of native and inherited tags in CLASS."
   (condition-case err
-      (apply 'append (mapcar 'idlwave-class-tags
-                            (cons class (idlwave-all-class-inherits class))))
+      (apply #'append (mapcar #'idlwave-class-tags
+                             (cons class (idlwave-all-class-inherits class))))
     (error
      (idlwave-class-tag-reset)
      (error "%s" (error-message-string err)))))
@@ -7369,10 +7344,9 @@ property indicating the link is added."
 (defvar idlwave-current-class-tags nil)
 (defvar idlwave-current-native-class-tags nil)
 (defvar idlwave-sint-class-tags nil)
-(declare-function idlwave-sintern-class-tag "idlwave" t t)
-(idlwave-new-sintern-type 'class-tag)
-(add-to-list 'idlwave-complete-special 'idlwave-complete-class-structure-tag)
-(add-hook 'idlwave-update-rinfo-hook 'idlwave-class-tag-reset)
+(idlwave-new-sintern-type class-tag)
+(add-hook 'idlwave-complete-functions #'idlwave-complete-class-structure-tag)
+(add-hook 'idlwave-update-rinfo-hook #'idlwave-class-tag-reset)
 
 (defun idlwave-complete-class-structure-tag ()
   "Complete a structure tag on a `self' argument in an object method."
@@ -7384,25 +7358,26 @@ property indicating the link is added."
          (skip-chars-backward "a-zA-Z0-9._$")
          (and (< (point) (- pos 4))
               (looking-at "self\\.")))
-       (let* ((class-selector (nth 2 (idlwave-current-routine)))
-              (super-classes (idlwave-all-class-inherits class-selector)))
+       (let* ((idlwave--class-selector (nth 2 (idlwave-current-routine)))
+              (idlwave--super-classes (idlwave-all-class-inherits
+                                       idlwave--class-selector)))
          ;; Check if we are in a class routine
-         (unless class-selector
+         (unless idlwave--class-selector
            (error "Not in a method procedure or function"))
          ;; Check if we need to update the "current" class
-         (if (not (equal class-selector idlwave-current-tags-class))
-             (idlwave-prepare-class-tag-completion class-selector))
+         (if (not (equal idlwave--class-selector idlwave-current-tags-class))
+             (idlwave-prepare-class-tag-completion idlwave--class-selector))
          (setq idlwave-completion-help-info
                (list 'idlwave-complete-class-structure-tag-help
                      (idlwave-sintern-routine
-                      (concat class-selector "__define"))
+                      (concat idlwave--class-selector "__define"))
                      nil))
           ;; FIXME: idlwave-cpl-bold doesn't seem used anywhere.
-         (let  ((idlwave-cpl-bold idlwave-current-native-class-tags))
+         (let  ((_idlwave-cpl-bold idlwave-current-native-class-tags))
            (idlwave-complete-in-buffer
             'class-tag 'class-tag
             idlwave-current-class-tags nil
-            (format "Select a tag of class %s" class-selector)
+            (format "Select a tag of class %s" idlwave--class-selector)
             "class tag"
             'idlwave-attach-class-tag-classes))
          t) ; return t to skip other completions
@@ -7420,7 +7395,7 @@ property indicating the link is added."
                  (list (idlwave-sintern-class-tag x 'set)))
                (idlwave-all-class-tags class)))
   (setq idlwave-current-native-class-tags
-       (mapcar 'downcase (idlwave-class-tags class))))
+       (mapcar #'downcase (idlwave-class-tags class))))
 
 ;===========================================================================
 ;;
@@ -7429,13 +7404,11 @@ property indicating the link is added."
 
 (defvar idlwave-sint-sysvars nil)
 (defvar idlwave-sint-sysvartags nil)
-(declare-function idlwave-sintern-sysvar    "idlwave" t t)
-(declare-function idlwave-sintern-sysvartag "idlwave" t t)
-(idlwave-new-sintern-type 'sysvar)
-(idlwave-new-sintern-type 'sysvartag)
-(add-to-list 'idlwave-complete-special 'idlwave-complete-sysvar-or-tag)
-(add-hook 'idlwave-update-rinfo-hook 'idlwave-sysvars-reset)
-(add-hook 'idlwave-after-load-rinfo-hook 'idlwave-sintern-sysvar-alist)
+(idlwave-new-sintern-type sysvar)
+(idlwave-new-sintern-type sysvartag)
+(add-hook 'idlwave-complete-functions #'idlwave-complete-sysvar-or-tag)
+(add-hook 'idlwave-update-rinfo-hook #'idlwave-sysvars-reset)
+(add-hook 'idlwave-after-load-rinfo-hook #'idlwave-sintern-sysvar-alist)
 
 
 (defun idlwave-complete-sysvar-or-tag ()
@@ -7591,7 +7564,7 @@ associated TAG, if any."
   (let ((text idlwave-shell-command-output)
        (start 0)
        (old idlwave-system-variables-alist)
-       var tags type name class link old-entry)
+       var tags link old-entry) ;; type name class
     (setq idlwave-system-variables-alist nil)
     (while (string-match "^IDLWAVE-SYSVAR: !\\([a-zA-Z0-9_$]+\\)\\( 
\\(.*\\)\\)?"
                         text start)
@@ -7611,7 +7584,8 @@ associated TAG, if any."
                                         (cdr (assq
                                               (idlwave-sintern-sysvartag x)
                                               (cdr (assq 'tags old-entry))))))
-                                tags)) link)
+                                tags))
+                       link)
                  idlwave-system-variables-alist)))
     ;; Keep the old value if query was not successful
     (setq idlwave-system-variables-alist
@@ -7700,7 +7674,7 @@ itself."
   (setq this-command last-command)
   (idlwave-do-mouse-completion-help ev))
 
-(defun idlwave-routine-info (&optional arg external)
+(defun idlwave-routine-info (&optional arg _external)
   "Display a routines calling sequence and list of keywords.
 When point is on the name a function or procedure, or in the argument
 list of a function or procedure, this command displays a help buffer with
@@ -7737,7 +7711,7 @@ arg, the class property is cleared out."
           (idlwave-force-class-query (equal arg '(4)))
           (module (idlwave-what-module)))
       (if (car module)
-         (apply 'idlwave-display-calling-sequence
+         (apply #'idlwave-display-calling-sequence
                 (idlwave-fix-module-if-obj_new module))
        (error "Don't know which calling sequence to show")))))
 
@@ -7820,7 +7794,7 @@ force class query for object methods."
         (name (idlwave-completing-read
                (if (or (not this-buffer)
                        (assoc default list))
-                   (format "Module (Default %s): " default)
+                   (format-prompt "Module" default)
                  (format "Module in this file: "))
                list))
         type class)
@@ -7954,7 +7928,7 @@ Used by `idlwave-routine-info' and `idlwave-find-module'."
             (stringp class))
        (list (car module)
              (nth 1 module)
-             (apply 'idlwave-find-inherited-class module))
+             (apply #'idlwave-find-inherited-class module))
       module)))
 
 (defun idlwave-find-inherited-class (name type class)
@@ -7979,7 +7953,7 @@ appropriate Init method."
               (setq string (buffer-substring (point) pos))
               (string-match "obj_new([^'\"]*['\"]\\([a-zA-Z0-9_]+\\)"
                             string)))
-       (let ((name "Init")
+       (let (;; (name "Init")
              (class (match-string 1 string)))
          (setq module (list (idlwave-sintern-method "Init")
                             'fun
@@ -7992,7 +7966,8 @@ appropriate Init method."
 Translate OBJ_NEW, adding all super-class keywords, or all keywords
 from all classes if CLASS equals t.  If SYSTEM is non-nil, don't
 demand _EXTRA in the keyword list."
-  (let ((case-fold-search t))
+  (let ((case-fold-search t)
+        (idlwave--super-classes super-classes))
 
     ;; If this is the OBJ_NEW function, try to figure out the class and use
     ;; the keywords from the corresponding INIT method.
@@ -8013,7 +7988,8 @@ demand _EXTRA in the keyword list."
                               (idlwave-sintern-method "INIT")
                               'fun
                               class
-                              (idlwave-routines)) 'do-link))))))
+                              (idlwave-routines))
+                             'do-link))))))
 
     ;; If the class is t, combine all keywords of all methods NAME
     (when (eq class t)
@@ -8030,7 +8006,7 @@ demand _EXTRA in the keyword list."
     ;; If we have inheritance, add all keywords from superclasses, if
     ;; the user indicated that method in `idlwave-keyword-class-inheritance'
     (when (and
-          super-classes
+          idlwave--super-classes
           idlwave-keyword-class-inheritance
           (stringp class)
           (or
@@ -8045,7 +8021,7 @@ demand _EXTRA in the keyword list."
 
       (cl-loop for entry in (idlwave-routines) do
            (and (nth 2 entry)                           ; non-nil class
-                (memq (nth 2 entry) super-classes)      ; an inherited class
+                (memq (nth 2 entry) idlwave--super-classes) ;an inherited class
                 (eq (nth 1 entry) type)                 ; correct type
                 (eq (car entry) name)                   ; correct name
                 (mapc (lambda (k) (add-to-list 'keywords k))
@@ -8095,16 +8071,16 @@ If we do not know about MODULE, just return KEYWORD 
literally."
 
 (defvar idlwave-rinfo-mouse-map
   (let ((map (make-sparse-keymap)))
-    (define-key map [mouse-2] 'idlwave-mouse-active-rinfo)
-    (define-key map [(shift mouse-2)] 'idlwave-mouse-active-rinfo-shift)
-    (define-key map [mouse-3] 'idlwave-mouse-active-rinfo-right)
-    (define-key map " " 'idlwave-active-rinfo-space)
-    (define-key map "q" 'idlwave-quit-help)
+    (define-key map [mouse-2] #'idlwave-mouse-active-rinfo)
+    (define-key map [(shift mouse-2)] #'idlwave-mouse-active-rinfo-shift)
+    (define-key map [mouse-3] #'idlwave-mouse-active-rinfo-right)
+    (define-key map " " #'idlwave-active-rinfo-space)
+    (define-key map "q" #'idlwave-quit-help)
     map))
 
 (defvar idlwave-rinfo-map
   (let ((map (make-sparse-keymap)))
-    (define-key map "q" 'idlwave-quit-help)
+    (define-key map "q" #'idlwave-quit-help)
     map))
 
 (defvar idlwave-popup-source nil)
@@ -8151,7 +8127,7 @@ If we do not know about MODULE, just return KEYWORD 
literally."
         (data (list name type class (current-buffer) nil initial-class))
         (face 'idlwave-help-link)
         beg props win cnt total)
-    ;; Fix keywords, but don't add chained super-classes, since these
+    ;; Fix keywords, but don't add chained idlwave--super-classes, since these
     ;; are shown separately for that super-class
     (setq keywords (idlwave-fix-keywords name type class keywords))
     (cond
@@ -8336,7 +8312,7 @@ to it."
       (add-text-properties beg (point) (list 'face 'bold)))
     (when (and file (not (equal file "")))
       (setq beg (point))
-      (insert (apply 'abbreviate-file-name (list file)))
+      (insert (apply #'abbreviate-file-name (list file)))
       (if file-props
          (add-text-properties beg (point) file-props)))))
 
@@ -8441,9 +8417,9 @@ was pressed."
               idlwave-keyword-completion-adds-equal)
          (insert "=")))))
 
-(defun idlwave-list-buffer-load-path-shadows (&optional arg)
+(defun idlwave-list-buffer-load-path-shadows (&optional _arg)
   "List the load path shadows of all routines defined in current buffer."
-  (interactive "P")
+  (interactive)
   (idlwave-routines)
   (if (derived-mode-p 'idlwave-mode)
       (idlwave-list-load-path-shadows
@@ -8451,13 +8427,13 @@ was pressed."
        "in current buffer")
     (error "Current buffer is not in idlwave-mode")))
 
-(defun idlwave-list-shell-load-path-shadows (&optional arg)
+(defun idlwave-list-shell-load-path-shadows (&optional _arg)
   "List the load path shadows of all routines compiled under the shell.
 This is very useful for checking an IDL application.  Just compile the
 application, do RESOLVE_ALL, and `C-c C-i' to compile all referenced
 routines and update IDLWAVE internal info.  Then check for shadowing
 with this command."
-  (interactive "P")
+  (interactive)
   (cond
    ((or (not (fboundp 'idlwave-shell-is-running))
        (not (idlwave-shell-is-running)))
@@ -8468,15 +8444,15 @@ with this command."
     (idlwave-list-load-path-shadows nil idlwave-compiled-routines
                                    "in the shell"))))
 
-(defun idlwave-list-all-load-path-shadows (&optional arg)
+(defun idlwave-list-all-load-path-shadows (&optional _arg)
   "List the load path shadows of all routines known to IDLWAVE."
-  (interactive "P")
+  (interactive)
   (idlwave-list-load-path-shadows nil nil "globally"))
 
 (defvar idlwave-sort-prefer-buffer-info t
   "Internal variable used to influence `idlwave-routine-twin-compare'.")
 
-(defun idlwave-list-load-path-shadows (arg &optional special-routines loc)
+(defun idlwave-list-load-path-shadows (_arg &optional special-routines loc)
   "List the routines which are defined multiple times.
 Search the information IDLWAVE has about IDL routines for multiple
 definitions.
@@ -8525,12 +8501,12 @@ can be used to detect possible name clashes during this 
process."
       (lambda (ev)
        (interactive "e")
        (mouse-set-point ev)
-       (apply 'idlwave-do-find-module
+       (apply #'idlwave-do-find-module
               (get-text-property (point) 'find-args))))
     (define-key keymap [(return)]
       (lambda ()
        (interactive)
-       (apply 'idlwave-do-find-module
+       (apply #'idlwave-do-find-module
               (get-text-property (point) 'find-args))))
     (message "Compiling list...( 0%%)")
     (with-current-buffer (get-buffer-create "*Shadows*")
@@ -8606,6 +8582,10 @@ ENTRY will also be returned, as the first item of this 
list."
        (push candidate twins))
     (cons entry (nreverse twins))))
 
+;; Bound in idlwave-study-twins,idlwave-routine-entry-compare-twins.
+(defvar idlwave-twin-class)
+(defvar idlwave-twin-name)
+
 (defun idlwave-study-twins (entries)
   "Return dangerous twins of first entry in ENTRIES.
 Dangerous twins are routines with same name, but in different files on
@@ -8618,7 +8598,7 @@ routines, and may have been scanned."
         (type (nth 1 entry))    ; Must be bound for
         (idlwave-twin-class (nth 2 entry)) ;  idlwave-routine-twin-compare
         (cnt 0)
-        source type type-cons file alist syslibp key)
+        source type-cons file alist syslibp key)
     (while (setq entry (pop entries))
       (cl-incf cnt)
       (setq source (nth 3 entry)
@@ -8654,12 +8634,12 @@ routines, and may have been scanned."
     (when (and (idlwave-syslib-scanned-p)
               (setq entry (assoc 'system alist)))
       (setcar entry 'builtin))
-    (sort alist 'idlwave-routine-twin-compare)))
+    (sort alist #'idlwave-routine-twin-compare)))
 
 ;; FIXME: Dynamically scoped vars need to use the `idlwave-' prefix.
 ;; (defvar type)
 
-(define-obsolete-function-alias 'idlwave-xor 'xor "27.1")
+(define-obsolete-function-alias 'idlwave-xor #'xor "27.1")
 
 (defun idlwave-routine-entry-compare (a b)
   "Compare two routine info entries for sorting.
@@ -8690,7 +8670,7 @@ names and path locations."
   "Compare two routine entries, under the assumption that they are twins.
 This basically calls `idlwave-routine-twin-compare' with the correct args."
   (let* ((idlwave-twin-name (car a))
-        (type (nth 1 a))
+        ;; (type (nth 1 a))
         (idlwave-twin-class (nth 2 a)) ; used in idlwave-routine-twin-compare
         (asrc (nth 3 a))
         (atype (car asrc))
@@ -8706,10 +8686,6 @@ This basically calls `idlwave-routine-twin-compare' with 
the correct args."
         (list (file-truename bfile) bfile (list btype))
        (list btype bfile (list btype))))))
 
-;; Bound in idlwave-study-twins,idlwave-routine-entry-compare-twins.
-(defvar idlwave-twin-class)
-(defvar idlwave-twin-name)
-
 (defun idlwave-routine-twin-compare (a b)
   "Compare two routine twin entries for sorting.
 In here, A and B are not normal routine info entries, but special
@@ -8809,9 +8785,7 @@ This expects NAME TYPE IDLWAVE-TWIN-CLASS to be bound to 
the right values."
 
 (defun idlwave-path-alist-add-flag (list-entry flag)
   "Add a flag to the path list entry, if not set."
-  (let ((flags (cdr list-entry)))
-    (add-to-list 'flags flag)
-    (setcdr list-entry flags)))
+  (cl-pushnew flag (cdr list-entry) :test #'equal))
 
 (defun idlwave-path-alist-remove-flag (list-entry flag)
   "Remove a flag to the path list entry, if set."
@@ -8920,8 +8894,8 @@ Assumes that point is at the beginning of the unit as 
found by
      ["(Un)Comment Region" idlwave-toggle-comment-region t]
      ["Continue/Split line" idlwave-split-line t]
      "--"
-     ["Toggle Auto Fill" idlwave-auto-fill-mode :style toggle
-      :selected (symbol-value idlwave-fill-function)])
+     ["Toggle Auto Fill" auto-fill-mode :style toggle
+      :selected auto-fill-function])
     ("Templates"
      ["Procedure" idlwave-procedure t]
      ["Function" idlwave-function t]
@@ -9069,7 +9043,7 @@ With arg, list all abbrevs with the corresponding hook.
 This function was written since `list-abbrevs' looks terrible for IDLWAVE 
mode."
 
   (interactive "P")
-  (let ((table (symbol-value 'idlwave-mode-abbrev-table))
+  (let ((table idlwave-mode-abbrev-table)
        abbrevs
        str rpl func fmt (len-str 0) (len-rpl 0))
     (mapatoms
diff --git a/lisp/progmodes/inf-lisp.el b/lisp/progmodes/inf-lisp.el
index ac23059..af6ccce 100644
--- a/lisp/progmodes/inf-lisp.el
+++ b/lisp/progmodes/inf-lisp.el
@@ -76,8 +76,7 @@
 Input matching this regexp is not saved on the input history in Inferior Lisp
 mode.  Default is whitespace followed by 0 or 1 single-letter colon-keyword
 \(as in :a, :c, etc.)"
-  :type 'regexp
-  :group 'inferior-lisp)
+  :type 'regexp)
 
 (defvar inferior-lisp-mode-map
   (let ((map (copy-keymap comint-mode-map)))
@@ -155,8 +154,7 @@ mode.  Default is whitespace followed by 0 or 1 
single-letter colon-keyword
 
 (defcustom inferior-lisp-program "lisp"
   "Program name for invoking an inferior Lisp in Inferior Lisp mode."
-  :type 'string
-  :group 'inferior-lisp)
+  :type 'string)
 
 (defcustom inferior-lisp-load-command "(load \"%s\")\n"
   "Format-string for building a Lisp expression to load a file.
@@ -166,8 +164,7 @@ to load that file.  The default works acceptably on most 
Lisps.
 The string \"(progn (load \\\"%s\\\" :verbose nil :print t) (values))\\n\"
 produces cosmetically superior output for this application,
 but it works only in Common Lisp."
-  :type 'string
-  :group 'inferior-lisp)
+  :type 'string)
 
 (defcustom inferior-lisp-prompt "^[^> \n]*>+:? *"
   "Regexp to recognize prompts in the Inferior Lisp mode.
@@ -182,8 +179,7 @@ More precise choices:
 Lucid Common Lisp: \"^\\\\(>\\\\|\\\\(->\\\\)+\\\\) *\"
 franz: \"^\\\\(->\\\\|<[0-9]*>:\\\\) *\"
 kcl: \"^>+ *\""
-  :type 'regexp
-  :group 'inferior-lisp)
+  :type 'regexp)
 
 (defvar inferior-lisp-buffer nil "*The current inferior-lisp process buffer.
 
@@ -487,12 +483,11 @@ describing the last `lisp-load-file' or 
`lisp-compile-file' command.")
 If it's loaded into a buffer that is in one of these major modes, it's
 considered a Lisp source file by `lisp-load-file' and `lisp-compile-file'.
 Used by these commands to determine defaults."
-  :type '(repeat symbol)
-  :group 'inferior-lisp)
+  :type '(repeat symbol))
 
 (defun lisp-load-file (file-name)
   "Load a Lisp file into the inferior Lisp process."
-  (interactive (comint-get-source "Load Lisp file: " lisp-prev-l/c-dir/file
+  (interactive (comint-get-source "Load Lisp file" lisp-prev-l/c-dir/file
                                  lisp-source-modes nil)) ; nil because LOAD
                                        ; doesn't need an exact name
   (comint-check-source file-name) ; Check to see if buffer needs saved.
@@ -505,7 +500,7 @@ Used by these commands to determine defaults."
 
 (defun lisp-compile-file (file-name)
   "Compile a Lisp file in the inferior Lisp process."
-  (interactive (comint-get-source "Compile Lisp file: " lisp-prev-l/c-dir/file
+  (interactive (comint-get-source "Compile Lisp file" lisp-prev-l/c-dir/file
                                  lisp-source-modes nil)) ; nil = don't need
                                        ; suffix .lisp
   (comint-check-source file-name) ; Check to see if buffer needs saved.
diff --git a/lisp/progmodes/js.el b/lisp/progmodes/js.el
index cdf6536..eb690a7 100644
--- a/lisp/progmodes/js.el
+++ b/lisp/progmodes/js.el
@@ -282,7 +282,7 @@ Match group 1 is the name of the macro.")
      "continue" "debugger" "default" "delete" "do" "else"
      "enum" "export" "extends" "final" "finally" "for"
      "function" "goto" "if" "implements" "import" "in"
-     "instanceof" "interface" "native" "new" "package"
+     "instanceof" "interface" "native" "new" "of" "package"
      "private" "protected" "public" "return" "static"
      "super" "switch" "synchronized" "throw"
      "throws" "transient" "try" "typeof" "var" "void" "let"
@@ -427,22 +427,19 @@ Match group 1 is the name of the macro.")
 (defcustom js-indent-level 4
   "Number of spaces for each indentation step in `js-mode'."
   :type 'integer
-  :safe 'integerp
-  :group 'js)
+  :safe 'integerp)
 
 (defcustom js-expr-indent-offset 0
   "Number of additional spaces for indenting continued expressions.
 The value must be no less than minus `js-indent-level'."
   :type 'integer
-  :safe 'integerp
-  :group 'js)
+  :safe 'integerp)
 
 (defcustom js-paren-indent-offset 0
   "Number of additional spaces for indenting expressions in parentheses.
 The value must be no less than minus `js-indent-level'."
   :type 'integer
   :safe 'integerp
-  :group 'js
   :version "24.1")
 
 (defcustom js-square-indent-offset 0
@@ -450,7 +447,6 @@ The value must be no less than minus `js-indent-level'."
 The value must be no less than minus `js-indent-level'."
   :type 'integer
   :safe 'integerp
-  :group 'js
   :version "24.1")
 
 (defcustom js-curly-indent-offset 0
@@ -458,7 +454,6 @@ The value must be no less than minus `js-indent-level'."
 The value must be no less than minus `js-indent-level'."
   :type 'integer
   :safe 'integerp
-  :group 'js
   :version "24.1")
 
 (defcustom js-switch-indent-offset 0
@@ -466,26 +461,22 @@ The value must be no less than minus `js-indent-level'."
 The value must not be negative."
   :type 'integer
   :safe 'integerp
-  :group 'js
   :version "24.4")
 
 (defcustom js-flat-functions nil
   "Treat nested functions as top-level functions in `js-mode'.
 This applies to function movement, marking, and so on."
-  :type 'boolean
-  :group 'js)
+  :type 'boolean)
 
 (defcustom js-indent-align-list-continuation t
   "Align continuation of non-empty ([{ lines in `js-mode'."
   :version "26.1"
   :type 'boolean
-  :safe 'booleanp
-  :group 'js)
+  :safe 'booleanp)
 
 (defcustom js-comment-lineup-func #'c-lineup-C-comments
   "Lineup function for `cc-mode-style', for C comments in `js-mode'."
-  :type 'function
-  :group 'js)
+  :type 'function)
 
 (defcustom js-enabled-frameworks js--available-frameworks
   "Frameworks recognized by `js-mode'.
@@ -493,30 +484,26 @@ To improve performance, you may turn off some frameworks 
you
 seldom use, either globally or on a per-buffer basis."
   :type (cons 'set (mapcar (lambda (x)
                              (list 'const x))
-                           js--available-frameworks))
-  :group 'js)
+                           js--available-frameworks)))
 
 (defcustom js-js-switch-tabs
   (and (memq system-type '(darwin)) t)
   "Whether `js-mode' should display tabs while selecting them.
 This is useful only if the windowing system has a good mechanism
 for preventing Firefox from stealing the keyboard focus."
-  :type 'boolean
-  :group 'js)
+  :type 'boolean)
 
 (defcustom js-js-tmpdir
   "~/.emacs.d/js/js"
   "Temporary directory used by `js-mode' to communicate with Mozilla.
 This directory must be readable and writable by both Mozilla and Emacs."
-  :type 'directory
-  :group 'js)
+  :type 'directory)
 
 (defcustom js-js-timeout 5
   "Reply timeout for executing commands in Mozilla via `js-mode'.
 The value is given in seconds.  Increase this value if you are
 getting timeout messages."
-  :type 'integer
-  :group 'js)
+  :type 'integer)
 
 (defcustom js-indent-first-init nil
   "Non-nil means specially indent the first variable declaration's initializer.
@@ -557,8 +544,7 @@ don't indent the first one's initializer; otherwise, indent 
it.
       bar = 2;"
   :version "25.1"
   :type '(choice (const nil) (const t) (const dynamic))
-  :safe 'symbolp
-  :group 'js)
+  :safe 'symbolp)
 
 (defcustom js-chain-indent nil
   "Use \"chained\" indentation.
@@ -571,8 +557,7 @@ then the \".\"s will be lined up:
 "
   :version "26.1"
   :type 'boolean
-  :safe 'booleanp
-  :group 'js)
+  :safe 'booleanp)
 
 (defcustom js-jsx-detect-syntax t
   "When non-nil, automatically detect whether JavaScript uses JSX.
@@ -581,8 +566,7 @@ t.  The detection strategy can be customized by adding 
elements
 to `js-jsx-regexps', which see."
   :version "27.1"
   :type 'boolean
-  :safe 'booleanp
-  :group 'js)
+  :safe 'booleanp)
 
 (defcustom js-jsx-syntax nil
   "When non-nil, parse JavaScript with consideration for JSX syntax.
@@ -600,8 +584,7 @@ When `js-mode' is already enabled, you should call
 It is set to be buffer-local (and t) when in `js-jsx-mode'."
   :version "27.1"
   :type 'boolean
-  :safe 'booleanp
-  :group 'js)
+  :safe 'booleanp)
 
 (defcustom js-jsx-align->-with-< t
   "When non-nil, “>” will be indented to the opening “<” in JSX.
@@ -625,8 +608,7 @@ When this is disabled, JSX indentation looks like this:
     />"
   :version "27.1"
   :type 'boolean
-  :safe 'booleanp
-  :group 'js)
+  :safe 'booleanp)
 
 (defcustom js-jsx-indent-level nil
   "When non-nil, indent JSX by this value, instead of like JS.
@@ -655,8 +637,7 @@ indentation looks like this (different):
   :version "27.1"
   :type '(choice integer
                  (const :tag "Not Set" nil))
-  :safe (lambda (x) (or (null x) (integerp x)))
-  :group 'js)
+  :safe (lambda (x) (or (null x) (integerp x))))
 ;; This is how indentation behaved out-of-the-box until Emacs 27.  JSX
 ;; indentation was controlled with `sgml-basic-offset', which defaults
 ;; to 2, whereas `js-indent-level' defaults to 4.  Users who had the
@@ -685,8 +666,7 @@ indentation looks like this:
 This variable is like `sgml-attribute-offset'."
   :version "27.1"
   :type 'integer
-  :safe 'integerp
-  :group 'js)
+  :safe 'integerp)
 
 ;;; KeyMap
 
@@ -3719,8 +3699,7 @@ Otherwise, use the current value of `process-mark'."
 Strings and numbers are JSON-encoded.  Lists (including nil) are
 made into JavaScript array literals and their contents encoded
 with `js--js-encode-value'."
-  (cond ((stringp x) (json-encode-string x))
-        ((numberp x) (json-encode-number x))
+  (cond ((or (stringp x) (numberp x)) (json-encode x))
         ((symbolp x) (format "{objid:%S}" (symbol-name x)))
         ((js--js-handle-p x)
 
@@ -4410,7 +4389,8 @@ If one hasn't been set, or if it's stale, prompt for a 
new one."
             (with-temp-buffer
               (insert js--js-inserter)
               (insert "(")
-              (insert (json-encode-list defun-info))
+              (let ((standard-output (current-buffer)))
+                (json--print-list defun-info))
               (insert ",\n")
               (insert defun-body)
               (insert "\n)")
diff --git a/lisp/progmodes/ld-script.el b/lisp/progmodes/ld-script.el
index c4ea8e1..485e64e 100644
--- a/lisp/progmodes/ld-script.el
+++ b/lisp/progmodes/ld-script.el
@@ -35,8 +35,7 @@
 (defvar ld-script-location-counter-face 'ld-script-location-counter)
 (defface ld-script-location-counter
   '((t :weight bold :inherit font-lock-builtin-face))
-  "Face for location counter in GNU ld script."
-  :group 'ld-script)
+  "Face for location counter in GNU ld script.")
 
 ;; Syntax rules
 (defvar ld-script-mode-syntax-table
diff --git a/lisp/progmodes/m4-mode.el b/lisp/progmodes/m4-mode.el
index 99f4be3..d9c09f6 100644
--- a/lisp/progmodes/m4-mode.el
+++ b/lisp/progmodes/m4-mode.el
@@ -60,12 +60,34 @@ If m4 is not in your PATH, set this to an absolute file 
name."
 ;;or
 ;;(defconst m4-program-options '("--prefix-builtins"))
 
+;; Needed at compile-time for `m4-font-lock-keywords' below.
+(eval-and-compile
+  (defconst m4--macro-list
+    ;; From (info "(m4) Macro index")
+    '("__file__" "__gnu__" "__line__" "__os2__" "__program__" "__unix__"
+      "__windows__" "argn" "array" "array_set" "builtin" "capitalize"
+      "changecom" "changequote" "changeword" "cleardivert" "cond" "copy"
+      "curry" "debugfile" "debugmode" "decr" "define" "define_blind"
+      "defn" "divert" "divnum" "dnl" "downcase" "dquote" "dquote_elt"
+      "dumpdef" "errprint" "esyscmd" "eval" "example" "exch"
+      "fatal_error" "file" "foreach" "foreachq" "forloop" "format" "gnu"
+      "ifdef" "ifelse" "include" "incr" "index" "indir" "join" "joinall"
+      "len" "line" "m4exit" "m4wrap" "maketemp" "mkstemp" "nargs" "os2"
+      "patsubst" "popdef" "pushdef" "quote" "regexp" "rename" "reverse"
+      "shift" "sinclude" "stack_foreach" "stack_foreach_lifo"
+      "stack_foreach_sep" "stack_foreach_sep_lifo" "substr" "syscmd"
+      "sysval" "traceoff" "traceon" "translit" "undefine" "undivert"
+      "unix" "upcase" "windows")
+    "List of valid m4 macros for M4 mode."))
+
 (defvar m4-font-lock-keywords
-  '(("\\(\\_<\\(m4_\\)?dnl\\_>\\).*$" (0 font-lock-comment-face t))
-    ("\\$[*#@0-9]" . font-lock-variable-name-face)
-    ("\\$@" . font-lock-variable-name-face)
-    ("\\$\\*" . font-lock-variable-name-face)
-    
("\\_<\\(m4_\\)?\\(builtin\\|change\\(com\\|quote\\|word\\)\\|d\\(e\\(bug\\(file\\|mode\\)\\|cr\\|f\\(ine\\|n\\)\\)\\|iv\\(ert\\|num\\)\\|nl\\|umpdef\\)\\|e\\(rrprint\\|syscmd\\|val\\)\\|f\\(ile\\|ormat\\)\\|gnu\\|i\\(f\\(def\\|else\\)\\|n\\(c\\(lude\\|r\\)\\|d\\(ex\\|ir\\)\\)\\)\\|l\\(en\\|ine\\)\\|m\\(4\\(exit\\|wrap\\)\\|aketemp\\)\\|p\\(atsubst\\|opdef\\|ushdef\\)\\|regexp\\|s\\(hift\\|include\\|ubstr\\|ys\\(cmd\\|val\\)\\)\\|tra\\(ceo\\(ff\\|n\\)\\|nslit\\)\\|un\\(d\\(efine\\|iv
 [...]
+  (eval-when-compile
+    `(("\\(\\_<\\(m4_\\)?dnl\\_>\\).*$" (0 font-lock-comment-face t))
+      ("\\$[*#@0-9]" . font-lock-variable-name-face)
+      ("\\$@" . font-lock-variable-name-face)
+      ("\\$\\*" . font-lock-variable-name-face)
+      (,(concat "\\_<\\(m4_\\)?" (regexp-opt m4--macro-list) "\\_>")
+       . font-lock-keyword-face)))
   "Default `font-lock-keywords' for M4 mode.")
 
 (defcustom m4-mode-hook nil
@@ -100,22 +122,22 @@ If m4 is not in your PATH, set this to an absolute file 
name."
              (string-to-syntax "."))))))
 
 (defvar m4-mode-map
-  (let ((map (make-sparse-keymap))
-       (menu-map (make-sparse-keymap)))
+  (let ((map (make-sparse-keymap)))
     (define-key map "\C-c\C-b" 'm4-m4-buffer)
     (define-key map "\C-c\C-r" 'm4-m4-region)
     (define-key map "\C-c\C-c" 'comment-region)
-    (define-key map [menu-bar m4-mode] (cons "M4" menu-map))
-    (define-key menu-map [m4c]
-      '(menu-item "Comment Region" comment-region
-                 :help "Comment Region"))
-    (define-key menu-map [m4b]
-      '(menu-item "M4 Buffer" m4-m4-buffer
-                 :help "Send contents of the current buffer to m4"))
-    (define-key menu-map [m4r]
-      '(menu-item "M4 Region" m4-m4-region
-                 :help "Send contents of the current region to m4"))
-    map))
+    map)
+  "Keymap for M4 Mode.")
+
+(easy-menu-define m4-mode-menu m4-mode-map
+  "Menu for M4 Mode."
+  '("M4"
+    ["M4 Region" m4-m4-region
+     :help "Send contents of the current region to m4"]
+    ["M4 Buffer" m4-m4-buffer
+     :help "Send contents of the current buffer to m4"]
+    ["Comment Region" comment-region
+     :help "Comment Region"]))
 
 (defun m4-m4-buffer ()
   "Send contents of the current buffer to m4."
@@ -155,22 +177,4 @@ If m4 is not in your PATH, set this to an absolute file 
name."
 ;;stuff to play with for debugging
 ;(char-to-string (char-syntax ?`))
 
-;;;how I generate the nasty looking regexps at the top
-;;;(make-regexp '("builtin" "changecom" "changequote" "changeword" "debugfile"
-;;;              "debugmode" "decr" "define" "defn" "divert" "divnum" "dnl"
-;;;              "dumpdef" "errprint" "esyscmd" "eval" "file" "format" "gnu"
-;;;              "ifdef" "ifelse" "include" "incr" "index" "indir" "len" "line"
-;;;              "m4exit" "m4wrap" "maketemp" "patsubst" "popdef" "pushdef" 
"regexp"
-;;;              "shift" "sinclude" "substr" "syscmd" "sysval" "traceoff" 
"traceon"
-;;;              "translit" "undefine" "undivert" "unix"))
-;;;(make-regexp '("m4_builtin" "m4_changecom" "m4_changequote" "m4_changeword"
-;;;              "m4_debugfile" "m4_debugmode" "m4_decr" "m4_define" "m4_defn"
-;;;              "m4_divert" "m4_divnum" "m4_dnl" "m4_dumpdef" "m4_errprint"
-;;;              "m4_esyscmd" "m4_eval" "m4_file" "m4_format" "m4_ifdef" 
"m4_ifelse"
-;;;              "m4_include" "m4_incr" "m4_index" "m4_indir" "m4_len" 
"m4_line"
-;;;              "m4_m4exit" "m4_m4wrap" "m4_maketemp" "m4_patsubst" 
"m4_popdef"
-;;;              "m4_pushdef" "m4_regexp" "m4_shift" "m4_sinclude" "m4_substr"
-;;;              "m4_syscmd" "m4_sysval" "m4_traceoff" "m4_traceon" 
"m4_translit"
-;;;              "m4_m4_undefine" "m4_undivert"))
-
 ;;; m4-mode.el ends here
diff --git a/lisp/progmodes/make-mode.el b/lisp/progmodes/make-mode.el
index e382d6e..3f466e1 100644
--- a/lisp/progmodes/make-mode.el
+++ b/lisp/progmodes/make-mode.el
@@ -101,14 +101,12 @@
 (defface makefile-space
   '((((class color)) (:background  "hotpink"))
     (t (:reverse-video t)))
-  "Face to use for highlighting leading spaces in Font-Lock mode."
-  :group 'makefile)
+  "Face to use for highlighting leading spaces in Font-Lock mode.")
 
 (defface makefile-targets
   ;; This needs to go along both with foreground and background colors (i.e. 
shell)
   '((t (:inherit font-lock-function-name-face)))
   "Face to use for additionally highlighting rule targets in Font-Lock mode."
-  :group 'makefile
   :version "22.1")
 
 (defface makefile-shell
@@ -116,7 +114,6 @@
   ;;'((((class color) (min-colors 88) (background light)) (:background  
"seashell1"))
   ;;  (((class color) (min-colors 88) (background dark)) (:background  
"seashell4")))
   "Face to use for additionally highlighting Shell commands in Font-Lock mode."
-  :group 'makefile
   :version "22.1")
 
 (defface makefile-makepp-perl
@@ -124,19 +121,16 @@
     (((class color) (background dark)) (:background  "DarkBlue"))
     (t (:reverse-video t)))
   "Face to use for additionally highlighting Perl code in Font-Lock mode."
-  :group 'makefile
   :version "22.1")
 
 (defcustom makefile-browser-buffer-name "*Macros and Targets*"
   "Name of the macro- and target browser buffer."
-  :type 'string
-  :group 'makefile)
+  :type 'string)
 
 (defcustom makefile-target-colon ":"
   "String to append to all target names inserted by `makefile-insert-target'.
 \":\" or \"::\" are common values."
-  :type 'string
-  :group 'makefile)
+  :type 'string)
 
 (defcustom makefile-macro-assign " = "
   "String to append to all macro names inserted by `makefile-insert-macro'.
@@ -144,70 +138,58 @@ The normal value should be \" = \", since this is what
 standard make expects.  However, newer makes such as dmake
 allow a larger variety of different macro assignments, so you
 might prefer to use \" += \" or \" := \" ."
-  :type 'string
-  :group 'makefile)
+  :type 'string)
 
 (defcustom makefile-electric-keys nil
   "If non-nil, Makefile mode should install electric keybindings.
 Default is nil."
-  :type 'boolean
-  :group 'makefile)
+  :type 'boolean)
 
 (defcustom makefile-use-curly-braces-for-macros-p nil
   "Controls the style of generated macro references.
 Non-nil means macro references should use curly braces, like `${this}'.
 nil means use parentheses, like `$(this)'."
-  :type 'boolean
-  :group 'makefile)
+  :type 'boolean)
 
 (defcustom makefile-tab-after-target-colon t
   "If non-nil, insert a TAB after a target colon.
 Otherwise, a space is inserted.
 The default is t."
-  :type 'boolean
-  :group 'makefile)
+  :type 'boolean)
 
 (defcustom makefile-browser-leftmost-column 10
   "Number of blanks to the left of the browser selection mark."
-  :type 'integer
-  :group 'makefile)
+  :type 'integer)
 
 (defcustom makefile-browser-cursor-column 10
   "Column the cursor goes to when it moves up or down in the Makefile browser."
-  :type 'integer
-  :group 'makefile)
+  :type 'integer)
 
 (defcustom makefile-backslash-column 48
   "Column in which `makefile-backslash-region' inserts backslashes."
-  :type 'integer
-  :group 'makefile)
+  :type 'integer)
 
 (defcustom makefile-backslash-align t
   "If non-nil, `makefile-backslash-region' will align backslashes."
-  :type 'boolean
-  :group 'makefile)
+  :type 'boolean)
 
 (defcustom makefile-browser-selected-mark "+  "
   "String used to mark selected entries in the Makefile browser."
-  :type 'string
-  :group 'makefile)
+  :type 'string)
 
 (defcustom makefile-browser-unselected-mark "   "
   "String used to mark unselected entries in the Makefile browser."
-  :type 'string
-  :group 'makefile)
+  :type 'string)
 
 (defcustom makefile-browser-auto-advance-after-selection-p t
   "If non-nil, cursor will move after item is selected in Makefile browser."
-  :type 'boolean
-  :group 'makefile)
+  :type 'boolean)
 
 (defcustom makefile-pickup-everything-picks-up-filenames-p nil
   "If non-nil, `makefile-pickup-everything' picks up filenames as targets.
 This means it calls `makefile-pickup-filenames-as-targets'.
 Otherwise filenames are omitted."
-  :type 'boolean
-  :group 'makefile)
+  :type 'boolean)
 
 (defcustom makefile-cleanup-continuations nil
   "If non-nil, automatically clean up continuation lines when saving.
@@ -215,13 +197,11 @@ A line is cleaned up by removing all whitespace following 
a trailing
 backslash.  This is done silently.
 IMPORTANT: Please note that enabling this option causes Makefile mode
 to MODIFY A FILE WITHOUT YOUR CONFIRMATION when \"it seems necessary\"."
-  :type 'boolean
-  :group 'makefile)
+  :type 'boolean)
 
 (defcustom makefile-mode-hook nil
   "Normal hook run by `makefile-mode'."
-  :type 'hook
-  :group 'makefile)
+  :type 'hook)
 
 (defvar makefile-browser-hook '())
 
@@ -240,8 +220,7 @@ to MODIFY A FILE WITHOUT YOUR CONFIRMATION when \"it seems 
necessary\"."
   "List of special targets.
 You will be offered to complete on one of those in the minibuffer whenever
 you enter a \".\" at the beginning of a line in `makefile-mode'."
-  :type '(repeat string)
-  :group 'makefile)
+  :type '(repeat string))
 (put 'makefile-special-targets-list 'risky-local-variable t)
 
 (defcustom makefile-runtime-macros-list
@@ -250,8 +229,7 @@ you enter a \".\" at the beginning of a line in 
`makefile-mode'."
 If you insert a macro reference using `makefile-insert-macro-ref', the name
 of the macro is checked against this list.  If it can be found its name will
 not be enclosed in { } or ( )."
-  :type '(repeat (list string))
-  :group 'makefile)
+  :type '(repeat (list string)))
 
 ;; Note that the first big subexpression is used by font lock.  Note
 ;; that if you change this regexp you might have to fix the imenu
@@ -563,8 +541,7 @@ not be enclosed in { } or ( )."
 (defcustom makefile-brave-make "make"
   "How to invoke make, for `makefile-query-targets'.
 This should identify a `make' command that can handle the `-q' option."
-  :type 'string
-  :group 'makefile)
+  :type 'string)
 
 (defvaralias 'makefile-query-one-target-method
   'makefile-query-one-target-method-function)
@@ -584,13 +561,11 @@ The function must satisfy this calling convention:
 * It must return the integer value 0 (zero) if the given target
   should be considered up-to-date in the context of the given
   makefile, any nonzero integer value otherwise."
-  :type 'function
-  :group 'makefile)
+  :type 'function)
 
 (defcustom makefile-up-to-date-buffer-name "*Makefile Up-to-date overview*"
   "Name of the Up-to-date overview buffer."
-  :type 'string
-  :group 'makefile)
+  :type 'string)
 
 ;;; --- end of up-to-date-overview configuration ------------------
 
@@ -598,8 +573,7 @@ The function must satisfy this calling convention:
   "Abbrev table in use in Makefile buffers.")
 
 (defvar makefile-mode-map
-  (let ((map (make-sparse-keymap))
-       (opt-map (make-sparse-keymap)))
+  (let ((map (make-sparse-keymap)))
     ;; set up the keymap
     (define-key map "\C-c:" 'makefile-insert-target-ref)
     (if makefile-electric-keys
@@ -624,72 +598,62 @@ The function must satisfy this calling convention:
     (define-key map "\M-p"     'makefile-previous-dependency)
     (define-key map "\M-n"     'makefile-next-dependency)
     (define-key map "\e\t"     'completion-at-point)
-
-    ;; Make menus.
-    (define-key map [menu-bar makefile-mode]
-      (cons "Makefile" (make-sparse-keymap "Makefile")))
-
-    (define-key map [menu-bar makefile-mode makefile-type]
-      (cons "Switch Makefile Type" opt-map))
-    (define-key opt-map [makefile-makepp-mode]
-      '(menu-item "Makepp" makefile-makepp-mode
-                 :help "An adapted `makefile-mode' that knows about makepp"
-                 :button (:radio . (eq major-mode 'makefile-makepp-mode))))
-    (define-key opt-map [makefile-imake-mode]
-      '(menu-item "Imake" makefile-imake-mode
-                 :help "An adapted `makefile-mode' that knows about imake"
-                 :button (:radio . (eq major-mode 'makefile-imake-mode))))
-    (define-key opt-map [makefile-mode]
-      '(menu-item "Classic" makefile-mode
-                 :help "`makefile-mode' with no special functionality"
-                 :button (:radio . (eq major-mode 'makefile-mode))))
-    (define-key opt-map [makefile-bsdmake-mode]
-      '(menu-item "BSD" makefile-bsdmake-mode
-                 :help "An adapted `makefile-mode' that knows about BSD make"
-                 :button (:radio . (eq major-mode 'makefile-bsdmake-mode))))
-    (define-key opt-map [makefile-automake-mode]
-      '(menu-item "Automake" makefile-automake-mode
-                 :help "An adapted `makefile-mode' that knows about automake"
-                 :button (:radio . (eq major-mode 'makefile-automake-mode))))
-    (define-key opt-map [makefile-gmake-mode]
-      '(menu-item "GNU make" makefile-gmake-mode
-                 :help "An adapted `makefile-mode' that knows about GNU make"
-                 :button (:radio . (eq major-mode 'makefile-gmake-mode))))
-    (define-key map [menu-bar makefile-mode browse]
-      '(menu-item "Pop up Makefile Browser" makefile-switch-to-browser
-                 ;; XXX: this needs a better string, the function is not 
documented...
-                 :help "Pop up Makefile Browser"))
-    (define-key map [menu-bar makefile-mode overview]
-      '(menu-item "Up To Date Overview" makefile-create-up-to-date-overview
-                 :help "Create a buffer containing an overview of the state of 
all known targets"))
-    ;; Target related
-    (define-key map [menu-bar makefile-mode separator1]  '("----"))
-    (define-key map [menu-bar makefile-mode pickup-file]
-      '(menu-item "Pick File Name as Target" 
makefile-pickup-filenames-as-targets
-                 :help "Scan the current directory for filenames to use as 
targets"))
-    (define-key map [menu-bar makefile-mode function]
-      '(menu-item "Insert GNU make function" makefile-insert-gmake-function
-                 :help "Insert a GNU make function call"))
-    (define-key map [menu-bar makefile-mode pickup]
-      '(menu-item "Find Targets and Macros" makefile-pickup-everything
-                 :help "Notice names of all macros and targets in Makefile"))
-    (define-key map [menu-bar makefile-mode complete]
-      '(menu-item "Complete Target or Macro" completion-at-point
-                 :help "Perform completion on Makefile construct preceding 
point"))
-    (define-key map [menu-bar makefile-mode backslash]
-      '(menu-item "Backslash Region" makefile-backslash-region
-                 :help "Insert, align, or delete end-of-line backslashes on 
the lines in the region"))
-    ;; Motion
-    (define-key map [menu-bar makefile-mode separator]  '("----"))
-    (define-key map [menu-bar makefile-mode prev]
-      '(menu-item "Move to Previous Dependency" makefile-previous-dependency
-                 :help "Move point to the beginning of the previous dependency 
line"))
-    (define-key map [menu-bar makefile-mode next]
-      '(menu-item "Move to Next Dependency" makefile-next-dependency
-                 :help "Move point to the beginning of the next dependency 
line"))
     map)
   "The keymap that is used in Makefile mode.")
 
+(easy-menu-define makefile-mode-menu makefile-mode-map
+  "Menu for Makefile mode."
+  '("Makefile"
+    ;; Motion
+    ["Move to Next Dependency" makefile-next-dependency
+     :help "Move point to the beginning of the next dependency line"]
+    ["Move to Previous Dependency" makefile-previous-dependency
+     :help "Move point to the beginning of the previous dependency line"]
+    "----"
+    ;; Target related
+    ["Backslash Region" makefile-backslash-region
+     :help "Insert, align, or delete end-of-line backslashes on the lines in 
the region"]
+    ["Complete Target or Macro" completion-at-point
+     :help "Perform completion on Makefile construct preceding point"]
+    ["Find Targets and Macros" makefile-pickup-everything
+     :help "Notice names of all macros and targets in Makefile"]
+    ["Insert GNU make function" makefile-insert-gmake-function
+     :help "Insert a GNU make function call"]
+    ["Pick File Name as Target" makefile-pickup-filenames-as-targets
+     :help "Scan the current directory for filenames to use as targets"]
+    "----"
+    ;; Other.
+    ["Up To Date Overview" makefile-create-up-to-date-overview
+     :help "Create a buffer containing an overview of the state of all known 
targets"]
+    ["Pop up Makefile Browser" makefile-switch-to-browser
+     ;; XXX: this needs a better string, the function is not documented...
+     :help "Pop up Makefile Browser"]
+    ("Switch Makefile Type"
+     ["GNU make" makefile-gmake-mode
+      :help "An adapted `makefile-mode' that knows about GNU make"
+      :style radio
+      :selected (eq major-mode 'makefile-gmake-mode)]
+     ["Automake" makefile-automake-mode
+      :help "An adapted `makefile-mode' that knows about automake"
+      :style radio
+      :selected (eq major-mode 'makefile-automake-mode)]
+     ["BSD" makefile-bsdmake-mode
+      :help "An adapted `makefile-mode' that knows about BSD make"
+      :style radio
+      :selected (eq major-mode 'makefile-bsdmake-mode)]
+     ["Classic" makefile-mode
+      :help "`makefile-mode' with no special functionality"
+      :style radio
+      :selected (eq major-mode 'makefile-mode)]
+     ["Imake" makefile-imake-mode
+      :help "An adapted `makefile-mode' that knows about imake"
+      :style radio
+      :selected (eq major-mode 'makefile-imake-mode)]
+     ["Makepp" makefile-makepp-mode
+      :help "An adapted `makefile-mode' that knows about makepp"
+      :style radio
+      :selected (eq major-mode 'makefile-makepp-mode)])))
+
 
 (defvar makefile-browser-map
   (let ((map (make-sparse-keymap)))
diff --git a/lisp/progmodes/meta-mode.el b/lisp/progmodes/meta-mode.el
index 9da968c..a590148 100644
--- a/lisp/progmodes/meta-mode.el
+++ b/lisp/progmodes/meta-mode.el
@@ -88,8 +88,6 @@
 
 ;;; Code:
 
-(require 'easymenu)
-
 (defgroup meta-font nil
   "Major mode for editing Metafont or MetaPost sources."
   :link '(custom-group-link :tag "Font Lock Faces group" font-lock-faces)
@@ -109,44 +107,31 @@
              "\\(def\\|let\\|mode_def\\|vardef\\)")
             (macro-keywords-2
              "\\(primarydef\\|secondarydef\\|tertiarydef\\)")
-;(make-regexp
-; '("expr" "suffix" "text" "primary" "secondary" "tertiary") t)
             (args-keywords
-             (concat "\\(expr\\|primary\\|s\\(econdary\\|uffix\\)\\|"
-                     "te\\(rtiary\\|xt\\)\\)"))
-;(make-regexp
-; '("boolean" "color" "numeric" "pair" "path" "pen" "picture"
-;   "string" "transform" "newinternal") t)
+             (eval-when-compile
+               (regexp-opt
+                '("expr" "suffix" "text" "primary" "secondary" "tertiary")
+                t)))
             (type-keywords
-             (concat "\\(boolean\\|color\\|n\\(ewinternal\\|umeric\\)\\|"
-                     "p\\(a\\(ir\\|th\\)\\|en\\|icture\\)\\|string\\|"
-                     "transform\\)"))
-;(make-regexp
-; '("for" "forever" "forsuffixes" "endfor"
-;   "step" "until" "upto" "downto" "thru" "within"
-;   "iff" "if" "elseif" "else" "fi" "exitif" "exitunless"
-;   "let" "def" "vardef" "enddef" "mode_def"
-;   "true" "false" "known" "unknown" "and" "or" "not"
-;   "save" "interim" "inner" "outer" "relax"
-;   "begingroup" "endgroup" "expandafter" "scantokens"
-;   "generate" "input" "endinput" "end" "bye"
-;   "message" "errmessage" "errhelp" "special" "numspecial"
-;   "readstring" "readfrom" "write") t)
+             (eval-when-compile
+              (regexp-opt
+               '("boolean" "color" "numeric" "pair" "path" "pen" "picture"
+                 "string" "transform" "newinternal")
+               t)))
             (syntactic-keywords
-             (concat "\\(and\\|b\\(egingroup\\|ye\\)\\|"
-                     "d\\(ef\\|ownto\\)\\|e\\(lse\\(\\|if\\)"
-                     "\\|nd\\(\\|def\\|for\\|group\\|input\\)"
-                     "\\|rr\\(help\\|message\\)"
-                     "\\|x\\(it\\(if\\|unless\\)\\|pandafter\\)\\)\\|"
-                     "f\\(alse\\|i\\|or\\(\\|ever\\|suffixes\\)\\)\\|"
-                     "generate\\|i\\(ff?\\|n\\(ner\\|put\\|terim\\)\\)\\|"
-                     "known\\|let\\|m\\(essage\\|ode_def\\)\\|"
-                     "n\\(ot\\|umspecial\\)\\|o\\(r\\|uter\\)\\|"
-                     "re\\(ad\\(from\\|string\\)\\|lax\\)\\|"
-                     "s\\(ave\\|cantokens\\|pecial\\|tep\\)\\|"
-                     "t\\(hru\\|rue\\)\\|"
-                     "u\\(n\\(known\\|til\\)\\|pto\\)\\|"
-                     "vardef\\|w\\(ithin\\|rite\\)\\)"))
+             (eval-when-compile
+              (regexp-opt
+               '("for" "forever" "forsuffixes" "endfor"
+                 "step" "until" "upto" "downto" "thru" "within"
+                 "iff" "if" "elseif" "else" "fi" "exitif" "exitunless"
+                 "let" "def" "vardef" "enddef" "mode_def"
+                 "true" "false" "known" "unknown" "and" "or" "not"
+                 "save" "interim" "inner" "outer" "relax"
+                 "begingroup" "endgroup" "expandafter" "scantokens"
+                 "generate" "input" "endinput" "end" "bye"
+                 "message" "errmessage" "errhelp" "special" "numspecial"
+                 "readstring" "readfrom" "write")
+               t)))
             )
         (list
          ;; embedded TeX code in btex ... etex
@@ -463,25 +448,21 @@ If the list was changed, sort the list and remove 
duplicates first."
 
 (defcustom meta-indent-level 2
   "Indentation of begin-end blocks in Metafont or MetaPost mode."
-  :type 'integer
-  :group 'meta-font)
+  :type 'integer)
 
 
 (defcustom meta-left-comment-regexp "%%+"
   "Regexp matching comments that should be placed on the left margin."
-  :type 'regexp
-  :group 'meta-font)
+  :type 'regexp)
 
 (defcustom meta-right-comment-regexp nil
   "Regexp matching comments that should be placed on the right margin."
   :type '(choice regexp
-                (const :tag "None" nil))
-  :group 'meta-font)
+                 (const :tag "None" nil)))
 
 (defcustom meta-ignore-comment-regexp "%[^%]"
   "Regexp matching comments whose indentation should not be touched."
-  :type 'regexp
-  :group 'meta-font)
+  :type 'regexp)
 
 
 (defcustom meta-begin-environment-regexp
@@ -489,22 +470,19 @@ If the list was changed, sort the list and remove 
duplicates first."
           "def\\|for\\(\\|ever\\|suffixes\\)\\|if\\|mode_def\\|"
           "primarydef\\|secondarydef\\|tertiarydef\\|vardef\\)")
   "Regexp matching the beginning of environments to be indented."
-  :type 'regexp
-  :group 'meta-font)
+  :type 'regexp)
 
 (defcustom meta-end-environment-regexp
   (concat "\\(end\\(char\\|def\\|f\\(ig\\|or\\)\\|gr\\(aph\\|oup\\)\\)"
           "\\|fi\\)")
   "Regexp matching the end of environments to be indented."
-  :type 'regexp
-  :group 'meta-font)
+  :type 'regexp)
 
 (defcustom meta-within-environment-regexp
 ; (concat "\\(e\\(lse\\(\\|if\\)\\|xit\\(if\\|unless\\)\\)\\)")
   (concat "\\(else\\(\\|if\\)\\)")
   "Regexp matching keywords within environments not to be indented."
-  :type 'regexp
-  :group 'meta-font)
+  :type 'regexp)
 
 
 (defun meta-comment-indent ()
@@ -689,14 +667,12 @@ If the list was changed, sort the list and remove 
duplicates first."
   (concat "\\(begin\\(char\\|fig\\|logochar\\)\\|def\\|mode_def\\|"
           "primarydef\\|secondarydef\\|tertiarydef\\|vardef\\)")
   "Regexp matching beginning of defuns in Metafont or MetaPost mode."
-  :type 'regexp
-  :group 'meta-font)
+  :type 'regexp)
 
 (defcustom meta-end-defun-regexp
   (concat "\\(end\\(char\\|def\\|fig\\)\\)")
   "Regexp matching the end of defuns in Metafont or MetaPost mode."
-  :type 'regexp
-  :group 'meta-font)
+  :type 'regexp)
 
 
 (defun meta-beginning-of-defun (&optional arg)
@@ -893,24 +869,21 @@ The environment marked is the one that contains point or 
follows point."
 
 (defcustom meta-mode-load-hook nil
   "Hook evaluated when first loading Metafont or MetaPost mode."
-  :type 'hook
-  :group 'meta-font)
+  :type 'hook)
 (make-obsolete-variable 'meta-mode-load-hook
                         "use `with-eval-after-load' instead." "28.1")
 
 (defcustom meta-common-mode-hook nil
   "Hook evaluated by both `metafont-mode' and `metapost-mode'."
-  :type 'hook
-  :group 'meta-font)
+  :type 'hook)
 
 (defcustom metafont-mode-hook nil
   "Hook evaluated by `metafont-mode' after `meta-common-mode-hook'."
-  :type 'hook
-  :group 'meta-font)
+  :type 'hook)
+
 (defcustom metapost-mode-hook nil
   "Hook evaluated by `metapost-mode' after `meta-common-mode-hook'."
-  :type 'hook
-  :group 'meta-font)
+  :type 'hook)
 
 
 
diff --git a/lisp/progmodes/modula2.el b/lisp/progmodes/modula2.el
index a77a4e2..2a0374a 100644
--- a/lisp/progmodes/modula2.el
+++ b/lisp/progmodes/modula2.el
@@ -1,4 +1,4 @@
-;;; modula2.el --- Modula-2 editing support package
+;;; modula2.el --- Modula-2 editing support package  -*- lexical-binding: t -*-
 
 ;; Author: Michael Schmidt <michael@pbinfo.UUCP>
 ;;     Tom Perrine <Perrin@LOGICON.ARPA>
@@ -51,62 +51,57 @@
 
 (defcustom m2-compile-command "m2c"
   "Command to compile Modula-2 programs."
-  :type 'string
-  :group 'modula2)
+  :type 'string)
 
 (defcustom m2-link-command "m2l"
   "Command to link Modula-2 programs."
-  :type 'string
-  :group 'modula2)
+  :type 'string)
 
 (defcustom m2-link-name nil
   "Name of the Modula-2 executable."
-  :type '(choice (const nil) string)
-  :group 'modula2)
+  :type '(choice (const nil) string))
 
 (defcustom m2-end-comment-column 75
   "Column for aligning the end of a comment, in Modula-2."
-  :type 'integer
-  :group 'modula2)
+  :type 'integer)
 
 ;;; Added by TEP
 (defvar m2-mode-map
   (let ((map (make-sparse-keymap)))
     ;; FIXME: Many of those bindings are contrary to coding conventions.
-    (define-key map "\C-cb" 'm2-begin)
-    (define-key map "\C-cc" 'm2-case)
-    (define-key map "\C-cd" 'm2-definition)
-    (define-key map "\C-ce" 'm2-else)
-    (define-key map "\C-cf" 'm2-for)
-    (define-key map "\C-ch" 'm2-header)
-    (define-key map "\C-ci" 'm2-if)
-    (define-key map "\C-cm" 'm2-module)
-    (define-key map "\C-cl" 'm2-loop)
-    (define-key map "\C-co" 'm2-or)
-    (define-key map "\C-cp" 'm2-procedure)
-    (define-key map "\C-c\C-w" 'm2-with)
-    (define-key map "\C-cr" 'm2-record)
-    (define-key map "\C-cs" 'm2-stdio)
-    (define-key map "\C-ct" 'm2-type)
-    (define-key map "\C-cu" 'm2-until)
-    (define-key map "\C-cv" 'm2-var)
-    (define-key map "\C-cw" 'm2-while)
-    (define-key map "\C-cx" 'm2-export)
-    (define-key map "\C-cy" 'm2-import)
-    (define-key map "\C-c{" 'm2-begin-comment)
-    (define-key map "\C-c}" 'm2-end-comment)
-    (define-key map "\C-c\C-z" 'suspend-emacs)
-    (define-key map "\C-c\C-v" 'm2-visit)
-    (define-key map "\C-c\C-t" 'm2-toggle)
-    (define-key map "\C-c\C-l" 'm2-link)
-    (define-key map "\C-c\C-c" 'm2-compile)
+    (define-key map "\C-cb" #'m2-begin)
+    (define-key map "\C-cc" #'m2-case)
+    (define-key map "\C-cd" #'m2-definition)
+    (define-key map "\C-ce" #'m2-else)
+    (define-key map "\C-cf" #'m2-for)
+    (define-key map "\C-ch" #'m2-header)
+    (define-key map "\C-ci" #'m2-if)
+    (define-key map "\C-cm" #'m2-module)
+    (define-key map "\C-cl" #'m2-loop)
+    (define-key map "\C-co" #'m2-or)
+    (define-key map "\C-cp" #'m2-procedure)
+    (define-key map "\C-c\C-w" #'m2-with)
+    (define-key map "\C-cr" #'m2-record)
+    (define-key map "\C-cs" #'m2-stdio)
+    (define-key map "\C-ct" #'m2-type)
+    (define-key map "\C-cu" #'m2-until)
+    (define-key map "\C-cv" #'m2-var)
+    (define-key map "\C-cw" #'m2-while)
+    (define-key map "\C-cx" #'m2-export)
+    (define-key map "\C-cy" #'m2-import)
+    (define-key map "\C-c{" #'m2-begin-comment)
+    (define-key map "\C-c}" #'m2-end-comment)
+    (define-key map "\C-c\C-z" #'suspend-emacs)
+    (define-key map "\C-c\C-v" #'m2-visit)
+    (define-key map "\C-c\C-t" #'m2-toggle)
+    (define-key map "\C-c\C-l" #'m2-link)
+    (define-key map "\C-c\C-c" #'m2-compile)
     map)
   "Keymap used in Modula-2 mode.")
 
 (defcustom m2-indent 5
   "This variable gives the indentation in Modula-2 mode."
-  :type 'integer
-  :group 'modula2)
+  :type 'integer)
 (put 'm2-indent 'safe-local-variable
      (lambda (v) (or (null v) (integerp v))))
 
diff --git a/lisp/progmodes/octave.el b/lisp/progmodes/octave.el
index ddcc6f5..196f2de 100644
--- a/lisp/progmodes/octave.el
+++ b/lisp/progmodes/octave.el
@@ -215,9 +215,15 @@ newline or semicolon after an else or end keyword."
   (concat "[^#%\n]*\\(" octave-continuation-marker-regexp
           "\\)\\s-*\\(\\s<.*\\)?$"))
 
-;; Char \ is considered a bad decision for continuing a line.
 (defconst octave-continuation-string "..."
-  "Character string used for Octave continuation lines.")
+  "Character string used for Octave continuation lines.
+Joins current line with following line, except within
+double-quoted strings, where `octave-string-continuation-marker'
+is used instead.")
+
+(defconst octave-string-continuation-marker "\\"
+  "Line continuation marker for double-quoted Octave strings.
+Non-string statements use `octave-continuation-string'.")
 
 (defvar octave-mode-imenu-generic-expression
   (list
@@ -485,8 +491,8 @@ Non-nil means always go to the next Octave code line after 
sending."
          'font-lock-keyword-face)
    ;; Note: 'end' also serves as the last index in an indexing expression,
    ;; and 'enumerate' is also a function.
-   ;; Ref: http://www.mathworks.com/help/matlab/ref/end.html
-   ;; Ref: http://www.mathworks.com/help/matlab/ref/enumeration.html
+   ;; Ref: https://www.mathworks.com/help/matlab/ref/end.html
+   ;; Ref: https://www.mathworks.com/help/matlab/ref/enumeration.html
    (list (lambda (limit)
            (while (re-search-forward "\\_<en\\(?:d\\|umeratio\\(n\\)\\)\\_>"
                                      limit 'move)
@@ -1032,11 +1038,11 @@ directory and makes this the current buffer's default 
directory."
     (looking-at regexp)))
 
 (defun octave-maybe-insert-continuation-string ()
-  (if (or (octave-in-comment-p)
-         (save-excursion
-           (beginning-of-line)
-           (looking-at octave-continuation-regexp)))
-      nil
+  (declare (obsolete nil "28.1"))
+  (unless (or (octave-in-comment-p)
+              (save-excursion
+                (beginning-of-line)
+                (looking-at octave-continuation-regexp)))
     (delete-horizontal-space)
     (insert (concat " " octave-continuation-string))))
 
@@ -1218,23 +1224,22 @@ q: Don't fix\n" func file))
 (defun octave-indent-new-comment-line (&optional soft)
   "Break Octave line at point, continuing comment if within one.
 Insert `octave-continuation-string' before breaking the line
-unless inside a list.  Signal an error if within a single-quoted
-string."
+unless inside a list.  If within a double-quoted string, insert
+`octave-string-continuation-marker' instead.  Signal an error if
+within a single-quoted string."
   (interactive)
   (funcall comment-line-break-function soft))
 
 (defun octave--indent-new-comment-line (orig &rest args)
-  (cond
-   ((octave-in-comment-p) nil)
-   ((eq (octave-in-string-p) ?')
-    (error "Cannot split a single-quoted string"))
-   ((eq (octave-in-string-p) ?\")
-    (insert octave-continuation-string))
-   (t
-    (delete-horizontal-space)
-    (unless (and (cadr (syntax-ppss))
-                 (eq (char-after (cadr (syntax-ppss))) ?\())
-      (insert " " octave-continuation-string))))
+  (pcase (syntax-ppss)
+    ((app ppss-string-terminator ?\')
+     (user-error "Cannot split a single-quoted string"))
+    ((app ppss-string-terminator ?\")
+     (insert octave-string-continuation-marker))
+    ((pred (not ppss-comment-depth))
+     (delete-horizontal-space)
+     (unless (octave-smie--in-parens-p)
+       (insert " " octave-continuation-string))))
   (apply orig args)
   (indent-according-to-mode))
 
@@ -1663,9 +1668,7 @@ code line."
 
 (define-button-type 'octave-help-function
   'follow-link t
-  'action (lambda (b)
-            (octave-help
-             (buffer-substring (button-start b) (button-end b)))))
+  'action (lambda (b) (octave-help (button-label b))))
 
 (defvar octave-help-mode-map
   (let ((map (make-sparse-keymap)))
diff --git a/lisp/progmodes/pascal.el b/lisp/progmodes/pascal.el
index 59f90d7..e6e6e40 100644
--- a/lisp/progmodes/pascal.el
+++ b/lisp/progmodes/pascal.el
@@ -199,38 +199,32 @@
 
 (defcustom pascal-indent-level 3
   "Indentation of Pascal statements with respect to containing block."
-  :type 'integer
-  :group 'pascal)
+  :type 'integer)
 
 (defcustom pascal-case-indent 2
   "Indentation for case statements."
-  :type 'integer
-  :group 'pascal)
+  :type 'integer)
 
 (defcustom pascal-auto-newline nil
   "Non-nil means automatically insert newlines in certain cases.
 These include after semicolons and after the punctuation mark after an `end'."
-  :type 'boolean
-  :group 'pascal)
+  :type 'boolean)
 
 (defcustom pascal-indent-nested-functions t
   "Non-nil means nested functions are indented."
-  :type 'boolean
-  :group 'pascal)
+  :type 'boolean)
 
 (defcustom pascal-tab-always-indent t
   "Non-nil means TAB in Pascal mode should always reindent the current line.
 If this is nil, TAB inserts a tab if it is at the end of the line
 and follows non-whitespace text."
-  :type 'boolean
-  :group 'pascal)
+  :type 'boolean)
 
 (defcustom pascal-auto-endcomments t
   "Non-nil means automatically insert comments after certain `end's.
 Specifically, this is done after the ends of case statements and functions.
 The name of the function or case is included between the braces."
-  :type 'boolean
-  :group 'pascal)
+  :type 'boolean)
 
 (defcustom pascal-auto-lineup '(all)
   "List of contexts where auto lineup of :'s or ='s should be done.
@@ -243,8 +237,7 @@ will do all lineups."
              (const :tag "Everything" all)
              (const :tag "Parameter lists" paramlist)
              (const :tag "Declarations" declaration)
-             (const :tag "Case statements" case))
-  :group 'pascal)
+              (const :tag "Case statements" case)))
 
 (defvar pascal-toggle-completions nil
   "If non-nil, `pascal-complete-word' tries all possible completions.
@@ -260,8 +253,7 @@ completions.")
 These include integer, real, char, etc.
 The types defined within the Pascal program
 are handled in another way, and should not be added to this list."
-  :type '(repeat (string :tag "Keyword"))
-  :group 'pascal)
+  :type '(repeat (string :tag "Keyword")))
 
 (defcustom pascal-start-keywords
   '("begin" "end" "function" "procedure" "repeat" "until" "while"
@@ -270,8 +262,7 @@ are handled in another way, and should not be added to this 
list."
 These are keywords such as begin, repeat, until, readln.
 The procedures and variables defined within the Pascal program
 are handled in another way, and should not be added to this list."
-  :type '(repeat (string :tag "Keyword"))
-  :group 'pascal)
+  :type '(repeat (string :tag "Keyword")))
 
 (defcustom pascal-separator-keywords
   '("downto" "else" "mod" "div" "then")
@@ -279,8 +270,7 @@ are handled in another way, and should not be added to this 
list."
 These are keywords such as downto, else, mod, then.
 Variables and function names defined within the Pascal program
 are handled in another way, and should not be added to this list."
-  :type '(repeat (string :tag "Keyword"))
-  :group 'pascal)
+  :type '(repeat (string :tag "Keyword")))
 
 
 ;;;
diff --git a/lisp/progmodes/perl-mode.el b/lisp/progmodes/perl-mode.el
index 0120e4a..fd23683 100644
--- a/lisp/progmodes/perl-mode.el
+++ b/lisp/progmodes/perl-mode.el
@@ -98,8 +98,7 @@
 (defface perl-non-scalar-variable
   '((t :inherit font-lock-variable-name-face :underline t))
   "Face used for non-scalar variables."
-  :version "28.1"
-  :group 'perl)
+  :version "28.1")
 
 (defvar perl-mode-abbrev-table nil
   "Abbrev table in use in perl-mode buffers.")
@@ -171,9 +170,9 @@
     ;;  (1 font-lock-constant-face) (2 font-lock-variable-name-face nil t))
     ;;
     ;; Fontify function and package names in declarations.
-    ("\\<\\(package\\|sub\\)\\>[ \t]*\\(\\sw+\\)?"
+    ("\\<\\(package\\|sub\\)\\>[ \t]*\\(\\(?:\\sw\\|::\\)+\\)?"
      (1 font-lock-keyword-face) (2 font-lock-function-name-face nil t))
-    ("\\(^\\|[^$@%&\\]\\)\\<\\(import\\|no\\|require\\|use\\)\\>[ 
\t]*\\(\\sw+\\)?"
+    ("\\(?:^\\|[^$@%&\\]\\)\\<\\(import\\|no\\|require\\|use\\)\\>[ 
\t]*\\(\\(?:\\sw\\|::\\)+\\)?"
      (1 font-lock-keyword-face) (2 font-lock-constant-face nil t)))
   "Subdued level highlighting for Perl mode.")
 
@@ -188,7 +187,7 @@
               "\\>")
      ;;
      ;; Fontify declarators and prefixes as types.
-     ("\\<\\(has\\|local\\|my\\|our\\|state\\)\\>" . font-lock-type-face) ; 
declarators
+     ("\\<\\(has\\|local\\|my\\|our\\|state\\)\\>" . font-lock-keyword-face) ; 
declarators
           ;;
      ;; Fontify function, variable and file name references.
      ("&\\(\\sw+\\(::\\sw+\\)*\\)" 1 font-lock-function-name-face)
@@ -640,7 +639,6 @@ This is a non empty list of strings, the checker tool 
possibly
 followed by required arguments.  Once launched it will receive
 the Perl source to be checked as its standard input."
   :version "26.1"
-  :group 'perl
   :type '(repeat string))
 
 (defvar-local perl--flymake-proc nil)
diff --git a/lisp/progmodes/prog-mode.el b/lisp/progmodes/prog-mode.el
index d88d350..19de754 100644
--- a/lisp/progmodes/prog-mode.el
+++ b/lisp/progmodes/prog-mode.el
@@ -41,8 +41,7 @@
   :type 'hook
   :options '(flyspell-prog-mode abbrev-mode flymake-mode
                                 display-line-numbers-mode
-                                prettify-symbols-mode)
-  :group 'prog-mode)
+                                prettify-symbols-mode))
 
 (defvar prog-mode-map
   (let ((map (make-sparse-keymap)))
@@ -166,8 +165,7 @@ on the symbol."
   :version "25.1"
   :type '(choice (const :tag "Never unprettify" nil)
                  (const :tag "Unprettify when point is inside" t)
-                 (const :tag "Unprettify when point is inside or at right 
edge" right-edge))
-  :group 'prog-mode)
+                 (const :tag "Unprettify when point is inside or at right 
edge" right-edge)))
 
 (defun prettify-symbols--post-command-hook ()
   (cl-labels ((get-prop-as-list
diff --git a/lisp/progmodes/project.el b/lisp/progmodes/project.el
index 944b886..8ae30f5 100644
--- a/lisp/progmodes/project.el
+++ b/lisp/progmodes/project.el
@@ -106,7 +106,7 @@
 ;;
 ;; - Write a new function that will determine the current project
 ;; based on the directory and add it to `project-find-functions'
-;; (which see) using `add-hook'. It is a good idea to depend on the
+;; (which see) using `add-hook'.  It is a good idea to depend on the
 ;; directory only, and not on the current major mode, for example.
 ;; Because the usual expectation is that all files in the directory
 ;; belong to the same project (even if some/most of them are ignored).
@@ -201,20 +201,27 @@ of the project instance object."
     (when maybe-prompt
       (if pr
           (project-remember-project pr)
-        (project--remove-from-project-list directory)
+        (project--remove-from-project-list
+         directory "Project `%s' not found; removed from list")
         (setq pr (cons 'transient directory))))
     pr))
 
 (defun project--find-in-directory (dir)
   (run-hook-with-args-until-success 'project-find-functions dir))
 
+(defvar project--within-roots-fallback nil)
+
 (cl-defgeneric project-root (project)
   "Return root directory of the current project.
 
 It usually contains the main build file, dependencies
 configuration file, etc. Though neither is mandatory.
 
-The directory name must be absolute."
+The directory name must be absolute.")
+
+(cl-defmethod project-root (project
+                            &context (project--within-roots-fallback
+                                      (eql nil)))
   (car (project-roots project)))
 
 (cl-defgeneric project-roots (project)
@@ -226,7 +233,8 @@ and the rest should be possible to express through
   ;; FIXME: Can we specify project's version here?
   ;; FIXME: Could we make this affect cl-defmethod calls too?
   (declare (obsolete project-root "0.3.0"))
-  (list (project-root project)))
+  (let ((project--within-roots-fallback t))
+    (list (project-root project))))
 
 ;; FIXME: Add MODE argument, like in `ede-source-paths'?
 (cl-defgeneric project-external-roots (_project)
@@ -803,9 +811,12 @@ pattern to search for."
       (user-error "No matches for: %s" regexp))
     xrefs))
 
+(defvar project-regexp-history-variable 'grep-regexp-history)
+
 (defun project--read-regexp ()
-  (let ((sym (thing-at-point 'symbol)))
-    (read-regexp "Find regexp" (and sym (regexp-quote sym)))))
+  (let ((sym (thing-at-point 'symbol t)))
+    (read-regexp "Find regexp" (and sym (regexp-quote sym))
+                 project-regexp-history-variable)))
 
 ;;;###autoload
 (defun project-find-file ()
@@ -933,7 +944,7 @@ if one already exists."
                    "-shell*"))
          (shell-buffer (get-buffer default-project-shell-name)))
     (if (and shell-buffer (not current-prefix-arg))
-        (pop-to-buffer shell-buffer)
+        (pop-to-buffer-same-window shell-buffer)
       (shell (generate-new-buffer-name default-project-shell-name)))))
 
 ;;;###autoload
@@ -953,7 +964,7 @@ if one already exists."
                   "-eshell*"))
          (eshell-buffer (get-buffer eshell-buffer-name)))
     (if (and eshell-buffer (not current-prefix-arg))
-        (pop-to-buffer eshell-buffer)
+        (pop-to-buffer-same-window eshell-buffer)
       (eshell t))))
 
 ;;;###autoload
@@ -1239,17 +1250,27 @@ Save the result in `project-list-file' if the list of 
projects has changed."
       (push (list dir) project--list)
       (project--write-project-list))))
 
-(defun project--remove-from-project-list (pr-dir)
-  "Remove directory PR-DIR of a missing project from the project list.
+(defun project--remove-from-project-list (project-root report-message)
+  "Remove directory PROJECT-ROOT of a missing project from the project list.
 If the directory was in the list before the removal, save the
 result in `project-list-file'.  Announce the project's removal
-from the list."
+from the list using REPORT-MESSAGE, which is a format string
+passed to `message' as its first argument."
   (project--ensure-read-project-list)
-  (when-let ((ent (assoc pr-dir project--list)))
+  (when-let ((ent (assoc project-root project--list)))
     (setq project--list (delq ent project--list))
-    (message "Project `%s' not found; removed from list" pr-dir)
+    (message report-message project-root)
     (project--write-project-list)))
 
+;;;###autoload
+(defun project-remove-known-project (project-root)
+  "Remove directory PROJECT-ROOT from the project list.
+PROJECT-ROOT is the root directory of a known project listed in
+the project list."
+  (interactive (list (project-prompt-project-dir)))
+  (project--remove-from-project-list
+   project-root "Project `%s' removed from known projects"))
+
 (defun project-prompt-project-dir ()
   "Prompt the user for a directory that is one of the known project roots.
 The project is chosen among projects known from the project list,
@@ -1284,7 +1305,6 @@ It's also possible to enter an arbitrary directory not in 
the list."
 
 ;;; Project switching
 
-;;;###autoload
 (defcustom project-switch-commands
   '((project-find-file "Find file")
     (project-find-regexp "Find regexp")
diff --git a/lisp/progmodes/prolog.el b/lisp/progmodes/prolog.el
index 9f5f9ed..29cce51 100644
--- a/lisp/progmodes/prolog.el
+++ b/lisp/progmodes/prolog.el
@@ -267,7 +267,6 @@
   (require 'shell)
   )
 
-(require 'easymenu)
 (require 'align)
 
 (defgroup prolog nil
diff --git a/lisp/progmodes/ps-mode.el b/lisp/progmodes/ps-mode.el
index 15fd2e8..598f748 100644
--- a/lisp/progmodes/ps-mode.el
+++ b/lisp/progmodes/ps-mode.el
@@ -39,7 +39,6 @@
   "Peter Kleiweg <p.c.j.kleiweg@rug.nl>, bug-gnu-emacs@gnu.org")
 
 (require 'comint)
-(require 'easymenu)
 (require 'smie)
 
 ;; Define core `PostScript' group.
diff --git a/lisp/progmodes/ruby-mode.el b/lisp/progmodes/ruby-mode.el
index e7f407b..84ac8fd 100644
--- a/lisp/progmodes/ruby-mode.el
+++ b/lisp/progmodes/ruby-mode.el
@@ -331,7 +331,7 @@ It is used when `ruby-encoding-magic-comment-style' is set 
to `custom'."
 (require 'smie)
 
 ;; Here's a simplified BNF grammar, for reference:
-;; http://www.cse.buffalo.edu/~regan/cse305/RubyBNF.pdf
+;; https://www.cse.buffalo.edu/~regan/cse305/RubyBNF.pdf
 (defconst ruby-smie-grammar
   (smie-prec2->grammar
    (smie-merge-prec2s
@@ -1802,12 +1802,12 @@ FEATURE-NAME is a relative file name, file extension is 
optional.
 This commands delegates to `gem which', which searches both
 installed gems and the standard library.  When called
 interactively, defaults to the feature name in the `require'
-statement around point."
+or `gem' statement around point."
   (interactive)
   (unless feature-name
     (let ((init (save-excursion
                   (forward-line 0)
-                  (when (looking-at "require [\"']\\(.*\\)[\"']")
+                  (when (looking-at "\\(?:require\\| *gem\\) 
[\"']\\(.*?\\)[\"']")
                     (match-string 1)))))
       (setq feature-name (read-string "Feature name: " init))))
   (let ((out
diff --git a/lisp/progmodes/scheme.el b/lisp/progmodes/scheme.el
index f610efb..b697284 100644
--- a/lisp/progmodes/scheme.el
+++ b/lisp/progmodes/scheme.el
@@ -28,7 +28,7 @@
 ;; the Lisp mode documented in the Emacs manual.  `dsssl-mode' is a
 ;; variant of scheme-mode for editing DSSSL specifications for SGML
 ;; documents.  [As of Apr 1997, some pointers for DSSSL may be found,
-;; for instance, at <URL:http://www.sil.org/sgml/related.html#dsssl>.]
+;; for instance, at <URL:https://www.sil.org/sgml/related.html#dsssl>.]
 ;; All these Lisp-ish modes vary basically in details of the language
 ;; syntax they highlight/indent/index, but dsssl-mode uses "^;;;" as
 ;; the page-delimiter since ^L isn't normally a valid SGML character.
@@ -162,25 +162,26 @@
 (defvar scheme-mode-line-process "")
 
 (defvar scheme-mode-map
-  (let ((smap (make-sparse-keymap))
-        (map (make-sparse-keymap "Scheme")))
-    (set-keymap-parent smap lisp-mode-shared-map)
-    (define-key smap [menu-bar scheme] (cons "Scheme" map))
-    (define-key map [run-scheme] '("Run Inferior Scheme" . run-scheme))
-    (define-key map [uncomment-region]
-      '("Uncomment Out Region" . (lambda (beg end)
-                                   (interactive "r")
-                                   (comment-region beg end '(4)))))
-    (define-key map [comment-region] '("Comment Out Region" . comment-region))
-    (define-key map [indent-region] '("Indent Region" . indent-region))
-    (define-key map [indent-line] '("Indent Line" . lisp-indent-line))
-    (put 'comment-region 'menu-enable 'mark-active)
-    (put 'uncomment-region 'menu-enable 'mark-active)
-    (put 'indent-region 'menu-enable 'mark-active)
-    smap)
+  (let ((map (make-sparse-keymap)))
+    (set-keymap-parent map lisp-mode-shared-map)
+    map)
   "Keymap for Scheme mode.
 All commands in `lisp-mode-shared-map' are inherited by this map.")
 
+(easy-menu-define scheme-mode-menu scheme-mode-map
+  "Menu for Scheme mode."
+  '("Scheme"
+    ["Indent Line" lisp-indent-line]
+    ["Indent Region" indent-region
+     :enable mark-active]
+    ["Comment Out Region" comment-region
+     :enable mark-active]
+    ["Uncomment Out Region" (lambda (beg end)
+                                (interactive "r")
+                                (comment-region beg end '(4)))
+     :enable mark-active]
+    ["Run Inferior Scheme" run-scheme]))
+
 ;; Used by cmuscheme
 (defun scheme-mode-commands (map)
   ;;(define-key map "\t" 'indent-for-tab-command) ; default
@@ -215,8 +216,7 @@ Blank lines separate paragraphs.  Semicolons start comments.
 (defcustom scheme-mit-dialect t
   "If non-nil, scheme mode is specialized for MIT Scheme.
 Set this to nil if you normally use another dialect."
-  :type 'boolean
-  :group 'scheme)
+  :type 'boolean)
 
 (defcustom dsssl-sgml-declaration
   "<!DOCTYPE style-sheet PUBLIC \"-//James Clark//DTD DSSSL Style Sheet//EN\">
@@ -226,26 +226,22 @@ If it is defined as a string this will be inserted into 
an empty buffer
 which is in `dsssl-mode'.  It is typically James Clark's style-sheet
 doctype, as required for Jade."
   :type '(choice (string :tag "Specified string")
-                 (const :tag "None" :value nil))
-  :group 'scheme)
+                 (const :tag "None" :value nil)))
 
 (defcustom scheme-mode-hook nil
   "Normal hook run when entering `scheme-mode'.
 See `run-hooks'."
-  :type 'hook
-  :group 'scheme)
+  :type 'hook)
 
 (defcustom dsssl-mode-hook nil
   "Normal hook run when entering `dsssl-mode'.
 See `run-hooks'."
-  :type 'hook
-  :group 'scheme)
+  :type 'hook)
 
 ;; This is shared by cmuscheme and xscheme.
 (defcustom scheme-program-name "scheme"
   "Program invoked by the `run-scheme' command."
-  :type 'string
-  :group 'scheme)
+  :type 'string)
 
 (defvar dsssl-imenu-generic-expression
   ;; Perhaps this should also look for the style-sheet DTD tags.  I'm
@@ -429,12 +425,10 @@ that variable's value is a string."
            '(1 font-lock-keyword-face)
            '(4 font-lock-function-name-face))
      (cons
-      (concat "(\\("
-              ;; (make-regexp '("case" "cond" "else" "if" "lambda"
-              ;; "let" "let*" "letrec" "and" "or" "map" "with-mode"))
-              "and\\|c\\(ase\\|ond\\)\\|else\\|if\\|"
-              "l\\(ambda\\|et\\(\\|\\*\\|rec\\)\\)\\|map\\|or\\|with-mode"
-              "\\)\\>")
+      (concat "(" (regexp-opt
+                   '("case" "cond" "else" "if" "lambda"
+                     "let" "let*" "letrec" "and" "or" "map" "with-mode")
+                   'words))
       1)
      ;; DSSSL syntax
      '("(\\(element\\|mode\\|declare-\\w+\\)\\>[ \t]*\\(\\sw+\\)"
diff --git a/lisp/progmodes/sh-script.el b/lisp/progmodes/sh-script.el
index f588ad9..ba59f9c 100644
--- a/lisp/progmodes/sh-script.el
+++ b/lisp/progmodes/sh-script.el
@@ -403,8 +403,7 @@ This is buffer-local in every such buffer.")
   "Syntax-table used in Shell-Script mode.  See `sh-feature'.")
 
 (defvar sh-mode-map
-  (let ((map (make-sparse-keymap))
-       (menu-map (make-sparse-keymap)))
+  (let ((map (make-sparse-keymap)))
     (define-key map "\C-c(" 'sh-function)
     (define-key map "\C-c\C-w" 'sh-while)
     (define-key map "\C-c\C-u" 'sh-until)
@@ -434,74 +433,57 @@ This is buffer-local in every such buffer.")
     (define-key map "\C-c:" 'sh-set-shell)
     (define-key map [remap backward-sentence] 'sh-beginning-of-command)
     (define-key map [remap forward-sentence] 'sh-end-of-command)
-    (define-key map [menu-bar sh-script] (cons "Sh-Script" menu-map))
-    (define-key menu-map [smie-config-guess]
-      '(menu-item "Learn buffer indentation" smie-config-guess
-        :help "Learn how to indent the buffer the way it currently is."))
-    (define-key menu-map [smie-config-show-indent]
-      '(menu-item "Show indentation" smie-config-show-indent
-                 :help "Show the how the current line would be indented"))
-    (define-key menu-map [smie-config-set-indent]
-      '(menu-item "Set indentation" smie-config-set-indent
-                 :help "Set the indentation for the current line"))
-
-    (define-key menu-map [sh-pair]
-      '(menu-item "Insert braces and quotes in pairs"
-        electric-pair-mode
-        :button (:toggle . (bound-and-true-p electric-pair-mode))
-        :help "Inserting a brace or quote automatically inserts the matching 
pair"))
-
-    (define-key menu-map [sh-s0] '("--"))
-    ;; Insert
-    (define-key menu-map [sh-function]
-      '(menu-item "Function..." sh-function
-                 :help "Insert a function definition"))
-    (define-key menu-map [sh-add]
-      '(menu-item "Addition..." sh-add
-        :help "Insert an addition of VAR and prefix DELTA for Bourne (type) 
shell"))
-    (define-key menu-map [sh-until]
-      '(menu-item "Until Loop" sh-until
-                 :help "Insert an until loop"))
-    (define-key menu-map [sh-repeat]
-      '(menu-item "Repeat Loop" sh-repeat
-                 :help "Insert a repeat loop definition"))
-    (define-key menu-map [sh-while]
-      '(menu-item "While Loop" sh-while
-                 :help "Insert a while loop"))
-    (define-key menu-map [sh-getopts]
-      '(menu-item "Options Loop" sh-while-getopts
-                 :help "Insert a while getopts loop."))
-    (define-key menu-map [sh-indexed-loop]
-      '(menu-item "Indexed Loop" sh-indexed-loop
-                 :help "Insert an indexed loop from 1 to n."))
-    (define-key menu-map [sh-select]
-      '(menu-item "Select Statement" sh-select
-                 :help "Insert a select statement "))
-    (define-key menu-map [sh-if]
-      '(menu-item "If Statement" sh-if
-                 :help "Insert an if statement"))
-    (define-key menu-map [sh-for]
-      '(menu-item "For Loop" sh-for
-                 :help "Insert a for loop"))
-    (define-key menu-map [sh-case]
-      '(menu-item "Case Statement" sh-case
-                 :help "Insert a case/switch statement"))
-    (define-key menu-map [sh-s1] '("--"))
-    (define-key menu-map [sh-exec]
-      '(menu-item "Execute region" sh-execute-region
-        :help "Pass optional header and region to a subshell for 
noninteractive execution"))
-    (define-key menu-map [sh-exec-interpret]
-      '(menu-item "Execute script..." executable-interpret
-        :help "Run script with user-specified args, and collect output in a 
buffer"))
-    (define-key menu-map [sh-set-shell]
-      '(menu-item "Set shell type..." sh-set-shell
-                 :help "Set this buffer's shell to SHELL (a string)"))
-    (define-key menu-map [sh-backslash-region]
-      '(menu-item "Backslash region" sh-backslash-region
-        :help "Insert, align, or delete end-of-line backslashes on the lines 
in the region."))
     map)
   "Keymap used in Shell-Script mode.")
 
+(easy-menu-define sh-mode-menu sh-mode-map
+  "Menu for Shell-Script mode."
+  '("Sh-Script"
+    ["Backslash region" sh-backslash-region
+     :help "Insert, align, or delete end-of-line backslashes on the lines in 
the region."]
+    ["Set shell type..." sh-set-shell
+     :help "Set this buffer's shell to SHELL (a string)"]
+    ["Execute script..." executable-interpret
+     :help "Run script with user-specified args, and collect output in a 
buffer"]
+    ["Execute region" sh-execute-region
+     :help "Pass optional header and region to a subshell for noninteractive 
execution"]
+    "---"
+    ;; Insert
+    ["Case Statement" sh-case
+     :help "Insert a case/switch statement"]
+    ["For Loop" sh-for
+     :help "Insert a for loop"]
+    ["If Statement" sh-if
+     :help "Insert an if statement"]
+    ["Select Statement" sh-select
+     :help "Insert a select statement "]
+    ["Indexed Loop" sh-indexed-loop
+     :help "Insert an indexed loop from 1 to n."]
+    ["Options Loop" sh-while-getopts
+     :help "Insert a while getopts loop."]
+    ["While Loop" sh-while
+     :help "Insert a while loop"]
+    ["Repeat Loop" sh-repeat
+     :help "Insert a repeat loop definition"]
+    ["Until Loop" sh-until
+     :help "Insert an until loop"]
+    ["Addition..." sh-add
+     :help "Insert an addition of VAR and prefix DELTA for Bourne (type) 
shell"]
+    ["Function..." sh-function
+     :help "Insert a function definition"]
+    "---"
+    ;; Other
+    ["Insert braces and quotes in pairs" electric-pair-mode
+     :style toggle
+     :selected (bound-and-true-p electric-pair-mode)
+     :help "Inserting a brace or quote automatically inserts the matching 
pair"]
+    ["Set indentation" smie-config-set-indent
+     :help "Set the indentation for the current line"]
+    ["Show indentation" smie-config-show-indent
+     :help "Show the how the current line would be indented"]
+    ["Learn buffer indentation" smie-config-guess
+     :help "Learn how to indent the buffer the way it currently is."]))
+
 (defvar sh-skeleton-pair-default-alist '((?\( _ ?\)) (?\))
                                      (?\[ ?\s _ ?\s ?\]) (?\])
                                      (?{ _ ?}) (?\}))
diff --git a/lisp/progmodes/simula.el b/lisp/progmodes/simula.el
index a863e7e..f92f446 100644
--- a/lisp/progmodes/simula.el
+++ b/lisp/progmodes/simula.el
@@ -51,16 +51,14 @@ the run of whitespace at the beginning of the line.")
   "Non-nil means TAB in SIMULA mode should always reindent the current line.
 Otherwise TAB indents only when point is within
 the run of whitespace at the beginning of the line."
-  :type 'boolean
-  :group 'simula)
+  :type 'boolean)
 
 (defconst simula-indent-level-default 3
   "Indentation of SIMULA statements with respect to containing block.")
 
 (defcustom simula-indent-level simula-indent-level-default
   "Indentation of SIMULA statements with respect to containing block."
-  :type 'integer
-  :group 'simula)
+  :type 'integer)
 
 
 (defconst simula-substatement-offset-default 3
@@ -68,8 +66,7 @@ the run of whitespace at the beginning of the line."
 
 (defcustom simula-substatement-offset simula-substatement-offset-default
   "Extra indentation after DO, THEN, ELSE, WHEN and OTHERWISE."
-  :type 'integer
-  :group 'simula)
+  :type 'integer)
 
 (defconst simula-continued-statement-offset-default 3
   "Extra indentation for lines not starting a statement or substatement.
@@ -83,16 +80,14 @@ the previous line of the statement.")
 If value is a list, each line in a multipleline continued statement
 will have the car of the list extra indentation with respect to
 the previous line of the statement."
-  :type 'integer
-  :group 'simula)
+  :type 'integer)
 
 (defconst simula-label-offset-default -4711
   "Offset of SIMULA label lines relative to usual indentation.")
 
 (defcustom simula-label-offset simula-label-offset-default
   "Offset of SIMULA label lines relative to usual indentation."
-  :type 'integer
-  :group 'simula)
+  :type 'integer)
 
 (defconst simula-if-indent-default '(0 . 0)
   "Extra indentation of THEN and ELSE with respect to the starting IF.
@@ -103,8 +98,7 @@ extra ELSE indentation.  IF after ELSE is indented as the 
starting IF.")
   "Extra indentation of THEN and ELSE with respect to the starting IF.
 Value is a cons cell, the car is extra THEN indentation and the cdr
 extra ELSE indentation.  IF after ELSE is indented as the starting IF."
-  :type '(cons integer integer)
-  :group 'simula)
+  :type '(cons integer integer))
 
 (defconst simula-inspect-indent-default '(0 . 0)
   "Extra indentation of WHEN and OTHERWISE with respect to the INSPECT.
@@ -115,16 +109,14 @@ and the cdr extra OTHERWISE indentation.")
   "Extra indentation of WHEN and OTHERWISE with respect to the INSPECT.
 Value is a cons cell, the car is extra WHEN indentation
 and the cdr extra OTHERWISE indentation."
-  :type '(cons integer integer)
-  :group 'simula)
+  :type '(cons integer integer))
 
 (defconst simula-electric-indent-default nil
   "Non-nil means `simula-indent-line' function may reindent previous line.")
 
 (defcustom simula-electric-indent simula-electric-indent-default
   "Non-nil means `simula-indent-line' function may reindent previous line."
-  :type 'boolean
-  :group 'simula)
+  :type 'boolean)
 
 (defconst simula-abbrev-keyword-default 'upcase
   "Specify how to convert case for SIMULA keywords.
@@ -135,8 +127,7 @@ Value is one of the symbols `upcase', `downcase', 
`capitalize',
   "Specify how to convert case for SIMULA keywords.
 Value is one of the symbols `upcase', `downcase', `capitalize',
 \(as in) `abbrev-table' or nil if they should not be changed."
-  :type '(choice (const upcase) (const downcase) (const capitalize)(const nil))
-  :group 'simula)
+  :type '(choice (const upcase) (const downcase) (const capitalize)(const 
nil)))
 
 (defconst simula-abbrev-stdproc-default 'abbrev-table
   "Specify how to convert case for standard SIMULA procedure and class names.
@@ -148,16 +139,14 @@ Value is one of the symbols `upcase', `downcase', 
`capitalize',
 Value is one of the symbols `upcase', `downcase', `capitalize',
 \(as in) `abbrev-table', or nil if they should not be changed."
   :type '(choice (const upcase) (const downcase) (const capitalize)
-         (const abbrev-table) (const nil))
-  :group 'simula)
+          (const abbrev-table) (const nil)))
 
 (defcustom simula-abbrev-file nil
   "File with extra abbrev definitions for use in SIMULA mode.
 These are used together with the standard abbrev definitions for SIMULA.
 Please note that the standard definitions are required
 for SIMULA mode to function correctly."
-  :type '(choice file (const nil))
-  :group 'simula)
+  :type '(choice file (const nil)))
 
 (defvar simula-mode-syntax-table nil
   "Syntax table in SIMULA mode buffers.")
@@ -281,48 +270,25 @@ for SIMULA mode to function correctly."
     (define-key map ":"          'simula-electric-label)
     (define-key map "\e\C-q"     'simula-indent-exp)
     (define-key map "\t"         'simula-indent-command)
-
-    (define-key map [menu-bar simula]
-      (cons "SIMULA" (make-sparse-keymap "SIMULA")))
-    (define-key map [menu-bar simula indent-exp]
-      '("Indent Expression" . simula-indent-exp))
-    (define-key map [menu-bar simula indent-line]
-      '("Indent Line" . simula-indent-command))
-    (define-key map [menu-bar simula separator-navigate]
-      '("--"))
-    (define-key map [menu-bar simula backward-stmt]
-      '("Previous Statement" . simula-previous-statement))
-    (define-key map [menu-bar simula forward-stmt]
-      '("Next Statement" . simula-next-statement))
-    (define-key map [menu-bar simula backward-up]
-      '("Backward Up Level" . simula-backward-up-level))
-    (define-key map [menu-bar simula forward-down]
-      '("Forward Down Statement" . simula-forward-down-level))
-
-    (put 'simula-next-statement 'menu-enable '(not (eobp)))
-    (put 'simula-previous-statement 'menu-enable '(not (bobp)))
-    (put 'simula-forward-down-level 'menu-enable '(not (eobp)))
-    (put 'simula-backward-up-level 'menu-enable '(not (bobp)))
-    (put 'simula-indent-command 'menu-enable '(not buffer-read-only))
-    (put 'simula-indent-exp 'menu-enable '(not buffer-read-only))
-
-    ;; RMS: mouse-3 should not select this menu.  mouse-3's global
-    ;; definition is useful in SIMULA mode and we should not interfere
-    ;; with that.  The menu is mainly for beginners, and for them,
-    ;; the menubar requires less memory than a special click.
-    ;; in Lucid Emacs, we want the menu to popup when the 3rd button is
-    ;; hit.  In 19.10 and beyond this is done automatically if we put
-    ;; the menu on mode-popup-menu variable, see c-common-init [cc-mode.el]
-    ;;(if (not (boundp 'mode-popup-menu))
-    ;; (define-key simula-mode-map 'button3 'simula-popup-menu))
     map)
   "Keymap used in `simula-mode'.")
 
-;; menus for Lucid
-(defun simula-popup-menu (_e)
-  "Pops up the SIMULA menu."
-  (interactive "@e")
-  (popup-menu (cons (concat mode-name " Mode Commands") simula-mode-menu)))
+(easy-menu-define simula-mode-menu simula-mode-map
+  "Menu for `simula-mode'."
+  '("SIMULA"
+    ["Forward Down Statement" simula-forward-down-level
+     :enable (not (eobp))]
+    ["Backward Up Level" simula-backward-up-level
+     :enable (not (bobp))]
+    ["Next Statement" simula-next-statement
+     :enable (not (eobp))]
+    ["Previous Statement" simula-previous-statement
+     :enable (not (bobp))]
+    "---"
+    ["Indent Line" simula-indent-command
+     :enable (not buffer-read-only)]
+    ["Indent Expression" simula-indent-exp
+     :enable (not buffer-read-only)]))
 
 ;;;###autoload
 (define-derived-mode simula-mode prog-mode "Simula"
@@ -1607,11 +1573,23 @@ If not nil and not t, move to limit of search and 
return nil."
        ("^%\\([ \t\f].*\\)?$" nil comment)
        ("^%include\\>" nil include)
        ("\"[^\"\n]*\"\\|'.'\\|'![0-9]+!'" nil string)
-       
("\\<\\(ACTIVATE\\|AFTER\\|AND\\|ARRAY\\|AT\\|BEFORE\\|BEGIN\\|BOOLEAN\\|CHARACTER\\|CLASS\\|DELAY\\|DO\\|ELSE\\|END\\|EQ\\|EQV\\|EXTERNAL\\|FALSE\\|FOR\\|GE\\|GO\\|GOTO\\|GT\\|HIDDEN\\|IF\\|IMP\\|IN\\|INNER\\|INSPECT\\|INTEGER\\|IS\\|LABEL\\|LE\\|LONG\\|LT\\|NAME\\|NE\\|NEW\\|NONE\\|NOT\\|NOTEXT\\|OR\\|OTHERWISE\\|PRIOR\\|PROCEDURE\\|PROTECTED\\|QUA\\|REACTIVATE\\|REAL\\|REF\\|SHORT\\|STEP\\|SWITCH\\|TEXT\\|THEN\\|THIS\\|TO\\|TRUE\\|UNTIL\\|VALUE\\|VIRTUAL\\|WHEN\\|WHILE\\)\\>"
 n [...]
+       ((regexp-opt '("ACTIVATE" "AFTER" "AND" "ARRAY" "AT" "BEFORE"
+                      "BEGIN" "BOOLEAN" "CHARACTER" "CLASS" "DELAY"
+                      "DO" "ELSE" "END" "EQ" "EQV" "EXTERNAL" "FALSE"
+                      "FOR" "GE" "GO" "GOTO" "GT" "HIDDEN" "IF" "IMP"
+                      "IN" "INNER" "INSPECT" "INTEGER" "IS" "LABEL"
+                      "LE" "LONG" "LT" "NAME" "NE" "NEW" "NONE" "NOT"
+                      "NOTEXT" "OR" "OTHERWISE" "PRIOR" "PROCEDURE"
+                      "PROTECTED" "QUA" "REACTIVATE" "REAL" "REF"
+                      "SHORT" "STEP" "SWITCH" "TEXT" "THEN" "THIS"
+                      "TO" "TRUE" "UNTIL" "VALUE" "VIRTUAL" "WHEN"
+                      "WHILE")
+                    'words)
+        nil keyword)
        ("!\\|\\<COMMENT\\>" ";" comment))
      nil 'case-insensitive)))
 
-;; defuns for submitting bug reports
+;; obsolete
 
 (defconst simula-mode-help-address "bug-gnu-emacs@gnu.org"
   "Address accepting submission of `simula-mode' bug reports.")
@@ -1622,6 +1600,12 @@ If not nil and not t, move to limit of search and return 
nil."
 (define-obsolete-function-alias 'simula-submit-bug-report
   'report-emacs-bug "24.4")
 
+(defun simula-popup-menu (_e)
+  "Pops up the SIMULA menu."
+  (declare (obsolete simula-mode-menu "28.1"))
+  (interactive "@e")
+  (popup-menu (cons (concat mode-name " Mode Commands") simula-mode-menu)))
+
 (provide 'simula)
 
 ;;; simula.el ends here
diff --git a/lisp/progmodes/sql.el b/lisp/progmodes/sql.el
index f1f4d61..6224b3b 100644
--- a/lisp/progmodes/sql.el
+++ b/lisp/progmodes/sql.el
@@ -2992,7 +2992,7 @@ displayed."
 ;; (defconst sql-smie-grammar
 ;;   (smie-prec2->grammar
 ;;    (smie-bnf->prec2
-;;     ;; Partly based on http://www.h2database.com/html/grammar.html
+;;     ;; Partly based on https://www.h2database.com/html/grammar.html
 ;;     '((cmd ("SELECT" select-exp "FROM" select-table-exp)
 ;;            )
 ;;       (select-exp ("*") (exp) (exp "AS" column-alias))
diff --git a/lisp/progmodes/tcl.el b/lisp/progmodes/tcl.el
index 82e1343..f6a50bf 100644
--- a/lisp/progmodes/tcl.el
+++ b/lisp/progmodes/tcl.el
@@ -1413,7 +1413,7 @@ Prefix argument means switch to the Tcl buffer 
afterwards."
    (list
     ;; car because comint-get-source returns a list holding the
     ;; filename.
-    (car (comint-get-source "Load Tcl file: "
+    (car (comint-get-source "Load Tcl file"
                            (or (and
                                 (derived-mode-p 'tcl-mode)
                                 (buffer-file-name))
@@ -1433,7 +1433,7 @@ If an inferior Tcl process exists, it is killed first.
 Prefix argument means switch to the Tcl buffer afterwards."
   (interactive
    (list
-    (car (comint-get-source "Restart with Tcl file: "
+    (car (comint-get-source "Restart with Tcl file"
                            (or (and
                                 (derived-mode-p 'tcl-mode)
                                 (buffer-file-name))
diff --git a/lisp/progmodes/vera-mode.el b/lisp/progmodes/vera-mode.el
index c2e1719..4622256 100644
--- a/lisp/progmodes/vera-mode.el
+++ b/lisp/progmodes/vera-mode.el
@@ -5,7 +5,7 @@
 ;; Author:      Reto Zimmermann <reto@gnu.org>
 ;; Version:     2.28
 ;; Keywords:    languages vera
-;; WWW:         http://www.iis.ee.ethz.ch/~zimmi/emacs/vera-mode.html
+;; WWW:         https://guest.iis.ee.ethz.ch/~zimmi/emacs/vera-mode.html
 
 ;; Yoni Rabkin <yoni@rabkins.net> contacted the maintainer of this
 ;; file on 18/3/2008, and the maintainer agreed that when a bug is
@@ -119,8 +119,6 @@ If nil, TAB always indents current line."
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;; Menu
 
-(require 'easymenu)
-
 (easy-menu-define vera-mode-menu vera-mode-map
   "Menu keymap for Vera Mode."
   '("Vera"
@@ -251,7 +249,7 @@ Add a description of the problem and include a reproducible 
test case.
 Feel free to send questions and enhancement requests to <reto@gnu.org>.
 
 Official distribution is at
-URL `http://www.iis.ee.ethz.ch/~zimmi/emacs/vera-mode.html'
+URL `https://www.iis.ee.ethz.ch/~zimmi/emacs/vera-mode.html'
 
 
                                                   The Vera Mode Maintainer
diff --git a/lisp/progmodes/verilog-mode.el b/lisp/progmodes/verilog-mode.el
index f934ef7..8ba3483 100644
--- a/lisp/progmodes/verilog-mode.el
+++ b/lisp/progmodes/verilog-mode.el
@@ -9,7 +9,7 @@
 ;; Keywords: languages
 ;; The "Version" is the date followed by the decimal rendition of the Git
 ;;     commit hex.
-;; Version: 2021.02.02.263931197
+;; Version: 2021.03.29.215531170
 
 ;; Yoni Rabkin <yoni@rabkins.net> contacted the maintainer of this
 ;; file on 19/3/2008, and the maintainer agreed that when a bug is
@@ -124,7 +124,7 @@
 ;;
 
 ;; This variable will always hold the version number of the mode
-(defconst verilog-mode-version "2021-02-02-fbb453d-vpo-GNU"
+(defconst verilog-mode-version "2021-03-29-cd8bea2-vpo-GNU"
   "Version of this Verilog mode.")
 (defconst verilog-mode-release-emacs t
   "If non-nil, this version of Verilog mode was released with Emacs itself.")
@@ -134,7 +134,7 @@
   (interactive)
   (message "Using verilog-mode version %s" verilog-mode-version))
 
-(defmacro verilog--supressed-warnings (warnings &rest body)
+(defmacro verilog--suppressed-warnings (warnings &rest body)
   (declare (indent 1) (debug t))
   (cond
    ((fboundp 'with-suppressed-warnings)
@@ -290,7 +290,7 @@ STRING should be given if the last search was by 
`string-match' on STRING."
             (concat open (mapconcat 'regexp-quote strings "\\|") close)))
         )
     ;; Emacs.
-    (defalias 'verilog-regexp-opt 'regexp-opt)))
+    (defalias 'verilog-regexp-opt #'regexp-opt)))
 
 ;; emacs >=22 has looking-back, but older emacs and xemacs don't.
 ;; This function is lifted directly from emacs's subr.el
@@ -300,7 +300,7 @@ STRING should be given if the last search was by 
`string-match' on STRING."
 (eval-and-compile
   (cond
    ((fboundp 'looking-back)
-    (defalias 'verilog-looking-back 'looking-back))
+    (defalias 'verilog-looking-back #'looking-back))
    (t
     (defun verilog-looking-back (regexp limit &optional greedy)
       "Return non-nil if text before point matches regular expression REGEXP.
@@ -340,14 +340,14 @@ wherever possible, since it is slow."
   (cond
    ((fboundp 'restore-buffer-modified-p)
     ;; Faster, as does not update mode line when nothing changes
-    (defalias 'verilog-restore-buffer-modified-p 'restore-buffer-modified-p))
+    (defalias 'verilog-restore-buffer-modified-p #'restore-buffer-modified-p))
    (t
-    (defalias 'verilog-restore-buffer-modified-p 'set-buffer-modified-p))))
+    (defalias 'verilog-restore-buffer-modified-p #'set-buffer-modified-p))))
 
 (eval-and-compile
   (cond
    ((fboundp 'quit-window)
-    (defalias 'verilog-quit-window 'quit-window))
+    (defalias 'verilog-quit-window #'quit-window))
    (t
     (defun verilog-quit-window (_kill-ignored window)
       "Quit WINDOW and bury its buffer. KILL-IGNORED is ignored."
@@ -379,7 +379,7 @@ wherever possible, since it is slow."
   ;; Added in Emacs 25.1
   (condition-case nil
       (unless (fboundp 'forward-word-strictly)
-        (defalias 'forward-word-strictly 'forward-word))
+        (defalias 'forward-word-strictly #'forward-word))
     (error nil)))
 
 (eval-when-compile
@@ -1483,48 +1483,48 @@ If set will become buffer local.")
 
 (defvar verilog-mode-map
   (let ((map (make-sparse-keymap)))
-    (define-key map ";"        'electric-verilog-semi)
-    (define-key map [(control 59)]    'electric-verilog-semi-with-comment)
-    (define-key map ":"        'electric-verilog-colon)
+    (define-key map ";"        #'electric-verilog-semi)
+    (define-key map [(control 59)]    #'electric-verilog-semi-with-comment)
+    (define-key map ":"        #'electric-verilog-colon)
     ;;(define-key map "="        'electric-verilog-equal)
-    (define-key map "`"        'electric-verilog-tick)
-    (define-key map "\t"       'electric-verilog-tab)
-    (define-key map "\r"       'electric-verilog-terminate-line)
+    (define-key map "`"        #'electric-verilog-tick)
+    (define-key map "\t"       #'electric-verilog-tab)
+    (define-key map "\r"       #'electric-verilog-terminate-line)
     ;; backspace/delete key bindings
-    (define-key map [backspace]    'backward-delete-char-untabify)
+    (define-key map [backspace]    #'backward-delete-char-untabify)
     (unless (boundp 'delete-key-deletes-forward) ; XEmacs variable
-      (define-key map [delete]       'delete-char)
-      (define-key map [(meta delete)] 'kill-word))
-    (define-key map "\M-\C-b"  'electric-verilog-backward-sexp)
-    (define-key map "\M-\C-f"  'electric-verilog-forward-sexp)
-    (define-key map "\M-\r"    'electric-verilog-terminate-and-indent)
+      (define-key map [delete]       #'delete-char)
+      (define-key map [(meta delete)] #'kill-word))
+    (define-key map "\M-\C-b"  #'electric-verilog-backward-sexp)
+    (define-key map "\M-\C-f"  #'electric-verilog-forward-sexp)
+    (define-key map "\M-\r"    #'electric-verilog-terminate-and-indent)
     (define-key map "\M-\t"    (if (fboundp 'completion-at-point)
-                                   'completion-at-point 
'verilog-complete-word))
+                                   #'completion-at-point 
#'verilog-complete-word))
     (define-key map "\M-?"     (if (fboundp 'completion-help-at-point)
-                                   'completion-help-at-point 
'verilog-show-completions))
+                                   #'completion-help-at-point 
#'verilog-show-completions))
     ;; Note \C-c and letter are reserved for users
-    (define-key map "\C-c`"    'verilog-lint-off)
-    (define-key map "\C-c*"    'verilog-delete-auto-star-implicit)
-    (define-key map "\C-c?"    'verilog-diff-auto)
-    (define-key map "\C-c\C-r" 'verilog-label-be)
-    (define-key map "\C-c\C-i" 'verilog-pretty-declarations)
-    (define-key map "\C-c="    'verilog-pretty-expr)
-    (define-key map "\C-c\C-b" 'verilog-submit-bug-report)
-    (define-key map "\C-c/"    'verilog-star-comment)
-    (define-key map "\C-c\C-c" 'verilog-comment-region)
-    (define-key map "\C-c\C-u" 'verilog-uncomment-region)
+    (define-key map "\C-c`"    #'verilog-lint-off)
+    (define-key map "\C-c*"    #'verilog-delete-auto-star-implicit)
+    (define-key map "\C-c?"    #'verilog-diff-auto)
+    (define-key map "\C-c\C-r" #'verilog-label-be)
+    (define-key map "\C-c\C-i" #'verilog-pretty-declarations)
+    (define-key map "\C-c="    #'verilog-pretty-expr)
+    (define-key map "\C-c\C-b" #'verilog-submit-bug-report)
+    (define-key map "\C-c/"    #'verilog-star-comment)
+    (define-key map "\C-c\C-c" #'verilog-comment-region)
+    (define-key map "\C-c\C-u" #'verilog-uncomment-region)
     (when (featurep 'xemacs)
-      (define-key map [(meta control h)] 'verilog-mark-defun)
-      (define-key map "\M-\C-a"  'verilog-beg-of-defun)
-      (define-key map "\M-\C-e"  'verilog-end-of-defun))
-    (define-key map "\C-c\C-d" 'verilog-goto-defun)
-    (define-key map "\C-c\C-k" 'verilog-delete-auto)
-    (define-key map "\C-c\C-a" 'verilog-auto)
-    (define-key map "\C-c\C-s" 'verilog-auto-save-compile)
-    (define-key map "\C-c\C-p" 'verilog-preprocess)
-    (define-key map "\C-c\C-z" 'verilog-inject-auto)
-    (define-key map "\C-c\C-e" 'verilog-expand-vector)
-    (define-key map "\C-c\C-h" 'verilog-header)
+      (define-key map [(meta control h)] #'verilog-mark-defun)
+      (define-key map "\M-\C-a"  #'verilog-beg-of-defun)
+      (define-key map "\M-\C-e"  #'verilog-end-of-defun))
+    (define-key map "\C-c\C-d" #'verilog-goto-defun)
+    (define-key map "\C-c\C-k" #'verilog-delete-auto)
+    (define-key map "\C-c\C-a" #'verilog-auto)
+    (define-key map "\C-c\C-s" #'verilog-auto-save-compile)
+    (define-key map "\C-c\C-p" #'verilog-preprocess)
+    (define-key map "\C-c\C-z" #'verilog-inject-auto)
+    (define-key map "\C-c\C-e" #'verilog-expand-vector)
+    (define-key map "\C-c\C-h" #'verilog-header)
     map)
   "Keymap used in Verilog mode.")
 
@@ -1969,7 +1969,11 @@ To call on \\[verilog-auto], set 
`verilog-auto-delete-trailing-whitespace'."
     (unless (bolp) (insert "\n"))))
 
 (defvar compile-command)
+;; These are known to be from other packages and may not be defined
+(defvar diff-command)
+;; There are known to be from newer versions of Emacs
 (defvar create-lockfiles)  ; Emacs 24
+(defvar which-func-modes)
 
 ;; compilation program
 (defun verilog-set-compile-command ()
@@ -2009,9 +2013,10 @@ portion, will be substituted."
    (t
     (set (make-local-variable 'compile-command)
         (if verilog-tool
-            (if (string-match "%s" (eval verilog-tool))
-                (format (eval verilog-tool) (or buffer-file-name ""))
-              (concat (eval verilog-tool) " " (or buffer-file-name "")))
+            (let ((cmd (symbol-value verilog-tool)))
+              (if (string-match "%s" cmd)
+                  (format cmd (or buffer-file-name ""))
+                (concat cmd " " (or buffer-file-name ""))))
           ""))))
   (verilog-modify-compile-command))
 
@@ -2098,7 +2103,7 @@ find the errors."
   (interactive)
   (when (boundp 'compilation-error-regexp-alist-alist)
     (when (not (assoc 'verilog-xl-1 compilation-error-regexp-alist-alist))
-      (mapcar
+      (mapc
        (lambda (item)
          (push (car item) compilation-error-regexp-alist)
          (push item compilation-error-regexp-alist-alist))
@@ -5455,8 +5460,7 @@ becomes:
           (let* ((code (match-string 2))
                  (file (match-string 3))
                  (line (match-string 4))
-                 (buffer (get-file-buffer file))
-                 dir filename)
+                 (buffer (get-file-buffer file)))
             (unless buffer
               (progn
                 (setq buffer
@@ -5468,9 +5472,8 @@ becomes:
                                    (read-file-name
                                     (format "Find this error in: (default %s) "
                                             file)
-                                    dir file t))))
-                        (if (file-directory-p name)
-                            (setq name (expand-file-name filename name)))
+                                    nil ;; dir
+                                    file t))))
                         (setq buffer
                               (and (file-exists-p name)
                                    (find-file-noselect name))))))))
@@ -5550,7 +5553,7 @@ FILENAME to find directory to run in, or defaults to 
`buffer-file-name'."
           ;; font-lock-fontify-buffer, but IIUC the problem this is supposed to
           ;; solve only appears in Emacsen older than font-lock-ensure anyway.
           (when fontlocked
-            (verilog--supressed-warnings
+            (verilog--suppressed-warnings
                 ((interactive-only font-lock-fontify-buffer))
               (font-lock-fontify-buffer))))))))
 
@@ -5613,12 +5616,11 @@ Save the result unless optional NO-SAVE is t."
      ;; Process the files
      (mapc (lambda (buf)
              (when (buffer-file-name buf)
-               (save-excursion
-                 (if (not (file-exists-p (buffer-file-name buf)))
-                     (error
-                      "File not found: %s" (buffer-file-name buf)))
-                 (message "Processing %s" (buffer-file-name buf))
-                 (set-buffer buf)
+               (if (not (file-exists-p (buffer-file-name buf)))
+                   (error
+                    "File not found: %s" (buffer-file-name buf)))
+               (message "Processing %s" (buffer-file-name buf))
+               (with-current-buffer buf
                  (funcall funref)
                  (verilog-star-cleanup)
                  (when (and (not no-save)
@@ -6653,7 +6655,7 @@ Return >0 for nested struct."
        (verilog-in-struct-p))
       ;; true
       (save-excursion
-       (if (looking-at "}\\(?:\\s-*\\w+\\s-*\\)?;") 1))
+        (if (looking-at "}\\(?:\\s-*\\w+\\s-*\\(\\s-*\\,\\s-*\\w+\\)*\\)?;") 
1))
     ;; false
     nil))
 
@@ -6860,16 +6862,19 @@ Only look at a few lines to determine indent level."
            (indent-line-to val)))
         (t
          (goto-char here)
-         (let ((val))
-           (verilog-beg-of-statement-1)
-           (if (and (< (point) here)
-                    (verilog-re-search-forward "=[ \t]*" here 'move)
-                    ;; not at a |=>, #=#, or [=n] operator
-                    (not (string-match "\\[=.\\|#=#\\||=>"
-                                        (or (buffer-substring (- (point) 2) 
(1+ (point)))
-                                            ""))))  ; don't let buffer 
over/under-run spoil the party
-               (setq val (current-column))
-             (setq val (eval (cdr (assoc type verilog-indent-alist)))))
+         (verilog-beg-of-statement-1)
+         (let ((val
+                (if (and (< (point) here)
+                         (verilog-re-search-forward "=[ \t]*" here 'move)
+                         ;; not at a |=>, #=#, or [=n] operator
+                         (not (string-match "\\[=.\\|#=#\\||=>"
+                                             (or (buffer-substring
+                                                  (- (point) 2) (1+ (point)))
+                                                 ;; Don't let buffer over/under
+                                                 ;; run spoil the party.
+                                                 ""))))
+                    (current-column)
+                  (eval (cdr (assoc type verilog-indent-alist))))))
            (goto-char here)
            (indent-line-to val))))))
 
@@ -7305,7 +7310,8 @@ BASEIND is the base indent to offset everything."
        (if (verilog-re-search-backward
             (or (and verilog-indent-declaration-macros
                      verilog-declaration-re-1-macro)
-                verilog-declaration-re-1-no-macro) lim t)
+                verilog-declaration-re-1-no-macro)
+            lim t)
            (progn
              (goto-char (match-end 0))
              (skip-chars-forward " \t")
@@ -7423,9 +7429,7 @@ BEG and END."
 ;;
 (defvar verilog-str nil)
 (defvar verilog-all nil)
-(defvar verilog-pred nil)
 (defvar verilog-buffer-to-use nil)
-(defvar verilog-flag nil)
 (defvar verilog-toggle-completions nil
   "True means \\<verilog-mode-map>\\[verilog-complete-word] should try all 
possible completions one by one.
 Repeated use of \\[verilog-complete-word] will show you all of them.
@@ -7572,9 +7576,7 @@ TYPE is `module', `tf' for task or function, or t if 
unknown."
     (while (verilog-re-search-forward verilog-str (point-max) t)
       (progn (setq match (buffer-substring (match-beginning 2)
                                           (match-end 2)))
-            (if (or (null verilog-pred)
-                    (funcall verilog-pred match))
-                (setq verilog-all (cons match verilog-all)))))
+             (setq verilog-all (cons match verilog-all))))
     (if (match-beginning 0)
        (goto-char (match-beginning 0)))))
 
@@ -7594,9 +7596,7 @@ for matches of `str' and adding the occurrence tp `all' 
through point END."
                  (not (match-end 1)))
        (setq match (buffer-substring (match-beginning 0) (match-end 0)))
        (if (string-match (concat "\\<" verilog-str) match)
-           (if (or (null verilog-pred)
-                   (funcall verilog-pred match))
-               (setq verilog-all (cons match verilog-all)))))
+            (setq verilog-all (cons match verilog-all))))
       (forward-line 1)))
   verilog-all)
 
@@ -7611,28 +7611,25 @@ for matches of `str' and adding the occurrence tp `all' 
through point END."
 
 (defun verilog-keyword-completion (keyword-list)
   "Give list of all possible completions of keywords in KEYWORD-LIST."
-  (mapcar (lambda (s)
-           (if (string-match (concat "\\<" verilog-str) s)
-               (if (or (null verilog-pred)
-                       (funcall verilog-pred s))
-                   (setq verilog-all (cons s verilog-all)))))
-         keyword-list))
-
-
-(defun verilog-completion (verilog-str verilog-pred verilog-flag)
-  "Function passed to `completing-read', `try-completion' or `all-completions'.
-Called to get completion on VERILOG-STR.  If VERILOG-PRED is non-nil, it
-must be a function to be called for every match to check if this should
-really be a match.  If VERILOG-FLAG is t, the function returns a list of
-all possible completions.  If VERILOG-FLAG is nil it returns a string,
-the longest possible completion, or t if VERILOG-STR is an exact match.
-If VERILOG-FLAG is `lambda', the function returns t if VERILOG-STR is an
-exact match, nil otherwise."
-  (save-excursion
-    (let ((verilog-all nil))
-      ;; Set buffer to use for searching labels. This should be set
-      ;; within functions which use verilog-completions
-      (set-buffer verilog-buffer-to-use)
+  (dolist (s keyword-list)
+    (if (string-match (concat "\\<" verilog-str) s)
+        (push s verilog-all))))
+
+
+(defun verilog-completion (str pred flag)
+  "Completion table for Verilog tokens.
+Function passed to `completing-read', `try-completion' or `all-completions'.
+Called to get completion on STR.
+If FLAG is t, the function returns a list of all possible completions.
+If FLAG is nil it returns a string, the longest possible completion,
+or t if STR is an exact match.
+If FLAG is `lambda', the function returns t if STR is an exact match,
+nil otherwise."
+  (let ((verilog-str str)
+        (verilog-all nil))
+    ;; Set buffer to use for searching labels. This should be set
+    ;; within functions which use verilog-completions
+    (with-current-buffer verilog-buffer-to-use
 
       ;; Determine what should be completed
       (let ((state (car (verilog-calculate-indent))))
@@ -7674,43 +7671,47 @@ exact match, nil otherwise."
               (verilog-keyword-completion verilog-separator-keywords))))
 
       ;; Now we have built a list of all matches. Give response to caller
-      (verilog-completion-response))))
-
-(defun verilog-completion-response ()
-  (cond ((or (equal verilog-flag 'lambda) (null verilog-flag))
-        ;; This was not called by all-completions
-        (if (null verilog-all)
-            ;; Return nil if there was no matching label
-            nil
-          ;; Get longest string common in the labels
-           ;; FIXME: Why not use `try-completion'?
-          (let* ((elm (cdr verilog-all))
-                 (match (car verilog-all))
-                 (min (length match))
-                 tmp)
-            (if (string= match verilog-str)
-                ;; Return t if first match was an exact match
-                (setq match t)
-              (while (not (null elm))
-                ;; Find longest common string
-                (if (< (setq tmp (verilog-string-diff match (car elm))) min)
-                    (progn
-                      (setq min tmp)
-                      (setq match (substring match 0 min))))
-                ;; Terminate with match=t if this is an exact match
-                (if (string= (car elm) verilog-str)
-                    (progn
-                      (setq match t)
-                      (setq elm nil))
-                  (setq elm (cdr elm)))))
-            ;; If this is a test just for exact match, return nil ot t
-            (if (and (equal verilog-flag 'lambda) (not (equal match 't)))
-                nil
-              match))))
-       ;; If flag is t, this was called by all-completions. Return
-       ;; list of all possible completions
-       (verilog-flag
-        verilog-all)))
+      (verilog--complete-with-action flag verilog-all verilog-str pred))))
+
+
+(defalias 'verilog--complete-with-action
+  (if (fboundp 'complete-with-action)
+      #'complete-with-action
+    (lambda (flag collection string _predicate)
+      (cond ((or (equal flag 'lambda) (null flag))
+            ;; This was not called by all-completions
+            (if (null collection)
+                ;; Return nil if there was no matching label
+                nil
+              ;; Get longest string common in the labels
+              (let* ((elm (cdr collection))
+                     (match (car collection))
+                     (min (length match))
+                     tmp)
+                (if (string= match string)
+                    ;; Return t if first match was an exact match
+                    (setq match t)
+                  (while (not (null elm))
+                    ;; Find longest common string
+                    (if (< (setq tmp (verilog-string-diff match (car elm)))
+                           min)
+                        (progn
+                          (setq min tmp)
+                          (setq match (substring match 0 min))))
+                    ;; Terminate with match=t if this is an exact match
+                    (if (string= (car elm) string)
+                        (progn
+                          (setq match t)
+                          (setq elm nil))
+                      (setq elm (cdr elm)))))
+                ;; If this is a test just for exact match, return nil ot t
+                (if (and (equal flag 'lambda) (not (equal match 't)))
+                    nil
+                  match))))
+           ;; If flag is t, this was called by all-completions. Return
+           ;; list of all possible completions
+           (flag
+            collection)))))
 
 (defvar verilog-last-word-numb 0)
 (defvar verilog-last-word-shown nil)
@@ -7728,7 +7729,7 @@ exact match, nil otherwise."
          (allcomp (if (and verilog-toggle-completions
                            (string= verilog-last-word-shown verilog-str))
                       verilog-last-completions
-                    (all-completions verilog-str 'verilog-completion))))
+                    (all-completions verilog-str #'verilog-completion))))
     (list b e allcomp)))
 
 (defun verilog-complete-word ()
@@ -7744,9 +7745,7 @@ and `verilog-separator-keywords'.)"
         (verilog-str (buffer-substring b e))
         (allcomp (nth 2 comp-info))
         (match (if verilog-toggle-completions
-                   "" (try-completion
-                       verilog-str (mapcar (lambda (elm)
-                                             (cons elm 0)) allcomp)))))
+                   "" (try-completion verilog-str allcomp))))
     ;; Delete old string
     (delete-region b e)
 
@@ -7818,39 +7817,38 @@ With optional second ARG non-nil, STR is the complete 
name of the instruction."
     (setq str (concat str "[a-zA-Z0-9_]*")))
   (concat "^\\s-*\\(function\\|task\\|module\\)[ 
\t]+\\(?:\\(?:static\\|automatic\\)\\s-+\\)?\\(" str "\\)\\>"))
 
-(defun verilog-comp-defun (verilog-str verilog-pred verilog-flag)
-  "Function passed to `completing-read', `try-completion' or `all-completions'.
-Returns a completion on any function name based on VERILOG-STR prefix.  If
-VERILOG-PRED is non-nil, it must be a function to be called for every match
-to check if this should really be a match.  If VERILOG-FLAG is t, the
-function returns a list of all possible completions.  If it is nil it
-returns a string, the longest possible completion, or t if VERILOG-STR is
-an exact match.  If VERILOG-FLAG is `lambda', the function returns t if
-VERILOG-STR is an exact match, nil otherwise."
-  (save-excursion
-    (let ((verilog-all nil)
-         match)
-
-      ;; Set buffer to use for searching labels. This should be set
-      ;; within functions which use verilog-completions
-      (set-buffer verilog-buffer-to-use)
+(defun verilog-comp-defun (str pred flag)
+  "Completion table for function names.
+Function passed to `completing-read', `try-completion' or `all-completions'.
+Returns a completion on any function name based on STR prefix.
+If FLAG is t, the function returns a list of all possible completions.
+If it is nil it returns a string, the longest possible completion,
+or t if STR is an exact match.
+If FLAG is `lambda', the function returns t if STR is an exact match,
+nil otherwise."
+  (let ((verilog-all nil)
+       (verilog-str str)
+       match)
+
+    ;; Set buffer to use for searching labels. This should be set
+    ;; within functions which use verilog-completions
+    (with-current-buffer verilog-buffer-to-use
 
       (let ((verilog-str verilog-str))
        ;; Build regular expression for functions
-       (if (string= verilog-str "")
-           (setq verilog-str (verilog-build-defun-re "[a-zA-Z_]"))
-         (setq verilog-str (verilog-build-defun-re verilog-str)))
+       (setq verilog-str
+             (verilog-build-defun-re (if (string= verilog-str "")
+                                         "[a-zA-Z_]"
+                                       verilog-str)))
        (goto-char (point-min))
 
        ;; Build a list of all possible completions
        (while (verilog-re-search-forward verilog-str nil t)
          (setq match (buffer-substring (match-beginning 2) (match-end 2)))
-         (if (or (null verilog-pred)
-                 (funcall verilog-pred match))
-             (setq verilog-all (cons match verilog-all)))))
+         (setq verilog-all (cons match verilog-all))))
 
       ;; Now we have built a list of all matches. Give response to caller
-      (verilog-completion-response))))
+      (verilog--complete-with-action flag verilog-all verilog-str pred))))
 
 (defun verilog-goto-defun ()
   "Move to specified Verilog module/interface/task/function.
@@ -7865,10 +7863,10 @@ If search fails, other files are checked based on
                    ;; Do completion with default
                    (completing-read (concat "Goto-Label: (default "
                                             default ") ")
-                                    'verilog-comp-defun nil nil "")
+                                    #'verilog-comp-defun nil nil "")
                  ;; There is no default value. Complete without it
                  (completing-read "Goto-Label: "
-                                  'verilog-comp-defun nil nil "")))
+                                  #'verilog-comp-defun nil nil "")))
         pt)
     ;; Make sure library paths are correct, in case need to resolve module
     (verilog-auto-reeval-locals)
@@ -7927,10 +7925,9 @@ If search fails, other files are checked based on
                 (tag (format "%3d" linenum))
                 (empty (make-string (length tag) ?\ ))
                 tem)
-           (save-excursion
-             (setq tem (make-marker))
-             (set-marker tem (point))
-             (set-buffer standard-output)
+           (setq tem (make-marker))
+           (set-marker tem (point))
+           (with-current-buffer standard-output
              (setq occur-pos-list (cons tem occur-pos-list))
              (or first (zerop nlines)
                  (insert "--------\n"))
@@ -8648,11 +8645,6 @@ Optional NUM-PARAM and MAX-PARAM check for a specific 
number of parameters."
 (defvar sigs-out-i)
 (defvar sigs-out-unk)
 (defvar sigs-temp)
-;; These are known to be from other packages and may not be defined
-(defvar diff-command)
-;; There are known to be from newer versions of Emacs
-(defvar create-lockfiles)
-(defvar which-func-modes)
 
 (defun verilog-read-decls ()
   "Compute signal declaration information for the current module at point.
@@ -10099,7 +10091,7 @@ If undefined, and WING-IT, return just SYMBOL without 
the tick, else nil."
              ;; variable in only one buffer returns t in another.
              ;; This can confuse, so check for nil.
              ;; Namespace intentionally short for AUTOs and compatibility
-             (let ((val (eval (intern (concat "vh-" symbol)))))
+             (let ((val (symbol-value (intern (concat "vh-" symbol)))))
                (if (eq val nil)
                    (if wing-it symbol nil)
                  val))
@@ -10138,7 +10130,7 @@ This function is intended for use in AUTO_TEMPLATE Lisp 
expressions."
              ;; variable in only one buffer returns t in another.
              ;; This can confuse, so check for nil.
              ;; Namespace intentionally short for AUTOs and compatibility
-             (setq val (eval (intern (concat "vh-" symbol)))))
+             (setq val (symbol-value (intern (concat "vh-" symbol)))))
             (setq text (replace-match val nil nil text)))
            (t (setq ok nil)))))
   text)
@@ -10493,7 +10485,7 @@ those clocking block's signals."
     ;; New scheme
     ;; Namespace intentionally short for AUTOs and compatibility
     (let* ((enumvar (intern (concat "venum-" enum))))
-      (dolist (en (and (boundp enumvar) (eval enumvar)))
+      (dolist (en (and (boundp enumvar) (symbol-value enumvar)))
         (let ((sig (list en)))
           (unless (member sig out-list)
             (push sig out-list)))))
@@ -10698,9 +10690,7 @@ When MODI is non-null, also add to modi-cache, for 
tracking."
        (verilog-insert "// " (verilog-sig-comment sig) "\n"))
       (setq sigs (cdr sigs)))))
 
-(defvar indent-pt) ;; Local used by `verilog-insert-indent'.
-
-(defun verilog-insert-indent (&rest stuff)
+(defun verilog--insert-indent (indent-pt &rest stuff)
   "Indent to position stored in local `indent-pt' variable, then insert STUFF.
 Presumes that any newlines end a list element."
   (let ((need-indent t))
@@ -10710,6 +10700,10 @@ Presumes that any newlines end a list element."
       (verilog-insert (car stuff))
       (setq need-indent (string-match "\n$" (car stuff))
            stuff (cdr stuff)))))
+
+(defmacro verilog-insert-indent (&rest stuff)
+  `(verilog--insert-indent indent-pt ,@stuff))
+
 ;;(let ((indent-pt 10)) (verilog-insert-indent "hello\n" "addon" "there\n"))
 
 (defun verilog-forward-or-insert-line ()
@@ -11518,7 +11512,8 @@ See the example in `verilog-auto-inout-modport'."
           (inst-name (nth 2 params))
           (regexp (nth 3 params))
            (prefix (nth 4 params))
-           direction-re submodi)  ; direction argument not supported until 
requested
+           ;; direction-re  ; direction argument not supported until requested
+           submodi)
       ;; Lookup position, etc of co-module
       ;; Note this may raise an error
       (when (setq submodi (verilog-modi-lookup submod t))
@@ -11539,11 +11534,11 @@ See the example in `verilog-auto-inout-modport'."
          (setq sig-list-i  (verilog-signals-edit-wire-reg
                             (verilog-signals-matching-dir-re
                              (verilog-signals-matching-regexp sig-list-i 
regexp)
-                             "input" direction-re))
+                             "input" nil)) ;; direction-re
                sig-list-o  (verilog-signals-edit-wire-reg
                             (verilog-signals-matching-dir-re
                              (verilog-signals-matching-regexp sig-list-o 
regexp)
-                             "output" direction-re)))
+                             "output" nil))) ;; direction-re
          (setq sig-list-i (sort (copy-alist sig-list-i) 
#'verilog-signals-sort-compare))
          (setq sig-list-o (sort (copy-alist sig-list-o) 
#'verilog-signals-sort-compare))
          (when (or sig-list-i sig-list-o)
@@ -11684,7 +11679,7 @@ If PAR-VALUES replace final strings with these 
parameter values."
       (setq tpl-net (verilog-string-replace-matches "\\[\\]" vl-bits nil nil 
tpl-net)))
     ;; Insert it
     (when (or tpl-ass (not verilog-auto-inst-template-required))
-      (verilog-auto-inst-first section)
+      (verilog--auto-inst-first indent-pt section)
       (indent-to indent-pt)
       (insert "." port)
       (unless (and verilog-auto-inst-dot-name
@@ -11723,7 +11718,7 @@ If PAR-VALUES replace final strings with these 
parameter values."
 (defvar verilog-auto-inst-first-any nil
   "Local first-in-any-section for `verilog-auto-inst-first'.")
 
-(defun verilog-auto-inst-first (section)
+(defun verilog--auto-inst-first (indent-pt section)
   "Insert , and SECTION before port, as part of \\[verilog-auto-inst]."
   ;; Do we need a trailing comma?
   ;; There maybe an ifdef or something similar before us.  What a mess.  Thus
@@ -12957,21 +12952,25 @@ that expression are included."
                             (verilog-signals-not-matching-regexp
                              (verilog-signals-matching-dir-re
                               (verilog-signals-matching-regexp sig-list-i 
regexp)
-                              "input" direction-re) not-re))
+                              "input" direction-re)
+                             not-re))
                sig-list-o  (verilog-signals-edit-wire-reg
                             (verilog-signals-not-matching-regexp
                              (verilog-signals-matching-dir-re
                               (verilog-signals-matching-regexp sig-list-o 
regexp)
-                              "output" direction-re) not-re))
+                              "output" direction-re)
+                             not-re))
                sig-list-io (verilog-signals-edit-wire-reg
                             (verilog-signals-not-matching-regexp
                              (verilog-signals-matching-dir-re
                               (verilog-signals-matching-regexp sig-list-io 
regexp)
-                              "inout" direction-re) not-re))
+                              "inout" direction-re)
+                             not-re))
                sig-list-if (verilog-signals-not-matching-regexp
                             (verilog-signals-matching-dir-re
                              (verilog-signals-matching-regexp sig-list-if 
regexp)
-                             "interface" direction-re) not-re))
+                             "interface" direction-re)
+                            not-re))
          (when v2k (verilog-repair-open-comma))
          (when (or sig-list-i sig-list-o sig-list-io sig-list-if)
            (verilog-insert-indent "// Beginning of automatic in/out/inouts 
(from specific module)\n")
@@ -13257,7 +13256,8 @@ driver/monitor using AUTOINST in the testbench."
           (modport-re (nth 1 params))
           (regexp (nth 2 params))
            (prefix (nth 3 params))
-           direction-re submodi)  ; direction argument not supported until 
requested
+           ;; direction-re  ; direction argument not supported until requested
+           submodi)
       ;; Lookup position, etc of co-module
       ;; Note this may raise an error
       (when (setq submodi (verilog-modi-lookup submod t))
@@ -13288,7 +13288,7 @@ driver/monitor using AUTOINST in the testbench."
                               (verilog-signals-add-prefix
                                (verilog-signals-matching-dir-re
                                 (verilog-signals-matching-regexp sig-list-i 
regexp)
-                                "input" direction-re)
+                                "input" nil) ;; direction-re
                                prefix)
                               (verilog-decls-get-ports moddecls)))
                sig-list-o  (verilog-signals-edit-wire-reg
@@ -13296,7 +13296,7 @@ driver/monitor using AUTOINST in the testbench."
                               (verilog-signals-add-prefix
                                (verilog-signals-matching-dir-re
                                 (verilog-signals-matching-regexp sig-list-o 
regexp)
-                                "output" direction-re)
+                                "output" nil) ;; direction-re
                                prefix)
                               (verilog-decls-get-ports moddecls)))
                sig-list-io (verilog-signals-edit-wire-reg
@@ -13304,7 +13304,7 @@ driver/monitor using AUTOINST in the testbench."
                               (verilog-signals-add-prefix
                                (verilog-signals-matching-dir-re
                                 (verilog-signals-matching-regexp sig-list-io 
regexp)
-                                "inout" direction-re)
+                                "inout" nil) ;; direction-re
                                prefix)
                               (verilog-decls-get-ports moddecls))))
          (when v2k (verilog-repair-open-comma))
@@ -14275,37 +14275,37 @@ Wilson Snyder (wsnyder@wsnyder.org)."
 
 (defvar verilog-template-map
   (let ((map (make-sparse-keymap)))
-    (define-key map "a" 'verilog-sk-always)
-    (define-key map "b" 'verilog-sk-begin)
-    (define-key map "c" 'verilog-sk-case)
-    (define-key map "f" 'verilog-sk-for)
-    (define-key map "g" 'verilog-sk-generate)
-    (define-key map "h" 'verilog-sk-header)
-    (define-key map "i" 'verilog-sk-initial)
-    (define-key map "j" 'verilog-sk-fork)
-    (define-key map "m" 'verilog-sk-module)
-    (define-key map "o" 'verilog-sk-ovm-class)
-    (define-key map "p" 'verilog-sk-primitive)
-    (define-key map "r" 'verilog-sk-repeat)
-    (define-key map "s" 'verilog-sk-specify)
-    (define-key map "t" 'verilog-sk-task)
-    (define-key map "u" 'verilog-sk-uvm-object)
-    (define-key map "w" 'verilog-sk-while)
-    (define-key map "x" 'verilog-sk-casex)
-    (define-key map "z" 'verilog-sk-casez)
-    (define-key map "?" 'verilog-sk-if)
-    (define-key map ":" 'verilog-sk-else-if)
-    (define-key map "/" 'verilog-sk-comment)
-    (define-key map "A" 'verilog-sk-assign)
-    (define-key map "F" 'verilog-sk-function)
-    (define-key map "I" 'verilog-sk-input)
-    (define-key map "O" 'verilog-sk-output)
-    (define-key map "S" 'verilog-sk-state-machine)
-    (define-key map "=" 'verilog-sk-inout)
-    (define-key map "U" 'verilog-sk-uvm-component)
-    (define-key map "W" 'verilog-sk-wire)
-    (define-key map "R" 'verilog-sk-reg)
-    (define-key map "D" 'verilog-sk-define-signal)
+    (define-key map "a" #'verilog-sk-always)
+    (define-key map "b" #'verilog-sk-begin)
+    (define-key map "c" #'verilog-sk-case)
+    (define-key map "f" #'verilog-sk-for)
+    (define-key map "g" #'verilog-sk-generate)
+    (define-key map "h" #'verilog-sk-header)
+    (define-key map "i" #'verilog-sk-initial)
+    (define-key map "j" #'verilog-sk-fork)
+    (define-key map "m" #'verilog-sk-module)
+    (define-key map "o" #'verilog-sk-ovm-class)
+    (define-key map "p" #'verilog-sk-primitive)
+    (define-key map "r" #'verilog-sk-repeat)
+    (define-key map "s" #'verilog-sk-specify)
+    (define-key map "t" #'verilog-sk-task)
+    (define-key map "u" #'verilog-sk-uvm-object)
+    (define-key map "w" #'verilog-sk-while)
+    (define-key map "x" #'verilog-sk-casex)
+    (define-key map "z" #'verilog-sk-casez)
+    (define-key map "?" #'verilog-sk-if)
+    (define-key map ":" #'verilog-sk-else-if)
+    (define-key map "/" #'verilog-sk-comment)
+    (define-key map "A" #'verilog-sk-assign)
+    (define-key map "F" #'verilog-sk-function)
+    (define-key map "I" #'verilog-sk-input)
+    (define-key map "O" #'verilog-sk-output)
+    (define-key map "S" #'verilog-sk-state-machine)
+    (define-key map "=" #'verilog-sk-inout)
+    (define-key map "U" #'verilog-sk-uvm-component)
+    (define-key map "W" #'verilog-sk-wire)
+    (define-key map "R" #'verilog-sk-reg)
+    (define-key map "D" #'verilog-sk-define-signal)
     map)
   "Keymap used in Verilog mode for smart template operations.")
 
@@ -14696,13 +14696,13 @@ and the case items."
   (let ((map (make-sparse-keymap))) ; as described in info pages, make a map
     (set-keymap-parent map verilog-mode-map)
     ;; mouse button bindings
-    (define-key map "\r"            'verilog-load-file-at-point)
-    (if (featurep 'xemacs)
-       (define-key map 'button2    'verilog-load-file-at-mouse);ffap-at-mouse ?
-      (define-key map [mouse-2]     'verilog-load-file-at-mouse))
+    (define-key map "\r"            #'verilog-load-file-at-point)
+    (define-key map
+      (if (featurep 'xemacs) 'button2 [mouse-2])
+      #'verilog-load-file-at-mouse)
     (if (featurep 'xemacs)
-       (define-key map 'Sh-button2 'mouse-yank) ; you wanna paste don't you ?
-      (define-key map [S-mouse-2]   'mouse-yank-at-click))
+       (define-key map 'Sh-button2 #'mouse-yank) ; you wanna paste don't you ?
+      (define-key map [S-mouse-2]   #'mouse-yank-at-click))
     map)
   "Map containing mouse bindings for `verilog-mode'.")
 
@@ -14775,7 +14775,7 @@ Clicking on the middle-mouse button loads them in a 
buffer (as in dired)."
   (verilog-highlight-region (point-min) (point-max) nil))
 
 ;; Deprecated, but was interactive, so we'll keep it around
-(defalias 'verilog-colorize-include-files-buffer 'verilog-highlight-buffer)
+(defalias 'verilog-colorize-include-files-buffer #'verilog-highlight-buffer)
 
 ;; ffap-at-mouse isn't useful for Verilog mode. It uses library paths.
 ;; so define this function to do more or less the same as ffap-at-mouse
diff --git a/lisp/progmodes/vhdl-mode.el b/lisp/progmodes/vhdl-mode.el
index c4de800..856432c 100644
--- a/lisp/progmodes/vhdl-mode.el
+++ b/lisp/progmodes/vhdl-mode.el
@@ -6,7 +6,7 @@
 ;;              Rodney J. Whitby <software.vhdl-mode@rwhitby.net>
 ;; Maintainer:  Reto Zimmermann <reto@gnu.org>
 ;; Keywords:    languages vhdl
-;; WWW:         http://www.iis.ee.ethz.ch/~zimmi/emacs/vhdl-mode.html
+;; WWW:         https://guest.iis.ee.ethz.ch/~zimmi/emacs/vhdl-mode.html
 
 ;; Yoni Rabkin <yoni@rabkins.net> contacted the maintainer of this
 ;; file on 18/3/2008, and the maintainer agreed that when a bug is
@@ -2159,7 +2159,8 @@ your style, only those that are different from the 
default.")
 
 ;; mandatory
 (require 'compile)                     ; XEmacs
-(require 'easymenu)
+(when (< emacs-major-version 28)       ; preloaded in Emacs 28
+  (require 'easymenu))
 (require 'hippie-exp)
 
 ;; optional (minimize warning messages during compile)
diff --git a/lisp/progmodes/xref.el b/lisp/progmodes/xref.el
index 18fdd96..ea52bef 100644
--- a/lisp/progmodes/xref.el
+++ b/lisp/progmodes/xref.el
@@ -97,10 +97,6 @@ This is typically the filename.")
   "Return the line number corresponding to the location."
   nil)
 
-(cl-defgeneric xref-location-column (_location)
-  "Return the exact column corresponding to the location."
-  nil)
-
 (cl-defgeneric xref-match-length (_item)
   "Return the length of the match."
   nil)
@@ -130,7 +126,7 @@ in its full absolute form."
 (defclass xref-file-location (xref-location)
   ((file :type string :initarg :file)
    (line :type fixnum :initarg :line :reader xref-location-line)
-   (column :type fixnum :initarg :column :reader xref-location-column))
+   (column :type fixnum :initarg :column :reader xref-file-location-column))
   :documentation "A file location is a file/line/column triple.
 Line numbers start from 1 and columns from 0.")
 
@@ -415,6 +411,12 @@ elements is negated: these commands will NOT prompt."
   "Functions called after returning to a pre-jump location."
   :type 'hook)
 
+(defcustom xref-after-update-hook nil
+  "Functions called after the xref buffer is updated."
+  :type 'hook
+  :version "28.1"
+  :package-version '(xref . "1.0.4"))
+
 (defvar xref--marker-ring (make-ring xref-marker-ring-length)
   "Ring of markers to implement the marker stack.")
 
@@ -607,16 +609,26 @@ SELECT is `quit', also quit the *xref* window."
     (when xref
       (xref--show-location (xref-item-location xref)))))
 
+(defun xref-next-line-no-show ()
+  "Move to the next xref but don't display its source."
+  (interactive)
+  (xref--search-property 'xref-item))
+
 (defun xref-next-line ()
   "Move to the next xref and display its source in the appropriate window."
   (interactive)
-  (xref--search-property 'xref-item)
+  (xref-next-line-no-show)
   (xref-show-location-at-point))
 
+(defun xref-prev-line-no-show ()
+  "Move to the previous xref but don't display its source."
+  (interactive)
+  (xref--search-property 'xref-item t))
+
 (defun xref-prev-line ()
   "Move to the previous xref and display its source in the appropriate window."
   (interactive)
-  (xref--search-property 'xref-item t)
+  (xref-prev-line-no-show)
   (xref-show-location-at-point))
 
 (defun xref-next-group ()
@@ -713,10 +725,7 @@ references displayed in the current *xref* buffer."
                    (push pair all-pairs)
                    ;; Perform sanity check first.
                    (xref--goto-location loc)
-                   (if (xref--outdated-p item
-                                         (buffer-substring-no-properties
-                                          (line-beginning-position)
-                                          (line-end-position)))
+                   (if (xref--outdated-p item)
                        (message "Search result out of date, skipping")
                      (cond
                       ((null file-buf)
@@ -733,18 +742,38 @@ references displayed in the current *xref* buffer."
            (move-marker (car pair) nil)
            (move-marker (cdr pair) nil)))))))
 
-(defun xref--outdated-p (item line-text)
-  ;; FIXME: The check should probably be a generic function instead of
-  ;; the assumption that all matches contain the full line as summary.
-  (let ((summary (xref-item-summary item))
-        (strip (lambda (s) (if (string-match "\r\\'" s)
-                          (substring-no-properties s 0 -1)
-                        s))))
+(defun xref--outdated-p (item)
+  "Check that the match location at current position is up-to-date.
+ITEMS is an xref item which "
+  ;; FIXME: The check should most likely be a generic function instead
+  ;; of the assumption that all matches' summaries relate to the
+  ;; buffer text in a particular way.
+  (let* ((summary (xref-item-summary item))
+         ;; Sometimes buffer contents include ^M, and sometimes Grep
+         ;; output includes it, and they don't always match.
+         (strip (lambda (s) (if (string-match "\r\\'" s)
+                           (substring-no-properties s 0 -1)
+                         s)))
+         (stripped-summary (funcall strip summary))
+         (lendpos (line-end-position))
+         (check (lambda ()
+                  (let ((comparison-end
+                         (+ (point) (length stripped-summary))))
+                    (and (>= lendpos comparison-end)
+                         (equal stripped-summary
+                                (buffer-substring-no-properties
+                                 (point) comparison-end)))))))
     (not
-     ;; Sometimes buffer contents include ^M, and sometimes Grep
-     ;; output includes it, and they don't always match.
-     (equal (funcall strip line-text)
-            (funcall strip summary)))))
+     (or
+      ;; Either summary contains match text and after
+      ;; (2nd+ match on the line)...
+      (funcall check)
+      ;; ...or it starts at bol, includes the match and after.
+      (and (< (point) (+ (line-beginning-position)
+                         (length stripped-summary)))
+           (save-excursion
+             (forward-line 0)
+             (funcall check)))))))
 
 ;; FIXME: Write a nicer UI.
 (defun xref--query-replace-1 (from to iter)
@@ -886,30 +915,24 @@ GROUP is a string for decoration purposes and XREF is an
                                (length (and line (format "%d" line)))))
            for line-format = (and max-line-width
                                   (format "%%%dd: " max-line-width))
-           with prev-line-key = nil
+           with prev-group = nil
+           with prev-line = nil
            do
            (xref--insert-propertized '(face xref-file-header xref-group t)
                                      group "\n")
            (cl-loop for (xref . more2) on xrefs do
                     (with-slots (summary location) xref
                       (let* ((line (xref-location-line location))
-                             (new-summary summary)
-                             (line-key (list (xref-location-group location) 
line))
                              (prefix
-                              (if line
-                                  (propertize (format line-format line)
-                                              'face 'xref-line-number)
-                                "  ")))
+                              (cond
+                               ((not line) "  ")
+                               ((equal line prev-line) "")
+                               (t (propertize (format line-format line)
+                                              'face 'xref-line-number)))))
                         ;; Render multiple matches on the same line, together.
-                        (when (and line (equal prev-line-key line-key))
-                          (when-let ((column (xref-location-column location)))
-                            (delete-region
-                             (save-excursion
-                               (forward-line -1)
-                               (move-to-column (+ (length prefix) column))
-                               (point))
-                             (point))
-                            (setq new-summary (substring summary column) 
prefix "")))
+                        (when (and (equal prev-group group)
+                                   (not (equal prev-line line)))
+                          (insert "\n"))
                         (xref--insert-propertized
                          (list 'xref-item xref
                                'mouse-face 'highlight
@@ -917,9 +940,11 @@ GROUP is a string for decoration purposes and XREF is an
                                'help-echo
                                (concat "mouse-2: display in another window, "
                                        "RET or mouse-1: follow reference"))
-                         prefix new-summary)
-                        (setq prev-line-key line-key)))
-                    (insert "\n"))))
+                         prefix summary)
+                        (setq prev-line line
+                              prev-group group))))
+           (insert "\n"))
+  (run-hooks 'xref-after-update-hook))
 
 (defun xref--analyze (xrefs)
   "Find common filenames in XREFS.
@@ -1678,20 +1703,30 @@ Such as the current syntax table and the applied syntax 
properties."
                                  syntax-needed)))))
 
 (defun xref--collect-matches-1 (regexp file line line-beg line-end 
syntax-needed)
-  (let (matches)
+  (let (match-pairs matches)
     (when syntax-needed
       (syntax-propertize line-end))
-    ;; FIXME: This results in several lines with the same
-    ;; summary. Solve with composite pattern?
     (while (and
             ;; REGEXP might match an empty string.  Or line.
-            (or (null matches)
+            (or (null match-pairs)
                 (> (point) line-beg))
             (re-search-forward regexp line-end t))
-      (let* ((beg-column (- (match-beginning 0) line-beg))
-             (end-column (- (match-end 0) line-beg))
+      (push (cons (match-beginning 0)
+                  (match-end 0))
+            match-pairs))
+    (setq match-pairs (nreverse match-pairs))
+    (while match-pairs
+      (let* ((beg-end (pop match-pairs))
+             (beg-column (- (car beg-end) line-beg))
+             (end-column (- (cdr beg-end) line-beg))
              (loc (xref-make-file-location file line beg-column))
-             (summary (buffer-substring line-beg line-end)))
+             (summary (buffer-substring (if matches (car beg-end) line-beg)
+                                        (if match-pairs
+                                            (caar match-pairs)
+                                          line-end))))
+        (when matches
+          (cl-decf beg-column (- (car beg-end) line-beg))
+          (cl-decf end-column (- (car beg-end) line-beg)))
         (add-face-text-property beg-column end-column 'xref-match
                                 t summary)
         (push (xref-make-match summary loc (- end-column beg-column))
diff --git a/lisp/progmodes/xscheme.el b/lisp/progmodes/xscheme.el
index e85e3cf..613863d 100644
--- a/lisp/progmodes/xscheme.el
+++ b/lisp/progmodes/xscheme.el
@@ -104,20 +104,17 @@ reading-string         reading prompt string")
 
 (defcustom scheme-band-name nil
   "Band loaded by the `run-scheme' command."
-  :type '(choice (const nil) string)
-  :group 'xscheme)
+  :type '(choice (const nil) string))
 
 (defcustom scheme-program-arguments nil
   "Arguments passed to the Scheme program by the `run-scheme' command."
-  :type '(choice (const nil) string)
-  :group 'xscheme)
+  :type '(choice (const nil) string))
 
 (defcustom xscheme-allow-pipelined-evaluation t
   "If non-nil, an expression may be transmitted while another is evaluating.
 Otherwise, attempting to evaluate an expression before the previous expression
 has finished evaluating will signal an error."
-  :type 'boolean
-  :group 'xscheme)
+  :type 'boolean)
 
 (defcustom xscheme-startup-message
   "This is the Scheme process buffer.
@@ -128,19 +125,16 @@ Type \\[describe-mode] for more information.
 "
   "String to insert into Scheme process buffer first time it is started.
 Is processed with `substitute-command-keys' first."
-  :type 'string
-  :group 'xscheme)
+  :type 'string)
 
 (defcustom xscheme-signal-death-message nil
   "If non-nil, causes a message to be generated when the Scheme process dies."
-  :type 'boolean
-  :group 'xscheme)
+  :type 'boolean)
 
 (defcustom xscheme-start-hook nil
   "If non-nil, a procedure to call when the Scheme process is started.
 When called, the current buffer will be the Scheme process-buffer."
   :type 'hook
-  :group 'xscheme
   :version "20.3")
 
 (defun xscheme-evaluation-commands (keymap)
diff --git a/lisp/ps-samp.el b/lisp/ps-samp.el
index fdff0f1..22a29b8 100644
--- a/lisp/ps-samp.el
+++ b/lisp/ps-samp.el
@@ -1,4 +1,4 @@
-;;; ps-samp.el --- ps-print sample setup code
+;;; ps-samp.el --- ps-print sample setup code  -*- lexical-binding: t -*-
 
 ;; Copyright (C) 2007-2021 Free Software Foundation, Inc.
 
diff --git a/lisp/recentf.el b/lisp/recentf.el
index d39a523..48b8e2b 100644
--- a/lisp/recentf.el
+++ b/lisp/recentf.el
@@ -37,7 +37,6 @@
 ;;
 
 ;;; Code:
-(require 'easymenu)
 (require 'tree-widget)
 (require 'timer)
 
diff --git a/lisp/repeat.el b/lisp/repeat.el
index 795577c..a2b04b8 100644
--- a/lisp/repeat.el
+++ b/lisp/repeat.el
@@ -180,7 +180,7 @@ this function is always whether the value of `this-command' 
would've been
   (= repeat-num-input-keys-at-repeat num-input-keys))
 
 ;; An example of the use of (repeat-is-really-this-command) may still be
-;; available in <http://www.eskimo.com/~seldon/dotemacs.el>; search for
+;; available in <https://www.eskimo.com/~seldon/dotemacs.el>; search for
 ;; "defun wm-switch-buffer".
 
 ;;;;; ******************* THE REPEAT COMMAND ITSELF ******************* ;;;;;
@@ -329,6 +329,77 @@ recently executed command not bound to an input event\"."
 
 ;;;;; ************************* EMACS CONTROL ************************* ;;;;;
 
+
+;; And now for something completely different.
+
+;;; repeat-mode
+
+(defcustom repeat-exit-key nil
+  "Key that stops the modal repeating of keys in sequence.
+For example, you can set it to <return> like `isearch-exit'."
+  :type '(choice (const :tag "No special key to exit repeating sequence" nil)
+                (key-sequence :tag "Key that exits repeating sequence"))
+  :group 'convenience
+  :version "28.1")
+
+;;;###autoload
+(define-minor-mode repeat-mode
+  "Toggle Repeat mode.
+When Repeat mode is enabled, and the command symbol has the property named
+`repeat-map', this map is activated temporarily for the next command."
+  :global t :group 'convenience
+  (if (not repeat-mode)
+      (remove-hook 'post-command-hook 'repeat-post-hook)
+    (add-hook 'post-command-hook 'repeat-post-hook)
+    (let* ((keymaps nil)
+           (commands (all-completions
+                      "" obarray (lambda (s)
+                                   (and (commandp s)
+                                        (get s 'repeat-map)
+                                        (push (get s 'repeat-map) keymaps))))))
+      (message "Repeat mode is enabled for %d commands and %d keymaps"
+               (length commands)
+               (length (delete-dups keymaps))))))
+
+(defun repeat-post-hook ()
+  "Function run after commands to set transient keymap for repeatable keys."
+  (when repeat-mode
+    (let ((repeat-map (and (symbolp this-command)
+                           (get this-command 'repeat-map))))
+      (when repeat-map
+        (when (boundp repeat-map)
+          (setq repeat-map (symbol-value repeat-map)))
+        (let ((map (copy-keymap repeat-map))
+              keys mess)
+          (map-keymap (lambda (key _) (push key keys)) map)
+
+          ;; Exit when the last char is not among repeatable keys,
+          ;; so e.g. `C-x u u' repeats undo, whereas `C-/ u' doesn't.
+          (when (or (memq last-command-event keys)
+                    (memq this-original-command '(universal-argument
+                                                  universal-argument-more
+                                                 digit-argument
+                                                  negative-argument)))
+            ;; Messaging
+            (setq mess (format-message
+                        "Repeat with %s%s"
+                        (mapconcat (lambda (key)
+                                     (key-description (vector key)))
+                                   keys ", ")
+                        (if repeat-exit-key
+                            (format ", or exit with %s"
+                                    (key-description repeat-exit-key))
+                          "")))
+            (if (current-message)
+                (message "%s [%s]" (current-message) mess)
+              (message mess))
+
+            ;; Adding an exit key
+            (when repeat-exit-key
+              (define-key map repeat-exit-key 'ignore))
+
+            (set-transient-map map)))))))
+
 (provide 'repeat)
 
 ;;; repeat.el ends here
diff --git a/lisp/replace.el b/lisp/replace.el
index eb7a439..f131d26 100644
--- a/lisp/replace.el
+++ b/lisp/replace.el
@@ -1104,51 +1104,39 @@ a previously found match."
       count)))
 
 
-(defvar occur-menu-map
-  (let ((map (make-sparse-keymap)))
-    (bindings--define-key map [next-error-follow-minor-mode]
-      '(menu-item "Auto Occurrence Display"
-                 next-error-follow-minor-mode
-                 :help "Display another occurrence when moving the cursor"
-                 :button (:toggle . (and (boundp 'next-error-follow-minor-mode)
-                                         next-error-follow-minor-mode))))
-    (bindings--define-key map [separator-1] menu-bar-separator)
-    (bindings--define-key map [kill-this-buffer]
-      '(menu-item "Kill Occur Buffer" kill-this-buffer
-                 :help "Kill the current *Occur* buffer"))
-    (bindings--define-key map [quit-window]
-      '(menu-item "Quit Occur Window" quit-window
-                 :help "Quit the current *Occur* buffer.  Bury it, and maybe 
delete the selected frame"))
-    (bindings--define-key map [revert-buffer]
-      '(menu-item "Revert Occur Buffer" revert-buffer
-                 :help "Replace the text in the *Occur* buffer with the 
results of rerunning occur"))
-    (bindings--define-key map [clone-buffer]
-      '(menu-item "Clone Occur Buffer" clone-buffer
-                 :help "Create and return a twin copy of the current *Occur* 
buffer"))
-    (bindings--define-key map [occur-rename-buffer]
-      '(menu-item "Rename Occur Buffer" occur-rename-buffer
-                 :help "Rename the current *Occur* buffer to *Occur: 
original-buffer-name*."))
-    (bindings--define-key map [occur-edit-buffer]
-      '(menu-item "Edit Occur Buffer" occur-edit-mode
-                 :help "Edit the *Occur* buffer and apply changes to the 
original buffers."))
-    (bindings--define-key map [separator-2] menu-bar-separator)
-    (bindings--define-key map [occur-mode-goto-occurrence-other-window]
-      '(menu-item "Go To Occurrence Other Window" 
occur-mode-goto-occurrence-other-window
-                 :help "Go to the occurrence the current line describes, in 
another window"))
-    (bindings--define-key map [occur-mode-goto-occurrence]
-      '(menu-item "Go To Occurrence" occur-mode-goto-occurrence
-                 :help "Go to the occurrence the current line describes"))
-    (bindings--define-key map [occur-mode-display-occurrence]
-      '(menu-item "Display Occurrence" occur-mode-display-occurrence
-                 :help "Display in another window the occurrence the current 
line describes"))
-    (bindings--define-key map [occur-next]
-      '(menu-item "Move to Next Match" occur-next
-                 :help "Move to the Nth (default 1) next match in an Occur 
mode buffer"))
-    (bindings--define-key map [occur-prev]
-      '(menu-item "Move to Previous Match" occur-prev
-                 :help "Move to the Nth (default 1) previous match in an Occur 
mode buffer"))
-    map)
-  "Menu keymap for `occur-mode'.")
+(easy-menu-define occur-menu-map nil
+  "Menu for `occur-mode'."
+  '("Occur"
+    ["Move to Previous Match" occur-prev
+     :help "Move to the Nth (default 1) previous match in an Occur mode 
buffer"]
+    ["Move to Next Match" occur-next
+     :help "Move to the Nth (default 1) next match in an Occur mode buffer"]
+    ["Display Occurrence" occur-mode-display-occurrence
+     :help "Display in another window the occurrence the current line 
describes"]
+    ["Go To Occurrence" occur-mode-goto-occurrence
+     :help "Go to the occurrence the current line describes"]
+    ["Go To Occurrence Other Window" occur-mode-goto-occurrence-other-window
+     :help "Go to the occurrence the current line describes, in another 
window"]
+    "---"
+    ["Edit Occur Buffer" occur-edit-mode
+     :help "Edit the *Occur* buffer and apply changes to the original 
buffers."]
+    ["Rename Occur Buffer" occur-rename-buffer
+     :help "Rename the current *Occur* buffer to *Occur: 
original-buffer-name*."]
+    ["Clone Occur Buffer" clone-buffer
+     :help "Create and return a twin copy of the current *Occur* buffer"]
+    ["Revert Occur Buffer" revert-buffer
+     :help "Replace the text in the *Occur* buffer with the results of 
rerunning occur"]
+    ["Quit Occur Window" quit-window
+     :help "Quit the current *Occur* buffer.  Bury it, and maybe delete the 
selected frame"]
+    ["Kill Occur Buffer" kill-this-buffer
+     :help "Kill the current *Occur* buffer"]
+    "---"
+    ["Auto Occurrence Display"
+     next-error-follow-minor-mode
+     :help "Display another occurrence when moving the cursor"
+     :style toggle
+     :selected (and (boundp 'next-error-follow-minor-mode)
+                    next-error-follow-minor-mode)]))
 
 (defvar occur-mode-map
   (let ((map (make-sparse-keymap)))
diff --git a/lisp/ruler-mode.el b/lisp/ruler-mode.el
index 38283a5..fc9196c 100644
--- a/lisp/ruler-mode.el
+++ b/lisp/ruler-mode.el
@@ -1,4 +1,4 @@
-;;; ruler-mode.el --- display a ruler in the header line
+;;; ruler-mode.el --- display a ruler in the header line  -*- lexical-binding: 
t -*-
 
 ;; Copyright (C) 2001-2021 Free Software Foundation, Inc.
 
@@ -25,7 +25,7 @@
 ;;; Commentary:
 
 ;; This library provides a minor mode to display a ruler in the header
-;; line.  It works from Emacs 21 onwards.
+;; line.
 ;;
 ;; You can use the mouse to change the `fill-column' `comment-column',
 ;; `goal-column', `window-margins' and `tab-stop-list' settings:
@@ -122,7 +122,6 @@ Also allowing to visually change `tab-stop-list' setting 
using
 <C-down-mouse-1> and <C-down-mouse-3> on the ruler to respectively add
 or remove a tab stop.  \\[ruler-mode-toggle-show-tab-stops] or
 <C-down-mouse-2> on the ruler toggles showing/editing of tab stops."
-  :group 'ruler-mode
   :type 'boolean)
 
 ;; IMPORTANT: This function must be defined before the following
@@ -140,7 +139,6 @@ or remove a tab stop.  \\[ruler-mode-toggle-show-tab-stops] 
or
                                            ?\¶
                                          ?\|)
   "Character used at the `fill-column' location."
-  :group 'ruler-mode
   :type '(choice
           (character :tag "Character")
           (integer :tag "Integer char value"
@@ -148,7 +146,6 @@ or remove a tab stop.  \\[ruler-mode-toggle-show-tab-stops] 
or
 
 (defcustom ruler-mode-comment-column-char ?\#
   "Character used at the `comment-column' location."
-  :group 'ruler-mode
   :type '(choice
           (character :tag "Character")
           (integer :tag "Integer char value"
@@ -156,7 +153,6 @@ or remove a tab stop.  \\[ruler-mode-toggle-show-tab-stops] 
or
 
 (defcustom ruler-mode-goal-column-char ?G
   "Character used at the `goal-column' location."
-  :group 'ruler-mode
   :type '(choice
           (character :tag "Character")
           (integer :tag "Integer char value"
@@ -166,7 +162,6 @@ or remove a tab stop.  \\[ruler-mode-toggle-show-tab-stops] 
or
                                               ?\¦
                                             ?\@)
   "Character used at the `current-column' location."
-  :group 'ruler-mode
   :type '(choice
           (character :tag "Character")
           (integer :tag "Integer char value"
@@ -174,7 +169,6 @@ or remove a tab stop.  \\[ruler-mode-toggle-show-tab-stops] 
or
 
 (defcustom ruler-mode-tab-stop-char ?\T
   "Character used at `tab-stop-list' locations."
-  :group 'ruler-mode
   :type '(choice
           (character :tag "Character")
           (integer :tag "Integer char value"
@@ -182,7 +176,6 @@ or remove a tab stop.  \\[ruler-mode-toggle-show-tab-stops] 
or
 
 (defcustom ruler-mode-basic-graduation-char ?\.
   "Character used for basic graduations."
-  :group 'ruler-mode
   :type '(choice
           (character :tag "Character")
           (integer :tag "Integer char value"
@@ -190,7 +183,6 @@ or remove a tab stop.  \\[ruler-mode-toggle-show-tab-stops] 
or
 
 (defcustom ruler-mode-inter-graduation-char ?\!
   "Character used for intermediate graduations."
-  :group 'ruler-mode
   :type '(choice
           (character :tag "Character")
           (integer :tag "Integer char value"
@@ -198,7 +190,6 @@ or remove a tab stop.  \\[ruler-mode-toggle-show-tab-stops] 
or
 
 (defcustom ruler-mode-set-goal-column-ding-flag t
   "Non-nil means do `ding' when `goal-column' is set."
-  :group 'ruler-mode
   :type 'boolean)
 
 (defface ruler-mode-default
@@ -215,8 +206,7 @@ or remove a tab stop.  \\[ruler-mode-toggle-show-tab-stops] 
or
                             :line-width 1
                             :style released-button)
                )))
-  "Default face used by the ruler."
-  :group 'ruler-mode)
+  "Default face used by the ruler.")
 
 (defface ruler-mode-pad
   '((((type tty))
@@ -227,64 +217,56 @@ or remove a tab stop.  
\\[ruler-mode-toggle-show-tab-stops] or
      (:inherit ruler-mode-default
                :background "grey64"
                )))
-  "Face used to pad inactive ruler areas."
-  :group 'ruler-mode)
+  "Face used to pad inactive ruler areas.")
 
 (defface ruler-mode-margins
   '((t
      (:inherit ruler-mode-default
                :foreground "white"
                )))
-  "Face used to highlight margin areas."
-  :group 'ruler-mode)
+  "Face used to highlight margin areas.")
 
 (defface ruler-mode-fringes
   '((t
      (:inherit ruler-mode-default
                :foreground "green"
                )))
-  "Face used to highlight fringes areas."
-  :group 'ruler-mode)
+  "Face used to highlight fringes areas.")
 
 (defface ruler-mode-column-number
   '((t
      (:inherit ruler-mode-default
                :foreground "black"
                )))
-  "Face used to highlight number graduations."
-  :group 'ruler-mode)
+  "Face used to highlight number graduations.")
 
 (defface ruler-mode-fill-column
   '((t
      (:inherit ruler-mode-default
                :foreground "red"
                )))
-  "Face used to highlight the fill column character."
-  :group 'ruler-mode)
+  "Face used to highlight the fill column character.")
 
 (defface ruler-mode-comment-column
   '((t
      (:inherit ruler-mode-default
                :foreground "red"
                )))
-  "Face used to highlight the comment column character."
-  :group 'ruler-mode)
+  "Face used to highlight the comment column character.")
 
 (defface ruler-mode-goal-column
   '((t
      (:inherit ruler-mode-default
                :foreground "red"
                )))
-  "Face used to highlight the goal column character."
-  :group 'ruler-mode)
+  "Face used to highlight the goal column character.")
 
 (defface ruler-mode-tab-stop
   '((t
      (:inherit ruler-mode-default
                :foreground "steelblue"
                )))
-  "Face used to highlight tab stop characters."
-  :group 'ruler-mode)
+  "Face used to highlight tab stop characters.")
 
 (defface ruler-mode-current-column
   '((t
@@ -292,8 +274,7 @@ or remove a tab stop.  \\[ruler-mode-toggle-show-tab-stops] 
or
                :weight bold
                :foreground "yellow"
                )))
-  "Face used to highlight the `current-column' character."
-  :group 'ruler-mode)
+  "Face used to highlight the `current-column' character.")
 
 
 (defsubst ruler-mode-full-window-width ()
@@ -547,15 +528,15 @@ START-EVENT is the mouse click event."
     (define-key km [header-line (control down-mouse-2)]
       #'ruler-mode-toggle-show-tab-stops)
     (define-key km [header-line (shift mouse-1)]
-      'ignore)
+      #'ignore)
     (define-key km [header-line (shift mouse-3)]
-      'ignore)
+      #'ignore)
     (define-key km [header-line (control mouse-1)]
-      'ignore)
+      #'ignore)
     (define-key km [header-line (control mouse-3)]
-      'ignore)
+      #'ignore)
     (define-key km [header-line (control mouse-2)]
-      'ignore)
+      #'ignore)
     km)
   "Keymap for ruler minor mode.")
 
diff --git a/lisp/ses.el b/lisp/ses.el
index d6090f3..6058d48 100644
--- a/lisp/ses.el
+++ b/lisp/ses.el
@@ -332,9 +332,9 @@ column or default printer and then modify its output.")
       next-line-add-newlines transient-mark-mode)
     "Buffer-local variables used by SES."))
 
-(defmacro ses--metaprogramming (exp) (declare (debug t)) (eval exp t))
-(ses--metaprogramming
- `(progn ,@(mapcar (lambda (x) `(defvar ,(or (car-safe x) x))) ses-localvars)))
+(defmacro ses--\,@ (exp) (declare (debug t)) (macroexp-progn (eval exp t)))
+(ses--\,@
+ (mapcar (lambda (x) `(defvar ,(or (car-safe x) x))) ses-localvars))
 
 (defun ses-set-localvars ()
   "Set buffer-local and initialize some SES variables."
@@ -840,31 +840,31 @@ and ARGS and reset `ses-start-time' to the current time."
   "Install VAL as the contents for field FIELD (named by a quoted symbol) of
 cell (ROW,COL).  This is undoable.  The cell's data will be updated through
 `post-command-hook'."
-  `(let ((row ,row)
-         (col ,col)
-         (val ,val))
-     (let* ((cell (ses-get-cell row col))
+  (macroexp-let2 nil row row
+  (macroexp-let2 nil col col
+  (macroexp-let2 nil val val
+    `(let* ((cell (ses-get-cell ,row ,col))
             (change
              ,(let ((field (progn (cl-assert (eq (car field) 'quote))
                                   (cadr field))))
                 (if (eq field 'value)
-                    '(ses-set-with-undo (ses-cell-symbol cell) val)
+                    `(ses-set-with-undo (ses-cell-symbol cell) ,val)
                   ;; (let* ((slots (get 'ses-cell 'cl-struct-slots))
                   ;;        (slot (or (assq field slots)
                   ;;                  (error "Unknown field %S" field)))
                   ;;        (idx (- (length slots)
                   ;;                (length (memq slot slots)))))
-                  ;;   `(ses-aset-with-undo cell ,idx val))
+                  ;;   `(ses-aset-with-undo cell ,idx ,val))
                   (let ((getter (intern-soft (format "ses-cell--%s" field))))
                     `(ses-setter-with-undo
                       (eval-when-compile
                         (cons #',getter
                               (lambda (newval cell)
                                 (setf (,getter cell) newval))))
-                      val cell))))))
+                      ,val cell))))))
        (if change
-           (add-to-list 'ses--deferred-write (cons row col))))
-     nil)) ; Make coverage-tester happy.
+           (add-to-list 'ses--deferred-write (cons ,row ,col)))
+       nil))))) ; Make coverage-tester happy.
 
 (defun ses-cell-set-formula (row col formula)
   "Store a new formula for (ROW . COL) and enqueue the cell for
@@ -2653,9 +2653,7 @@ canceled."
   (barf-if-buffer-read-only)
   (if (eq default t)
       (setq default "")
-    (setq prompt (format "%s (default %S): "
-                        (substring prompt 0 -2)
-                        default)))
+    (setq prompt (format-prompt prompt default)))
   (dolist (key ses-completion-keys)
     (define-key ses-mode-edit-map key 'ses-read-printer-complete-symbol))
   ;; make it globally visible, so that it can be visible from the minibuffer.
@@ -2702,7 +2700,7 @@ right-justified) or a list of one string (will be 
left-justified)."
                ;;Range contains differing printer functions
                (setq default t)
                (throw 'ses-read-cell-printer t))))))
-     (list (ses-read-printer (format "Cell %S printer: " ses--curcell)
+     (list (ses-read-printer (format "Cell %S printer" ses--curcell)
                             default))))
   (unless (eq newval t)
     (ses-begin-change)
@@ -2716,7 +2714,7 @@ See `ses-read-cell-printer' for input forms."
   (interactive
    (let ((col (cdr (ses-sym-rowcol ses--curcell))))
      (ses-check-curcell)
-     (list col (ses-read-printer (format "Column %s printer: "
+     (list col (ses-read-printer (format "Column %s printer"
                                         (ses-column-letter col))
                                 (ses-col-printer col)))))
 
@@ -2731,7 +2729,7 @@ See `ses-read-cell-printer' for input forms."
   "Set the default printer function for cells that have no other.
 See `ses-read-cell-printer' for input forms."
   (interactive
-   (list (ses-read-printer "Default printer: " ses--default-printer)))
+   (list (ses-read-printer "Default printer" ses--default-printer)))
   (unless (eq newval t)
     (ses-begin-change)
     (ses-set-parameter 'ses--default-printer newval)
@@ -3773,7 +3771,7 @@ function is redefined."
      (setq name (intern name))
      (let* ((cur-printer (gethash name ses--local-printer-hashmap))
             (default (and cur-printer (ses--locprn-def cur-printer))))
-            (setq def (ses-read-printer (format "Enter definition of printer 
%S: " name)
+            (setq def (ses-read-printer (format "Enter definition of printer 
%S" name)
                                         default)))
             (list name def)))
 
diff --git a/lisp/shell.el b/lisp/shell.el
index 3212824..cd99b00 100644
--- a/lisp/shell.el
+++ b/lisp/shell.el
@@ -110,11 +110,6 @@
   "Directory support in shell mode."
   :group 'shell)
 
-;; Unused.
-;;; (defgroup shell-faces nil
-;;;   "Faces in shell buffers."
-;;;   :group 'shell)
-
 ;;;###autoload
 (defcustom shell-dumb-shell-regexp (purecopy "cmd\\(proxy\\)?\\.exe")
   "Regexp to match shells that don't save their command history, and
@@ -463,7 +458,7 @@ Shell buffers.  It implements `shell-completion-execonly' 
for
   (if (pcomplete-match "/")
       (pcomplete-here (pcomplete-entries nil
                                         (if shell-completion-execonly
-                                            'file-executable-p)))
+                                            #'file-executable-p)))
     (pcomplete-here
      (nth 2 (shell--command-completion-data)))))
 
@@ -556,8 +551,7 @@ Variables `comint-output-filter-functions', a hook, and
 `comint-scroll-to-bottom-on-input' and `comint-scroll-to-bottom-on-output'
 control whether input and output cause the window to scroll to the end of the
 buffer."
-  (when (called-interactively-p 'any)
-    (error "Can't be called interactively; did you mean `shell-script-mode' 
instead?"))
+  :interactive nil
   (setq comint-prompt-regexp shell-prompt-pattern)
   (shell-completion-vars)
   (setq-local paragraph-separate "\\'")
@@ -744,7 +738,7 @@ Make the shell buffer the current buffer, and return it.
                  (current-buffer)))
   ;; The buffer's window must be correctly set when we call comint
   ;; (so that comint sets the COLUMNS env var properly).
-  (pop-to-buffer buffer)
+  (pop-to-buffer-same-window buffer)
 
   (with-connection-local-variables
    ;; On remote hosts, the local `shell-file-name' might be useless.
diff --git a/lisp/simple.el b/lisp/simple.el
index 0c5bcb6..c48e644 100644
--- a/lisp/simple.el
+++ b/lisp/simple.el
@@ -138,6 +138,10 @@ messages are highlighted; this helps to see what messages 
were visited."
   nil
   "Overlay highlighting the current error message in the `next-error' buffer.")
 
+(defvar global-minor-modes nil
+  "A list of the currently enabled global minor modes.
+This is a list of symbols.")
+
 (defcustom next-error-hook nil
   "List of hook functions run by `next-error' after visiting source file."
   :type 'hook
@@ -234,15 +238,6 @@ all other buffers."
   :group 'next-error
   :version "28.1")
 
-(defcustom next-error-found-function #'ignore
-  "Function called when a next locus is found and displayed.
-Function is called with two arguments: a FROM-BUFFER buffer
-from which next-error navigated, and a target buffer TO-BUFFER."
-  :type '(choice (const :tag "No default" ignore)
-                 (function :tag "Other function"))
-  :group 'next-error
-  :version "27.1")
-
 (defun next-error-buffer-on-selected-frame (&optional _avoid-current
                                                       extra-test-inclusive
                                                       extra-test-exclusive)
@@ -382,6 +377,26 @@ To control which errors are matched, customize the variable
                 (not (eq prev next-error-last-buffer)))
         (message "Current locus from %s" next-error-last-buffer)))))
 
+(defun next-error-quit-window (from-buffer to-buffer)
+  "Quit window of FROM-BUFFER when the prefix arg is 0.
+Intended to be used in `next-error-found-function'."
+  (when (and (eq current-prefix-arg 0) from-buffer
+             (not (eq from-buffer to-buffer)))
+    (let ((window (get-buffer-window from-buffer)))
+      (when (window-live-p window)
+        (quit-restore-window window)))))
+
+(defcustom next-error-found-function #'ignore
+  "Function called when a next locus is found and displayed.
+Function is called with two arguments: a FROM-BUFFER buffer
+from which next-error navigated, and a target buffer TO-BUFFER."
+  :type '(choice (const :tag "No default" ignore)
+                 (const :tag "Quit previous window with M-0"
+                        next-error-quit-window)
+                 (function :tag "Other function"))
+  :group 'next-error
+  :version "27.1")
+
 (defun next-error-found (&optional from-buffer to-buffer)
   "Function to call when the next locus is found and displayed.
 FROM-BUFFER is a buffer from which next-error navigated,
@@ -545,7 +560,7 @@ It must be called via `run-hook-with-args-until-success' 
with no arguments.
 If any function on this hook returns a non-nil value, `delete-selection-mode'
 will act on that value (see `delete-selection-helper') and will
 usually delete the region.  If all the functions on this hook return
-nil, it is an indiction that `self-insert-command' needs the region
+nil, it is an indication that `self-insert-command' needs the region
 untouched by `delete-selection-mode' and will itself do whatever is
 appropriate with the region.
 Any function on `post-self-insert-hook' that acts on the region should
@@ -821,7 +836,10 @@ In programming language modes, this is the same as TAB.
 In some text modes, where TAB inserts a tab, this command indents to the
 column specified by the function `current-left-margin'.
 
-With ARG, perform this action that many times."
+With ARG, perform this action that many times.
+
+Also see `open-line' (bound to \\[open-line]) for a command that
+just inserts a newline without doing any indentation."
   (interactive "*p")
   (delete-horizontal-space t)
   (unless arg
@@ -1274,7 +1292,19 @@ that uses or sets the mark."
 
 ;; Counting lines, one way or another.
 
-(defvar-local goto-line-history nil
+(defcustom goto-line-history-local nil
+  "If this option is nil, `goto-line-history' is shared between all buffers.
+If it is non-nil, each buffer has its own value of this history list.
+
+Note that on changing from non-nil to nil, the former contents of
+`goto-line-history' for each buffer are discarded on use of
+`goto-line' in that buffer."
+  :group 'editing
+  :type 'boolean
+  :safe #'booleanp
+  :version "28.1")
+
+(defvar goto-line-history nil
   "History of values entered with `goto-line'.")
 
 (defun goto-line-read-args (&optional relative)
@@ -1292,6 +1322,11 @@ that uses or sets the mark."
             (if buffer
                 (concat " in " (buffer-name buffer))
               "")))
+      ;; Has the buffer locality of `goto-line-history' changed?
+      (cond ((and goto-line-history-local (not (local-variable-p 
'goto-line-history)))
+             (make-local-variable 'goto-line-history))
+            ((and (not goto-line-history-local) (local-variable-p 
'goto-line-history))
+             (kill-local-variable 'goto-line-history)))
       ;; Read the argument, offering that number (if any) as default.
       (list (read-number (format "Goto%s line%s: "
                                  (if (buffer-narrowed-p)
@@ -1900,55 +1935,137 @@ to get different commands to edit and resubmit."
 (defvar extended-command-history nil)
 (defvar execute-extended-command--last-typed nil)
 
+(defcustom read-extended-command-predicate nil
+  "Predicate to use to determine which commands to include when completing.
+If it's nil, include all the commands.
+If it's a function, it will be called with two parameters: the
+symbol of the command and a buffer.  The predicate should return
+non-nil if the command should be present when doing `M-x TAB'
+in that buffer."
+  :version "28.1"
+  :group 'completion
+  :type '(choice (const :tag "Don't exclude any commands" nil)
+                 (const :tag "Exclude commands irrelevant to current buffer's 
mode"
+                        command-completion-default-include-p)
+                 (function :tag "Other function")))
+
 (defun read-extended-command ()
-  "Read command name to invoke in `execute-extended-command'."
-  (minibuffer-with-setup-hook
-      (lambda ()
-        (add-hook 'post-self-insert-hook
-                  (lambda ()
-                    (setq execute-extended-command--last-typed
-                              (minibuffer-contents)))
-                  nil 'local)
-        (setq-local minibuffer-default-add-function
-            (lambda ()
-              ;; Get a command name at point in the original buffer
-              ;; to propose it after M-n.
-              (let ((def (with-current-buffer
-                             (window-buffer (minibuffer-selected-window))
-                           (and (commandp (function-called-at-point))
-                                (format "%S" (function-called-at-point)))))
-                    (all (sort (minibuffer-default-add-completions)
-                                #'string<)))
-                (if def
-                    (cons def (delete def all))
-                  all)))))
-    ;; Read a string, completing from and restricting to the set of
-    ;; all defined commands.  Don't provide any initial input.
-    ;; Save the command read on the extended-command history list.
-    (completing-read
-     (concat (cond
-             ((eq current-prefix-arg '-) "- ")
-             ((and (consp current-prefix-arg)
-                   (eq (car current-prefix-arg) 4)) "C-u ")
-             ((and (consp current-prefix-arg)
-                   (integerp (car current-prefix-arg)))
-              (format "%d " (car current-prefix-arg)))
-             ((integerp current-prefix-arg)
-              (format "%d " current-prefix-arg)))
-            ;; This isn't strictly correct if `execute-extended-command'
-            ;; is bound to anything else (e.g. [menu]).
-            ;; It could use (key-description (this-single-command-keys)),
-            ;; but actually a prompt other than "M-x" would be confusing,
-            ;; because "M-x" is a well-known prompt to read a command
-            ;; and it serves as a shorthand for "Extended command: ".
-            "M-x ")
-     (lambda (string pred action)
-       (if (and suggest-key-bindings (eq action 'metadata))
-          '(metadata
-            (affixation-function . read-extended-command--affixation)
-            (category . command))
-         (complete-with-action action obarray string pred)))
-     #'commandp t nil 'extended-command-history)))
+  "Read command name to invoke in `execute-extended-command'.
+This function uses the `read-extended-command-predicate' user option."
+  (let ((buffer (current-buffer)))
+    (minibuffer-with-setup-hook
+        (lambda ()
+          (add-hook 'post-self-insert-hook
+                    (lambda ()
+                      (setq execute-extended-command--last-typed
+                            (minibuffer-contents)))
+                    nil 'local)
+          (setq-local minibuffer-default-add-function
+                     (lambda ()
+                       ;; Get a command name at point in the original buffer
+                       ;; to propose it after M-n.
+                       (let ((def
+                               (with-current-buffer
+                                  (window-buffer (minibuffer-selected-window))
+                                (and (commandp (function-called-at-point))
+                                     (format
+                                       "%S" (function-called-at-point)))))
+                             (all (sort (minibuffer-default-add-completions)
+                                         #'string<)))
+                         (if def
+                             (cons def (delete def all))
+                           all)))))
+      ;; Read a string, completing from and restricting to the set of
+      ;; all defined commands.  Don't provide any initial input.
+      ;; Save the command read on the extended-command history list.
+      (completing-read
+       (concat (cond
+               ((eq current-prefix-arg '-) "- ")
+               ((and (consp current-prefix-arg)
+                     (eq (car current-prefix-arg) 4)) "C-u ")
+               ((and (consp current-prefix-arg)
+                     (integerp (car current-prefix-arg)))
+                (format "%d " (car current-prefix-arg)))
+               ((integerp current-prefix-arg)
+                (format "%d " current-prefix-arg)))
+              ;; This isn't strictly correct if `execute-extended-command'
+              ;; is bound to anything else (e.g. [menu]).
+              ;; It could use (key-description (this-single-command-keys)),
+              ;; but actually a prompt other than "M-x" would be confusing,
+              ;; because "M-x" is a well-known prompt to read a command
+              ;; and it serves as a shorthand for "Extended command: ".
+               (if (memq 'shift (event-modifiers last-command-event))
+                  "M-X "
+                "M-x "))
+       (lambda (string pred action)
+         (if (and suggest-key-bindings (eq action 'metadata))
+            '(metadata
+              (affixation-function . read-extended-command--affixation)
+              (category . command))
+           (complete-with-action action obarray string pred)))
+       (lambda (sym)
+         (and (commandp sym)
+              (cond ((null read-extended-command-predicate))
+                    ((functionp read-extended-command-predicate)
+                     ;; Don't let bugs break M-x completion; interpret
+                     ;; them as the absence of a predicate.
+                     (condition-case-unless-debug err
+                         (funcall read-extended-command-predicate sym buffer)
+                       (error (message "read-extended-command-predicate: %s: 
%s"
+                                       sym (error-message-string err))))))))
+       t nil 'extended-command-history))))
+
+(defun command-completion-using-modes-p (symbol buffer)
+  "Say whether SYMBOL has been marked as a mode-specific command in BUFFER."
+  ;; Check the modes.
+  (let ((modes (command-modes symbol)))
+    ;; Common case: Just a single mode.
+    (if (null (cdr modes))
+        (or (provided-mode-derived-p
+             (buffer-local-value 'major-mode buffer) (car modes))
+            (memq (car modes)
+                  (buffer-local-value 'local-minor-modes buffer))
+            (memq (car modes) global-minor-modes))
+      ;; Uncommon case: Multiple modes.
+      (apply #'provided-mode-derived-p
+             (buffer-local-value 'major-mode buffer)
+             modes)
+      (seq-intersection modes
+                        (buffer-local-value 'local-minor-modes buffer)
+                        #'eq)
+      (seq-intersection modes global-minor-modes #'eq))))
+
+(defun command-completion-default-include-p (symbol buffer)
+  "Say whether SYMBOL should be offered as a completion.
+If there's a `completion-predicate' for SYMBOL, the result from
+calling that predicate is called.  If there isn't one, this
+predicate is true if the command SYMBOL is applicable to the
+major mode in BUFFER, or any of the active minor modes in
+BUFFER."
+  (if (get symbol 'completion-predicate)
+      ;; An explicit completion predicate takes precedence.
+      (funcall (get symbol 'completion-predicate) symbol buffer)
+    (or (null (command-modes symbol))
+        (command-completion-using-modes-p symbol buffer))))
+
+(defun command-completion-with-modes-p (modes buffer)
+  "Say whether MODES are in action in BUFFER.
+This is the case if either the major mode is derived from one of MODES,
+or (if one of MODES is a minor mode), if it is switched on in BUFFER."
+  (or (apply #'provided-mode-derived-p
+             (buffer-local-value 'major-mode buffer)
+             modes)
+      ;; It's a minor mode.
+      (seq-intersection modes
+                        (buffer-local-value 'local-minor-modes buffer)
+                        #'eq)
+      (seq-intersection modes global-minor-modes #'eq)))
+
+(defun command-completion-button-p (category buffer)
+  "Return non-nil if there's a button of CATEGORY at point in BUFFER."
+  (with-current-buffer buffer
+    (and (get-text-property (point) 'button)
+         (eq (get-text-property (point) 'category) category))))
 
 (defun read-extended-command--affixation (command-names)
   (with-selected-window (or (minibuffer-selected-window) (selected-window))
@@ -2097,6 +2214,38 @@ invoking, give a prefix argument to 
`execute-extended-command'."
                          suggest-key-bindings
                        2))))))))
 
+(defun execute-extended-command-for-buffer (prefixarg &optional
+                                                      command-name typed)
+  "Query user for a command relevant for the current mode, and then execute it.
+This is like `execute-extended-command', but it limits the
+completions to commands that are particularly relevant to the
+current buffer.  This includes commands that have been marked as
+being specially designed for the current major mode (and enabled
+minor modes), as well as commands bound in the active local key
+maps."
+  (declare (interactive-only command-execute))
+  (interactive
+   (let* ((execute-extended-command--last-typed nil)
+          (keymaps
+           ;; The major mode's keymap and any active minor modes.
+           (cons
+            (current-local-map)
+            (mapcar
+             #'cdr
+             (seq-filter
+              (lambda (elem)
+                (symbol-value (car elem)))
+              minor-mode-map-alist))))
+          (read-extended-command-predicate
+           (lambda (symbol buffer)
+             (or (command-completion-using-modes-p symbol buffer)
+                 (where-is-internal symbol keymaps)))))
+     (list current-prefix-arg
+           (read-extended-command)
+           execute-extended-command--last-typed)))
+  (with-suppressed-warnings ((interactive-only execute-extended-command))
+    (execute-extended-command prefixarg command-name typed)))
+
 (defun command-execute (cmd &optional record-flag keys special)
   ;; BEWARE: Called directly from the C code.
   "Execute CMD as an editor command.
@@ -2694,8 +2843,35 @@ the minibuffer contents."
 
 (defconst undo-equiv-table (make-hash-table :test 'eq :weakness t)
   "Table mapping redo records to the corresponding undo one.
-A redo record for undo-in-region maps to t.
-A redo record for ordinary undo maps to the following (earlier) undo.")
+A redo record for an undo in region maps to 'undo-in-region.
+A redo record for ordinary undo maps to the following (earlier) undo.
+A redo record that undoes to the beginning of the undo list maps to t.
+In the rare case where there are (erroneously) consecutive nil's in
+`buffer-undo-list', `undo' maps the previous valid undo record to
+'empty, if the previous record is a redo record, `undo' doesn't change
+its mapping.
+
+To be clear, a redo record is just an undo record, the only difference
+is that it is created by an undo command (instead of an ordinary buffer
+edit).  Since a record used to undo ordinary change is called undo
+record, a record used to undo an undo is called redo record.
+
+`undo' uses this table to make sure the previous command is `undo'.
+`undo-redo' uses this table to set the correct `pending-undo-list'.
+
+When you undo, `pending-undo-list' shrinks and `buffer-undo-list'
+grows, and Emacs maps the tip of `buffer-undo-list' to the tip of
+`pending-undo-list' in this table.
+
+For example, consider this undo list where each node represents an
+undo record: if we undo from 4, `pending-undo-list' will be at 3,
+`buffer-undo-list' at 5, and 5 will map to 3.
+
+    |
+    3  5
+    | /
+    |/
+    4")
 
 (defvar undo-in-region nil
   "Non-nil if `pending-undo-list' is not just a tail of `buffer-undo-list'.")
@@ -2742,7 +2918,9 @@ as an argument limits undo to changes within the current 
region."
     ;; the next command should not be a "consecutive undo".
     ;; So set `this-command' to something other than `undo'.
     (setq this-command 'undo-start)
-
+    ;; Here we decide whether to break the undo chain.  If the
+    ;; previous command is `undo', we don't call `undo-start', i.e.,
+    ;; don't break the undo chain.
     (unless (and (eq last-command 'undo)
                 (or (eq pending-undo-list t)
                     ;; If something (a timer or filter?) changed the buffer
@@ -2771,7 +2949,7 @@ as an argument limits undo to changes within the current 
region."
        ;; undo-redo-undo-redo-... so skip to the very last equiv.
        (while (let ((next (gethash equiv undo-equiv-table)))
                 (if next (setq equiv next))))
-       (setq pending-undo-list equiv)))
+       (setq pending-undo-list (if (consp equiv) equiv t))))
     (undo-more
      (if (numberp arg)
         (prefix-numeric-value arg)
@@ -2787,11 +2965,17 @@ as an argument limits undo to changes within the 
current region."
       (while (eq (car list) nil)
        (setq list (cdr list)))
       (puthash list
-               ;; Prevent identity mapping.  This can happen if
-               ;; consecutive nils are erroneously in undo list.
-               (if (or undo-in-region (eq list pending-undo-list))
-                   t
-                 pending-undo-list)
+               (cond
+                (undo-in-region 'undo-in-region)
+                ;; Prevent identity mapping.  This can happen if
+                ;; consecutive nils are erroneously in undo list.  It
+                ;; has to map to _something_ so that the next `undo'
+                ;; command recognizes that the previous command is
+                ;; `undo' and doesn't break the undo chain.
+                ((eq list pending-undo-list)
+                 (or (gethash list undo-equiv-table)
+                     'empty))
+                (t pending-undo-list))
               undo-equiv-table))
     ;; Don't specify a position in the undo record for the undo command.
     ;; Instead, undoing this should move point to where the change is.
@@ -2913,8 +3097,7 @@ Return what remains of the list."
                      (and (consp time)
                           (equal (list (car time) (cdr time))
                                  (visited-file-modtime))))
-             (when (fboundp 'unlock-buffer)
-               (unlock-buffer))
+             (unlock-buffer)
              (set-buffer-modified-p nil)))
           ;; Element (nil PROP VAL BEG . END) is property change.
           (`(nil . ,(or `(,prop ,val ,beg . ,end) pcase--dontcare))
@@ -3105,7 +3288,7 @@ list can be applied to the current buffer."
         undo-elt)
     (while ulist
       (when undo-no-redo
-        (while (gethash ulist undo-equiv-table)
+        (while (consp (gethash ulist undo-equiv-table))
           (setq ulist (gethash ulist undo-equiv-table))))
       (setq undo-elt (car ulist))
       (cond
@@ -4540,7 +4723,7 @@ see other processes running on the system, use 
`list-system-processes'."
     (setq prefix-command--last-echo
           (let ((strs nil))
             (run-hook-wrapped 'prefix-command-echo-keystrokes-functions
-                              (lambda (fun) (push (funcall fun) strs)))
+                              (lambda (fun) (push (funcall fun) strs) nil))
             (setq strs (delq nil strs))
             (when strs (mapconcat #'identity strs " "))))))
 
@@ -5884,8 +6067,9 @@ START and END specify the portion of the current buffer 
to be copied."
 
 (defvar activate-mark-hook nil
   "Hook run when the mark becomes active.
-It is also run at the end of a command, if the mark is active and
-it is possible that the region may have changed.")
+It is also run when the region is reactivated, for instance after
+using a command that switches back to a buffer that has an active
+mark.")
 
 (defvar deactivate-mark-hook nil
   "Hook run when the mark becomes inactive.")
diff --git a/lisp/skeleton.el b/lisp/skeleton.el
index 48491e4..c363fb2 100644
--- a/lisp/skeleton.el
+++ b/lisp/skeleton.el
@@ -104,10 +104,10 @@ are integer buffer positions in the reverse order of the 
insertion order.")
 (defvar skeleton-point)
 (defvar skeleton-regions)
 
-(def-edebug-spec skeleton-edebug-spec
-  ([&or null stringp (stringp &rest stringp) [[&not atom] sexp]]
-   &rest &or "n" "_" "-" ">" "@" "&" "!" "|" "resume:"
-   ("quote" def-form) skeleton-edebug-spec def-form))
+(def-edebug-elem-spec 'skeleton-edebug-spec
+  '([&or null stringp (stringp &rest stringp) [[&not atom] sexp]]
+    &rest &or "n" "_" "-" ">" "@" "&" "!" "|" "resume:"
+    ("quote" def-form) skeleton-edebug-spec def-form))
 ;;;###autoload
 (defmacro define-skeleton (command documentation &rest skeleton)
   "Define a user-configurable COMMAND that enters a statement skeleton.
@@ -290,7 +290,8 @@ i.e. we are handling the iterator of a subskeleton, returns 
empty string if
 user didn't modify input.
 While reading, the value of `minibuffer-help-form' is variable `help' if that
 is non-nil or a default string."
-  (let ((minibuffer-help-form (or (if (boundp 'help) (symbol-value 'help))
+  (with-suppressed-warnings ((lexical help)) (defvar help)) ;FIXME: Prefix!
+  (let ((minibuffer-help-form (or (bound-and-true-p help)
                                  (if recursive "\
 As long as you provide input you will insert another subskeleton.
 
diff --git a/lisp/speedbar.el b/lisp/speedbar.el
index e43978f..12e57b1 100644
--- a/lisp/speedbar.el
+++ b/lisp/speedbar.el
@@ -1,4 +1,4 @@
-;;; speedbar --- quick access to files and tags in a frame
+;;; speedbar --- quick access to files and tags in a frame  -*- 
lexical-binding: t; -*-
 
 ;; Copyright (C) 1996-2021 Free Software Foundation, Inc.
 
@@ -106,7 +106,6 @@
 ;;; TODO:
 ;; - Timeout directories we haven't visited in a while.
 
-(require 'easymenu)
 (require 'dframe)
 (require 'ezimage)
 
@@ -142,25 +141,6 @@
 
 ;;; Code:
 
-;; Note: `inversion-test' requires parts of the CEDET package that are
-;; not included with Emacs.
-;;
-;; (defun speedbar-require-version (major minor &optional beta)
-;;   "Non-nil if this version of SPEEDBAR does not satisfy a specific version.
-;; Arguments can be:
-;;
-;;   (MAJOR MINOR &optional BETA)
-;;
-;;   Values MAJOR and MINOR must be integers.  BETA can be an integer, or
-;; excluded if a released version is required.
-;;
-;; It is assumed that if the current version is newer than that specified,
-;; everything passes.  Exceptions occur when known incompatibilities are
-;; introduced."
-;;   (inversion-test 'speedbar
-;;               (concat major "." minor
-;;                       (when beta (concat "beta" beta)))))
-
 (defvar speedbar-initial-expansion-mode-alist
   '(("buffers" speedbar-buffer-easymenu-definition speedbar-buffers-key-map
      speedbar-buffer-buttons)
@@ -309,22 +289,6 @@ A nil value means don't show the file in the list."
   :group 'speedbar
   :type 'boolean)
 
-;;; EVENTUALLY REMOVE THESE
-
-;; When I moved to a repeating timer, I had the horrible misfortune
-;; of losing the ability for adaptive speed choice.  This update
-;; speed currently causes long delays when it should have been turned off.
-(defvar speedbar-update-speed dframe-update-speed)
-(make-obsolete-variable 'speedbar-update-speed
-                       'dframe-update-speed
-                       "speedbar 1.0pre3 (Emacs 23.1)")
-
-(defvar speedbar-navigating-speed dframe-update-speed)
-(make-obsolete-variable 'speedbar-navigating-speed
-                       'dframe-update-speed
-                       "speedbar 1.0pre3 (Emacs 23.1)")
-;;; END REMOVE THESE
-
 (defcustom speedbar-frame-parameters '((minibuffer . nil)
                                       (width . 20)
                                       (border-width . 0)
@@ -1640,7 +1604,7 @@ variable `speedbar-obj-alist'."
 
 (defmacro speedbar-with-writable (&rest forms)
   "Allow the buffer to be writable and evaluate FORMS."
-  (declare (indent 0))
+  (declare (indent 0) (debug t))
   `(let ((inhibit-read-only t))
      ,@forms))
 
@@ -2195,10 +2159,13 @@ passes some tests."
                          ;; way by displaying the range over which we
                          ;; have grouped them.
                          (setq work-list
-                               (cons (cons (concat short-start-name
-                                                   " to "
-                                                   short-end-name)
-                                           short-group-list)
+                               (cons (cons
+                                       (concat short-start-name
+                                              " to " short-end-name)
+                                       (sort (copy-sequence short-group-list)
+                                             (lambda (e1 e2)
+                                               (string< (car e1)
+                                                        (car e2)))))
                                      work-list))))
                     ;; Reset short group list information every time.
                        (setq short-group-list nil
@@ -3280,7 +3247,7 @@ subdirectory chosen will be at INDENT level."
   ;; in case.
   (let ((speedbar-smart-directory-expand-flag nil))
     (speedbar-update-contents))
-  (speedbar-set-timer speedbar-navigating-speed)
+  (speedbar-set-timer dframe-update-speed)
   (setq speedbar-last-selected-file nil)
   (speedbar-stealthy-updates))
 
@@ -3343,7 +3310,7 @@ INDENT is the current indentation level and is unused."
   ;; update contents will change directory without
   ;; having to touch the attached frame.
   (speedbar-update-contents)
-  (speedbar-set-timer speedbar-navigating-speed))
+  (speedbar-set-timer dframe-update-speed))
 
 (defun speedbar-tag-file (text token indent)
   "The cursor is on a selected line.  Expand the tags in the specified file.
@@ -4001,11 +3968,6 @@ TEXT is the buffer's name, TOKEN and INDENT are unused."
   "Speedbar face for separator labels in a display."
   :group 'speedbar-faces)
 
-;; some edebug hooks
-(add-hook 'edebug-setup-hook
-         (lambda ()
-           (def-edebug-spec speedbar-with-writable def-body)))
-
 ;; Fix a font lock problem for some versions of Emacs
 (and (boundp 'font-lock-global-modes)
      font-lock-global-modes
diff --git a/lisp/subr.el b/lisp/subr.el
index 6573090..c2be26a 100644
--- a/lisp/subr.el
+++ b/lisp/subr.el
@@ -64,8 +64,8 @@ For more information, see Info node `(elisp)Declaring 
Functions'."
 
 ;;;; Basic Lisp macros.
 
-(defalias 'not 'null)
-(defalias 'sxhash 'sxhash-equal)
+(defalias 'not #'null)
+(defalias 'sxhash #'sxhash-equal)
 
 (defmacro noreturn (form)
   "Evaluate FORM, expecting it not to return.
@@ -82,14 +82,27 @@ Testcover will raise an error."
   form)
 
 (defmacro def-edebug-spec (symbol spec)
-  "Set the `edebug-form-spec' property of SYMBOL according to SPEC.
+  "Set the Edebug SPEC to use for sexps which have SYMBOL as head.
 Both SYMBOL and SPEC are unevaluated.  The SPEC can be:
 0 (instrument no arguments); t (instrument all arguments);
 a symbol (naming a function with an Edebug specification); or a list.
 The elements of the list describe the argument types; see
 Info node `(elisp)Specification List' for details."
+  (declare (indent 1))
   `(put (quote ,symbol) 'edebug-form-spec (quote ,spec)))
 
+(defun def-edebug-elem-spec (name spec)
+  "Define a new Edebug spec element NAME as shorthand for SPEC.
+The SPEC has to be a list."
+  (declare (indent 1))
+  (when (string-match "\\`[&:]" (symbol-name name))
+    ;; & and : have special meaning in spec element names.
+    (error "Edebug spec name cannot start with '&' or ':'"))
+  (unless (consp spec)
+    (error "Edebug spec has to be a list: %S" spec))
+  (put name 'edebug-elem-spec spec))
+
+
 (defmacro lambda (&rest cdr)
   "Return an anonymous function.
 Under dynamic binding, a call of the form (lambda ARGS DOCSTRING
@@ -360,10 +373,18 @@ PREFIX is a string, and defaults to \"g\"."
 
 (defun ignore (&rest _arguments)
   "Do nothing and return nil.
-This function accepts any number of ARGUMENTS, but ignores them."
+This function accepts any number of ARGUMENTS, but ignores them.
+Also see `always'."
+  (declare (completion ignore))
   (interactive)
   nil)
 
+(defun always (&rest _arguments)
+  "Do nothing and return t.
+This function accepts any number of ARGUMENTS, but ignores them.
+Also see `ignore'."
+  t)
+
 ;; Signal a compile-error if the first arg is missing.
 (defun error (&rest args)
   "Signal an error, making a message by passing ARGS to `format-message'.
@@ -772,7 +793,7 @@ If TEST is omitted or nil, `equal' is used."
   (let (found (tail alist) value)
     (while (and tail (not found))
       (let ((elt (car tail)))
-       (when (funcall (or test 'equal) (if (consp elt) (car elt) elt) key)
+       (when (funcall (or test #'equal) (if (consp elt) (car elt) elt) key)
          (setq found t value (if (consp elt) (cdr elt) default))))
       (setq tail (cdr tail)))
     value))
@@ -866,7 +887,9 @@ Example:
 
 (defun remove (elt seq)
   "Return a copy of SEQ with all occurrences of ELT removed.
-SEQ must be a list, vector, or string.  The comparison is done with `equal'."
+SEQ must be a list, vector, or string.  The comparison is done with `equal'.
+Contrary to `delete', this does not use side-effects, and the argument
+SEQ is not modified."
   (declare (side-effect-free t))
   (if (nlistp seq)
       ;; If SEQ isn't a list, there's no need to copy SEQ because
@@ -902,6 +925,7 @@ For an approximate inverse of this, see `key-description'."
 
 (defun undefined ()
   "Beep to tell the user this binding is undefined."
+  (declare (completion ignore))
   (interactive)
   (ding)
   (if defining-kbd-macro
@@ -922,14 +946,14 @@ For an approximate inverse of this, see 
`key-description'."
   "Make MAP override all normally self-inserting keys to be undefined.
 Normally, as an exception, digits and minus-sign are set to make prefix args,
 but optional second arg NODIGITS non-nil treats them like other chars."
-  (define-key map [remap self-insert-command] 'undefined)
+  (define-key map [remap self-insert-command] #'undefined)
   (or nodigits
       (let (loop)
-       (define-key map "-" 'negative-argument)
+       (define-key map "-" #'negative-argument)
        ;; Make plain numbers do numeric args.
        (setq loop ?0)
        (while (<= loop ?9)
-         (define-key map (char-to-string loop) 'digit-argument)
+         (define-key map (char-to-string loop) #'digit-argument)
          (setq loop (1+ loop))))))
 
 (defun make-composed-keymap (maps &optional parent)
@@ -966,8 +990,8 @@ a menu, so this function is not useful for non-menu 
keymaps."
   (setq key
        (if (<= (length key) 1) (aref key 0)
          (setq keymap (lookup-key keymap
-                                  (apply 'vector
-                                         (butlast (mapcar 'identity key)))))
+                                  (apply #'vector
+                                         (butlast (mapcar #'identity key)))))
          (aref key (1- (length key)))))
   (let ((tail keymap) done inserted)
     (while (and (not done) tail)
@@ -1095,7 +1119,7 @@ Subkeymaps may be modified but are not canonicalized."
                      (push (cons key item) bindings)))
                  map)))
     ;; Create the new map.
-    (setq map (funcall (if ranges 'make-keymap 'make-sparse-keymap) prompt))
+    (setq map (funcall (if ranges #'make-keymap #'make-sparse-keymap) prompt))
     (dolist (binding ranges)
       ;; Treat char-ranges specially.  FIXME: need to merge as well.
       (define-key map (vector (car binding)) (cdr binding)))
@@ -1285,6 +1309,7 @@ in a cleaner way with command remapping, like this:
     (define-key map "l" #'downcase-word)
     (define-key map "c" #'capitalize-word)
     (define-key map "x" #'execute-extended-command)
+    (define-key map "X" #'execute-extended-command-for-buffer)
     map)
   "Default keymap for ESC (meta) commands.
 The normal global definition of the character ESC indirects to this keymap.")
@@ -1734,29 +1759,29 @@ be a list of the form returned by `event-start' and 
`event-end'."
 
 ;;;; Alternate names for functions - these are not being phased out.
 
-(defalias 'send-string 'process-send-string)
-(defalias 'send-region 'process-send-region)
-(defalias 'string= 'string-equal)
-(defalias 'string< 'string-lessp)
-(defalias 'string> 'string-greaterp)
-(defalias 'move-marker 'set-marker)
-(defalias 'rplaca 'setcar)
-(defalias 'rplacd 'setcdr)
-(defalias 'beep 'ding) ;preserve lingual purity
-(defalias 'indent-to-column 'indent-to)
-(defalias 'backward-delete-char 'delete-backward-char)
+(defalias 'send-string #'process-send-string)
+(defalias 'send-region #'process-send-region)
+(defalias 'string= #'string-equal)
+(defalias 'string< #'string-lessp)
+(defalias 'string> #'string-greaterp)
+(defalias 'move-marker #'set-marker)
+(defalias 'rplaca #'setcar)
+(defalias 'rplacd #'setcdr)
+(defalias 'beep #'ding) ;preserve lingual purity
+(defalias 'indent-to-column #'indent-to)
+(defalias 'backward-delete-char #'delete-backward-char)
 (defalias 'search-forward-regexp (symbol-function 're-search-forward))
 (defalias 'search-backward-regexp (symbol-function 're-search-backward))
-(defalias 'int-to-string 'number-to-string)
-(defalias 'store-match-data 'set-match-data)
-(defalias 'chmod 'set-file-modes)
-(defalias 'mkdir 'make-directory)
+(defalias 'int-to-string #'number-to-string)
+(defalias 'store-match-data #'set-match-data)
+(defalias 'chmod #'set-file-modes)
+(defalias 'mkdir #'make-directory)
 ;; These are the XEmacs names:
-(defalias 'point-at-eol 'line-end-position)
-(defalias 'point-at-bol 'line-beginning-position)
+(defalias 'point-at-eol #'line-end-position)
+(defalias 'point-at-bol #'line-beginning-position)
 
 (define-obsolete-function-alias 'user-original-login-name
-  'user-login-name "28.1")
+  #'user-login-name "28.1")
 
 
 ;;;; Hook manipulation functions.
@@ -1870,7 +1895,7 @@ one will be removed."
                                         (if local "Buffer-local" "Global"))
                                 fn-alist
                                 nil t)
-                               fn-alist nil nil 'string=)))
+                               fn-alist nil nil #'string=)))
      (list hook function local)))
   (or (boundp hook) (set hook nil))
   (or (default-boundp hook) (set-default hook nil))
@@ -2074,7 +2099,7 @@ can do the job."
                      ,(if append
                           `(setq ,sym (append ,sym (list ,x)))
                         `(push ,x ,sym))))))
-          (if (not (macroexp--compiling-p))
+          (if (not (macroexp-compiling-p))
               code
             `(progn
                (macroexp--funcall-if-compiled ',warnfun)
@@ -2082,9 +2107,9 @@ can do the job."
   (if (cond
        ((null compare-fn)
        (member element (symbol-value list-var)))
-       ((eq compare-fn 'eq)
+       ((eq compare-fn #'eq)
        (memq element (symbol-value list-var)))
-       ((eq compare-fn 'eql)
+       ((eq compare-fn #'eql)
        (memql element (symbol-value list-var)))
        (t
        (let ((lst (symbol-value list-var)))
@@ -2302,7 +2327,8 @@ tho trying to avoid AVOIDED-MODES."
 (defun add-minor-mode (toggle name &optional keymap after toggle-fun)
   "Register a new minor mode.
 
-This is an XEmacs-compatibility function.  Use `define-minor-mode' instead.
+This function shouldn't be used directly -- use `define-minor-mode'
+instead (which will then call this function).
 
 TOGGLE is a symbol that is the name of a buffer-local variable that
 is toggled on or off to say whether the minor mode is active or not.
@@ -2509,13 +2535,13 @@ use `start-file-process'."
 
 (defun process-lines-handling-status (program status-handler &rest args)
   "Execute PROGRAM with ARGS, returning its output as a list of lines.
-If STATUS-HANDLER is non-NIL, it must be a function with one
+If STATUS-HANDLER is non-nil, it must be a function with one
 argument, which will be called with the exit status of the
 program before the output is collected.  If STATUS-HANDLER is
-NIL, an error is signalled if the program returns with a non-zero
+nil, an error is signaled if the program returns with a non-zero
 exit status."
   (with-temp-buffer
-    (let ((status (apply 'call-process program nil (current-buffer) nil args)))
+    (let ((status (apply #'call-process program nil (current-buffer) nil 
args)))
       (if status-handler
          (funcall status-handler status)
        (unless (eq status 0)
@@ -2540,7 +2566,7 @@ Also see `process-lines-ignore-status'."
   "Execute PROGRAM with ARGS, returning its output as a list of lines.
 The exit status of the program is ignored.
 Also see `process-lines'."
-  (apply #'process-lines-handling-status program #'identity args))
+  (apply #'process-lines-handling-status program #'ignore args))
 
 (defun process-live-p (process)
   "Return non-nil if PROCESS is alive.
@@ -2561,7 +2587,7 @@ process."
         (format "Buffer %S has a running process; kill it? "
                 (buffer-name (current-buffer)))))))
 
-(add-hook 'kill-buffer-query-functions 'process-kill-buffer-query-function)
+(add-hook 'kill-buffer-query-functions #'process-kill-buffer-query-function)
 
 ;; process plist management
 
@@ -2749,7 +2775,7 @@ by doing (clear-string STRING)."
             (use-local-map read-passwd-map)
             (setq-local inhibit-modification-hooks nil) ;bug#15501.
            (setq-local show-paren-mode nil)            ;bug#16091.
-            (add-hook 'post-command-hook 'read-password--hide-password nil t))
+            (add-hook 'post-command-hook #'read-password--hide-password nil t))
         (unwind-protect
             (let ((enable-recursive-minibuffers t)
                  (read-hide-char (or read-hide-char ?*)))
@@ -2759,8 +2785,8 @@ by doing (clear-string STRING)."
               ;; Not sure why but it seems that there might be cases where the
               ;; minibuffer is not always properly reset later on, so undo
               ;; whatever we've done here (bug#11392).
-              (remove-hook 'after-change-functions 
'read-password--hide-password
-                           'local)
+              (remove-hook 'after-change-functions
+                           #'read-password--hide-password 'local)
               (kill-local-variable 'post-self-insert-hook)
               ;; And of course, don't keep the sensitive data around.
               (erase-buffer))))))))
@@ -2780,9 +2806,9 @@ This function is used by the `interactive' code letter 
`n'."
     (when default1
       (setq prompt
            (if (string-match "\\(\\):[ \t]*\\'" prompt)
-               (replace-match (format " (default %s)" default1) t t prompt 1)
+               (replace-match (format minibuffer-default-prompt-format 
default1) t t prompt 1)
              (replace-regexp-in-string "[ \t]*\\'"
-                                       (format " (default %s) " default1)
+                                       (format 
minibuffer-default-prompt-format default1)
                                        prompt t t))))
     (while
        (progn
@@ -2790,7 +2816,7 @@ This function is used by the `interactive' code letter 
`n'."
                      prompt nil nil nil (or hist 'read-number-history)
                      (when default
                        (if (consp default)
-                           (mapcar 'number-to-string (delq nil default))
+                           (mapcar #'number-to-string (delq nil default))
                          (number-to-string default))))))
            (condition-case nil
                (setq n (cond
@@ -2808,6 +2834,11 @@ This function is used by the `interactive' code letter 
`n'."
 Otherwise, use the minibuffer.")
 
 (defun read-char-choice (prompt chars &optional inhibit-keyboard-quit)
+  (if (not read-char-choice-use-read-key)
+      (read-char-from-minibuffer prompt chars)
+    (read-char-choice-with-read-key prompt chars inhibit-keyboard-quit)))
+
+(defun read-char-choice-with-read-key (prompt chars &optional 
inhibit-keyboard-quit)
   "Read and return one of CHARS, prompting for PROMPT.
 Any input that is not one of CHARS is ignored.
 
@@ -2817,46 +2848,44 @@ keyboard-quit events while waiting for a valid input.
 If you bind the variable `help-form' to a non-nil value
 while calling this function, then pressing `help-char'
 causes it to evaluate `help-form' and display the result."
-  (if (not read-char-choice-use-read-key)
-      (read-char-from-minibuffer prompt chars)
-    (unless (consp chars)
-      (error "Called `read-char-choice' without valid char choices"))
-    (let (char done show-help (helpbuf " *Char Help*"))
-      (let ((cursor-in-echo-area t)
-            (executing-kbd-macro executing-kbd-macro)
-            (esc-flag nil))
-        (save-window-excursion        ; in case we call help-form-show
-          (while (not done)
-            (unless (get-text-property 0 'face prompt)
-              (setq prompt (propertize prompt 'face 'minibuffer-prompt)))
-            (setq char (let ((inhibit-quit inhibit-keyboard-quit))
-                         (read-key prompt)))
-            (and show-help (buffer-live-p (get-buffer helpbuf))
-                 (kill-buffer helpbuf))
-            (cond
-             ((not (numberp char)))
-             ;; If caller has set help-form, that's enough.
-             ;; They don't explicitly have to add help-char to chars.
-             ((and help-form
-                   (eq char help-char)
-                   (setq show-help t)
-                   (help-form-show)))
-             ((memq char chars)
-              (setq done t))
-             ((and executing-kbd-macro (= char -1))
-              ;; read-event returns -1 if we are in a kbd macro and
-              ;; there are no more events in the macro.  Attempt to
-              ;; get an event interactively.
-              (setq executing-kbd-macro nil))
-             ((not inhibit-keyboard-quit)
-              (cond
-               ((and (null esc-flag) (eq char ?\e))
-                (setq esc-flag t))
-               ((memq char '(?\C-g ?\e))
-                (keyboard-quit))))))))
-      ;; Display the question with the answer.  But without 
cursor-in-echo-area.
-      (message "%s%s" prompt (char-to-string char))
-      char)))
+  (unless (consp chars)
+    (error "Called `read-char-choice' without valid char choices"))
+  (let (char done show-help (helpbuf " *Char Help*"))
+    (let ((cursor-in-echo-area t)
+          (executing-kbd-macro executing-kbd-macro)
+         (esc-flag nil))
+      (save-window-excursion         ; in case we call help-form-show
+       (while (not done)
+         (unless (get-text-property 0 'face prompt)
+           (setq prompt (propertize prompt 'face 'minibuffer-prompt)))
+         (setq char (let ((inhibit-quit inhibit-keyboard-quit))
+                      (read-key prompt)))
+         (and show-help (buffer-live-p (get-buffer helpbuf))
+              (kill-buffer helpbuf))
+         (cond
+          ((not (numberp char)))
+          ;; If caller has set help-form, that's enough.
+          ;; They don't explicitly have to add help-char to chars.
+          ((and help-form
+                (eq char help-char)
+                (setq show-help t)
+                (help-form-show)))
+          ((memq char chars)
+           (setq done t))
+          ((and executing-kbd-macro (= char -1))
+           ;; read-event returns -1 if we are in a kbd macro and
+           ;; there are no more events in the macro.  Attempt to
+           ;; get an event interactively.
+           (setq executing-kbd-macro nil))
+          ((not inhibit-keyboard-quit)
+           (cond
+            ((and (null esc-flag) (eq char ?\e))
+             (setq esc-flag t))
+            ((memq char '(?\C-g ?\e))
+             (keyboard-quit))))))))
+    ;; Display the question with the answer.  But without cursor-in-echo-area.
+    (message "%s%s" prompt (char-to-string char))
+    char))
 
 (defun sit-for (seconds &optional nodisp obsolete)
   "Redisplay, then wait for SECONDS seconds.  Stop when input is available.
@@ -2944,13 +2973,13 @@ If there is a natural number at point, use it as 
default."
   (let ((map (make-sparse-keymap)))
     (set-keymap-parent map minibuffer-local-map)
 
-    (define-key map [remap self-insert-command] 
'read-char-from-minibuffer-insert-char)
+    (define-key map [remap self-insert-command] 
#'read-char-from-minibuffer-insert-char)
 
-    (define-key map [remap recenter-top-bottom] 
'minibuffer-recenter-top-bottom)
-    (define-key map [remap scroll-up-command] 'minibuffer-scroll-up-command)
-    (define-key map [remap scroll-down-command] 
'minibuffer-scroll-down-command)
-    (define-key map [remap scroll-other-window] 
'minibuffer-scroll-other-window)
-    (define-key map [remap scroll-other-window-down] 
'minibuffer-scroll-other-window-down)
+    (define-key map [remap recenter-top-bottom] 
#'minibuffer-recenter-top-bottom)
+    (define-key map [remap scroll-up-command] #'minibuffer-scroll-up-command)
+    (define-key map [remap scroll-down-command] 
#'minibuffer-scroll-down-command)
+    (define-key map [remap scroll-other-window] 
#'minibuffer-scroll-other-window)
+    (define-key map [remap scroll-other-window-down] 
#'minibuffer-scroll-other-window-down)
 
     map)
   "Keymap for the `read-char-from-minibuffer' function.")
@@ -3013,9 +3042,9 @@ There is no need to explicitly add `help-char' to CHARS;
                                 (help-form-show)))))
                         (dolist (char chars)
                           (define-key map (vector char)
-                            'read-char-from-minibuffer-insert-char))
+                            #'read-char-from-minibuffer-insert-char))
                         (define-key map [remap self-insert-command]
-                          'read-char-from-minibuffer-insert-other)
+                          #'read-char-from-minibuffer-insert-other)
                         (puthash (list help-form (cons help-char chars))
                                  map read-char-from-minibuffer-map-hash)
                         map))
@@ -3048,26 +3077,26 @@ There is no need to explicitly add `help-char' to CHARS;
     (set-keymap-parent map minibuffer-local-map)
 
     (dolist (symbol '(act act-and-show act-and-exit automatic))
-      (define-key map (vector 'remap symbol) 'y-or-n-p-insert-y))
+      (define-key map (vector 'remap symbol) #'y-or-n-p-insert-y))
 
-    (define-key map [remap skip] 'y-or-n-p-insert-n)
+    (define-key map [remap skip] #'y-or-n-p-insert-n)
 
     (dolist (symbol '(backup undo undo-all edit edit-replacement
                       delete-and-edit ignore self-insert-command))
-      (define-key map (vector 'remap symbol) 'y-or-n-p-insert-other))
+      (define-key map (vector 'remap symbol) #'y-or-n-p-insert-other))
 
-    (define-key map [remap recenter] 'minibuffer-recenter-top-bottom)
-    (define-key map [remap scroll-up] 'minibuffer-scroll-up-command)
-    (define-key map [remap scroll-down] 'minibuffer-scroll-down-command)
-    (define-key map [remap scroll-other-window] 
'minibuffer-scroll-other-window)
-    (define-key map [remap scroll-other-window-down] 
'minibuffer-scroll-other-window-down)
+    (define-key map [remap recenter] #'minibuffer-recenter-top-bottom)
+    (define-key map [remap scroll-up] #'minibuffer-scroll-up-command)
+    (define-key map [remap scroll-down] #'minibuffer-scroll-down-command)
+    (define-key map [remap scroll-other-window] 
#'minibuffer-scroll-other-window)
+    (define-key map [remap scroll-other-window-down] 
#'minibuffer-scroll-other-window-down)
 
-    (define-key map [escape] 'abort-recursive-edit)
+    (define-key map [escape] #'abort-recursive-edit)
     (dolist (symbol '(quit exit exit-prefix))
-      (define-key map (vector 'remap symbol) 'abort-recursive-edit))
+      (define-key map (vector 'remap symbol) #'abort-recursive-edit))
 
     ;; FIXME: try catch-all instead of explicit bindings:
-    ;; (define-key map [remap t] 'y-or-n-p-insert-other)
+    ;; (define-key map [remap t] #'y-or-n-p-insert-other)
 
     map)
   "Keymap that defines additional bindings for `y-or-n-p' answers.")
@@ -3311,7 +3340,7 @@ to `accept-change-group' or `cancel-change-group'."
         ;; insertions are ever merged/combined, so we use such a "boundary"
         ;; only when the last change was an insertion and we use the position
         ;; of the last insertion.
-        (when (numberp (caar buffer-undo-list))
+        (when (numberp (car-safe (car buffer-undo-list)))
           (push (cons (caar buffer-undo-list) (caar buffer-undo-list))
                 buffer-undo-list))))))
 
@@ -3364,7 +3393,7 @@ This finishes the change group by reverting all of its 
changes."
 
 ;; For compatibility.
 (define-obsolete-function-alias 'redraw-modeline
-  'force-mode-line-update "24.3")
+  #'force-mode-line-update "24.3")
 
 (defun momentary-string-display (string pos &optional exit-char message)
   "Momentarily display STRING in the buffer at POS.
@@ -3508,7 +3537,7 @@ When in a major mode that does not provide its own
 symbol at point exactly."
   (let ((tag (funcall (or find-tag-default-function
                          (get major-mode 'find-tag-default-function)
-                         'find-tag-default))))
+                         #'find-tag-default))))
     (if tag (regexp-quote tag))))
 
 (defun find-tag-default-as-symbol-regexp ()
@@ -3522,8 +3551,8 @@ symbol at point exactly."
     (if (and tag-regexp
             (eq (or find-tag-default-function
                     (get major-mode 'find-tag-default-function)
-                    'find-tag-default)
-                'find-tag-default))
+                    #'find-tag-default)
+                #'find-tag-default))
        (format "\\_<%s\\_>" tag-regexp)
       tag-regexp)))
 
@@ -3857,7 +3886,7 @@ discouraged."
   (call-process shell-file-name
                infile buffer display
                shell-command-switch
-               (mapconcat 'identity (cons command args) " ")))
+               (mapconcat #'identity (cons command args) " ")))
 
 (defun process-file-shell-command (command &optional infile buffer display
                                           &rest args)
@@ -3869,7 +3898,7 @@ Similar to `call-process-shell-command', but calls 
`process-file'."
   (with-connection-local-variables
    (process-file
     shell-file-name infile buffer display shell-command-switch
-    (mapconcat 'identity (cons command args) " "))))
+    (mapconcat #'identity (cons command args) " "))))
 
 (defun call-shell-region (start end command &optional delete buffer)
   "Send text from START to END as input to an inferior shell running COMMAND.
@@ -4330,6 +4359,8 @@ the specified region.  It must not change
 Additionally, the buffer modifications of BODY are recorded on
 the buffer's undo list as a single (apply ...) entry containing
 the function `undo--wrap-and-run-primitive-undo'."
+  (if (markerp beg) (setq beg (marker-position beg)))
+  (if (markerp end) (setq end (marker-position end)))
   (let ((old-bul buffer-undo-list)
        (end-marker (copy-marker end t))
        result)
@@ -4755,7 +4786,7 @@ Unless optional argument INPLACE is non-nil, return a new 
string."
   "Replace FROMSTRING with TOSTRING in INSTRING each time it occurs."
   (declare (pure t) (side-effect-free t))
   (when (equal fromstring "")
-    (signal 'wrong-length-argument fromstring))
+    (signal 'wrong-length-argument '(0)))
   (let ((start 0)
         (result nil)
         pos)
@@ -4886,8 +4917,8 @@ FILE, a string, is described in the function 
`eval-after-load'."
              ""
            ;; Note: regexp-opt can't be used here, since we need to call
            ;; this before Emacs has been fully started.  2006-05-21
-           (concat "\\(" (mapconcat 'regexp-quote load-suffixes "\\|") "\\)?"))
-         "\\(" (mapconcat 'regexp-quote jka-compr-load-suffixes "\\|")
+           (concat "\\(" (mapconcat #'regexp-quote load-suffixes "\\|") 
"\\)?"))
+         "\\(" (mapconcat #'regexp-quote jka-compr-load-suffixes "\\|")
          "\\)?\\'"))
 
 (defun load-history-filename-element (file-regexp)
@@ -4903,7 +4934,6 @@ Return nil if there isn't one."
              load-elt (and loads (car loads)))))
     load-elt))
 
-(put 'eval-after-load 'lisp-indent-function 1)
 (defun eval-after-load (file form)
   "Arrange that if FILE is loaded, FORM will be run immediately afterwards.
 If FILE is already loaded, evaluate FORM right now.
@@ -4938,7 +4968,8 @@ like `font-lock'.
 This function makes or adds to an entry on `after-load-alist'.
 
 See also `with-eval-after-load'."
-  (declare (compiler-macro
+  (declare (indent 1)
+           (compiler-macro
             (lambda (whole)
               (if (eq 'quote (car-safe form))
                   ;; Quote with lambda so the compiler can look inside.
@@ -5019,14 +5050,10 @@ This function is called directly from the C code."
                             obarray))
           (msg (format "Package %s is deprecated" package))
           (fun (lambda (msg) (message "%s" msg))))
-      ;; Cribbed from cl--compiling-file.
       (when (or (not (fboundp 'byte-compile-warning-enabled-p))
                 (byte-compile-warning-enabled-p 'obsolete package))
         (cond
-        ((and (boundp 'byte-compile--outbuffer)
-              (bufferp (symbol-value 'byte-compile--outbuffer))
-              (equal (buffer-name (symbol-value 'byte-compile--outbuffer))
-                     " *Compiler Output*"))
+        ((bound-and-true-p byte-compile-current-file)
          ;; Don't warn about obsolete files using other obsolete files.
          (unless (and (stringp byte-compile-current-file)
                       (string-match-p "/obsolete/[^/]*\\'"
@@ -5045,7 +5072,7 @@ This function is called directly from the C code."
   "Display delayed warnings from `delayed-warnings-list'.
 Used from `delayed-warnings-hook' (which see)."
   (dolist (warning (nreverse delayed-warnings-list))
-    (apply 'display-warning warning))
+    (apply #'display-warning warning))
   (setq delayed-warnings-list nil))
 
 (defun collapse-delayed-warnings ()
@@ -5378,7 +5405,7 @@ The properties used on SYMBOL are `composefunc', 
`sendfunc',
 `abortfunc', and `hookvar'."
   (put symbol 'composefunc composefunc)
   (put symbol 'sendfunc sendfunc)
-  (put symbol 'abortfunc (or abortfunc 'kill-buffer))
+  (put symbol 'abortfunc (or abortfunc #'kill-buffer))
   (put symbol 'hookvar (or hookvar 'mail-send-hook)))
 
 
@@ -5543,7 +5570,7 @@ To test whether a function can be called interactively, 
use
            (set symbol tail)))))
 
 (define-obsolete-function-alias
-  'set-temporary-overlay-map 'set-transient-map "24.4")
+  'set-temporary-overlay-map #'set-transient-map "24.4")
 
 (defun set-transient-map (map &optional keep-pred on-exit)
   "Set MAP as a temporary keymap taking precedence over other keymaps.
@@ -6171,7 +6198,29 @@ returned list are in the same order as in TREE.
 
 ;; Technically, `flatten-list' is a misnomer, but we provide it here
 ;; for discoverability:
-(defalias 'flatten-list 'flatten-tree)
+(defalias 'flatten-list #'flatten-tree)
+
+(defun string-trim-left (string &optional regexp)
+  "Trim STRING of leading string matching REGEXP.
+
+REGEXP defaults to \"[ \\t\\n\\r]+\"."
+  (if (string-match (concat "\\`\\(?:" (or regexp "[ \t\n\r]+") "\\)") string)
+      (substring string (match-end 0))
+    string))
+
+(defun string-trim-right (string &optional regexp)
+  "Trim STRING of trailing string matching REGEXP.
+
+REGEXP defaults to  \"[ \\t\\n\\r]+\"."
+  (let ((i (string-match-p (concat "\\(?:" (or regexp "[ \t\n\r]+") "\\)\\'")
+                           string)))
+    (if i (substring string 0 i) string)))
+
+(defun string-trim (string &optional trim-left trim-right)
+  "Trim STRING of leading and trailing strings matching TRIM-LEFT and 
TRIM-RIGHT.
+
+TRIM-LEFT and TRIM-RIGHT default to \"[ \\t\\n\\r]+\"."
+  (string-trim-left (string-trim-right string trim-right) trim-left))
 
 ;; The initial anchoring is for better performance in searching matches.
 (defconst regexp-unmatchable "\\`a\\`"
diff --git a/lisp/tab-bar.el b/lisp/tab-bar.el
index 6720d82..2e27b29 100644
--- a/lisp/tab-bar.el
+++ b/lisp/tab-bar.el
@@ -72,6 +72,24 @@
   :version "27.1"
   :group 'tab-bar-faces)
 
+(defface tab-bar-tab-group-current
+  '((t :inherit tab-bar-tab :box nil :weight bold))
+  "Tab bar face for current group tab."
+  :version "28.1"
+  :group 'tab-bar-faces)
+
+(defface tab-bar-tab-group-inactive
+  '((t :inherit (shadow tab-bar-tab-inactive)))
+  "Tab bar face for inactive group tab."
+  :version "28.1"
+  :group 'tab-bar-faces)
+
+(defface tab-bar-tab-ungrouped
+  '((t :inherit (shadow tab-bar-tab-inactive)))
+  "Tab bar face for ungrouped tab when tab groups are used."
+  :version "28.1"
+  :group 'tab-bar-faces)
+
 
 (defcustom tab-bar-select-tab-modifiers '()
   "List of modifier keys for selecting a tab by its index digit.
@@ -89,8 +107,9 @@ Possible modifier keys are `control', `meta', `shift', 
`hyper', `super' and
   :set (lambda (sym val)
          (set-default sym val)
          ;; Reenable the tab-bar with new keybindings
-         (tab-bar-mode -1)
-         (tab-bar-mode 1))
+         (when tab-bar-mode
+           (tab-bar--undefine-keys)
+           (tab-bar--define-keys)))
   :group 'tab-bar
   :version "27.1")
 
@@ -99,18 +118,44 @@ Possible modifier keys are `control', `meta', `shift', 
`hyper', `super' and
   "Install key bindings for switching between tabs if the user has configured 
them."
   (when tab-bar-select-tab-modifiers
     (global-set-key (vector (append tab-bar-select-tab-modifiers (list ?0)))
-                    'tab-bar-switch-to-recent-tab)
-    (dotimes (i 9)
+                    'tab-recent)
+    (dotimes (i 8)
       (global-set-key (vector (append tab-bar-select-tab-modifiers
                                       (list (+ i 1 ?0))))
-                      'tab-bar-select-tab)))
+                      'tab-bar-select-tab))
+    (global-set-key (vector (append tab-bar-select-tab-modifiers (list ?9)))
+                    'tab-last))
   ;; Don't override user customized key bindings
   (unless (global-key-binding [(control tab)])
     (global-set-key [(control tab)] 'tab-next))
   (unless (global-key-binding [(control shift tab)])
     (global-set-key [(control shift tab)] 'tab-previous))
   (unless (global-key-binding [(control shift iso-lefttab)])
-    (global-set-key [(control shift iso-lefttab)] 'tab-previous)))
+    (global-set-key [(control shift iso-lefttab)] 'tab-previous))
+
+  ;; Replace default value with a condition that supports displaying
+  ;; global-mode-string in the tab bar instead of the mode line.
+  (when (and (memq 'tab-bar-format-global tab-bar-format)
+             (member '(global-mode-string ("" global-mode-string " "))
+                     mode-line-misc-info))
+    (setq mode-line-misc-info
+          (append '(global-mode-string
+                    ("" (:eval (if (and tab-bar-mode
+                                        (memq 'tab-bar-format-global
+                                              tab-bar-format))
+                                   "" global-mode-string))
+                     " "))
+                  (remove '(global-mode-string ("" global-mode-string " "))
+                          mode-line-misc-info)))))
+
+(defun tab-bar--undefine-keys ()
+  "Uninstall key bindings previously bound by `tab-bar--define-keys'."
+  (when (eq (global-key-binding [(control tab)]) 'tab-next)
+    (global-unset-key [(control tab)]))
+  (when (eq (global-key-binding [(control shift tab)]) 'tab-previous)
+    (global-unset-key [(control shift tab)]))
+  (when (eq (global-key-binding [(control shift iso-lefttab)]) 'tab-previous)
+    (global-unset-key [(control shift iso-lefttab)])))
 
 (defun tab-bar--load-buttons ()
   "Load the icons for the tab buttons."
@@ -134,32 +179,54 @@ Possible modifier keys are `control', `meta', `shift', 
`hyper', `super' and
                                           :ascent center))
                          tab-bar-close-button)))
 
+(defun tab-bar--tab-bar-lines-for-frame (frame)
+  "Determine and return the value of `tab-bar-lines' for FRAME.
+Return 0 if `tab-bar-mode' is not enabled.  Otherwise return
+either 1 or 0 depending on the value of the customizable variable
+`tab-bar-show', which see."
+  (cond
+   ((not tab-bar-mode) 0)
+   ((not tab-bar-show) 0)
+   ((eq tab-bar-show t) 1)
+   ((natnump tab-bar-show)
+    (if (> (length (funcall tab-bar-tabs-function frame)) tab-bar-show) 1 0))))
+
+(defun tab-bar--update-tab-bar-lines (&optional frames)
+  "Update the `tab-bar-lines' frame parameter in FRAMES.
+If the optional parameter FRAMES is omitted, update only
+the currently selected frame.  If it is `t', update all frames
+as well as the default for new frames.  Otherwise FRAMES should be
+a list of frames to update."
+  (let ((frame-lst (cond ((null frames)
+                          (list (selected-frame)))
+                         ((eq frames t)
+                          (frame-list))
+                         (t frames))))
+    ;; Loop over all frames and update `tab-bar-lines'
+    (dolist (frame frame-lst)
+      (unless (frame-parameter frame 'tab-bar-lines-keep-state)
+        (set-frame-parameter frame 'tab-bar-lines
+                             (tab-bar--tab-bar-lines-for-frame frame)))))
+  ;; Update `default-frame-alist'
+  (when (eq frames t)
+    (setq default-frame-alist
+          (cons (cons 'tab-bar-lines (if (and tab-bar-mode (eq tab-bar-show 
t)) 1 0))
+                (assq-delete-all 'tab-bar-lines default-frame-alist)))))
+
 (define-minor-mode tab-bar-mode
   "Toggle the tab bar in all graphical frames (Tab Bar mode)."
   :global t
   ;; It's defined in C/cus-start, this stops the d-m-m macro defining it again.
   :variable tab-bar-mode
-  (let ((val (if tab-bar-mode 1 0)))
-    (dolist (frame (frame-list))
-      (set-frame-parameter frame 'tab-bar-lines val))
-    ;; If the user has given `default-frame-alist' a `tab-bar-lines'
-    ;; parameter, replace it.
-    (if (assq 'tab-bar-lines default-frame-alist)
-        (setq default-frame-alist
-              (cons (cons 'tab-bar-lines val)
-                    (assq-delete-all 'tab-bar-lines
-                                     default-frame-alist)))))
+
+  ;; Recalculate `tab-bar-lines' for all frames
+  (tab-bar--update-tab-bar-lines t)
+
   (when tab-bar-mode
     (tab-bar--load-buttons))
   (if tab-bar-mode
       (tab-bar--define-keys)
-    ;; Unset only keys bound by tab-bar
-    (when (eq (global-key-binding [(control tab)]) 'tab-next)
-      (global-unset-key [(control tab)]))
-    (when (eq (global-key-binding [(control shift tab)]) 'tab-previous)
-      (global-unset-key [(control shift tab)]))
-    (when (eq (global-key-binding [(control shift iso-lefttab)]) 'tab-previous)
-      (global-unset-key [(control shift iso-lefttab)]))))
+    (tab-bar--undefine-keys)))
 
 (defun tab-bar-handle-mouse (event)
   "Text-mode emulation of switching tabs on the tab bar.
@@ -206,7 +273,9 @@ new frame when the global `tab-bar-mode' is enabled, by 
using
   (add-hook 'after-make-frame-functions 'toggle-frame-tab-bar)"
   (interactive)
   (set-frame-parameter frame 'tab-bar-lines
-                       (if (> (frame-parameter frame 'tab-bar-lines) 0) 0 1)))
+                       (if (> (frame-parameter frame 'tab-bar-lines) 0) 0 1))
+  (set-frame-parameter frame 'tab-bar-lines-keep-state
+                       (not (frame-parameter frame 
'tab-bar-lines-keep-state))))
 
 (defvar tab-bar-map (make-sparse-keymap)
   "Keymap for the tab bar.
@@ -250,17 +319,9 @@ you can use the command `toggle-frame-tab-bar'."
   :initialize 'custom-initialize-default
   :set (lambda (sym val)
          (set-default sym val)
-         ;; Preload button images
-         (tab-bar-mode 1)
-         ;; Then handle each frame individually
-         (dolist (frame (frame-list))
-           (set-frame-parameter
-            frame 'tab-bar-lines
-            (if (or (eq val t)
-                    (and (natnump val)
-                         (> (length (funcall tab-bar-tabs-function frame))
-                            val)))
-                1 0))))
+         (if val
+             (tab-bar-mode 1)
+           (tab-bar--update-tab-bar-lines t)))
   :group 'tab-bar
   :version "27.1")
 
@@ -284,6 +345,20 @@ before calling the command that adds a new tab."
   :group 'tab-bar
   :version "27.1")
 
+(defcustom tab-bar-new-tab-group t
+  "Defines what group to assign to a new tab.
+If nil, don't set a default group automatically.
+If t, inherit the group name from the previous tab.
+If the value is a string, use it as the group name of a new tab.
+If the value is a function, call it with no arguments
+to get the group name."
+  :type '(choice (const    :tag "No automatic group" nil)
+                 (const    :tag "Inherit group from previous tab" t)
+                 (string   :tag "Fixed group name")
+                 (function :tag "Function that returns group name"))
+  :group 'tab-bar
+  :version "28.1")
+
 (defcustom tab-bar-new-button-show t
   "If non-nil, show the \"New tab\" button in the tab bar.
 When this is nil, you can create new tabs with \\[tab-new]."
@@ -352,6 +427,9 @@ and `tab-bar-select-tab-modifiers'."
 (defvar tab-bar-separator nil
   "String that delimits tabs.")
 
+(defun tab-bar-separator ()
+  (or tab-bar-separator (if window-system " " "|")))
+
 
 (defcustom tab-bar-tab-name-function #'tab-bar-tab-name-current
   "Function to get a tab name.
@@ -429,13 +507,13 @@ For example, \\='((tab (name . \"Tab 1\")) (current-tab 
(name . \"Tab 2\")))
 By default, use function `tab-bar-tabs'.")
 
 (defun tab-bar-tabs (&optional frame)
-  "Return a list of tabs belonging to the selected frame.
+  "Return a list of tabs belonging to the FRAME.
 Ensure the frame parameter `tabs' is pre-populated.
 Update the current tab name when it exists.
 Return its existing value or a new value."
   (let ((tabs (frame-parameter frame 'tabs)))
     (if tabs
-        (let* ((current-tab (assq 'current-tab tabs))
+        (let* ((current-tab (tab-bar--current-tab-find tabs))
                (current-tab-name (assq 'name current-tab))
                (current-tab-explicit-name (assq 'explicit-name current-tab)))
           (when (and current-tab-name
@@ -444,11 +522,25 @@ Return its existing value or a new value."
             (setf (cdr current-tab-name)
                   (funcall tab-bar-tab-name-function))))
       ;; Create default tabs
-      (setq tabs (list (tab-bar--current-tab)))
-      (set-frame-parameter frame 'tabs tabs))
+      (setq tabs (list (tab-bar--current-tab-make)))
+      (tab-bar-tabs-set tabs frame))
     tabs))
 
+(defun tab-bar-tabs-set (tabs &optional frame)
+  "Set a list of TABS on the FRAME."
+  (set-frame-parameter frame 'tabs tabs))
+
 
+(defcustom tab-bar-tab-face-function #'tab-bar-tab-face-default
+  "Function to define a tab face.
+Function gets one argument: a tab."
+  :type 'function
+  :group 'tab-bar
+  :version "28.1")
+
+(defun tab-bar-tab-face-default (tab)
+  (if (eq (car tab) 'current-tab) 'tab-bar-tab 'tab-bar-tab-inactive))
+
 (defcustom tab-bar-tab-name-format-function #'tab-bar-tab-name-format-default
   "Function to format a tab name.
 Function gets two arguments, the tab and its number, and should return
@@ -471,58 +563,216 @@ the formatted tab name to display in the tab bar."
                                (if current-p 'non-selected 'selected)))
                       tab-bar-close-button)
                  ""))
-     'face (if current-p 'tab-bar-tab 'tab-bar-tab-inactive))))
+     'face (funcall tab-bar-tab-face-function tab))))
+
+(defcustom tab-bar-format '(tab-bar-format-history
+                            tab-bar-format-tabs
+                            tab-bar-separator
+                            tab-bar-format-add-tab)
+  "Template for displaying tab bar items.
+Every item in the list is a function that returns
+a string, or a list of menu-item elements, or nil.
+When you add more items `tab-bar-format-align-right' and
+`tab-bar-format-global' to the end, then after enabling
+`display-time-mode' (or any other mode that uses `global-mode-string')
+it will display time aligned to the right on the tab bar instead of
+the mode line.  Replacing `tab-bar-format-tabs' with
+`tab-bar-format-tabs-groups' will group tabs on the tab bar."
+  :type 'hook
+  :options '(tab-bar-format-history
+             tab-bar-format-tabs
+             tab-bar-format-tabs-groups
+             tab-bar-separator
+             tab-bar-format-add-tab
+             tab-bar-format-align-right
+             tab-bar-format-global)
+  :initialize 'custom-initialize-default
+  :set (lambda (sym val)
+         (set-default sym val)
+         (force-mode-line-update))
+  :group 'tab-bar
+  :version "28.1")
+
+(defun tab-bar-format-history ()
+  (when (and tab-bar-history-mode tab-bar-history-buttons-show)
+    `((sep-history-back menu-item ,(tab-bar-separator) ignore)
+      (history-back
+       menu-item ,tab-bar-back-button tab-bar-history-back
+       :help "Click to go back in tab history")
+      (sep-history-forward menu-item ,(tab-bar-separator) ignore)
+      (history-forward
+       menu-item ,tab-bar-forward-button tab-bar-history-forward
+       :help "Click to go forward in tab history"))))
+
+(defun tab-bar--format-tab (tab i)
+  (append
+   `((,(intern (format "sep-%i" i)) menu-item ,(tab-bar-separator) ignore))
+   (cond
+    ((eq (car tab) 'current-tab)
+     `((current-tab
+        menu-item
+        ,(funcall tab-bar-tab-name-format-function tab i)
+        ignore
+        :help "Current tab")))
+    (t
+     `((,(intern (format "tab-%i" i))
+        menu-item
+        ,(funcall tab-bar-tab-name-format-function tab i)
+        ,(or
+          (alist-get 'binding tab)
+          `(lambda ()
+             (interactive)
+             (tab-bar-select-tab ,i)))
+        :help "Click to visit tab"))))
+   `((,(if (eq (car tab) 'current-tab) 'C-current-tab (intern (format 
"C-tab-%i" i)))
+      menu-item ""
+      ,(or
+        (alist-get 'close-binding tab)
+        `(lambda ()
+           (interactive)
+           (tab-bar-close-tab ,i)))))))
+
+(defun tab-bar-format-tabs ()
+  (let ((i 0))
+    (mapcan
+     (lambda (tab)
+       (setq i (1+ i))
+       (tab-bar--format-tab tab i))
+     (funcall tab-bar-tabs-function))))
+
+(defcustom tab-bar-tab-group-function #'tab-bar-tab-group-default
+  "Function to get a tab group name.
+Function gets one argument: a tab."
+  :type 'function
+  :initialize 'custom-initialize-default
+  :set (lambda (sym val)
+         (set-default sym val)
+         (force-mode-line-update))
+  :group 'tab-bar
+  :version "28.1")
+
+(defun tab-bar-tab-group-default (tab)
+  (alist-get 'group tab))
+
+(defcustom tab-bar-tab-group-format-function #'tab-bar-tab-group-format-default
+  "Function to format a tab group name.
+Function gets two arguments, a tab with a group name and its number,
+and should return the formatted tab group name to display in the tab bar."
+  :type 'function
+  :initialize 'custom-initialize-default
+  :set (lambda (sym val)
+         (set-default sym val)
+         (force-mode-line-update))
+  :group 'tab-bar
+  :version "28.1")
+
+(defun tab-bar-tab-group-format-default (tab i)
+  (propertize
+   (concat (if tab-bar-tab-hints (format "%d " i) "")
+           (funcall tab-bar-tab-group-function tab))
+   'face 'tab-bar-tab-group-inactive))
+
+(defcustom tab-bar-tab-group-face-function #'tab-bar-tab-group-face-default
+  "Function to define a tab group face.
+Function gets one argument: a tab."
+  :type 'function
+  :group 'tab-bar
+  :version "28.1")
+
+(defun tab-bar-tab-group-face-default (tab)
+  (if (not (or (eq (car tab) 'current-tab)
+               (funcall tab-bar-tab-group-function tab)))
+      'tab-bar-tab-ungrouped
+    (tab-bar-tab-face-default tab)))
+
+(defun tab-bar--format-tab-group (tab i &optional current-p)
+  (append
+   `((,(intern (format "sep-%i" i)) menu-item ,(tab-bar-separator) ignore))
+   `((,(intern (format "group-%i" i))
+      menu-item
+      ,(if current-p
+           (propertize (funcall tab-bar-tab-group-function tab)
+                       'face 'tab-bar-tab-group-current)
+         (funcall tab-bar-tab-group-format-function tab i))
+      ,(if current-p 'ignore
+         (or
+          (alist-get 'binding tab)
+          `(lambda ()
+             (interactive)
+             (tab-bar-select-tab ,i))))
+      :help "Click to visit group"))))
+
+(defun tab-bar-format-tabs-groups ()
+  (let* ((tabs (funcall tab-bar-tabs-function))
+         (current-group (funcall tab-bar-tab-group-function
+                                 (tab-bar--current-tab-find tabs)))
+         (previous-group nil)
+         (i 0))
+    (mapcan
+     (lambda (tab)
+       (let ((tab-group (funcall tab-bar-tab-group-function tab)))
+         (setq i (1+ i))
+         (prog1 (cond
+                 ;; Show current group tabs and ungrouped tabs
+                 ((or (equal tab-group current-group) (not tab-group))
+                  (append
+                   ;; Prepend current group name before first tab
+                   (when (and (not (equal previous-group tab-group)) tab-group)
+                     (tab-bar--format-tab-group tab i t))
+                   ;; Override default tab faces to use group faces
+                   (let ((tab-bar-tab-face-function 
tab-bar-tab-group-face-function))
+                     (tab-bar--format-tab tab i))))
+                 ;; Show first tab of other groups with a group name
+                 ((not (equal previous-group tab-group))
+                  (tab-bar--format-tab-group tab i))
+                 ;; Hide other group tabs
+                 (t nil))
+           (setq previous-group tab-group))))
+     tabs)))
+
+(defun tab-bar-format-add-tab ()
+  (when (and tab-bar-new-button-show tab-bar-new-button)
+    `((add-tab menu-item ,tab-bar-new-button tab-bar-new-tab
+               :help "New tab"))))
+
+(defun tab-bar-format-align-right ()
+  "Align the rest of tab bar items to the right."
+  (let* ((rest (cdr (memq 'tab-bar-format-align-right tab-bar-format)))
+         (rest (tab-bar-format-list rest))
+         (rest (mapconcat (lambda (item) (nth 2 item)) rest ""))
+         (hpos (length rest))
+         (str (propertize " " 'display `(space :align-to (- right ,hpos)))))
+    `((align-right menu-item ,str ignore))))
+
+(defun tab-bar-format-global ()
+  "Format `global-mode-string' to display it in the tab bar.
+When `tab-bar-format-global' is added to `tab-bar-format'
+(possibly appended after `tab-bar-format-align-right'),
+then modes that display information on the mode line
+using `global-mode-string' will display the same text
+on the tab bar instead."
+  `((global menu-item ,(format-mode-line global-mode-string) ignore)))
+
+(defun tab-bar-format-list (format-list)
+  (let ((i 0))
+    (apply #'append
+           (mapcar
+            (lambda (format)
+              (setq i (1+ i))
+              (cond
+               ((functionp format)
+                (let ((ret (funcall format)))
+                  (when (stringp ret)
+                    (setq ret `((,(intern (format "str-%i" i))
+                                 menu-item ,ret ignore))))
+                  ret))))
+            format-list))))
 
 (defun tab-bar-make-keymap-1 ()
   "Generate an actual keymap from `tab-bar-map', without caching."
-  (let* ((separator (or tab-bar-separator (if window-system " " "|")))
-         (i 0)
-         (tabs (funcall tab-bar-tabs-function)))
-    (append
-     '(keymap (mouse-1 . tab-bar-handle-mouse))
-     (when (and tab-bar-history-mode tab-bar-history-buttons-show)
-       `((sep-history-back menu-item ,separator ignore)
-         (history-back
-          menu-item ,tab-bar-back-button tab-bar-history-back
-          :help "Click to go back in tab history")
-         (sep-history-forward menu-item ,separator ignore)
-         (history-forward
-          menu-item ,tab-bar-forward-button tab-bar-history-forward
-          :help "Click to go forward in tab history")))
-     (mapcan
-      (lambda (tab)
-        (setq i (1+ i))
-        (append
-         `((,(intern (format "sep-%i" i)) menu-item ,separator ignore))
-         (cond
-          ((eq (car tab) 'current-tab)
-           `((current-tab
-              menu-item
-              ,(funcall tab-bar-tab-name-format-function tab i)
-              ignore
-              :help "Current tab")))
-          (t
-           `((,(intern (format "tab-%i" i))
-              menu-item
-              ,(funcall tab-bar-tab-name-format-function tab i)
-              ,(or
-                (alist-get 'binding tab)
-                `(lambda ()
-                   (interactive)
-                   (tab-bar-select-tab ,i)))
-              :help "Click to visit tab"))))
-         `((,(if (eq (car tab) 'current-tab) 'C-current-tab (intern (format 
"C-tab-%i" i)))
-            menu-item ""
-            ,(or
-              (alist-get 'close-binding tab)
-              `(lambda ()
-                 (interactive)
-                 (tab-bar-close-tab ,i)))))))
-      tabs)
-     `((sep-add-tab menu-item ,separator ignore))
-     (when (and tab-bar-new-button-show tab-bar-new-button)
-       `((add-tab menu-item ,tab-bar-new-button tab-bar-new-tab
-                  :help "New tab"))))))
+  (append
+   '(keymap (mouse-1 . tab-bar-handle-mouse))
+   (tab-bar-format-list tab-bar-format)))
 
 
 ;; Some window-configuration parameters don't need to be persistent.
@@ -545,8 +795,9 @@ the formatted tab name to display in the tab bar."
 (push '(tabs . frameset-filter-tabs) frameset-filter-alist)
 
 (defun tab-bar--tab (&optional frame)
-  (let* ((tab (assq 'current-tab (frame-parameter frame 'tabs)))
+  (let* ((tab (tab-bar--current-tab-find nil frame))
          (tab-explicit-name (alist-get 'explicit-name tab))
+         (tab-group (alist-get 'group tab))
          (bl  (seq-filter #'buffer-live-p (frame-parameter frame 
'buffer-list)))
          (bbl (seq-filter #'buffer-live-p (frame-parameter frame 
'buried-buffer-list))))
     `(tab
@@ -554,6 +805,7 @@ the formatted tab name to display in the tab bar."
                    (alist-get 'name tab)
                  (funcall tab-bar-tab-name-function)))
       (explicit-name . ,tab-explicit-name)
+      ,@(if tab-group `((group . ,tab-group)))
       (time . ,(float-time))
       (ws . ,(window-state-get
               (frame-root-window (or frame (selected-frame))) 'writable))
@@ -565,16 +817,27 @@ the formatted tab name to display in the tab bar."
       (wc-history-forward . ,(gethash (or frame (selected-frame)) 
tab-bar-history-forward)))))
 
 (defun tab-bar--current-tab (&optional tab frame)
-  ;; `tab` here is an argument meaning 'use tab as template'. This is
+  (tab-bar--current-tab-make (or tab (tab-bar--current-tab-find nil frame))))
+
+(defun tab-bar--current-tab-make (&optional tab)
+  ;; `tab' here is an argument meaning "use tab as template".  This is
   ;; necessary when switching tabs, otherwise the destination tab
-  ;; inherit the current tab's `explicit-name` parameter.
-  (let* ((tab (or tab (assq 'current-tab (frame-parameter frame 'tabs))))
-         (tab-explicit-name (alist-get 'explicit-name tab)))
+  ;; inherits the current tab's `explicit-name' parameter.
+  (let* ((tab-explicit-name (alist-get 'explicit-name tab))
+         (tab-group (if tab
+                        (alist-get 'group tab)
+                      (pcase tab-bar-new-tab-group
+                        ((pred stringp) tab-bar-new-tab-group)
+                        ((pred functionp) (funcall tab-bar-new-tab-group))))))
     `(current-tab
       (name . ,(if tab-explicit-name
                    (alist-get 'name tab)
                  (funcall tab-bar-tab-name-function)))
-      (explicit-name . ,tab-explicit-name))))
+      (explicit-name . ,tab-explicit-name)
+      ,@(if tab-group `((group . ,tab-group))))))
+
+(defun tab-bar--current-tab-find (&optional tabs frame)
+  (assq 'current-tab (or tabs (funcall tab-bar-tabs-function frame))))
 
 (defun tab-bar--current-tab-index (&optional tabs frame)
   (seq-position (or tabs (funcall tab-bar-tabs-function frame))
@@ -607,7 +870,7 @@ the formatted tab name to display in the tab bar."
 When this command is bound to a numeric key (with a prefix or modifier key
 using `tab-bar-select-tab-modifiers'), calling it without an argument
 will translate its bound numeric key to the numeric argument.
-ARG counts from 1."
+ARG counts from 1.  Negative ARG counts tabs from the end of the tab bar."
   (interactive "P")
   (unless (integerp arg)
     (let ((key (event-basic-type last-command-event)))
@@ -617,7 +880,9 @@ ARG counts from 1."
 
   (let* ((tabs (funcall tab-bar-tabs-function))
          (from-index (tab-bar--current-tab-index tabs))
-         (to-index (1- (max 1 (min arg (length tabs))))))
+         (to-index (if (< arg 0) (+ (length tabs) (1+ arg)) arg))
+         (to-index (1- (max 1 (min to-index (length tabs))))))
+
     (unless (eq from-index to-index)
       (let* ((from-tab (tab-bar--tab))
              (to-tab (nth to-index tabs))
@@ -665,13 +930,13 @@ ARG counts from 1."
                      tab-bar-history-forward)))
 
          (ws
-          (window-state-put ws (frame-root-window (selected-frame)) 'safe)))
+          (window-state-put ws nil 'safe)))
 
         (setq tab-bar-history-omit t)
 
         (when from-index
           (setf (nth from-index tabs) from-tab))
-        (setf (nth to-index tabs) (tab-bar--current-tab (nth to-index tabs)))
+        (setf (nth to-index tabs) (tab-bar--current-tab-make (nth to-index 
tabs)))
 
         (unless tab-bar-mode
           (message "Selected tab '%s'" (alist-get 'name to-tab))))
@@ -695,6 +960,12 @@ ARG counts from 1."
     (setq arg 1))
   (tab-bar-switch-to-next-tab (- arg)))
 
+(defun tab-bar-switch-to-last-tab (&optional arg)
+  "Switch to the last tab or ARGth tab from the end of the tab bar."
+  (interactive "p")
+  (tab-bar-select-tab (- (length (funcall tab-bar-tabs-function))
+                         (1- (or arg 1)))))
+
 (defun tab-bar-switch-to-recent-tab (&optional arg)
   "Switch to ARGth most recently visited tab."
   (interactive "p")
@@ -709,7 +980,8 @@ ARG counts from 1."
   "Switch to the tab by NAME.
 Default values are tab names sorted by recency, so you can use \
 \\<minibuffer-local-map>\\[next-history-element]
-to get the name of the last visited tab, the second last, and so on."
+to get the name of the most recently visited tab, the second
+most recent, and so on."
   (interactive
    (let* ((recent-tabs (mapcar (lambda (tab)
                                  (alist-get 'name tab))
@@ -725,20 +997,27 @@ to get the name of the last visited tab, the second last, 
and so on."
 (defun tab-bar-move-tab-to (to-index &optional from-index)
   "Move tab from FROM-INDEX position to new position at TO-INDEX.
 FROM-INDEX defaults to the current tab index.
-FROM-INDEX and TO-INDEX count from 1."
+FROM-INDEX and TO-INDEX count from 1.
+Negative TO-INDEX counts tabs from the end of the tab bar.
+Argument addressing is absolute in contrast to `tab-bar-move-tab'
+where argument addressing is relative."
   (interactive "P")
   (let* ((tabs (funcall tab-bar-tabs-function))
          (from-index (or from-index (1+ (tab-bar--current-tab-index tabs))))
          (from-tab (nth (1- from-index) tabs))
-         (to-index (max 0 (min (1- (or to-index 1)) (1- (length tabs))))))
+         (to-index (if to-index (prefix-numeric-value to-index) 1))
+         (to-index (if (< to-index 0) (+ (length tabs) (1+ to-index)) 
to-index))
+         (to-index (max 0 (min (1- to-index) (1- (length tabs))))))
     (setq tabs (delq from-tab tabs))
     (cl-pushnew from-tab (nthcdr to-index tabs))
-    (set-frame-parameter nil 'tabs tabs)
+    (tab-bar-tabs-set tabs)
     (force-mode-line-update)))
 
 (defun tab-bar-move-tab (&optional arg)
   "Move the current tab ARG positions to the right.
-If a negative ARG, move the current tab ARG positions to the left."
+If a negative ARG, move the current tab ARG positions to the left.
+Argument addressing is relative in contrast to `tab-bar-move-tab-to'
+where argument addressing is absolute."
   (interactive "p")
   (let* ((tabs (funcall tab-bar-tabs-function))
          (from-index (or (tab-bar--current-tab-index tabs) 0))
@@ -773,7 +1052,7 @@ Interactively, ARG selects the ARGth different frame to 
move to."
         (let ((inhibit-message t) ; avoid message about deleted tab
               tab-bar-closed-tabs)
           (tab-bar-close-tab from-index)))
-      (set-frame-parameter to-frame 'tabs to-tabs)
+      (tab-bar-tabs-set to-tabs to-frame)
       (force-mode-line-update t))))
 
 
@@ -795,9 +1074,8 @@ on the tab bar specifying where to insert a new tab."
 
 (defcustom tab-bar-tab-post-open-functions nil
   "List of functions to call after creating a new tab.
-The current tab is supplied as an argument. Any modifications
-made to the tab argument will be applied after all functions are
-called."
+The current tab is supplied as an argument.  Any modifications made
+to the tab argument will be applied after all functions are called."
   :type '(repeat function)
   :group 'tab-bar
   :version "27.1")
@@ -806,7 +1084,9 @@ called."
   "Add a new tab at the absolute position TO-INDEX.
 TO-INDEX counts from 1.  If no TO-INDEX is specified, then add
 a new tab at the position specified by `tab-bar-new-tab-to'.
-
+Negative TO-INDEX counts tabs from the end of the tab bar.
+Argument addressing is absolute in contrast to `tab-bar-new-tab'
+where argument addressing is relative.
 After the tab is created, the hooks in
 `tab-bar-tab-post-open-functions' are run."
   (interactive "P")
@@ -833,35 +1113,38 @@ After the tab is created, the hooks in
 
     (when from-index
       (setf (nth from-index tabs) from-tab))
-    (let ((to-tab (tab-bar--current-tab))
-          (to-index (or (if to-index (1- to-index))
-                        (pcase tab-bar-new-tab-to
-                          ('leftmost 0)
-                          ('rightmost (length tabs))
-                          ('left (or from-index 1))
-                          ('right (1+ (or from-index 0)))
-                          ((pred functionp)
-                           (funcall tab-bar-new-tab-to))))))
+
+    (let* ((to-tab (tab-bar--current-tab-make
+                    (when (eq tab-bar-new-tab-group t)
+                      `((group . ,(alist-get 'group from-tab))))))
+           (to-index (and to-index (prefix-numeric-value to-index)))
+           (to-index (or (if to-index
+                             (if (< to-index 0)
+                                 (+ (length tabs) (1+ to-index))
+                               (1- to-index)))
+                         (pcase tab-bar-new-tab-to
+                           ('leftmost 0)
+                           ('rightmost (length tabs))
+                           ('left (or from-index 1))
+                           ('right (1+ (or from-index 0)))
+                           ((pred functionp)
+                            (funcall tab-bar-new-tab-to))))))
       (setq to-index (max 0 (min (or to-index 0) (length tabs))))
       (cl-pushnew to-tab (nthcdr to-index tabs))
 
       (when (eq to-index 0)
-        ;; pushnew handles the head of tabs but not frame-parameter
-        (set-frame-parameter nil 'tabs tabs))
+        ;; `pushnew' handles the head of tabs but not frame-parameter
+        (tab-bar-tabs-set tabs))
 
       (run-hook-with-args 'tab-bar-tab-post-open-functions
                           (nth to-index tabs)))
 
-    (cond
-     ((eq tab-bar-show t)
-      (tab-bar-mode 1))
-     ((and (natnump tab-bar-show)
-           (> (length (funcall tab-bar-tabs-function)) tab-bar-show)
-           (zerop (frame-parameter nil 'tab-bar-lines)))
-      (progn
-        (tab-bar--load-buttons)
-        (tab-bar--define-keys)
-        (set-frame-parameter nil 'tab-bar-lines 1))))
+    (when tab-bar-show
+      (if (not tab-bar-mode)
+          ;; Turn on `tab-bar-mode' since a tab was created.
+          ;; Note: this also updates `tab-bar-lines'.
+          (tab-bar-mode 1)
+        (tab-bar--update-tab-bar-lines)))
 
     (force-mode-line-update)
     (unless tab-bar-mode
@@ -870,7 +1153,11 @@ After the tab is created, the hooks in
 (defun tab-bar-new-tab (&optional arg)
   "Create a new tab ARG positions to the right.
 If a negative ARG, create a new tab ARG positions to the left.
-If ARG is zero, create a new tab in place of the current tab."
+If ARG is zero, create a new tab in place of the current tab.
+If no ARG is specified, then add a new tab at the position
+specified by `tab-bar-new-tab-to'.
+Argument addressing is relative in contrast to `tab-bar-new-tab-to'
+where argument addressing is absolute."
   (interactive "P")
   (if arg
       (let* ((tabs (funcall tab-bar-tabs-function))
@@ -879,6 +1166,15 @@ If ARG is zero, create a new tab in place of the current 
tab."
         (tab-bar-new-tab-to (1+ to-index)))
     (tab-bar-new-tab-to)))
 
+(defun tab-bar-duplicate-tab (&optional arg)
+  "Duplicate the current tab to ARG positions to the right.
+If a negative ARG, duplicate the tab to ARG positions to the left.
+If ARG is zero, duplicate the tab in place of the current tab."
+  (interactive "P")
+  (let ((tab-bar-new-tab-choice nil)
+        (tab-bar-new-tab-group t))
+    (tab-bar-new-tab arg)))
+
 
 (defvar tab-bar-closed-tabs nil
   "A list of closed tabs to be able to undo their closing.")
@@ -898,10 +1194,10 @@ If `recent', select the most recently visited tab."
   "Defines what to do when the last tab is closed.
 If nil, do nothing and show a message, like closing the last window or frame.
 If `delete-frame', delete the containing frame, as a web browser would do.
-If `tab-bar-mode-disable', disable tab-bar-mode so that tabs no longer show in
-the frame.
-If the value is a function, call that function with the tab to be closed as an
- argument."
+If `tab-bar-mode-disable', disable tab-bar-mode so that tabs no longer show
+in the frame.
+If the value is a function, call that function with the tab to be closed
+as an argument."
   :type '(choice (const    :tag "Do nothing and show message" nil)
                  (const    :tag "Close the containing frame" delete-frame)
                  (const    :tag "Disable tab-bar-mode" tab-bar-mode-disable)
@@ -912,7 +1208,7 @@ If the value is a function, call that function with the 
tab to be closed as an
 (defcustom tab-bar-tab-prevent-close-functions nil
   "List of functions to call to determine whether to close a tab.
 The tab to be closed and a boolean indicating whether or not it
-is the only tab in the frame are supplied as arguments. If any
+is the only tab in the frame are supplied as arguments.  If any
 function returns a non-nil value, the tab will not be closed."
   :type '(repeat function)
   :group 'tab-bar
@@ -994,13 +1290,10 @@ for the last tab on a frame is determined by
                               (tab-bar--tab)
                             close-tab)))
                 tab-bar-closed-tabs)
-          (set-frame-parameter nil 'tabs (delq close-tab tabs)))
+          (tab-bar-tabs-set (delq close-tab tabs)))
 
-        (when (and (not (zerop (frame-parameter nil 'tab-bar-lines)))
-                   (natnump tab-bar-show)
-                   (<= (length (funcall tab-bar-tabs-function))
-                       tab-bar-show))
-          (set-frame-parameter nil 'tab-bar-lines 0))
+        ;; Recalculate `tab-bar-lines' and update frames
+        (tab-bar--update-tab-bar-lines)
 
         (force-mode-line-update)
         (unless tab-bar-mode
@@ -1019,35 +1312,34 @@ for the last tab on a frame is determined by
   "Close all tabs on the selected frame, except the selected one."
   (interactive)
   (let* ((tabs (funcall tab-bar-tabs-function))
-         (current-index (tab-bar--current-tab-index tabs)))
-    (when current-index
-      (dotimes (index (length tabs))
-        (unless (or (eq index current-index)
+         (current-tab (tab-bar--current-tab-find tabs))
+         (index 0))
+    (when current-tab
+      (dolist (tab tabs)
+        (unless (or (eq tab current-tab)
                     (run-hook-with-args-until-success
-                     'tab-bar-tab-prevent-close-functions
-                     (nth index tabs)
-                     ; last-tab-p logically can't ever be true if we
-                     ; make it this far
+                     'tab-bar-tab-prevent-close-functions tab
+                     ;; `last-tab-p' logically can't ever be true
+                     ;; if we make it this far
                      nil))
           (push `((frame . ,(selected-frame))
                   (index . ,index)
-                  (tab . ,(nth index tabs)))
+                  (tab . ,tab))
                 tab-bar-closed-tabs)
-          (run-hook-with-args 'tab-bar-tab-pre-close-functions (nth index 
tabs) nil)))
-      (set-frame-parameter nil 'tabs (list (nth current-index tabs)))
+          (run-hook-with-args 'tab-bar-tab-pre-close-functions tab nil)
+          (setq tabs (delq tab tabs)))
+        (setq index (1+ index)))
+      (tab-bar-tabs-set tabs)
 
-      (when (and (not (zerop (frame-parameter nil 'tab-bar-lines)))
-                 (natnump tab-bar-show)
-                 (<= (length (funcall tab-bar-tabs-function))
-                     tab-bar-show))
-        (set-frame-parameter nil 'tab-bar-lines 0))
+      ;; Recalculate tab-bar-lines and update frames
+      (tab-bar--update-tab-bar-lines)
 
       (force-mode-line-update)
       (unless tab-bar-mode
         (message "Deleted all other tabs")))))
 
 (defun tab-bar-undo-close-tab ()
-  "Restore the last closed tab."
+  "Restore the most recently closed tab."
   (interactive)
   ;; Pop out closed tabs that were on already deleted frames
   (while (and tab-bar-closed-tabs
@@ -1067,7 +1359,7 @@ for the last tab on a frame is determined by
           (cl-pushnew tab (nthcdr index tabs))
           (when (eq index 0)
             ;; pushnew handles the head of tabs but not frame-parameter
-            (set-frame-parameter nil 'tabs tabs))
+            (tab-bar-tabs-set tabs))
           (tab-bar-select-tab (1+ index))))
 
     (message "No more closed tabs to undo")))
@@ -1118,6 +1410,109 @@ function `tab-bar-tab-name-function'."
   (tab-bar-rename-tab new-name (1+ (tab-bar--tab-index-by-name tab-name))))
 
 
+;;; Tab groups
+
+(defun tab-bar-move-tab-to-group (&optional tab)
+  "Relocate TAB (or the current tab) closer to its group."
+  (interactive)
+  (let* ((tabs (funcall tab-bar-tabs-function))
+         (tab (or tab (tab-bar--current-tab-find tabs)))
+         (tab-index (tab-bar--tab-index tab))
+         (group (alist-get 'group tab))
+         ;; Beginning position of the same group
+         (beg (seq-position tabs group
+                            (lambda (tb gr)
+                              (and (not (eq tb tab))
+                                   (equal (alist-get 'group tb) gr)))))
+         ;; Size of the same group
+         (len (when beg
+                (seq-position (nthcdr beg tabs) group
+                              (lambda (tb gr)
+                                (not (equal (alist-get 'group tb) gr))))))
+         (pos (when beg
+                (cond
+                 ;; Don't move tab when it's already inside group bounds
+                 ((and len (>= tab-index beg) (<= tab-index (+ beg len))) nil)
+                 ;; Move tab from the right to the group end
+                 ((and len (> tab-index (+ beg len))) (+ beg len 1))
+                 ;; Move tab from the left to the group beginning
+                 ((< tab-index beg) beg)))))
+    (when pos
+      (tab-bar-move-tab-to pos (1+ tab-index)))))
+
+(defcustom tab-bar-tab-post-change-group-functions nil
+  "List of functions to call after changing a tab group.
+The current tab is supplied as an argument."
+  :type 'hook
+  :options '(tab-bar-move-tab-to-group)
+  :group 'tab-bar
+  :version "28.1")
+
+(defun tab-bar-change-tab-group (group-name &optional arg)
+  "Add the tab specified by its absolute position ARG to GROUP-NAME.
+If no ARG is specified, then set the GROUP-NAME for the current tab.
+ARG counts from 1.
+If GROUP-NAME is the empty string, then remove the tab from any group.
+While using this command, you might also want to replace
+`tab-bar-format-tabs' with `tab-bar-format-tabs-groups' in
+`tab-bar-format' to group tabs on the tab bar."
+  (interactive
+   (let* ((tabs (funcall tab-bar-tabs-function))
+          (tab-index (or current-prefix-arg
+                         (1+ (tab-bar--current-tab-index tabs))))
+          (group-name (funcall tab-bar-tab-group-function
+                               (nth (1- tab-index) tabs))))
+     (list (completing-read
+            "Group name for tab (leave blank to remove group): "
+            (delete-dups
+             (delq nil (cons group-name
+                             (mapcar (lambda (tab)
+                                       (funcall tab-bar-tab-group-function 
tab))
+                                     (funcall tab-bar-tabs-function))))))
+           current-prefix-arg)))
+  (let* ((tabs (funcall tab-bar-tabs-function))
+         (tab-index (if arg
+                        (1- (max 0 (min arg (length tabs))))
+                      (tab-bar--current-tab-index tabs)))
+         (tab (nth tab-index tabs))
+         (group (assq 'group tab))
+         (group-new-name (and (> (length group-name) 0) group-name)))
+    (if group
+        (setcdr group group-new-name)
+      (nconc tab `((group . ,group-new-name))))
+
+    (run-hook-with-args 'tab-bar-tab-post-change-group-functions tab)
+
+    (force-mode-line-update)
+    (unless tab-bar-mode
+      (message "Set tab group to '%s'" group-new-name))))
+
+(defun tab-bar-close-group-tabs (group-name)
+  "Close all tabs that belong to GROUP-NAME on the selected frame."
+  (interactive
+   (let ((group-name (funcall tab-bar-tab-group-function
+                              (tab-bar--current-tab-find))))
+     (list (completing-read
+            "Close all tabs with group name: "
+            (delete-dups
+             (delq nil (cons group-name
+                             (mapcar (lambda (tab)
+                                       (funcall tab-bar-tab-group-function 
tab))
+                                     (funcall tab-bar-tabs-function)))))))))
+  (let* ((close-group (and (> (length group-name) 0) group-name))
+         (tab-bar-tab-prevent-close-functions
+          (cons (lambda (tab _last-tab-p)
+                  (not (equal (funcall tab-bar-tab-group-function tab)
+                              close-group)))
+                tab-bar-tab-prevent-close-functions)))
+    (tab-bar-close-other-tabs)
+
+    (when (equal (funcall tab-bar-tab-group-function
+                          (tab-bar--current-tab-find))
+                 close-group)
+      (tab-bar-close-tab))))
+
+
 ;;; Tab history mode
 
 (defvar tab-bar-history-limit 10
@@ -1138,7 +1533,7 @@ function `tab-bar-tab-name-function'."
 (defvar tab-bar-history-old-minibuffer-depth 0
   "Minibuffer depth before the current command.")
 
-(defun tab-bar-history--pre-change ()
+(defun tab-bar--history-pre-change ()
   (setq tab-bar-history-old-minibuffer-depth (minibuffer-depth))
   ;; Store wc before possibly entering the minibuffer
   (when (zerop tab-bar-history-old-minibuffer-depth)
@@ -1221,29 +1616,12 @@ and can restore them."
                                                 :ascent center))
                                tab-bar-forward-button))
 
-        (add-hook 'pre-command-hook 'tab-bar-history--pre-change)
+        (add-hook 'pre-command-hook 'tab-bar--history-pre-change)
         (add-hook 'window-configuration-change-hook 'tab-bar--history-change))
-    (remove-hook 'pre-command-hook 'tab-bar-history--pre-change)
+    (remove-hook 'pre-command-hook 'tab-bar--history-pre-change)
     (remove-hook 'window-configuration-change-hook 'tab-bar--history-change)))
 
 
-;;; Short aliases
-
-(defalias 'tab-new         'tab-bar-new-tab)
-(defalias 'tab-new-to      'tab-bar-new-tab-to)
-(defalias 'tab-close       'tab-bar-close-tab)
-(defalias 'tab-close-other 'tab-bar-close-other-tabs)
-(defalias 'tab-undo        'tab-bar-undo-close-tab)
-(defalias 'tab-select      'tab-bar-select-tab)
-(defalias 'tab-next        'tab-bar-switch-to-next-tab)
-(defalias 'tab-previous    'tab-bar-switch-to-prev-tab)
-(defalias 'tab-recent      'tab-bar-switch-to-recent-tab)
-(defalias 'tab-move        'tab-bar-move-tab)
-(defalias 'tab-move-to     'tab-bar-move-tab-to)
-(defalias 'tab-rename      'tab-bar-rename-tab)
-(defalias 'tab-list        'tab-switcher)
-
-
 ;;; Non-graphical access to frame-local tabs (named window configurations)
 
 (defun tab-switcher ()
@@ -1421,7 +1799,7 @@ Then move up one line.  Prefix arg means move that many 
lines."
           (index . ,(tab-bar--tab-index tab))
           (tab . ,tab))
         tab-bar-closed-tabs)
-  (set-frame-parameter nil 'tabs (delq tab (funcall tab-bar-tabs-function))))
+  (tab-bar-tabs-set (delq tab (funcall tab-bar-tabs-function))))
 
 (defun tab-switcher-execute ()
   "Delete window configurations marked with 
\\<tab-switcher-mode-map>\\[tab-switcher-delete] commands."
@@ -1525,6 +1903,8 @@ a function, then it is called with two arguments: BUFFER 
and ALIST, and
 should return the tab name.  When a `tab-name' entry is omitted, create
 a new tab without an explicit name.
 
+The ALIST entry `tab-group' (string or function) defines the tab group.
+
 If ALIST contains a `reusable-frames' entry, its value determines
 which frames to search for a reusable tab:
   nil -- the selected frame (actually the last non-minibuffer frame)
@@ -1577,6 +1957,8 @@ then it is called with two arguments: BUFFER and ALIST, 
and should return
 the tab name.  When a `tab-name' entry is omitted, create a new tab without
 an explicit name.
 
+The ALIST entry `tab-group' (string or function) defines the tab group.
+
 This is an action function for buffer display, see Info
 node `(elisp) Buffer Display Action Functions'.  It should be
 called only by `display-buffer' or a function directly or
@@ -1588,6 +1970,11 @@ indirectly called by the latter."
         (setq tab-name (funcall tab-name buffer alist)))
       (when tab-name
         (tab-bar-rename-tab tab-name)))
+    (let ((tab-group (alist-get 'tab-group alist)))
+      (when (functionp tab-group)
+        (setq tab-group (funcall tab-group buffer alist)))
+      (when tab-group
+        (tab-bar-change-tab-group tab-group)))
     (window--display-buffer buffer (selected-window) 'tab alist)))
 
 (defun switch-to-buffer-other-tab (buffer-or-name &optional norecord)
@@ -1618,7 +2005,6 @@ Like \\[find-file-other-frame] (which see), but creates a 
new tab."
 (defun find-file-read-only-other-tab (filename &optional wildcards)
   "Edit file FILENAME, in another tab, but don't allow changes.
 Like \\[find-file-other-frame] (which see), but creates a new tab.
-
 Like \\[find-file-other-tab], but marks buffer as read-only.
 Use \\[read-only-mode] to permit editing."
   (interactive
@@ -1648,13 +2034,41 @@ When `switch-to-buffer-obey-display-actions' is non-nil,
    nil "[other-tab]")
   (message "Display next command buffer in a new tab..."))
 
+
+;;; Short aliases and keybindings
+
+(defalias 'tab-new         'tab-bar-new-tab)
+(defalias 'tab-new-to      'tab-bar-new-tab-to)
+(defalias 'tab-duplicate   'tab-bar-duplicate-tab)
+(defalias 'tab-close       'tab-bar-close-tab)
+(defalias 'tab-close-other 'tab-bar-close-other-tabs)
+(defalias 'tab-close-group 'tab-bar-close-group-tabs)
+(defalias 'tab-undo        'tab-bar-undo-close-tab)
+(defalias 'tab-select      'tab-bar-select-tab)
+(defalias 'tab-switch      'tab-bar-switch-to-tab)
+(defalias 'tab-next        'tab-bar-switch-to-next-tab)
+(defalias 'tab-previous    'tab-bar-switch-to-prev-tab)
+(defalias 'tab-last        'tab-bar-switch-to-last-tab)
+(defalias 'tab-recent      'tab-bar-switch-to-recent-tab)
+(defalias 'tab-move        'tab-bar-move-tab)
+(defalias 'tab-move-to     'tab-bar-move-tab-to)
+(defalias 'tab-rename      'tab-bar-rename-tab)
+(defalias 'tab-group       'tab-bar-change-tab-group)
+(defalias 'tab-list        'tab-switcher)
+
+(define-key tab-prefix-map "n" 'tab-duplicate)
+(define-key tab-prefix-map "N" 'tab-new-to)
 (define-key tab-prefix-map "2" 'tab-new)
 (define-key tab-prefix-map "1" 'tab-close-other)
 (define-key tab-prefix-map "0" 'tab-close)
+(define-key tab-prefix-map "u" 'tab-undo)
 (define-key tab-prefix-map "o" 'tab-next)
+(define-key tab-prefix-map "O" 'tab-previous)
 (define-key tab-prefix-map "m" 'tab-move)
+(define-key tab-prefix-map "M" 'tab-move-to)
+(define-key tab-prefix-map "G" 'tab-group)
 (define-key tab-prefix-map "r" 'tab-rename)
-(define-key tab-prefix-map "\r" 'tab-bar-select-tab-by-name)
+(define-key tab-prefix-map "\r" 'tab-switch)
 (define-key tab-prefix-map "b" 'switch-to-buffer-other-tab)
 (define-key tab-prefix-map "f" 'find-file-other-tab)
 (define-key tab-prefix-map "\C-f" 'find-file-other-tab)
diff --git a/lisp/tab-line.el b/lisp/tab-line.el
index 1bdddc2..0d97da8 100644
--- a/lisp/tab-line.el
+++ b/lisp/tab-line.el
@@ -44,6 +44,7 @@ whether the tab is a buffer, and whether the tab is selected."
   :type '(repeat
           (choice (function-item tab-line-tab-face-special)
                   (function-item tab-line-tab-face-inactive-alternating)
+                  (function-item tab-line-tab-face-group)
                   (function :tag "Custom function")))
   :group 'tab-line
   :version "28.1")
@@ -55,29 +56,25 @@ whether the tab is a buffer, and whether the tab is 
selected."
   :version "27.1")
 
 (defface tab-line-tab
-  '((default
-      :inherit tab-line)
+  '((default :inherit tab-line)
     (((class color) (min-colors 88))
      :box (:line-width 1 :style released-button))
-    (t
-     :inverse-video nil))
+    (t :inverse-video nil))
   "Tab line face for selected tab."
   :version "27.1"
   :group 'tab-line-faces)
 
 (defface tab-line-tab-inactive
-  '((default
-      :inherit tab-line-tab)
+  '((default :inherit tab-line-tab)
     (((class color) (min-colors 88))
      :background "grey75")
-    (t
-     :inverse-video t))
+    (t :inverse-video t))
   "Tab line face for non-selected tab."
   :version "27.1"
   :group 'tab-line-faces)
 
 (defface tab-line-tab-inactive-alternate
-  `((t (:inherit tab-line-tab-inactive :background "grey65")))
+  '((t :inherit tab-line-tab-inactive :background "grey65"))
   "Alternate face for inactive tab-line tabs.
 Applied to alternating tabs when option
 `tab-line-tab-face-functions' includes function
@@ -86,18 +83,25 @@ Applied to alternating tabs when option
   :group 'tab-line-faces)
 
 (defface tab-line-tab-special
-  '((default (:weight bold))
+  '((default :weight bold)
     (((supports :slant italic))
-     (:slant italic :weight normal)))
+     :slant italic :weight normal))
   "Face for special (i.e. non-file-backed) tabs.
 Applied when option `tab-line-tab-face-functions' includes
 function `tab-line-tab-face-special'."
   :version "28.1"
   :group 'tab-line-faces)
 
+(defface tab-line-tab-group
+  '((t :inherit tab-line :box nil))
+  "Face for group tabs.
+Applied when option `tab-line-tab-face-functions' includes
+function `tab-line-tab-face-group'."
+  :version "28.1"
+  :group 'tab-line-faces)
+
 (defface tab-line-tab-current
-  '((default
-      :inherit tab-line-tab)
+  '((default :inherit tab-line-tab)
     (((class color) (min-colors 88))
      :background "grey85"))
   "Tab line face for tab with current buffer in selected window."
@@ -105,7 +109,7 @@ function `tab-line-tab-face-special'."
   :group 'tab-line-faces)
 
 (defface tab-line-highlight
-  '((default :inherit tab-line-tab))
+  '((t :inherit tab-line-tab))
   "Tab line face for highlighting."
   :version "27.1"
   :group 'tab-line-faces)
@@ -178,7 +182,7 @@ If the value is a function, call it with no arguments."
 
 (defvar tab-line-new-button
   (propertize " + "
-              'display `(image :type xpm
+              'display '(image :type xpm
                                :file "tabs/new.xpm"
                                :margin (2 . 0)
                                :ascent center)
@@ -206,7 +210,7 @@ If nil, don't show it at all."
 
 (defvar tab-line-close-button
   (propertize " x"
-              'display `(image :type xpm
+              'display '(image :type xpm
                                :file "tabs/close.xpm"
                                :margin (2 . 0)
                                :ascent center)
@@ -217,7 +221,7 @@ If nil, don't show it at all."
 
 (defvar tab-line-left-button
   (propertize " <"
-              'display `(image :type xpm
+              'display '(image :type xpm
                                :file "tabs/left-arrow.xpm"
                                :margin (2 . 0)
                                :ascent center)
@@ -228,7 +232,7 @@ If nil, don't show it at all."
 
 (defvar tab-line-right-button
   (propertize "> "
-              'display `(image :type xpm
+              'display '(image :type xpm
                                :file "tabs/right-arrow.xpm"
                                :margin (2 . 0)
                                :ascent center)
@@ -294,7 +298,10 @@ be displayed, or just a list of strings to display in the 
tab line.
 By default, use function `tab-line-tabs-window-buffers' that
 returns a list of buffers associated with the selected window.
 When `tab-line-tabs-mode-buffers', return a list of buffers
-with the same major mode as the current buffer."
+with the same major mode as the current buffer.
+When `tab-line-tabs-buffer-groups', return a list of buffers
+grouped either by `tab-line-tabs-buffer-group-function', when set,
+or by `tab-line-tabs-buffer-groups'."
   :type '(choice (const :tag "Window buffers"
                         tab-line-tabs-window-buffers)
                  (const :tag "Same mode buffers"
@@ -356,6 +363,11 @@ If the major mode's name string matches REGEXP, use 
GROUPNAME instead.")
           mode))))
 
 (defun tab-line-tabs-buffer-groups ()
+  "Return a list of tabs that should be displayed in the tab line.
+By default return a list of buffers grouped by major mode,
+according to `tab-line-tabs-buffer-groups'.
+If non-nil, `tab-line-tabs-buffer-group-function' is used to
+generate the group name."
   (if (window-parameter nil 'tab-line-groups)
       (let* ((buffers (funcall tab-line-tabs-buffer-list-function))
              (groups
@@ -385,6 +397,7 @@ If the major mode's name string matches REGEXP, use 
GROUPNAME instead.")
                       (set-window-parameter nil 'tab-line-group nil))))
            (group-tab `(tab
                         (name . ,group)
+                        (group-tab . t)
                         (select . ,(lambda ()
                                      (set-window-parameter nil 
'tab-line-groups t)
                                      (set-window-parameter nil 'tab-line-group 
group)
@@ -430,42 +443,56 @@ variable `tab-line-tabs-function'."
             next-buffers)))
 
 
+(defcustom tab-line-tab-name-format-function #'tab-line-tab-name-format-default
+  "Function to format a tab name.
+Function gets two arguments: the tab and a list of all tabs, and
+should return the formatted tab name to display in the tab line."
+  :type 'function
+  :initialize 'custom-initialize-default
+  :set (lambda (sym val)
+         (set-default sym val)
+         (force-mode-line-update))
+  :group 'tab-line
+  :version "28.1")
+
+(defun tab-line-tab-name-format-default (tab tabs)
+  (let* ((buffer-p (bufferp tab))
+         (selected-p (if buffer-p
+                         (eq tab (window-buffer))
+                       (cdr (assq 'selected tab))))
+         (name (if buffer-p
+                   (funcall tab-line-tab-name-function tab tabs)
+                 (cdr (assq 'name tab))))
+         (face (if selected-p
+                   (if (eq (selected-window) (old-selected-window))
+                       'tab-line-tab-current
+                     'tab-line-tab)
+                 'tab-line-tab-inactive)))
+    (dolist (fn tab-line-tab-face-functions)
+      (setf face (funcall fn tab tabs face buffer-p selected-p)))
+    (apply 'propertize
+           (concat (propertize name 'keymap tab-line-tab-map)
+                   (or (and (or buffer-p (assq 'buffer tab) (assq 'close tab))
+                            tab-line-close-button-show
+                            (not (eq tab-line-close-button-show
+                                     (if selected-p 'non-selected 'selected)))
+                            tab-line-close-button)
+                       ""))
+           `(
+             tab ,tab
+             ,@(if selected-p '(selected t))
+             face ,face
+             mouse-face tab-line-highlight))))
+
 (defun tab-line-format-template (tabs)
   "Template for displaying tab line for selected window."
-  (let* ((selected-buffer (window-buffer))
-         (separator (or tab-line-separator (if window-system " " "|")))
+  (let* ((separator (or tab-line-separator (if window-system " " "|")))
          (hscroll (window-parameter nil 'tab-line-hscroll))
          (strings
           (mapcar
            (lambda (tab)
-             (let* ((buffer-p (bufferp tab))
-                    (selected-p (if buffer-p
-                                    (eq tab selected-buffer)
-                                  (cdr (assq 'selected tab))))
-                    (name (if buffer-p
-                              (funcall tab-line-tab-name-function tab tabs)
-                            (cdr (assq 'name tab))))
-                    (face (if selected-p
-                              (if (eq (selected-window) (old-selected-window))
-                                  'tab-line-tab-current
-                                'tab-line-tab)
-                            'tab-line-tab-inactive)))
-               (dolist (fn tab-line-tab-face-functions)
-                 (setf face (funcall fn tab tabs face buffer-p selected-p)))
-               (concat
-                separator
-                (apply 'propertize
-                       (concat (propertize name 'keymap tab-line-tab-map)
-                               (or (and (or buffer-p (assq 'buffer tab) (assq 
'close tab))
-                                        tab-line-close-button-show
-                                        (not (eq tab-line-close-button-show
-                                                 (if selected-p 'non-selected 
'selected)))
-                                        tab-line-close-button) ""))
-                       `(
-                         tab ,tab
-                         ,@(if selected-p '(selected t))
-                         face ,face
-                         mouse-face tab-line-highlight)))))
+             (concat separator
+                     (funcall tab-line-tab-name-format-function tab tabs)))
            tabs))
          (hscroll-data (tab-line-auto-hscroll strings hscroll)))
     (setq hscroll (nth 1 hscroll-data))
@@ -506,6 +533,13 @@ When TAB is a non-file-backed buffer, make FACE inherit 
from
     (setf face `(:inherit (tab-line-tab-special ,face))))
   face)
 
+(defun tab-line-tab-face-group (tab _tabs face _buffer-p _selected-p)
+  "Return FACE for TAB according to whether it's a group tab.
+For use in `tab-line-tab-face-functions'."
+  (when (alist-get 'group-tab tab)
+    (setf face `(:inherit (tab-line-tab-group ,face))))
+  face)
+
 (defvar tab-line-auto-hscroll)
 
 (defun tab-line-format ()
diff --git a/lisp/talk.el b/lisp/talk.el
index 473f8ac..56d36dd 100644
--- a/lisp/talk.el
+++ b/lisp/talk.el
@@ -1,4 +1,4 @@
-;;; talk.el --- allow several users to talk to each other through Emacs
+;;; talk.el --- allow several users to talk to each other through Emacs  -*- 
lexical-binding: t -*-
 
 ;; Copyright (C) 1995, 2001-2021 Free Software Foundation, Inc.
 
@@ -23,7 +23,7 @@
 ;;; Commentary:
 
 ;; This is a multi-user talk package that runs in Emacs.
-;; Use talk-connect to bring a new person into the conversation.
+;; Use `talk-connect' to bring a new person into the conversation.
 
 ;;; Code:
 
diff --git a/lisp/tar-mode.el b/lisp/tar-mode.el
index 89a71ac..fa9b475 100644
--- a/lisp/tar-mode.el
+++ b/lisp/tar-mode.el
@@ -635,54 +635,38 @@ For instance, if mode is #o700, then it produces 
`rwx------'."
     ;; Let mouse-1 follow the link.
     (define-key map [follow-link] 'mouse-face)
 
-    ;; Make menu bar items.
-
     ;; Get rid of the Edit menu bar item to save space.
     (define-key map [menu-bar edit] 'undefined)
 
-    (define-key map [menu-bar immediate]
-      (cons "Immediate" (make-sparse-keymap "Immediate")))
-
-    (define-key map [menu-bar immediate woman]
-      '("Read Man Page (WoMan)" . woman-tar-extract-file))
-    (define-key map [menu-bar immediate view]
-      '("View This File" . tar-view))
-    (define-key map [menu-bar immediate display]
-      '("Display in Other Window" . tar-display-other-window))
-    (define-key map [menu-bar immediate find-file-other-window]
-      '("Find in Other Window" . tar-extract-other-window))
-    (define-key map [menu-bar immediate find-file]
-      '("Find This File" . tar-extract))
-
-    (define-key map [menu-bar mark]
-      (cons "Mark" (make-sparse-keymap "Mark")))
-
-    (define-key map [menu-bar mark unmark-all]
-      '("Unmark All" . tar-clear-modification-flags))
-    (define-key map [menu-bar mark deletion]
-      '("Flag" . tar-flag-deleted))
-    (define-key map [menu-bar mark unmark]
-      '("Unflag" . tar-unflag))
-
-    (define-key map [menu-bar operate]
-      (cons "Operate" (make-sparse-keymap "Operate")))
-
-    (define-key map [menu-bar operate chown]
-      '("Change Owner..." . tar-chown-entry))
-    (define-key map [menu-bar operate chgrp]
-      '("Change Group..." . tar-chgrp-entry))
-    (define-key map [menu-bar operate chmod]
-      '("Change Mode..." . tar-chmod-entry))
-    (define-key map [menu-bar operate rename]
-      '("Rename to..." . tar-rename-entry))
-    (define-key map [menu-bar operate copy]
-      '("Copy to..." . tar-copy))
-    (define-key map [menu-bar operate expunge]
-      '("Expunge Marked Files" . tar-expunge))
-    
     map)
   "Local keymap for Tar mode listings.")
 
+(easy-menu-define tar-mode-immediate-menu tar-mode-map
+  "Immediate menu for Tar mode."
+  '("Immediate"
+    ["Find This File" tar-extract]
+    ["Find in Other Window" tar-extract-other-window]
+    ["Display in Other Window" tar-display-other-window]
+    ["View This File" tar-view]
+    ["Read Man Page (WoMan)" woman-tar-extract-file]))
+
+(easy-menu-define tar-mode-mark-menu tar-mode-map
+  "Mark menu for Tar mode."
+  '("Mark"
+    ["Unflag" tar-unflag]
+    ["Flag" tar-flag-deleted]
+    ["Unmark All" tar-clear-modification-flags]))
+
+(easy-menu-define tar-mode-operate-menu tar-mode-map
+  "Operate menu for Tar mode."
+  '("Operate"
+    ["Expunge Marked Files" tar-expunge]
+    ["Copy to..." tar-copy]
+    ["Rename to..." tar-rename-entry]
+    ["Change Mode..." tar-chmod-entry]
+    ["Change Group..." tar-chgrp-entry]
+    ["Change Owner..." tar-chown-entry]))
+
 
 ;; tar mode is suitable only for specially formatted data.
 (put 'tar-mode 'mode-class 'special)
@@ -701,12 +685,12 @@ For instance, if mode is #o700, then it produces 
`rwx------'."
 (define-derived-mode tar-mode special-mode "Tar"
   "Major mode for viewing a tar file as a dired-like listing of its contents.
 You can move around using the usual cursor motion commands.
-Letters no longer insert themselves.
-Type `e' to pull a file out of the tar file and into its own buffer;
+Letters no longer insert themselves.\\<tar-mode-map>
+Type \\[tar-extract] to pull a file out of the tar file and into its own 
buffer;
 or click mouse-2 on the file's line in the Tar mode buffer.
-Type `c' to copy an entry from the tar file into another file on disk.
+Type \\[tar-copy] to copy an entry from the tar file into another file on disk.
 
-If you edit a sub-file of this archive (as with the `e' command) and
+If you edit a sub-file of this archive (as with the \\[tar-extract] command) 
and
 save it with \\[save-buffer], the contents of that buffer will be
 saved back into the tar-file buffer; in this way you can edit a file
 inside of a tar archive without extracting it and re-archiving it.
diff --git a/lisp/term.el b/lisp/term.el
index 6beb17f..d41895a 100644
--- a/lisp/term.el
+++ b/lisp/term.el
@@ -2535,7 +2535,7 @@ See `term-prompt-regexp'."
 ;; then the filename reader will only accept a file that exists.
 ;;
 ;; A typical use:
-;; (interactive (term-get-source "Compile file: " prev-lisp-dir/file
+;; (interactive (term-get-source "Compile file" prev-lisp-dir/file
 ;;                                 '(lisp-mode) t))
 
 ;; This is pretty stupid about strings.  It decides we're in a string
@@ -2566,9 +2566,7 @@ See `term-prompt-regexp'."
                       (car def)))
         (deffile (if sfile-p (file-name-nondirectory stringfile)
                       (cdr def)))
-        (ans (read-file-name (if deffile (format "%s(default %s) "
-                                                 prompt    deffile)
-                                 prompt)
+        (ans (read-file-name (format-prompt prompt deffile)
                              defdir
                              (concat defdir deffile)
                              mustmatch-p)))
diff --git a/lisp/term/w32-win.el b/lisp/term/w32-win.el
index e845193..687250f 100644
--- a/lisp/term/w32-win.el
+++ b/lisp/term/w32-win.el
@@ -555,6 +555,9 @@ be found in this alist.
 This alist is used by w32font.c when it looks for fonts that can display
 characters from scripts for which no USBs are defined.")
 
+(declare-function x-list-fonts "xfaces.c"
+                  (pattern &optional face frame maximum width))
+
 (defun w32-find-non-USB-fonts (&optional frame size)
   "Compute the value of `w32-non-USB-fonts' for specified SIZE and FRAME.
 FRAME defaults to the selected frame.
diff --git a/lisp/textmodes/artist.el b/lisp/textmodes/artist.el
index e66adb4..dc45a73 100644
--- a/lisp/textmodes/artist.el
+++ b/lisp/textmodes/artist.el
@@ -6,7 +6,7 @@
 ;; Keywords:     mouse
 ;; Old-Version:         1.2.6
 ;; Release-date: 6-Aug-2004
-;; Location:     http://www.lysator.liu.se/~tab/artist/
+;; Location:     https://www.lysator.liu.se/~tab/artist/
 
 ;; Yoni Rabkin <yoni@rabkins.net> contacted the maintainer of this
 ;; file on 19/3/2008, and the maintainer agreed that when a bug is filed in
@@ -481,50 +481,6 @@ This variable is initialized by the 
`artist-make-prev-next-op-alist' function.")
 (defvar artist-arrow-point-1 nil)
 (defvar artist-arrow-point-2 nil)
 
-(defvar artist-menu-map
-  (let ((map (make-sparse-keymap)))
-    (define-key map [spray-chars]
-      '(menu-item "Characters for Spray" artist-select-spray-chars
-                 :help "Choose characters for sprayed by the spray-can"))
-    (define-key map [borders]
-      '(menu-item "Draw Shape Borders" artist-toggle-borderless-shapes
-                 :help "Toggle whether shapes are drawn with borders"
-                 :button (:toggle . (not artist-borderless-shapes))))
-    (define-key map [trimming]
-      '(menu-item "Trim Line Endings" artist-toggle-trim-line-endings
-                 :help "Toggle trimming of line-endings"
-                 :button (:toggle . artist-trim-line-endings)))
-    (define-key map [rubber-band]
-      '(menu-item "Rubber-banding" artist-toggle-rubber-banding
-                 :help "Toggle rubber-banding"
-                 :button (:toggle . artist-rubber-banding)))
-    (define-key map [set-erase]
-      '(menu-item "Character to Erase..." artist-select-erase-char
-                 :help "Choose a specific character to erase"))
-    (define-key map [set-line]
-      '(menu-item "Character for Line..." artist-select-line-char
-                 :help "Choose the character to insert when drawing lines"))
-    (define-key map [set-fill]
-      '(menu-item "Character for Fill..." artist-select-fill-char
-                 :help "Choose the character to insert when filling in 
shapes"))
-    (define-key map [artist-separator] '(menu-item "--"))
-    (dolist (op '(("Vaporize" artist-select-op-vaporize-lines vaporize-lines)
-                 ("Erase" artist-select-op-erase-rectangle erase-rect)
-                 ("Spray-can" artist-select-op-spray-set-size spray-get-size)
-                 ("Text" artist-select-op-text-overwrite text-ovwrt)
-                 ("Ellipse" artist-select-op-circle circle)
-                 ("Poly-line" artist-select-op-straight-poly-line spolyline)
-                 ("Square" artist-select-op-square square)
-                 ("Rectangle" artist-select-op-rectangle rectangle)
-                 ("Line" artist-select-op-straight-line s-line)
-                 ("Pen" artist-select-op-pen-line pen-line)))
-      (define-key map (vector (nth 2 op))
-       `(menu-item ,(nth 0 op)
-                   ,(nth 1 op)
-                   :help ,(format "Draw using the %s style" (nth 0 op))
-                   :button (:radio . (eq artist-curr-go ',(nth 2 op))))))
-    map))
-
 (defvar artist-mode-map
   (let ((map (make-sparse-keymap)))
     (setq artist-mode-map (make-sparse-keymap))
@@ -577,10 +533,50 @@ This variable is initialized by the 
`artist-make-prev-next-op-alist' function.")
     (define-key map "\C-c\C-a\C-y" 'artist-select-op-paste)
     (define-key map "\C-c\C-af"    'artist-select-op-flood-fill)
     (define-key map "\C-c\C-a\C-b" 'artist-submit-bug-report)
-    (define-key map [menu-bar artist] (cons "Artist" artist-menu-map))
     map)
   "Keymap for `artist-mode'.")
 
+(easy-menu-define artist-menu-map artist-mode-map
+  "Menu for `artist-mode'."
+  `("Artist"
+    ,@(mapcar
+       (lambda (op)
+         `[,(nth 0 op) ,(nth 1 op)
+           :help ,(format "Draw using the %s style" (nth 0 op))
+           :style radio
+           :selected (eq artist-curr-go ',(nth 2 op))])
+       '(("Vaporize" artist-select-op-vaporize-lines vaporize-lines)
+         ("Erase" artist-select-op-erase-rectangle erase-rect)
+         ("Spray-can" artist-select-op-spray-set-size spray-get-size)
+         ("Text" artist-select-op-text-overwrite text-ovwrt)
+         ("Ellipse" artist-select-op-circle circle)
+         ("Poly-line" artist-select-op-straight-poly-line spolyline)
+         ("Square" artist-select-op-square square)
+         ("Rectangle" artist-select-op-rectangle rectangle)
+         ("Line" artist-select-op-straight-line s-line)
+         ("Pen" artist-select-op-pen-line pen-line)))
+    "---"
+    ["Character for Fill..." artist-select-fill-char
+     :help "Choose the character to insert when filling in shapes"]
+    ["Character for Line..." artist-select-line-char
+     :help "Choose the character to insert when drawing lines"]
+    ["Character to Erase..." artist-select-erase-char
+     :help "Choose a specific character to erase"]
+    ["Rubber-banding" artist-toggle-rubber-banding
+     :help "Toggle rubber-banding"
+     :style toggle
+     :selected artist-rubber-banding]
+    ["Trim Line Endings" artist-toggle-trim-line-endings
+     :help "Toggle trimming of line-endings"
+     :style toggle
+     :selected artist-trim-line-endings]
+    ["Draw Shape Borders" artist-toggle-borderless-shapes
+     :help "Toggle whether shapes are drawn with borders"
+     :style toggle
+     :selected (not artist-borderless-shapes)]
+    ["Characters for Spray" artist-select-spray-chars
+     :help "Choose characters for sprayed by the spray-can"]))
+
 (defvar artist-replacement-table (make-vector 256 0)
   "Replacement table for `artist-replace-char'.")
 
@@ -3470,7 +3466,7 @@ The Y-RADIUS must be 0, but the X-RADIUS must not be 0."
        (line-char  (if artist-line-char-set artist-line-char ?-))
        (i          0)
        (point-list nil)
-       (fill-info  nil)
+       ;; (fill-info  nil)
        (shape-info (make-vector 2 0)))
     (while (< i width)
       (let* ((line-x (+ left-edge i))
@@ -3483,7 +3479,7 @@ The Y-RADIUS must be 0, but the X-RADIUS must not be 0."
        (setq point-list (append point-list (list new-coord)))
        (setq i (1+ i))))
     (aset shape-info 0 point-list)
-    (aset shape-info 1 fill-info)
+    (aset shape-info 1 nil) ;; fill-info
     (artist-make-2point-object (artist-make-endpoint x1 y1)
                               (artist-make-endpoint x-radius y-radius)
                               shape-info)))
diff --git a/lisp/textmodes/bib-mode.el b/lisp/textmodes/bib-mode.el
index ec21987..e2fd3ec 100644
--- a/lisp/textmodes/bib-mode.el
+++ b/lisp/textmodes/bib-mode.el
@@ -29,6 +29,8 @@
 ;;   bibliography file.  Keys are automagically inserted as you type,
 ;;   and appropriate keys are presented for various kinds of entries.
 
+;; FIXME: Fix the namespace use of this library.
+
 ;;; Code:
 
 (defgroup bib nil
@@ -39,7 +41,7 @@
 
 (defcustom bib-file "~/my-bibliography.bib"
   "Default name of file used by `addbib'."
-    :type 'file)
+  :type 'file)
 
 (defcustom unread-bib-file "~/to-be-read.bib"
    "Default name of file used by `unread-bib' in Bib mode."
@@ -48,10 +50,10 @@
 (defvar bib-mode-map
   (let ((map (make-sparse-keymap)))
     (set-keymap-parent map text-mode-map)
-    (define-key map "\C-M" 'return-key-bib)
-    (define-key map "\C-c\C-u" 'unread-bib)
-    (define-key map "\C-c\C-@" 'mark-bib)
-    (define-key map "\e`" 'abbrev-mode)
+    (define-key map "\C-M" #'return-key-bib)
+    (define-key map "\C-c\C-u" #'unread-bib)
+    (define-key map "\C-c\C-@" #'mark-bib)
+    (define-key map "\e`" #'abbrev-mode)
     map))
 
 (defun addbib ()
diff --git a/lisp/textmodes/bibtex-style.el b/lisp/textmodes/bibtex-style.el
index 66d245f..6d01871 100644
--- a/lisp/textmodes/bibtex-style.el
+++ b/lisp/textmodes/bibtex-style.el
@@ -49,7 +49,7 @@
     "REVERSE" "SORT" "STRINGS"))
 
 (defconst bibtex-style-functions
-  ;; From http://www.eeng.dcu.ie/local-docs/btxdocs/btxhak/btxhak/node4.html.
+  ;; From https://www.eeng.dcu.ie/local-docs/btxdocs/btxhak/btxhak/node4.html.
   '("<" ">" "=" "+" "-" "*" ":="
     "add.period$" "call.type$" "change.case$" "chr.to.int$" "cite$"
     "duplicate$" "empty$" "format.name$" "if$" "int.to.chr$" "int.to.str$"
@@ -70,7 +70,7 @@
   (setq-local outline-regexp "^[a-z]")
   (setq-local imenu-generic-expression
               '((nil "\\<\\(FUNCTION\\|MACRO\\)\\s-+{\\([^}\n]+\\)}" 2)))
-  (setq-local indent-line-function 'bibtex-style-indent-line)
+  (setq-local indent-line-function #'bibtex-style-indent-line)
   (setq-local parse-sexp-ignore-comments t)
   (setq font-lock-defaults
        '(bibtex-style-font-lock-keywords nil t
diff --git a/lisp/textmodes/bibtex.el b/lisp/textmodes/bibtex.el
index a22cd97..f01c66b 100644
--- a/lisp/textmodes/bibtex.el
+++ b/lisp/textmodes/bibtex.el
@@ -1431,7 +1431,7 @@ If `bibtex-expand-strings' is non-nil, BibTeX strings are 
expanded
 for generating the URL.
 Set this variable before loading BibTeX mode.
 
-The following is a complex example, see URL `http://link.aps.org/'.
+The following is a complex example, see URL `https://link.aps.org/'.
 
    (((\"journal\" . \"\\\\=<\\(PR[ABCDEL]?\\|RMP\\)\\\\=>\")
      \"http://link.aps.org/abstract/%s/v%s/p%s\";
@@ -3327,7 +3327,7 @@ Use `bibtex-summary-function' to generate summary."
         (message "%s %s" key summary))))))
 
 (defun bibtex-copy-summary-as-kill (&optional arg)
-  "Push summery of current BibTeX entry to kill ring.
+  "Push summary of current BibTeX entry to kill ring.
 Use `bibtex-summary-function' to generate summary.
 If prefix ARG is non-nil push BibTeX entry's URL to kill ring
 that is generated by calling `bibtex-url'."
diff --git a/lisp/textmodes/conf-mode.el b/lisp/textmodes/conf-mode.el
index d88964a..5f34ae1 100644
--- a/lisp/textmodes/conf-mode.el
+++ b/lisp/textmodes/conf-mode.el
@@ -63,8 +63,7 @@ not align (only setting space according to 
`conf-assignment-space')."
   :type 'boolean)
 
 (defvar conf-mode-map
-  (let ((map (make-sparse-keymap))
-       (menu-map (make-sparse-keymap)))
+  (let ((map (make-sparse-keymap)))
     (define-key map "\C-c\C-u" 'conf-unix-mode)
     (define-key map "\C-c\C-w" 'conf-windows-mode)
     (define-key map "\C-c\C-j" 'conf-javaprop-mode)
@@ -78,52 +77,46 @@ not align (only setting space according to 
`conf-assignment-space')."
     (define-key map "\C-c\"" 'conf-quote-normal)
     (define-key map "\C-c'" 'conf-quote-normal)
     (define-key map "\C-c\C-a" 'conf-align-assignments)
-    (define-key map [menu-bar sh-script] (cons "Conf" menu-map))
-    (define-key menu-map [conf-windows-mode]
-      '(menu-item "Windows mode"
-                 conf-windows-mode
-                 :help "Conf Mode starter for Windows style Conf files"
-                 :button (:radio . (eq major-mode 'conf-windows-mode))))
-    (define-key menu-map [conf-javaprop-mode]
-      '(menu-item "Java properties mode"
-                 conf-javaprop-mode
-                 :help "Conf Mode starter for Java properties files"
-                 :button (:radio . (eq major-mode 'conf-javaprop-mode))))
-    (define-key menu-map [conf-space-keywords]
-      '(menu-item "Space keywords mode..."
-                 conf-space-keywords
-                 :help "Enter Conf Space mode using regexp KEYWORDS to match 
the keywords"
-                 :button (:radio . (eq major-mode 'conf-space-keywords))))
-    (define-key menu-map [conf-ppd-mode]
-      '(menu-item "PPD mode"
-                 conf-ppd-mode
-                 :help "Conf Mode starter for Adobe/CUPS PPD files"
-                 :button (:radio . (eq major-mode 'conf-ppd-mode))))
-    (define-key menu-map [conf-colon-mode]
-      '(menu-item "Colon mode"
-                 conf-colon-mode
-                 :help "Conf Mode starter for Colon files"
-                 :button (:radio . (eq major-mode 'conf-colon-mode))))
-    (define-key menu-map [conf-unix-mode]
-      '(menu-item "Unix mode"
-                 conf-unix-mode
-                 :help "Conf Mode starter for Unix style Conf files"
-                 :button (:radio . (eq major-mode 'conf-unix-mode))))
-    (define-key menu-map [conf-xdefaults-mode]
-      '(menu-item "Xdefaults mode"
-                 conf-xdefaults-mode
-                 :help "Conf Mode starter for Xdefaults files"
-                 :button (:radio . (eq major-mode 'conf-xdefaults-mode))))
-    (define-key menu-map [c-s0] '("--"))
-    (define-key menu-map [conf-quote-normal]
-      '(menu-item "Set quote syntax normal" conf-quote-normal
-                 :help "Set the syntax of \\=' and \" to punctuation"))
-    (define-key menu-map [conf-align-assignments]
-      '(menu-item "Align assignments" conf-align-assignments
-                 :help "Align assignments"))
     map)
   "Local keymap for `conf-mode' buffers.")
 
+(easy-menu-define conf-mode-menu conf-mode-map
+  "Menu for `conf-mode'."
+  '("Conf"
+    ["Align assignments" conf-align-assignments
+     :help "Align assignments"]
+    ["Set quote syntax normal" conf-quote-normal
+     :help "Set the syntax of \\=' and \" to punctuation"]
+    "---"
+    ["Xdefaults mode" conf-xdefaults-mode
+     :help "Conf Mode starter for Xdefaults files"
+     :style radio
+     :selected (eq major-mode 'conf-xdefaults-mode)]
+    ["Unix mode" conf-unix-mode
+     :help "Conf Mode starter for Unix style Conf files"
+     :style radio
+     :selected (eq major-mode 'conf-unix-mode)]
+    ["Colon mode" conf-colon-mode
+     :help "Conf Mode starter for Colon files"
+     :style radio
+     :selected (eq major-mode 'conf-colon-mode)]
+    ["PPD mode" conf-ppd-mode
+     :help "Conf Mode starter for Adobe/CUPS PPD files"
+     :style radio
+     :selected (eq major-mode 'conf-ppd-mode)]
+    ["Space keywords mode..." conf-space-keywords
+     :help "Enter Conf Space mode using regexp KEYWORDS to match the keywords"
+     :style radio
+     :selected (eq major-mode 'conf-space-keywords)]
+    ["Java properties mode" conf-javaprop-mode
+     :help "Conf Mode starter for Java properties files"
+     :style radio
+     :selected (eq major-mode 'conf-javaprop-mode)]
+    ["Windows mode" conf-windows-mode
+     :help "Conf Mode starter for Windows style Conf files"
+     :style radio
+     :selected (eq major-mode 'conf-windows-mode)]))
+
 (defvar conf-mode-syntax-table
   (let ((table (make-syntax-table)))
     (modify-syntax-entry ?=  "." table)
diff --git a/lisp/textmodes/css-mode.el b/lisp/textmodes/css-mode.el
index 622853d..47b0b51 100644
--- a/lisp/textmodes/css-mode.el
+++ b/lisp/textmodes/css-mode.el
@@ -427,7 +427,7 @@
      "paged-y" "paged-x-controls" "paged-y-controls" "fragments")
 
     ;; CSS Text Decoration Module Level 3
-    ;; (http://dev.w3.org/csswg/css-text-decor-3/#property-index)
+    ;; (https://dev.w3.org/csswg/css-text-decor-3/#property-index)
     ("text-decoration" text-decoration-line text-decoration-style
      text-decoration-color)
     ("text-decoration-color" color)
diff --git a/lisp/textmodes/dns-mode.el b/lisp/textmodes/dns-mode.el
index 23a6229..2fa5e8d 100644
--- a/lisp/textmodes/dns-mode.el
+++ b/lisp/textmodes/dns-mode.el
@@ -1,4 +1,4 @@
-;;; dns-mode.el --- a mode for viewing/editing Domain Name System master files
+;;; dns-mode.el --- a mode for viewing/editing Domain Name System master files 
 -*- lexical-binding: t -*-
 
 ;; Copyright (C) 2000-2001, 2004-2021 Free Software Foundation, Inc.
 
@@ -70,23 +70,19 @@
 
 (defface dns-mode-control-entity '((t :inherit font-lock-keyword-face))
   "Face used for DNS control entities, e.g. $ORIGIN."
-  :version "26.1"
-  :group 'dns-mode)
+  :version "26.1")
 
 (defface dns-mode-bad-control-entity '((t :inherit font-lock-warning-face))
   "Face used for non-standard DNS control entities, e.g. $FOO."
-  :version "26.1"
-  :group 'dns-mode)
+  :version "26.1")
 
 (defface dns-mode-type '((t :inherit font-lock-type-face))
   "Face used for DNS types, e.g., SOA."
-  :version "26.1"
-  :group 'dns-mode)
+  :version "26.1")
 
 (defface dns-mode-class '((t :inherit font-lock-constant-face))
   "Face used for DNS classes, e.g., IN."
-  :version "26.1"
-  :group 'dns-mode)
+  :version "26.1")
 
 (defvar dns-mode-control-entity-face ''dns-mode-control-entity
   "Name of face used for control entities, e.g. $ORIGIN.")
@@ -121,8 +117,7 @@
     (,(regexp-opt dns-mode-types) 0 ,dns-mode-type-face))
   "Font lock keywords used to highlight text in DNS master file mode."
   :version "26.1"
-  :type 'sexp
-  :group 'dns-mode)
+  :type 'sexp)
 
 (defcustom dns-mode-soa-auto-increment-serial t
   "Whether to increment the SOA serial number automatically.
@@ -134,8 +129,7 @@ manually with \\[dns-mode-soa-increment-serial]."
   :type '(choice (const :tag "Always" t)
                 (const :tag "Ask" ask)
                 (const :tag "Never" nil))
-  :safe 'symbolp
-  :group 'dns-mode)
+  :safe 'symbolp)
 
 ;; Syntax table.
 
@@ -150,8 +144,8 @@ manually with \\[dns-mode-soa-increment-serial]."
 
 (defvar dns-mode-map
   (let ((map (make-sparse-keymap)))
-    (define-key map "\C-c\C-s" 'dns-mode-soa-increment-serial)
-    (define-key map "\C-c\C-e" 'dns-mode-ipv6-to-nibbles)
+    (define-key map "\C-c\C-s" #'dns-mode-soa-increment-serial)
+    (define-key map "\C-c\C-e" #'dns-mode-ipv6-to-nibbles)
     map)
   "Keymap for DNS master file mode.")
 
@@ -183,7 +177,7 @@ Turning on DNS mode runs `dns-mode-hook'."
   (setq-local comment-start-skip ";+ *")
   (setq-local font-lock-defaults
               '(dns-mode-font-lock-keywords nil nil ((?_ . "w"))))
-  (add-hook 'before-save-hook 'dns-mode-soa-maybe-increment-serial
+  (add-hook 'before-save-hook #'dns-mode-soa-maybe-increment-serial
             nil t))
 
 ;;;###autoload (defalias 'zone-mode 'dns-mode)
diff --git a/lisp/textmodes/enriched.el b/lisp/textmodes/enriched.el
index fe92d60..ba8fac8 100644
--- a/lisp/textmodes/enriched.el
+++ b/lisp/textmodes/enriched.el
@@ -1,4 +1,4 @@
-;;; enriched.el --- read and save files in text/enriched format
+;;; enriched.el --- read and save files in text/enriched format  -*- 
lexical-binding: t; -*-
 
 ;; Copyright (C) 1994-1996, 2001-2021 Free Software Foundation, Inc.
 
@@ -50,8 +50,7 @@
 
 (defcustom enriched-verbose t
   "If non-nil, give status messages when reading and writing files."
-  :type 'boolean
-  :group 'enriched)
+  :type 'boolean)
 
 ;;;
 ;;; Set up faces & display table
@@ -65,14 +64,12 @@
   "Face used for text that must be shown in fixed width.
 Currently, Emacs can only display fixed-width fonts, but this may change.
 This face is used for text specifically marked as fixed-width, for example
-in text/enriched files."
-  :group 'enriched)
+in text/enriched files.")
 
 (defface excerpt
   '((t (:slant italic)))
   "Face used for text that is an excerpt from another document.
-This is used in Enriched mode for text explicitly marked as an excerpt."
-  :group 'enriched)
+This is used in Enriched mode for text explicitly marked as an excerpt.")
 
 (defconst enriched-display-table (or (copy-sequence standard-display-table)
                                     (make-display-table)))
@@ -146,8 +143,7 @@ Any property that is neither on this list nor dealt with by
 If you set variables in this hook, you should arrange for them to be restored
 to their old values if you leave Enriched mode.  One way to do this is to add
 them and their old values to `enriched-old-bindings'."
-  :type 'hook
-  :group 'enriched)
+  :type 'hook)
 
 (defcustom enriched-allow-eval-in-display-props nil
   "If non-nil allow to evaluate arbitrary forms in display properties.
@@ -162,8 +158,7 @@ Note, however, that applying unsafe display properties could
 execute malicious Lisp code, if that code came from an external source."
   :risky t
   :type 'boolean
-  :version "26.1"
-  :group 'enriched)
+  :version "26.1")
 
 (defvar-local enriched-old-bindings nil
   "Store old variable values that we change when entering mode.
@@ -186,14 +181,16 @@ The value is a list of \(VAR VALUE VAR VALUE...).")
 
 (defvar enriched-mode-map
   (let ((map (make-sparse-keymap)))
-    (define-key map "\C-m" 'reindent-then-newline-and-indent)
+    ;; FIXME: These newline/reindent bindings might be redundant now
+    ;; that we have `electric-indent-mode' enabled by default.
+    (define-key map "\C-m" #'reindent-then-newline-and-indent)
     (define-key map
-      [remap newline-and-indent] 'reindent-then-newline-and-indent)
+      [remap newline-and-indent] #'reindent-then-newline-and-indent)
     (define-key map "\M-j" 'facemenu-justification-menu)
-    (define-key map "\M-S" 'set-justification-center)
-    (define-key map "\C-x\t" 'increase-left-margin)
-    (define-key map "\C-c[" 'set-left-margin)
-    (define-key map "\C-c]" 'set-right-margin)
+    (define-key map "\M-S" #'set-justification-center)
+    (define-key map "\C-x\t" #'increase-left-margin)
+    (define-key map "\C-c[" #'set-left-margin)
+    (define-key map "\C-c]" #'set-right-margin)
     map)
   "Keymap for Enriched mode.")
 
@@ -220,7 +217,7 @@ Commands:
   (cond ((null enriched-mode)
         ;; Turn mode off
          (remove-hook 'change-major-mode-hook
-                      'enriched-before-change-major-mode 'local)
+                      #'enriched-before-change-major-mode 'local)
         (setq buffer-file-format (delq 'text/enriched buffer-file-format))
         ;; restore old variable values
         (while enriched-old-bindings
@@ -237,7 +234,7 @@ Commands:
 
        (t                              ; Turn mode on
          (add-hook 'change-major-mode-hook
-                   'enriched-before-change-major-mode nil 'local)
+                   #'enriched-before-change-major-mode nil 'local)
         (add-to-list 'buffer-file-format 'text/enriched)
         ;; Save old variable values before we change them.
         ;; These will be restored if we exit Enriched mode.
@@ -250,10 +247,12 @@ Commands:
         (make-local-variable 'default-text-properties)
         (setq buffer-display-table  enriched-display-table)
         (use-hard-newlines 1 (if enriched-rerun-flag 'never nil))
-        (let ((sticky (plist-get default-text-properties 'front-sticky))
-              (p enriched-par-props))
-          (dolist (x p)
-            (add-to-list 'sticky x))
+        (let* ((sticky
+                (delete-dups
+                 (append
+                  enriched-par-props
+                  (copy-sequence
+                   (plist-get default-text-properties 'front-sticky))))))
           (if sticky
               (setq default-text-properties
                     (plist-put default-text-properties
@@ -269,7 +268,7 @@ Commands:
     (let ((enriched-rerun-flag t))
       (enriched-mode 1))))
 
-(add-hook 'after-change-major-mode-hook 'enriched-after-change-major-mode)
+(add-hook 'after-change-major-mode-hook #'enriched-after-change-major-mode)
 
 
 (fset 'enriched-mode-map enriched-mode-map)
@@ -347,7 +346,7 @@ the region, and the START and END of each region."
                  (if orig-buf (set-buffer orig-buf))
                  (funcall enriched-initial-annotation))))
       (enriched-map-property-regions 'hard
-       (lambda (v b e)
+       (lambda (v b _e)
          (if (and v (= ?\n (char-after b)))
              (progn (goto-char b) (insert "\n"))))
        (point) nil)
@@ -391,9 +390,11 @@ which can be the value of the `face' text property."
        ((and (listp face) (eq (car face) :background))
         (list (list "x-bg-color" (cadr face))))
        ((listp face)
-        (apply 'append (mapcar 'enriched-face-ans face)))
+        (apply #'append (mapcar #'enriched-face-ans face)))
        ((let* ((fg (face-attribute face :foreground))
                (bg (face-attribute face :background))
+                (weight (face-attribute face :weight))
+                (slant (face-attribute face :slant))
                (props (face-font face t))
                (ans (cdr (format-annotate-single-property-change
                           'face nil props enriched-translations))))
@@ -401,6 +402,10 @@ which can be the value of the `face' text property."
             (setq ans (cons (list "x-color" fg) ans)))
           (unless (eq bg 'unspecified)
             (setq ans (cons (list "x-bg-color" bg) ans)))
+           (if (eq weight 'bold)
+               (setq ans (cons (list "bold") ans)))
+           (if (eq slant 'italic)
+               (setq ans (cons (list "italic") ans)))
           ans))))
 
 ;;;
diff --git a/lisp/textmodes/fill.el b/lisp/textmodes/fill.el
index 6681b03..cb5027a 100644
--- a/lisp/textmodes/fill.el
+++ b/lisp/textmodes/fill.el
@@ -45,7 +45,7 @@ A value of nil means that any change in indentation starts a 
new paragraph."
 (defcustom colon-double-space nil
   "Non-nil means put two spaces after a colon when filling."
   :type 'boolean)
-(put 'colon-double-space 'safe-local-variable 'booleanp)
+(put 'colon-double-space 'safe-local-variable #'booleanp)
 
 (defcustom fill-separate-heterogeneous-words-with-space nil
   "Non-nil means to use a space to separate words of a different kind.
@@ -703,7 +703,8 @@ space does not end a sentence, so don't break a line there."
     (or justify (setq justify (current-justification)))
 
     ;; Don't let Adaptive Fill mode alter the fill prefix permanently.
-    (let ((fill-prefix fill-prefix))
+    (let ((actual-fill-prefix fill-prefix)
+          (fill-prefix fill-prefix))
       ;; Figure out how this paragraph is indented, if desired.
       (when (and adaptive-fill-mode
                 (or (null fill-prefix) (string= fill-prefix "")))
@@ -717,7 +718,7 @@ space does not end a sentence, so don't break a line there."
       (goto-char from)
       (beginning-of-line)
 
-      (if (not justify)          ; filling disabled: just check indentation
+      (if (not justify)     ; filling disabled: just check indentation
          (progn
            (goto-char from)
            (while (< (point) to)
@@ -747,12 +748,14 @@ space does not end a sentence, so don't break a line 
there."
               linebeg)
          (while (< (point) to)
             ;; On the first line, there may be text in the fill prefix
-            ;; zone.  In that case, don't consider that area when
-            ;; trying to find a place to put a line break (bug#45720).
+            ;; zone (when `fill-prefix' is specified externally, and
+            ;; not computed).  In that case, don't consider that area
+            ;; when trying to find a place to put a line break
+            ;; (bug#45720).
             (if (not first)
                (setq linebeg (point))
               (setq first nil
-                    linebeg (+ (point) (length fill-prefix))))
+                    linebeg (+ (point) (length actual-fill-prefix))))
            (move-to-column (current-fill-column))
            (if (when (< (point) to)
                  ;; Find the position where we'll break the line.
diff --git a/lisp/textmodes/flyspell.el b/lisp/textmodes/flyspell.el
index 83dba71..a48b345 100644
--- a/lisp/textmodes/flyspell.el
+++ b/lisp/textmodes/flyspell.el
@@ -2293,8 +2293,8 @@ If OPOINT is non-nil, restore point there after adjusting 
it for replacement."
                                 corrects)
                       '()))
         (affix      (car (cdr (cdr (cdr poss)))))
-        show-affix-info
-        (base-menu  (let ((save (if (and (consp affix) show-affix-info)
+        ;; show-affix-info
+        (base-menu  (let ((save (if nil ;; (and (consp affix) show-affix-info)
                                     (list
                                      (list (concat "Save affix: " (car affix))
                                            'save)
diff --git a/lisp/textmodes/ispell.el b/lisp/textmodes/ispell.el
index ea46270..cee578f 100644
--- a/lisp/textmodes/ispell.el
+++ b/lisp/textmodes/ispell.el
@@ -131,8 +131,7 @@
 (defcustom ispell-highlight-p 'block
   "Highlight spelling errors when non-nil.
 When set to `block', assumes a block cursor with TTY displays."
-  :type '(choice (const block) (const :tag "off" nil) (const :tag "on" t))
-  :group 'ispell)
+  :type '(choice (const block) (const :tag "off" nil) (const :tag "on" t)))
 
 (defcustom ispell-lazy-highlight (boundp 'lazy-highlight-cleanup)
   "Controls the lazy-highlighting of spelling errors.
@@ -141,7 +140,6 @@ error is highlighted lazily using isearch lazy highlighting 
(see
 `lazy-highlight-initial-delay' and `lazy-highlight-interval')."
   :type 'boolean
   :group 'lazy-highlight
-  :group 'ispell
   :version "22.1")
 
 (defcustom ispell-highlight-face (if ispell-lazy-highlight 'isearch 'highlight)
@@ -149,16 +147,14 @@ error is highlighted lazily using isearch lazy 
highlighting (see
 This variable can be set by the user to whatever face they desire.
 It's most convenient if the cursor color and highlight color are
 slightly different."
-  :type 'face
-  :group 'ispell)
+  :type 'face)
 
 (defcustom ispell-check-comments t
   "Spelling of comments checked when non-nil.
 When set to `exclusive', ONLY comments are checked.  (For code comments).
 Warning!  Not checking comments, when a comment start is embedded in strings,
 may produce undesired results."
-  :type '(choice (const exclusive) (const :tag "off" nil) (const :tag "on" t))
-  :group 'ispell)
+  :type '(choice (const exclusive) (const :tag "off" nil) (const :tag "on" t)))
 ;;;###autoload
 (put 'ispell-check-comments 'safe-local-variable
      (lambda (a) (memq a '(nil t exclusive))))
@@ -166,8 +162,7 @@ may produce undesired results."
 (defcustom ispell-query-replace-choices nil
   "Corrections made throughout region when non-nil.
 Uses `query-replace' (\\[query-replace]) for corrections."
-  :type 'boolean
-  :group 'ispell)
+  :type 'boolean)
 
 (defcustom ispell-skip-tib nil
   "Does not spell check `tib' bibliography references when non-nil.
@@ -177,8 +172,7 @@ Skips any text between strings matching regular expressions
 TeX users beware:  Any text between [. and .] will be skipped -- even if
 that's your whole buffer -- unless you set `ispell-skip-tib' to nil.
 That includes the [.5mm] type of number..."
-  :type 'boolean
-  :group 'ispell)
+  :type 'boolean)
 
 (defvar ispell-tib-ref-beginning "[[<]\\."
   "Regexp matching the beginning of a Tib reference.")
@@ -189,14 +183,12 @@ That includes the [.5mm] type of number..."
 (defcustom ispell-keep-choices-win t
   "If non-nil, keep the `*Choices*' window for the entire spelling session.
 This minimizes redisplay thrashing."
-  :type 'boolean
-  :group 'ispell)
+  :type 'boolean)
 
 (defcustom ispell-choices-win-default-height 2
   "The default size of the `*Choices*' window, including the mode line.
 Must be greater than 1."
-  :type 'integer
-  :group 'ispell)
+  :type 'integer)
 
 (defcustom ispell-program-name
   (or (executable-find "aspell")
@@ -211,8 +203,7 @@ Must be greater than 1."
   :set (lambda (symbol value)
          (set-default symbol value)
          (if (featurep 'ispell)
-             (ispell-set-spellchecker-params)))
-  :group 'ispell)
+             (ispell-set-spellchecker-params))))
 
 (defcustom ispell-alternate-dictionary
   (cond ((file-readable-p "/usr/dict/web2") "/usr/dict/web2")
@@ -224,14 +215,12 @@ Must be greater than 1."
         "/usr/share/lib/dict/words")
        ((file-readable-p "/sys/dict") "/sys/dict"))
   "Alternate plain word-list dictionary for spelling help."
-  :type '(choice file (const :tag "None" nil))
-  :group 'ispell)
+  :type '(choice file (const :tag "None" nil)))
 
 (defcustom ispell-complete-word-dict nil
   "Plain word-list dictionary used for word completion if
 different from `ispell-alternate-dictionary'."
-  :type '(choice file (const :tag "None" nil))
-  :group 'ispell)
+  :type '(choice file (const :tag "None" nil)))
 
 (defcustom ispell-message-dictionary-alist nil
   "List used by `ispell-message' to select a new dictionary.
@@ -241,29 +230,25 @@ DICTIONARY if `ispell-local-dictionary' is not 
buffer-local.
 E.g. you may use the following value:
    ((\"^Newsgroups:[ \\t]*de\\\\.\" . \"deutsch8\")
     (\"^To:[^\\n,]+\\\\.de[ \\t\\n,>]\" . \"deutsch8\"))"
-  :type '(repeat (cons regexp string))
-  :group 'ispell)
+  :type '(repeat (cons regexp string)))
 
 
 (defcustom ispell-message-fcc-skip 50000
   "Query before saving Fcc message copy if attachment larger than this value.
 Always stores Fcc copy of message when nil."
-  :type '(choice integer (const :tag "off" nil))
-  :group 'ispell)
+  :type '(choice integer (const :tag "off" nil)))
 
 
 (defcustom ispell-grep-command
   "grep"
   "Name of the grep command for search processes."
-  :type 'string
-  :group 'ispell)
+  :type 'string)
 
 (defcustom ispell-grep-options
   "-Ei"
   "String of options to use when running the program in `ispell-grep-command'.
 Should probably be \"-Ei\"."
-  :type 'string
-  :group 'ispell)
+  :type 'string)
 
 (defcustom ispell-look-command
   (cond ((file-exists-p "/bin/look") "/bin/look")
@@ -272,36 +257,30 @@ Should probably be \"-Ei\"."
        (t "look"))
   "Name of the look command for search processes.
 This must be an absolute file name."
-  :type 'file
-  :group 'ispell)
+  :type 'file)
 
 (defcustom ispell-look-p (file-exists-p ispell-look-command)
   "Non-nil means use `look' rather than `grep'.
 Default is based on whether `look' seems to be available."
-  :type 'boolean
-  :group 'ispell)
+  :type 'boolean)
 
 (defcustom ispell-have-new-look nil
   "Non-nil means use the `-r' option (regexp) when running `look'."
-  :type 'boolean
-  :group 'ispell)
+  :type 'boolean)
 
 (defcustom ispell-look-options (if ispell-have-new-look "-dfr" "-df")
   "String of command options for `ispell-look-command'."
-  :type 'string
-  :group 'ispell)
+  :type 'string)
 
 (defcustom ispell-use-ptys-p nil
   "When non-nil, Emacs uses ptys to communicate with Ispell.
 When nil, Emacs uses pipes."
-  :type 'boolean
-  :group 'ispell)
+  :type 'boolean)
 
 (defcustom ispell-following-word nil
   "Non-nil means `ispell-word' checks the word around or after point.
 Otherwise `ispell-word' checks the preceding word."
-  :type 'boolean
-  :group 'ispell)
+  :type 'boolean)
 
 (defcustom ispell-help-in-bufferp nil
   "Non-nil means display interactive keymap help in a buffer.
@@ -312,21 +291,18 @@ The following values are supported:
              for a couple of seconds.
   electric   Pop up a new buffer and display a long help message there.
              User can browse and then exit the help mode."
-  :type '(choice (const electric) (const :tag "off" nil) (const :tag "on" t))
-  :group 'ispell)
+  :type '(choice (const electric) (const :tag "off" nil) (const :tag "on" t)))
 
 (defcustom ispell-quietly nil
   "Non-nil means suppress messages in `ispell-word'."
-  :type 'boolean
-  :group 'ispell)
+  :type 'boolean)
 
 (defvaralias 'ispell-format-word 'ispell-format-word-function)
 
 (defcustom ispell-format-word-function (function upcase)
   "Formatting function for displaying word being spell checked.
 The function must take one string argument and return a string."
-  :type 'function
-  :group 'ispell)
+  :type 'function)
 
 ;; FIXME framepop.el last updated c 2003 (?),
 ;; use posframe.
@@ -335,21 +311,18 @@ The function must take one string argument and return a 
string."
 You can set this variable to dynamically use framepop if you are in a
 window system by evaluating the following on startup to set this variable:
   (and (display-graphic-p) (require \\='framepop nil t))"
-  :type 'boolean
-  :group 'ispell)
+  :type 'boolean)
 
 ;;;###autoload
 (defcustom ispell-personal-dictionary nil
   "File name of your personal spelling dictionary, or nil.
 If nil, the default personal dictionary for your spelling checker is used."
   :type '(choice file
-                (const :tag "default" nil))
-  :group 'ispell)
+                 (const :tag "default" nil)))
 
 (defcustom ispell-silently-savep nil
   "When non-nil, save personal dictionary without asking for confirmation."
-  :type 'boolean
-  :group 'ispell)
+  :type 'boolean)
 
 (defvar-local ispell-local-dictionary-overridden nil
   "Non-nil means the user has explicitly set this buffer's Ispell dictionary.")
@@ -366,8 +339,7 @@ calling \\[ispell-change-dictionary] with that value.  This 
variable
 is automatically set when defined in the file with either
 `ispell-dictionary-keyword' or the Local Variable syntax."
   :type '(choice string
-                (const :tag "default" nil))
-  :group 'ispell)
+                 (const :tag "default" nil)))
 ;;;###autoload
 (put 'ispell-local-dictionary 'safe-local-variable 'string-or-null-p)
 
@@ -376,16 +348,14 @@ is automatically set when defined in the file with either
 (defcustom ispell-dictionary nil
   "Default dictionary to use if `ispell-local-dictionary' is nil."
   :type '(choice string
-                (const :tag "default" nil))
-  :group 'ispell)
+                 (const :tag "default" nil)))
 
 (defcustom ispell-extra-args nil
   "If non-nil, a list of extra switches to pass to the Ispell program.
 For example, (\"-W\" \"3\") to cause it to accept all 1-3 character
 words as correct.  See also `ispell-dictionary-alist', which may be used
 for language-specific arguments."
-  :type '(repeat string)
-  :group 'ispell)
+  :type '(repeat string))
 
 
 
@@ -400,8 +370,7 @@ such as \"&amp;\".  See `ispell-html-skip-alists' for more 
details.
 
 This variable affects spell-checking of HTML, XML, and SGML files."
   :type '(choice (const :tag "always" t) (const :tag "never" nil)
-                (const :tag "use-mode-name" use-mode-name))
-  :group 'ispell)
+                 (const :tag "use-mode-name" use-mode-name)))
 
 (make-variable-buffer-local 'ispell-skip-html)
 
@@ -427,8 +396,7 @@ re-start Emacs."
                               (const "~nroff") (const "~list")
                               (const "~latin1") (const "~latin3")
                               (const :tag "default" nil))
-                      (coding-system :tag "Coding System")))
-  :group 'ispell)
+                       (coding-system :tag "Coding System"))))
 
 
 (defvar ispell-dictionary-base-alist
diff --git a/lisp/textmodes/less-css-mode.el b/lisp/textmodes/less-css-mode.el
index 24ccb3c..d374cab 100644
--- a/lisp/textmodes/less-css-mode.el
+++ b/lisp/textmodes/less-css-mode.el
@@ -91,7 +91,7 @@ executable, e.g.: \"~/.gem/ruby/1.8/bin/lessc\"."
   "If non-nil, Less buffers are compiled to CSS after each save."
   :type 'boolean)
 ;;;###autoload
-(put 'less-css-compile-at-save 'safe-local-variable 'booleanp)
+(put 'less-css-compile-at-save 'safe-local-variable #'booleanp)
 
 (defcustom less-css-lessc-options '("--no-color")
   "Command line options for Less executable.
@@ -107,7 +107,7 @@ using `expand-file-name', so both relative and absolute 
paths
 will work as expected."
   :type '(choice (const :tag "Same as Less file" nil) directory))
 ;;;###autoload
-(put 'less-css-output-directory 'safe-local-variable 'stringp)
+(put 'less-css-output-directory 'safe-local-variable #'stringp)
 
 (defcustom less-css-output-file-name nil
   "File name in which to save CSS, or nil to use <name>.css for <name>.less.
@@ -133,7 +133,7 @@ the path is relative, it will be relative to the current
 directory by default."
   :type '(choice (const nil) file))
 ;;;###autoload
-(put 'less-css-input-file-name 'safe-local-variable 'stringp)
+(put 'less-css-input-file-name 'safe-local-variable #'stringp)
 (make-variable-buffer-local 'less-css-input-file-name)
 
 (defconst less-css-default-error-regex
@@ -211,7 +211,7 @@ directory by default."
 
 (defvar less-css-mode-map
   (let ((map (make-sparse-keymap)))
-    (define-key map "\C-c\C-c" 'less-css-compile)
+    (define-key map "\C-c\C-c" #'less-css-compile)
     map))
 
 ;;;###autoload (add-to-list 'auto-mode-alist '("\\.less\\'" . less-css-mode))
@@ -226,7 +226,7 @@ Special commands:
   (setq-local comment-continue " *")
   (setq-local comment-start-skip "/[*/]+[ \t]*")
   (setq-local comment-end-skip "[ \t]*\\(?:\n\\|\\*+/\\)")
-  (add-hook 'after-save-hook 'less-css-compile-maybe nil t))
+  (add-hook 'after-save-hook #'less-css-compile-maybe nil t))
 
 (provide 'less-css-mode)
 ;;; less-css-mode.el ends here
diff --git a/lisp/textmodes/makeinfo.el b/lisp/textmodes/makeinfo.el
index e48649b..8152f4b 100644
--- a/lisp/textmodes/makeinfo.el
+++ b/lisp/textmodes/makeinfo.el
@@ -1,4 +1,4 @@
-;;; makeinfo.el --- run makeinfo conveniently
+;;; makeinfo.el --- run makeinfo conveniently  -*- lexical-binding: t; -*-
 
 ;; Copyright (C) 1991, 1993, 2001-2021 Free Software Foundation, Inc.
 
@@ -59,16 +59,14 @@
 (defcustom makeinfo-run-command "makeinfo"
   "Command used to run `makeinfo' subjob.
 The name of the file is appended to this string, separated by a space."
-  :type 'string
-  :group 'makeinfo)
+  :type 'string)
 
 (defcustom makeinfo-options "--fill-column=70"
   "String containing options for running `makeinfo'.
 Do not include `--footnote-style' or `--paragraph-indent';
 the proper way to specify those is with the Texinfo commands
 `@footnotestyle' and `@paragraphindent'."
-  :type 'string
-  :group 'makeinfo)
+  :type 'string)
 
 (require 'texinfo)
 
@@ -95,7 +93,7 @@ apply to a temporary file, not the original; use the 
`makeinfo-buffer'
 command to gain use of `next-error'."
 
   (interactive "r")
-  (let (filename-or-header
+  (let (;; filename-or-header
         filename-or-header-beginning
         filename-or-header-end)
     ;; Cannot use `let' for makeinfo-temp-file or
@@ -175,7 +173,7 @@ command to gain use of `next-error'."
             t
              'makeinfo-compilation-sentinel-region)))))))
 
-(defun makeinfo-next-error (arg reset)
+(defun makeinfo-next-error (_arg _reset)
   "This function is used to disable `next-error' if the user has
 used `makeinfo-region'.  Since the compilation process is used on
 a temporary file in that case, calling `next-error' would give
diff --git a/lisp/textmodes/mhtml-mode.el b/lisp/textmodes/mhtml-mode.el
index 32542d0..2590538 100644
--- a/lisp/textmodes/mhtml-mode.el
+++ b/lisp/textmodes/mhtml-mode.el
@@ -313,7 +313,7 @@ Prefix arg specifies how many times to move (default 1)."
   (interactive "P")
   (pcase (get-text-property (point) 'mhtml-submode)
     ('nil (sgml-skip-tag-forward arg))
-    (submode (forward-sexp arg))))
+    (_submode (forward-sexp arg))))
 
 ;;;###autoload
 (define-derived-mode mhtml-mode html-mode
diff --git a/lisp/textmodes/nroff-mode.el b/lisp/textmodes/nroff-mode.el
index e7d852b..94519c3 100644
--- a/lisp/textmodes/nroff-mode.el
+++ b/lisp/textmodes/nroff-mode.el
@@ -46,38 +46,34 @@
   :type 'boolean)
 
 (defvar nroff-mode-map
-  (let ((map (make-sparse-keymap))
-       (menu-map (make-sparse-keymap)))
-    (define-key map "\t"  'tab-to-tab-stop)
-    (define-key map "\e?" 'nroff-count-text-lines)
-    (define-key map "\n"  'nroff-electric-newline)
-    (define-key map "\en" 'nroff-forward-text-line)
-    (define-key map "\ep" 'nroff-backward-text-line)
-    (define-key map "\C-c\C-c" 'nroff-view)
-    (define-key map [menu-bar nroff-mode] (cons "Nroff" menu-map))
-    (define-key menu-map [nn]
-      '(menu-item "Newline" nroff-electric-newline
-                 :help "Insert newline for nroff mode; special if 
nroff-electric mode"))
-    (define-key menu-map [nc]
-      '(menu-item "Count text lines" nroff-count-text-lines
-                 :help "Count lines in region, except for nroff request 
lines."))
-    (define-key menu-map [nf]
-      '(menu-item "Forward text line" nroff-forward-text-line
-                 :help "Go forward one nroff text line, skipping lines of 
nroff requests"))
-    (define-key menu-map [nb]
-      '(menu-item "Backward text line" nroff-backward-text-line
-                 :help "Go backward one nroff text line, skipping lines of 
nroff requests"))
-    (define-key menu-map [ne]
-      '(menu-item "Electric newline mode"
-                 nroff-electric-mode
-                 :help "Auto insert closing requests if necessary"
-                 :button (:toggle . nroff-electric-mode)))
-    (define-key menu-map [npm]
-      '(menu-item "Preview as man page" nroff-view
-                 :help "Run man on this file."))
+  (let ((map (make-sparse-keymap)))
+    (define-key map "\t"  #'tab-to-tab-stop)
+    (define-key map "\e?" #'nroff-count-text-lines)
+    (define-key map "\n"  #'nroff-electric-newline)
+    (define-key map "\en" #'nroff-forward-text-line)
+    (define-key map "\ep" #'nroff-backward-text-line)
+    (define-key map "\C-c\C-c" #'nroff-view)
     map)
   "Major mode keymap for `nroff-mode'.")
 
+(easy-menu-define nroff-mode-menu nroff-mode-map
+  "Menu for `nroff-mode'."
+  '("Nroff"
+    ["Preview as man page" nroff-view
+     :help "Run man on this file."]
+    ["Electric newline mode" nroff-electric-mode
+     :help "Auto insert closing requests if necessary"
+     :style toggle
+     :selected nroff-electric-mode]
+    ["Backward text line" nroff-backward-text-line
+     :help "Go backward one nroff text line, skipping lines of nroff requests"]
+    ["Forward text line" nroff-forward-text-line
+     :help "Go forward one nroff text line, skipping lines of nroff requests"]
+    ["Count text lines" nroff-count-text-lines
+     :help "Count lines in region, except for nroff request lines."]
+    ["Newline" nroff-electric-newline
+     :help "Insert newline for nroff mode; special if nroff-electric mode"]))
+
 (defvar nroff-mode-syntax-table
   (let ((st (copy-syntax-table text-mode-syntax-table)))
     ;; " isn't given string quote syntax in text-mode but it
diff --git a/lisp/textmodes/page-ext.el b/lisp/textmodes/page-ext.el
index c3e1fb1..87c91e8 100644
--- a/lisp/textmodes/page-ext.el
+++ b/lisp/textmodes/page-ext.el
@@ -293,7 +293,7 @@ Used by `pages-directory-for-addresses' function."
 ;; FIXME: Merely loading a package shouldn't have this kind of side-effects!
 (global-unset-key "\C-x\C-p")
 (define-key ctl-x-map "\C-p" #'pages-ctl-x-ctl-p-prefix)
-(define-obsolete-function-alias 'ctl-x-ctl-p-prefix 'pages-ctl-x-ctl-p-prefix 
"27.1")
+(define-obsolete-function-alias 'ctl-x-ctl-p-prefix #'pages-ctl-x-ctl-p-prefix 
"27.1")
 (defalias 'pages-ctl-x-ctl-p-prefix pages--ctl-x-ctl-p-map)
 
 
diff --git a/lisp/textmodes/paragraphs.el b/lisp/textmodes/paragraphs.el
index 96edfd6..31e91c7 100644
--- a/lisp/textmodes/paragraphs.el
+++ b/lisp/textmodes/paragraphs.el
@@ -96,9 +96,8 @@ lines that start paragraphs from lines that separate them.
 
 If the variable `use-hard-newlines' is non-nil, then only lines following a
 hard newline are considered to match."
-  :group 'paragraphs
   :type 'regexp)
-(put 'paragraph-start 'safe-local-variable 'stringp)
+(put 'paragraph-start 'safe-local-variable #'stringp)
 
 ;; paragraph-start requires a hard newline, but paragraph-separate does not:
 ;; It is assumed that paragraph-separate is distinctive enough to be believed
@@ -114,9 +113,8 @@ This is matched against the text at the left margin, which 
is not necessarily
 the beginning of the line, so it should not use \"^\" as an anchor.  This
 ensures that the paragraph functions will work equally within a region of
 text indented by a margin setting."
-  :group 'paragraphs
   :type 'regexp)
-(put 'paragraph-separate 'safe-local-variable 'stringp)
+(put 'paragraph-separate 'safe-local-variable #'stringp)
 
 (defcustom sentence-end-double-space t
   "Non-nil means a single space does not end a sentence.
@@ -128,7 +126,7 @@ regexp describing the end of a sentence, when the value of 
the variable
 `sentence-end' is nil.  See Info node `(elisp)Standard Regexps'."
   :type 'boolean
   :group 'fill)
-(put 'sentence-end-double-space 'safe-local-variable 'booleanp)
+(put 'sentence-end-double-space 'safe-local-variable #'booleanp)
 
 (defcustom sentence-end-without-period nil
   "Non-nil means a sentence will end without a period.
@@ -140,7 +138,7 @@ regexp describing the end of a sentence, when the value of 
the variable
 `sentence-end' is nil.  See Info node `(elisp)Standard Regexps'."
   :type 'boolean
   :group 'fill)
-(put 'sentence-end-without-period 'safe-local-variable 'booleanp)
+(put 'sentence-end-without-period 'safe-local-variable #'booleanp)
 
 (defcustom sentence-end-without-space
   "。.?!"
@@ -149,9 +147,8 @@ regexp describing the end of a sentence, when the value of 
the variable
 This value is used by the function `sentence-end' to construct the
 regexp describing the end of a sentence, when the value of the variable
 `sentence-end' is nil.  See Info node `(elisp)Standard Regexps'."
-  :group 'paragraphs
   :type 'string)
-(put 'sentence-end-without-space 'safe-local-variable 'stringp)
+(put 'sentence-end-without-space 'safe-local-variable #'stringp)
 
 (defcustom sentence-end nil
   "Regexp describing the end of a sentence.
@@ -161,16 +158,14 @@ All paragraph boundaries also end sentences, regardless.
 The value nil means to use the default value defined by the
 function `sentence-end'.  You should always use this function
 to obtain the value of this variable."
-  :group 'paragraphs
   :type '(choice regexp (const :tag "Use default value" nil)))
-(put 'sentence-end 'safe-local-variable 'string-or-null-p)
+(put 'sentence-end 'safe-local-variable #'string-or-null-p)
 
 (defcustom sentence-end-base "[.?!…‽][]\"'”’)}»›]*"
   "Regexp matching the basic end of a sentence, not including following space."
-  :group 'paragraphs
   :type 'regexp
   :version "25.1")
-(put 'sentence-end-base 'safe-local-variable 'stringp)
+(put 'sentence-end-base 'safe-local-variable #'stringp)
 
 (defun sentence-end ()
   "Return the regexp describing the end of a sentence.
@@ -197,16 +192,14 @@ in between.  See Info node `(elisp)Standard Regexps'."
 
 (defcustom page-delimiter "^\014"
   "Regexp describing line-beginnings that separate pages."
-  :group 'paragraphs
   :type 'regexp)
-(put 'page-delimiter 'safe-local-variable 'stringp)
+(put 'page-delimiter 'safe-local-variable #'stringp)
 
 (defcustom paragraph-ignore-fill-prefix nil
   "Non-nil means the paragraph commands are not affected by `fill-prefix'.
 This is desirable in modes where blank lines are the paragraph delimiters."
-  :group 'paragraphs
   :type 'boolean)
-(put 'paragraph-ignore-fill-prefix 'safe-local-variable 'booleanp)
+(put 'paragraph-ignore-fill-prefix 'safe-local-variable #'booleanp)
 
 ;; Silence the compiler.
 (defvar multiple-lines)
diff --git a/lisp/textmodes/picture.el b/lisp/textmodes/picture.el
index 3cb1043..1368af0 100644
--- a/lisp/textmodes/picture.el
+++ b/lisp/textmodes/picture.el
@@ -37,28 +37,22 @@
 
 (defcustom picture-rectangle-ctl ?+
   "Character `picture-draw-rectangle' uses for top left corners."
-  :type 'character
-  :group 'picture)
+  :type 'character)
 (defcustom picture-rectangle-ctr ?+
   "Character `picture-draw-rectangle' uses for top right corners."
-  :type 'character
-  :group 'picture)
+  :type 'character)
 (defcustom picture-rectangle-cbr ?+
   "Character `picture-draw-rectangle' uses for bottom right corners."
-  :type 'character
-  :group 'picture)
+  :type 'character)
 (defcustom picture-rectangle-cbl ?+
   "Character `picture-draw-rectangle' uses for bottom left corners."
-  :type 'character
-  :group 'picture)
+  :type 'character)
 (defcustom picture-rectangle-v   ?|
   "Character `picture-draw-rectangle' uses for vertical lines."
-  :type 'character
-  :group 'picture)
+  :type 'character)
 (defcustom picture-rectangle-h   ?-
   "Character `picture-draw-rectangle' uses for horizontal lines."
-  :type 'character
-  :group 'picture)
+  :type 'character)
 
 
 ;; Picture Movement Commands
@@ -409,8 +403,7 @@ character `\\' in the set it must be preceded by itself: 
\"\\\\\".
 
 The command \\[picture-tab-search] is defined to move beneath (or to) a
 character belonging to this set independent of the tab stops list."
-  :type 'string
-  :group 'picture)
+  :type 'string)
 
 (defun picture-set-tab-stops (&optional arg)
   "Set value of `tab-stop-list' according to context of this line.
@@ -682,8 +675,7 @@ Leaves the region surrounding the rectangle."
 (defcustom picture-mode-hook nil
   "If non-nil, its value is called on entry to Picture mode.
 Picture mode is invoked by the command \\[picture-mode]."
-  :type 'hook
-  :group 'picture)
+  :type 'hook)
 
 (defvar picture-mode-old-local-map)
 (defvar picture-mode-old-mode-name)
diff --git a/lisp/textmodes/refbib.el b/lisp/textmodes/refbib.el
index bff5712..084b17c 100644
--- a/lisp/textmodes/refbib.el
+++ b/lisp/textmodes/refbib.el
@@ -1,4 +1,4 @@
-;;; refbib.el --- convert refer-style references to ones usable by Latex bib
+;;; refbib.el --- convert refer-style references to ones usable by Latex bib  
-*- lexical-binding: t; -*-
 
 ;; Copyright (C) 1989, 2001-2021 Free Software Foundation, Inc.
 
@@ -65,8 +65,7 @@
 
 (defcustom r2b-trace-on nil
   "Non-nil means trace conversion."
-  :type 'boolean
-  :group 'refbib)
+  :type 'boolean)
 
 (defcustom r2b-journal-abbrevs
   '(
@@ -83,8 +82,7 @@ letter, even if it really doesn't.
 \(\"Ijcai81\" \"ijcai7\")) would expand Aij to the text string
 \"Artificial Intelligence\", but would replace Ijcai81 with the
 BibTeX macro \"ijcai7\"."
-  :type '(repeat (list string string))
-  :group 'refbib)
+  :type '(repeat (list string string)))
 
 (defcustom r2b-booktitle-abbrevs
   '(
@@ -101,8 +99,7 @@ should be listed as beginning with a capital letter, even if 
it doesn't.
 \(\"Ijcai81\" \"ijcai7\")) would expand Aij to the text string
 \"Artificial Intelligence\", but would replace Ijcai81 with the
 BibTeX macro \"ijcai7\"."
-  :type '(repeat (list string string))
-  :group 'refbib)
+  :type '(repeat (list string string)))
 
 (defcustom r2b-proceedings-list
   '()
@@ -119,8 +116,7 @@ a conference, and its expansion is the BibTeX macro 
\"ijcai7\".  Then
 expansion were \"Proceedings of the Seventh International Conference
 on Artificial Intelligence\", then you would NOT need to include Ijcai81
 in `r2b-proceedings-list' (although it wouldn't cause an error)."
-  :type '(repeat (list string string))
-  :group 'refbib)
+  :type '(repeat (list string string)))
 
 (defvar r2b-additional-stop-words
   "Some\\|What"
@@ -129,8 +125,7 @@ This is in addition to the 
`r2b-capitalize-title-stop-words'.")
 
 (defcustom r2b-delimit-with-quote t
   "If true, then use \" to delimit fields, otherwise use braces."
-  :type 'boolean
-  :group 'refbib)
+  :type 'boolean)
 
 ;**********************************************************
 ; Utility Functions
@@ -205,13 +200,11 @@ This is in addition to the 
`r2b-capitalize-title-stop-words'.")
 
 (defcustom r2b-out-buf-name "*Out*"
   "Name of buffer for output from refer-to-bibtex."
-  :type 'string
-  :group 'refbib)
+  :type 'string)
 
 (defcustom r2b-log-name "*Log*"
   "Name of buffer for logs errors from refer-to-bibtex."
-  :type 'string
-  :group 'refbib)
+  :type 'string)
 
 (defvar r2b-in-buf nil)
 (defvar r2b-out-buf nil)
@@ -418,7 +411,7 @@ title if CAPITALIZE is true.  Returns value of VAR."
 with a comma and newline; if ABBREVS list is given, then
 try to replace the {DATA} with an abbreviation."
   (if data
-    (let (match nodelim multi-line index)
+    (let (match nodelim index) ;; multi-line
       (cond
        ((and abbrevs (setq match (assoc data abbrevs)))
          (if (null (cdr match))
@@ -514,7 +507,7 @@ but not a publisher."
 
 (defun r2b-barf-output ()
    "Generate bibtex based on global variables."
-   (let ((standard-output r2b-out-buf) (case-fold-search t) match)
+   (let ((standard-output r2b-out-buf) (case-fold-search t)) ;; match
 
       (r2b-trace "...barfing")
       (sit-for 0)
diff --git a/lisp/textmodes/refer.el b/lisp/textmodes/refer.el
index ae1f778..53519ac 100644
--- a/lisp/textmodes/refer.el
+++ b/lisp/textmodes/refer.el
@@ -1,4 +1,4 @@
-;;; refer.el --- look up references in bibliography files
+;;; refer.el --- look up references in bibliography files  -*- 
lexical-binding: t; -*-
 
 ;; Copyright (C) 1992, 1996, 2001-2021 Free Software Foundation, Inc.
 
@@ -91,8 +91,7 @@ the default search path.  Since Refer does not know that 
default path,
 it cannot search it.  Include that path explicitly in your BIBINPUTS
 environment if you really want it searched (which is not likely to
 happen anyway)."
-  :type '(choice (repeat directory) (const bibinputs) (const texinputs))
-  :group 'refer)
+  :type '(choice (repeat directory) (const bibinputs) (const texinputs)))
 
 (defcustom refer-bib-files 'dir
   "List of \\.bib files to search for references,
@@ -110,16 +109,14 @@ If `refer-bib-files' is nil, auto or dir, it is setq'd to 
the appropriate
 list of files when it is first used if `refer-cache-bib-files' is t.  If
 `refer-cache-bib-files' is nil, the list of \\.bib files to use is re-read
 each time it is needed."
-  :type '(choice (repeat file) (const nil) (const auto) (const dir))
-  :group 'refer)
+  :type '(choice (repeat file) (const nil) (const auto) (const dir)))
 
 (defcustom refer-cache-bib-files t
   "Variable determining whether the value of `refer-bib-files' should be 
cached.
 If t, initialize the value of refer-bib-files the first time it is used.  If
 nil, re-read the list of \\.bib files depending on the value of 
`refer-bib-files'
 each time it is needed."
-  :type 'boolean
-  :group 'refer)
+  :type 'boolean)
 
 (defcustom refer-bib-files-regexp "\\\\bibliography"
   "Regexp matching a bibliography file declaration.
@@ -131,8 +128,7 @@ command is expected to specify a file name, or a list of 
comma-separated file
 names, within curly braces.
 If a specified file doesn't exist and has no extension, a \\.bib extension
 is automatically tried."
-  :type 'regexp
-  :group 'refer)
+  :type 'regexp)
 
 (make-variable-buffer-local 'refer-bib-files)
 (make-variable-buffer-local 'refer-cache-bib-files)
@@ -180,7 +176,7 @@ found on the last `refer-find-entry' or 
`refer-find-next-entry'."
 
 (defun refer-find-entry-internal (keywords continue)
    (let ((keywords-list (refer-convert-string-to-list-of-strings keywords))
-         (old-buffer (current-buffer))
+         ;; (old-buffer (current-buffer))
          (old-window (selected-window))
          (new-window (selected-window))
          (files (if continue
@@ -188,7 +184,7 @@ found on the last `refer-find-entry' or 
`refer-find-next-entry'."
                   (setq refer-saved-pos nil)
                   (refer-get-bib-files)))
          (n 0)
-         (found nil)
+         ;; (found nil)
          (file nil))
      ;; find window in which to display bibliography file.
      ;; if a bibliography file is already displayed in a window, use
diff --git a/lisp/textmodes/refill.el b/lisp/textmodes/refill.el
index 8f4f3c5..0a0e4cc 100644
--- a/lisp/textmodes/refill.el
+++ b/lisp/textmodes/refill.el
@@ -1,4 +1,4 @@
-;;; refill.el --- `auto-fill' by refilling paragraphs on changes
+;;; refill.el --- `auto-fill' by refilling paragraphs on changes  -*- 
lexical-binding: t -*-
 
 ;; Copyright (C) 2000-2021 Free Software Foundation, Inc.
 
@@ -83,16 +83,11 @@
 
 ;;; Code:
 
-;; Unused.
-;;; (defgroup refill nil
-;;;   "Refilling paragraphs on changes."
-;;;   :group 'fill)
-
 (defvar-local refill-ignorable-overlay nil
   "Portion of the most recently filled paragraph not needing filling.
 This is used to optimize refilling.")
 
-(defun refill-adjust-ignorable-overlay (overlay afterp beg end &optional len)
+(defun refill-adjust-ignorable-overlay (overlay afterp beg _end &optional _len)
   "Adjust OVERLAY to not include the about-to-be-modified region."
   (when (not afterp)
     (save-excursion
@@ -157,7 +152,7 @@ ensures refilling is only done once per command that causes 
a change,
 regardless of the number of after-change calls from commands doing
 complex processing.")
 
-(defun refill-after-change-function (beg end len)
+(defun refill-after-change-function (_beg end _len)
   "Function for `after-change-functions' which just sets `refill-doit'."
   (unless undo-in-progress
     (setq refill-doit end)))
@@ -232,9 +227,9 @@ For true \"word wrap\" behavior, use `visual-line-mode' 
instead."
     (kill-local-variable 'refill-saved-state))
   (if refill-mode
       (progn
-       (add-hook 'after-change-functions 'refill-after-change-function nil t)
-       (add-hook 'post-command-hook 'refill-post-command-function nil t)
-       (add-hook 'pre-command-hook 'refill-pre-command-function nil t)
+       (add-hook 'after-change-functions #'refill-after-change-function nil t)
+       (add-hook 'post-command-hook #'refill-post-command-function nil t)
+       (add-hook 'pre-command-hook #'refill-pre-command-function nil t)
         (setq-local refill-saved-state
                     (mapcar (lambda (s) (cons s (symbol-value s)))
                             '(fill-paragraph-function auto-fill-function)))
@@ -249,8 +244,8 @@ For true \"word wrap\" behavior, use `visual-line-mode' 
instead."
        (overlay-put refill-ignorable-overlay 'insert-behind-hooks
                     '(refill-adjust-ignorable-overlay))
        (auto-fill-mode 0))
-    (remove-hook 'after-change-functions 'refill-after-change-function t)
-    (remove-hook 'post-command-hook 'refill-post-command-function t)
+    (remove-hook 'after-change-functions #'refill-after-change-function t)
+    (remove-hook 'post-command-hook #'refill-post-command-function t)
     (kill-local-variable 'backward-delete-char-untabify-method)))
 
 (provide 'refill)
diff --git a/lisp/textmodes/reftex-auc.el b/lisp/textmodes/reftex-auc.el
index ae3faec..8429fce 100644
--- a/lisp/textmodes/reftex-auc.el
+++ b/lisp/textmodes/reftex-auc.el
@@ -1,4 +1,4 @@
-;;; reftex-auc.el --- RefTeX's interface to AUCTeX
+;;; reftex-auc.el --- RefTeX's interface to AUCTeX  -*- lexical-binding: t; -*-
 
 ;; Copyright (C) 1997-2021 Free Software Foundation, Inc.
 
@@ -69,6 +69,8 @@ What is being used depends upon `reftex-plug-into-AUCTeX'."
         (LaTeX-add-labels label))
     (TeX-argument-insert label optional)))
 
+(declare-function LaTeX-add-bibitems "latex") ;FIXME: Can't find the definition
+
 ;;;###autoload
 (defun reftex-arg-cite (optional &optional prompt definition)
   "Use `reftex-citation' or AUCTeX's code to insert a cite-key macro argument.
@@ -82,13 +84,13 @@ What is being used depends upon `reftex-plug-into-AUCTeX'."
                           (if prompt prompt "Add key")
                           " (default none): "))
       (setq items (multi-prompt "," t prompt (LaTeX-bibitem-list)))))
-    (apply 'LaTeX-add-bibitems items)
-    (TeX-argument-insert (mapconcat 'identity items reftex-cite-key-separator)
+    (apply #'LaTeX-add-bibitems items)
+    (TeX-argument-insert (mapconcat #'identity items reftex-cite-key-separator)
                         optional)))
 
 
 ;;;###autoload
-(defun reftex-arg-index-tag (optional &optional prompt &rest args)
+(defun reftex-arg-index-tag (optional &optional prompt &rest _args)
   "Prompt for an index tag with completion.
 This is the name of an index, not the entry."
   (let (tag taglist)
@@ -102,13 +104,13 @@ This is the name of an index, not the entry."
           (setq taglist
                 (cdr (assoc 'index-tags
                             (symbol-value reftex-docstruct-symbol)))
-                tag (completing-read prompt (mapcar 'list taglist))))
+                tag (completing-read prompt (mapcar #'list taglist))))
       ;; Just ask like AUCTeX does.
       (setq tag (read-string prompt)))
     (TeX-argument-insert tag optional)))
 
 ;;;###autoload
-(defun reftex-arg-index (optional &optional prompt &rest args)
+(defun reftex-arg-index (optional &optional prompt &rest _args)
   "Prompt for an index entry completing with known entries.
 Completion is specific for just one index, if the macro or a tag
 argument identify one of multiple indices."
@@ -149,23 +151,27 @@ argument identify one of multiple indices."
   ;; `reftex-plug-into-AUCTeX'.
 
   (if (reftex-plug-flag 0)
-      (setq LaTeX-label-function 'reftex-label)
-    (setq LaTeX-label-function nil))
-
-  (and (or (reftex-plug-flag 1) (reftex-plug-flag 2))
-       (fboundp 'TeX-arg-label)
-       (fset 'TeX-arg-label 'reftex-arg-label))
-
-  (and (reftex-plug-flag 3)
-       (fboundp 'TeX-arg-cite)
-       (fset 'TeX-arg-cite 'reftex-arg-cite))
-
-  (and (reftex-plug-flag 4)
-       (fboundp 'TeX-arg-index-tag)
-       (fset 'TeX-arg-index-tag 'reftex-arg-index-tag))
-  (and (reftex-plug-flag 4)
-       (fboundp 'TeX-arg-index)
-       (fset 'TeX-arg-index 'reftex-arg-index)))
+      (if (bound-and-true-p LaTeX-label-function)
+          (add-function :override LaTeX-label-function #'reftex-label)
+        (setq LaTeX-label-function #'reftex-label))
+    (if (eq #'reftex-label (bound-and-true-p LaTeX-label-function))
+        (setq LaTeX-label-function nil)
+      (remove-function LaTeX-label-function #'reftex-label)))
+
+  (if (or (reftex-plug-flag 1) (reftex-plug-flag 2))
+      (advice-add 'TeX-arg-label :override #'reftex-arg-label)
+    (advice-remove 'TeX-arg-label #'reftex-arg-label))
+
+  (if (reftex-plug-flag 3)
+      (advice-add 'TeX-arg-cite :override #'reftex-arg-cite)
+    (advice-remove 'TeX-arg-cite #'reftex-arg-cite))
+
+  (if (reftex-plug-flag 4)
+      (advice-add 'TeX-arg-index-tag :override #'reftex-arg-index-tag)
+    (advice-remove 'TeX-arg-index-tag #'reftex-arg-index-tag))
+  (if (reftex-plug-flag 4)
+      (advice-add 'TeX-arg-index :override #'reftex-arg-index)
+    (advice-remove 'TeX-arg-index #'reftex-arg-index)))
 
 ;;;###autoload
 (defun reftex-toggle-plug-into-AUCTeX ()
@@ -205,7 +211,7 @@ the label information is recompiled on next use."
       (when changed
         (put reftex-docstruct-symbol 'reftex-label-alist-style list)))))
 ;;;###autoload
-(defalias 'reftex-add-to-label-alist 'reftex-add-label-environments)
+(defalias 'reftex-add-to-label-alist #'reftex-add-label-environments)
 
 ;;;###autoload
 (defun reftex-add-section-levels (entry-list)
diff --git a/lisp/textmodes/reftex-cite.el b/lisp/textmodes/reftex-cite.el
index 5579e40..650d11d 100644
--- a/lisp/textmodes/reftex-cite.el
+++ b/lisp/textmodes/reftex-cite.el
@@ -1,4 +1,4 @@
-;;; reftex-cite.el --- creating citations with RefTeX
+;;; reftex-cite.el --- creating citations with RefTeX  -*- lexical-binding: t; 
-*-
 
 ;; Copyright (C) 1997-2021 Free Software Foundation, Inc.
 
@@ -310,11 +310,11 @@ Return list with entries."
     ;; Sorting
     (cond
      ((eq 'author reftex-sort-bibtex-matches)
-      (sort found-list 'reftex-bib-sort-author))
+      (sort found-list #'reftex-bib-sort-author))
      ((eq 'year   reftex-sort-bibtex-matches)
-      (sort found-list 'reftex-bib-sort-year))
+      (sort found-list #'reftex-bib-sort-year))
      ((eq 'reverse-year reftex-sort-bibtex-matches)
-      (sort found-list 'reftex-bib-sort-year-reverse))
+      (sort found-list #'reftex-bib-sort-year-reverse))
      (t found-list))))
 
 (defun reftex-bib-sort-author (e1 e2)
@@ -390,7 +390,7 @@ The environment should be located in FILES."
              (when (and start end)
                (setq entries
                      (append entries
-                             (mapcar 'reftex-parse-bibitem
+                             (mapcar #'reftex-parse-bibitem
                                      (delete ""
                                              (split-string
                                               (buffer-substring-no-properties
@@ -533,7 +533,7 @@ If FORMAT is non-nil `format' entry accordingly."
   "Format a BibTeX ENTRY so that it is nice to look at."
   (let*
       ((auth-list (reftex-get-bib-names "author" entry))
-       (authors (mapconcat 'identity auth-list ", "))
+       (authors (mapconcat #'identity auth-list ", "))
        (year      (reftex-get-bib-field "year" entry))
        (title     (reftex-get-bib-field "title" entry))
        (type      (reftex-get-bib-field "&type" entry))
@@ -607,7 +607,7 @@ If FORMAT is non-nil `format' entry accordingly."
         (push (substring text 0 (+ 60 (match-beginning 0))) lines)
         (setq text (substring text (+ 61 (match-beginning 0)))))
     (push text lines)
-    (setq text (mapconcat 'identity (nreverse lines) "\n     "))
+    (setq text (mapconcat #'identity (nreverse lines) "\n     "))
 
     (when (reftex-use-fonts)
       (put-text-property 0 (length text) 'face reftex-bib-author-face text))
@@ -676,7 +676,7 @@ While entering the regexp, completion on knows citation 
keys is possible.
       ;; All keys go into a single command - we need to trick a little
       ;; FIXME: Unfortunately, this means that commenting does not work right.
       (pop selected-entries)
-      (let ((concat-keys (mapconcat 'car selected-entries
+      (let ((concat-keys (mapconcat #'car selected-entries
                                    reftex-cite-key-separator)))
         (setq insert-entries
               (list (list concat-keys (cons "&key" concat-keys))))))
@@ -726,7 +726,7 @@ While entering the regexp, completion on knows citation 
keys is possible.
       (when (and reftex-mode
                  (fboundp 'LaTeX-add-bibitems)
                  reftex-plug-into-AUCTeX)
-        (apply 'LaTeX-add-bibitems (mapcar 'car selected-entries)))
+        (apply #'LaTeX-add-bibitems (mapcar #'car selected-entries)))
 
       ;; Produce the cite-view strings
       (when (and reftex-mode reftex-cache-cite-echo cite-view)
@@ -749,7 +749,7 @@ While entering the regexp, completion on knows citation 
keys is possible.
         (forward-char 1)))
 
     ;; Return the citation key
-    (mapcar 'car selected-entries)))
+    (mapcar #'car selected-entries)))
 
 (defun reftex-figure-out-cite-format (arg &optional no-insert format-key)
   "Check if there is already a cite command at point and change cite format
@@ -815,15 +815,16 @@ in order to only add another reference in the same cite 
command."
   (reftex-citation nil ?t))
 
 (defvar reftex-select-bib-map)
+(defvar reftex--found-list)
 (defun reftex-offer-bib-menu ()
   "Offer bib menu and return list of selected items."
   (let ((bibtype (reftex-bib-or-thebib))
-        found-list rtn key data selected-entries)
+        reftex--found-list rtn key data selected-entries)
     (while
         (not
          (catch 'done
            ;; Scan bibtex files
-           (setq found-list
+           (setq reftex--found-list
               (cond
                ((eq bibtype 'bib)
 ;              ((assq 'bib (symbol-value reftex-docstruct-symbol))
@@ -834,7 +835,7 @@ in order to only add another reference in the same cite 
command."
                 ;; using thebibliography environment.
                 (reftex-extract-bib-entries-from-thebibliography
                  (reftex-uniquify
-                  (mapcar 'cdr
+                  (mapcar #'cdr
                           (reftex-all-assq
                            'thebib (symbol-value reftex-docstruct-symbol))))))
                (reftex-default-bibliography
@@ -842,7 +843,7 @@ in order to only add another reference in the same cite 
command."
                 (reftex-extract-bib-entries (reftex-default-bibliography)))
                (t (error "No valid bibliography in this document, and no 
default available"))))
 
-           (unless found-list
+           (unless reftex--found-list
              (error "Sorry, no matches found"))
 
           ;; Remember where we came from
@@ -854,11 +855,11 @@ in order to only add another reference in the same cite 
command."
             (delete-other-windows)
             (reftex-kill-buffer "*RefTeX Select*")
             (switch-to-buffer-other-window "*RefTeX Select*")
-            (unless (eq major-mode 'reftex-select-bib-mode)
+            (unless (derived-mode-p 'reftex-select-bib-mode)
               (reftex-select-bib-mode))
-            (let ((buffer-read-only nil))
+            (let ((inhibit-read-only t))
               (erase-buffer)
-              (reftex-insert-bib-matches found-list))
+              (reftex-insert-bib-matches reftex--found-list))
             (setq buffer-read-only t)
             (if (= 0 (buffer-size))
                 (error "No matches found"))
@@ -881,34 +882,36 @@ in order to only add another reference in the same cite 
command."
                 (throw 'done nil))
                ((eq key ?r)
                 ;; Restrict with new regular expression
-                (setq found-list (reftex-restrict-bib-matches found-list))
+                (setq reftex--found-list
+                      (reftex-restrict-bib-matches reftex--found-list))
                 (let ((buffer-read-only nil))
                   (erase-buffer)
-                  (reftex-insert-bib-matches found-list))
+                  (reftex-insert-bib-matches reftex--found-list))
                 (goto-char 1))
                ((eq key ?A)
                 ;; Take all (marked)
                 (setq selected-entries
                       (if reftex-select-marked
-                          (mapcar 'car (nreverse reftex-select-marked))
-                        found-list))
+                          (mapcar #'car (nreverse reftex-select-marked))
+                        reftex--found-list))
                 (throw 'done t))
                ((eq key ?a)
                 ;; Take all (marked), and push the symbol 'concat
                 (setq selected-entries
                       (cons 'concat
                             (if reftex-select-marked
-                                (mapcar 'car (nreverse reftex-select-marked))
-                              found-list)))
+                                (mapcar #'car (nreverse reftex-select-marked))
+                              reftex--found-list)))
                 (throw 'done t))
                ((eq key ?e)
                 ;; Take all (marked), and push the symbol 'concat
-                (reftex-extract-bib-file found-list reftex-select-marked)
+                (reftex-extract-bib-file reftex--found-list
+                                         reftex-select-marked)
                 (setq selected-entries "BibTeX database file created")
                 (throw 'done t))
                ((eq key ?E)
                 ;; Take all (marked), and push the symbol 'concat
-                (reftex-extract-bib-file found-list reftex-select-marked
+                (reftex-extract-bib-file reftex--found-list 
reftex-select-marked
                                          'complement)
                 (setq selected-entries "BibTeX database file created")
                 (throw 'done t))
@@ -918,7 +921,7 @@ in order to only add another reference in the same cite 
command."
                 (setq selected-entries
                       (if reftex-select-marked
                           (cons 'concat
-                                (mapcar 'car (nreverse reftex-select-marked)))
+                                (mapcar #'car (nreverse reftex-select-marked)))
                         (if data (list data) nil)))
                 (throw 'done t))
                ((stringp key)
@@ -971,7 +974,7 @@ in order to only add another reference in the same cite 
command."
                              nil)
                          (cdr (assoc "&entry" x))))
                      all)))
-    (insert (mapconcat 'identity all "\n\n"))
+    (insert (mapconcat #'identity all "\n\n"))
     (save-buffer)
     (goto-char (point-min))))
 
@@ -1004,7 +1007,7 @@ in order to only add another reference in the same cite 
command."
             last (nth (1- n) namelist))
       (setcdr (nthcdr (- n 2) namelist) nil)
       (concat
-       (mapconcat 'identity namelist (nth 0 reftex-cite-punctuation))
+       (mapconcat #'identity namelist (nth 0 reftex-cite-punctuation))
        (nth 1 reftex-cite-punctuation)
        last)))))
 
@@ -1100,7 +1103,7 @@ in order to only add another reference in the same cite 
command."
         (put reftex-docstruct-symbol 'modified t)))
     string))
 
-(defun reftex-bibtex-selection-callback (data ignore no-revisit)
+(defun reftex-bibtex-selection-callback (data _ignore no-revisit)
   "Callback function to be called from the BibTeX selection, in
 order to display context.  This function is relatively slow and not
 recommended for follow mode.  It works OK for individual lookups."
@@ -1119,7 +1122,7 @@ recommended for follow mode.  It works OK for individual 
lookups."
 ;        ((assq 'thebib (symbol-value reftex-docstruct-symbol))
           (setq bibfile-list
                 (reftex-uniquify
-                 (mapcar 'cdr
+                 (mapcar #'cdr
                          (reftex-all-assq
                           'thebib (symbol-value reftex-docstruct-symbol))))
                 item t))
@@ -1163,7 +1166,7 @@ recommended for follow mode.  It works OK for individual 
lookups."
   "Return a list of BibTeX @string references that appear as values in ALIST."
   (reftex-remove-if (lambda (x) (string-match "^\\([\"{]\\|[0-9]+$\\)" x))
                    ;; get list of values, discard keys
-                   (mapcar 'cdr
+                   (mapcar #'cdr
                            ;; remove &key and &type entries
                            (reftex-remove-if (lambda (pair)
                                                (string-match "^&" (car pair)))
@@ -1186,7 +1189,7 @@ created files in the variables 
`reftex-create-bibtex-header' or
   (interactive "FNew BibTeX file: ")
   (let ((keys (reftex-all-used-citation-keys))
         (files (reftex-get-bibfile-list))
-        file key entries beg end entry string-keys string-entries)
+        key entries beg end entry string-keys string-entries)
     (save-current-buffer
       (dolist (file files)
         (set-buffer (reftex-get-file-buffer-force file 'mark))
@@ -1252,9 +1255,9 @@ created files in the variables 
`reftex-create-bibtex-header' or
           (error "Abort")))
     (erase-buffer)
     (if reftex-create-bibtex-header (insert reftex-create-bibtex-header 
"\n\n"))
-    (insert (mapconcat 'identity (reverse string-entries) "\n\n"))
+    (insert (mapconcat #'identity (reverse string-entries) "\n\n"))
     (if string-entries (insert "\n\n\n"))
-    (insert (mapconcat 'identity (reverse entries) "\n\n"))
+    (insert (mapconcat #'identity (reverse entries) "\n\n"))
     (if reftex-create-bibtex-footer (insert "\n\n" 
reftex-create-bibtex-footer))
     (goto-char (point-min))
     (save-buffer)
diff --git a/lisp/textmodes/reftex-dcr.el b/lisp/textmodes/reftex-dcr.el
index e517cea..a21dd33 100644
--- a/lisp/textmodes/reftex-dcr.el
+++ b/lisp/textmodes/reftex-dcr.el
@@ -1,4 +1,4 @@
-;;; reftex-dcr.el --- viewing cross references and citations with RefTeX
+;;; reftex-dcr.el --- viewing cross references and citations with RefTeX  -*- 
lexical-binding: t; -*-
 
 ;; Copyright (C) 1997-2021 Free Software Foundation, Inc.
 
@@ -132,7 +132,7 @@ to the functions `reftex-view-cr-cite' and 
`reftex-view-cr-ref'."
      ((eq bibtype 'thebib)
       (setq item t
             files (reftex-uniquify
-                   (mapcar 'cdr
+                   (mapcar #'cdr
                            (reftex-all-assq
                             'thebib (symbol-value reftex-docstruct-symbol))))))
      (reftex-default-bibliography
@@ -161,10 +161,10 @@ to the functions `reftex-view-cr-cite' and 
`reftex-view-cr-ref'."
           (shrink-window (1- (- (window-height) size)))
           (recenter 0))
         ;; Arrange restoration
-        (add-hook 'pre-command-hook 'reftex-restore-window-conf))
+        (add-hook 'pre-command-hook #'reftex-restore-window-conf))
 
         ;; Normal display in other window
-      (add-hook 'pre-command-hook 'reftex-highlight-shall-die)
+      (add-hook 'pre-command-hook #'reftex-highlight-shall-die)
       (setq pop-win (selected-window))
       (select-window win)
       (goto-char pos)
@@ -212,13 +212,13 @@ to the functions `reftex-view-cr-cite' and 
`reftex-view-cr-ref'."
           (error (set-window-configuration window-conf)
                  (message "ref: Label %s not found" label)
                  (error "ref: Label %s not found" label)))) ;; 2nd is line OK
-      (add-hook 'pre-command-hook 'reftex-highlight-shall-die)
+      (add-hook 'pre-command-hook #'reftex-highlight-shall-die)
 
       (when (eq how 'tmp-window)
         ;; Resize window and arrange restoration
         (shrink-window (1- (- (window-height) 9)))
         (recenter '(4))
-        (add-hook 'pre-command-hook 'reftex-restore-window-conf))
+        (add-hook 'pre-command-hook #'reftex-restore-window-conf))
       (setq pop-win (selected-window))
       (select-window win)
       (goto-char pos)
@@ -266,7 +266,7 @@ With argument, actually select the window showing the cross 
reference."
 (defun reftex-restore-window-conf ()
   (set-window-configuration (get 'reftex-auto-view-crossref 'last-window-conf))
   (put 'reftex-auto-view-crossref 'last-window-conf nil)
-  (remove-hook 'pre-command-hook 'reftex-restore-window-conf))
+  (remove-hook 'pre-command-hook #'reftex-restore-window-conf))
 
 (defun reftex-echo-ref (label entry docstruct)
   ;; Display crossref info in echo area.
@@ -320,10 +320,6 @@ With argument, actually select the window showing the 
cross reference."
       (with-current-buffer buf
         (run-hooks 'reftex-display-copied-context-hook)))))
 
-(defvar reftex-use-itimer-in-xemacs nil
-  "Non-nil means use the idle timers in XEmacs for crossref display.
-Currently, idle timer restart is broken and we use the post-command-hook.")
-
 ;;;###autoload
 (defun reftex-toggle-auto-view-crossref ()
   "Toggle the automatic display of crossref information in the echo area.
@@ -332,36 +328,16 @@ will display info in the echo area."
   (interactive)
   (if reftex-auto-view-crossref-timer
       (progn
-        (if (featurep 'xemacs)
-            (if reftex-use-itimer-in-xemacs
-                (delete-itimer reftex-auto-view-crossref-timer)
-              (remove-hook 'post-command-hook 'reftex-start-itimer-once))
-          (cancel-timer reftex-auto-view-crossref-timer))
+        (cancel-timer reftex-auto-view-crossref-timer)
         (setq reftex-auto-view-crossref-timer nil)
         (message "Automatic display of crossref information was turned off"))
     (setq reftex-auto-view-crossref-timer
-          (if (featurep 'xemacs)
-              (if reftex-use-itimer-in-xemacs
-                  (start-itimer "RefTeX Idle Timer"
-                                'reftex-view-crossref-when-idle
-                                reftex-idle-time reftex-idle-time t)
-                (add-hook 'post-command-hook 'reftex-start-itimer-once)
-                t)
-            (run-with-idle-timer
-             reftex-idle-time t 'reftex-view-crossref-when-idle)))
+          (run-with-idle-timer
+           reftex-idle-time t #'reftex-view-crossref-when-idle))
     (unless reftex-auto-view-crossref
       (setq reftex-auto-view-crossref t))
     (message "Automatic display of crossref information was turned on")))
 
-(defun reftex-start-itimer-once ()
-   (and (featurep 'xemacs)
-       reftex-mode
-        (not (itimer-live-p reftex-auto-view-crossref-timer))
-        (setq reftex-auto-view-crossref-timer
-              (start-itimer "RefTeX Idle Timer"
-                            'reftex-view-crossref-when-idle
-                            reftex-idle-time nil t))))
-
 ;;;###autoload
 (defun reftex-view-crossref-from-bibtex (&optional arg)
   "View location in a LaTeX document which cites the BibTeX entry at point.
@@ -431,7 +407,7 @@ Calling this function several times find successive 
citation locations."
           (put 'reftex-view-regexp-match :cnt (cl-incf cnt))
           (reftex-highlight 0 (match-beginning highlight-group)
                             (match-end highlight-group))
-          (add-hook 'pre-command-hook 'reftex-highlight-shall-die)
+          (add-hook 'pre-command-hook #'reftex-highlight-shall-die)
           (setq pop-window (selected-window)))
       (put 'reftex-view-regexp-match :props nil)
       (or cont (set-window-configuration window-conf)))
diff --git a/lisp/textmodes/reftex-global.el b/lisp/textmodes/reftex-global.el
index 4d02160..3b7518e 100644
--- a/lisp/textmodes/reftex-global.el
+++ b/lisp/textmodes/reftex-global.el
@@ -1,4 +1,4 @@
-;;; reftex-global.el --- operations on entire documents with RefTeX
+;;; reftex-global.el --- operations on entire documents with RefTeX  -*- 
lexical-binding: t; -*-
 
 ;; Copyright (C) 1997-2021 Free Software Foundation, Inc.
 
@@ -39,7 +39,7 @@ The TAGS file is also immediately visited with 
`visit-tags-table'."
   (reftex-access-scan-info current-prefix-arg)
   (let* ((master (reftex-TeX-master-file))
          (files  (reftex-all-document-files))
-         (cmd    (format "etags %s" (mapconcat 'shell-quote-argument
+         (cmd    (format "etags %s" (mapconcat #'shell-quote-argument
                                               files " "))))
     (with-current-buffer (reftex-get-file-buffer-force master)
       (message "Running etags to create TAGS file...")
@@ -65,7 +65,7 @@ No active TAGS table is required."
   (let* ((files  (reftex-all-document-files t))
          (cmd    (format
                   "%s %s" grep-cmd
-                  (mapconcat 'identity files " "))))
+                  (mapconcat #'identity files " "))))
     (grep cmd)))
 
 ;;;###autoload
@@ -160,7 +160,7 @@ No active TAGS table is required."
       (when (and (car (car dlist))
                  (cdr (car dlist)))
         (cl-incf cnt)
-        (insert (mapconcat 'identity (car dlist) "\n    ") "\n"))
+        (insert (mapconcat #'identity (car dlist) "\n    ") "\n"))
       (pop dlist))
     (goto-char (point-min))
     (when (= cnt 0)
@@ -208,7 +208,7 @@ one with the `xr' package."
       (error "Abort"))
   ;; Make the translation list
   (let* ((re-core (concat "\\("
-                          (mapconcat 'cdr reftex-typekey-to-prefix-alist "\\|")
+                          (mapconcat #'cdr reftex-typekey-to-prefix-alist 
"\\|")
                           "\\)"))
          (label-re (concat "\\`" re-core "\\([0-9]+\\)\\'"))
          (search-re (concat "[{,]\\(" re-core "\\([0-9]+\\)\\)[,}]"))
@@ -326,7 +326,7 @@ labels."
         file buffer)
     (save-current-buffer
       (while (setq file (pop files))
-        (setq buffer (reftex-get-buffer-visiting file))
+        (setq buffer (find-buffer-visiting file))
         (when buffer
           (set-buffer buffer)
           (save-buffer))))))
@@ -344,7 +344,7 @@ Also checks if buffers visiting the files are in read-only 
mode."
         (ding)
         (or (y-or-n-p (format "No write access to %s. Continue? " file))
             (error "Abort")))
-      (when (and (setq buf (reftex-get-buffer-visiting file))
+      (when (and (setq buf (find-buffer-visiting file))
                  (with-current-buffer buf
                    buffer-read-only))
         (ding)
@@ -366,10 +366,10 @@ Also checks if buffers visiting the files are in 
read-only mode."
   (goto-char (if isearch-forward (point-min) (point-max))))
 
 (defun reftex-isearch-push-state-function ()
-  `(lambda (cmd)
-     (reftex-isearch-pop-state-function cmd ,(current-buffer))))
+  (let ((buf (current-buffer)))
+    (lambda (cmd) (reftex-isearch-pop-state-function cmd buf))))
 
-(defun reftex-isearch-pop-state-function (cmd buffer)
+(defun reftex-isearch-pop-state-function (_cmd buffer)
   (switch-to-buffer buffer))
 
 (defun reftex-isearch-isearch-search (string bound noerror)
@@ -451,17 +451,17 @@ With no argument, this command toggles
                  (if (boundp 'multi-isearch-next-buffer-function)
                      (set (make-local-variable
                            'multi-isearch-next-buffer-function)
-                          'reftex-isearch-switch-to-next-file)
+                          #'reftex-isearch-switch-to-next-file)
                    (set (make-local-variable 'isearch-wrap-function)
-                        'reftex-isearch-wrap-function)
+                        #'reftex-isearch-wrap-function)
                    (set (make-local-variable 'isearch-search-fun-function)
-                        (lambda () 'reftex-isearch-isearch-search))
+                        (lambda () #'reftex-isearch-isearch-search))
                    (set (make-local-variable 'isearch-push-state-function)
-                        'reftex-isearch-push-state-function)
+                        #'reftex-isearch-push-state-function)
                    (set (make-local-variable 'isearch-next-buffer-function)
-                        'reftex-isearch-switch-to-next-file))
+                        #'reftex-isearch-switch-to-next-file))
                  (setq reftex-isearch-minor-mode t))))
-           (add-hook 'reftex-mode-hook 'reftex-isearch-minor-mode))
+           (add-hook 'reftex-mode-hook #'reftex-isearch-minor-mode))
        (dolist (crt-buf (buffer-list))
          (with-current-buffer crt-buf
            (when reftex-mode
@@ -472,7 +472,7 @@ With no argument, this command toggles
                (kill-local-variable 'isearch-push-state-function)
                (kill-local-variable 'isearch-next-buffer-function))
              (setq reftex-isearch-minor-mode nil))))
-       (remove-hook 'reftex-mode-hook 'reftex-isearch-minor-mode)))
+       (remove-hook 'reftex-mode-hook #'reftex-isearch-minor-mode)))
     ;; Force mode line redisplay.
     (set-buffer-modified-p (buffer-modified-p))))
 
diff --git a/lisp/textmodes/reftex-index.el b/lisp/textmodes/reftex-index.el
index 5049ffb..28cc7db 100644
--- a/lisp/textmodes/reftex-index.el
+++ b/lisp/textmodes/reftex-index.el
@@ -1,4 +1,4 @@
-;;; reftex-index.el --- index support with RefTeX
+;;; reftex-index.el --- index support with RefTeX  -*- lexical-binding: t; -*-
 
 ;; Copyright (C) 1997-2021 Free Software Foundation, Inc.
 
@@ -30,8 +30,6 @@
 (require 'reftex)
 
 ;; START remove for XEmacs release
-(defvar mark-active)
-(defvar transient-mark-mode)
 (defvar TeX-master)
 ;; END remove for XEmacs release
 
@@ -49,7 +47,7 @@ which is part of AUCTeX, the string is first processed with 
the
   (interactive "P")
   (let* ((use-default (not (equal arg '(16))))  ; check for double prefix
          ;; check if we have an active selection
-         (active (reftex-region-active-p))
+         (active (region-active-p))
          (beg (if active
                   (region-beginning)
                 (save-excursion
@@ -89,7 +87,7 @@ which is part of AUCTeX, the string is first processed with 
the
         (reftex-index def-char full-entry def-tag sel)))))
 
 ;;;###autoload
-(defun reftex-index (&optional char key tag sel no-insert)
+(defun reftex-index (&optional char key tag sel _no-insert)
   "Query for an index macro and insert it along with its arguments.
 The index macros available are those defined in `reftex-index-macro' or
 by a call to `reftex-add-index-macros', typically from an AUCTeX style file.
@@ -178,7 +176,7 @@ will prompt for other arguments."
                                                  (format "default %s" default))
                                        "")))
                           ": ")))
-        (tag (completing-read prompt (mapcar 'list index-tags))))
+        (tag (completing-read prompt (mapcar #'list index-tags))))
     (if (and default (equal tag "")) (setq tag default))
     (reftex-update-default-index tag)
     tag))
@@ -239,7 +237,7 @@ will prompt for other arguments."
                           (format "[^M]  %s (the default)\n" default)
                         "")
                       (mapconcat (lambda(x)
-                                   (apply 'format "[%c]   %s" x))
+                                   (apply #'format "[%c]   %s" x))
                                  tag-alist "\n")))
         ;; Query the user for an index-tag
         (setq rpl (reftex-select-with-char prompt help 3 t))
@@ -278,56 +276,57 @@ will prompt for other arguments."
 (defvar reftex-index-mode-map
   (let ((map (make-sparse-keymap)))
     ;; Index map
-    (define-key map (if (featurep 'xemacs) [(button2)] [(mouse-2)])
-      'reftex-index-mouse-goto-line-and-hide)
+    (define-key map [(mouse-2)] #'reftex-index-mouse-goto-line-and-hide)
     (define-key map [follow-link] 'mouse-face)
 
     (substitute-key-definition
-     'next-line 'reftex-index-next map global-map)
+     #'next-line #'reftex-index-next map global-map)
     (substitute-key-definition
-     'previous-line 'reftex-index-previous map global-map)
-
-    (define-key map "n" 'reftex-index-next)
-    (define-key map "p" 'reftex-index-previous)
-    (define-key map "?" 'reftex-index-show-help)
-    (define-key map " " 'reftex-index-view-entry)
-    (define-key map "\C-m" 'reftex-index-goto-entry-and-hide)
-    (define-key map "\C-i" 'reftex-index-goto-entry)
-    (define-key map "\C-k" 'reftex-index-kill)
-    (define-key map "r" 'reftex-index-rescan)
-    (define-key map "R" 'reftex-index-Rescan)
-    (define-key map "g" 'revert-buffer)
-    (define-key map "q" 'reftex-index-quit)
-    (define-key map "k" 'reftex-index-quit-and-kill)
-    (define-key map "f" 'reftex-index-toggle-follow)
-    (define-key map "s" 'reftex-index-switch-index-tag)
-    (define-key map "e" 'reftex-index-edit)
-    (define-key map "^" 'reftex-index-level-up)
-    (define-key map "_" 'reftex-index-level-down)
-    (define-key map "}" 'reftex-index-restrict-to-section)
-    (define-key map "{" 'reftex-index-widen)
-    (define-key map ">" 'reftex-index-restriction-forward)
-    (define-key map "<" 'reftex-index-restriction-backward)
-    (define-key map "(" 'reftex-index-toggle-range-beginning)
-    (define-key map ")" 'reftex-index-toggle-range-end)
-    (define-key map "|" 'reftex-index-edit-attribute)
-    (define-key map "@" 'reftex-index-edit-visual)
-    (define-key map "*" 'reftex-index-edit-key)
-    (define-key map "\C-c=" 'reftex-index-goto-toc)
-    (define-key map "c" 'reftex-index-toggle-context)
+     #'previous-line #'reftex-index-previous map global-map)
+
+    (define-key map "n" #'reftex-index-next)
+    (define-key map "p" #'reftex-index-previous)
+    (define-key map "?" #'reftex-index-show-help)
+    (define-key map " " #'reftex-index-view-entry)
+    (define-key map "\C-m" #'reftex-index-goto-entry-and-hide)
+    (define-key map "\C-i" #'reftex-index-goto-entry)
+    (define-key map "\C-k" #'reftex-index-kill)
+    (define-key map "r" #'reftex-index-rescan)
+    (define-key map "R" #'reftex-index-Rescan)
+    (define-key map "g" #'revert-buffer)
+    (define-key map "q" #'reftex-index-quit)
+    (define-key map "k" #'reftex-index-quit-and-kill)
+    (define-key map "f" #'reftex-index-toggle-follow)
+    (define-key map "s" #'reftex-index-switch-index-tag)
+    (define-key map "e" #'reftex-index-edit)
+    (define-key map "^" #'reftex-index-level-up)
+    (define-key map "_" #'reftex-index-level-down)
+    (define-key map "}" #'reftex-index-restrict-to-section)
+    (define-key map "{" #'reftex-index-widen)
+    (define-key map ">" #'reftex-index-restriction-forward)
+    (define-key map "<" #'reftex-index-restriction-backward)
+    (define-key map "(" #'reftex-index-toggle-range-beginning)
+    (define-key map ")" #'reftex-index-toggle-range-end)
+    (define-key map "|" #'reftex-index-edit-attribute)
+    (define-key map "@" #'reftex-index-edit-visual)
+    (define-key map "*" #'reftex-index-edit-key)
+    (define-key map "\C-c=" #'reftex-index-goto-toc)
+    (define-key map "c" #'reftex-index-toggle-context)
 
     ;; The capital letters and the exclamation mark
-    (cl-loop for key across (concat "!" reftex-index-section-letters) do
-             (define-key map (vector (list key))
-               (list 'lambda '() '(interactive)
-                     (list 'reftex-index-goto-letter key))))
+    (mapc (lambda (key)
+            (define-key map (vector (list key))
+              (lambda () (interactive)
+                (reftex-index-goto-letter key))))
+          (concat "!" reftex-index-section-letters))
 
     (easy-menu-define reftex-index-menu map
       "Menu for Index buffer"
       '("Index"
         ["Goto section A-Z"
          (message "To go to a section, just press any of: !%s"
-                  reftex-index-section-letters) t]
+                  reftex-index-section-letters)
+         t]
         ["Show Entry" reftex-index-view-entry t]
         ["Go To Entry" reftex-index-goto-entry t]
         ["Exit & Go To Entry" reftex-index-goto-entry-and-hide t]
@@ -394,7 +393,7 @@ Press `?' for a summary of important key bindings, or check 
the menu.
 Here are all local bindings.
 
 \\{reftex-index-mode-map}"
-  (set (make-local-variable 'revert-buffer-function) 'reftex-index-revert)
+  (set (make-local-variable 'revert-buffer-function) #'reftex-index-revert)
   (set (make-local-variable 'reftex-index-restriction-data) nil)
   (set (make-local-variable 'reftex-index-restriction-indicator) nil)
   (setq mode-line-format
@@ -403,15 +402,9 @@ Here are all local bindings.
               "  R<" 'reftex-index-restriction-indicator ">"
               " -%-"))
   (setq truncate-lines t)
-  (when (featurep 'xemacs)
-    ;; XEmacs needs the call to make-local-hook
-    (make-local-hook 'post-command-hook)
-    (make-local-hook 'pre-command-hook))
   (make-local-variable 'reftex-last-follow-point)
-  (when (featurep 'xemacs)
-    (easy-menu-add reftex-index-menu reftex-index-mode-map))
-  (add-hook 'post-command-hook 'reftex-index-post-command-hook nil t)
-  (add-hook 'pre-command-hook  'reftex-index-pre-command-hook nil t))
+  (add-hook 'post-command-hook #'reftex-index-post-command-hook nil t)
+  (add-hook 'pre-command-hook  #'reftex-index-pre-command-hook nil t))
 
 (defconst reftex-index-help
 "                      AVAILABLE KEYS IN INDEX BUFFER
@@ -450,7 +443,7 @@ _ ^        Add/Remove parent key (to make this item a 
subitem).
          (match
           (cond
            ((or (not no-revisit)
-                (reftex-get-buffer-visiting file))
+                (find-buffer-visiting file))
             (switch-to-buffer-other-window
              (reftex-get-file-buffer-force file nil))
             (goto-char (or pos (point-min)))
@@ -567,7 +560,7 @@ SPC=view TAB=goto RET=goto+hide [e]dit [q]uit [r]escan 
[f]ollow [?]Help
       (run-hooks 'reftex-display-copied-context-hook)
       (message "Building %s buffer...done." buffer-name)
       (setq buffer-read-only t))
-    (and locations (apply 'reftex-find-start-point (point) locations))
+    (and locations (apply #'reftex-find-start-point (point) locations))
     (if reftex-index-restriction-indicator
         (message "Index restricted: <%s>" 
reftex-index-restriction-indicator))))
 
@@ -582,7 +575,7 @@ SPC=view TAB=goto RET=goto+hide [e]dit [q]uit [r]escan 
[f]ollow [?]Help
          (indent "   ")
          (context reftex-index-include-context)
          (context-indent (concat indent "  "))
-         (section-chars (mapcar 'identity reftex-index-section-letters))
+         (section-chars (mapcar #'identity reftex-index-section-letters))
          (this-section-char 0)
          (font (reftex-use-fonts))
          (bor (car reftex-index-restriction-data))
@@ -733,9 +726,9 @@ SPC=view TAB=goto RET=goto+hide [e]dit [q]uit [r]escan 
[f]ollow [?]Help
   (if reftex-index-follow-mode
       (setq reftex-index-follow-mode 1)))
 
-(defun reftex-index-next (&optional arg)
+(defun reftex-index-next (&optional _arg)
   "Move to next selectable item."
-  (interactive "p")
+  (interactive "^")
   (setq reftex-callback-fwd t)
   (or (eobp) (forward-char 1))
   (goto-char (or (next-single-property-change (point) :data)
@@ -743,9 +736,9 @@ SPC=view TAB=goto RET=goto+hide [e]dit [q]uit [r]escan 
[f]ollow [?]Help
   (unless (get-text-property (point) :data)
     (goto-char (or (next-single-property-change (point) :data)
                    (point)))))
-(defun reftex-index-previous (&optional arg)
+(defun reftex-index-previous (&optional _arg)
   "Move to previous selectable item."
-  (interactive "p")
+  (interactive "^")
   (setq reftex-callback-fwd nil)
   (goto-char (or (previous-single-property-change (point) :data)
                  (point)))
@@ -793,7 +786,7 @@ Label context is only displayed when the labels are there 
as well."
   (or (one-window-p) (delete-window))
   (switch-to-buffer (marker-buffer reftex-index-return-marker))
   (goto-char (or (marker-position reftex-index-return-marker) (point))))
-(defun reftex-index-goto-toc (&rest ignore)
+(defun reftex-index-goto-toc (&rest _ignore)
   "Switch to the table of contents of the current document.
 The function will go to the section where the entry at point was defined."
   (interactive)
@@ -802,7 +795,7 @@ The function will go to the section where the entry at 
point was defined."
     (switch-to-buffer (marker-buffer reftex-index-return-marker)))
   (delete-other-windows)
   (reftex-toc))
-(defun reftex-index-rescan (&rest ignore)
+(defun reftex-index-rescan (&rest _ignore)
   "Regenerate the *Index* buffer after reparsing file of section at point."
   (interactive)
   (let ((index-tag reftex-index-tag))
@@ -818,7 +811,7 @@ The function will go to the section where the entry at 
point was defined."
             (reftex-display-index index-tag nil 'redo line)))
       (reftex-index-Rescan))
     (reftex-kill-temporary-buffers)))
-(defun reftex-index-Rescan (&rest ignore)
+(defun reftex-index-Rescan (&rest _ignore)
   "Regenerate the *Index* buffer after reparsing the entire document."
   (interactive)
   (let ((index-tag reftex-index-tag)
@@ -827,7 +820,7 @@ The function will go to the section where the entry at 
point was defined."
      (reftex-get-file-buffer-force reftex-last-index-file))
     (setq current-prefix-arg '(16))
     (reftex-display-index index-tag nil 'redo line)))
-(defun reftex-index-revert (&rest ignore)
+(defun reftex-index-revert (&rest _ignore)
   "Regenerate the *Index* from the internal lists.  No reparsing os done."
   (interactive)
   (let ((buf (current-buffer))
@@ -840,7 +833,7 @@ The function will go to the section where the entry at 
point was defined."
     (setq current-prefix-arg nil
           reftex-last-follow-point 1)
     (reftex-display-index index-tag nil 'redo data line)))
-(defun reftex-index-switch-index-tag (&rest ignore)
+(defun reftex-index-switch-index-tag (&rest _ignore)
   "Switch to a different index of the same document."
   (interactive)
   (switch-to-buffer
@@ -865,14 +858,14 @@ The function will go to the section where the entry at 
point was defined."
             reftex-index-restriction-indicator (nth 6 bor) )))
   (reftex-index-revert))
 
-(defun reftex-index-widen (&rest ignore)
+(defun reftex-index-widen (&rest _ignore)
   "Show the unrestricted index (all entries)."
   (interactive)
   (setq reftex-index-restriction-indicator nil
         reftex-index-restriction-data nil)
   (reftex-index-revert)
   (message "Index widened"))
-(defun reftex-index-restriction-forward (&rest ignore)
+(defun reftex-index-restriction-forward (&rest _ignore)
   "Restrict to previous section.
 When index is currently unrestricted, restrict it to a section.
 When index is restricted, select the next section as restriction criterion."
@@ -888,7 +881,7 @@ When index is restricted, select the next section as 
restriction criterion."
                   (car (memq (assq 'toc (cdr (memq bor docstruct)))
                              docstruct))))
       (reftex-index-revert))))
-(defun reftex-index-restriction-backward (&rest ignore)
+(defun reftex-index-restriction-backward (&rest _ignore)
   "Restrict to next section.
 When index is currently unrestricted, restrict it to a section.
 When index is restricted, select the previous section as restriction 
criterion."
@@ -986,7 +979,7 @@ When index is restricted, select the previous section as 
restriction criterion."
     (setq analyze (reftex-index-analyze-entry data)
           attr (nth 2 analyze))
     (setf (nth 2 analyze) (if (string= attr bor) "" bor))
-    (setq new (apply 'concat analyze))
+    (setq new (apply #'concat analyze))
     (reftex-index-change-entry
      new (if (string= (nth 2 analyze) bor)
              "Entry is now START-OF-PAGE-RANGE"
@@ -1002,7 +995,7 @@ When index is restricted, select the previous section as 
restriction criterion."
     (setq analyze (reftex-index-analyze-entry data)
           attr (nth 2 analyze))
     (setf (nth 2 analyze) (if (string= attr eor) "" eor))
-    (setq new (apply 'concat analyze))
+    (setq new (apply #'concat analyze))
     (reftex-index-change-entry
      new (if (string= (nth 2 analyze) eor)
              "Entry is now END-OF-PAGE-RANGE"
@@ -1043,7 +1036,7 @@ When index is restricted, select the previous section as 
restriction criterion."
                (error "Invalid value")
              (setf (nth n analyze) npart)))
           (t (setf (nth n analyze) (concat initial npart))))
-    (setq new (apply 'concat analyze))
+    (setq new (apply #'concat analyze))
     ;; Change the entry and insert the changed version into the index.
     (reftex-index-change-entry
      new (if (string= npart "")
@@ -1180,27 +1173,50 @@ This gets refreshed in every phrases command.")
 (defvar reftex-index-phrases-files nil
   "List of document files relevant for the phrases file.")
 
-(defvar reftex-index-phrases-font-lock-keywords nil
-  "Font lock keywords for reftex-index-phrases-mode.")
-(defvar reftex-index-phrases-font-lock-defaults nil
-  "Font lock defaults for reftex-index-phrases-mode.")
+(defvar reftex-index-phrases-font-lock-keywords
+  (list
+   (cons reftex-index-phrases-comment-regexp 'font-lock-comment-face)
+   (list reftex-index-phrases-macrodef-regexp
+         '(1 font-lock-type-face)
+         '(2 font-lock-keyword-face)
+         '(3 'secondary-selection)
+         '(4 font-lock-function-name-face)
+         '(5 'secondary-selection)
+         '(6 font-lock-string-face))
+   (list reftex-index-phrases-phrase-regexp1
+         '(1 font-lock-keyword-face)
+         '(2 'secondary-selection)
+         '(3 font-lock-string-face)
+         '(4 'secondary-selection))
+   (list reftex-index-phrases-phrase-regexp2
+         '(1 font-lock-keyword-face)
+         '(2 'secondary-selection)
+         '(3 font-lock-string-face)
+         '(4 'secondary-selection)
+         '(5 font-lock-function-name-face))
+   '("^\t$" . 'secondary-selection))
+  "Font lock keywords for `reftex-index-phrases-mode'.")
+(defvar reftex-index-phrases-font-lock-defaults
+  '((reftex-index-phrases-font-lock-keywords)
+    nil t nil beginning-of-line)
+  "Font lock defaults for `reftex-index-phrases-mode'.")
 (define-obsolete-variable-alias
   'reftex-index-phrases-map 'reftex-index-phrases-mode-map "24.1")
 (defvar reftex-index-phrases-mode-map
   (let ((map (make-sparse-keymap)))
     ;; Keybindings and Menu for phrases buffer
-    (define-key map "\C-c\C-c" 'reftex-index-phrases-save-and-return)
-    (define-key map "\C-c\C-x" 'reftex-index-this-phrase)
-    (define-key map "\C-c\C-f" 'reftex-index-next-phrase)
-    (define-key map "\C-c\C-r" 'reftex-index-region-phrases)
-    (define-key map "\C-c\C-a" 'reftex-index-all-phrases)
-    (define-key map "\C-c\C-d" 'reftex-index-remaining-phrases)
-    (define-key map "\C-c\C-s" 'reftex-index-sort-phrases)
-    (define-key map "\C-c\C-n" 'reftex-index-new-phrase)
-    (define-key map "\C-c\C-m" 'reftex-index-phrases-set-macro-key)
-    (define-key map "\C-c\C-i" 'reftex-index-phrases-info)
-    (define-key map "\C-c\C-t" 'reftex-index-find-next-conflict-phrase)
-    (define-key map "\C-i" 'self-insert-command)
+    (define-key map "\C-c\C-c" #'reftex-index-phrases-save-and-return)
+    (define-key map "\C-c\C-x" #'reftex-index-this-phrase)
+    (define-key map "\C-c\C-f" #'reftex-index-next-phrase)
+    (define-key map "\C-c\C-r" #'reftex-index-region-phrases)
+    (define-key map "\C-c\C-a" #'reftex-index-all-phrases)
+    (define-key map "\C-c\C-d" #'reftex-index-remaining-phrases)
+    (define-key map "\C-c\C-s" #'reftex-index-sort-phrases)
+    (define-key map "\C-c\C-n" #'reftex-index-new-phrase)
+    (define-key map "\C-c\C-m" #'reftex-index-phrases-set-macro-key)
+    (define-key map "\C-c\C-i" #'reftex-index-phrases-info)
+    (define-key map "\C-c\C-t" #'reftex-index-find-next-conflict-phrase)
+    (define-key map "\C-i" #'self-insert-command)
 
     (easy-menu-define reftex-index-phrases-menu map
       "Menu for Phrases buffer"
@@ -1295,7 +1311,7 @@ If the buffer is non-empty, delete the old header first."
                                       reftex-key-to-index-macro-alist)))
          (macro-alist
           (sort (copy-sequence reftex-index-macro-alist)
-                (lambda (a b) (equal (car a) default-macro))))
+                (lambda (a _b) (equal (car a) default-macro))))
          macro entry key repeat)
 
     (if master (set (make-local-variable 'TeX-master)
@@ -1311,9 +1327,7 @@ If the buffer is non-empty, delete the old header first."
           (beginning-of-line 2))
       (while (looking-at "^[ \t]*$")
           (beginning-of-line 2))
-      (if (featurep 'xemacs)
-         (zmacs-activate-region)
-       (setq mark-active t))
+      (activate-mark)
       (if (yes-or-no-p "Delete and rebuild header? ")
           (delete-region (point-min) (point))))
 
@@ -1336,7 +1350,6 @@ If the buffer is non-empty, delete the old header first."
                       (if repeat "t" "nil"))))
     (insert 
"%---------------------------------------------------------------------\n\n\n")))
 
-(defvar TeX-master)
 (defun reftex-index-phrase-tex-master (&optional dir)
   "Return the name of the master file associated with a phrase buffer."
   (if (and (boundp 'TeX-master)
@@ -1387,41 +1400,8 @@ Here are all local bindings.
   :syntax-table reftex-index-phrases-syntax-table
   (set (make-local-variable 'font-lock-defaults)
        reftex-index-phrases-font-lock-defaults)
-  (when (featurep 'xemacs)
-    (easy-menu-add reftex-index-phrases-menu reftex-index-phrases-mode-map))
   (set (make-local-variable 'reftex-index-phrases-marker) (make-marker)))
-;; (add-hook 'reftex-index-phrases-mode-hook 'turn-on-font-lock)
-
-;; Font Locking stuff
-(let ((ss (if (featurep 'xemacs) 'secondary-selection ''secondary-selection)))
-  (setq reftex-index-phrases-font-lock-keywords
-        (list
-         (cons reftex-index-phrases-comment-regexp 'font-lock-comment-face)
-         (list reftex-index-phrases-macrodef-regexp
-               '(1 font-lock-type-face)
-               '(2 font-lock-keyword-face)
-               (list 3 ss)
-               '(4 font-lock-function-name-face)
-               (list 5 ss)
-               '(6 font-lock-string-face))
-         (list reftex-index-phrases-phrase-regexp1
-               '(1 font-lock-keyword-face)
-               (list 2 ss)
-               '(3 font-lock-string-face)
-               (list 4 ss))
-         (list reftex-index-phrases-phrase-regexp2
-               '(1 font-lock-keyword-face)
-               (list 2 ss)
-               '(3 font-lock-string-face)
-               (list 4 ss)
-               '(5 font-lock-function-name-face))
-         (cons "^\t$" ss)))
-  (setq reftex-index-phrases-font-lock-defaults
-        '((reftex-index-phrases-font-lock-keywords)
-          nil t nil beginning-of-line))
-  (put 'reftex-index-phrases-mode 'font-lock-defaults
-       reftex-index-phrases-font-lock-defaults) ; XEmacs
-  )
+;; (add-hook 'reftex-index-phrases-mode-hook #'turn-on-font-lock)
 
 (defun reftex-index-next-phrase (&optional arg)
   "Index the next ARG phrases in the phrases buffer."
@@ -1561,9 +1541,7 @@ index the new part without having to go over the 
unchanged parts again."
       (unwind-protect
           (progn
             ;; Hide the region highlighting
-            (if (featurep 'xemacs)
-               (zmacs-deactivate-region)
-             (deactivate-mark))
+           (deactivate-mark)
             (delete-other-windows)
             (reftex-index-visit-phrases-buffer)
             (reftex-index-all-phrases))
@@ -1593,7 +1571,7 @@ index the new part without having to go over the 
unchanged parts again."
   (if (and text (stringp text))
       (insert text)))
 
-(defun reftex-index-find-next-conflict-phrase (&optional arg)
+(defun reftex-index-find-next-conflict-phrase (&optional _arg)
   "Find the next a phrase which is has conflicts in the phrase buffer.
 The command helps to find possible conflicts in the phrase indexing process.
 It searches downward from point for a phrase which is repeated elsewhere
@@ -1601,7 +1579,7 @@ in the buffer, or which is a subphrase of another phrase. 
 If such a
 phrase is found, the phrase info is displayed.
 To check the whole buffer, start at the beginning and continue by calling
 this function repeatedly."
-  (interactive "P")
+  (interactive)
   (if (catch 'exit
         (while (re-search-forward reftex-index-phrases-phrase-regexp12 nil t)
           (goto-char (match-beginning 3))
@@ -1743,6 +1721,8 @@ information about the currently selected macro."
                      (if repeat "with" "without")))
         (error "Abort")))))
 
+(defvar reftex--chars-first)
+
 (defun reftex-index-sort-phrases (&optional chars-first)
   "Sort the phrases lines in the buffer alphabetically.
 Normally, this looks only at the phrases.  With a prefix arg CHARS-FIRST,
@@ -1762,19 +1742,18 @@ it first compares the macro identifying chars and then 
the phrases."
     (if end (setq end (progn (goto-char end) (end-of-line) (point))))
     ;; Take the lines, sort them and re-insert.
     (if (and beg end)
-        (progn
+        (let ((reftex--chars-first chars-first))
           (message "Sorting lines...")
           (let* ((lines (split-string (buffer-substring beg end) "\n"))
-                 (lines1 (sort lines 'reftex-compare-phrase-lines)))
+                 (lines1 (sort lines #'reftex-compare-phrase-lines)))
             (message "Sorting lines...done")
             (let ((inhibit-quit t))  ;; make sure we do not lose lines
               (delete-region beg end)
-              (insert (mapconcat 'identity lines1 "\n"))))
+              (insert (mapconcat #'identity lines1 "\n"))))
           (goto-char (point-max))
           (re-search-backward (concat "^" (regexp-quote line) "$") nil t))
       (error "Cannot find phrases lines to sort"))))
 
-(defvar chars-first)
 (defun reftex-compare-phrase-lines (a b)
   "The comparison function used for sorting."
   (let (ca cb pa pb c-p p-p)
@@ -1798,7 +1777,7 @@ it first compares the macro identifying chars and then 
the phrases."
                       p-p (string< pa pb))
                 ;; Do the right comparison, based on the value of `chars-first'
                 ;; `chars-first' is bound locally in the calling function
-                (if chars-first
+                (if reftex--chars-first
                     (if (string= ca cb) p-p c-p)
                   (if (string= pa pb) c-p p-p)))))
       ;; If line a does not match, the answer we return determines
@@ -1830,14 +1809,14 @@ With optional arg ALLOW-NEWLINE, allow single newline 
between words."
 
 (defun reftex-index-simplify-phrase (phrase)
   "Make phrase single spaces and single line."
-  (mapconcat 'identity (split-string phrase) " "))
+  (mapconcat #'identity (split-string phrase) " "))
 
 (defun reftex-index-phrases-find-dup-re (phrase &optional sub)
   "Return a regexp which matches variations of PHRASE (with additional space).
 When SUB ins non-nil, the regexp will also match when PHRASE is a subphrase
 of another phrase.  The regexp works lonly in the phrase buffer."
   (concat (if sub "^\\S-?\t\\([^\t\n]*" "^\\S-?\t")
-          (mapconcat 'regexp-quote (split-string phrase) " +")
+          (mapconcat #'regexp-quote (split-string phrase) " +")
           (if sub "[^\t\n]*\\)\\([\t\n]\\|$\\)" " *\\([\t\n]\\|$\\)")))
 
 (defun reftex-index-make-replace-string (macro-fmt match index-key
@@ -1870,7 +1849,7 @@ Treats the logical `and' for index phrases."
                   (unless (stringp reftex-index-phrases-restrict-file)
                     (widen))
                   (goto-char (point-min))
-                  (apply 'reftex-query-index-phrase args))))))
+                  (apply #'reftex-query-index-phrase args))))))
       (reftex-unhighlight 0)
       (set-window-configuration win-conf))))
 
diff --git a/lisp/textmodes/reftex-parse.el b/lisp/textmodes/reftex-parse.el
index 98c61f5..0157f84 100644
--- a/lisp/textmodes/reftex-parse.el
+++ b/lisp/textmodes/reftex-parse.el
@@ -1,4 +1,4 @@
-;;; reftex-parse.el --- parser functions for RefTeX
+;;; reftex-parse.el --- parser functions for RefTeX  -*- lexical-binding: t; 
-*-
 
 ;; Copyright (C) 1997-2021 Free Software Foundation, Inc.
 
@@ -143,7 +143,7 @@ When allowed, do only a partial scan from FILE."
                       (car (push (list 'is-multi is-multi) docstruct)))))
       (setcdr entry (cons is-multi nil)))
     (and reftex--index-tags
-         (setq reftex--index-tags (sort reftex--index-tags 'string<)))
+         (setq reftex--index-tags (sort reftex--index-tags #'string<)))
     (let ((index-tag-cell (assq 'index-tags docstruct)))
       (if index-tag-cell
           (setcdr index-tag-cell reftex--index-tags)
@@ -160,10 +160,10 @@ When allowed, do only a partial scan from FILE."
                          nil))
                      allxr))
              (alist (delq nil alist))
-             (allprefix (delq nil (mapcar 'car alist)))
+             (allprefix (delq nil (mapcar #'car alist)))
              (regexp (if allprefix
                          (concat "\\`\\("
-                                 (mapconcat 'identity allprefix "\\|")
+                                 (mapconcat #'identity allprefix "\\|")
                                  "\\)")
                        "\\\\\\\\\\\\")))   ; this will never match
         (push (list 'xr alist regexp) docstruct)))
@@ -209,7 +209,7 @@ of master file."
     (catch 'exit
       (setq file-found (reftex-locate-file file "tex" master-dir))
       (if (and (not file-found)
-               (setq buf (reftex-get-buffer-visiting file)))
+               (setq buf (find-buffer-visiting file)))
           (setq file-found (buffer-file-name buf)))
 
       (unless file-found
@@ -384,8 +384,9 @@ of master file."
                     (concat
                      ;;           "\\(\\`\\|[\n\r]\\)[^%]*\\\\\\("
                      "\\(^\\)[^%\n\r]*\\\\\\("
-                     (mapconcat 'identity reftex-bibliography-commands "\\|")
-                     "\\)\\(\\[.+?\\]\\)?{[ \t]*\\([^}]+\\)") nil t))
+                     (mapconcat #'identity reftex-bibliography-commands "\\|")
+                     "\\)\\(\\[.+?\\]\\)?{[ \t]*\\([^}]+\\)")
+                    nil t))
          (setq files
                (append files
                        (split-string (reftex-match-string 4)
@@ -532,7 +533,7 @@ Careful: This function expects the match-data to be still 
in place!"
 
            (key (if prefix (concat prefix rawkey) rawkey))
            (sortkey (downcase key))
-           (showkey (mapconcat 'identity
+           (showkey (mapconcat #'identity
                                (split-string key reftex-index-level-re)
                                " ! ")))
       (goto-char end-of-args)
diff --git a/lisp/textmodes/reftex-ref.el b/lisp/textmodes/reftex-ref.el
index 439c02f..611102e 100644
--- a/lisp/textmodes/reftex-ref.el
+++ b/lisp/textmodes/reftex-ref.el
@@ -1,4 +1,4 @@
-;;; reftex-ref.el --- code to create labels and references with RefTeX
+;;; reftex-ref.el --- code to create labels and references with RefTeX  -*- 
lexical-binding: t; -*-
 
 ;; Copyright (C) 1997-2021 Free Software Foundation, Inc.
 
@@ -84,10 +84,12 @@ If optional BOUND is an integer, limit backward searches to 
that point."
 
           (if (or (re-search-forward
                    (format reftex-find-label-regexp-format
-                           (regexp-quote label)) nil t)
+                           (regexp-quote label))
+                   nil t)
                   (re-search-forward
                    (format reftex-find-label-regexp-format2
-                           (regexp-quote label)) nil t))
+                           (regexp-quote label))
+                   nil t))
 
               (progn
                 (backward-char 1)
@@ -248,13 +250,13 @@ This function is controlled by the settings of 
reftex-insert-label-flags."
                        ""
                      "POSITION UNCERTAIN.  RESCAN TO FIX."))
              (file (buffer-file-name))
-             (text nil)
+             ;; (text nil)
              (tail (memq here-I-am (symbol-value reftex-docstruct-symbol))))
 
         (or (cdr here-I-am-info) (setq rescan-is-useful t))
 
         (when tail
-          (push (list label typekey text file nil note) (cdr tail))
+          (push (list label typekey nil file nil note) (cdr tail))
           (put reftex-docstruct-symbol 'modified t)))
 
       ;; Insert the label into the buffer
@@ -286,7 +288,7 @@ also applies `reftex-translate-to-ascii-function' to the 
string."
   (when (and reftex-translate-to-ascii-function
              (fboundp reftex-translate-to-ascii-function))
     (setq string (funcall reftex-translate-to-ascii-function string)))
-  (apply 'reftex-convert-string string
+  (apply #'reftex-convert-string string
          "[-~ \t\n\r,;]+" reftex-label-illegal-re nil nil
          reftex-derive-label-parameters))
 
@@ -402,6 +404,8 @@ also applies `reftex-translate-to-ascii-function' to the 
string."
  a / A      Put all marked entries into one/many \\ref commands.
  q / RET    Quit without referencing / Accept current label (also on 
mouse-2).")
 
+(defvar reftex-refstyle)
+
 ;;;###autoload
 (defun reftex-reference (&optional type no-insert cut)
   "Make a LaTeX reference.  Look only for labels of a certain TYPE.
@@ -473,7 +477,7 @@ When called with 2 C-u prefix args, disable magic word 
recognition."
     ;; If the first entry is the symbol 'concat, concat all labels.
     ;; We keep the cdr of the first label for typekey etc information.
     (if (eq (car labels) 'concat)
-        (setq labels (list (list (mapconcat 'car (cdr labels) ",")
+        (setq labels (list (list (mapconcat #'car (cdr labels) ",")
                                  (cdr (nth 1 labels))))))
     (setq type (nth 1 (car labels))
           form (or (cdr (assoc type reftex-typekey-to-format-alist))
@@ -502,7 +506,7 @@ When called with 2 C-u prefix args, disable magic word 
recognition."
           (setq form (substring form 1)))
         ;; do we have a special format?
        (unless (string= reftex-refstyle "\\ref")
-         (setq reftex-format-ref-function 'reftex-format-special))
+         (setq reftex-format-ref-function #'reftex-format-special))
         ;; ok, insert the reference
         (if sep1 (insert sep1))
         (insert
@@ -744,7 +748,7 @@ When called with 2 C-u prefix args, disable magic word 
recognition."
       ;; Goto the file in another window
       (setq buffer
             (if no-revisit
-                (reftex-get-buffer-visiting file)
+                (find-buffer-visiting file)
               (reftex-get-file-buffer-force
                file (not reftex-keep-temporary-buffers))))
       (if buffer
@@ -826,14 +830,16 @@ When called with 2 C-u prefix args, disable magic word 
recognition."
     (dolist (item (nth 2 elt))
       (let ((macro (car item))
            (package (nth 1 elt)))
-       (eval `(defun ,(intern (format "reftex-%s-%s" package
-                                      (substring macro 1 (length macro)))) ()
-                ,(format "Insert a reference using the `%s' macro from the %s \
+       (defalias (intern (format "reftex-%s-%s" package
+                                 (substring macro 1 (length macro))))
+         (lambda ()
+           (:documentation
+            (format "Insert a reference using the `%s' macro from the %s \
 package.\n\nThis is a generated function."
-                         macro package)
-                (interactive)
-                (let ((reftex-refstyle ,macro))
-                  (reftex-reference))))))))
+                    macro package))
+           (interactive)
+           (let ((reftex-refstyle macro))
+             (reftex-reference))))))))
 
 (defun reftex-format-special (label fmt refstyle)
   "Apply selected reference style to format FMT and add LABEL.
diff --git a/lisp/textmodes/reftex-sel.el b/lisp/textmodes/reftex-sel.el
index d2e9974..b0a8ebf 100644
--- a/lisp/textmodes/reftex-sel.el
+++ b/lisp/textmodes/reftex-sel.el
@@ -1,4 +1,4 @@
-;;; reftex-sel.el --- the selection modes for RefTeX
+;;; reftex-sel.el --- the selection modes for RefTeX  -*- lexical-binding: t; 
-*-
 
 ;; Copyright (C) 1997-2021 Free Software Foundation, Inc.
 
@@ -34,31 +34,29 @@
   (let ((map (make-sparse-keymap)))
     (set-keymap-parent map special-mode-map)
     (substitute-key-definition
-     'next-line 'reftex-select-next                      map global-map)
+     #'next-line #'reftex-select-next                      map global-map)
     (substitute-key-definition
-     'previous-line 'reftex-select-previous              map global-map)
+     #'previous-line #'reftex-select-previous              map global-map)
     (substitute-key-definition
-     'keyboard-quit 'reftex-select-keyboard-quit         map global-map)
+     #'keyboard-quit #'reftex-select-keyboard-quit         map global-map)
     (substitute-key-definition
-     'newline 'reftex-select-accept                      map global-map)
-
-    (define-key map " " 'reftex-select-callback)
-    (define-key map "n" 'reftex-select-next)
-    (define-key map [(down)] 'reftex-select-next)
-    (define-key map "p" 'reftex-select-previous)
-    (define-key map [(up)] 'reftex-select-previous)
-    (define-key map "f" 'reftex-select-toggle-follow)
-    (define-key map "\C-m" 'reftex-select-accept)
-    (define-key map [(return)] 'reftex-select-accept)
-    (define-key map "q" 'reftex-select-quit)
-    (define-key map "." 'reftex-select-show-insertion-point)
-    (define-key map "?" 'reftex-select-help)
+     #'newline #'reftex-select-accept                      map global-map)
+
+    (define-key map " " #'reftex-select-callback)
+    (define-key map "n" #'reftex-select-next)
+    (define-key map [(down)] #'reftex-select-next)
+    (define-key map "p" #'reftex-select-previous)
+    (define-key map [(up)] #'reftex-select-previous)
+    (define-key map "f" #'reftex-select-toggle-follow)
+    (define-key map "\C-m" #'reftex-select-accept)
+    (define-key map [(return)] #'reftex-select-accept)
+    (define-key map "q" #'reftex-select-quit)
+    (define-key map "." #'reftex-select-show-insertion-point)
+    (define-key map "?" #'reftex-select-help)
 
     ;; The mouse-2 binding
-    (if (featurep 'xemacs)
-        (define-key map [(button2)] 'reftex-select-mouse-accept)
-      (define-key map [(mouse-2)] 'reftex-select-mouse-accept)
-      (define-key map [follow-link] 'mouse-face))
+    (define-key map [(mouse-2)] #'reftex-select-mouse-accept)
+    (define-key map [follow-link] 'mouse-face)
     map))
 
 (define-obsolete-variable-alias
@@ -67,25 +65,26 @@
   (let ((map (make-sparse-keymap)))
     (set-keymap-parent map reftex-select-shared-map)
 
-    (cl-loop for key across "aAcgFlrRstx#%" do
-             (define-key map (vector (list key))
-               (list 'lambda '()
-                     "Press `?' during selection to find out about this key."
-                     '(interactive) (list 'throw '(quote myexit) key))))
-
-    (define-key map "b" 'reftex-select-jump-to-previous)
-    (define-key map "z" 'reftex-select-jump)
-    (define-key map "v" 'reftex-select-cycle-ref-style-forward)
-    (define-key map "V" 'reftex-select-cycle-ref-style-backward)
-    (define-key map "m" 'reftex-select-mark)
-    (define-key map "u" 'reftex-select-unmark)
-    (define-key map "," 'reftex-select-mark-comma)
-    (define-key map "-" 'reftex-select-mark-to)
-    (define-key map "+" 'reftex-select-mark-and)
-    (define-key map [(tab)] 'reftex-select-read-label)
-    (define-key map "\C-i" 'reftex-select-read-label)
-    (define-key map "\C-c\C-n" 'reftex-select-next-heading)
-    (define-key map "\C-c\C-p" 'reftex-select-previous-heading)
+    (mapc (lambda (key)
+            (define-key map (vector (list key))
+              (lambda ()
+                "Press `?' during selection to find out about this key."
+                (interactive) (throw 'myexit key))))
+          "aAcgFlrRstx#%")
+
+    (define-key map "b" #'reftex-select-jump-to-previous)
+    (define-key map "z" #'reftex-select-jump)
+    (define-key map "v" #'reftex-select-cycle-ref-style-forward)
+    (define-key map "V" #'reftex-select-cycle-ref-style-backward)
+    (define-key map "m" #'reftex-select-mark)
+    (define-key map "u" #'reftex-select-unmark)
+    (define-key map "," #'reftex-select-mark-comma)
+    (define-key map "-" #'reftex-select-mark-to)
+    (define-key map "+" #'reftex-select-mark-and)
+    (define-key map [(tab)] #'reftex-select-read-label)
+    (define-key map "\C-i" #'reftex-select-read-label)
+    (define-key map "\C-c\C-n" #'reftex-select-next-heading)
+    (define-key map "\C-c\C-p" #'reftex-select-previous-heading)
 
     map)
   "Keymap used for *RefTeX Select* buffer, when selecting a label.
@@ -104,10 +103,6 @@ Press `?' for a summary of important key bindings.
 During a selection process, these are the local bindings.
 
 \\{reftex-select-label-mode-map}"
-  (when (featurep 'xemacs)
-    ;; XEmacs needs the call to make-local-hook
-    (make-local-hook 'pre-command-hook)
-    (make-local-hook 'post-command-hook))
   (set (make-local-variable 'reftex-select-marked) nil)
   (when (syntax-table-p reftex-latex-syntax-table)
     (set-syntax-table reftex-latex-syntax-table))
@@ -120,16 +115,17 @@ During a selection process, these are the local bindings.
   (let ((map (make-sparse-keymap)))
     (set-keymap-parent map reftex-select-shared-map)
 
-    (cl-loop for key across "grRaAeE" do
-             (define-key map (vector (list key))
-               (list 'lambda '()
-                     "Press `?' during selection to find out about this key."
-                     '(interactive) (list 'throw '(quote myexit) key))))
+    (mapc (lambda (key)
+            (define-key map (vector (list key))
+              (lambda ()
+                "Press `?' during selection to find out about this key."
+                (interactive) (throw 'myexit key))))
+          "grRaAeE")
 
-    (define-key map "\C-i" 'reftex-select-read-cite)
-    (define-key map [(tab)] 'reftex-select-read-cite)
-    (define-key map "m" 'reftex-select-mark)
-    (define-key map "u" 'reftex-select-unmark)
+    (define-key map "\C-i" #'reftex-select-read-cite)
+    (define-key map [(tab)] #'reftex-select-read-cite)
+    (define-key map "m" #'reftex-select-mark)
+    (define-key map "u" #'reftex-select-unmark)
 
     map)
   "Keymap used for *RefTeX Select* buffer, when selecting a BibTeX entry.
@@ -148,10 +144,6 @@ Press `?' for a summary of important key bindings.
 During a selection process, these are the local bindings.
 
 \\{reftex-select-label-mode-map}"
-  (when (featurep 'xemacs)
-    ;; XEmacs needs the call to make-local-hook
-    (make-local-hook 'pre-command-hook)
-    (make-local-hook 'post-command-hook))
   (set (make-local-variable 'reftex-select-marked) nil)
   ;; We do not set a local map - reftex-select-item does this.
   )
@@ -432,12 +424,21 @@ During a selection process, these are the local bindings.
 (defvar reftex-last-data nil)
 (defvar reftex-last-line nil)
 (defvar reftex-select-marked nil)
+(defvar reftex-refstyle)
+
+;; The following variables are all bound dynamically in `reftex-select-item'.
+
+(defvar reftex-select-data)
+(defvar reftex-select-prompt)
+(defvar reftex--cb-flag)
+(defvar reftex--last-data)
+(defvar reftex--call-back)
+(defvar reftex--help-string)
 
 ;;;###autoload
-(defun reftex-select-item (reftex-select-prompt help-string keymap
-                                  &optional offset
-                                  call-back cb-flag)
-  ;; Select an item, using REFTEX-SELECT-PROMPT.
+(defun reftex-select-item ( prompt help-string keymap
+                            &optional offset call-back cb-flag)
+  ;; Select an item, using PROMPT.
   ;; The function returns a key indicating an exit status, along with a
   ;; data structure indicating which item was selected.
   ;; HELP-STRING contains help.  KEYMAP is a keymap with the available
@@ -448,7 +449,12 @@ During a selection process, these are the local bindings.
   ;; When CALL-BACK is given, it is a function which is called with the index
   ;; of the element.
   ;; CB-FLAG is the initial value of that flag.
-  (let (ev reftex-select-data last-data (selection-buffer (current-buffer)))
+  (let ((reftex-select-prompt prompt)
+        (reftex--help-string help-string)
+        (reftex--call-back call-back)
+        (reftex--cb-flag cb-flag)
+        ev reftex-select-data reftex--last-data
+        (selection-buffer (current-buffer)))
 
     (setq reftex-select-marked nil)
 
@@ -466,43 +472,29 @@ During a selection process, these are the local bindings.
       (unwind-protect
           (progn
             (use-local-map keymap)
-            (add-hook 'pre-command-hook 'reftex-select-pre-command-hook nil t)
-            (add-hook 'post-command-hook 'reftex-select-post-command-hook nil 
t)
+            (add-hook 'pre-command-hook #'reftex-select-pre-command-hook nil t)
+            (add-hook 'post-command-hook #'reftex-select-post-command-hook nil 
t)
             (princ reftex-select-prompt)
             (set-marker reftex-recursive-edit-marker (point))
-            ;; XEmacs does not run post-command-hook here
-            (and (featurep 'xemacs) (run-hooks 'post-command-hook))
             (recursive-edit))
 
         (set-marker reftex-recursive-edit-marker nil)
         (with-current-buffer selection-buffer
           (use-local-map nil)
-          (remove-hook 'pre-command-hook 'reftex-select-pre-command-hook t)
+          (remove-hook 'pre-command-hook #'reftex-select-pre-command-hook t)
           (remove-hook 'post-command-hook
-                       'reftex-select-post-command-hook t))
+                       #'reftex-select-post-command-hook t))
         ;; Kill the mark overlays
-        (mapc (lambda (c) (reftex-delete-overlay (nth 1 c)))
+        (mapc (lambda (c) (delete-overlay (nth 1 c)))
               reftex-select-marked)))))
 
     (set (make-local-variable 'reftex-last-line)
          (+ (count-lines (point-min) (point)) (if (bolp) 1 0)))
-    (set (make-local-variable 'reftex-last-data) last-data)
+    (set (make-local-variable 'reftex-last-data) reftex--last-data)
     (reftex-kill-buffer "*RefTeX Help*")
     (setq reftex-callback-fwd (not reftex-callback-fwd)) ;; ;-)))
     (message "")
-    (list ev reftex-select-data last-data)))
-
-;; The following variables are all bound dynamically in `reftex-select-item'.
-;; The defvars are here only to silence the byte compiler.
-
-(defvar found-list)
-(defvar cb-flag)
-(defvar reftex-select-data)
-(defvar reftex-select-prompt)
-(defvar last-data)
-(defvar call-back)
-(defvar help-string)
-(defvar reftex-refstyle)
+    (list ev reftex-select-data reftex--last-data)))
 
 ;; The selection commands
 
@@ -513,12 +505,12 @@ During a selection process, these are the local bindings.
 (defun reftex-select-post-command-hook ()
   (let (b e)
     (setq reftex-select-data (get-text-property (point) :data))
-    (setq last-data (or reftex-select-data last-data))
+    (setq reftex--last-data (or reftex-select-data reftex--last-data))
 
-    (when (and reftex-select-data cb-flag
+    (when (and reftex-select-data reftex--cb-flag
                (not (equal reftex-last-follow-point (point))))
       (setq reftex-last-follow-point (point))
-      (funcall call-back reftex-select-data reftex-callback-fwd
+      (funcall reftex--call-back reftex-select-data reftex-callback-fwd
                (not reftex-revisit-to-follow)))
     (if reftex-select-data
         (setq b (or (previous-single-property-change
@@ -594,7 +586,7 @@ Useful for large TOC's."
   "Toggle follow mode:  Other window follows with full context."
   (interactive)
   (setq reftex-last-follow-point -1)
-  (setq cb-flag (not cb-flag)))
+  (setq reftex--cb-flag (not reftex--cb-flag)))
 
 (defun reftex-select-cycle-ref-style-internal (&optional reverse)
   "Cycle through macros used for referencing.
@@ -632,7 +624,9 @@ Cycle in reverse order if optional argument REVERSE is 
non-nil."
 (defun reftex-select-callback ()
   "Show full context in another window."
   (interactive)
-  (if reftex-select-data (funcall call-back reftex-select-data 
reftex-callback-fwd nil) (ding)))
+  (if reftex-select-data
+      (funcall reftex--call-back reftex-select-data reftex-callback-fwd nil)
+    (ding)))
 (defun reftex-select-accept ()
   "Accept the currently selected item."
   (interactive)
@@ -642,7 +636,7 @@ Cycle in reverse order if optional argument REVERSE is 
non-nil."
   (interactive "e")
   (mouse-set-point ev)
   (setq reftex-select-data (get-text-property (point) :data))
-  (setq last-data (or reftex-select-data last-data))
+  (setq reftex--last-data (or reftex-select-data reftex--last-data))
   (throw 'myexit 'return))
 (defun reftex-select-read-label ()
   "Use minibuffer to read a label to reference, with completion."
@@ -652,16 +646,19 @@ Cycle in reverse order if optional argument REVERSE is 
non-nil."
                 nil nil reftex-prefix)))
     (unless (or (equal label "") (equal label reftex-prefix))
       (throw 'myexit label))))
+
+(defvar reftex--found-list)
+
 (defun reftex-select-read-cite ()
   "Use minibuffer to read a citation key with completion."
   (interactive)
-  (let* ((key (completing-read "Citation key: " found-list))
-         (entry (assoc key found-list)))
+  (let* ((key (completing-read "Citation key: " reftex--found-list))
+         (entry (assoc key reftex--found-list)))
     (cond
      ((or (null key) (equal key "")))
      (entry
       (setq reftex-select-data entry)
-      (setq last-data reftex-select-data)
+      (setq reftex--last-data reftex-select-data)
       (throw 'myexit 'return))
      (t (throw 'myexit key)))))
 
@@ -676,14 +673,14 @@ Cycle in reverse order if optional argument REVERSE is 
non-nil."
     (setq boe (or (previous-single-property-change (1+ (point)) :data)
                   (point-min))
           eoe (or (next-single-property-change (point) :data) (point-max)))
-    (setq ovl (reftex-make-overlay boe eoe))
+    (setq ovl (make-overlay boe eoe))
     (push (list data ovl separator) reftex-select-marked)
-    (reftex-overlay-put ovl 'font-lock-face reftex-select-mark-face)
-    (reftex-overlay-put ovl 'before-string
-                        (if separator
-                            (format "*%c%d* " separator
-                                    (length reftex-select-marked))
-                          (format "*%d*  " (length reftex-select-marked))))
+    (overlay-put ovl 'font-lock-face reftex-select-mark-face)
+    (overlay-put ovl 'before-string
+                 (if separator
+                     (format "*%c%d* " separator
+                             (length reftex-select-marked))
+                   (format "*%d*  " (length reftex-select-marked))))
     (message "Entry has mark no. %d" (length reftex-select-marked))))
 
 (defun reftex-select-mark-comma ()
@@ -709,15 +706,15 @@ Cycle in reverse order if optional argument REVERSE is 
non-nil."
          sep)
     (unless cell
       (error "No marked entry at point"))
-    (and ovl (reftex-delete-overlay ovl))
+    (and ovl (delete-overlay ovl))
     (setq reftex-select-marked (delq cell reftex-select-marked))
     (setq cnt (1+ (length reftex-select-marked)))
     (mapc (lambda (c)
             (setq sep (nth 2 c))
-            (reftex-overlay-put (nth 1 c) 'before-string
-                                (if sep
-                                    (format "*%c%d* " sep (cl-decf cnt))
-                                  (format "*%d*  " (cl-decf cnt)))))
+            (overlay-put (nth 1 c) 'before-string
+                         (if sep
+                             (format "*%c%d* " sep (cl-decf cnt))
+                           (format "*%d*  " (cl-decf cnt)))))
           reftex-select-marked)
     (message "Entry no longer marked")))
 
@@ -725,7 +722,7 @@ Cycle in reverse order if optional argument REVERSE is 
non-nil."
   "Display a summary of the special key bindings."
   (interactive)
   (with-output-to-temp-buffer "*RefTeX Help*"
-    (princ help-string))
+    (princ reftex--help-string))
   (reftex-enlarge-to-fit "*RefTeX Help*" t))
 
 (provide 'reftex-sel)
diff --git a/lisp/textmodes/reftex-toc.el b/lisp/textmodes/reftex-toc.el
index 3b9f970..b564349 100644
--- a/lisp/textmodes/reftex-toc.el
+++ b/lisp/textmodes/reftex-toc.el
@@ -1,4 +1,4 @@
-;;; reftex-toc.el --- RefTeX's table of contents mode
+;;; reftex-toc.el --- RefTeX's table of contents mode  -*- lexical-binding: t; 
-*-
 
 ;; Copyright (C) 1997-2000, 2003-2021 Free Software Foundation, Inc.
 
@@ -32,8 +32,7 @@
 (defvar reftex-toc-mode-map
   (let ((map (make-sparse-keymap)))
 
-    (define-key map (if (featurep 'xemacs) [(button2)] [(mouse-2)])
-      'reftex-toc-mouse-goto-line-and-hide)
+    (define-key map [(mouse-2)] #'reftex-toc-mouse-goto-line-and-hide)
     (define-key map [follow-link] 'mouse-face)
 
     (substitute-key-definition
@@ -41,34 +40,34 @@
     (substitute-key-definition
      'previous-line 'reftex-toc-previous map global-map)
 
-    (define-key map "n" 'reftex-toc-next)
-    (define-key map "p" 'reftex-toc-previous)
-    (define-key map "?" 'reftex-toc-show-help)
-    (define-key map " " 'reftex-toc-view-line)
-    (define-key map "\C-m" 'reftex-toc-goto-line-and-hide)
-    (define-key map "\C-i" 'reftex-toc-goto-line)
-    (define-key map "\C-c>" 'reftex-toc-display-index)
-    (define-key map "r" 'reftex-toc-rescan)
-    (define-key map "R" 'reftex-toc-Rescan)
-    (define-key map "q" 'reftex-toc-quit) ;
-    (define-key map "k" 'reftex-toc-quit-and-kill)
-    (define-key map "f" 'reftex-toc-toggle-follow) ;
-    (define-key map "a" 'reftex-toggle-auto-toc-recenter)
-    (define-key map "d" 'reftex-toc-toggle-dedicated-frame)
-    (define-key map "F" 'reftex-toc-toggle-file-boundary)
-    (define-key map "i" 'reftex-toc-toggle-index)
-    (define-key map "l" 'reftex-toc-toggle-labels)
-    (define-key map "t" 'reftex-toc-max-level)
-    (define-key map "c" 'reftex-toc-toggle-context)
-    ;; (define-key map "%" 'reftex-toc-toggle-commented)
-    (define-key map "\M-%" 'reftex-toc-rename-label)
-    (define-key map "x" 'reftex-toc-external)
-    (define-key map "z" 'reftex-toc-jump)
-    (define-key map "." 'reftex-toc-show-calling-point)
-    (define-key map "\C-c\C-n" 'reftex-toc-next-heading)
-    (define-key map "\C-c\C-p" 'reftex-toc-previous-heading)
-    (define-key map ">" 'reftex-toc-demote)
-    (define-key map "<" 'reftex-toc-promote)
+    (define-key map "n" #'reftex-toc-next)
+    (define-key map "p" #'reftex-toc-previous)
+    (define-key map "?" #'reftex-toc-show-help)
+    (define-key map " " #'reftex-toc-view-line)
+    (define-key map "\C-m" #'reftex-toc-goto-line-and-hide)
+    (define-key map "\C-i" #'reftex-toc-goto-line)
+    (define-key map "\C-c>" #'reftex-toc-display-index)
+    (define-key map "r" #'reftex-toc-rescan)
+    (define-key map "R" #'reftex-toc-Rescan)
+    (define-key map "q" #'reftex-toc-quit) ;
+    (define-key map "k" #'reftex-toc-quit-and-kill)
+    (define-key map "f" #'reftex-toc-toggle-follow) ;
+    (define-key map "a" #'reftex-toggle-auto-toc-recenter)
+    (define-key map "d" #'reftex-toc-toggle-dedicated-frame)
+    (define-key map "F" #'reftex-toc-toggle-file-boundary)
+    (define-key map "i" #'reftex-toc-toggle-index)
+    (define-key map "l" #'reftex-toc-toggle-labels)
+    (define-key map "t" #'reftex-toc-max-level)
+    (define-key map "c" #'reftex-toc-toggle-context)
+    ;; (define-key map "%" #'reftex-toc-toggle-commented)
+    (define-key map "\M-%" #'reftex-toc-rename-label)
+    (define-key map "x" #'reftex-toc-external)
+    (define-key map "z" #'reftex-toc-jump)
+    (define-key map "." #'reftex-toc-show-calling-point)
+    (define-key map "\C-c\C-n" #'reftex-toc-next-heading)
+    (define-key map "\C-c\C-p" #'reftex-toc-previous-heading)
+    (define-key map ">" #'reftex-toc-demote)
+    (define-key map "<" #'reftex-toc-promote)
 
     (easy-menu-define
       reftex-toc-menu map
@@ -130,9 +129,7 @@ Here are all local bindings.
 
 \\{reftex-toc-mode-map}"
   (set (make-local-variable 'transient-mark-mode) t)
-  (when (featurep 'xemacs)
-    (set (make-local-variable 'zmacs-regions) t))
-  (set (make-local-variable 'revert-buffer-function) 'reftex-toc-revert)
+  (set (make-local-variable 'revert-buffer-function) #'reftex-toc-revert)
   (set (make-local-variable 'reftex-toc-include-labels-indicator) "")
   (set (make-local-variable 'reftex-toc-max-level-indicator)
        (if (= reftex-toc-max-level 100)
@@ -146,15 +143,9 @@ Here are all local bindings.
               "  T<" 'reftex-toc-max-level-indicator ">"
               " -%-"))
   (setq truncate-lines t)
-  (when (featurep 'xemacs)
-    ;; XEmacs needs the call to make-local-hook
-    (make-local-hook 'post-command-hook)
-    (make-local-hook 'pre-command-hook))
   (make-local-variable 'reftex-last-follow-point)
-  (add-hook 'post-command-hook 'reftex-toc-post-command-hook nil t)
-  (add-hook 'pre-command-hook  'reftex-toc-pre-command-hook nil t)
-  (when (featurep 'xemacs)
-    (easy-menu-add reftex-toc-menu reftex-toc-mode-map)))
+  (add-hook 'post-command-hook #'reftex-toc-post-command-hook nil t)
+  (add-hook 'pre-command-hook  #'reftex-toc-pre-command-hook nil t))
 
 (defvar reftex-last-toc-file nil
   "Stores the file name from which `reftex-toc' was called.  For redo 
command.")
@@ -420,7 +411,6 @@ SPC=view TAB=goto RET=goto+hide [q]uit [r]escan [l]abels 
[f]ollow [x]r [?]Help
 (defun reftex-toc-next (&optional _arg)
   "Move to next selectable item."
   (interactive)
-  (when (featurep 'xemacs) (setq zmacs-region-stays t))
   (setq reftex-callback-fwd t)
   (or (eobp) (forward-char 1))
   (goto-char (or (next-single-property-change (point) :data)
@@ -428,21 +418,18 @@ SPC=view TAB=goto RET=goto+hide [q]uit [r]escan [l]abels 
[f]ollow [x]r [?]Help
 (defun reftex-toc-previous (&optional _arg)
   "Move to previous selectable item."
   (interactive)
-  (when (featurep 'xemacs) (setq zmacs-region-stays t))
   (setq reftex-callback-fwd nil)
   (goto-char (or (previous-single-property-change (point) :data)
                  (point))))
 (defun reftex-toc-next-heading (&optional arg)
   "Move to next table of contents line."
   (interactive "p")
-  (when (featurep 'xemacs) (setq zmacs-region-stays t))
   (end-of-line)
   (re-search-forward "^ " nil t arg)
   (beginning-of-line))
 (defun reftex-toc-previous-heading (&optional arg)
   "Move to previous table of contents line."
   (interactive "p")
-  (when (featurep 'xemacs) (setq zmacs-region-stays t))
   (re-search-backward "^ " nil t arg))
 (defun reftex-toc-toggle-follow ()
   "Toggle follow (other window follows with context)."
@@ -662,7 +649,7 @@ point."
   (let* ((reftex--start-line (+ (count-lines (point-min) (point))
                                 (if (bolp) 1 0)))
         (reftex--mark-line
-          (if (reftex-region-active-p)
+          (if (region-active-p)
               (save-excursion (goto-char (mark))
                               (+ (count-lines (point-min) (point))
                                  (if (bolp) 1 0)))))
@@ -671,7 +658,7 @@ point."
          beg end entries data sections nsec msg)
     (setq msg
           (catch 'exit
-            (if (reftex-region-active-p)
+            (if (region-active-p)
                 ;; A region is dangerous, check if we have a brand new scan,
                 ;; to make sure we are not missing any section statements.
                 (if (not (reftex-toc-check-docstruct))
@@ -712,7 +699,7 @@ point."
                 nil              ; we have permission, do nothing
               (error "Abort"))   ; abort, we don't have permission
             ;; Do the changes
-            (mapc 'reftex-toc-promote-action entries)
+            (mapc #'reftex-toc-promote-action entries)
             ;; Rescan the document and rebuilt the toc buffer
             (save-window-excursion
               (reftex-toc-Rescan))
@@ -734,10 +721,8 @@ point."
       (forward-line (1- point-line)))
     (when mpos
       (set-mark mpos)
-      (if (featurep 'xemacs)
-          (zmacs-activate-region)
-        (setq mark-active t
-              deactivate-mark nil)))))
+      (setq mark-active t
+            deactivate-mark nil))))
 
 (defun reftex-toc-promote-prepare (x delta)
   "Look at a TOC entry and see if we could pro/demote it.
@@ -918,7 +903,7 @@ label prefix determines the wording of a reference."
       (setq match
             (let ((where (car toc))
                   (file (nth 1 toc)))
-              (if (or (not no-revisit) (reftex-get-buffer-visiting file))
+              (if (or (not no-revisit) (find-buffer-visiting file))
                   (progn
                     (switch-to-buffer-other-window
                      (reftex-get-file-buffer-force file nil))
@@ -981,7 +966,7 @@ label prefix determines the wording of a reference."
                                              reftex-section-levels-all)))
                                     "[[{]?"))))
            ((or (not no-revisit)
-                (reftex-get-buffer-visiting file))
+                (find-buffer-visiting file))
             ;; Marker is lost.  Use the backup method.
             (switch-to-buffer-other-window
              (reftex-get-file-buffer-force file nil))
@@ -1035,18 +1020,12 @@ section."
   (interactive)
   (if reftex-toc-auto-recenter-timer
       (progn
-        (if (featurep 'xemacs)
-            (delete-itimer reftex-toc-auto-recenter-timer)
-          (cancel-timer reftex-toc-auto-recenter-timer))
+        (cancel-timer reftex-toc-auto-recenter-timer)
         (setq reftex-toc-auto-recenter-timer nil)
         (message "Automatic recentering of TOC window was turned off"))
     (setq reftex-toc-auto-recenter-timer
-          (if (featurep 'xemacs)
-              (start-itimer "RefTeX Idle Timer for recenter"
-                            'reftex-recenter-toc-when-idle
-                            reftex-idle-time reftex-idle-time t)
-            (run-with-idle-timer
-             reftex-idle-time t 'reftex-recenter-toc-when-idle)))
+          (run-with-idle-timer
+           reftex-idle-time t #'reftex-recenter-toc-when-idle))
     (message "Automatic recentering of TOC window was turned on")))
 
 (defun reftex-toc-toggle-dedicated-frame ()
@@ -1090,15 +1069,12 @@ always show the current section in connection with the 
option
       (switch-to-buffer "*toc*")
       (select-frame current-frame)
       (cond ((fboundp 'x-focus-frame)
-             (x-focus-frame current-frame))
-            ((and (featurep 'xemacs) ; `focus-frame' is a nop in Emacs.
-                  (fboundp 'focus-frame))
-             (focus-frame current-frame)))
+             (x-focus-frame current-frame)))
       (select-window current-window)
       (when (eq reftex-auto-recenter-toc 'frame)
         (unless reftex-toc-auto-recenter-timer
           (reftex-toggle-auto-toc-recenter))
-        (add-hook 'delete-frame-functions 'reftex-toc-delete-frame-hook)))))
+        (add-hook 'delete-frame-functions #'reftex-toc-delete-frame-hook)))))
 
 (defun reftex-toc-delete-frame-hook (frame)
   (if (and reftex-toc-auto-recenter-timer
diff --git a/lisp/textmodes/reftex-vars.el b/lisp/textmodes/reftex-vars.el
index 1b29eaf..a65772d 100644
--- a/lisp/textmodes/reftex-vars.el
+++ b/lisp/textmodes/reftex-vars.el
@@ -1,4 +1,4 @@
-;;; reftex-vars.el --- configuration variables for RefTeX
+;;; reftex-vars.el --- configuration variables for RefTeX  -*- 
lexical-binding: t; -*-
 
 ;; Copyright (C) 1997-1999, 2001-2021 Free Software Foundation, Inc.
 
@@ -282,7 +282,7 @@ distribution.  Mixed-case symbols are convenience aliases.")
 The file name is expected after the command, either in braces or separated
 by whitespace."
   :group 'reftex-table-of-contents-browser
-  :set 'reftex-set-dirty
+  :set #'reftex-set-dirty
   :type '(repeat string))
 
 (defcustom reftex-max-section-depth 12
@@ -319,7 +319,7 @@ commands, promotion only works correctly if this list is 
sorted first
 by set, then within each set by level.  The promotion commands always
 select the nearest entry with the correct new level."
   :group 'reftex-table-of-contents-browser
-  :set 'reftex-set-dirty
+  :set #'reftex-set-dirty
   :type '(repeat
           (cons (string :tag "sectioning macro" "")
                 (choice
@@ -463,7 +463,7 @@ The value of this variable is a list of symbols with 
associations in the
 constant `reftex-label-alist-builtin'.  Check that constant for a full list
 of options."
   :group 'reftex-defining-label-environments
-  :set   'reftex-set-dirty
+  :set   #'reftex-set-dirty
   :type `(set
           :indent 4
           :inline t
@@ -611,7 +611,7 @@ Any list entry may also be a symbol.  If that has an 
association in
 list.  However, builtin defaults should normally be set with the variable
 `reftex-default-label-alist-entries'."
   :group 'reftex-defining-label-environments
-  :set 'reftex-set-dirty
+  :set #'reftex-set-dirty
   :type
   `(repeat
     (choice :tag "Package or Detailed   "
@@ -1198,7 +1198,7 @@ File names matched by these regexps will not be parsed by 
RefTeX.
 Intended for files which contain only `@string' macro definitions and the
 like, which are ignored by RefTeX anyway."
   :group 'reftex-citation-support
-  :set 'reftex-set-dirty
+  :set #'reftex-set-dirty
   :type '(repeat (regexp)))
 
 (defcustom reftex-default-bibliography nil
@@ -1318,7 +1318,7 @@ macro before insertion.  For example, it will change
     \\cite[][Chapter 1]{Jones}     -> \\cite[Chapter 1]{Jones}
     \\cite[see][]{Jones}           -> \\cite[see][]{Jones}
     \\cite[see][Chapter 1]{Jones}  -> \\cite{Jones}
-Is is possible that other packages have other conventions about which
+It is possible that other packages have other conventions about which
 optional argument is interpreted how - that is why this cleaning up
 can be turned off."
   :group 'reftex-citation-support
@@ -1460,7 +1460,7 @@ Note that AUCTeX sets these things internally for RefTeX 
as well, so
 with a sufficiently new version of AUCTeX, you should not set the
 package here."
   :group 'reftex-index-support
-  :set 'reftex-set-dirty
+  :set #'reftex-set-dirty
   :type `(list
           (repeat
            :inline t
@@ -1728,7 +1728,7 @@ Multiple directories can be separated by the system 
dependent `path-separator'.
 Directories ending in `//' or `!!' will be expanded recursively.
 See also `reftex-use-external-file-finders'."
   :group 'reftex-finding-files
-  :set 'reftex-set-dirty
+  :set #'reftex-set-dirty
   :type '(repeat (string :tag "Specification")))
 
 (defcustom reftex-bibpath-environment-variables '("BIBINPUTS" "TEXBIB")
@@ -1744,7 +1744,7 @@ Directories ending in `//' or `!!' will be expanded 
recursively.
 See also `reftex-use-external-file-finders'."
   :group 'reftex-citation-support
   :group 'reftex-finding-files
-  :set 'reftex-set-dirty
+  :set #'reftex-set-dirty
   :type '(repeat (string :tag "Specification")))
 
 (defcustom reftex-file-extensions '(("tex" . (".tex" ".ltx"))
diff --git a/lisp/textmodes/reftex.el b/lisp/textmodes/reftex.el
index be9b236..c732299 100644
--- a/lisp/textmodes/reftex.el
+++ b/lisp/textmodes/reftex.el
@@ -1,4 +1,4 @@
-;;; reftex.el --- minor mode for doing \label, \ref, \cite, \index in LaTeX
+;;; reftex.el --- minor mode for doing \label, \ref, \cite, \index in LaTeX  
-*- lexical-binding: t; -*-
 ;; Copyright (C) 1997-2000, 2003-2021 Free Software Foundation, Inc.
 
 ;; Author: Carsten Dominik <dominik@science.uva.nl>
@@ -38,9 +38,8 @@
 ;;
 ;;     https://www.gnu.org/software/auctex/manual/reftex.index.html
 ;;
-;; RefTeX is bundled with Emacs and available as a plug-in package for
-;; XEmacs 21.x.  If you need to install it yourself, you can find a
-;; distribution at
+;; RefTeX is bundled with Emacs.
+;; If you need to install it yourself, you can find a distribution at
 ;;
 ;;    https://www.gnu.org/software/auctex/reftex.html
 ;;
@@ -51,7 +50,8 @@
 ;;; Code:
 
 (eval-when-compile (require 'cl-lib))
-(require 'easymenu)
+(when (< emacs-major-version 28)  ; preloaded in Emacs 28
+  (require 'easymenu))
 
 (defvar reftex-tables-dirty t
   "Flag showing if tables need to be re-computed.")
@@ -99,37 +99,34 @@
 (defvar reftex-mode-map
   (let ((map (make-sparse-keymap)))
     ;; The default bindings in the mode map.
-    (define-key map "\C-c=" 'reftex-toc)
-    (define-key map "\C-c-" 'reftex-toc-recenter)
-    (define-key map "\C-c(" 'reftex-label)
-    (define-key map "\C-c)" 'reftex-reference)
-    (define-key map "\C-c[" 'reftex-citation)
-    (define-key map "\C-c<" 'reftex-index)
-    (define-key map "\C-c>" 'reftex-display-index)
-    (define-key map "\C-c/" 'reftex-index-selection-or-word)
-    (define-key map "\C-c\\" 'reftex-index-phrase-selection-or-word)
-    (define-key map "\C-c|" 'reftex-index-visit-phrases-buffer)
-    (define-key map "\C-c&" 'reftex-view-crossref)
+    (define-key map "\C-c=" #'reftex-toc)
+    (define-key map "\C-c-" #'reftex-toc-recenter)
+    (define-key map "\C-c(" #'reftex-label)
+    (define-key map "\C-c)" #'reftex-reference)
+    (define-key map "\C-c[" #'reftex-citation)
+    (define-key map "\C-c<" #'reftex-index)
+    (define-key map "\C-c>" #'reftex-display-index)
+    (define-key map "\C-c/" #'reftex-index-selection-or-word)
+    (define-key map "\C-c\\" #'reftex-index-phrase-selection-or-word)
+    (define-key map "\C-c|" #'reftex-index-visit-phrases-buffer)
+    (define-key map "\C-c&" #'reftex-view-crossref)
 
     ;; Bind `reftex-mouse-view-crossref' only when the key is still free
-    (if (featurep 'xemacs)
-        (unless (key-binding [(shift button2)])
-          (define-key map [(shift button2)] 'reftex-mouse-view-crossref))
-      (unless (key-binding [(shift mouse-2)])
-        (define-key map [(shift mouse-2)] 'reftex-mouse-view-crossref)))
+    (unless (key-binding [(shift mouse-2)])
+      (define-key map [(shift mouse-2)] #'reftex-mouse-view-crossref))
 
     ;; For most of these commands there are already bindings in place.
     ;; Setting `reftex-extra-bindings' really is only there to spare users
     ;; the hassle of defining bindings in the user space themselves.  This
     ;; is why they violate the key binding recommendations.
     (when reftex-extra-bindings
-      (define-key map "\C-ct" 'reftex-toc)
-      (define-key map "\C-cl" 'reftex-label)
-      (define-key map "\C-cr" 'reftex-reference)
-      (define-key map "\C-cc" 'reftex-citation)
-      (define-key map "\C-cv" 'reftex-view-crossref)
-      (define-key map "\C-cg" 'reftex-grep-document)
-      (define-key map "\C-cs" 'reftex-search-document))
+      (define-key map "\C-ct" #'reftex-toc)
+      (define-key map "\C-cl" #'reftex-label)
+      (define-key map "\C-cr" #'reftex-reference)
+      (define-key map "\C-cc" #'reftex-citation)
+      (define-key map "\C-cv" #'reftex-view-crossref)
+      (define-key map "\C-cg" #'reftex-grep-document)
+      (define-key map "\C-cs" #'reftex-search-document))
 
     map)
   "Keymap for RefTeX mode.")
@@ -203,8 +200,6 @@ on the menu bar.
   (if reftex-mode
       (progn
         ;; Mode was turned on
-        (when (featurep 'xemacs)
-          (easy-menu-add reftex-mode-menu))
         (and reftex-plug-into-AUCTeX
              (reftex-plug-into-AUCTeX))
         (unless (get 'reftex-auto-view-crossref 'initialized)
@@ -219,10 +214,7 @@ on the menu bar.
         ;; Prepare the special syntax tables.
        (reftex--prepare-syntax-tables)
 
-        (run-hooks 'reftex-mode-hook))
-    ;; Mode was turned off
-    (when (featurep 'xemacs)
-      (easy-menu-remove reftex-mode-menu))))
+        (run-hooks 'reftex-mode-hook))))
 
 (defvar reftex-docstruct-symbol)
 (defun reftex-kill-buffer-hook ()
@@ -390,11 +382,11 @@ If the symbols for the current master file do not exist, 
they are created."
      ((null master)
       (error "Need a filename for this buffer, please save it first"))
      ((or (file-exists-p (concat master ".tex"))
-          (reftex-get-buffer-visiting (concat master ".tex")))
+          (find-buffer-visiting (concat master ".tex")))
       ;; Ahh, an extra .tex was missing...
       (setq master (concat master ".tex")))
      ((or (file-exists-p master)
-          (reftex-get-buffer-visiting master))
+          (find-buffer-visiting master))
       ;; We either see the file, or have a buffer on it.  OK.
       )
      (t
@@ -889,7 +881,7 @@ This enforces rescanning the buffer on next use."
         ;; Are the magic words regular expressions?  Quote normal words.
         (if (eq (car wordlist) 'regexp)
             (setq wordlist (cdr wordlist))
-          (setq wordlist (mapcar 'regexp-quote wordlist)))
+          (setq wordlist (mapcar #'regexp-quote wordlist)))
         ;; Remember the first association of each word.
         (while (stringp (setq word (pop wordlist)))
           (or (assoc word reftex-words-to-typekey-alist)
@@ -1016,11 +1008,11 @@ This enforces rescanning the buffer on next use."
            (wbol "\\(^\\)%?[ \t]*") ; Need to keep the empty group because
                                     ; match numbers are hard coded
            (label-re (concat "\\(?:"
-                            (mapconcat 'identity reftex-label-regexps "\\|")
+                            (mapconcat #'identity reftex-label-regexps "\\|")
                             "\\)"))
            (include-re (concat wbol
                                "\\\\\\("
-                               (mapconcat 'identity
+                               (mapconcat #'identity
                                           reftex-include-file-commands "\\|")
                                "\\)[{ \t]+\\([^} \t\n\r]+\\)"))
            (section-re
@@ -1032,23 +1024,24 @@ This enforces rescanning the buffer on next use."
            (macro-re
             (if macros-with-labels
                 (concat "\\("
-                        (mapconcat 'regexp-quote macros-with-labels "\\|")
+                        (mapconcat #'regexp-quote macros-with-labels "\\|")
                         "\\)[[{]")
               ""))
            (index-re
             (concat "\\("
-                    (mapconcat 'regexp-quote reftex-macros-with-index "\\|")
+                    (mapconcat #'regexp-quote reftex-macros-with-index "\\|")
                     "\\)[[{]"))
            (find-index-re-format
             (concat "\\("
-                    (mapconcat 'regexp-quote reftex-macros-with-index "\\|")
+                    (mapconcat #'regexp-quote reftex-macros-with-index "\\|")
                     "\\)\\([[{][^]}]*[]}]\\)*[[{]\\(%s\\)[]}]"))
            (find-label-re-format
             (concat "\\("
                    "label[[:space:]]*=[[:space:]]*"
                    "\\|"
-                    (mapconcat 'regexp-quote (append '("\\label")
-                                                     macros-with-labels) "\\|")
+                    (mapconcat #'regexp-quote (append '("\\label")
+                                                      macros-with-labels)
+                               "\\|")
                     "\\)\\([[{][^]}]*[]}]\\)*[[{]\\(%s\\)[]}]"))
            (index-level-re
             (regexp-quote (nth 0 reftex-index-special-chars)))
@@ -1080,7 +1073,7 @@ This enforces rescanning the buffer on next use."
             "\\([]} \t\n\r]\\)\\([[{]\\)\\(%s\\)[]}]")
       (message "Compiling label environment definitions...done")))
   (put reftex-docstruct-symbol 'reftex-cache
-       (mapcar 'symbol-value reftex-cache-variables)))
+       (mapcar #'symbol-value reftex-cache-variables)))
 
 (defun reftex-parse-args (macro)
   ;; Return a list of macro name, nargs, arg-nr which is label and a list of
@@ -1276,8 +1269,8 @@ Valid actions are: readable, restore, read, kill, write."
       (- 1 xr-index))
      (t
       (save-excursion
-        (let* ((length (apply 'max (mapcar
-                                    (lambda(x) (length (car x))) xr-alist)))
+        (let* ((length (apply #'max (mapcar
+                                     (lambda(x) (length (car x))) xr-alist)))
                (fmt (format " [%%c]  %%-%ds  %%s\n" length))
                (n (1- ?0)))
           (setq key
@@ -1311,7 +1304,7 @@ When DIE is non-nil, throw an error if file not found."
          (extensions (cdr (assoc type reftex-file-extensions)))
          (def-ext (car extensions))
          (ext-re (concat "\\("
-                         (mapconcat 'regexp-quote extensions "\\|")
+                         (mapconcat #'regexp-quote extensions "\\|")
                          "\\)\\'"))
          (files (if (string-match ext-re file)
                     (cons file nil)
@@ -1353,7 +1346,7 @@ When DIE is non-nil, throw an error if file not found."
         out)
     (if (string-match "%f" prg)
         (setq prg (replace-match file t t prg)))
-    (setq out (apply 'reftex-process-string (split-string prg)))
+    (setq out (apply #'reftex-process-string (split-string prg)))
     (if (string-match "[ \t\n]+\\'" out)     ; chomp
         (setq out (replace-match "" nil nil out)))
     (cond ((equal out "") nil)
@@ -1366,7 +1359,7 @@ When DIE is non-nil, throw an error if file not found."
     (with-output-to-string
       (with-current-buffer standard-output
         (let ((default-directory calling-dir)) ; set default directory
-          (apply 'call-process program nil '(t nil) nil args))))))
+          (apply #'call-process program nil '(t nil) nil args))))))
 
 (defun reftex-access-search-path (type &optional recurse master-dir file)
   ;; Access path from environment variables.  TYPE is either "tex" or "bib".
@@ -1385,7 +1378,7 @@ When DIE is non-nil, throw an error if file not found."
              (mapconcat
               (lambda(x)
                 (if (string-match "^!" x)
-                    (apply 'reftex-process-string
+                    (apply #'reftex-process-string
                            (split-string (substring x 1)))
                   (or (getenv x) x)))
               ;; For consistency, the next line should look like this:
@@ -1530,12 +1523,7 @@ When DIE is non-nil, throw an error if file not found."
   (when (match-beginning n)
     (buffer-substring-no-properties (match-beginning n) (match-end n))))
 
-(defun reftex-region-active-p ()
-  "Should we operate on an active region?"
-  (if (fboundp 'use-region-p)
-      (use-region-p)
-    ;; For XEmacs.
-    (region-active-p)))
+(define-obsolete-function-alias 'reftex-region-active-p #'use-region-p "28.1")
 
 (defun reftex-kill-buffer (buffer)
   ;; Kill buffer if it exists.
@@ -1744,26 +1732,12 @@ When DIE is non-nil, throw an error if file not found."
       (setq string (replace-match "[\n\r]" nil t string)))
     string))
 
-(defun reftex-get-buffer-visiting (file)
-  ;; return a buffer visiting FILE
-  (cond
-   ((boundp 'find-file-compare-truenames) ; XEmacs
-    (let ((find-file-compare-truenames t))
-      (get-file-buffer file)))
-   ((fboundp 'find-buffer-visiting)       ; Emacs
-    (find-buffer-visiting file))
-   (t (error "This should not happen (reftex-get-buffer-visiting)"))))
-
-;; Define `current-message' for compatibility with XEmacs prior to 20.4
-(defvar message-stack)
-(if (and (featurep 'xemacs)
-         (not (fboundp 'current-message)))
-    (defun current-message (&optional _frame)
-      (cdr (car message-stack))))
+(define-obsolete-function-alias 'reftex-get-buffer-visiting
+  #'find-buffer-visiting "28.1")
 
 (defun reftex-visited-files (list)
   ;; Takes a list of filenames and returns the buffers of those already visited
-  (delq nil (mapcar (lambda (x) (if (reftex-get-buffer-visiting x) x nil))
+  (delq nil (mapcar (lambda (x) (if (find-buffer-visiting x) x nil))
                     list)))
 
 (defun reftex-get-file-buffer-force (file &optional mark-to-kill)
@@ -1773,7 +1747,7 @@ When DIE is non-nil, throw an error if file not found."
   ;; initializations according to `reftex-initialize-temporary-buffers',
   ;; and mark the buffer to be killed after use.
 
-  (let ((buf (reftex-get-buffer-visiting file)))
+  (let ((buf (find-buffer-visiting file)))
 
     (cond (buf
            ;; We have it already as a buffer - just return it
@@ -1865,7 +1839,7 @@ When DIE is non-nil, throw an error if file not found."
   (setq list (copy-sequence list))
   (if sort
       (progn
-       (setq list (sort list 'string<))
+       (setq list (sort list #'string<))
        (let ((p list))
          (while (cdr p)
            (if (string= (car p) (car (cdr p)))
@@ -2002,7 +1976,7 @@ IGNORE-WORDS List of words which should be removed from 
the string."
         (setcdr (nthcdr (1- nwords) words) nil))
 
     ;; First, try to use all words
-    (setq string (mapconcat 'identity words sep))
+    (setq string (mapconcat #'identity words sep))
 
     ;; Abbreviate words if enforced by user settings or string length
     (if (or (eq t abbrev)
@@ -2016,7 +1990,7 @@ IGNORE-WORDS List of words which should be removed from 
the string."
                                  (match-string 1 w))
                              w))
                words)
-              string (mapconcat 'identity words sep)))
+              string (mapconcat #'identity words sep)))
 
     ;; Shorten if still to long
     (setq string
@@ -2080,24 +2054,11 @@ IGNORE-WORDS List of words which should be removed from 
the string."
         (progn
           ;; Rename buffer temporarily to start w/o space (because of 
font-lock)
           (rename-buffer newname t)
-          (cond
-           ((fboundp 'font-lock-default-fontify-region)
-            ;; Good: we have the indirection functions
-            (set (make-local-variable 'font-lock-fontify-region-function)
-                 'reftex-select-font-lock-fontify-region)
-            (let ((major-mode 'latex-mode))
-              (font-lock-mode 1)))
-           ((fboundp 'font-lock-set-defaults-1)
-            ;; Looks like the XEmacs font-lock stuff.
-            ;; FIXME: this is still kind of a hack, but it works.
-            (set (make-local-variable 'font-lock-keywords) nil)
-            (let ((major-mode 'latex-mode)
-                  (font-lock-defaults-computed nil))
-              (font-lock-set-defaults-1)
-              (reftex-select-font-lock-fontify-region (point-min) 
(point-max))))
-           (t
-            ;; Oops?
-            (message "Sorry: cannot refontify RefTeX Select buffer."))))
+          ;; Good: we have the indirection functions
+          (set (make-local-variable 'font-lock-fontify-region-function)
+               #'reftex-select-font-lock-fontify-region)
+          (let ((major-mode 'latex-mode))
+            (font-lock-mode 1)))
       (rename-buffer oldname))))
 
 (defun reftex-select-font-lock-fontify-region (beg end &optional _loudly)
@@ -2122,46 +2083,39 @@ IGNORE-WORDS List of words which should be removed from 
the string."
   (let (face)
     (catch 'exit
       (while (setq face (pop faces))
-        (if (featurep 'xemacs)
-            (if (find-face face) (throw 'exit face))
-          (if (facep face) (throw 'exit face)))))))
-
-;; Highlighting uses overlays.  For XEmacs, we use extends.
-(defalias 'reftex-make-overlay
-  (if (featurep 'xemacs) 'make-extent 'make-overlay))
-(defalias 'reftex-overlay-put
-  (if (featurep 'xemacs) 'set-extent-property 'overlay-put))
-(defalias 'reftex-move-overlay
-  (if (featurep 'xemacs) 'set-extent-endpoints 'move-overlay))
-(defalias 'reftex-delete-overlay
-  (if (featurep 'xemacs) 'detach-extent 'delete-overlay))
+        (if (facep face) (throw 'exit face))))))
+
+(define-obsolete-function-alias 'reftex-make-overlay #'make-overlay "28.1")
+(define-obsolete-function-alias 'reftex-overlay-put #'overlay-put "28.1")
+(define-obsolete-function-alias 'reftex-move-overlay #'move-overlay "28.1")
+(define-obsolete-function-alias 'reftex-delete-overlay #'delete-overlay "28.1")
 
 ;; We keep a vector with several different overlays to do our highlighting.
 (defvar reftex-highlight-overlays [nil nil nil])
 
 ;; Initialize the overlays
-(aset reftex-highlight-overlays 0 (reftex-make-overlay 1 1))
-(reftex-overlay-put (aref reftex-highlight-overlays 0)
+(aset reftex-highlight-overlays 0 (make-overlay 1 1))
+(overlay-put (aref reftex-highlight-overlays 0)
              'face 'highlight)
-(aset reftex-highlight-overlays 1 (reftex-make-overlay 1 1))
-(reftex-overlay-put (aref reftex-highlight-overlays 1)
+(aset reftex-highlight-overlays 1 (make-overlay 1 1))
+(overlay-put (aref reftex-highlight-overlays 1)
              'face reftex-cursor-selected-face)
-(aset reftex-highlight-overlays 2 (reftex-make-overlay 1 1))
-(reftex-overlay-put (aref reftex-highlight-overlays 2)
+(aset reftex-highlight-overlays 2 (make-overlay 1 1))
+(overlay-put (aref reftex-highlight-overlays 2)
              'face reftex-cursor-selected-face)
 
 ;; Two functions for activating and deactivation highlight overlays
 (defun reftex-highlight (index begin end &optional buffer)
   "Highlight a region with overlay INDEX."
-  (reftex-move-overlay (aref reftex-highlight-overlays index)
+  (move-overlay (aref reftex-highlight-overlays index)
                 begin end (or buffer (current-buffer))))
 (defun reftex-unhighlight (index)
   "Detach overlay INDEX."
-  (reftex-delete-overlay (aref reftex-highlight-overlays index)))
+  (delete-overlay (aref reftex-highlight-overlays index)))
 
 (defun reftex-highlight-shall-die ()
   ;; Function used in pre-command-hook to remove highlights.
-  (remove-hook 'pre-command-hook 'reftex-highlight-shall-die)
+  (remove-hook 'pre-command-hook #'reftex-highlight-shall-die)
   (reftex-unhighlight 0))
 
 ;;; =========================================================================
@@ -2173,7 +2127,7 @@ IGNORE-WORDS List of words which should be removed from 
the string."
 ;; Bind `reftex-view-crossref-from-bibtex' in BibTeX mode map
 (eval-after-load
  "bibtex"
- '(define-key bibtex-mode-map "\C-c&" 'reftex-view-crossref-from-bibtex))
+ '(define-key bibtex-mode-map "\C-c&" #'reftex-view-crossref-from-bibtex))
 
 ;;; =========================================================================
 ;;;
@@ -2378,9 +2332,9 @@ Your bug report will be posted to the AUCTeX bug 
reporting list.
 
 ;;; Install the kill-buffer and kill-emacs hooks ------------------------------
 
-(add-hook 'kill-buffer-hook 'reftex-kill-buffer-hook)
+(add-hook 'kill-buffer-hook #'reftex-kill-buffer-hook)
 (unless noninteractive
-  (add-hook 'kill-emacs-hook  'reftex-kill-emacs-hook))
+  (add-hook 'kill-emacs-hook #'reftex-kill-emacs-hook))
 
 ;;; Run Hook ------------------------------------------------------------------
 
diff --git a/lisp/textmodes/remember.el b/lisp/textmodes/remember.el
index 820ee38..b731c12 100644
--- a/lisp/textmodes/remember.el
+++ b/lisp/textmodes/remember.el
@@ -1,4 +1,4 @@
-;;; remember --- a mode for quickly jotting down things to remember
+;;; remember --- a mode for quickly jotting down things to remember  -*- 
lexical-binding: t; -*-
 
 ;; Copyright (C) 1999-2001, 2003-2021 Free Software Foundation, Inc.
 
@@ -193,24 +193,20 @@
 (defcustom remember-mode-hook nil
   "Functions run upon entering `remember-mode'."
   :type 'hook
-  :options '(flyspell-mode turn-on-auto-fill org-remember-apply-template)
-  :group 'remember)
+  :options '(flyspell-mode turn-on-auto-fill org-remember-apply-template))
 
 (defcustom remember-in-new-frame nil
   "Non-nil means use a separate frame for capturing remember data."
-  :type 'boolean
-  :group 'remember)
+  :type 'boolean)
 
 (defcustom remember-register ?R
   "The register in which the window configuration is stored."
-  :type 'character
-  :group 'remember)
+  :type 'character)
 
 (defcustom remember-filter-functions nil
   "Functions run to filter remember data.
 All functions are run in the remember buffer."
-  :type 'hook
-  :group 'remember)
+  :type 'hook)
 
 (defcustom remember-handler-functions '(remember-append-to-file)
   "Functions run to process remember data.
@@ -223,13 +219,11 @@ recorded somewhere by that function."
              remember-append-to-file
              remember-store-in-files
              remember-diary-extract-entries
-             org-remember-handler)
-  :group 'remember)
+             org-remember-handler))
 
 (defcustom remember-all-handler-functions nil
   "If non-nil every function in `remember-handler-functions' is called."
-  :type 'boolean
-  :group 'remember)
+  :type 'boolean)
 
 ;; See below for more user variables.
 
@@ -240,16 +234,14 @@ recorded somewhere by that function."
 
 (defcustom remember-save-after-remembering t
   "Non-nil means automatically save after remembering."
-  :type 'boolean
-  :group 'remember)
+  :type 'boolean)
 
 ;;; User Functions:
 
 (defcustom remember-annotation-functions '(buffer-file-name)
   "Hook that returns an annotation to be inserted into the remember buffer."
   :type 'hook
-  :options '(org-remember-annotation buffer-file-name)
-  :group 'remember)
+  :options '(org-remember-annotation buffer-file-name))
 
 (defvar remember-annotation nil
   "Current annotation.")
@@ -258,13 +250,11 @@ recorded somewhere by that function."
 
 (defcustom remember-before-remember-hook nil
   "Functions run before switching to the *Remember* buffer."
-  :type 'hook
-  :group 'remember)
+  :type 'hook)
 
 (defcustom remember-run-all-annotation-functions-flag nil
   "Non-nil means use all annotations returned by 
`remember-annotation-functions'."
-  :type 'boolean
-  :group 'remember)
+  :type 'boolean)
 
 ;;;###autoload
 (defun remember (&optional initial)
@@ -280,12 +270,13 @@ With a prefix or a visible region, use the region as 
INITIAL."
            (buffer-substring (region-beginning) (region-end)))))
   (funcall (if remember-in-new-frame
                #'frameset-to-register
-             #'window-configuration-to-register) remember-register)
+             #'window-configuration-to-register)
+           remember-register)
   (let* ((annotation
           (if remember-run-all-annotation-functions-flag
-              (mapconcat 'identity
+              (mapconcat #'identity
                          (delq nil
-                               (mapcar 'funcall remember-annotation-functions))
+                               (mapcar #'funcall 
remember-annotation-functions))
                          "\n")
             (run-hook-with-args-until-success
              'remember-annotation-functions)))
@@ -293,7 +284,8 @@ With a prefix or a visible region, use the region as 
INITIAL."
     (run-hooks 'remember-before-remember-hook)
     (funcall (if remember-in-new-frame
                  #'switch-to-buffer-other-frame
-               #'switch-to-buffer-other-window) buf)
+               #'switch-to-buffer-other-window)
+             buf)
     (if remember-in-new-frame
         (set-window-dedicated-p
          (get-buffer-window (current-buffer) (selected-frame)) t))
@@ -337,13 +329,11 @@ With a prefix or a visible region, use the region as 
INITIAL."
 
 (defcustom remember-mailbox "~/Mail/remember"
   "The file in which to store remember data as mail."
-  :type 'file
-  :group 'remember)
+  :type 'file)
 
 (defcustom remember-default-priority "medium"
   "The default priority for remembered mail messages."
-  :type 'string
-  :group 'remember)
+  :type 'string)
 
 (defun remember-store-in-mailbox ()
   "Store remember data as if it were incoming mail.
@@ -396,19 +386,16 @@ exists) might be changed."
              (with-current-buffer buf
                (set-visited-file-name
                 (expand-file-name remember-data-file))))))
-  :initialize 'custom-initialize-default
-  :group 'remember)
+  :initialize #'custom-initialize-default)
 
 (defcustom remember-leader-text "** "
   "The text used to begin each remember item."
-  :type 'string
-  :group 'remember)
+  :type 'string)
 
 (defcustom remember-time-format "%a %b %d %H:%M:%S %Y"
   "The format for time stamp, passed to `format-time-string'.
 The default emulates `current-time-string' for backward compatibility."
   :type 'string
-  :group 'remember
   :version "27.1")
 
 (defcustom remember-text-format-function nil
@@ -416,7 +403,6 @@ The default emulates `current-time-string' for backward 
compatibility."
 The function receives the remembered text as argument and should
 return the text to be remembered."
   :type '(choice (const nil) function)
-  :group 'remember
   :version "28.1")
 
 (defun remember-append-to-file ()
@@ -465,16 +451,14 @@ If you want to remember a region, supply a universal 
prefix to
   "The directory in which to store remember data as files.
 Used by `remember-store-in-files'."
   :type 'directory
-  :version "24.4"
-  :group 'remember)
+  :version "24.4")
 
 (defcustom remember-directory-file-name-format "%Y-%m-%d_%T-%z"
   "Format string for the file name in which to store unprocessed data.
 This is passed to `format-time-string'.
 Used by `remember-store-in-files'."
   :type 'string
-  :version "24.4"
-  :group 'remember)
+  :version "24.4")
 
 (defun remember-store-in-files ()
   "Store remember data in a file in `remember-data-directory'.
@@ -511,8 +495,7 @@ Most useful for remembering things from other applications."
 (defcustom remember-diary-file nil
   "File for extracted diary entries.
 If this is nil, then `diary-file' will be used instead."
-  :type '(choice (const :tag "diary-file" nil) file)
-  :group 'remember)
+  :type '(choice (const :tag "diary-file" nil) file))
 
 (defvar calendar-date-style)            ; calendar.el
 
@@ -560,7 +543,7 @@ If this is nil, then `diary-file' will be used instead."
       (while (re-search-forward remember-diary-regexp nil t)
         (push (remember-diary-convert-entry (match-string 1)) list))
       (when list
-        (diary-make-entry (mapconcat 'identity list "\n")
+        (diary-make-entry (mapconcat #'identity list "\n")
                           nil remember-diary-file)
         (when remember-save-after-remembering
           (with-current-buffer (find-buffer-visiting (or remember-diary-file
@@ -572,9 +555,9 @@ If this is nil, then `diary-file' will be used instead."
 
 (defvar remember-mode-map
   (let ((map (make-sparse-keymap)))
-    (define-key map "\C-x\C-s" 'remember-finalize)
-    (define-key map "\C-c\C-c" 'remember-finalize)
-    (define-key map "\C-c\C-k" 'remember-destroy)
+    (define-key map "\C-x\C-s" #'remember-finalize)
+    (define-key map "\C-c\C-c" #'remember-finalize)
+    (define-key map "\C-c\C-k" #'remember-destroy)
     map)
   "Keymap used in `remember-mode'.")
 
@@ -620,7 +603,7 @@ If this is nil, use `initial-major-mode'."
 
 (defvar remember-notes-mode-map
   (let ((map (make-sparse-keymap)))
-    (define-key map "\C-c\C-c" 'remember-notes-save-and-bury-buffer)
+    (define-key map "\C-c\C-c" #'remember-notes-save-and-bury-buffer)
     map)
   "Keymap used in `remember-notes-mode'.")
 
diff --git a/lisp/textmodes/rst.el b/lisp/textmodes/rst.el
index 2b31e7e..ce15637 100644
--- a/lisp/textmodes/rst.el
+++ b/lisp/textmodes/rst.el
@@ -105,10 +105,6 @@
 ;; Common Lisp stuff
 (require 'cl-lib)
 
-;; Correct wrong declaration.
-(def-edebug-spec push
-  (&or [form symbolp] [form gv-place]))
-
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;; Support for `testcover'
 
@@ -620,7 +616,7 @@ After interpretation of ARGS the results are concatenated 
as for
    (:constructor
     rst-Ado-new-transition
     (&aux
-     (char nil)
+     ;; (char nil)
      (-style 'transition)))
    ;; Construct a simple section header.
    (:constructor
diff --git a/lisp/textmodes/sgml-mode.el b/lisp/textmodes/sgml-mode.el
index 7051f52..6958ab8 100644
--- a/lisp/textmodes/sgml-mode.el
+++ b/lisp/textmodes/sgml-mode.el
@@ -34,6 +34,7 @@
 
 (require 'dom)
 (require 'seq)
+(require 'facemenu)
 (eval-when-compile (require 'subr-x))
 (eval-when-compile
   (require 'skeleton)
@@ -117,8 +118,7 @@ definitions.  So we normally turn it off.")
 This takes effect when first loading the `sgml-mode' library.")
 
 (defvar sgml-mode-map
-  (let ((map (make-keymap))    ;`sparse' doesn't allow binding to charsets.
-       (menu-map (make-sparse-keymap "SGML")))
+  (let ((map (make-keymap)))   ;`sparse' doesn't allow binding to charsets.
     (define-key map "\C-c\C-i" 'sgml-tags-invisible)
     (define-key map "/" 'sgml-slash)
     (define-key map "\C-c\C-n" 'sgml-name-char)
@@ -153,26 +153,24 @@ This takes effect when first loading the `sgml-mode' 
library.")
          (map (nth 1 map)))
       (while (< (setq c (1+ c)) 256)
        (aset map c 'sgml-maybe-name-self)))
-    (define-key map [menu-bar sgml] (cons "SGML" menu-map))
-    (define-key menu-map [sgml-validate] '("Validate" . sgml-validate))
-    (define-key menu-map [sgml-name-8bit-mode]
-      '("Toggle 8 Bit Insertion" . sgml-name-8bit-mode))
-    (define-key menu-map [sgml-tags-invisible]
-      '("Toggle Tag Visibility" . sgml-tags-invisible))
-    (define-key menu-map [sgml-tag-help]
-      '("Describe Tag" . sgml-tag-help))
-    (define-key menu-map [sgml-delete-tag]
-      '("Delete Tag" . sgml-delete-tag))
-    (define-key menu-map [sgml-skip-tag-forward]
-      '("Forward Tag" . sgml-skip-tag-forward))
-    (define-key menu-map [sgml-skip-tag-backward]
-      '("Backward Tag" . sgml-skip-tag-backward))
-    (define-key menu-map [sgml-attributes]
-      '("Insert Attributes" . sgml-attributes))
-    (define-key menu-map [sgml-tag] '("Insert Tag" . sgml-tag))
     map)
   "Keymap for SGML mode.  See also `sgml-specials'.")
 
+(easy-menu-define sgml-mode-menu sgml-mode-map
+  "Menu for SGML mode."
+  '("SGML"
+    ["Insert Tag" sgml-tag]
+    ["Insert Attributes" sgml-attributes]
+    ["Backward Tag" sgml-skip-tag-backward]
+    ["Forward Tag" sgml-skip-tag-forward]
+    ["Delete Tag" sgml-delete-tag]
+    ["Describe Tag" sgml-tag-help]
+    "---"
+    ["Toggle Tag Visibility" sgml-tags-invisible]
+    ["Toggle 8 Bit Insertion" sgml-name-8bit-mode]
+    "---"
+    ["Validate" sgml-validate]))
+
 (defun sgml-make-syntax-table (specials)
   (let ((table (make-syntax-table text-mode-syntax-table)))
     (modify-syntax-entry ?< "(>" table)
@@ -1788,8 +1786,7 @@ This defaults to `sgml-quick-keys'.
 This takes effect when first loading the library.")
 
 (defvar html-mode-map
-  (let ((map (make-sparse-keymap))
-       (menu-map (make-sparse-keymap "HTML")))
+  (let ((map (make-sparse-keymap)))
     (set-keymap-parent map  sgml-mode-map)
     (define-key map "\C-c6" 'html-headline-6)
     (define-key map "\C-c5" 'html-headline-5)
@@ -1826,34 +1823,35 @@ This takes effect when first loading the library.")
       (define-key map "\C-cs" 'html-span))
     (define-key map "\C-c\C-s" 'html-autoview-mode)
     (define-key map "\C-c\C-v" 'browse-url-of-buffer)
-    (define-key map [menu-bar html] (cons "HTML" menu-map))
-    (define-key menu-map [html-autoview-mode]
-      '("Toggle Autoviewing" . html-autoview-mode))
-    (define-key menu-map [browse-url-of-buffer]
-      '("View Buffer Contents" . browse-url-of-buffer))
-    (define-key menu-map [nil] '("--"))
-    ;;(define-key menu-map "6" '("Heading 6" . html-headline-6))
-    ;;(define-key menu-map "5" '("Heading 5" . html-headline-5))
-    ;;(define-key menu-map "4" '("Heading 4" . html-headline-4))
-    (define-key menu-map "3" '("Heading 3" . html-headline-3))
-    (define-key menu-map "2" '("Heading 2" . html-headline-2))
-    (define-key menu-map "1" '("Heading 1" . html-headline-1))
-    (define-key menu-map "l" '("Radio Buttons" . html-radio-buttons))
-    (define-key menu-map "c" '("Checkboxes" . html-checkboxes))
-    (define-key menu-map "l" '("List Item" . html-list-item))
-    (define-key menu-map "u" '("Unordered List" . html-unordered-list))
-    (define-key menu-map "o" '("Ordered List" . html-ordered-list))
-    (define-key menu-map "-" '("Horizontal Rule" . html-horizontal-rule))
-    (define-key menu-map "\n" '("Line Break" . html-line))
-    (define-key menu-map "\r" '("Paragraph" . html-paragraph))
-    (define-key menu-map "i" '("Image" . html-image))
-    (define-key menu-map "h" '("Href Anchor URL" . html-href-anchor))
-    (define-key menu-map "f" '("Href Anchor File" . html-href-anchor-file))
-    (define-key menu-map "n" '("Name Anchor" . html-name-anchor))
-    (define-key menu-map "#" '("ID Anchor" . html-id-anchor))
     map)
   "Keymap for commands for use in HTML mode.")
 
+(easy-menu-define html-mode-menu html-mode-map
+  "Menu for HTML mode."
+  '("HTML"
+    ["ID Anchor" html-id-anchor]
+    ["Name Anchor" html-name-anchor]
+    ["Href Anchor File" html-href-anchor-file]
+    ["Href Anchor URL" html-href-anchor]
+    ["Image" html-image]
+    ["Paragraph" html-paragraph]
+    ["Line Break" html-line]
+    ["Horizontal Rule" html-horizontal-rule]
+    ["Ordered List" html-ordered-list]
+    ["Unordered List" html-unordered-list]
+    ["List Item" html-list-item]
+    ["Checkboxes" html-checkboxes]
+    ["Radio Buttons" html-radio-buttons]
+    ["Heading 1" html-headline-1]
+    ["Heading 2" html-headline-2]
+    ["Heading 3" html-headline-3]
+    ;; ["Heading 4" html-headline-4]
+    ;; ["Heading 5" html-headline-5]
+    ;; ["Heading 6" html-headline-6]
+    "---"
+    ["View Buffer Contents" browse-url-of-buffer]
+    ["Toggle Autoviewing" html-autoview-mode]))
+
 (defvar html-face-tag-alist
   '((bold . "strong")
     (italic . "em")
@@ -2370,7 +2368,7 @@ or Edit/Text Properties/Face commands.
 Pages can have <a name=\"SOMENAME\">named points</a> and can link other points
 to them with <a href=\"#SOMENAME\">see also somename</a>.  In the same way <a
 href=\"URL\">see also URL</a> where URL is a filename relative to current
-directory, or absolute as in `http://www.cs.indiana.edu/elisp/w3/docs.html'.
+directory, or absolute as in `https://www.cs.indiana.edu/elisp/w3/docs.html'.
 
 Images in many formats can be inlined with <img src=\"URL\">.
 
diff --git a/lisp/textmodes/table.el b/lisp/textmodes/table.el
index 06785e4..13b4a6d 100644
--- a/lisp/textmodes/table.el
+++ b/lisp/textmodes/table.el
@@ -1306,17 +1306,16 @@ the last cache point coordinate."
   (let ((func-symbol (intern (format "*table--cell-%s" command)))
         (doc-string (format "Table remapped function for `%s'." command)))
     (defalias func-symbol
-      `(lambda
-         (&rest args)
-         ,doc-string
-         (interactive)
-         (let ((table-inhibit-update t)
-               (deactivate-mark nil))
-           (table--finish-delayed-tasks)
-           (table-recognize-cell 'force)
-           (table-with-cache-buffer
-             (call-interactively ',command)
-             (setq table-inhibit-auto-fill-paragraph t)))))
+      (lambda (&rest _args)
+        (:documentation doc-string)
+        (interactive)
+        (let ((table-inhibit-update t)
+              (deactivate-mark nil))
+          (table--finish-delayed-tasks)
+          (table-recognize-cell 'force)
+          (table-with-cache-buffer
+           (call-interactively command)
+           (setq table-inhibit-auto-fill-paragraph t)))))
     (push (cons command func-symbol)
           table-command-remap-alist)))
 
@@ -1338,17 +1337,16 @@ the last cache point coordinate."
   (let ((func-symbol (intern (format "*table--cell-%s" command)))
         (doc-string (format "Table remapped function for `%s'." command)))
     (defalias func-symbol
-      `(lambda
-         (&rest args)
-         ,doc-string
-         (interactive)
-         (table--finish-delayed-tasks)
-         (table-recognize-cell 'force)
-         (table-with-cache-buffer
-           (table--remove-cell-properties (point-min) (point-max))
-           (table--remove-eol-spaces (point-min) (point-max))
-           (call-interactively ',command))
-         (table--finish-delayed-tasks)))
+      (lambda (&rest _args)
+        (:documentation doc-string)
+        (interactive)
+        (table--finish-delayed-tasks)
+        (table-recognize-cell 'force)
+        (table-with-cache-buffer
+         (table--remove-cell-properties (point-min) (point-max))
+         (table--remove-eol-spaces (point-min) (point-max))
+         (call-interactively command))
+        (table--finish-delayed-tasks)))
     (push (cons command func-symbol)
           table-command-remap-alist)))
 
@@ -1360,19 +1358,18 @@ the last cache point coordinate."
            insert))
   (let ((func-symbol (intern (format "*table--cell-%s" command)))
         (doc-string (format "Table remapped function for `%s'." command)))
-    (fset func-symbol
-          `(lambda
-             (&rest args)
-             ,doc-string
-             (interactive)
-             (table--finish-delayed-tasks)
-             (table-recognize-cell 'force)
-             (table-with-cache-buffer
-               (call-interactively ',command)
-               (table--untabify (point-min) (point-max))
-               (table--fill-region (point-min) (point-max))
-               (setq table-inhibit-auto-fill-paragraph t))
-             (table--finish-delayed-tasks)))
+    (defalias func-symbol
+      (lambda (&rest _args)
+        (:documentation doc-string)
+        (interactive)
+        (table--finish-delayed-tasks)
+        (table-recognize-cell 'force)
+        (table-with-cache-buffer
+         (call-interactively command)
+         (table--untabify (point-min) (point-max))
+         (table--fill-region (point-min) (point-max))
+         (setq table-inhibit-auto-fill-paragraph t))
+        (table--finish-delayed-tasks)))
     (push (cons command func-symbol)
           table-command-remap-alist)))
 
@@ -1384,18 +1381,17 @@ the last cache point coordinate."
            fill-paragraph))
   (let ((func-symbol (intern (format "*table--cell-%s" command)))
         (doc-string (format "Table remapped function for `%s'." command)))
-    (fset func-symbol
-          `(lambda
-             (&rest args)
-             ,doc-string
-             (interactive)
-             (table--finish-delayed-tasks)
-             (table-recognize-cell 'force)
-             (table-with-cache-buffer
-               (let ((fill-column table-cell-info-width))
-                 (call-interactively ',command))
-               (setq table-inhibit-auto-fill-paragraph t))
-             (table--finish-delayed-tasks)))
+    (defalias func-symbol
+      (lambda (&rest _args)
+        (:documentation doc-string)
+        (interactive)
+        (table--finish-delayed-tasks)
+        (table-recognize-cell 'force)
+        (table-with-cache-buffer
+         (let ((fill-column table-cell-info-width))
+           (call-interactively command))
+         (setq table-inhibit-auto-fill-paragraph t))
+        (table--finish-delayed-tasks)))
     (push (cons command func-symbol)
           table-command-remap-alist)))
 
@@ -1492,7 +1488,7 @@ Move the point under the table as shown below.
     +--------------+------+--------------------------------+
     -!-
 
-Type M-x table-insert-row instead of \\[table-insert-row-column].  
\\[table-insert-row-column] does not work
+Type \\[table-insert-row] instead of \\[table-insert-row-column].  
\\[table-insert-row-column] does not work
 when the point is outside of the table.  This insertion at
 outside of the table effectively appends a row at the end.
 
@@ -2915,11 +2911,11 @@ HTML:
         URL `https://www.w3.org'
 
 LaTeX:
-        URL `http://www.maths.tcd.ie/~dwilkins/LaTeXPrimer/Tables.html'
+        URL `https://www.maths.tcd.ie/~dwilkins/LaTeXPrimer/Tables.html'
 
 CALS (DocBook DTD):
-        URL `http://www.oasis-open.org/html/a502.htm'
-        URL 
`http://www.oreilly.com/catalog/docbook/chapter/book/table.html#AEN114751'
+        URL `https://www.oasis-open.org/html/a502.htm'
+        URL 
`https://www.oreilly.com/catalog/docbook/chapter/book/table.html#AEN114751'
 "
   (interactive
    (let* ((_ (unless (table--probe-cell) (error "Table not found here")))
@@ -2975,8 +2971,8 @@ CALS (DocBook DTD):
                (setq col-list (cons (car lu-coordinate) col-list)))
              (unless (memq (cdr lu-coordinate) row-list)
                (setq row-list (cons (cdr lu-coordinate) row-list))))))
-       (setq col-list (sort col-list '<))
-       (setq row-list (sort row-list '<))
+       (setq col-list (sort col-list #'<))
+       (setq row-list (sort row-list #'<))
        (message "Generating source...")
        ;; clear the source generation property list
        (setplist 'table-source-info-plist nil)
@@ -3023,7 +3019,7 @@ CALS (DocBook DTD):
                "")))
      ((eq language 'latex)
       (insert (format "%% This LaTeX table template is generated by emacs 
%s\n" emacs-version)
-             "\\begin{tabular}{|" (apply 'concat (make-list (length col-list) 
"l|")) "}\n"
+             "\\begin{tabular}{|" (apply #'concat (make-list (length col-list) 
"l|")) "}\n"
              "\\hline\n"))
      ((eq language 'cals)
       (insert (format "<!-- This CALS table template is generated by emacs %s 
-->\n" emacs-version)
@@ -3054,7 +3050,7 @@ CALS (DocBook DTD):
       (set-marker-insertion-type (table-get-source-info 'colspec-marker) t) ;; 
insert before
       (save-excursion
        (goto-char (table-get-source-info 'colspec-marker))
-       (dolist (col (sort (table-get-source-info 'colnum-list) '<))
+       (dolist (col (sort (table-get-source-info 'colnum-list) #'<))
           (insert (format "    <colspec colnum=\"%d\" colname=\"c%d\"/>\n" col 
col))))
       (insert (format "    </%s>\n  </tgroup>\n</table>\n" 
(table-get-source-info 'row-type))))
      ((eq language 'mediawiki)
@@ -3852,7 +3848,7 @@ converts a table into plain text without frames.  It is a 
companion to
 
 ;; Create the keymap after running the user init file so that the user
 ;; modification to the global-map is accounted.
-(add-hook 'after-init-hook 'table--make-cell-map t)
+(add-hook 'after-init-hook #'table--make-cell-map t)
 
 (defun *table--cell-self-insert-command ()
   "Table cell version of `self-insert-command'."
diff --git a/lisp/textmodes/tex-mode.el b/lisp/textmodes/tex-mode.el
index d5a79ad..fb57b9b 100644
--- a/lisp/textmodes/tex-mode.el
+++ b/lisp/textmodes/tex-mode.el
@@ -857,11 +857,11 @@ START is the position of the \\ and DELIM is the 
delimiter char."
 
 (defun tex-define-common-keys (keymap)
   "Define the keys that we want defined both in TeX mode and in the TeX shell."
-  (define-key keymap "\C-c\C-k" 'tex-kill-job)
-  (define-key keymap "\C-c\C-l" 'tex-recenter-output-buffer)
-  (define-key keymap "\C-c\C-q" 'tex-show-print-queue)
-  (define-key keymap "\C-c\C-p" 'tex-print)
-  (define-key keymap "\C-c\C-v" 'tex-view)
+  (define-key keymap "\C-c\C-k" #'tex-kill-job)
+  (define-key keymap "\C-c\C-l" #'tex-recenter-output-buffer)
+  (define-key keymap "\C-c\C-q" #'tex-show-print-queue)
+  (define-key keymap "\C-c\C-p" #'tex-print)
+  (define-key keymap "\C-c\C-v" #'tex-view)
 
   (define-key keymap [menu-bar tex] (cons "TeX" (make-sparse-keymap "TeX")))
 
@@ -884,27 +884,27 @@ START is the position of the \\ and DELIM is the 
delimiter char."
   (let ((map (make-sparse-keymap)))
     (set-keymap-parent map text-mode-map)
     (tex-define-common-keys map)
-    (define-key map "\"" 'tex-insert-quote)
-    (define-key map "\n" 'tex-handle-newline)
-    (define-key map "\M-\r" 'latex-insert-item)
-    (define-key map "\C-c}" 'up-list)
-    (define-key map "\C-c{" 'tex-insert-braces)
-    (define-key map "\C-c\C-r" 'tex-region)
-    (define-key map "\C-c\C-b" 'tex-buffer)
-    (define-key map "\C-c\C-f" 'tex-file)
-    (define-key map "\C-c\C-c" 'tex-compile)
-    (define-key map "\C-c\C-i" 'tex-bibtex-file)
-    (define-key map "\C-c\C-o" 'latex-insert-block)
+    (define-key map "\"" #'tex-insert-quote)
+    (define-key map "\n" #'tex-handle-newline)
+    (define-key map "\M-\r" #'latex-insert-item)
+    (define-key map "\C-c}" #'up-list)
+    (define-key map "\C-c{" #'tex-insert-braces)
+    (define-key map "\C-c\C-r" #'tex-region)
+    (define-key map "\C-c\C-b" #'tex-buffer)
+    (define-key map "\C-c\C-f" #'tex-file)
+    (define-key map "\C-c\C-c" #'tex-compile)
+    (define-key map "\C-c\C-i" #'tex-bibtex-file)
+    (define-key map "\C-c\C-o" #'latex-insert-block)
 
     ;; Redundant keybindings, for consistency with SGML mode.
-    (define-key map "\C-c\C-t" 'latex-insert-block)
-    (define-key map "\C-c]" 'latex-close-block)
-    (define-key map "\C-c/" 'latex-close-block)
-
-    (define-key map "\C-c\C-e" 'latex-close-block)
-    (define-key map "\C-c\C-u" 'tex-goto-last-unclosed-latex-block)
-    (define-key map "\C-c\C-m" 'tex-feed-input)
-    (define-key map [(control return)] 'tex-feed-input)
+    (define-key map "\C-c\C-t" #'latex-insert-block)
+    (define-key map "\C-c]" #'latex-close-block)
+    (define-key map "\C-c/" #'latex-close-block)
+
+    (define-key map "\C-c\C-e" #'latex-close-block)
+    (define-key map "\C-c\C-u" #'tex-goto-last-unclosed-latex-block)
+    (define-key map "\C-c\C-m" #'tex-feed-input)
+    (define-key map [(control return)] #'tex-feed-input)
     (define-key map [menu-bar tex tex-bibtex-file]
       '("BibTeX File" . tex-bibtex-file))
     (define-key map [menu-bar tex tex-validate-region]
@@ -922,7 +922,7 @@ START is the position of the \\ and DELIM is the delimiter 
char."
 (defvar latex-mode-map
   (let ((map (make-sparse-keymap)))
     (set-keymap-parent map tex-mode-map)
-    (define-key map "\C-c\C-s" 'latex-split-block)
+    (define-key map "\C-c\C-s" #'latex-split-block)
     map)
   "Keymap for `latex-mode'.  See also `tex-mode-map'.")
 
@@ -1033,11 +1033,11 @@ says which mode to use."
 ;; received them from someone using AUCTeX).
 
 ;;;###autoload
-(defalias 'TeX-mode 'tex-mode)
+(defalias 'TeX-mode #'tex-mode)
 ;;;###autoload
-(defalias 'plain-TeX-mode 'plain-tex-mode)
+(defalias 'plain-TeX-mode #'plain-tex-mode)
 ;;;###autoload
-(defalias 'LaTeX-mode 'latex-mode)
+(defalias 'LaTeX-mode #'latex-mode)
 
 ;;;###autoload
 (define-derived-mode plain-tex-mode tex-mode "TeX"
@@ -1560,7 +1560,7 @@ the name of the environment and SKEL-ELEM is an element 
to use in
 a skeleton (see `skeleton-insert').")
 
 ;; Like tex-insert-braces, but for LaTeX.
-(defalias 'tex-latex-block 'latex-insert-block)
+(defalias 'tex-latex-block #'latex-insert-block)
 (define-skeleton latex-insert-block
   "Create a matching pair of lines \\begin{NAME} and \\end{NAME} at point.
 Puts point on a blank line between them."
@@ -1866,7 +1866,7 @@ Mark is left at original location."
        (with-syntax-table tex-mode-syntax-table
          (forward-sexp))))))
 
-(defalias 'tex-close-latex-block 'latex-close-block)
+(defalias 'tex-close-latex-block #'latex-close-block)
 (define-skeleton latex-close-block
   "Create an \\end{...} to match the last unclosed \\begin{...}."
   (save-excursion
@@ -2008,7 +2008,7 @@ Mark is left at original location."
        ;; Specify an interactive shell, to make sure it prompts.
        "-i")
     (let ((proc (get-process "tex-shell")))
-      (set-process-sentinel proc 'tex-shell-sentinel)
+      (set-process-sentinel proc #'tex-shell-sentinel)
       (set-process-query-on-exit-flag proc nil)
       (tex-shell)
       (while (zerop (buffer-size))
@@ -2063,7 +2063,7 @@ evaluates to a command string.
 
 Return the process in which TeX is running."
   (save-excursion
-    (let* ((cmd (eval command))
+    (let* ((cmd (eval command t))
           (proc (tex-shell-proc))
           (buf (process-buffer proc))
            (star (string-match "\\*" cmd))
@@ -2313,7 +2313,7 @@ FILE is typically the output DVI or PDF file."
             executable))))))
 
 (defun tex-command-executable (cmd)
-  (let ((s (if (stringp cmd) cmd (eval (car cmd)))))
+  (let ((s (if (stringp cmd) cmd (eval (car cmd) t))))
     (substring s 0 (string-match "[ \t]\\|\\'" s))))
 
 (defun tex-command-active-p (cmd fspec)
@@ -2400,7 +2400,7 @@ Only applies the FSPEC to the args part of FORMAT."
                (setq latest (nth 1 cmd) cmds (list cmd)))))))
     ;; Expand the command spec into the actual text.
     (dolist (cmd (prog1 cmds (setq cmds nil)))
-      (push (cons (eval (car cmd)) (cdr cmd)) cmds))
+      (push (cons (eval (car cmd) t) (cdr cmd)) cmds))
     ;; Select the favorite command from the history.
     (let ((hist tex-compile-history)
          re hist-cmd)
@@ -2446,7 +2446,7 @@ Only applies the FSPEC to the args part of FORMAT."
           (completing-read
            (format "Command [%s]: " (tex-summarize-command default))
            (mapcar (lambda (x)
-                     (list (tex-format-cmd (eval (car x)) fspec)))
+                     (list (tex-format-cmd (eval (car x) t) fspec)))
                    tex-compile-commands)
            nil nil nil 'tex-compile-history default))))
   (save-some-buffers (not compilation-ask-about-save) nil)
@@ -2740,7 +2740,7 @@ because there is no standard value that would generally 
work."
   ;; Restart the TeX shell if necessary.
   (or (tex-shell-running)
       (tex-start-shell))
-  (let ((tex-dvi-print-command (eval tex-dvi-view-command)))
+  (let ((tex-dvi-print-command (eval tex-dvi-view-command t)))
     (tex-print)))
 
 (defun tex-append (file-name suffix)
diff --git a/lisp/textmodes/texinfmt.el b/lisp/textmodes/texinfmt.el
index fe052e3..a797df9 100644
--- a/lisp/textmodes/texinfmt.el
+++ b/lisp/textmodes/texinfmt.el
@@ -1,4 +1,4 @@
-;;; texinfmt.el --- format Texinfo files into Info files
+;;; texinfmt.el --- format Texinfo files into Info files  -*- lexical-binding: 
t; -*-
 
 ;; Copyright (C) 1985-1986, 1988, 1990-1998, 2000-2021 Free Software
 ;; Foundation, Inc.
@@ -186,6 +186,7 @@ containing the Texinfo file.")
 ;; These come from tex-mode.el.
 (defvar tex-start-of-header)
 (defvar tex-end-of-header)
+(defvar texinfo-example-start)
 
 ;;;###autoload
 (defun texinfo-format-region (region-beginning region-end)
@@ -211,7 +212,7 @@ converted to Info is stored in a temporary buffer."
         texinfo-last-node
         texinfo-node-names
         (texinfo-footnote-number 0)
-        last-input-buffer
+        ;; last-input-buffer
         (fill-column-for-info fill-column)
         (input-buffer (current-buffer))
         (input-directory default-directory)
@@ -405,7 +406,7 @@ if large.  You can use `Info-split' to do this manually."
         texinfo-stack
         texinfo-node-names
         (texinfo-footnote-number 0)
-        last-input-buffer
+        ;; last-input-buffer
         outfile
         (fill-column-for-info fill-column)
         (input-buffer (current-buffer))
@@ -924,7 +925,7 @@ commands."
          (error "Unterminated @%s" (car (car texinfo-stack)))))
 
   ;; Remove excess whitespace
-  (let ((whitespace-silent t))
+  (dlet ((whitespace-silent t))
     (whitespace-cleanup)))
 
 (defvar texinfo-copying-text ""
@@ -1032,18 +1033,18 @@ Leave point after argument."
 (defun texinfo-optional-braces-discard ()
   "Discard braces following command, if any."
   (goto-char texinfo-command-end)
-  (let ((start (point)))
-    (cond ((looking-at "[ \t]*\n"))     ; do nothing
-          ((looking-at "{")             ; remove braces, if any
-           (forward-list 1)
-           (setq texinfo-command-end (point)))
-          (t
-           (error
-            "Invalid `texinfo-optional-braces-discard' format (need 
braces?)")))
-    (delete-region texinfo-command-start texinfo-command-end)))
+  ;; (let ((start (point)))
+  (cond ((looking-at "[ \t]*\n"))       ; do nothing
+        ((looking-at "{")               ; remove braces, if any
+         (forward-list 1)
+         (setq texinfo-command-end (point)))
+        (t
+         (error
+          "Invalid `texinfo-optional-braces-discard' format (need braces?)")))
+  (delete-region texinfo-command-start texinfo-command-end)) ;;)
 
 (defun texinfo-format-parse-line-args ()
-  (let ((start (1- (point)))
+  (let (;; (start (1- (point)))
         next beg end
         args)
     (skip-chars-forward " ")
@@ -1064,7 +1065,7 @@ Leave point after argument."
     (nreverse args)))
 
 (defun texinfo-format-parse-args ()
-  (let ((start (1- (point)))
+  (let (;; (start (1- (point)))
         next beg end
         args)
     (search-forward "{")
@@ -2007,26 +2008,26 @@ commands that are defined in texinfo.tex for printed 
output.
      ;;
      ;; Case 2: {Column 1 template} {Column 2} {Column 3 example}
      ((looking-at "{")
-      (let ((start-of-templates (point)))
-        (while (not (eolp))
-          (skip-chars-forward " \t")
-          (let* ((start-of-template (1+ (point)))
-                 (end-of-template
-                 ;; forward-sexp works with braces in Texinfo mode
-                  (progn (forward-sexp 1) (1- (point)))))
-            (push (- end-of-template start-of-template)
-                  texinfo-multitable-width-list)
-            ;; Remove carriage return from within a template, if any.
-            ;; This helps those who want to use more than
-            ;; one line's worth of words in @multitable line.
-            (narrow-to-region start-of-template end-of-template)
-            (goto-char (point-min))
-            (while (search-forward "
+      ;; (let ((start-of-templates (point)))
+      (while (not (eolp))
+        (skip-chars-forward " \t")
+        (let* ((start-of-template (1+ (point)))
+               (end-of-template
+                ;; forward-sexp works with braces in Texinfo mode
+                (progn (forward-sexp 1) (1- (point)))))
+          (push (- end-of-template start-of-template)
+                texinfo-multitable-width-list)
+          ;; Remove carriage return from within a template, if any.
+          ;; This helps those who want to use more than
+          ;; one line's worth of words in @multitable line.
+          (narrow-to-region start-of-template end-of-template)
+          (goto-char (point-min))
+          (while (search-forward "
 " nil t)
-              (delete-char -1))
-            (goto-char (point-max))
-            (widen)
-            (forward-char 1)))))
+            (delete-char -1))
+          (goto-char (point-max))
+          (widen)
+          (forward-char 1)))) ;; )
      ;;
      ;; Case 3: Trouble
      (t
@@ -2040,7 +2041,7 @@ commands that are defined in texinfo.tex for printed 
output.
             ;; additional between column spaces, if any
             texinfo-extra-inter-column-width
             ;; sum of spaces for each entry
-            (apply '+ texinfo-multitable-width-list))))
+            (apply #'+ texinfo-multitable-width-list))))
       (if (> desired-columns fill-column)
           (error
            "Multi-column table width, %d chars, is greater than page width, %d 
chars."
@@ -2171,9 +2172,9 @@ This command is executed when texinfmt sees @item inside 
@multitable."
       (while (< column-number total-number-of-columns)
         (setq here (point))
         (insert-rectangle
-         (eval (intern
-                (concat texinfo-multitable-rectangle-name
-                        (int-to-string column-number)))))
+         (symbol-value (intern
+                        (concat texinfo-multitable-rectangle-name
+                                (int-to-string column-number)))))
         (goto-char here)
         (end-of-line)
         (setq column-number (1+ column-number))))
@@ -2396,8 +2397,8 @@ Use only the FILENAME arg; for Info, ignore the other 
arguments to @image."
 
 (put 'alias 'texinfo-format 'texinfo-alias)
 (defun texinfo-alias ()
-  (let ((start (1- (point)))
-        args)
+  (let (;; (start (1- (point))
+        ) ;; args
     (skip-chars-forward " ")
     (setq texinfo-command-end (line-end-position))
     (if (not (looking-at "\\([^=]+\\)=\\(.*\\)"))
@@ -3410,7 +3411,7 @@ Default is to leave paragraph indentation as is."
     (while args
       (insert " "
               (if (or (= ?& (aref (car args) 0))
-                      (eq (eval (car texinfo-defun-type)) 'deftp-type))
+                      (eq (car texinfo-defun-type) 'deftp-type))
                   (car args)
                 (upcase (car args))))
       (setq args (cdr args)))))
@@ -3775,80 +3776,80 @@ Default is to leave paragraph indentation as is."
 (put 'deffn 'texinfo-format 'texinfo-format-defun)
 (put 'deffnx 'texinfo-format 'texinfo-format-defunx)
 (put 'deffn 'texinfo-end 'texinfo-end-defun)
-(put 'deffn 'texinfo-defun-type '('deffn-type nil))
-(put 'deffnx 'texinfo-defun-type '('deffn-type nil))
+(put 'deffn 'texinfo-defun-type '(deffn-type nil))
+(put 'deffnx 'texinfo-defun-type '(deffn-type nil))
 (put 'deffn 'texinfo-defun-index 'texinfo-findex)
 (put 'deffnx 'texinfo-defun-index 'texinfo-findex)
 
 (put 'defun 'texinfo-format 'texinfo-format-defun)
 (put 'defunx 'texinfo-format 'texinfo-format-defunx)
 (put 'defun 'texinfo-end 'texinfo-end-defun)
-(put 'defun 'texinfo-defun-type '('defun-type "Function"))
-(put 'defunx 'texinfo-defun-type '('defun-type "Function"))
+(put 'defun 'texinfo-defun-type '(defun-type "Function"))
+(put 'defunx 'texinfo-defun-type '(defun-type "Function"))
 (put 'defun 'texinfo-defun-index 'texinfo-findex)
 (put 'defunx 'texinfo-defun-index 'texinfo-findex)
 
 (put 'defmac 'texinfo-format 'texinfo-format-defun)
 (put 'defmacx 'texinfo-format 'texinfo-format-defunx)
 (put 'defmac 'texinfo-end 'texinfo-end-defun)
-(put 'defmac 'texinfo-defun-type '('defun-type "Macro"))
-(put 'defmacx 'texinfo-defun-type '('defun-type "Macro"))
+(put 'defmac 'texinfo-defun-type '(defun-type "Macro"))
+(put 'defmacx 'texinfo-defun-type '(defun-type "Macro"))
 (put 'defmac 'texinfo-defun-index 'texinfo-findex)
 (put 'defmacx 'texinfo-defun-index 'texinfo-findex)
 
 (put 'defspec 'texinfo-format 'texinfo-format-defun)
 (put 'defspecx 'texinfo-format 'texinfo-format-defunx)
 (put 'defspec 'texinfo-end 'texinfo-end-defun)
-(put 'defspec 'texinfo-defun-type '('defun-type "Special form"))
-(put 'defspecx 'texinfo-defun-type '('defun-type "Special form"))
+(put 'defspec 'texinfo-defun-type '(defun-type "Special form"))
+(put 'defspecx 'texinfo-defun-type '(defun-type "Special form"))
 (put 'defspec 'texinfo-defun-index 'texinfo-findex)
 (put 'defspecx 'texinfo-defun-index 'texinfo-findex)
 
 (put 'defvr 'texinfo-format 'texinfo-format-defun)
 (put 'defvrx 'texinfo-format 'texinfo-format-defunx)
 (put 'defvr 'texinfo-end 'texinfo-end-defun)
-(put 'defvr 'texinfo-defun-type '('deffn-type nil))
-(put 'defvrx 'texinfo-defun-type '('deffn-type nil))
+(put 'defvr 'texinfo-defun-type '(deffn-type nil))
+(put 'defvrx 'texinfo-defun-type '(deffn-type nil))
 (put 'defvr 'texinfo-defun-index 'texinfo-vindex)
 (put 'defvrx 'texinfo-defun-index 'texinfo-vindex)
 
 (put 'defvar 'texinfo-format 'texinfo-format-defun)
 (put 'defvarx 'texinfo-format 'texinfo-format-defunx)
 (put 'defvar 'texinfo-end 'texinfo-end-defun)
-(put 'defvar 'texinfo-defun-type '('defun-type "Variable"))
-(put 'defvarx 'texinfo-defun-type '('defun-type "Variable"))
+(put 'defvar 'texinfo-defun-type '(defun-type "Variable"))
+(put 'defvarx 'texinfo-defun-type '(defun-type "Variable"))
 (put 'defvar 'texinfo-defun-index 'texinfo-vindex)
 (put 'defvarx 'texinfo-defun-index 'texinfo-vindex)
 
 (put 'defconst 'texinfo-format 'texinfo-format-defun)
 (put 'defconstx 'texinfo-format 'texinfo-format-defunx)
 (put 'defconst 'texinfo-end 'texinfo-end-defun)
-(put 'defconst 'texinfo-defun-type '('defun-type "Constant"))
-(put 'defconstx 'texinfo-defun-type '('defun-type "Constant"))
+(put 'defconst 'texinfo-defun-type '(defun-type "Constant"))
+(put 'defconstx 'texinfo-defun-type '(defun-type "Constant"))
 (put 'defconst 'texinfo-defun-index 'texinfo-vindex)
 (put 'defconstx 'texinfo-defun-index 'texinfo-vindex)
 
 (put 'defcmd 'texinfo-format 'texinfo-format-defun)
 (put 'defcmdx 'texinfo-format 'texinfo-format-defunx)
 (put 'defcmd 'texinfo-end 'texinfo-end-defun)
-(put 'defcmd 'texinfo-defun-type '('defun-type "Command"))
-(put 'defcmdx 'texinfo-defun-type '('defun-type "Command"))
+(put 'defcmd 'texinfo-defun-type '(defun-type "Command"))
+(put 'defcmdx 'texinfo-defun-type '(defun-type "Command"))
 (put 'defcmd 'texinfo-defun-index 'texinfo-findex)
 (put 'defcmdx 'texinfo-defun-index 'texinfo-findex)
 
 (put 'defopt 'texinfo-format 'texinfo-format-defun)
 (put 'defoptx 'texinfo-format 'texinfo-format-defunx)
 (put 'defopt 'texinfo-end 'texinfo-end-defun)
-(put 'defopt 'texinfo-defun-type '('defun-type "User Option"))
-(put 'defoptx 'texinfo-defun-type '('defun-type "User Option"))
+(put 'defopt 'texinfo-defun-type '(defun-type "User Option"))
+(put 'defoptx 'texinfo-defun-type '(defun-type "User Option"))
 (put 'defopt 'texinfo-defun-index 'texinfo-vindex)
 (put 'defoptx 'texinfo-defun-index 'texinfo-vindex)
 
 (put 'deftp 'texinfo-format 'texinfo-format-defun)
 (put 'deftpx 'texinfo-format 'texinfo-format-defunx)
 (put 'deftp 'texinfo-end 'texinfo-end-defun)
-(put 'deftp 'texinfo-defun-type '('deftp-type nil))
-(put 'deftpx 'texinfo-defun-type '('deftp-type nil))
+(put 'deftp 'texinfo-defun-type '(deftp-type nil))
+(put 'deftpx 'texinfo-defun-type '(deftp-type nil))
 (put 'deftp 'texinfo-defun-index 'texinfo-tindex)
 (put 'deftpx 'texinfo-defun-index 'texinfo-tindex)
 
@@ -3857,32 +3858,32 @@ Default is to leave paragraph indentation as is."
 (put 'defop 'texinfo-format 'texinfo-format-defun)
 (put 'defopx 'texinfo-format 'texinfo-format-defunx)
 (put 'defop 'texinfo-end 'texinfo-end-defun)
-(put 'defop 'texinfo-defun-type '('defop-type nil))
-(put 'defopx 'texinfo-defun-type '('defop-type nil))
+(put 'defop 'texinfo-defun-type '(defop-type nil))
+(put 'defopx 'texinfo-defun-type '(defop-type nil))
 (put 'defop 'texinfo-defun-index 'texinfo-findex)
 (put 'defopx 'texinfo-defun-index 'texinfo-findex)
 
 (put 'defmethod 'texinfo-format 'texinfo-format-defun)
 (put 'defmethodx 'texinfo-format 'texinfo-format-defunx)
 (put 'defmethod 'texinfo-end 'texinfo-end-defun)
-(put 'defmethod 'texinfo-defun-type '('defmethod-type "Method"))
-(put 'defmethodx 'texinfo-defun-type '('defmethod-type "Method"))
+(put 'defmethod 'texinfo-defun-type '(defmethod-type "Method"))
+(put 'defmethodx 'texinfo-defun-type '(defmethod-type "Method"))
 (put 'defmethod 'texinfo-defun-index 'texinfo-findex)
 (put 'defmethodx 'texinfo-defun-index 'texinfo-findex)
 
 (put 'defcv 'texinfo-format 'texinfo-format-defun)
 (put 'defcvx 'texinfo-format 'texinfo-format-defunx)
 (put 'defcv 'texinfo-end 'texinfo-end-defun)
-(put 'defcv 'texinfo-defun-type '('defop-type nil))
-(put 'defcvx 'texinfo-defun-type '('defop-type nil))
+(put 'defcv 'texinfo-defun-type '(defop-type nil))
+(put 'defcvx 'texinfo-defun-type '(defop-type nil))
 (put 'defcv 'texinfo-defun-index 'texinfo-vindex)
 (put 'defcvx 'texinfo-defun-index 'texinfo-vindex)
 
 (put 'defivar 'texinfo-format 'texinfo-format-defun)
 (put 'defivarx 'texinfo-format 'texinfo-format-defunx)
 (put 'defivar 'texinfo-end 'texinfo-end-defun)
-(put 'defivar 'texinfo-defun-type '('defmethod-type "Instance variable"))
-(put 'defivarx 'texinfo-defun-type '('defmethod-type "Instance variable"))
+(put 'defivar 'texinfo-defun-type '(defmethod-type "Instance variable"))
+(put 'defivarx 'texinfo-defun-type '(defmethod-type "Instance variable"))
 (put 'defivar 'texinfo-defun-index 'texinfo-vindex)
 (put 'defivarx 'texinfo-defun-index 'texinfo-vindex)
 
@@ -3891,32 +3892,32 @@ Default is to leave paragraph indentation as is."
 (put 'deftypefn 'texinfo-format 'texinfo-format-defun)
 (put 'deftypefnx 'texinfo-format 'texinfo-format-defunx)
 (put 'deftypefn 'texinfo-end 'texinfo-end-defun)
-(put 'deftypefn 'texinfo-defun-type '('deftypefn-type nil))
-(put 'deftypefnx 'texinfo-defun-type '('deftypefn-type nil))
+(put 'deftypefn 'texinfo-defun-type '(deftypefn-type nil))
+(put 'deftypefnx 'texinfo-defun-type '(deftypefn-type nil))
 (put 'deftypefn 'texinfo-defun-index 'texinfo-findex)
 (put 'deftypefnx 'texinfo-defun-index 'texinfo-findex)
 
 (put 'deftypefun 'texinfo-format 'texinfo-format-defun)
 (put 'deftypefunx 'texinfo-format 'texinfo-format-defunx)
 (put 'deftypefun 'texinfo-end 'texinfo-end-defun)
-(put 'deftypefun 'texinfo-defun-type '('deftypefun-type "Function"))
-(put 'deftypefunx 'texinfo-defun-type '('deftypefun-type "Function"))
+(put 'deftypefun 'texinfo-defun-type '(deftypefun-type "Function"))
+(put 'deftypefunx 'texinfo-defun-type '(deftypefun-type "Function"))
 (put 'deftypefun 'texinfo-defun-index 'texinfo-findex)
 (put 'deftypefunx 'texinfo-defun-index 'texinfo-findex)
 
 (put 'deftypevr 'texinfo-format 'texinfo-format-defun)
 (put 'deftypevrx 'texinfo-format 'texinfo-format-defunx)
 (put 'deftypevr 'texinfo-end 'texinfo-end-defun)
-(put 'deftypevr 'texinfo-defun-type '('deftypefn-type nil))
-(put 'deftypevrx 'texinfo-defun-type '('deftypefn-type nil))
+(put 'deftypevr 'texinfo-defun-type '(deftypefn-type nil))
+(put 'deftypevrx 'texinfo-defun-type '(deftypefn-type nil))
 (put 'deftypevr 'texinfo-defun-index 'texinfo-vindex)
 (put 'deftypevrx 'texinfo-defun-index 'texinfo-vindex)
 
 (put 'deftypevar 'texinfo-format 'texinfo-format-defun)
 (put 'deftypevarx 'texinfo-format 'texinfo-format-defunx)
 (put 'deftypevar 'texinfo-end 'texinfo-end-defun)
-(put 'deftypevar 'texinfo-defun-type '('deftypevar-type "Variable"))
-(put 'deftypevarx 'texinfo-defun-type '('deftypevar-type "Variable"))
+(put 'deftypevar 'texinfo-defun-type '(deftypevar-type "Variable"))
+(put 'deftypevarx 'texinfo-defun-type '(deftypevar-type "Variable"))
 (put 'deftypevar 'texinfo-defun-index 'texinfo-vindex)
 (put 'deftypevarx 'texinfo-defun-index 'texinfo-vindex)
 
@@ -3943,7 +3944,8 @@ Default is to leave paragraph indentation as is."
   "Clear the value of the flag."
   (let* ((arg (texinfo-parse-arg-discard))
          (flag (car (read-from-string arg)))
-         (value (substring arg (cdr (read-from-string arg)))))
+         ;; (value (substring arg (cdr (read-from-string arg))))
+         )
     (put flag 'texinfo-whether-setp 'flag-cleared)
     (put flag 'texinfo-set-value "")))
 
@@ -4043,7 +4045,7 @@ the @ifeq command."
   (goto-char texinfo-command-end)
   (let* ((case-fold-search t)
          (stop (save-excursion (forward-sexp 1) (point)))
-        start end
+        start ;; end
         ;; @ifeq{arg1, arg2, @command{optional-args}}
         (arg1
          (progn
diff --git a/lisp/textmodes/texinfo.el b/lisp/textmodes/texinfo.el
index 7799cdb..750a33d 100644
--- a/lisp/textmodes/texinfo.el
+++ b/lisp/textmodes/texinfo.el
@@ -1,4 +1,4 @@
-;;; texinfo.el --- major mode for editing Texinfo files
+;;; texinfo.el --- major mode for editing Texinfo files  -*- lexical-binding: 
t; -*-
 
 ;; Copyright (C) 1985, 1988-1993, 1996-1997, 2000-2021 Free Software
 ;; Foundation, Inc.
@@ -54,20 +54,17 @@
 ;;;###autoload
 (defcustom texinfo-open-quote (purecopy "``")
   "String inserted by typing \\[texinfo-insert-quote] to open a quotation."
-  :type 'string
-  :group 'texinfo)
+  :type 'string)
 
 ;;;###autoload
 (defcustom texinfo-close-quote (purecopy "''")
   "String inserted by typing \\[texinfo-insert-quote] to close a quotation."
-  :type 'string
-  :group 'texinfo)
+  :type 'string)
 
 (defcustom texinfo-mode-hook nil
   "Normal hook run when entering Texinfo mode."
   :type 'hook
-  :options '(turn-on-auto-fill flyspell-mode)
-  :group 'texinfo)
+  :options '(turn-on-auto-fill flyspell-mode))
 
 
 ;;; Autoloads:
@@ -349,8 +346,7 @@ Subexpression 1 is what goes into the corresponding `@end' 
statement.")
 
 (defface texinfo-heading
   '((t (:inherit font-lock-function-name-face)))
-  "Face used for section headings in `texinfo-mode'."
-  :group 'texinfo)
+  "Face used for section headings in `texinfo-mode'.")
 
 (defvar texinfo-font-lock-keywords
   `(;; All but the first had an OVERRIDE of t.
@@ -377,7 +373,7 @@ Subexpression 1 is what goes into the corresponding `@end' 
statement.")
     ("@\\(end\\|itemx?\\) +\\(.+\\)" 2 font-lock-keyword-face keep)
     ;; (,texinfo-environment-regexp
     ;;  1 (texinfo-clone-environment (match-beginning 1) (match-end 1)) keep)
-    (,(concat "^@" (regexp-opt (mapcar 'car texinfo-section-list) t)
+    (,(concat "^@" (regexp-opt (mapcar #'car texinfo-section-list) t)
               ".*\n")
      0 'texinfo-heading t))
   "Additional expressions to highlight in Texinfo mode.")
@@ -404,19 +400,21 @@ Subexpression 1 is what goes into the corresponding 
`@end' statement.")
 
 ;;; Keys common both to Texinfo mode and to TeX shell.
 
+(declare-function tex-show-print-queue "tex-mode" ())
+
 (defun texinfo-define-common-keys (keymap)
   "Define the keys both in Texinfo mode and in the texinfo-tex-shell."
-  (define-key keymap "\C-c\C-t\C-k"    'tex-kill-job)
-  (define-key keymap "\C-c\C-t\C-x"    'texinfo-quit-job)
-  (define-key keymap "\C-c\C-t\C-l"    'tex-recenter-output-buffer)
-  (define-key keymap "\C-c\C-t\C-d"    'texinfo-delete-from-print-queue)
-  (define-key keymap "\C-c\C-t\C-q"    'tex-show-print-queue)
-  (define-key keymap "\C-c\C-t\C-p"    'texinfo-tex-print)
-  (define-key keymap "\C-c\C-t\C-v"    'texinfo-tex-view)
-  (define-key keymap "\C-c\C-t\C-i"    'texinfo-texindex)
-
-  (define-key keymap "\C-c\C-t\C-r"    'texinfo-tex-region)
-  (define-key keymap "\C-c\C-t\C-b"    'texinfo-tex-buffer))
+  (define-key keymap "\C-c\C-t\C-k"    #'tex-kill-job)
+  (define-key keymap "\C-c\C-t\C-x"    #'texinfo-quit-job)
+  (define-key keymap "\C-c\C-t\C-l"    #'tex-recenter-output-buffer)
+  (define-key keymap "\C-c\C-t\C-d"    #'texinfo-delete-from-print-queue)
+  (define-key keymap "\C-c\C-t\C-q"    #'tex-show-print-queue)
+  (define-key keymap "\C-c\C-t\C-p"    #'texinfo-tex-print)
+  (define-key keymap "\C-c\C-t\C-v"    #'texinfo-tex-view)
+  (define-key keymap "\C-c\C-t\C-i"    #'texinfo-texindex)
+
+  (define-key keymap "\C-c\C-t\C-r"    #'texinfo-tex-region)
+  (define-key keymap "\C-c\C-t\C-b"    #'texinfo-tex-buffer))
 
 ;; Mode documentation displays commands in reverse order
 ;; from how they are listed in the texinfo-mode-map.
@@ -427,68 +425,68 @@ Subexpression 1 is what goes into the corresponding 
`@end' statement.")
     ;; bindings for `texnfo-tex.el'
     (texinfo-define-common-keys map)
 
-    (define-key map "\"" 'texinfo-insert-quote)
+    (define-key map "\"" #'texinfo-insert-quote)
 
     ;; bindings for `makeinfo.el'
-    (define-key map "\C-c\C-m\C-k" 'kill-compilation)
+    (define-key map "\C-c\C-m\C-k" #'kill-compilation)
     (define-key map "\C-c\C-m\C-l"
-      'makeinfo-recenter-compilation-buffer)
-    (define-key map "\C-c\C-m\C-r" 'makeinfo-region)
-    (define-key map "\C-c\C-m\C-b" 'makeinfo-buffer)
+      #'makeinfo-recenter-compilation-buffer)
+    (define-key map "\C-c\C-m\C-r" #'makeinfo-region)
+    (define-key map "\C-c\C-m\C-b" #'makeinfo-buffer)
 
     ;; bindings for `texinfmt.el'
-    (define-key map "\C-c\C-e\C-r"    'texinfo-format-region)
-    (define-key map "\C-c\C-e\C-b"    'texinfo-format-buffer)
+    (define-key map "\C-c\C-e\C-r"    #'texinfo-format-region)
+    (define-key map "\C-c\C-e\C-b"    #'texinfo-format-buffer)
 
     ;; AUCTeX-like bindings
-    (define-key map "\e\r"             'texinfo-insert-@item)
+    (define-key map "\e\r"             #'texinfo-insert-@item)
 
     ;; bindings for updating nodes and menus
 
-    (define-key map "\C-c\C-um"   'texinfo-master-menu)
+    (define-key map "\C-c\C-um"   #'texinfo-master-menu)
 
-    (define-key map "\C-c\C-u\C-m"   'texinfo-make-menu)
-    (define-key map "\C-c\C-u\C-n"   'texinfo-update-node)
-    (define-key map "\C-c\C-u\C-e"   'texinfo-every-node-update)
-    (define-key map "\C-c\C-u\C-a"   'texinfo-all-menus-update)
+    (define-key map "\C-c\C-u\C-m"   #'texinfo-make-menu)
+    (define-key map "\C-c\C-u\C-n"   #'texinfo-update-node)
+    (define-key map "\C-c\C-u\C-e"   #'texinfo-every-node-update)
+    (define-key map "\C-c\C-u\C-a"   #'texinfo-all-menus-update)
 
-    (define-key map "\C-c\C-s"     'texinfo-show-structure)
+    (define-key map "\C-c\C-s"     #'texinfo-show-structure)
 
-    (define-key map "\C-c}"          'up-list)
+    (define-key map "\C-c}"          #'up-list)
     ;; FIXME: This is often used for "close block" aka texinfo-insert-@end.
-    (define-key map "\C-c]"          'up-list)
-    (define-key map "\C-c/"         'texinfo-insert-@end)
-    (define-key map "\C-c{"            'texinfo-insert-braces)
+    (define-key map "\C-c]"          #'up-list)
+    (define-key map "\C-c/"         #'texinfo-insert-@end)
+    (define-key map "\C-c{"            #'texinfo-insert-braces)
 
     ;; bindings for inserting strings
-    (define-key map "\C-c\C-o"     'texinfo-insert-block)
-    (define-key map "\C-c\C-c\C-d" 'texinfo-start-menu-description)
-    (define-key map "\C-c\C-c\C-s" 'texinfo-insert-@strong)
-    (define-key map "\C-c\C-c\C-e" 'texinfo-insert-@emph)
-
-    (define-key map "\C-c\C-cv"    'texinfo-insert-@var)
-    (define-key map "\C-c\C-cu"    'texinfo-insert-@uref)
-    (define-key map "\C-c\C-ct"    'texinfo-insert-@table)
-    (define-key map "\C-c\C-cs"    'texinfo-insert-@samp)
-    (define-key map "\C-c\C-cr"    'texinfo-insert-dwim-@ref)
-    (define-key map "\C-c\C-cq"    'texinfo-insert-@quotation)
-    (define-key map "\C-c\C-co"    'texinfo-insert-@noindent)
-    (define-key map "\C-c\C-cn"    'texinfo-insert-@node)
-    (define-key map "\C-c\C-cm"    'texinfo-insert-@email)
-    (define-key map "\C-c\C-ck"    'texinfo-insert-@kbd)
-    (define-key map "\C-c\C-ci"    'texinfo-insert-@item)
-    (define-key map "\C-c\C-cf"    'texinfo-insert-@file)
-    (define-key map "\C-c\C-cx"    'texinfo-insert-@example)
-    (define-key map "\C-c\C-ce"    'texinfo-insert-@end)
-    (define-key map "\C-c\C-cd"    'texinfo-insert-@dfn)
-    (define-key map "\C-c\C-cc"    'texinfo-insert-@code)
+    (define-key map "\C-c\C-o"     #'texinfo-insert-block)
+    (define-key map "\C-c\C-c\C-d" #'texinfo-start-menu-description)
+    (define-key map "\C-c\C-c\C-s" #'texinfo-insert-@strong)
+    (define-key map "\C-c\C-c\C-e" #'texinfo-insert-@emph)
+
+    (define-key map "\C-c\C-cv"    #'texinfo-insert-@var)
+    (define-key map "\C-c\C-cu"    #'texinfo-insert-@uref)
+    (define-key map "\C-c\C-ct"    #'texinfo-insert-@table)
+    (define-key map "\C-c\C-cs"    #'texinfo-insert-@samp)
+    (define-key map "\C-c\C-cr"    #'texinfo-insert-dwim-@ref)
+    (define-key map "\C-c\C-cq"    #'texinfo-insert-@quotation)
+    (define-key map "\C-c\C-co"    #'texinfo-insert-@noindent)
+    (define-key map "\C-c\C-cn"    #'texinfo-insert-@node)
+    (define-key map "\C-c\C-cm"    #'texinfo-insert-@email)
+    (define-key map "\C-c\C-ck"    #'texinfo-insert-@kbd)
+    (define-key map "\C-c\C-ci"    #'texinfo-insert-@item)
+    (define-key map "\C-c\C-cf"    #'texinfo-insert-@file)
+    (define-key map "\C-c\C-cx"    #'texinfo-insert-@example)
+    (define-key map "\C-c\C-ce"    #'texinfo-insert-@end)
+    (define-key map "\C-c\C-cd"    #'texinfo-insert-@dfn)
+    (define-key map "\C-c\C-cc"    #'texinfo-insert-@code)
 
     ;; bindings for environment movement
-    (define-key map "\C-c."        'texinfo-to-environment-bounds)
-    (define-key map "\C-c\C-c\C-f" 'texinfo-next-environment-end)
-    (define-key map "\C-c\C-c\C-b" 'texinfo-previous-environment-end)
-    (define-key map "\C-c\C-c\C-n" 'texinfo-next-environment-start)
-    (define-key map "\C-c\C-c\C-p" 'texinfo-previous-environment-start)
+    (define-key map "\C-c."        #'texinfo-to-environment-bounds)
+    (define-key map "\C-c\C-c\C-f" #'texinfo-next-environment-end)
+    (define-key map "\C-c\C-c\C-b" #'texinfo-previous-environment-end)
+    (define-key map "\C-c\C-c\C-n" #'texinfo-next-environment-start)
+    (define-key map "\C-c\C-c\C-p" #'texinfo-previous-environment-start)
     map))
 
 (easy-menu-define texinfo-mode-menu
@@ -628,7 +626,7 @@ value of `texinfo-mode-hook'."
              (mapcar (lambda (x) (cons (concat "@" (car x)) (cadr x)))
                      texinfo-section-list))
   (setq-local outline-regexp
-             (concat (regexp-opt (mapcar 'car outline-heading-alist) t)
+             (concat (regexp-opt (mapcar #'car outline-heading-alist) t)
                      "\\>"))
 
   (setq-local tex-start-of-header "%\\*\\*start")
@@ -897,7 +895,7 @@ A numeric argument says how many words the braces should 
surround.
 The default is not to surround any existing words with the braces."
   nil
   "@uref{" _ "}")
-(defalias 'texinfo-insert-@url 'texinfo-insert-@uref)
+(defalias 'texinfo-insert-@url #'texinfo-insert-@uref)
 
 ;;; Texinfo file structure
 
@@ -962,32 +960,27 @@ to jump to the corresponding spot in the Texinfo source 
file."
 
 (defcustom texinfo-texi2dvi-command "texi2dvi"
   "Command used by `texinfo-tex-buffer' to run TeX and texindex on a buffer."
-  :type 'string
-  :group 'texinfo)
+  :type 'string)
 
 (defcustom texinfo-texi2dvi-options ""
   "Command line options for `texinfo-texi2dvi-command'."
   :type 'string
-  :group 'texinfo
   :version "28.1")
 
 (defcustom texinfo-tex-command "tex"
   "Command used by `texinfo-tex-region' to run TeX on a region."
-  :type 'string
-  :group 'texinfo)
+  :type 'string)
 
 (defcustom texinfo-texindex-command "texindex"
   "Command used by `texinfo-texindex' to sort unsorted index files."
-  :type 'string
-  :group 'texinfo)
+  :type 'string)
 
 (defcustom texinfo-delete-from-print-queue-command "lprm"
   "Command string used to delete a job from the line printer queue.
 Command is used by \\[texinfo-delete-from-print-queue] based on
 number provided by a previous \\[tex-show-print-queue]
 command."
-  :type 'string
-  :group 'texinfo)
+  :type 'string)
 
 (defvar texinfo-tex-trailer "@bye"
   "String appended after a region sent to TeX by `texinfo-tex-region'.")
diff --git a/lisp/textmodes/texnfo-upd.el b/lisp/textmodes/texnfo-upd.el
index ea35641..27807a9 100644
--- a/lisp/textmodes/texnfo-upd.el
+++ b/lisp/textmodes/texnfo-upd.el
@@ -1,4 +1,4 @@
-;;; texnfo-upd.el --- utilities for updating nodes and menus in Texinfo files
+;;; texnfo-upd.el --- utilities for updating nodes and menus in Texinfo files  
-*- lexical-binding: t; -*-
 
 ;; Copyright (C) 1989-1992, 2001-2021 Free Software Foundation, Inc.
 
@@ -420,7 +420,7 @@ of the node if one is found; else do not move point."
                 "\\|"                      ; or
                 "\\(^@ifnottex[ ]*\n\\)"   ; ifnottex line, if any
                 "\\)?"                     ; end of expression
-                (eval (cdr (assoc level texinfo-update-menu-lower-regexps))))
+                (eval (cdr (assoc level texinfo-update-menu-lower-regexps)) t))
                ;; the next higher level node marks the end of this
                ;; section, and no lower level node will be found beyond
                ;; this position even if region-end is farther off
@@ -454,7 +454,7 @@ if the match is found there, the value is t and point does 
not move."
              "\\|"                           ; or
              "\\(^@ifnottex[ ]*\n\\)"        ; ifnottex line, if any
              "\\)?"                          ; end of expression
-             (eval (cdr (assoc level texinfo-update-menu-higher-regexps))))
+             (eval (cdr (assoc level texinfo-update-menu-higher-regexps)) t))
             region-end t)
        (beginning-of-line) t)))))
 
@@ -505,7 +505,7 @@ The function finds entries of the same type.  Thus 
`subsections' and
          "\\(^@ifnottex[ ]*\n\\)"        ; ifnottex line, if any
           "\\)?"                          ; end of expression
          (eval
-          (cdr (assoc level texinfo-update-menu-same-level-regexps))))
+          (cdr (assoc level texinfo-update-menu-same-level-regexps)) t))
         search-end
         t)
        (goto-char (match-beginning 1)))))
@@ -742,7 +742,7 @@ You will need to edit the inserted text since a useful 
description
 complements the node name rather than repeats it as a title does."
 
   (interactive)
-  (let (beginning end node-name title)
+  (let (beginning node-name title) ;; end
     (save-excursion
       (beginning-of-line)
       (if (search-forward "* " (line-end-position) t)
@@ -1033,7 +1033,7 @@ However, there does not need to be a title field."
 
   (save-excursion
     ;; `master-menu-inserted-p' is a kludge to tell
-    ;; whether to insert @end detailmenu (see bleow)
+    ;; whether to insert @end detailmenu (see below)
     (let (master-menu-inserted-p)
       ;; Handle top of menu
       (insert "\n@menu\n")
@@ -1219,7 +1219,7 @@ Only argument is a string of the general type of section."
          "\\(^@ifnottex[ ]*\n\\)"        ; ifnottex line, if any
           "\\)?"                          ; end of expression
          (eval
-          (cdr (assoc level texinfo-update-menu-higher-regexps))))
+          (cdr (assoc level texinfo-update-menu-higher-regexps)) t))
         nil
         'goto-beginning)
        (point))))))
@@ -1243,7 +1243,7 @@ string of the general type of section."
             "\\)?"                        ; end of expression
            (eval
             ;; Never finds end of level above chapter so goes to end.
-            (cdr (assoc level texinfo-update-menu-higher-regexps))))
+            (cdr (assoc level texinfo-update-menu-higher-regexps)) t))
           nil
           'goto-end)
          (match-beginning 1)
@@ -1430,7 +1430,7 @@ will be at some level higher in the Texinfo file.  The 
fourth argument
                   "\\(^@ifnottex[ ]*\n\\)"
                   "\\)?")
                 (eval
-                 (cdr (assoc level texinfo-update-menu-same-level-regexps))))
+                 (cdr (assoc level texinfo-update-menu-same-level-regexps)) t))
                end
                t)
               'normal
@@ -1451,7 +1451,7 @@ will be at some level higher in the Texinfo file.  The 
fourth argument
                   "\\(^@ifnottex[ ]*\n\\)"
                   "\\)?")
                 (eval
-                 (cdr (assoc level texinfo-update-menu-same-level-regexps)))
+                 (cdr (assoc level texinfo-update-menu-same-level-regexps)) t)
                 "\\|"
                 ;; Match node line.
                 "\\(^@node\\).*\n"
@@ -1465,7 +1465,7 @@ will be at some level higher in the Texinfo file.  The 
fourth argument
                   "\\(^@ifnottex[ ]*\n\\)"
                   "\\)?")
                 (eval
-                 (cdr (assoc level texinfo-update-menu-higher-regexps)))
+                 (cdr (assoc level texinfo-update-menu-higher-regexps)) t)
                 "\\|"
                 ;; Handle `Top' node specially.
                 "^@node [ \t]*top[ \t]*\\(,\\|$\\)"
@@ -1489,7 +1489,7 @@ will be at some level higher in the Texinfo file.  The 
fourth argument
                   "\\|"
                   "\\(^@ifnottex[ ]*\n\\)"
                   "\\)?")
-                (eval (cdr (assoc level texinfo-update-menu-higher-regexps)))
+                (eval (cdr (assoc level texinfo-update-menu-higher-regexps)) t)
                 "\\|"
                 ;; Handle `Top' node specially.
                 "^@node [ \t]*top[ \t]*\\(,\\|$\\)"
@@ -1662,7 +1662,7 @@ or `Up' pointer."
             'no-pointer))
          ((eq direction 'up)
           (if (re-search-backward
-               (eval (cdr (assoc level texinfo-update-menu-higher-regexps)))
+               (eval (cdr (assoc level texinfo-update-menu-higher-regexps)) t)
                (point-min)
                t)
               'normal
@@ -1686,7 +1686,7 @@ node names in pre-existing `@node' lines that lack names."
   ;; Use marker; after inserting node lines, leave point at end of
   ;; region and mark at beginning.
 
-  (let (beginning-marker end-marker title last-section-position)
+  (let (end-marker title last-section-position) ;; beginning-marker
 
     ;; Save current position on mark ring and set mark to end.
     (push-mark end t)
@@ -2043,8 +2043,8 @@ chapter."
 
   (let* ((included-file-list (texinfo-multi-file-included-list outer-file))
         (files included-file-list)
-        next-node-name
-        previous-node-name
+        ;; next-node-name
+        ;; previous-node-name
         ;; Update the pointers and collect the names of the nodes and titles
         (main-menu-list (texinfo-multi-file-update files update-everything)))
 
diff --git a/lisp/textmodes/text-mode.el b/lisp/textmodes/text-mode.el
index 1432ab6..ffeb9e6 100644
--- a/lisp/textmodes/text-mode.el
+++ b/lisp/textmodes/text-mode.el
@@ -69,33 +69,32 @@
 
 (defvar text-mode-map
   (let ((map (make-sparse-keymap)))
-    (define-key map "\e\t" 'ispell-complete-word)
-    (define-key map [menu-bar text]
-      (cons "Text" (make-sparse-keymap "Text")))
-    (bindings--define-key map [menu-bar text toggle-text-mode-auto-fill]
-      '(menu-item "Auto Fill" toggle-text-mode-auto-fill
-                  :button (:toggle . (memq 'turn-on-auto-fill text-mode-hook))
-                  :help "Automatically fill text while typing in text modes 
(Auto Fill mode)"))
-    (bindings--define-key map [menu-bar text paragraph-indent-minor-mode]
-      '(menu-item "Paragraph Indent" paragraph-indent-minor-mode
-                  :button (:toggle . (bound-and-true-p 
paragraph-indent-minor-mode))
-                  :help "Toggle paragraph indent minor mode"))
-    (bindings--define-key map [menu-bar text sep] menu-bar-separator)
-    (bindings--define-key map [menu-bar text center-region]
-      '(menu-item "Center Region" center-region
-                  :help "Center the marked region"
-                  :enable (region-active-p)))
-    (bindings--define-key map [menu-bar text center-paragraph]
-      '(menu-item "Center Paragraph" center-paragraph
-                  :help "Center the current paragraph"))
-    (bindings--define-key map [menu-bar text center-line]
-      '(menu-item "Center Line" center-line
-                  :help "Center the current line"))
+    (define-key map "\e\t" #'ispell-complete-word)
     map)
   "Keymap for `text-mode'.
 Many other modes, such as `mail-mode', `outline-mode' and `indented-text-mode',
 inherit all the commands defined in this map.")
 
+(easy-menu-define text-mode-menu text-mode-map
+  "Menu for `text-mode'."
+  '("Text"
+    ["Center Line" center-line
+     :help "Center the current line"]
+    ["Center Paragraph" center-paragraph
+     :help "Center the current paragraph"]
+    ["Center Region" center-region
+     :help "Center the marked region"
+     :enable (region-active-p)]
+    "---"
+    ["Paragraph Indent" paragraph-indent-minor-mode
+     :help "Toggle paragraph indent minor mode"
+     :style toggle
+     :selected (bound-and-true-p paragraph-indent-minor-mode)]
+    ["Auto Fill" toggle-text-mode-auto-fill
+     :help "Automatically fill text while typing in text modes (Auto Fill 
mode)"
+     :style toggle
+     :selected (memq 'turn-on-auto-fill text-mode-hook)]))
+
 
 (define-derived-mode text-mode nil "Text"
   "Major mode for editing text written for humans to read.
@@ -142,7 +141,7 @@ Turning on Paragraph-Indent minor mode runs the normal hook
     (remove-function (local 'indent-line-function)
                      #'indent-to-left-margin)))
 
-(defalias 'indented-text-mode 'text-mode)
+(defalias 'indented-text-mode #'text-mode)
 
 ;; This can be made a no-op once all modes that use text-mode-hook
 ;; are "derived" from text-mode.  (As of 2015/04, and probably well before,
@@ -169,8 +168,6 @@ both existing buffers and buffers that you subsequently 
create."
             (if enable-mode "enabled" "disabled"))))
 
 
-(define-key facemenu-keymap "\eS" 'center-paragraph)
-
 (defun center-paragraph ()
   "Center each nonblank line in the paragraph at or after point.
 See `center-line' for more info."
@@ -198,8 +195,6 @@ See `center-line' for more info."
            (center-line))
        (forward-line 1)))))
 
-(define-key facemenu-keymap "\es" 'center-line)
-
 (defun center-line (&optional nlines)
   "Center the line point is on, within the width specified by `fill-column'.
 This means adjusting the indentation so that it equals
diff --git a/lisp/textmodes/tildify.el b/lisp/textmodes/tildify.el
index 33a976a..069c8e3 100644
--- a/lisp/textmodes/tildify.el
+++ b/lisp/textmodes/tildify.el
@@ -66,7 +66,6 @@ non-capturing groups can be used for grouping prior to the 
part of the regexp
 matching the white space).  The pattern is matched case-sensitive regardless of
 the value of `case-fold-search' setting."
   :version "25.1"
-  :group 'tildify
   :type 'regexp
   :safe t)
 
@@ -90,7 +89,6 @@ by the hard space character.
 
 The form (MAJOR-MODE . SYMBOL) defines alias item for MAJOR-MODE.  For this
 mode, the item for the mode SYMBOL is looked up in the alist instead."
-  :group 'tildify
   :type '(repeat (cons :tag "Entry for major mode"
                        (choice (const  :tag "Default" t)
                                (symbol :tag "Major mode"))
@@ -110,7 +108,6 @@ might be used for other modes if compatible encoding is 
used.
 
 If nil, current major mode has no way to represent a hard space."
   :version "25.1"
-  :group 'tildify
   :type '(choice (const :tag "Space character (no hard-space representation)"
                         " ")
                  (const :tag "No-break space (U+00A0)" "\u00A0")
@@ -133,7 +130,6 @@ STRING defines the hard space, which is inserted at places 
defined by
 
 The form (MAJOR-MODE . SYMBOL) defines alias item for MAJOR-MODE.  For this
 mode, the item for the mode SYMBOL is looked up in the alist instead."
-  :group 'tildify
   :type '(repeat (cons :tag "Entry for major mode"
                        (choice (const  :tag "Default" t)
                                (symbol :tag "Major mode"))
@@ -164,7 +160,6 @@ or better still:
 See `tildify-foreach-ignore-environments' function for other ways to use the
 variable."
   :version "25.1"
-  :group 'tildify
   :type 'function)
 
 (defcustom tildify-ignored-environments-alist ()
@@ -183,7 +178,6 @@ MAJOR-MODE defines major mode, for which the item applies.  
It can be either:
 
 See `tildify-foreach-ignore-environments' function for description of BEG-REGEX
 and END-REGEX."
-  :group 'tildify
   :type '(repeat
           (cons :tag "Entry for major mode"
                 (choice (const  :tag "Default" t)
@@ -295,7 +289,7 @@ variable.  For example, for an XML file one might use:
   (setq-local tildify-foreach-region-function
     (apply-partially \\='tildify-foreach-ignore-environments
                      \\='((\"<! *--\" . \"-- *>\") (\"<\" . \">\"))))"
-  (let ((beg-re (concat "\\(?:" (mapconcat 'car pairs "\\)\\|\\(?:") "\\)"))
+  (let ((beg-re (concat "\\(?:" (mapconcat #'car pairs "\\)\\|\\(?:") "\\)"))
         p end-re)
     (save-excursion
       (save-restriction
@@ -416,19 +410,16 @@ If the pattern matches `looking-back', a hard space needs 
to be inserted instead
 of a space at point.  The regexp is always case sensitive, regardless of the
 current `case-fold-search' setting."
   :version "25.1"
-  :group 'tildify
   :type 'regexp)
 
 (defcustom tildify-space-predicates '(tildify-space-region-predicate)
   "A list of predicate functions for `tildify-space' function."
   :version "25.1"
-  :group 'tildify
   :type '(repeat function))
 
 (defcustom tildify-double-space-undos t
   "Weather `tildify-space' should undo hard space when space is typed again."
   :version "25.1"
-  :group 'tildify
   :type 'boolean)
 
 ;;;###autoload
@@ -508,8 +499,8 @@ variable will be set to the representation."
                            "mode won't have any effect, disabling.")))
         (setq tildify-mode nil))))
   (if tildify-mode
-      (add-hook 'post-self-insert-hook 'tildify-space nil t)
-    (remove-hook 'post-self-insert-hook 'tildify-space t)))
+      (add-hook 'post-self-insert-hook #'tildify-space nil t)
+    (remove-hook 'post-self-insert-hook #'tildify-space t)))
 
 
 ;;; *** Announce ***
diff --git a/lisp/textmodes/two-column.el b/lisp/textmodes/two-column.el
index d072ab1..6c3bacc 100644
--- a/lisp/textmodes/two-column.el
+++ b/lisp/textmodes/two-column.el
@@ -1,4 +1,4 @@
-;;; two-column.el --- minor mode for editing of two-column text
+;;; two-column.el --- minor mode for editing of two-column text  -*- 
lexical-binding: t; -*-
 
 ;; Copyright (C) 1992-1995, 2001-2021 Free Software Foundation, Inc.
 
@@ -133,26 +133,22 @@
        '("-%*- %15b --"  (-3 . "%p")  "--%[("  mode-name
          minor-mode-alist  "%n"  mode-line-process  ")%]%-")
   "Value of `mode-line-format' for a buffer in two-column minor mode."
-  :type 'sexp
-  :group 'two-column)
+  :type 'sexp)
 
 (defcustom 2C-other-buffer-hook 'text-mode
   "Hook run in new buffer when it is associated with current one."
-  :type 'function
-  :group 'two-column)
+  :type 'function)
 
 (defcustom 2C-separator ""
   "A string inserted between the two columns when merging.
 This gets set locally by \\[2C-split]."
-  :type 'string
-  :group 'two-column)
+  :type 'string)
 (put '2C-separator 'permanent-local t)
 
 (defcustom 2C-window-width 40
   "The width of the first column.  (Must be at least `window-min-width'.)
 This value is local for every buffer that sets it."
-  :type 'integer
-  :group 'two-column)
+  :type 'integer)
 (make-variable-buffer-local '2C-window-width)
 (put '2C-window-width 'permanent-local t)
 
@@ -160,21 +156,19 @@ This value is local for every buffer that sets it."
   "Base for calculating `fill-column' for a buffer in two-column minor mode.
 The value of `fill-column' becomes `2C-window-width' for this buffer
 minus this value."
-  :type 'integer
-  :group 'two-column)
+  :type 'integer)
 
 (defcustom 2C-autoscroll t
   "If non-nil, Emacs attempts to keep the two column's buffers aligned."
-  :type 'boolean
-  :group 'two-column)
+  :type 'boolean)
 
 
 (defvar 2C-mode-map
   (let ((map (make-sparse-keymap)))
-    (define-key map "2" '2C-two-columns)
-    (define-key map [f2] '2C-two-columns)
-    (define-key map "b" '2C-associate-buffer)
-    (define-key map "s" '2C-split)
+    (define-key map "2" #'2C-two-columns)
+    (define-key map [f2] #'2C-two-columns)
+    (define-key map "b" #'2C-associate-buffer)
+    (define-key map "s" #'2C-split)
     map)
   "Keymap for commands for setting up two-column mode.")
 
@@ -184,19 +178,19 @@ minus this value."
 ;; This one is for historical reasons and simple keyboards, it is not
 ;; at all mnemonic.  All usual sequences containing 2 were used, and
 ;; f2 could not be set up in a standard way under Emacs 18.
-;;;###autoload (global-set-key "\C-x6" '2C-command)
+;;;###autoload (global-set-key "\C-x6" #'2C-command)
 
-;;;###autoload (global-set-key [f2] '2C-command)
+;;;###autoload (global-set-key [f2] #'2C-command)
 
 (defvar 2C-minor-mode-map
   (let ((map (make-sparse-keymap)))
-    (define-key map "1" '2C-merge)
-    (define-key map "d" '2C-dissociate)
-    (define-key map "o" '2C-associated-buffer)
-    (define-key map "\^m" '2C-newline)
-    (define-key map "|" '2C-toggle-autoscroll)
-    (define-key map "{" '2C-shrink-window-horizontally)
-    (define-key map "}" '2C-enlarge-window-horizontally)
+    (define-key map "1" #'2C-merge)
+    (define-key map "d" #'2C-dissociate)
+    (define-key map "o" #'2C-associated-buffer)
+    (define-key map "\^m" #'2C-newline)
+    (define-key map "|" #'2C-toggle-autoscroll)
+    (define-key map "{" #'2C-shrink-window-horizontally)
+    (define-key map "}" #'2C-enlarge-window-horizontally)
     map)
   "Keymap for commands for use in two-column mode.")
 
@@ -281,7 +275,7 @@ some prefix.
 The appearance of the screen can be customized by the variables
 `2C-window-width', `2C-beyond-fill-column', `2C-mode-line-format' and
 `truncate-partial-width-windows'."
-  (add-hook 'post-command-hook '2C-autoscroll nil t)
+  (add-hook 'post-command-hook #'2C-autoscroll nil t)
   (setq fill-column (- 2C-window-width
                       2C-beyond-fill-column)
        mode-line-format 2C-mode-line-format
diff --git a/lisp/thumbs.el b/lisp/thumbs.el
index 465d097..3e7c912 100644
--- a/lisp/thumbs.el
+++ b/lisp/thumbs.el
@@ -1,4 +1,4 @@
-;;; thumbs.el --- Thumbnails previewer for images files
+;;; thumbs.el --- Thumbnails previewer for images files  -*- lexical-binding: 
t -*-
 
 ;; Copyright (C) 2004-2021 Free Software Foundation, Inc.
 
@@ -23,7 +23,7 @@
 
 ;;; Commentary:
 
-;; This package create two new modes: thumbs-mode and thumbs-view-image-mode.
+;; This package create two new modes: `thumbs-mode' and 
`thumbs-view-image-mode'.
 ;; It is used for basic browsing and viewing of images from within Emacs.
 ;; Minimal image manipulation functions are also available via external
 ;; programs.  If you want to do more complex tasks like categorize and tag
@@ -34,7 +34,7 @@
 ;;
 ;; Thanks: Alex Schroeder <alex@gnu.org> for maintaining the package at some
 ;;         time.  The peoples at #emacs@freenode.net for numerous help.  RMS
-;;         for emacs and the GNU project.
+;;         for Emacs and the GNU project.
 ;;
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;;
@@ -68,29 +68,24 @@
 
 (defcustom thumbs-thumbsdir (locate-user-emacs-file "thumbs")
   "Directory to store thumbnails."
-  :type 'directory
-  :group 'thumbs)
+  :type 'directory)
 
 (defcustom thumbs-geometry "100x100"
   "Size of thumbnails."
-  :type 'string
-  :group 'thumbs)
+  :type 'string)
 
 (defcustom thumbs-per-line 4
   "Number of thumbnails per line to show in directory."
-  :type 'integer
-  :group 'thumbs)
+  :type 'integer)
 
 (defcustom thumbs-max-image-number 16
  "Maximum number of images initially displayed in thumbs buffer."
-  :type 'integer
-  :group 'thumbs)
+  :type 'integer)
 
 (defcustom thumbs-thumbsdir-max-size 50000000
   "Maximum size for thumbnails directory.
 When it reaches that size (in bytes), a warning is sent."
-  :type 'integer
-  :group 'thumbs)
+  :type 'integer)
 
 ;; Unfortunately Windows XP has a program called CONVERT.EXE in
 ;; C:/WINDOWS/SYSTEM32/ for partitioning NTFS systems.  So Emacs
@@ -98,54 +93,48 @@ When it reaches that size (in bytes), a warning is sent."
 ;; customize this value to the absolute filename.
 (defcustom thumbs-conversion-program
   (if (eq system-type 'windows-nt)
+      ;; FIXME is this necessary, or can a sane PATHEXE be assumed?
+      ;; Eg find-program does not do this.
       "convert.exe"
-    (or (executable-find "convert")
-       "/usr/X11R6/bin/convert"))
+    "convert")
   "Name of conversion program for thumbnails generation.
-It must be \"convert\"."
+This must be the ImageMagick \"convert\" utility."
   :type 'string
-  :group 'thumbs)
+  :version "28.1")
 
 (defcustom thumbs-setroot-command
   "xloadimage -onroot -fullscreen *"
   "Command to set the root window."
-  :type 'string
-  :group 'thumbs)
+  :type 'string)
 
 (defcustom thumbs-relief 5
   "Size of button-like border around thumbnails."
-  :type 'integer
-  :group 'thumbs)
+  :type 'integer)
 
 (defcustom thumbs-margin 2
   "Size of the margin around thumbnails.
 This is where you see the cursor."
-  :type 'integer
-  :group 'thumbs)
+  :type 'integer)
 
 (defcustom thumbs-thumbsdir-auto-clean t
   "If set, delete older file in the thumbnails directory.
 Deletion is done at load time when the directory size is bigger
 than `thumbs-thumbsdir-max-size'."
-  :type 'boolean
-  :group 'thumbs)
+  :type 'boolean)
 
 (defcustom thumbs-image-resizing-step 10
   "Step by which to resize image as a percentage."
-  :type 'integer
-  :group 'thumbs)
+  :type 'integer)
 
 (defcustom thumbs-temp-dir temporary-file-directory
   "Temporary directory to use.
 Defaults to `temporary-file-directory'.  Leaving it to
 this value can let another user see some of your images."
-  :type 'directory
-  :group 'thumbs)
+  :type 'directory)
 
 (defcustom thumbs-temp-prefix "emacsthumbs"
   "Prefix to add to temp files."
-  :type 'string
-  :group 'thumbs)
+  :type 'string)
 
 ;; Initialize some variable, for later use.
 (defvar-local thumbs-current-tmp-filename nil
@@ -199,23 +188,24 @@ Create the thumbnails directory if it does not exist."
 If the total size of all files in `thumbs-thumbsdir' is bigger than
 `thumbs-thumbsdir-max-size', files are deleted until the max size is
 reached."
-  (let* ((files-list
-         (sort
-          (mapcar
-           (lambda (f)
-             (let ((fattribs-list (file-attributes f)))
-               `(,(file-attribute-access-time fattribs-list)
-                 ,(file-attribute-size fattribs-list)
-                 ,f)))
-           (directory-files (thumbs-thumbsdir) t (image-file-name-regexp)))
-          (lambda (l1 l2) (time-less-p (car l1) (car l2)))))
-        (dirsize (apply '+ (mapcar (lambda (x) (cadr x)) files-list))))
-    (while (> dirsize thumbs-thumbsdir-max-size)
-      (progn
-       (message "Deleting file %s" (cadr (cdar files-list))))
-      (delete-file (cadr (cdar files-list)))
-      (setq dirsize (- dirsize (car (cdar files-list))))
-      (setq files-list (cdr files-list)))))
+  (when (file-directory-p thumbs-thumbsdir)
+    (let* ((files-list
+           (sort
+            (mapcar
+             (lambda (f)
+               (let ((fattribs-list (file-attributes f)))
+                 `(,(file-attribute-access-time fattribs-list)
+                   ,(file-attribute-size fattribs-list)
+                   ,f)))
+             (directory-files (thumbs-thumbsdir) t (image-file-name-regexp)))
+            (lambda (l1 l2) (time-less-p (car l1) (car l2)))))
+           (dirsize (apply #'+ (mapcar (lambda (x) (cadr x)) files-list))))
+      (while (> dirsize thumbs-thumbsdir-max-size)
+        (progn
+         (message "Deleting file %s" (cadr (cdar files-list))))
+        (delete-file (cadr (cdar files-list)))
+        (setq dirsize (- dirsize (car (cdar files-list))))
+        (setq files-list (cdr files-list))))))
 
 ;; Check the thumbnail directory size and clean it if necessary.
 (when thumbs-thumbsdir-auto-clean
@@ -289,7 +279,7 @@ smaller according to whether INCREMENT is 1 or -1."
              (subst-char-in-string
               ?\s ?\_
               (apply
-               'concat
+               #'concat
                (split-string filename "/")))))))
 
 (defun thumbs-make-thumb (img)
@@ -387,7 +377,7 @@ If MARKED is non-nil, the image is marked."
   "Make a preview buffer for all images in DIR.
 Optional argument REG to select file matching a regexp,
 and SAME-WINDOW to show thumbs in the same window."
-  (interactive "DDir: ")
+  (interactive "DThumbs (directory): ")
   (thumbs-show-thumbs-list
    (directory-files dir t (or reg (image-file-name-regexp)))
    dir same-window))
@@ -617,7 +607,7 @@ Open another window."
   (when (eolp) (forward-char)))
 
 ;; cleaning of old temp files
-(mapc 'delete-file
+(mapc #'delete-file
       (directory-files (thumbs-temp-dir) t thumbs-temp-prefix))
 
 ;; Image modification routines
diff --git a/lisp/time.el b/lisp/time.el
index 1403c4a..7e1d918 100644
--- a/lisp/time.el
+++ b/lisp/time.el
@@ -614,13 +614,14 @@ point."
         str))))
 
 ;;;###autoload
-(defun emacs-init-time ()
-  "Return a string giving the duration of the Emacs initialization."
+(defun emacs-init-time (&optional format)
+  "Return a string giving the duration of the Emacs initialization.
+FORMAT is a string to format the result, using `format'. If nil,
+the default format \"%f seconds\" is used."
   (interactive)
-  (let ((str
-        (format "%s seconds"
-                (float-time
-                 (time-subtract after-init-time before-init-time)))))
+  (let ((str (format (or format "%f seconds")
+                     (float-time (time-subtract after-init-time
+                                                before-init-time)))))
     (if (called-interactively-p 'interactive)
         (message "%s" str)
       str)))
diff --git a/lisp/tooltip.el b/lisp/tooltip.el
index 8e00aa5..03d9f54 100644
--- a/lisp/tooltip.el
+++ b/lisp/tooltip.el
@@ -131,7 +131,11 @@ of the `tooltip' face are used instead."
      :inherit variable-pitch)
     (t
      :inherit variable-pitch))
-  "Face for tooltips."
+  "Face for tooltips.
+
+When using the GTK toolkit, this face will only be used if
+`x-gtk-use-system-tooltips' is non-nil."
+  :group 'tooltip
   :group 'basic-faces)
 
 (defcustom tooltip-use-echo-area nil
@@ -248,7 +252,12 @@ in echo area."
            (setf (alist-get 'border-color params) fg))
          (when (stringp bg)
            (setf (alist-get 'background-color params) bg))
-         (x-show-tip (propertize text 'face 'tooltip)
+          ;; Use non-nil APPEND argument below to avoid overriding any
+          ;; faces used in our TEXT.  Among other things, this allows
+          ;; tooltips to use the `help-key-binding' face used in
+          ;; `substitute-command-keys' substitutions.
+          (add-face-text-property 0 (length text) 'tooltip t text)
+          (x-show-tip text
                      (selected-frame)
                      params
                      tooltip-hide-delay
diff --git a/lisp/tutorial.el b/lisp/tutorial.el
index 57e5570..186bf35 100644
--- a/lisp/tutorial.el
+++ b/lisp/tutorial.el
@@ -1,4 +1,4 @@
-;;; tutorial.el --- tutorial for Emacs
+;;; tutorial.el --- tutorial for Emacs  -*- lexical-binding: t -*-
 
 ;; Copyright (C) 2006-2021 Free Software Foundation, Inc.
 
@@ -25,10 +25,6 @@
 
 ;; Code for running the Emacs tutorial.
 
-;;; History:
-
-;; File was created 2006-09.
-
 ;;; Code:
 
 (require 'help-mode) ;; for function help-buffer
@@ -517,8 +513,8 @@ where
                           (list "more info" 'current-binding
                                 key-fun def-fun key where))
                     nil))
-           (add-to-list 'changed-keys
-                        (list key def-fun def-fun-txt where remark nil))))))
+            (push (list key def-fun def-fun-txt where remark nil)
+                  changed-keys)))))
     changed-keys))
 
 (defun tutorial--key-description (key)
@@ -768,7 +764,7 @@ Run the Viper tutorial? "))
        (if (fboundp 'viper-tutorial)
            (if (y-or-n-p (concat prompt1 prompt2))
                (progn (message "")
-                      (funcall 'viper-tutorial 0))
+                       (funcall #'viper-tutorial 0))
              (message "Tutorial aborted by user"))
          (message prompt1)))
     (let* ((lang (cond
diff --git a/lisp/uniquify.el b/lisp/uniquify.el
index c1ec90e..1d513d6 100644
--- a/lisp/uniquify.el
+++ b/lisp/uniquify.el
@@ -175,8 +175,8 @@ contains the name of the directory which the buffer is 
visiting.")
 (cl-defstruct (uniquify-item
            (:constructor nil) (:copier nil)
            (:constructor uniquify-make-item
-            (base dirname buffer &optional proposed)))
-  base dirname buffer proposed)
+            (base dirname buffer &optional proposed original-dirname)))
+  base dirname buffer proposed original-dirname)
 
 ;; Internal variables used free
 (defvar uniquify-possibly-resolvable nil)
@@ -211,7 +211,8 @@ this rationalization."
   (with-current-buffer newbuf (setq uniquify-managed nil))
   (when dirname
     (setq dirname (expand-file-name (directory-file-name dirname)))
-    (let ((fix-list (list (uniquify-make-item base dirname newbuf)))
+    (let ((fix-list (list (uniquify-make-item base dirname newbuf
+                                              nil dirname)))
          items)
       (dolist (buffer (buffer-list))
        (when (and (not (and uniquify-ignore-buffers-re
@@ -284,7 +285,9 @@ in `uniquify-list-buffers-directory-modes', otherwise 
returns nil."
       ;; Refresh the dirnames and proposed names.
       (setf (uniquify-item-proposed item)
            (uniquify-get-proposed-name (uniquify-item-base item)
-                                       (uniquify-item-dirname item)))
+                                       (uniquify-item-dirname item)
+                                        nil
+                                        (uniquify-item-original-dirname item)))
       (setq uniquify-managed fix-list)))
   ;; Strip any shared last directory names of the dirname.
   (when (and (cdr fix-list) uniquify-strip-common-suffix)
@@ -307,7 +310,8 @@ in `uniquify-list-buffers-directory-modes', otherwise 
returns nil."
                                              (uniquify-item-dirname item))))
                                      (and f (directory-file-name f)))
                                    (uniquify-item-buffer item)
-                                   (uniquify-item-proposed item))
+                                   (uniquify-item-proposed item)
+                                    (uniquify-item-original-dirname item))
                fix-list)))))
   ;; If uniquify-min-dir-content is 0, this will end up just
   ;; passing fix-list to uniquify-rationalize-conflicting-sublist.
@@ -335,13 +339,14 @@ in `uniquify-list-buffers-directory-modes', otherwise 
returns nil."
     (uniquify-rationalize-conflicting-sublist conflicting-sublist
                                              old-proposed depth)))
 
-(defun uniquify-get-proposed-name (base dirname &optional depth)
+(defun uniquify-get-proposed-name (base dirname &optional depth
+                                        original-dirname)
   (unless depth (setq depth uniquify-min-dir-content))
   (cl-assert (equal (directory-file-name dirname) dirname)) ;No trailing slash.
 
   ;; Distinguish directories by adding extra separator.
   (if (and uniquify-trailing-separator-p
-          (file-directory-p (expand-file-name base dirname))
+          (file-directory-p (expand-file-name base original-dirname))
           (not (string-equal base "")))
       (cond ((eq uniquify-buffer-name-style 'forward)
             (setq base (file-name-as-directory base)))
@@ -410,7 +415,8 @@ in `uniquify-list-buffers-directory-modes', otherwise 
returns nil."
                  (uniquify-get-proposed-name
                   (uniquify-item-base item)
                   (uniquify-item-dirname item)
-                  depth)))
+                  depth
+                   (uniquify-item-original-dirname item))))
          (uniquify-rationalize-a-list conf-list depth))
       (unless (string= old-name "")
        (uniquify-rename-buffer (car conf-list) old-name)))))
diff --git a/lisp/url/ChangeLog.1 b/lisp/url/ChangeLog.1
index 5a3bf3a..cdd37a6 100644
--- a/lisp/url/ChangeLog.1
+++ b/lisp/url/ChangeLog.1
@@ -2337,7 +2337,7 @@
        recurse when retrieving the property lists.  Returns an assoc
        list keyed off of the resource, the cdr of which is a property list.
        (url-dav-datatype-attribute): We support the XML-Data note
-       (http://www.w3.org/TR/1998/NOTE-XML-data) to figure out what the
+       (https://www.w3.org/TR/1998/NOTE-XML-data) to figure out what the
        datatypes of attributes are.  Currently only date, dateTime, int,
        number, float, boolean, and uri are supported.
 
diff --git a/lisp/url/url-cookie.el b/lisp/url/url-cookie.el
index 085159c..27f4f88 100644
--- a/lisp/url/url-cookie.el
+++ b/lisp/url/url-cookie.el
@@ -60,7 +60,7 @@
 
 (defcustom url-cookie-multiple-line nil
   "If nil, HTTP requests put all cookies for the server on one line.
-Some web servers, such as http://www.hotmail.com/, only accept cookies
+Some web servers, such as https://www.hotmail.com/, only accept cookies
 when they are on one line.  This is broken behavior, but just try
 telling Microsoft that."
   :type 'boolean
diff --git a/lisp/url/url-http.el b/lisp/url/url-http.el
index 8cebd4e..e3c1786 100644
--- a/lisp/url/url-http.el
+++ b/lisp/url/url-http.el
@@ -1292,7 +1292,7 @@ passing it an updated value of CBARGS as arguments.  The 
first
 element in CBARGS should be a plist describing what has happened
 so far during the request, as described in the docstring of
 `url-retrieve' (if in doubt, specify nil).  The current buffer
-then CALLBACK is executed is the retrieval buffer.
+when CALLBACK is executed is the retrieval buffer.
 
 Optional arg RETRY-BUFFER, if non-nil, specifies the buffer of a
 previous `url-http' call, which is being re-attempted.
diff --git a/lisp/url/url-news.el b/lisp/url/url-news.el
index 585a282..49cc587 100644
--- a/lisp/url/url-news.el
+++ b/lisp/url/url-news.el
@@ -27,11 +27,6 @@
 (require 'nntp)
 (autoload 'gnus-group-read-ephemeral-group "gnus-group")
 
-;; Unused.
-;;; (defgroup url-news nil
-;;;   "News related options."
-;;;   :group 'url)
-
 (defun url-news-open-host (host port user pass)
   (if (fboundp 'nnheader-init-server-buffer)
       (nnheader-init-server-buffer))
diff --git a/lisp/userlock.el b/lisp/userlock.el
index a340ff8..4a75815 100644
--- a/lisp/userlock.el
+++ b/lisp/userlock.el
@@ -1,4 +1,4 @@
-;;; userlock.el --- handle file access contention between multiple users
+;;; userlock.el --- handle file access contention between multiple users  -*- 
lexical-binding: t -*-
 
 ;; Copyright (C) 1985-1986, 2001-2021 Free Software Foundation, Inc.
 
@@ -39,6 +39,10 @@
 
 (define-error 'file-locked "File is locked" 'file-error)
 
+(defun userlock--fontify-key (key)
+  "Add the `help-key-binding' face to string KEY."
+  (propertize key 'face 'help-key-binding))
+
 ;;;###autoload
 (defun ask-user-about-lock (file opponent)
   "Ask user what to do when he wants to edit FILE but it is locked by OPPONENT.
@@ -64,8 +68,12 @@ in any way you like."
                          (match-string 0 opponent)))
              opponent))
       (while (null answer)
-       (message "%s locked by %s: (s, q, p, ?)? "
-                short-file short-opponent)
+        (message "%s locked by %s: (%s, %s, %s, %s)? "
+                 short-file short-opponent
+                 (userlock--fontify-key "s")
+                 (userlock--fontify-key "q")
+                 (userlock--fontify-key "p")
+                 (userlock--fontify-key "?"))
        (if noninteractive (error "Cannot resolve lock conflict in batch mode"))
        (let ((tem (let ((inhibit-quit t)
                         (cursor-in-echo-area t))
@@ -80,7 +88,12 @@ in any way you like."
                                      (?? . help))))
            (cond ((null answer)
                   (beep)
-                  (message "Please type q, s, or p; or ? for help")
+                   (message "Please type %s, %s, or %s; or %s for help"
+                            (userlock--fontify-key "q")
+                            (userlock--fontify-key "s")
+                            (userlock--fontify-key "p")
+                            ;; FIXME: Why do we use "?" here and "C-h" below?
+                            (userlock--fontify-key "?"))
                   (sit-for 3))
                  ((eq (cdr answer) 'help)
                   (ask-user-about-lock-help)
@@ -91,14 +104,19 @@ in any way you like."
 
 (defun ask-user-about-lock-help ()
   (with-output-to-temp-buffer "*Help*"
-    (princ "It has been detected that you want to modify a file that someone 
else has
+    (with-current-buffer standard-output
+      (insert
+       (format
+        "It has been detected that you want to modify a file that someone else 
has
 already started modifying in Emacs.
 
-You can <s>teal the file; the other user becomes the
+You can <%s>teal the file; the other user becomes the
   intruder if (s)he ever unmodifies the file and then changes it again.
-You can <p>roceed; you edit at your own (and the other user's) risk.
-You can <q>uit; don't modify this file.")
-    (with-current-buffer standard-output
+You can <%s>roceed; you edit at your own (and the other user's) risk.
+You can <%s>uit; don't modify this file."
+        (userlock--fontify-key "s")
+        (userlock--fontify-key "p")
+        (userlock--fontify-key "q")))
       (help-mode))))
 
 (define-error 'file-supersession nil 'file-error)
@@ -151,8 +169,13 @@ The buffer in question is current when this function is 
called."
   (save-window-excursion
     (let ((prompt
           (format "%s changed on disk; \
-really edit the buffer? (y, n, r or C-h) "
-                  (file-name-nondirectory filename)))
+really edit the buffer? (%s, %s, %s or %s) "
+                   (file-name-nondirectory filename)
+                   (userlock--fontify-key "y")
+                   (userlock--fontify-key "n")
+                   (userlock--fontify-key "r")
+                   ;; FIXME: Why do we use "C-h" here and "?" above?
+                   (userlock--fontify-key "C-h")))
          (choices '(?y ?n ?r ?? ?\C-h))
          answer)
       (when noninteractive
@@ -177,20 +200,38 @@ really edit the buffer? (y, n, r or C-h) "
 
 (defun ask-user-about-supersession-help ()
   (with-output-to-temp-buffer "*Help*"
-    (princ
-     (substitute-command-keys
-      "You want to modify a buffer whose disk file has changed
+    (let ((revert-buffer-binding
+           ;; This takes place in the original buffer.
+           (substitute-command-keys "\\[revert-buffer]")))
+      (with-current-buffer standard-output
+        (insert
+         (format
+          "You want to modify a buffer whose disk file has changed
 since you last read it in or saved it with this buffer.
 
-If you say `y' to go ahead and modify this buffer,
+If you say %s to go ahead and modify this buffer,
 you risk ruining the work of whoever rewrote the file.
-If you say `r' to revert, the contents of the buffer are refreshed
+If you say %s to revert, the contents of the buffer are refreshed
 from the file on disk.
-If you say `n', the change you started to make will be aborted.
+If you say %s, the change you started to make will be aborted.
 
-Usually, you should type `n' and then `\\[revert-buffer]',
-to get the latest version of the file, then make the change again."))
-    (with-current-buffer standard-output
-      (help-mode))))
+Usually, you should type %s and then %s,
+to get the latest version of the file, then make the change again."
+          (userlock--fontify-key "y")
+          (userlock--fontify-key "r")
+          (userlock--fontify-key "n")
+          (userlock--fontify-key "n")
+          revert-buffer-binding))
+        (help-mode)))))
+
+;;;###autoload
+(defun userlock--handle-unlock-error (error)
+  "Report an ERROR that occurred while unlocking a file."
+  (display-warning
+   '(unlock-file)
+   ;; There is no need to explain that this is an unlock error because
+   ;; ERR is a `file-error' condition, which explains this.
+   (message "%s, ignored" (error-message-string error))
+   :warning))
 
 ;;; userlock.el ends here
diff --git a/lisp/vc/add-log.el b/lisp/vc/add-log.el
index 19765e0..6b38806 100644
--- a/lisp/vc/add-log.el
+++ b/lisp/vc/add-log.el
@@ -1,4 +1,4 @@
-;;; add-log.el --- change log maintenance commands for Emacs
+;;; add-log.el --- change log maintenance commands for Emacs  -*- 
lexical-binding: t; -*-
 
 ;; Copyright (C) 1985-1986, 1988, 1993-1994, 1997-1998, 2000-2021 Free
 ;; Software Foundation, Inc.
@@ -49,15 +49,13 @@
 (defcustom change-log-default-name nil
   "Name of a change log file for \\[add-change-log-entry]."
   :type '(choice (const :tag "default" nil)
-                string)
-  :group 'change-log)
+                string))
 ;;;###autoload
-(put 'change-log-default-name 'safe-local-variable 'string-or-null-p)
+(put 'change-log-default-name 'safe-local-variable #'string-or-null-p)
 
 (defcustom change-log-mode-hook nil
   "Normal hook run by `change-log-mode'."
-  :type 'hook
-  :group 'change-log)
+  :type 'hook)
 
 ;; Many modes set this variable, so avoid warnings.
 ;;;###autoload
@@ -66,16 +64,14 @@
 It is called by `add-log-current-defun' with no argument, and
 should return the function's name as a string, or nil if point is
 outside a function."
-  :type '(choice (const nil) function)
-  :group 'change-log)
+  :type '(choice (const nil) function))
 
 ;;;###autoload
 (defcustom add-log-full-name nil
   "Full name of user, for inclusion in ChangeLog daily headers.
 This defaults to the value returned by the function `user-full-name'."
   :type '(choice (const :tag "Default" nil)
-                string)
-  :group 'change-log)
+                string))
 
 ;;;###autoload
 (defcustom add-log-mailing-address nil
@@ -86,8 +82,7 @@ will be recognized as referring to the same user; when 
creating a new
 ChangeLog entry, one element will be chosen at random."
   :type '(choice (const :tag "Default" nil)
                 (string :tag "String")
-                (repeat :tag "List of Strings" string))
-  :group 'change-log)
+                (repeat :tag "List of Strings" string)))
 
 (defcustom add-log-time-format 'add-log-iso8601-time-string
   "Function that defines the time format.
@@ -98,8 +93,7 @@ and `current-time-string' are two valid values."
                       add-log-iso8601-time-string)
                (const :tag "Old format, as returned by `current-time-string'"
                       current-time-string)
-               (function :tag "Other"))
-  :group 'change-log)
+               (function :tag "Other")))
 
 (defcustom add-log-keep-changes-together nil
   "If non-nil, normally keep day's log entries for one file together.
@@ -130,14 +124,12 @@ and in the former:
 The NEW-ENTRY arg to `add-change-log-entry' can override the effect of
 this variable."
   :version "20.3"
-  :type 'boolean
-  :group 'change-log)
+  :type 'boolean)
 
 (defcustom add-log-always-start-new-record nil
   "If non-nil, `add-change-log-entry' will always start a new record."
   :version "22.1"
-  :type 'boolean
-  :group 'change-log)
+  :type 'boolean)
 
 (defvar add-log-buffer-file-name-function 'buffer-file-name
   "If non-nil, function to call to identify the full filename of a buffer.
@@ -149,15 +141,13 @@ use `buffer-file-name'.")
 This function is called with one argument, the value of variable
 `buffer-file-name' in that buffer.  If this is nil, the default is to
 use the file's name relative to the directory of the change log file."
-  :type '(choice (const nil) function)
-  :group 'change-log)
+  :type '(choice (const nil) function))
 
 
 (defcustom change-log-version-info-enabled nil
   "If non-nil, enable recording version numbers with the changes."
   :version "21.1"
-  :type 'boolean
-  :group 'change-log)
+  :type 'boolean)
 
 (defcustom change-log-version-number-regexp-list
   (let ((re "\\([0-9]+\\.[0-9.]+\\)"))
@@ -170,64 +160,54 @@ use the file's name relative to the directory of the 
change log file."
 The version number must be in group 1.
 Note: The search is conducted only within 10%, at the beginning of the file."
   :version "21.1"
-  :type '(repeat regexp)
-  :group 'change-log)
+  :type '(repeat regexp))
 
 (defcustom change-log-directory-files '(".bzr" ".git" ".hg" ".svn")
   "List of files that cause `find-change-log' to stop in containing directory.
 This applies if no pre-existing ChangeLog is found.  If nil, then in such
 a case simply use the directory containing the changed file."
   :version "26.1"
-  :type '(repeat file)
-  :group 'change-log)
+  :type '(repeat file))
 
 (defface change-log-date
   '((t (:inherit font-lock-string-face)))
   "Face used to highlight dates in date lines."
-  :version "21.1"
-  :group 'change-log)
+  :version "21.1")
 
 (defface change-log-name
   '((t (:inherit font-lock-constant-face)))
   "Face for highlighting author names."
-  :version "21.1"
-  :group 'change-log)
+  :version "21.1")
 
 (defface change-log-email
   '((t (:inherit font-lock-variable-name-face)))
   "Face for highlighting author email addresses."
-  :version "21.1"
-  :group 'change-log)
+  :version "21.1")
 
 (defface change-log-file
   '((t (:inherit font-lock-function-name-face)))
   "Face for highlighting file names."
-  :version "21.1"
-  :group 'change-log)
+  :version "21.1")
 
 (defface change-log-list
   '((t (:inherit font-lock-keyword-face)))
   "Face for highlighting parenthesized lists of functions or variables."
-  :version "21.1"
-  :group 'change-log)
+  :version "21.1")
 
 (defface change-log-conditionals
   '((t (:inherit font-lock-variable-name-face)))
   "Face for highlighting conditionals of the form `[...]'."
-  :version "21.1"
-  :group 'change-log)
+  :version "21.1")
 
 (defface change-log-function
   '((t (:inherit font-lock-variable-name-face)))
   "Face for highlighting items of the form `<....>'."
-  :version "21.1"
-  :group 'change-log)
+  :version "21.1")
 
 (defface change-log-acknowledgment
   '((t (:inherit font-lock-comment-face)))
   "Face for highlighting acknowledgments."
-  :version "21.1"
-  :group 'change-log)
+  :version "21.1")
 (define-obsolete-face-alias 'change-log-acknowledgement
   'change-log-acknowledgment "24.3")
 
@@ -519,7 +499,7 @@ try to visit the file for the change under `point' instead."
           change-log-find-tail)
       (setq change-log-find-tail
            (condition-case nil
-               (apply 'change-log-goto-source-1
+               (apply #'change-log-goto-source-1
                       (append change-log-find-head change-log-find-tail))
              (error
               (format-message
@@ -556,7 +536,7 @@ try to visit the file for the change under `point' instead."
                      file (find-file-noselect file)))
          (condition-case nil
              (setq change-log-find-tail
-                   (apply 'change-log-goto-source-1 change-log-find-head))
+                   (apply #'change-log-goto-source-1 change-log-find-head))
            (error
             (format-message "Cannot find matches for tag `%s' in file `%s'"
                             tag file)))))))))
@@ -569,7 +549,7 @@ Compatibility function for \\[next-error] invocations."
         (count (abs argp))             ; how many cycles
         (down (< argp 0))              ; are we going down? (is argp negative?)
         (up (not down))
-        (search-function (if up 're-search-forward 're-search-backward)))
+        (search-function (if up #'re-search-forward #'re-search-backward)))
 
     ;; set the starting position
     (goto-char (cond (reset (point-min))
@@ -589,29 +569,27 @@ Compatibility function for \\[next-error] invocations."
        (select-window change-log-find-window)))))
 
 (defvar change-log-mode-map
-  (let ((map (make-sparse-keymap))
-       (menu-map (make-sparse-keymap)))
-    (define-key map [?\C-c ?\C-p] 'add-log-edit-prev-comment)
-    (define-key map [?\C-c ?\C-n] 'add-log-edit-next-comment)
-    (define-key map [?\C-c ?\C-f] 'change-log-find-file)
-    (define-key map [?\C-c ?\C-c] 'change-log-goto-source)
-    (define-key map [menu-bar changelog] (cons "ChangeLog" menu-map))
-    (define-key menu-map [gs]
-      '(menu-item "Go To Source" change-log-goto-source
-                 :help "Go to source location of ChangeLog tag near point"))
-    (define-key menu-map [ff]
-      '(menu-item "Find File" change-log-find-file
-                 :help "Visit the file for the change under point"))
-    (define-key menu-map [sep] '("--"))
-    (define-key menu-map [nx]
-      '(menu-item "Next Log-Edit Comment" add-log-edit-next-comment
-                 :help "Cycle forward through Log-Edit mode comment history"))
-    (define-key menu-map [pr]
-      '(menu-item "Previous Log-Edit Comment" add-log-edit-prev-comment
-                 :help "Cycle backward through Log-Edit mode comment history"))
+  (let ((map (make-sparse-keymap)))
+    (define-key map [?\C-c ?\C-p] #'add-log-edit-prev-comment)
+    (define-key map [?\C-c ?\C-n] #'add-log-edit-next-comment)
+    (define-key map [?\C-c ?\C-f] #'change-log-find-file)
+    (define-key map [?\C-c ?\C-c] #'change-log-goto-source)
     map)
   "Keymap for Change Log major mode.")
 
+(easy-menu-define change-log-mode-menu change-log-mode-map
+  "Menu for Change Log major mode."
+  '("ChangeLog"
+    ["Previous Log-Edit Comment" add-log-edit-prev-comment
+     :help "Cycle backward through Log-Edit mode comment history"]
+    ["Next Log-Edit Comment" add-log-edit-next-comment
+     :help "Cycle forward through Log-Edit mode comment history"]
+    "---"
+    ["Find File" change-log-find-file
+     :help "Visit the file for the change under point"]
+    ["Go To Source" change-log-goto-source
+     :help "Go to source location of ChangeLog tag near point"]))
+
 ;; It used to be called change-log-time-zone-rule but really should be
 ;; called add-log-time-zone-rule since it's only used from add-log-* code.
 (defvaralias 'change-log-time-zone-rule 'add-log-time-zone-rule)
@@ -814,7 +792,7 @@ means to put log entries in a suitably named buffer."
   :type 'boolean
   :version "27.1")
 
-(put 'add-log-dont-create-changelog-file 'safe-local-variable 'booleanp)
+(put 'add-log-dont-create-changelog-file 'safe-local-variable #'booleanp)
 
 (defun add-log--pseudo-changelog-buffer-name (changelog-file-name)
   "Compute a suitable name for a non-file visiting ChangeLog buffer.
@@ -1220,8 +1198,7 @@ file were isearch was started."
   "Heuristic regexp used by `add-log-current-defun' for unknown major modes.
 The regexp's first submatch is placed in the ChangeLog entry, in
 parentheses."
-  :type 'regexp
-  :group 'change-log)
+  :type 'regexp)
 
 (declare-function c-cpp-define-name "cc-cmds" ())
 (declare-function c-defun-name      "cc-cmds" ())
diff --git a/lisp/vc/compare-w.el b/lisp/vc/compare-w.el
index 932dcd7..4c1d9ea 100644
--- a/lisp/vc/compare-w.el
+++ b/lisp/vc/compare-w.el
@@ -1,4 +1,4 @@
-;;; compare-w.el --- compare text between windows for Emacs
+;;; compare-w.el --- compare text between windows for Emacs  -*- 
lexical-binding: t; -*-
 
 ;; Copyright (C) 1986, 1989, 1993, 1997, 2001-2021 Free Software
 ;; Foundation, Inc.
@@ -52,19 +52,16 @@ any text before that point.
 If the function returns the same value for both windows, then the
 whitespace is considered to match, and is skipped."
   :version "24.4"                      ; added \240
-  :type '(choice regexp function)
-  :group 'compare-windows)
+  :type '(choice regexp function))
 
 (defcustom compare-ignore-whitespace nil
   "Non-nil means command `compare-windows' ignores whitespace."
   :type 'boolean
-  :group 'compare-windows
   :version "22.1")
 
 (defcustom compare-ignore-case nil
   "Non-nil means command `compare-windows' ignores case differences."
-  :type 'boolean
-  :group 'compare-windows)
+  :type 'boolean)
 
 (defcustom compare-windows-sync 'compare-windows-sync-default-function
   "Function or regexp that is used to synchronize points in two
@@ -92,7 +89,6 @@ If the value of this variable is nil (option \"No sync\"), 
then
 no synchronization is performed, and the function `ding' is called
 to beep or flash the screen when points are mismatched."
   :type '(choice function regexp (const :tag "No sync" nil))
-  :group 'compare-windows
   :version "22.1")
 
 (defcustom compare-windows-sync-string-size 32
@@ -104,7 +100,6 @@ difference regions more coarse-grained.
 
 The default value 32 is good for the most cases."
   :type 'integer
-  :group 'compare-windows
   :version "22.1")
 
 (defcustom compare-windows-recenter nil
@@ -115,7 +110,6 @@ matching points side-by-side.
 The value `(-1 0)' is useful if windows are split vertically,
 and the value `((4) (4))' for horizontally split windows."
   :type '(list sexp sexp)
-  :group 'compare-windows
   :version "22.1")
 
 (defcustom compare-windows-highlight t
@@ -127,19 +121,16 @@ out all highlighting later with the command 
`compare-windows-dehighlight'."
   :type '(choice (const :tag "No highlighting" nil)
                 (const :tag "Persistent highlighting" persistent)
                 (other :tag "Highlight until next command" t))
-  :group 'compare-windows
   :version "22.1")
 
 (defface compare-windows-removed
   '((t :inherit diff-removed))
   "Face for highlighting `compare-windows' differing regions in the other 
window."
-  :group 'compare-windows
   :version "25.1")
 
 (defface compare-windows-added
   '((t :inherit diff-added))
   "Face for highlighting `compare-windows' differing regions in current 
window."
-  :group 'compare-windows
   :version "25.1")
 
 (define-obsolete-face-alias 'compare-windows 'compare-windows-added "25.1")
@@ -159,7 +150,6 @@ out all highlighting later with the command 
`compare-windows-dehighlight'."
          (function-item :tag "Next window"
                         compare-windows-get-next-window)
          (function :tag "Your function"))
-  :group 'compare-windows
   :version "25.1")
 
 (defun compare-windows-get-recent-window ()
@@ -389,7 +379,7 @@ on third call it again advances points to the next 
difference and so on."
               (setq p1 (1+ p1)))))
         (when p12s
           ;; use closest matching points (i.e. points with minimal sum)
-          (setq p12 (cdr (assq (apply 'min (mapcar 'car p12s)) p12s)))
+          (setq p12 (cdr (assq (apply #'min (mapcar #'car p12s)) p12s)))
           (goto-char (car p12))
           (compare-windows-highlight op1 (car p12) (current-buffer) w1
                                      op2 (cadr p12) b2 w2))
@@ -416,7 +406,7 @@ on third call it again advances points to the next 
difference and so on."
     (overlay-put compare-windows-overlay2 'window w2)
     (if (not (eq compare-windows-highlight 'persistent))
        ;; Remove highlighting before next command is executed
-       (add-hook 'pre-command-hook 'compare-windows-dehighlight)
+       (add-hook 'pre-command-hook #'compare-windows-dehighlight)
       (when compare-windows-overlay1
        (push (copy-overlay compare-windows-overlay1) compare-windows-overlays1)
        (delete-overlay compare-windows-overlay1))
@@ -427,9 +417,9 @@ on third call it again advances points to the next 
difference and so on."
 (defun compare-windows-dehighlight ()
   "Remove highlighting created by function `compare-windows-highlight'."
   (interactive)
-  (remove-hook 'pre-command-hook 'compare-windows-dehighlight)
-  (mapc 'delete-overlay compare-windows-overlays1)
-  (mapc 'delete-overlay compare-windows-overlays2)
+  (remove-hook 'pre-command-hook #'compare-windows-dehighlight)
+  (mapc #'delete-overlay compare-windows-overlays1)
+  (mapc #'delete-overlay compare-windows-overlays2)
   (and compare-windows-overlay1 (delete-overlay compare-windows-overlay1))
   (and compare-windows-overlay2 (delete-overlay compare-windows-overlay2)))
 
diff --git a/lisp/vc/cvs-status.el b/lisp/vc/cvs-status.el
index 26fb620..63b8863 100644
--- a/lisp/vc/cvs-status.el
+++ b/lisp/vc/cvs-status.el
@@ -28,7 +28,7 @@
 
 ;;; Code:
 
-(eval-when-compile (require 'cl-lib))
+(require 'cl-lib)
 (require 'pcvs-util)
 
 ;;;
@@ -169,7 +169,7 @@
   name
   type)
 
-(defsubst cvs-status-vl-to-str (vl) (mapconcat 'number-to-string vl "."))
+(defsubst cvs-status-vl-to-str (vl) (mapconcat #'number-to-string vl "."))
 
 (defun cvs-tag->string (tag)
   (if (stringp tag) tag
@@ -283,7 +283,7 @@ BEWARE:  because of stability issues, this is not a 
symmetric operation."
        tree1 (list (cons (cvs-tag-make (butlast vl2)) tree2)))))))))
 
 (defun cvs-tag-make-tag (tag)
-  (let ((vl (mapcar 'string-to-number (split-string (nth 2 tag) "\\."))))
+  (let ((vl (mapcar #'string-to-number (split-string (nth 2 tag) "\\."))))
     (cvs-tag-make vl (nth 0 tag) (intern (nth 1 tag)))))
 
 (defun cvs-tags->tree (tags)
@@ -450,10 +450,10 @@ Optional prefix ARG chooses between two representations."
          (tags nil)
          (cvs-tree-nomerge (if arg (not cvs-tree-nomerge) cvs-tree-nomerge)))
       (while (listp (setq tags (cvs-status-get-tags)))
-       (let ((tags (mapcar 'cvs-tag-make-tag tags))
+       (let ((tags (mapcar #'cvs-tag-make-tag tags))
              ;;(pt (save-excursion (forward-line -1) (point)))
              )
-         (setq tags (sort tags 'cvs-tag-lessp))
+         (setq tags (sort tags #'cvs-tag-lessp))
          (let* ((first (car tags))
                 (prev (if (cvs-tag-p first)
                           (list (car (cvs-tag->vlist first))) nil)))
@@ -472,7 +472,7 @@ Optional prefix ARG chooses between two representations."
                   (nprev (if (and cvs-tree-nomerge next
                                   (equal vlist (cvs-tag->vlist next)))
                              prev vlist)))
-             (cvs-map (lambda (v _p) v) nprev prev)))
+             (cl-mapcar (lambda (v _p) v) nprev prev)))
           (after (save-excursion
                   (newline)
                   (cvs-tree-tags-insert (cdr tags) nprev)))
@@ -484,7 +484,7 @@ Optional prefix ARG chooses between two representations."
                (as after (cdr as)))
          ((and (null as) (null vs) (null ps))
           (let ((revname (cvs-status-vl-to-str vlist)))
-            (if (cvs-every 'identity (cvs-map 'equal prev vlist))
+            (if (cl-every #'identity (cl-mapcar #'equal prev vlist))
                 (insert (make-string (+ 4 (length revname)) ? )
                         (or (cvs-tag->name tag) ""))
               (insert "  " revname ": " (or (cvs-tag->name tag) "")))))
@@ -500,7 +500,7 @@ Optional prefix ARG chooses between two representations."
                        (if next-eq (cons nil cvs-tree-char-space)
                          (cons t cvs-tree-char-eob))
                      (cons nil (if (and (eq (cvs-tag->type tag) 'branch)
-                                        (cvs-every 'null as))
+                                        (cl-every #'null as))
                                    cvs-tree-char-space
                                  cvs-tree-char-hbar))))))
            (insert (cdr na+char))
diff --git a/lisp/vc/diff-mode.el b/lisp/vc/diff-mode.el
index 7a47420..2c72c45 100644
--- a/lisp/vc/diff-mode.el
+++ b/lisp/vc/diff-mode.el
@@ -739,7 +739,7 @@ start and end positions."
   "Restrict the view to the current hunk.
 If the prefix ARG is given, restrict the view to the current file instead."
   (interactive "P")
-  (apply 'narrow-to-region
+  (apply #'narrow-to-region
         (if arg (diff-bounds-of-file) (diff-bounds-of-hunk)))
   (setq-local diff-narrowed-to (if arg 'file 'hunk)))
 
@@ -770,7 +770,7 @@ If the prefix ARG is given, restrict the view to the 
current file instead."
                        file-bounds
                      hunk-bounds))
            (inhibit-read-only t))
-      (apply 'kill-region bounds)
+      (apply #'kill-region bounds)
       (goto-char (car bounds))
       (ignore-errors (diff-beginning-of-hunk t)))))
 
@@ -828,7 +828,7 @@ data such as \"Index: ...\" and such."
       (error "No hunks")
     (diff-beginning-of-hunk t)
     (let ((inhibit-read-only t))
-      (apply 'kill-region (diff-bounds-of-file)))
+      (apply #'kill-region (diff-bounds-of-file)))
     (ignore-errors (diff-beginning-of-hunk t))))
 
 (defun diff-kill-junk ()
@@ -1810,7 +1810,7 @@ Whitespace differences are ignored."
        (if (> (- (car forw) orig) (- orig (car back))) back forw)
       (or back forw))))
 
-(define-obsolete-function-alias 'diff-xor 'xor "27.1")
+(define-obsolete-function-alias 'diff-xor #'xor "27.1")
 
 (defun diff-find-source-location (&optional other-file reverse noprompt)
   "Find current diff location within the source file.
@@ -1984,7 +1984,7 @@ With a prefix argument, try to REVERSE the hunk."
           (diff-hunk-kill)
         (diff-hunk-next)))))
 
-(defalias 'diff-mouse-goto-source 'diff-goto-source)
+(defalias 'diff-mouse-goto-source #'diff-goto-source)
 
 (defun diff-goto-source (&optional other-file event)
   "Jump to the corresponding source line.
@@ -2003,7 +2003,7 @@ revision of the file otherwise."
   (if event (posn-set-point (event-end event)))
   (let ((buffer (when event (current-buffer)))
         (reverse (not (save-excursion (beginning-of-line) (looking-at 
"[-<]")))))
-    (pcase-let ((`(,buf ,line-offset ,pos ,src ,_dst ,switched)
+    (pcase-let ((`(,buf ,_line-offset ,pos ,src ,_dst ,_switched)
                  (diff-find-source-location other-file reverse)))
       (pop-to-buffer buf)
       (goto-char (+ (car pos) (cdr src)))
@@ -2080,7 +2080,7 @@ For use in `add-log-current-defun-function'."
          (write-region (concat lead (car new)) nil file2 nil 'nomessage)
          (with-temp-buffer
            (let ((status
-                  (apply 'call-process
+                  (apply #'call-process
                          `(,diff-command nil t nil
                                         ,@opts ,file1 ,file2))))
              (pcase status
@@ -2826,7 +2826,7 @@ hunk text is not found in the source file."
 
 ;;; Support for converting a diff to diff3 markers via `wiggle'.
 
-;; Wiggle can be found at http://neil.brown.name/wiggle/ or in your nearest
+;; Wiggle can be found at https://neil.brown.name/wiggle/ or in your nearest
 ;; Debian repository.
 
 (defun diff-wiggle ()
diff --git a/lisp/vc/diff.el b/lisp/vc/diff.el
index 7c4931b..7bb1151 100644
--- a/lisp/vc/diff.el
+++ b/lisp/vc/diff.el
@@ -45,14 +45,12 @@ This variable is also used in the `vc-diff' command (and 
related
 commands) if the backend-specific diff switch variable isn't
 set (`vc-git-diff-switches' for git, for instance), and
 `vc-diff-switches' isn't set."
-  :type '(choice string (repeat string))
-  :group 'diff)
+  :type '(choice string (repeat string)))
 
 ;;;###autoload
 (defcustom diff-command (purecopy "diff")
   "The command to use to run diff."
-  :type 'string
-  :group 'diff)
+  :type 'string)
 
 ;; prompt if prefix arg present
 (defun diff-switches ()
@@ -60,7 +58,7 @@ set (`vc-git-diff-switches' for git, for instance), and
       (read-string "Diff switches: "
                   (if (stringp diff-switches)
                       diff-switches
-                    (mapconcat 'identity diff-switches " ")))))
+                    (mapconcat #'identity diff-switches " ")))))
 
 (defun diff-sentinel (code &optional old-temp-file new-temp-file)
   "Code run when the diff process exits.
@@ -165,7 +163,7 @@ returns the buffer used."
   (let* ((old-alt (diff-file-local-copy old))
         (new-alt (diff-file-local-copy new))
         (command
-         (mapconcat 'identity
+         (mapconcat #'identity
                     `(,diff-command
                       ;; Use explicitly specified switches
                       ,@switches
@@ -200,7 +198,7 @@ returns the buffer used."
       (if (and (not no-async) (fboundp 'make-process))
          (let ((proc (start-process "Diff" buf shell-file-name
                                      shell-command-switch command)))
-           (set-process-filter proc 'diff-process-filter)
+           (set-process-filter proc #'diff-process-filter)
             (set-process-sentinel
              proc (lambda (proc _msg)
                     (with-current-buffer (process-buffer proc)
diff --git a/lisp/vc/ediff-diff.el b/lisp/vc/ediff-diff.el
index fde9d43..b93dfc8 100644
--- a/lisp/vc/ediff-diff.el
+++ b/lisp/vc/ediff-diff.el
@@ -87,7 +87,7 @@ options after the default ones.
 This variable is not for customizing the look of the differences produced by
 the command \\[ediff-show-diff-output]. Use the variable
 `ediff-custom-diff-options' for that."
-  :set 'ediff-set-diff-options
+  :set #'ediff-set-diff-options
   :type 'string)
 
 (ediff-defvar-local ediff-ignore-case nil
diff --git a/lisp/vc/ediff-help.el b/lisp/vc/ediff-help.el
index 84bf063..a5bb953 100644
--- a/lisp/vc/ediff-help.el
+++ b/lisp/vc/ediff-help.el
@@ -156,7 +156,7 @@ the value of this variable and the variables 
`ediff-help-message-*' in
 ;; the keymap that defines clicks over the quick help regions
 (defvar ediff-help-region-map (make-sparse-keymap))
 
-(define-key ediff-help-region-map [mouse-2] 'ediff-help-for-quick-help)
+(define-key ediff-help-region-map [mouse-2] #'ediff-help-for-quick-help)
 
 ;; runs in the control buffer
 (defun ediff-set-help-overlays ()
diff --git a/lisp/vc/ediff-init.el b/lisp/vc/ediff-init.el
index 6e65816..17c4202 100644
--- a/lisp/vc/ediff-init.el
+++ b/lisp/vc/ediff-init.el
@@ -25,6 +25,7 @@
 ;;; Code:
 
 (require 'cl-lib)
+(require 'ediff-util)
 
 ;; Start compiler pacifier
 (defvar ediff-metajob-name)
@@ -980,8 +981,10 @@ this variable represents.")
 (defface ediff-even-diff-A
   `((((type pc))
      (:foreground "green3" :background "light grey" :extend t))
-    (((class color) (min-colors 88))
-     (:background "light grey" :extend t))
+    (((class color) (min-colors 88) (background light))
+     (:distant-foreground "Black" :background "light grey" :extend t))
+    (((class color) (min-colors 88) (background dark))
+     (:distant-foreground "White" :background "dark grey" :extend t))
     (((class color) (min-colors 16))
      (:foreground "Black" :background "light grey" :extend t))
     (((class color))
@@ -999,8 +1002,10 @@ widget to customize the actual face object 
`ediff-even-diff-A'
 this variable represents.")
 
 (defface ediff-even-diff-B
-  `((((class color) (min-colors 88))
-     (:background "Grey" :extend t))
+  `((((class color) (min-colors 88) (background light))
+     (:distant-foreground "Black" :background "Grey" :extend t))
+    (((class color) (min-colors 88) (background dark))
+     (:distant-foreground "White" :background "dim grey" :extend t))
     (((class color) (min-colors 16))
      (:foreground "White" :background "Grey" :extend t))
     (((class color))
@@ -1019,8 +1024,10 @@ this variable represents.")
 (defface ediff-even-diff-C
   `((((type pc))
      (:foreground "yellow3" :background "light grey" :extend t))
-    (((class color) (min-colors 88))
-     (:background "light grey" :extend t))
+    (((class color) (min-colors 88) (background light))
+     (:distant-foreground "Black" :background "light grey" :extend t))
+    (((class color) (min-colors 88) (background dark))
+     (:distant-foreground "White" :background "dark grey" :extend t))
     (((class color) (min-colors 16))
      (:foreground "Black" :background "light grey" :extend t))
     (((class color))
@@ -1040,8 +1047,10 @@ this variable represents.")
 (defface ediff-even-diff-Ancestor
   `((((type pc))
      (:foreground "cyan3" :background "light grey" :extend t))
-    (((class color) (min-colors 88))
-     (:background "Grey" :extend t))
+    (((class color) (min-colors 88) (background light))
+     (:distant-foreground "Black" :background "Grey" :extend t))
+    (((class color) (min-colors 88) (background dark))
+     (:distant-foreground "White" :background "dim grey" :extend t))
     (((class color) (min-colors 16))
      (:foreground "White" :background "Grey" :extend t))
     (((class color))
@@ -1068,8 +1077,10 @@ this variable represents.")
 (defface ediff-odd-diff-A
   '((((type pc))
      (:foreground "green3" :background "gray40" :extend t))
-    (((class color) (min-colors 88))
-     (:background "Grey" :extend t))
+    (((class color) (min-colors 88) (background light))
+     (:distant-foreground "Black" :background "Grey" :extend t))
+    (((class color) (min-colors 88) (background dark))
+     (:distant-foreground "White" :background "dim grey" :extend t))
     (((class color) (min-colors 16))
      (:foreground "White" :background "Grey" :extend t))
     (((class color))
@@ -1088,8 +1099,10 @@ this variable represents.")
 (defface ediff-odd-diff-B
   '((((type pc))
      (:foreground "White" :background "gray40" :extend t))
-    (((class color) (min-colors 88))
-     (:background "light grey" :extend t))
+    (((class color) (min-colors 88) (background light))
+     (:distant-foreground "Black" :background "light grey" :extend t))
+    (((class color) (min-colors 88) (background dark))
+     (:distant-foreground "White" :background "dark grey" :extend t))
     (((class color) (min-colors 16))
      (:foreground "Black" :background "light grey" :extend t))
     (((class color))
@@ -1108,8 +1121,10 @@ this variable represents.")
 (defface ediff-odd-diff-C
   '((((type pc))
      (:foreground "yellow3" :background "gray40" :extend t))
-    (((class color) (min-colors 88))
-     (:background "Grey" :extend t))
+    (((class color) (min-colors 88) (background light))
+     (:distant-foreground "Black" :background "Grey" :extend t))
+    (((class color) (min-colors 88) (background dark))
+     (:distant-foreground "White" :background "dim grey" :extend t))
     (((class color) (min-colors 16))
      (:foreground "White" :background "Grey" :extend t))
     (((class color))
@@ -1167,8 +1182,8 @@ this variable represents.")
 (put ediff-fine-diff-face-Ancestor 'ediff-help-echo
      "A `refinement' of the current difference region")
 
-(add-hook 'ediff-quit-hook 'ediff-cleanup-mess)
-(add-hook 'ediff-suspend-hook 'ediff-default-suspend-function)
+(add-hook 'ediff-quit-hook #'ediff-cleanup-mess)
+(add-hook 'ediff-suspend-hook #'ediff-default-suspend-function)
 
 
 ;;; Overlays
@@ -1298,7 +1313,8 @@ This default should work without changes."
 (defun ediff-paint-background-regions-in-one-buffer (buf-type unhighlight)
   (let ((diff-vector
         (eval (ediff-get-symbol-from-alist
-               buf-type ediff-difference-vector-alist)))
+               buf-type ediff-difference-vector-alist)
+              t))
        overl diff-num)
     (mapcar (lambda (rec)
              (setq overl (ediff-get-diff-overlay-from-diff-record rec)
diff --git a/lisp/vc/ediff-merg.el b/lisp/vc/ediff-merg.el
index 826cad9..ad4ef47 100644
--- a/lisp/vc/ediff-merg.el
+++ b/lisp/vc/ediff-merg.el
@@ -194,7 +194,7 @@ Buffer B."
 
 (defun ediff-set-merge-mode ()
   (normal-mode t)
-  (remove-hook 'write-file-functions 'ediff-set-merge-mode t))
+  (remove-hook 'write-file-functions #'ediff-set-merge-mode t))
 
 
 ;; Go over all diffs starting with DIFF-NUM and copy regions into buffer C
diff --git a/lisp/vc/ediff-mult.el b/lisp/vc/ediff-mult.el
index d32c18b..49b2890 100644
--- a/lisp/vc/ediff-mult.el
+++ b/lisp/vc/ediff-mult.el
@@ -147,15 +147,15 @@ Useful commands (type ? to hide them and free up screen):
 (defvar ediff-dir-diffs-buffer-map
   (let ((map (make-sparse-keymap)))
     (suppress-keymap map)
-    (define-key map "q" 'ediff-bury-dir-diffs-buffer)
-    (define-key map " " 'next-line)
-    (define-key map "n" 'next-line)
-    (define-key map "\C-?" 'previous-line)
-    (define-key map "p" 'previous-line)
-    (define-key map "C" 'ediff-dir-diff-copy-file)
-    (define-key map  [mouse-2] 'ediff-dir-diff-copy-file)
-    (define-key map [delete] 'previous-line)
-    (define-key map [backspace] 'previous-line)
+    (define-key map "q" #'ediff-bury-dir-diffs-buffer)
+    (define-key map " " #'next-line)
+    (define-key map "n" #'next-line)
+    (define-key map "\C-?" #'previous-line)
+    (define-key map "p" #'previous-line)
+    (define-key map "C" #'ediff-dir-diff-copy-file)
+    (define-key map  [mouse-2] #'ediff-dir-diff-copy-file)
+    (define-key map [delete] #'previous-line)
+    (define-key map [backspace] #'previous-line)
     map)
   "The keymap to be installed in the buffer showing differences between
 directories.")
@@ -413,12 +413,11 @@ Toggled by ediff-toggle-verbose-help-meta-buffer" )
       '(menu-item "Show Manual" ediff-documentation
                  :help "Display Ediff's manual"))
 
-    (or (ediff-one-filegroup-metajob)
-       (progn
-         (define-key ediff-meta-buffer-map "=" nil)
-         (define-key ediff-meta-buffer-map "==" 'ediff-meta-mark-equal-files)
-         (define-key ediff-meta-buffer-map "=m" 'ediff-meta-mark-equal-files)
-         (define-key ediff-meta-buffer-map "=h" 'ediff-meta-mark-equal-files)))
+    (unless (ediff-one-filegroup-metajob)
+      (define-key ediff-meta-buffer-map "=" nil)
+      (define-key ediff-meta-buffer-map "==" #'ediff-meta-mark-equal-files)
+      (define-key ediff-meta-buffer-map "=m" #'ediff-meta-mark-equal-files)
+      (define-key ediff-meta-buffer-map "=h" #'ediff-meta-mark-equal-files))
 
 
     (define-key menu-map [ediff-next-meta-item]
@@ -430,7 +429,7 @@ Toggled by ediff-toggle-verbose-help-meta-buffer" )
 
 
   (if ediff-no-emacs-help-in-control-buffer
-      (define-key ediff-meta-buffer-map  "\C-h"  'ediff-previous-meta-item))
+      (define-key ediff-meta-buffer-map  "\C-h"  #'ediff-previous-meta-item))
   (define-key ediff-meta-buffer-map [mouse-2] ediff-meta-action-function)
 
   (use-local-map ediff-meta-buffer-map)
@@ -633,7 +632,7 @@ behavior."
          difflist (delete "."  difflist)
          ;; copying is needed because sort sorts via side effects
          difflist (sort (ediff-copy-list (delete ".." difflist))
-                        'string-lessp))
+                        #'string-lessp))
 
     (setq difflist (mapcar (lambda (elt) (cons elt 1)) difflist))
 
@@ -837,14 +836,14 @@ behavior."
                (ediff-draw-dir-diffs ediff-dir-difference-list))
            (define-key
              ediff-meta-buffer-map "h" 'ediff-mark-for-hiding-at-pos)
-           (define-key ediff-meta-buffer-map "x" 'ediff-hide-marked-sessions)
+           (define-key ediff-meta-buffer-map "x" #'ediff-hide-marked-sessions)
            (define-key
-             ediff-meta-buffer-map "m" 'ediff-mark-for-operation-at-pos)
+             ediff-meta-buffer-map "m" #'ediff-mark-for-operation-at-pos)
            (define-key ediff-meta-buffer-map "u" nil)
            (define-key
-             ediff-meta-buffer-map "um" 'ediff-unmark-all-for-operation)
+             ediff-meta-buffer-map "um" #'ediff-unmark-all-for-operation)
            (define-key
-             ediff-meta-buffer-map "uh" 'ediff-unmark-all-for-hiding)
+             ediff-meta-buffer-map "uh" #'ediff-unmark-all-for-hiding)
 
            (define-key ediff-meta-buffer-map
              [menu-bar ediff-meta-mode ediff-hide-marked-sessions]
@@ -877,7 +876,7 @@ behavior."
                     '(menu-item "Collect diffs" ediff-collect-custom-diffs
                                 :help "Collect custom diffs of marked sessions 
in buffer `*Ediff Multifile Diffs*'"))
                   (define-key
-                    ediff-meta-buffer-map "P" 'ediff-collect-custom-diffs))
+                    ediff-meta-buffer-map "P" #'ediff-collect-custom-diffs))
                  ((ediff-patch-metajob jobname)
                   (define-key ediff-meta-buffer-map
                     [menu-bar ediff-meta-mode ediff-meta-show-patch]
@@ -885,8 +884,8 @@ behavior."
                                 :help "Show the multi-file patch associated 
with this group session"))
                   (define-key
                     ediff-meta-buffer-map "P" 'ediff-meta-show-patch)))
-           (define-key ediff-meta-buffer-map "^" 'ediff-up-meta-hierarchy)
-           (define-key ediff-meta-buffer-map "D" 'ediff-show-dir-diffs)
+           (define-key ediff-meta-buffer-map "^" #'ediff-up-meta-hierarchy)
+           (define-key ediff-meta-buffer-map "D" #'ediff-show-dir-diffs)
 
            (define-key ediff-meta-buffer-map
              [menu-bar ediff-meta-mode ediff-up-meta-hierarchy]
@@ -2128,7 +2127,7 @@ all marked sessions must be active."
     ))
 
 ;;;###autoload
-(defalias 'eregistry 'ediff-show-registry)
+(defalias 'eregistry #'ediff-show-registry)
 
 ;; If meta-buf doesn't exist, it is created.  In that case, id doesn't have a
 ;; parent meta-buf
diff --git a/lisp/vc/ediff-util.el b/lisp/vc/ediff-util.el
index 9909dcd..fc6dcf6 100644
--- a/lisp/vc/ediff-util.el
+++ b/lisp/vc/ediff-util.el
@@ -123,106 +123,106 @@ to invocation.")
   (setq ediff-mode-map (make-sparse-keymap))
   (suppress-keymap ediff-mode-map)
 
-  (define-key ediff-mode-map [mouse-2] 'ediff-help-for-quick-help)
-  (define-key ediff-mode-map "\C-m"  'ediff-help-for-quick-help)
+  (define-key ediff-mode-map [mouse-2] #'ediff-help-for-quick-help)
+  (define-key ediff-mode-map "\C-m"  #'ediff-help-for-quick-help)
 
-  (define-key ediff-mode-map "p" 'ediff-previous-difference)
-  (define-key ediff-mode-map "\C-?" 'ediff-previous-difference)
-  (define-key ediff-mode-map [delete] 'ediff-previous-difference)
+  (define-key ediff-mode-map "p" #'ediff-previous-difference)
+  (define-key ediff-mode-map "\C-?" #'ediff-previous-difference)
+  (define-key ediff-mode-map [delete] #'ediff-previous-difference)
   (define-key ediff-mode-map "\C-h" (if ediff-no-emacs-help-in-control-buffer
-                                       'ediff-previous-difference nil))
-  (define-key ediff-mode-map [backspace] 'ediff-previous-difference)
-  (define-key ediff-mode-map [?\S-\ ] 'ediff-previous-difference)
-  (define-key ediff-mode-map "n" 'ediff-next-difference)
-  (define-key ediff-mode-map " " 'ediff-next-difference)
-  (define-key ediff-mode-map "j" 'ediff-jump-to-difference)
+                                       #'ediff-previous-difference nil))
+  (define-key ediff-mode-map [backspace] #'ediff-previous-difference)
+  (define-key ediff-mode-map [?\S-\ ] #'ediff-previous-difference)
+  (define-key ediff-mode-map "n" #'ediff-next-difference)
+  (define-key ediff-mode-map " " #'ediff-next-difference)
+  (define-key ediff-mode-map "j" #'ediff-jump-to-difference)
   (define-key ediff-mode-map "g"  nil)
-  (define-key ediff-mode-map "ga" 'ediff-jump-to-difference-at-point)
-  (define-key ediff-mode-map "gb" 'ediff-jump-to-difference-at-point)
-  (define-key ediff-mode-map "q" 'ediff-quit)
-  (define-key ediff-mode-map "D" 'ediff-show-diff-output)
-  (define-key ediff-mode-map "z" 'ediff-suspend)
-  (define-key ediff-mode-map "\C-l" 'ediff-recenter)
-  (define-key ediff-mode-map "|" 'ediff-toggle-split)
-  (define-key ediff-mode-map "h" 'ediff-toggle-hilit)
+  (define-key ediff-mode-map "ga" #'ediff-jump-to-difference-at-point)
+  (define-key ediff-mode-map "gb" #'ediff-jump-to-difference-at-point)
+  (define-key ediff-mode-map "q" #'ediff-quit)
+  (define-key ediff-mode-map "D" #'ediff-show-diff-output)
+  (define-key ediff-mode-map "z" #'ediff-suspend)
+  (define-key ediff-mode-map "\C-l" #'ediff-recenter)
+  (define-key ediff-mode-map "|" #'ediff-toggle-split)
+  (define-key ediff-mode-map "h" #'ediff-toggle-hilit)
   (or ediff-word-mode
-      (define-key ediff-mode-map "@" 'ediff-toggle-autorefine))
+      (define-key ediff-mode-map "@" #'ediff-toggle-autorefine))
   (if ediff-narrow-job
-      (define-key ediff-mode-map "%" 'ediff-toggle-narrow-region))
-  (define-key ediff-mode-map "~" 'ediff-swap-buffers)
-  (define-key ediff-mode-map "v" 'ediff-scroll-vertically)
-  (define-key ediff-mode-map "\C-v" 'ediff-scroll-vertically)
-  (define-key ediff-mode-map "^" 'ediff-scroll-vertically)
-  (define-key ediff-mode-map "\M-v" 'ediff-scroll-vertically)
-  (define-key ediff-mode-map "V" 'ediff-scroll-vertically)
-  (define-key ediff-mode-map "<" 'ediff-scroll-horizontally)
-  (define-key ediff-mode-map ">" 'ediff-scroll-horizontally)
-  (define-key ediff-mode-map "i" 'ediff-status-info)
-  (define-key ediff-mode-map "E" 'ediff-documentation)
-  (define-key ediff-mode-map "?" 'ediff-toggle-help)
-  (define-key ediff-mode-map "!" 'ediff-update-diffs)
-  (define-key ediff-mode-map "M" 'ediff-show-current-session-meta-buffer)
-  (define-key ediff-mode-map "R" 'ediff-show-registry)
+      (define-key ediff-mode-map "%" #'ediff-toggle-narrow-region))
+  (define-key ediff-mode-map "~" #'ediff-swap-buffers)
+  (define-key ediff-mode-map "v" #'ediff-scroll-vertically)
+  (define-key ediff-mode-map "\C-v" #'ediff-scroll-vertically)
+  (define-key ediff-mode-map "^" #'ediff-scroll-vertically)
+  (define-key ediff-mode-map "\M-v" #'ediff-scroll-vertically)
+  (define-key ediff-mode-map "V" #'ediff-scroll-vertically)
+  (define-key ediff-mode-map "<" #'ediff-scroll-horizontally)
+  (define-key ediff-mode-map ">" #'ediff-scroll-horizontally)
+  (define-key ediff-mode-map "i" #'ediff-status-info)
+  (define-key ediff-mode-map "E" #'ediff-documentation)
+  (define-key ediff-mode-map "?" #'ediff-toggle-help)
+  (define-key ediff-mode-map "!" #'ediff-update-diffs)
+  (define-key ediff-mode-map "M" #'ediff-show-current-session-meta-buffer)
+  (define-key ediff-mode-map "R" #'ediff-show-registry)
   (or ediff-word-mode
-      (define-key ediff-mode-map "*" 'ediff-make-or-kill-fine-diffs))
+      (define-key ediff-mode-map "*" #'ediff-make-or-kill-fine-diffs))
   (define-key ediff-mode-map "a"  nil)
   (define-key ediff-mode-map "b"  nil)
   (define-key ediff-mode-map "r"  nil)
   (cond (ediff-merge-job
         ;; Will barf if no ancestor
-        (define-key ediff-mode-map "/" 'ediff-toggle-show-ancestor)
+        (define-key ediff-mode-map "/" #'ediff-toggle-show-ancestor)
         ;; In merging, we allow only A->C and B->C copying.
-        (define-key ediff-mode-map "a" 'ediff-copy-A-to-C)
-        (define-key ediff-mode-map "b" 'ediff-copy-B-to-C)
-        (define-key ediff-mode-map "r" 'ediff-restore-diff-in-merge-buffer)
-        (define-key ediff-mode-map "s" 'ediff-shrink-window-C)
-        (define-key ediff-mode-map "+" 'ediff-combine-diffs)
+        (define-key ediff-mode-map "a" #'ediff-copy-A-to-C)
+        (define-key ediff-mode-map "b" #'ediff-copy-B-to-C)
+        (define-key ediff-mode-map "r" #'ediff-restore-diff-in-merge-buffer)
+        (define-key ediff-mode-map "s" #'ediff-shrink-window-C)
+        (define-key ediff-mode-map "+" #'ediff-combine-diffs)
         (define-key ediff-mode-map "$"  nil)
-        (define-key ediff-mode-map "$$" 'ediff-toggle-show-clashes-only)
-        (define-key ediff-mode-map "$*" 'ediff-toggle-skip-changed-regions)
-        (define-key ediff-mode-map "&" 'ediff-re-merge))
+        (define-key ediff-mode-map "$$" #'ediff-toggle-show-clashes-only)
+        (define-key ediff-mode-map "$*" #'ediff-toggle-skip-changed-regions)
+        (define-key ediff-mode-map "&"  #'ediff-re-merge))
        (ediff-3way-comparison-job
-        (define-key ediff-mode-map "ab" 'ediff-copy-A-to-B)
-        (define-key ediff-mode-map "ba" 'ediff-copy-B-to-A)
-        (define-key ediff-mode-map "ac" 'ediff-copy-A-to-C)
-        (define-key ediff-mode-map "bc" 'ediff-copy-B-to-C)
+        (define-key ediff-mode-map "ab" #'ediff-copy-A-to-B)
+        (define-key ediff-mode-map "ba" #'ediff-copy-B-to-A)
+        (define-key ediff-mode-map "ac" #'ediff-copy-A-to-C)
+        (define-key ediff-mode-map "bc" #'ediff-copy-B-to-C)
         (define-key ediff-mode-map "c" nil)
-        (define-key ediff-mode-map "ca" 'ediff-copy-C-to-A)
-        (define-key ediff-mode-map "cb" 'ediff-copy-C-to-B)
-        (define-key ediff-mode-map "ra" 'ediff-restore-diff)
-        (define-key ediff-mode-map "rb" 'ediff-restore-diff)
-        (define-key ediff-mode-map "rc" 'ediff-restore-diff)
-        (define-key ediff-mode-map "C"  'ediff-toggle-read-only))
+        (define-key ediff-mode-map "ca" #'ediff-copy-C-to-A)
+        (define-key ediff-mode-map "cb" #'ediff-copy-C-to-B)
+        (define-key ediff-mode-map "ra" #'ediff-restore-diff)
+        (define-key ediff-mode-map "rb" #'ediff-restore-diff)
+        (define-key ediff-mode-map "rc" #'ediff-restore-diff)
+        (define-key ediff-mode-map "C"  #'ediff-toggle-read-only))
        (t ; 2-way comparison
-        (define-key ediff-mode-map "a"  'ediff-copy-A-to-B)
-        (define-key ediff-mode-map "b"  'ediff-copy-B-to-A)
-        (define-key ediff-mode-map "ra" 'ediff-restore-diff)
-        (define-key ediff-mode-map "rb" 'ediff-restore-diff))
+        (define-key ediff-mode-map "a"  #'ediff-copy-A-to-B)
+        (define-key ediff-mode-map "b"  #'ediff-copy-B-to-A)
+        (define-key ediff-mode-map "ra" #'ediff-restore-diff)
+        (define-key ediff-mode-map "rb" #'ediff-restore-diff))
        ) ; cond
-  (define-key ediff-mode-map "G" 'ediff-submit-report)
+  (define-key ediff-mode-map "G" #'ediff-submit-report)
   (define-key ediff-mode-map "#"  nil)
-  (define-key ediff-mode-map "#h"  'ediff-toggle-regexp-match)
-  (define-key ediff-mode-map "#f"  'ediff-toggle-regexp-match)
-  (define-key ediff-mode-map "#c"  'ediff-toggle-ignore-case)
+  (define-key ediff-mode-map "#h"  #'ediff-toggle-regexp-match)
+  (define-key ediff-mode-map "#f"  #'ediff-toggle-regexp-match)
+  (define-key ediff-mode-map "#c"  #'ediff-toggle-ignore-case)
   (or ediff-word-mode
-      (define-key ediff-mode-map "##"  'ediff-toggle-skip-similar))
+      (define-key ediff-mode-map "##"  #'ediff-toggle-skip-similar))
   (define-key ediff-mode-map "o"   nil)
-  (define-key ediff-mode-map "A"  'ediff-toggle-read-only)
-  (define-key ediff-mode-map "B"  'ediff-toggle-read-only)
+  (define-key ediff-mode-map "A"  #'ediff-toggle-read-only)
+  (define-key ediff-mode-map "B"  #'ediff-toggle-read-only)
   (define-key ediff-mode-map "w"   nil)
-  (define-key ediff-mode-map "wa"  'ediff-save-buffer)
-  (define-key ediff-mode-map "wb"  'ediff-save-buffer)
-  (define-key ediff-mode-map "wd"  'ediff-save-buffer)
-  (define-key ediff-mode-map "="   'ediff-inferior-compare-regions)
+  (define-key ediff-mode-map "wa"  #'ediff-save-buffer)
+  (define-key ediff-mode-map "wb"  #'ediff-save-buffer)
+  (define-key ediff-mode-map "wd"  #'ediff-save-buffer)
+  (define-key ediff-mode-map "="   #'ediff-inferior-compare-regions)
   (if (and (fboundp 'ediff-show-patch-diagnostics) (ediff-patch-job))
-      (define-key ediff-mode-map "P"  'ediff-show-patch-diagnostics))
+      (define-key ediff-mode-map "P"  #'ediff-show-patch-diagnostics))
   (if ediff-3way-job
       (progn
-       (define-key ediff-mode-map "wc" 'ediff-save-buffer)
-       (define-key ediff-mode-map "gc" 'ediff-jump-to-difference-at-point)
+       (define-key ediff-mode-map "wc" #'ediff-save-buffer)
+       (define-key ediff-mode-map "gc" #'ediff-jump-to-difference-at-point)
        ))
 
-  (define-key ediff-mode-map "m" 'ediff-toggle-wide-display)
+  (define-key ediff-mode-map "m" #'ediff-toggle-wide-display)
 
   ;; Allow ediff-mode-map to be referenced indirectly
   (fset 'ediff-mode-map ediff-mode-map)
diff --git a/lisp/vc/ediff-vers.el b/lisp/vc/ediff-vers.el
index 13a653b..9e82392 100644
--- a/lisp/vc/ediff-vers.el
+++ b/lisp/vc/ediff-vers.el
@@ -24,23 +24,9 @@
 
 ;;; Code:
 
-;; Compiler pacifier
-(defvar rcs-default-co-switches)
+(eval-when-compile (require 'ediff-init))
 
-(and noninteractive
-     (eval-when-compile
-       (condition-case nil
-          ;; for compatibility with current stable version of xemacs
-          (progn
-            ;;(require 'pcvs nil 'noerror)
-            ;;(require 'rcs nil 'noerror)
-            (require 'pcvs)
-            (require 'rcs))
-        (error nil))
-       (require 'vc)
-       (require 'ediff-init)
-       ))
-;; end pacifier
+(defvar rcs-default-co-switches)
 
 (defcustom ediff-keep-tmp-versions nil
   "If t, do not delete temporary previous versions for the files on which
diff --git a/lisp/vc/ediff-wind.el b/lisp/vc/ediff-wind.el
index 47ef37a..fc6ea94 100644
--- a/lisp/vc/ediff-wind.el
+++ b/lisp/vc/ediff-wind.el
@@ -1043,8 +1043,8 @@ create a new splittable frame if none is found."
   (with-current-buffer ctl-buffer
     (let* ((frame-A (window-frame ediff-window-A))
           (frame-A-parameters (frame-parameters frame-A))
-          (frame-A-top (eval (cdr (assoc 'top frame-A-parameters))))
-          (frame-A-left (eval (cdr (assoc 'left frame-A-parameters))))
+          (frame-A-top (eval (cdr (assoc 'top frame-A-parameters)) t))
+          (frame-A-left (eval (cdr (assoc 'left frame-A-parameters)) t))
           (frame-A-width (frame-width frame-A))
           (ctl-frame ediff-control-frame)
           horizontal-adjustment upward-adjustment
@@ -1105,7 +1105,7 @@ It assumes that it is called from within the control 
buffer."
         (cw (frame-char-width frame-A))
         (wd (- (/ (display-pixel-width) cw) 5)))
     (setq ediff-wide-display-orig-parameters
-         (list (cons 'left (max 0 (eval (cdr (assoc 'left frame-A-params)))))
+         (list (cons 'left (max 0 (eval (cdr (assoc 'left frame-A-params)) t)))
                (cons 'width (cdr (assoc 'width frame-A-params))))
          ediff-wide-display-frame frame-A)
     (modify-frame-parameters
diff --git a/lisp/vc/ediff.el b/lisp/vc/ediff.el
index ed375738..3536cbf 100644
--- a/lisp/vc/ediff.el
+++ b/lisp/vc/ediff.el
@@ -264,7 +264,7 @@ arguments after setting up the Ediff buffers."
                        'ediff-files3))
 
 ;;;###autoload
-(defalias 'ediff3 'ediff-files3)
+(defalias 'ediff3 #'ediff-files3)
 
 (defvar-local ediff--magic-file-name nil
   "Name of file where buffer's content was saved.
@@ -359,7 +359,7 @@ has been saved (if not in `buffer-file-name')."
 (declare-function diff-latest-backup-file "diff" (fn))
 
 ;;;###autoload
-(defalias 'ediff 'ediff-files)
+(defalias 'ediff #'ediff-files)
 
 ;;;###autoload
 (defun ediff-current-file ()
@@ -442,7 +442,7 @@ symbol describing the Ediff job type; it defaults to
   (ediff-buffers-internal buffer-A buffer-B nil startup-hooks job-name))
 
 ;;;###autoload
-(defalias 'ebuffers 'ediff-buffers)
+(defalias 'ebuffers #'ediff-buffers)
 
 
 ;;;###autoload
@@ -479,7 +479,7 @@ symbol describing the Ediff job type; it defaults to
   (ediff-buffers-internal buffer-A buffer-B buffer-C startup-hooks job-name))
 
 ;;;###autoload
-(defalias 'ebuffers3 'ediff-buffers3)
+(defalias 'ebuffers3 #'ediff-buffers3)
 
 
 
@@ -556,7 +556,7 @@ the same name in both.  The third argument, REGEXP, is nil 
or a regular
 expression; only file names that match the regexp are considered."
   (interactive
    (let ((dir-A (ediff-get-default-directory-name))
-        (default-regexp (eval ediff-default-filtering-regexp))
+        (default-regexp (eval ediff-default-filtering-regexp t))
         f)
      (list (setq f (read-directory-name
                    "Directory A to compare: " dir-A nil 'must-match))
@@ -570,14 +570,14 @@ expression; only file names that match the regexp are 
considered."
                           default-regexp)
            nil
            'ediff-filtering-regexp-history
-           (eval ediff-default-filtering-regexp))
+           (eval ediff-default-filtering-regexp t))
           )))
   (ediff-directories-internal
    dir1 dir2 nil regexp #'ediff-files 'ediff-directories
    ))
 
 ;;;###autoload
-(defalias 'edirs 'ediff-directories)
+(defalias 'edirs #'ediff-directories)
 
 
 ;;;###autoload
@@ -587,7 +587,7 @@ The second argument, REGEXP, is a regular expression that 
filters the file
 names.  Only the files that are under revision control are taken into account."
   (interactive
    (let ((dir-A (ediff-get-default-directory-name))
-        (default-regexp (eval ediff-default-filtering-regexp))
+        (default-regexp (eval ediff-default-filtering-regexp t))
         )
      (list (read-directory-name
            "Directory to compare with revision:" dir-A nil 'must-match)
@@ -596,14 +596,14 @@ names.  Only the files that are under revision control 
are taken into account."
              "Filter filenames through regular expression" default-regexp)
            nil
            'ediff-filtering-regexp-history
-           (eval ediff-default-filtering-regexp))
+           (eval ediff-default-filtering-regexp t))
           )))
   (ediff-directory-revisions-internal
-   dir1 regexp 'ediff-revision 'ediff-directory-revisions
+   dir1 regexp #'ediff-revision 'ediff-directory-revisions
    ))
 
 ;;;###autoload
-(defalias 'edir-revisions 'ediff-directory-revisions)
+(defalias 'edir-revisions #'ediff-directory-revisions)
 
 
 ;;;###autoload
@@ -614,7 +614,7 @@ regular expression; only file names that match the regexp 
are considered."
 
   (interactive
    (let ((dir-A (ediff-get-default-directory-name))
-        (default-regexp (eval ediff-default-filtering-regexp))
+        (default-regexp (eval ediff-default-filtering-regexp t))
         f)
      (list (setq f (read-directory-name "Directory A to compare:" dir-A nil))
           (setq f (read-directory-name "Directory B to compare:"
@@ -632,14 +632,14 @@ regular expression; only file names that match the regexp 
are considered."
                           default-regexp)
            nil
            'ediff-filtering-regexp-history
-           (eval ediff-default-filtering-regexp))
+           (eval ediff-default-filtering-regexp t))
           )))
   (ediff-directories-internal
    dir1 dir2 dir3 regexp #'ediff-files3 'ediff-directories3
    ))
 
 ;;;###autoload
-(defalias 'edirs3 'ediff-directories3)
+(defalias 'edirs3 #'ediff-directories3)
 
 ;;;###autoload
 (defun ediff-merge-directories (dir1 dir2 regexp &optional merge-autostore-dir)
@@ -649,7 +649,7 @@ expression; only file names that match the regexp are 
considered.
 MERGE-AUTOSTORE-DIR is the directory in which to store merged files."
   (interactive
    (let ((dir-A (ediff-get-default-directory-name))
-        (default-regexp (eval ediff-default-filtering-regexp))
+        (default-regexp (eval ediff-default-filtering-regexp t))
         f)
      (list (setq f (read-directory-name "Directory A to merge:"
                                        dir-A nil 'must-match))
@@ -663,7 +663,7 @@ MERGE-AUTOSTORE-DIR is the directory in which to store 
merged files."
                           default-regexp)
            nil
            'ediff-filtering-regexp-history
-           (eval ediff-default-filtering-regexp))
+           (eval ediff-default-filtering-regexp t))
           )))
   (ediff-directories-internal
    dir1 dir2 nil regexp #'ediff-merge-files 'ediff-merge-directories
@@ -671,7 +671,7 @@ MERGE-AUTOSTORE-DIR is the directory in which to store 
merged files."
    ))
 
 ;;;###autoload
-(defalias 'edirs-merge 'ediff-merge-directories)
+(defalias 'edirs-merge #'ediff-merge-directories)
 
 ;;;###autoload
 (defun ediff-merge-directories-with-ancestor (dir1 dir2 ancestor-dir regexp
@@ -685,7 +685,7 @@ only file names that match the regexp are considered.
 MERGE-AUTOSTORE-DIR is the directory in which to store merged files."
   (interactive
    (let ((dir-A (ediff-get-default-directory-name))
-        (default-regexp (eval ediff-default-filtering-regexp))
+        (default-regexp (eval ediff-default-filtering-regexp t))
         f)
      (list (setq f (read-directory-name "Directory A to merge:" dir-A nil))
           (setq f (read-directory-name "Directory B to merge:"
@@ -703,7 +703,7 @@ MERGE-AUTOSTORE-DIR is the directory in which to store 
merged files."
                           default-regexp)
            nil
            'ediff-filtering-regexp-history
-           (eval ediff-default-filtering-regexp))
+           (eval ediff-default-filtering-regexp t))
           )))
   (ediff-directories-internal
    dir1 dir2 ancestor-dir regexp
@@ -720,7 +720,7 @@ names.  Only the files that are under revision control are 
taken into account.
 MERGE-AUTOSTORE-DIR is the directory in which to store merged files."
   (interactive
    (let ((dir-A (ediff-get-default-directory-name))
-        (default-regexp (eval ediff-default-filtering-regexp))
+        (default-regexp (eval ediff-default-filtering-regexp t))
         )
      (list (read-directory-name
            "Directory to merge with revisions:" dir-A nil 'must-match)
@@ -729,15 +729,15 @@ MERGE-AUTOSTORE-DIR is the directory in which to store 
merged files."
                           default-regexp)
            nil
            'ediff-filtering-regexp-history
-           (eval ediff-default-filtering-regexp))
+           (eval ediff-default-filtering-regexp t))
           )))
   (ediff-directory-revisions-internal
-   dir1 regexp 'ediff-merge-revisions 'ediff-merge-directory-revisions
+   dir1 regexp #'ediff-merge-revisions 'ediff-merge-directory-revisions
    nil merge-autostore-dir
    ))
 
 ;;;###autoload
-(defalias 'edir-merge-revisions 'ediff-merge-directory-revisions)
+(defalias 'edir-merge-revisions #'ediff-merge-directory-revisions)
 
 ;;;###autoload
 (defun ediff-merge-directory-revisions-with-ancestor (dir1 regexp
@@ -749,7 +749,7 @@ names.  Only the files that are under revision control are 
taken into account.
 MERGE-AUTOSTORE-DIR is the directory in which to store merged files."
   (interactive
    (let ((dir-A (ediff-get-default-directory-name))
-        (default-regexp (eval ediff-default-filtering-regexp))
+        (default-regexp (eval ediff-default-filtering-regexp t))
         )
      (list (read-directory-name
            "Directory to merge with revisions and ancestors:"
@@ -759,10 +759,10 @@ MERGE-AUTOSTORE-DIR is the directory in which to store 
merged files."
                           default-regexp)
            nil
            'ediff-filtering-regexp-history
-           (eval ediff-default-filtering-regexp))
+           (eval ediff-default-filtering-regexp t))
           )))
   (ediff-directory-revisions-internal
-   dir1 regexp 'ediff-merge-revisions-with-ancestor
+   dir1 regexp #'ediff-merge-revisions-with-ancestor
    'ediff-merge-directory-revisions-with-ancestor
    nil merge-autostore-dir
    ))
diff --git a/lisp/vc/emerge.el b/lisp/vc/emerge.el
index d2d419a..8f7affe 100644
--- a/lisp/vc/emerge.el
+++ b/lisp/vc/emerge.el
@@ -79,90 +79,75 @@ but can be invoked directly in `fast' mode."
 ;; way they number lines of a file.
 (defcustom emerge-diff-program "diff"
   "Name of the program which compares two files."
-  :type 'string
-  :group 'emerge)
+  :type 'string)
 (defcustom emerge-diff3-program "diff3"
   "Name of the program which compares three files.
 Its arguments are the ancestor file and the two variant files."
-  :type 'string
-  :group 'emerge)
+  :type 'string)
 (defcustom emerge-diff-options ""
   "Options to pass to `emerge-diff-program' and `emerge-diff3-program'."
-  :type 'string
-  :group 'emerge)
+  :type 'string)
 (defcustom emerge-match-diff-line
   (let ((x "\\([0-9]+\\)\\(\\|,\\([0-9]+\\)\\)"))
     (concat "^" x "\\([acd]\\)" x "$"))
   "Pattern to match lines produced by diff that describe differences.
 This is as opposed to lines from the source files."
-  :type 'regexp
-  :group 'emerge)
+  :type 'regexp)
 (defcustom emerge-diff-ok-lines-regexp
   "^\\([0-9,]+[acd][0-9,]+$\\|[<>] \\|---\\)"
   "Regexp that matches normal output lines from `emerge-diff-program'.
 Lines that do not match are assumed to be error messages."
-  :type 'regexp
-  :group 'emerge)
+  :type 'regexp)
 (defcustom emerge-diff3-ok-lines-regexp
   "^\\([1-3]:\\|====\\|  \\)"
   "Regexp that matches normal output lines from `emerge-diff3-program'.
 Lines that do not match are assumed to be error messages."
-  :type 'regexp
-  :group 'emerge)
+  :type 'regexp)
 
 (defcustom emerge-rcs-ci-program "ci"
   "Name of the program that checks in RCS revisions."
-  :type 'string
-  :group 'emerge)
+  :type 'string)
 (defcustom emerge-rcs-co-program "co"
   "Name of the program that checks out RCS revisions."
-  :type 'string
-  :group 'emerge)
+  :type 'string)
 
 (defcustom emerge-process-local-variables nil
   "Non-nil if Emerge should process local-variables lists in merge buffers.
 \(You can explicitly request processing the local-variables
 by executing `(hack-local-variables)'.)"
-  :type 'boolean
-  :group 'emerge)
+  :type 'boolean)
 (defcustom emerge-execute-line-deletions nil
   "If non-nil: `emerge-execute-line' makes no output if an input was deleted.
 It concludes that an input version has been deleted when an ancestor entry
 is present, only one A or B entry is present, and an output entry is present.
 If nil: In such circumstances, the A or B file that is present will be
 copied to the designated output file."
-  :type 'boolean
-  :group 'emerge)
+  :type 'boolean)
 
 (defcustom emerge-before-flag "vvvvvvvvvvvvvvvvvvvv\n"
   "Flag placed above the highlighted block of code.  Must end with newline.
 Must be set before Emerge is loaded, or  emerge-new-flags  must be run
 after setting."
-  :type 'string
-  :group 'emerge)
+  :type 'string)
 (defcustom emerge-after-flag "^^^^^^^^^^^^^^^^^^^^\n"
   "Flag placed below the highlighted block of code.  Must end with newline.
 Must be set before Emerge is loaded, or  emerge-new-flags  must be run
 after setting."
-  :type 'string
-  :group 'emerge)
+  :type 'string)
 
 ;; Hook variables
 
 (defcustom emerge-startup-hook nil
   "Hook to run in the merge buffer after the merge has been set up."
-  :type 'hook
-  :group 'emerge)
+  :type 'hook)
 (defcustom emerge-select-hook nil
   "Hook to run after a difference has been selected.
 The variable `n' holds the (internal) number of the difference."
-  :type 'hook
-  :group 'emerge)
+  :type 'hook)
 (defcustom emerge-unselect-hook nil
   "Hook to run after a difference has been unselected.
 The variable `n' holds the (internal) number of the difference."
-  :type 'hook
-  :group 'emerge)
+  :type 'hook)
 
 ;; Variables to control the default directories of the arguments to
 ;; Emerge commands.
@@ -171,8 +156,7 @@ The variable `n' holds the (internal) number of the 
difference."
   "If nil, default dir for filenames in emerge is `default-directory'.
 If non-nil, filenames complete in the directory of the last argument of the
 same type to an `emerge-files...' command."
-  :type 'boolean
-  :group 'emerge)
+  :type 'boolean)
 
 (defvar emerge-last-dir-A nil
   "Last directory for the first file of an `emerge-files...' command.")
@@ -235,15 +219,13 @@ depend on the flags."
 (defcustom emerge-min-visible-lines 3
   "Number of lines that we want to show above and below the flags when we are
 displaying a difference."
-  :type 'integer
-  :group 'emerge)
+  :type 'integer)
 
 (defcustom emerge-temp-file-prefix
   (expand-file-name "emerge" temporary-file-directory)
   "Prefix to put on Emerge temporary file names.
 Do not start with `~/' or `~USERNAME/'."
-  :type 'string
-  :group 'emerge)
+  :type 'string)
 
 (make-obsolete-variable 'emerge-temp-file-prefix
                        "customize `temporary-file-directory' instead."
@@ -251,8 +233,7 @@ Do not start with `~/' or `~USERNAME/'."
 
 (defcustom emerge-temp-file-mode 384   ; u=rw only
   "Mode for Emerge temporary files."
-  :type 'integer
-  :group 'emerge)
+  :type 'integer)
 
 (make-obsolete-variable 'emerge-temp-file-mode
                        "it has no effect, temporary files are always private."
@@ -268,8 +249,7 @@ The template is inserted as a string, with the following 
interpolations:
 Don't forget to end the template with a newline.
 Note that this variable can be made local to a particular merge buffer by
 giving a prefix argument to `emerge-set-combine-versions-template'."
-  :type 'string
-  :group 'emerge)
+  :type 'string)
 
 ;; Build keymaps
 
@@ -294,8 +274,7 @@ Makes Emerge commands directly available.")
 (defcustom emerge-command-prefix "\C-c\C-c"
   "Command prefix for Emerge commands in `edit' mode.
 Must be set before Emerge is loaded."
-  :type 'string
-  :group 'emerge)
+  :type 'string)
 
 ;; This function sets up the fixed keymaps.  It is executed when the first
 ;; Emerge is done to allow the user maximum time to set up the global keymap.
@@ -1245,8 +1224,7 @@ Otherwise, the A or B file present is copied to the 
output file."
 
 (defcustom emerge-merge-directories-filename-regexp "[^.]"
   "Regexp describing files to be processed by `emerge-merge-directories'."
-  :type 'regexp
-  :group 'emerge)
+  :type 'regexp)
 
 ;;;###autoload
 (defun emerge-merge-directories (a-dir b-dir ancestor-dir output-dir)
@@ -3070,8 +3048,7 @@ See also `auto-save-file-name-p'."
 
 (defcustom emerge-metachars nil
   "No longer used.  Emerge now uses `shell-quote-argument'."
-  :type '(choice (const nil) regexp)
-  :group 'emerge)
+  :type '(choice (const nil) regexp))
 (make-obsolete-variable 'emerge-metachars nil "26.1")
 
 (provide 'emerge)
diff --git a/lisp/vc/pcvs-defs.el b/lisp/vc/pcvs-defs.el
index 2ee3da7..54ef069 100644
--- a/lisp/vc/pcvs-defs.el
+++ b/lisp/vc/pcvs-defs.el
@@ -1,4 +1,4 @@
-;;; pcvs-defs.el --- variable definitions for PCL-CVS
+;;; pcvs-defs.el --- variable definitions for PCL-CVS  -*- lexical-binding: t; 
-*-
 
 ;; Copyright (C) 1991-2021 Free Software Foundation, Inc.
 
@@ -71,7 +71,6 @@ versions, such as the one in SunOS-4.")
 
 (defcustom cvs-cvsrc-file (convert-standard-filename "~/.cvsrc")
   "Path to your cvsrc file."
-  :group 'pcl-cvs
   :type '(file))
 
 (defvar cvs-shared-start 4
@@ -96,24 +95,20 @@ If t, they will be removed from the *cvs* buffer after 
every command.
 If `delayed', they will be removed from the *cvs* buffer before every command.
 If `status', they will only be removed after a `cvs-mode-status' command.
 Else, they will never be automatically removed from the *cvs* buffer."
-  :group 'pcl-cvs
   :type '(choice (const nil) (const status) (const delayed) (const t)))
 
 (defcustom cvs-auto-remove-directories 'handled
   "If `all', directory entries will never be shown.
 If `handled', only non-handled directories will be shown.
 If `empty', only non-empty directories will be shown."
-  :group 'pcl-cvs
   :type '(choice (const :tag "No" nil) (const all) (const handled) (const 
empty)))
 
 (defcustom cvs-auto-revert t
   "Non-nil if changed files should automatically be reverted."
-  :group 'pcl-cvs
   :type '(boolean))
 
 (defcustom cvs-sort-ignore-file t
   "Non-nil if `cvs-mode-ignore' should sort the .cvsignore automatically."
-  :group 'pcl-cvs
   :type '(boolean))
 
 (defcustom cvs-force-dir-tag t
@@ -121,7 +116,6 @@ If `empty', only non-empty directories will be shown."
 Tagging should generally be applied a directory at a time, but sometimes it is
 useful to be able to tag a single file.  The normal way to do that is to use
 `cvs-mode-force-command' so as to temporarily override the restrictions."
-  :group 'pcl-cvs
   :type '(boolean))
 
 (defcustom cvs-default-ignore-marks nil
@@ -130,7 +124,6 @@ Normally they run on the files that are marked (with 
`cvs-mode-mark'),
 or the file under the cursor if no files are marked.  If this variable
 is set to a non-nil value they will by default run on the file on the
 current line.  See also `cvs-invert-ignore-marks'."
-  :group 'pcl-cvs
   :type '(boolean))
 
 (defcustom cvs-invert-ignore-marks
@@ -143,7 +136,6 @@ current line.  See also `cvs-invert-ignore-marks'."
   "List of cvs commands that invert the default ignore-mark behavior.
 Commands in this set will use the opposite default from the one set
 in `cvs-default-ignore-marks'."
-  :group 'pcl-cvs
   :type '(set (const "diff")
              (const "tag")
              (const "ignore")))
@@ -154,7 +146,6 @@ Non-nil means that PCL-CVS will ask confirmation before 
removing files
 except for files whose content can readily be recovered from the repository.
 A value of `list' means that the list of files to be deleted will be
 displayed when asking for confirmation."
-  :group 'pcl-cvs
   :type '(choice (const list)
                 (const t)
                 (const nil)))
@@ -162,7 +153,6 @@ displayed when asking for confirmation."
 (defcustom cvs-add-default-message nil
   "Default message to use when adding files.
 If set to nil, `cvs-mode-add' will always prompt for a message."
-  :group 'pcl-cvs
   :type '(choice (const :tag "Prompt" nil)
                 (string)))
 
@@ -171,7 +161,6 @@ If set to nil, `cvs-mode-add' will always prompt for a 
message."
 If non-nil, `cvs-mode-find-file' will place the cursor at the beginning of
 the modified area.  If the file is not locally modified, this will obviously
 have no effect."
-  :group 'pcl-cvs
   :type '(boolean))
 
 (defcustom cvs-buffer-name-alist
@@ -193,7 +182,6 @@ POSTPROC is a function that should be executed when the 
command terminates
 
 The CMD used for `cvs-mode-commit' is \"message\".  For that special
   case, POSTPROC is called just after MODE with special arguments."
-  :group 'pcl-cvs
   :type '(repeat
          (list (choice (const "diff")
                        (const "status")
@@ -236,7 +224,6 @@ Output from cvs is placed here for asynchronous commands.")
       '(cvs-ediff-diff . cvs-ediff-merge)
     '(cvs-emerge-diff . cvs-emerge-merge))
   "Pair of functions to be used for resp. diff'ing and merg'ing interactively."
-  :group 'pcl-cvs
   :type '(choice (const :tag "Ediff" (cvs-ediff-diff . cvs-ediff-merge))
                 (const :tag "Emerge" (cvs-emerge-diff . cvs-emerge-merge))))
 
@@ -255,7 +242,6 @@ Alternatives are:
  `samedir': reuse any cvs buffer displaying the same directory
  `subdir':  or reuse any cvs buffer displaying any sub- or super- directory
  `always':  reuse any cvs buffer."
-  :group 'pcl-cvs
   :type '(choice (const always) (const subdir) (const samedir) (const 
current)))
 
 (defvar cvs-temp-buffer nil
@@ -424,8 +410,7 @@ This variable is buffer local and only used in the *cvs* 
buffer.")
 
 (defcustom cvs-minor-mode-prefix "\C-xc"
   "Prefix key for the `cvs-mode' bindings in `cvs-minor-mode'."
-  :type 'string
-  :group 'pcl-cvs)
+  :type 'string)
 
 (easy-mmode-defmap cvs-minor-mode-map
   `((,cvs-minor-mode-prefix . cvs-mode-map)
diff --git a/lisp/vc/pcvs-info.el b/lisp/vc/pcvs-info.el
index e119717..21fe98d 100644
--- a/lisp/vc/pcvs-info.el
+++ b/lisp/vc/pcvs-info.el
@@ -1,4 +1,4 @@
-;;; pcvs-info.el --- internal representation of a fileinfo entry
+;;; pcvs-info.el --- internal representation of a fileinfo entry  -*- 
lexical-binding: t; -*-
 
 ;; Copyright (C) 1991-2021 Free Software Foundation, Inc.
 
@@ -384,8 +384,8 @@ For use by the ewoc package."
 The ordering defined by this function is such that directories are
 sorted alphabetically, and inside every directory the DIRCHANGE
 fileinfo will appear first, followed by all files (alphabetically)."
-  (let ((subtypea (cvs-fileinfo->subtype a))
-       (subtypeb (cvs-fileinfo->subtype b)))
+  (let (  ;; (subtypea (cvs-fileinfo->subtype a))
+       ) ;; (subtypeb (cvs-fileinfo->subtype b))
     (cond
      ;; Sort according to directories.
      ((string< (cvs-fileinfo->dir a) (cvs-fileinfo->dir b)) t)
diff --git a/lisp/vc/pcvs-parse.el b/lisp/vc/pcvs-parse.el
index 4381650..3a96c93 100644
--- a/lisp/vc/pcvs-parse.el
+++ b/lisp/vc/pcvs-parse.el
@@ -1,4 +1,4 @@
-;;; pcvs-parse.el --- the CVS output parser
+;;; pcvs-parse.el --- the CVS output parser  -*- lexical-binding: t; -*-
 
 ;; Copyright (C) 1991-2021 Free Software Foundation, Inc.
 
@@ -73,12 +73,12 @@ by `$'."
   '("status" "add" "commit" "update" "remove" "checkout" "ci")
   "List of CVS commands whose output is understood by the parser.")
 
-(defun cvs-parse-buffer (parse-spec dont-change-disc &optional subdir)
+(defun cvs-parse-buffer (parse-spec dcd &optional subdir)
   "Parse current buffer according to PARSE-SPEC.
 PARSE-SPEC is a function of no argument advancing the point and returning
   either a fileinfo or t (if the matched text should be ignored) or
   nil if it didn't match anything.
-DONT-CHANGE-DISC just indicates whether the command was changing the disc
+DCD just indicates whether the command was changing the disc
   or not (useful to tell the difference between `cvs-examine' and `cvs-update'
   output.
 The path names should be interpreted as relative to SUBDIR (defaults
@@ -86,6 +86,7 @@ The path names should be interpreted as relative to SUBDIR 
(defaults
 Return a list of collected entries, or t if an error occurred."
   (goto-char (point-min))
   (let ((fileinfos ())
+       (dont-change-disc dcd)
        (cvs-current-dir "")
        (case-fold-search nil)
        (cvs-current-subdir (or subdir "")))
@@ -134,12 +135,12 @@ Match RE and if successful, execute MATCHES."
 
 (defmacro cvs-or (&rest alts)
   "Try each one of the ALTS alternatives until one matches."
+  (declare (debug t))
   `(let ((-cvs-parse-point (point)))
      ,(cons 'or
            (mapcar (lambda (es)
                      `(or ,es (ignore (goto-char -cvs-parse-point))))
                    alts))))
-(def-edebug-spec cvs-or t)
 
 ;; This is how parser tables should be executed
 (defun cvs-parse-run-table (parse-spec)
@@ -185,17 +186,20 @@ The remaining KEYS are passed directly to 
`cvs-create-fileinfo'."
     (let ((type (if (consp type) (car type) type))
          (subtype (if (consp type) (cdr type))))
       (when dir (setq cvs-current-dir dir))
-      (apply 'cvs-create-fileinfo type
+      (apply #'cvs-create-fileinfo type
             (concat cvs-current-subdir (or dir cvs-current-dir))
             file (cvs-parse-msg) :subtype subtype keys))))
 
 ;;;; CVS Process Parser Tables:
-;;;;
-;;;; The table for status and update could actually be merged since they
-;;;; don't conflict.  But they don't overlap much either.
+;;
+;; The table for status and update could actually be merged since they
+;; don't conflict.  But they don't overlap much either.
 
 (defun cvs-parse-table ()
   "Table of message objects for `cvs-parse-process'."
+  (with-suppressed-warnings ((lexical c file dir path base-rev subtype))
+    (defvar c) (defvar file) (defvar dir) (defvar path) (defvar base-rev)
+    (defvar subtype))
   (let (c file dir path base-rev subtype)
     (cvs-or
 
@@ -401,6 +405,8 @@ The remaining KEYS are passed directly to 
`cvs-create-fileinfo'."
 
 
 (defun cvs-parse-merge ()
+  (with-suppressed-warnings ((lexical path base-rev head-rev type))
+    (defvar path) (defvar base-rev) (defvar head-rev) (defvar type))
   (let (path base-rev head-rev type)
     ;; A merge (maybe with a conflict).
     (and
@@ -445,6 +451,9 @@ The remaining KEYS are passed directly to 
`cvs-create-fileinfo'."
                            :merge (cons base-rev head-rev))))))
 
 (defun cvs-parse-status ()
+  (with-suppressed-warnings ((lexical nofile path base-rev head-rev type))
+    (defvar nofile) (defvar path) (defvar base-rev) (defvar head-rev)
+    (defvar type))
   (let (nofile path base-rev head-rev type)
     (and
      (cvs-match
@@ -493,6 +502,8 @@ The remaining KEYS are passed directly to 
`cvs-create-fileinfo'."
                          :head-rev head-rev))))
 
 (defun cvs-parse-commit ()
+  (with-suppressed-warnings ((lexical path file base-rev subtype))
+    (defvar path) (defvar file) (defvar base-rev) (defvar subtype))
   (let (path file base-rev subtype)
     (cvs-or
 
diff --git a/lisp/vc/pcvs-util.el b/lisp/vc/pcvs-util.el
index 57da7bf..75d9fe9 100644
--- a/lisp/vc/pcvs-util.el
+++ b/lisp/vc/pcvs-util.el
@@ -1,4 +1,4 @@
-;;; pcvs-util.el --- utility functions for PCL-CVS
+;;; pcvs-util.el --- utility functions for PCL-CVS  -*- lexical-binding: t; -*-
 
 ;; Copyright (C) 1991-2021 Free Software Foundation, Inc.
 
@@ -33,27 +33,9 @@
 ;;;;
 
 (defsubst cvs-car (x) (if (consp x) (car x) x))
-(defalias 'cvs-cdr 'cdr-safe)
+(defalias 'cvs-cdr #'cdr-safe)
 (defsubst cvs-append (&rest xs)
-  (apply 'append (mapcar (lambda (x) (if (listp x) x (list x))) xs)))
-
-(defsubst cvs-every (-cvs-every-f -cvs-every-l)
-  (while (consp -cvs-every-l)
-    (unless (funcall -cvs-every-f (pop -cvs-every-l))
-      (setq -cvs-every-l t)))
-  (not -cvs-every-l))
-
-(defun cvs-union (xs ys)
-  (let ((zs ys))
-    (dolist (x xs zs)
-      (unless (member x ys) (push x zs)))))
-
-(defun cvs-map (-cvs-map-f &rest -cvs-map-ls)
-  (let ((accum ()))
-    (while (not (cvs-every 'null -cvs-map-ls))
-      (push (apply -cvs-map-f (mapcar 'car -cvs-map-ls)) accum)
-      (setq -cvs-map-ls (mapcar 'cdr -cvs-map-ls)))
-    (nreverse accum)))
+  (apply #'append (mapcar (lambda (x) (if (listp x) x (list x))) xs)))
 
 (defun cvs-first (l &optional n)
   (if (null n) (car l)
@@ -146,7 +128,7 @@ If NOREUSE is non-nil, always return a new buffer."
   "Insert a list of STRINGS into the current buffer.
 Uses columns to keep the listing readable but compact."
   (when (consp strings)
-    (let* ((length (apply 'max (mapcar 'length strings)))
+    (let* ((length (apply #'max (mapcar #'length strings)))
           (wwidth (1- (window-width)))
           (columns (min
                     ;; At least 2 columns; at least 2 spaces between columns.
@@ -174,7 +156,7 @@ arguments.  If ARGS is not a list, no argument will be 
passed."
   (condition-case nil
       (with-temp-buffer
        (if args
-           (apply 'call-process
+           (apply #'call-process
                   file nil t nil (when (listp args) args))
          (insert-file-contents file))
        (goto-char (point-min))
@@ -182,7 +164,7 @@ arguments.  If ARGS is not a list, no argument will be 
passed."
                          (if oneline (line-end-position) (point-max))))
     (file-error nil)))
 
-(define-obsolete-function-alias 'cvs-string-prefix-p 'string-prefix-p "24.3")
+(define-obsolete-function-alias 'cvs-string-prefix-p #'string-prefix-p "24.3")
 
 ;;;;
 ;;;; file names
diff --git a/lisp/vc/pcvs.el b/lisp/vc/pcvs.el
index 1a42c67..6e039cc 100644
--- a/lisp/vc/pcvs.el
+++ b/lisp/vc/pcvs.el
@@ -115,7 +115,7 @@
 
 ;;; Code:
 
-(eval-when-compile (require 'cl-lib))
+(require 'cl-lib)
 (require 'ewoc)                                ;Ewoc was once cookie
 (require 'pcvs-defs)
 (require 'pcvs-util)
@@ -513,7 +513,7 @@ If non-nil, NEW means to create a new buffer no matter 
what."
       (let* ((dir+files+rest
              (if (or (null fis) (not single-dir))
                  ;; not single-dir mode: just process the whole thing
-                 (list "" (mapcar 'cvs-fileinfo->full-name fis) nil)
+                 (list "" (mapcar #'cvs-fileinfo->full-name fis) nil)
                ;; single-dir mode: extract the same-dir-elements
                (let ((dir (cvs-fileinfo->dir (car fis))))
                  ;; output the concerned dir so the parser can translate paths
@@ -2135,11 +2135,11 @@ Returns a list of FIS that should be `cvs remove'd."
                                    (eq (cvs-fileinfo->type fi) 'UNKNOWN))
                                  (cvs-mode-marked filter cmd))))
         (silent (or (not cvs-confirm-removals)
-                    (cvs-every (lambda (fi)
-                                 (or (not (file-exists-p
-                                           (cvs-fileinfo->full-name fi)))
-                                     (cvs-applicable-p fi 'safe-rm)))
-                               files)))
+                    (cl-every (lambda (fi)
+                                (or (not (file-exists-p
+                                          (cvs-fileinfo->full-name fi)))
+                                    (cvs-applicable-p fi 'safe-rm)))
+                              files)))
         (tmpbuf (cvs-temp-buffer)))
     (when (and (not silent) (equal cvs-confirm-removals 'list))
       (with-current-buffer tmpbuf
diff --git a/lisp/vc/smerge-mode.el b/lisp/vc/smerge-mode.el
index c66a4fb..694d452 100644
--- a/lisp/vc/smerge-mode.el
+++ b/lisp/vc/smerge-mode.el
@@ -1450,30 +1450,31 @@ If no conflict maker is found, turn off `smerge-mode'."
 First tries to go to the next conflict in the current buffer, and if not
 found, uses VC to try and find the next file with conflict."
   (interactive)
-  (let ((buffer (current-buffer)))
-    (condition-case nil
-        ;; FIXME: Try again from BOB before moving to the next file.
-        (smerge-next)
-      (error
-       (if (and (or smerge-change-buffer-confirm
-                    (and (buffer-modified-p) buffer-file-name))
-                (not (or (eq last-command this-command)
-                         (eq ?\r last-command-event)))) ;Called via M-x!?
-           ;; FIXME: Don't emit this message if `vc-find-conflicted-file' won't
-           ;; go to another file anyway (because there are no more conflicted
-           ;; files).
-           (message (if (buffer-modified-p)
-                        "No more conflicts here.  Repeat to save and go to 
next buffer"
-                      "No more conflicts here.  Repeat to go to next buffer"))
-         (if (and (buffer-modified-p) buffer-file-name)
-             (save-buffer))
-         (vc-find-conflicted-file)
-         (if (eq buffer (current-buffer))
-             ;; Do nothing: presumably `vc-find-conflicted-file' already
-             ;; emitted a message explaining there aren't any more conflicts.
-             nil
+  (condition-case nil
+      ;; FIXME: Try again from BOB before moving to the next file.
+      (smerge-next)
+    (error
+     (if (and (or smerge-change-buffer-confirm
+                  (and (buffer-modified-p) buffer-file-name))
+              (not (or (eq last-command this-command)
+                       (eq ?\r last-command-event)))) ;Called via M-x!?
+         ;; FIXME: Don't emit this message if `vc-find-conflicted-file' won't
+         ;; go to another file anyway (because there are no more conflicted
+         ;; files).
+         (message (if (buffer-modified-p)
+                      "No more conflicts here.  Repeat to save and go to next 
buffer"
+                    "No more conflicts here.  Repeat to go to next buffer"))
+       (if (and (buffer-modified-p) buffer-file-name)
+           (save-buffer))
+       (vc-find-conflicted-file)
+       ;; At this point, the caret will only be at a conflict marker
+       ;; if the file did not correspond to an opened
+       ;; buffer. Otherwise we need to jump to a marker explicitly.
+       (unless (looking-at "^<<<<<<<")
+         (let ((prev-pos (point)))
            (goto-char (point-min))
-           (smerge-next)))))))
+           (unless (ignore-errors (not (smerge-next)))
+             (goto-char prev-pos))))))))
 
 (provide 'smerge-mode)
 
diff --git a/lisp/vc/vc-annotate.el b/lisp/vc/vc-annotate.el
index b0435ab..07b2800 100644
--- a/lisp/vc/vc-annotate.el
+++ b/lisp/vc/vc-annotate.el
@@ -164,18 +164,18 @@ List of factors, used to expand/compress the time scale.  
See `vc-annotate'."
 
 (defvar vc-annotate-mode-map
   (let ((m (make-sparse-keymap)))
-    (define-key m "a" 'vc-annotate-revision-previous-to-line)
-    (define-key m "d" 'vc-annotate-show-diff-revision-at-line)
-    (define-key m "=" 'vc-annotate-show-diff-revision-at-line)
-    (define-key m "D" 'vc-annotate-show-changeset-diff-revision-at-line)
-    (define-key m "f" 'vc-annotate-find-revision-at-line)
-    (define-key m "j" 'vc-annotate-revision-at-line)
-    (define-key m "l" 'vc-annotate-show-log-revision-at-line)
-    (define-key m "n" 'vc-annotate-next-revision)
-    (define-key m "p" 'vc-annotate-prev-revision)
-    (define-key m "w" 'vc-annotate-working-revision)
-    (define-key m "v" 'vc-annotate-toggle-annotation-visibility)
-    (define-key m "\C-m" 'vc-annotate-goto-line)
+    (define-key m "a" #'vc-annotate-revision-previous-to-line)
+    (define-key m "d" #'vc-annotate-show-diff-revision-at-line)
+    (define-key m "=" #'vc-annotate-show-diff-revision-at-line)
+    (define-key m "D" #'vc-annotate-show-changeset-diff-revision-at-line)
+    (define-key m "f" #'vc-annotate-find-revision-at-line)
+    (define-key m "j" #'vc-annotate-revision-at-line)
+    (define-key m "l" #'vc-annotate-show-log-revision-at-line)
+    (define-key m "n" #'vc-annotate-next-revision)
+    (define-key m "p" #'vc-annotate-prev-revision)
+    (define-key m "w" #'vc-annotate-working-revision)
+    (define-key m "v" #'vc-annotate-toggle-annotation-visibility)
+    (define-key m "\C-m" #'vc-annotate-goto-line)
     m)
   "Local keymap used for VC-Annotate mode.")
 
diff --git a/lisp/vc/vc-bzr.el b/lisp/vc/vc-bzr.el
index d1385ea..de5a90d 100644
--- a/lisp/vc/vc-bzr.el
+++ b/lisp/vc/vc-bzr.el
@@ -45,9 +45,9 @@
 
 ;;; Code:
 
+(require 'vc-dispatcher)
 (eval-when-compile
   (require 'cl-lib)
-  (require 'vc-dispatcher)
   (require 'vc-dir))                    ; vc-dir-at-event
 
 (declare-function vc-deduce-fileset "vc"
@@ -66,7 +66,6 @@
 
 (defcustom vc-bzr-program "bzr"
   "Name of the bzr command (excluding any arguments)."
-  :group 'vc-bzr
   :type 'string)
 
 (defcustom vc-bzr-diff-switches nil
@@ -75,8 +74,7 @@ If nil, use the value of `vc-diff-switches'.  If t, use no 
switches."
   :type '(choice (const :tag "Unspecified" nil)
                  (const :tag "None" t)
                  (string :tag "Argument String")
-                 (repeat :tag "Argument List" :value ("") string))
-  :group 'vc-bzr)
+                 (repeat :tag "Argument List" :value ("") string)))
 
 (defcustom vc-bzr-annotate-switches nil
   "String or list of strings specifying switches for bzr annotate under VC.
@@ -85,15 +83,13 @@ If nil, use the value of `vc-annotate-switches'.  If t, use 
no switches."
                 (const :tag "None" t)
                 (string :tag "Argument String")
                 (repeat :tag "Argument List" :value ("") string))
-  :version "25.1"
-  :group 'vc-bzr)
+  :version "25.1")
 
 (defcustom vc-bzr-log-switches nil
   "String or list of strings specifying switches for bzr log under VC."
   :type '(choice (const :tag "None" nil)
                  (string :tag "Argument String")
-                 (repeat :tag "Argument List" :value ("") string))
-  :group 'vc-bzr)
+                 (repeat :tag "Argument List" :value ("") string)))
 
 (defcustom vc-bzr-status-switches
   (ignore-errors
@@ -108,7 +104,6 @@ The option \"--no-classify\" should be present if your bzr 
supports it."
   :type '(choice (const :tag "None" nil)
                  (string :tag "Argument String")
                  (repeat :tag "Argument List" :value ("") string))
-  :group 'vc-bzr
   :version "24.1")
 
 ;; since v0.9, bzr supports removing the progress indicators
@@ -122,7 +117,7 @@ prepends `vc-bzr-status-switches' to ARGS."
          `("BZR_PROGRESS_BAR=none" ; Suppress progress output (bzr >=0.9)
            "LC_MESSAGES=C"         ; Force English output
            ,@process-environment)))
-    (apply 'vc-do-command (or buffer "*vc*") okstatus vc-bzr-program
+    (apply #'vc-do-command (or buffer "*vc*") okstatus vc-bzr-program
            file-or-list bzr-command
            (if (and (string-equal "status" bzr-command)
                     vc-bzr-status-switches)
@@ -144,7 +139,7 @@ Use the current Bzr root directory as the ROOT argument to
             ,@process-environment))
         (root (vc-bzr-root default-directory))
         (buffer (format "*vc-bzr : %s*" (expand-file-name root))))
-    (apply 'vc-do-async-command buffer root
+    (apply #'vc-do-async-command buffer root
           vc-bzr-program bzr-command args)
     buffer))
 
@@ -267,7 +262,8 @@ in the repository root directory of FILE."
                  ;; If there is no parent, this must be a new repo.
                  ;; If file is in dirstate, can only be added (b#8025).
                  ((or (not (match-beginning 4))
-                      (eq (char-after (match-beginning 4)) ?a)) 'added)
+                      (eq (char-after (match-beginning 4)) ?a))
+                  'added)
                  ((or (and (eql (string-to-number (match-string 3))
                                (file-attribute-size (file-attributes file)))
                            (equal (match-string 5)
@@ -280,7 +276,7 @@ in the repository root directory of FILE."
                                       (memq
                                        ?x
                                        (mapcar
-                                        'identity
+                                        #'identity
                                        (file-attribute-modes
                                         (file-attributes file))))))
                                  (if (eq (char-after (match-beginning 7))
@@ -374,13 +370,13 @@ If PROMPT is non-nil, prompt for the Bzr command to run."
            command        (cadr args)
            args           (cddr args)))
     (require 'vc-dispatcher)
-    (let ((buf (apply 'vc-bzr-async-command command args)))
+    (let ((buf (apply #'vc-bzr-async-command command args)))
       (with-current-buffer buf
         (vc-run-delayed
           (vc-compilation-mode 'bzr)
           (setq-local compile-command
                       (concat vc-bzr-program " " command " "
-                              (if args (mapconcat 'identity args " ") "")))))
+                              (if args (mapconcat #'identity args " ") "")))))
       (vc-set-async-update buf))))
 
 (defun vc-bzr-pull (prompt)
@@ -424,7 +420,7 @@ default if it is available."
         (vc-bzr-program (car  cmd))
         (command        (cadr cmd))
         (args           (cddr cmd)))
-    (let ((buf (apply 'vc-bzr-async-command command args)))
+    (let ((buf (apply #'vc-bzr-async-command command args)))
       (with-current-buffer buf (vc-run-delayed (vc-compilation-mode 'bzr)))
       (vc-set-async-update buf))))
 
@@ -512,7 +508,7 @@ in the branch repository (or whose status not be 
determined)."
     (unless (re-search-forward "^<<<<<<< " nil t)
       (vc-bzr-command "resolve" nil 0 buffer-file-name)
       ;; Remove the hook so that it is not called multiple times.
-      (remove-hook 'after-save-hook 'vc-bzr-resolve-when-done t))))
+      (remove-hook 'after-save-hook #'vc-bzr-resolve-when-done t))))
 
 (defun vc-bzr-find-file-hook ()
   (when (and buffer-file-name
@@ -529,7 +525,7 @@ in the branch repository (or whose status not be 
determined)."
     ;; but the one in `bzr pull' isn't, so it would be good to provide an
     ;; elisp function to remerge from the .BASE/OTHER/THIS files.
     (smerge-start-session)
-    (add-hook 'after-save-hook 'vc-bzr-resolve-when-done nil t)
+    (add-hook 'after-save-hook #'vc-bzr-resolve-when-done nil t)
     (vc-message-unresolved-conflicts buffer-file-name)))
 
 (defun vc-bzr-version-dirstate (dir)
@@ -643,7 +639,7 @@ Returns nil if unable to find this information."
 
 ;; Could run `bzr status' in the directory and see if it succeeds, but
 ;; that's relatively expensive.
-(defalias 'vc-bzr-responsible-p 'vc-bzr-root
+(defalias 'vc-bzr-responsible-p #'vc-bzr-root
   "Return non-nil if FILE is (potentially) controlled by bzr.
 The criterion is that there is a `.bzr' directory in the same
 or a superior directory.")
@@ -664,7 +660,7 @@ or a superior directory.")
 
 (defun vc-bzr-checkin (files comment &optional _rev)
   "Check FILES in to bzr with log message COMMENT."
-  (apply 'vc-bzr-command "commit" nil 0 files
+  (apply #'vc-bzr-command "commit" nil 0 files
          (cons "-m" (log-edit-extract-headers
                      `(("Author" . ,(vc-bzr--sanitize-header "--author"))
                        ("Date" . ,(vc-bzr--sanitize-header "--commit-time"))
@@ -699,7 +695,7 @@ or a superior directory.")
 (defvar log-view-expanded-log-entry-function)
 
 (define-derived-mode vc-bzr-log-view-mode log-view-mode "Bzr-Log-View"
-  (remove-hook 'log-view-mode-hook 'vc-bzr-log-view-mode) ;Deactivate the hack.
+  (remove-hook 'log-view-mode-hook #'vc-bzr-log-view-mode) ;Deactivate the 
hack.
   (require 'add-log)
   (setq-local log-view-per-file-logs nil)
   (setq-local log-view-file-re regexp-unmatchable)
@@ -745,7 +741,7 @@ If LIMIT is non-nil, show no more than this many entries."
   ;; the log display may not what the user wants - but I see no other
   ;; way of getting the above regexps working.
   (with-current-buffer buffer
-    (apply 'vc-bzr-command "log" buffer 'async files
+    (apply #'vc-bzr-command "log" buffer 'async files
           (append
            (if shortlog '("--line") '("--long"))
            ;; The extra complications here when start-revision and limit
@@ -761,7 +757,8 @@ If LIMIT is non-nil, show no more than this many entries."
                           ;; This means we don't have to use --no-aliases.
                           ;; Is -c any different to -r in this case?
                           "-r%s"
-                        "-r..%s") start-revision)))
+                        "-r..%s")
+                      start-revision)))
             (if (eq vc-log-view-type 'with-diff) (list "-p"))
            (when limit (list "-l" (format "%s" limit)))
            ;; There is no sensible way to combine --limit and --forward,
@@ -782,7 +779,7 @@ If LIMIT is non-nil, show no more than this many entries."
 
 (defun vc-bzr-expanded-log-entry (revision)
   (with-temp-buffer
-    (apply 'vc-bzr-command "log" t nil nil
+    (apply #'vc-bzr-command "log" t nil nil
            (append
             (list "--long" (format "-r%s" revision))
             (if (stringp vc-bzr-log-switches)
@@ -795,11 +792,11 @@ If LIMIT is non-nil, show no more than this many entries."
       (buffer-substring (match-end 0) (point-max)))))
 
 (defun vc-bzr-log-incoming (buffer remote-location)
-  (apply 'vc-bzr-command "missing" buffer 'async nil
+  (apply #'vc-bzr-command "missing" buffer 'async nil
         (list "--theirs-only" (unless (string= remote-location "") 
remote-location))))
 
 (defun vc-bzr-log-outgoing (buffer remote-location)
-  (apply 'vc-bzr-command "missing" buffer 'async nil
+  (apply #'vc-bzr-command "missing" buffer 'async nil
         (list "--mine-only" (unless (string= remote-location "") 
remote-location))))
 
 (defun vc-bzr-show-log-entry (revision)
@@ -830,7 +827,7 @@ If LIMIT is non-nil, show no more than this many entries."
           (append
            ;; Only add --diff-options if there are any diff switches.
            (unless (zerop (length switches))
-             (list "--diff-options" (mapconcat 'identity switches " ")))
+             (list "--diff-options" (mapconcat #'identity switches " ")))
            ;; This `when' is just an optimization because bzr-1.2 is *much*
            ;; faster when the revision argument is not given.
            (when (or rev1 rev2)
@@ -995,7 +992,7 @@ stream.  Standard error output is discarded."
 
 (defun vc-bzr-dir-status-files (dir files update-function)
   "Return a list of conses (file . state) for DIR."
-  (apply 'vc-bzr-command "status" (current-buffer) 'async dir "-v" "-S" files)
+  (apply #'vc-bzr-command "status" (current-buffer) 'async dir "-v" "-S" files)
   (vc-run-delayed
    (vc-bzr-after-dir-status update-function
                             ;; "bzr status" results are relative to
@@ -1010,15 +1007,15 @@ stream.  Standard error output is discarded."
 (defvar vc-bzr-shelve-map
   (let ((map (make-sparse-keymap)))
     ;; Turn off vc-dir marking
-    (define-key map [mouse-2] 'ignore)
-
-    (define-key map [down-mouse-3] 'vc-bzr-shelve-menu)
-    (define-key map "\C-k" 'vc-bzr-shelve-delete-at-point)
-    (define-key map "=" 'vc-bzr-shelve-show-at-point)
-    (define-key map "\C-m" 'vc-bzr-shelve-show-at-point)
-    (define-key map "A" 'vc-bzr-shelve-apply-and-keep-at-point)
-    (define-key map "P" 'vc-bzr-shelve-apply-at-point)
-    (define-key map "S" 'vc-bzr-shelve-snapshot)
+    (define-key map [mouse-2] #'ignore)
+
+    (define-key map [down-mouse-3] #'vc-bzr-shelve-menu)
+    (define-key map "\C-k" #'vc-bzr-shelve-delete-at-point)
+    (define-key map "=" #'vc-bzr-shelve-show-at-point)
+    (define-key map "\C-m" #'vc-bzr-shelve-show-at-point)
+    (define-key map "A" #'vc-bzr-shelve-apply-and-keep-at-point)
+    (define-key map "P" #'vc-bzr-shelve-apply-at-point)
+    (define-key map "S" #'vc-bzr-shelve-snapshot)
     map))
 
 (defvar vc-bzr-shelve-menu-map
@@ -1211,7 +1208,7 @@ stream.  Standard error output is discarded."
   (let ((vc-bzr-revisions '())
         (default-directory (file-name-directory (car files))))
     (with-temp-buffer
-      (apply 'vc-bzr-command "log" t 0 files
+      (apply #'vc-bzr-command "log" t 0 files
              (append '("--line")
                      (if (stringp vc-bzr-log-switches)
                          (list vc-bzr-log-switches)
diff --git a/lisp/vc/vc-cvs.el b/lisp/vc/vc-cvs.el
index 0adb532..ef60713 100644
--- a/lisp/vc/vc-cvs.el
+++ b/lisp/vc/vc-cvs.el
@@ -76,8 +76,7 @@
                 (repeat :tag "Argument List"
                         :value ("")
                         string))
-  :version "22.1"
-  :group 'vc-cvs)
+  :version "22.1")
 
 (defcustom vc-cvs-register-switches nil
   "Switches for registering a file into CVS.
@@ -88,8 +87,7 @@ If t, use no switches."
                 (const :tag "None" t)
                 (string :tag "Argument String")
                 (repeat :tag "Argument List" :value ("") string))
-  :version "21.1"
-  :group 'vc-cvs)
+  :version "21.1")
 
 (defcustom vc-cvs-diff-switches nil
   "String or list of strings specifying switches for CVS diff under VC.
@@ -98,8 +96,7 @@ If nil, use the value of `vc-diff-switches'.  If t, use no 
switches."
                  (const :tag "None" t)
                  (string :tag "Argument String")
                  (repeat :tag "Argument List" :value ("") string))
-  :version "21.1"
-  :group 'vc-cvs)
+  :version "21.1")
 
 (defcustom vc-cvs-annotate-switches nil
   "String or list of strings specifying switches for cvs annotate under VC.
@@ -109,22 +106,19 @@ switches."
                 (const :tag "None" t)
                 (string :tag "Argument String")
                 (repeat :tag "Argument List" :value ("") string))
-  :version "25.1"
-  :group 'vc-cvs)
+  :version "25.1")
 
 (defcustom vc-cvs-header '("$Id\ $")
   "Header keywords to be inserted by `vc-insert-headers'."
   :version "24.1"     ; no longer consult the obsolete vc-header-alist
-  :type '(repeat string)
-  :group 'vc-cvs)
+  :type '(repeat string))
 
 (defcustom vc-cvs-use-edit t
   "Non-nil means to use `cvs edit' to \"check out\" a file.
 This is only meaningful if you don't use the implicit checkout model
 \(i.e. if you have $CVSREAD set)."
   :type 'boolean
-  :version "21.1"
-  :group 'vc-cvs)
+  :version "21.1")
 
 (defcustom vc-cvs-stay-local 'only-file
   "Non-nil means use local operations when possible for remote repositories.
@@ -151,16 +145,14 @@ except for hosts matched by these regular expressions."
                        (regexp :format " stay local,\n%t: %v"
                                :tag "if it matches")
                        (repeat :format "%v%i\n" :inline t (regexp :tag "or"))))
-  :version "23.1"
-  :group 'vc-cvs)
+  :version "23.1")
 
 (defcustom vc-cvs-sticky-date-format-string "%c"
   "Format string for mode-line display of sticky date.
 Format is according to `format-time-string'.  Only used if
 `vc-cvs-sticky-tag-display' is t."
   :type '(string)
-  :version "22.1"
-  :group 'vc-cvs)
+  :version "22.1")
 
 (defcustom vc-cvs-sticky-tag-display t
   "Specify the mode-line display of sticky tags.
@@ -198,8 +190,7 @@ displayed.  Date and time is displayed for sticky dates.
 
 See also variable `vc-cvs-sticky-date-format-string'."
   :type '(choice boolean function)
-  :version "22.1"
-  :group 'vc-cvs)
+  :version "22.1")
 
 ;;;
 ;;; Internal variables
@@ -310,7 +301,7 @@ to the CVS command."
            (vc-cvs-could-register file)
            (push (directory-file-name (file-name-directory file)) dirs)))
     (if dirs (vc-cvs-register dirs)))
-  (apply 'vc-cvs-command nil 0 files
+  (apply #'vc-cvs-command nil 0 files
          "add"
          (and comment (string-match "[^\t\n ]" comment)
               (concat "-m" comment))
@@ -346,12 +337,12 @@ its parents."
        (error "%s is not a valid symbolic tag name" rev)
       ;; If the input revision is a valid symbolic tag name, we create it
       ;; as a branch, commit and switch to it.
-      (apply 'vc-cvs-command nil 0 files "tag" "-b" (list rev))
-      (apply 'vc-cvs-command nil 0 files "update" "-r" (list rev))
+      (apply #'vc-cvs-command nil 0 files "tag" "-b" (list rev))
+      (apply #'vc-cvs-command nil 0 files "update" "-r" (list rev))
       (mapc (lambda (file) (vc-file-setprop file 'vc-cvs-sticky-tag rev))
            files)))
   (let ((status (apply
-                 'vc-cvs-command nil 1 files
+                 #'vc-cvs-command nil 1 files
                 "ci" (if rev (concat "-r" rev))
                  (concat "-m" (car (log-edit-extract-headers nil comment)))
                 (vc-switches 'CVS 'checkin))))
@@ -378,7 +369,7 @@ its parents."
         (vc-file-setprop
         (car files) 'vc-working-revision
         (vc-parse-buffer "^\\(new\\|initial\\) revision: \\([0-9.]+\\)" 2))
-      (mapc 'vc-file-clearprops files))
+      (mapc #'vc-file-clearprops files))
     ;; Anyway, forget the checkout model of the file, because we might have
     ;; guessed wrong when we found the file.  After commit, we can
     ;; tell it from the permissions of the file (see
@@ -391,7 +382,7 @@ its parents."
         (vc-cvs-command nil 0 files "update" "-A"))))
 
 (defun vc-cvs-find-revision (file rev buffer)
-  (apply 'vc-cvs-command
+  (apply #'vc-cvs-command
         buffer 0 file
         "-Q"                           ; suppress diagnostic output
         "update"
@@ -416,7 +407,7 @@ REV is the revision to check out."
                (if (equal file buffer-file-name) (read-only-mode -1))))
       ;; Check out a particular revision (or recreate the file).
       (vc-file-setprop file 'vc-working-revision nil)
-      (apply 'vc-cvs-command nil 0 file
+      (apply #'vc-cvs-command nil 0 file
              "-w"
              "update"
              (when rev
@@ -600,7 +591,7 @@ Remaining arguments are ignored."
                ;; This used to append diff-switches and vc-diff-switches,
                ;; which was consistent with the vc-diff-switches doc at that
                ;; time, but not with the actual behavior of any other VC diff.
-               (apply 'vc-do-command (or buffer "*vc-diff*") 1 "diff" nil
+               (apply #'vc-do-command (or buffer "*vc-diff*") 1 "diff" nil
                       ;; Not a CVS diff, does not use vc-cvs-diff-switches.
                       (append (vc-switches nil 'diff)
                               (list (file-relative-name file-oldvers)
@@ -608,7 +599,7 @@ Remaining arguments are ignored."
                (setq status 0))
            (push file invoke-cvs-diff-list)))))
     (when invoke-cvs-diff-list
-      (setq status (apply 'vc-cvs-command (or buffer "*vc-diff*")
+      (setq status (apply #'vc-cvs-command (or buffer "*vc-diff*")
                          (if async 'async 1)
                          invoke-cvs-diff-list "diff"
                          (and oldvers (concat "-r" oldvers))
@@ -787,7 +778,7 @@ If UPDATE is non-nil, then update (resynch) any affected 
buffers."
   "A wrapper around `vc-do-command' for use in vc-cvs.el.
 The difference to vc-do-command is that this function always invokes `cvs',
 and that it passes `vc-cvs-global-switches' to it before FLAGS."
-  (apply 'vc-do-command (or buffer "*vc*") okstatus "cvs" files
+  (apply #'vc-do-command (or buffer "*vc*") okstatus "cvs" files
          (if (stringp vc-cvs-global-switches)
              (cons vc-cvs-global-switches flags)
            (append vc-cvs-global-switches
@@ -816,7 +807,7 @@ individually should stay local."
                             (setq default nil stay-local (cdr stay-local)))
                         (when (consp stay-local)
                           (setq stay-local
-                                (mapconcat 'identity stay-local "\\|")))
+                                (mapconcat #'identity stay-local "\\|")))
                         (if (if (string-match stay-local hostname)
                                 default (not default))
                             'yes 'no))))))))))))
diff --git a/lisp/vc/vc-dav.el b/lisp/vc/vc-dav.el
index 88f46ef..5fd8d8e 100644
--- a/lisp/vc/vc-dav.el
+++ b/lisp/vc/vc-dav.el
@@ -1,4 +1,4 @@
-;;; vc-dav.el --- vc.el support for WebDAV
+;;; vc-dav.el --- vc.el support for WebDAV  -*- lexical-binding: t; -*-
 
 ;; Copyright (C) 2001, 2004-2021 Free Software Foundation, Inc.
 
@@ -64,7 +64,7 @@ For a list of possible values, see `vc-state'."
          'edited
        (cdr (car locks)))))))
 
-(defun vc-dav-checkout-model (url)
+(defun vc-dav-checkout-model (_url)
   "Indicate whether URL needs to be \"checked out\" before it can be edited.
 See `vc-checkout-model' for a list of possible values."
   ;; The only thing we can support with webdav is 'locking
@@ -72,21 +72,21 @@ See `vc-checkout-model' for a list of possible values."
 
 ;; This should figure out the version # of the file somehow.  What is
 ;; the most appropriate property in WebDAV to look at for this?
-(defun vc-dav-workfile-version (url)
+(defun vc-dav-workfile-version (_url)
   "Return the current workfile version of URL."
   "Unknown")
 
-(defun vc-dav-register (url &optional _comment)
+(defun vc-dav-register (_url &optional _comment)
   "Register URL in the DAV backend."
   ;; Do we need to do anything here?  FIXME?
   )
 
-(defun vc-dav-checkin (url comment &optional _rev)
+(defun vc-dav-checkin (_url _comment &optional _rev)
   "Commit changes in URL to WebDAV. COMMENT is used as a check-in comment."
   ;; This should PUT the resource and release any locks that we hold.
   )
 
-(defun vc-dav-checkout (url &optional rev destfile)
+(defun vc-dav-checkout (_url &optional _rev _destfile)
   "Check out revision REV of URL into the working area.
 
 If EDITABLE is non-nil URL should be writable by the user and if
@@ -101,7 +101,7 @@ write the contents to.
   ;; This should LOCK the resource.
   )
 
-(defun vc-dav-revert (url &optional contents-done)
+(defun vc-dav-revert (_url &optional _contents-done)
   "Revert URL back to the current workfile version.
 
 If optional arg CONTENTS-DONE is non-nil, then the contents of FILE
@@ -112,11 +112,11 @@ only needs to update the status of URL within the backend.
   ;; Should UNLOCK the file.
   )
 
-(defun vc-dav-print-log (url)
+(defun vc-dav-print-log (_url)
   "Insert the revision log of URL into the *vc* buffer."
   )
 
-(defun vc-dav-diff (url &optional rev1 rev2 buffer async)
+(defun vc-dav-diff (_url &optional _rev1 _rev2 _buffer _async)
   "Insert the diff for URL into the *vc-diff* buffer.
 If REV1 and REV2 are non-nil report differences from REV1 to REV2.
 If REV1 is nil, use the current workfile version as the older version.
@@ -135,11 +135,11 @@ It should return a status of either 0 (no differences 
found), or
 
 ;; This should use url-dav-get-properties with a depth of `1' to get
 ;; all the properties.
-(defun vc-dav-dir-state (url)
+(defun vc-dav-dir-state (_url)
   "find the version control state of all files in DIR in a fast way."
   )
 
-(defun vc-dav-responsible-p (url)
+(defun vc-dav-responsible-p (_url)
   "Return non-nil if DAV considers itself `responsible' for URL."
   ;; Check for DAV support on the web server.
   t)
diff --git a/lisp/vc/vc-dir.el b/lisp/vc/vc-dir.el
index a416474..eb8cf81 100644
--- a/lisp/vc/vc-dir.el
+++ b/lisp/vc/vc-dir.el
@@ -56,39 +56,48 @@ See `run-hooks'."
 
 (defface vc-dir-header '((t :inherit font-lock-type-face))
   "Face for headers in VC-dir buffers."
-  :group 'vc)
+  :group 'vc
+  :version "28.1")
 
 (defface vc-dir-header-value '((t :inherit font-lock-variable-name-face))
   "Face for header values in VC-dir buffers."
-  :group 'vc)
+  :group 'vc
+  :version "28.1")
 
 (defface vc-dir-directory '((t :inherit font-lock-comment-delimiter-face))
   "Face for directories in VC-dir buffers."
-  :group 'vc)
+  :group 'vc
+  :version "28.1")
 
 (defface vc-dir-file '((t :inherit font-lock-function-name-face))
   "Face for files in VC-dir buffers."
-  :group 'vc)
+  :group 'vc
+  :version "28.1")
 
 (defface vc-dir-mark-indicator '((t :inherit font-lock-type-face))
   "Face for mark indicators in VC-dir buffers."
-  :group 'vc)
+  :group 'vc
+  :version "28.1")
 
 (defface vc-dir-status-warning '((t :inherit font-lock-warning-face))
   "Face for warning status in VC-dir buffers."
-  :group 'vc)
+  :group 'vc
+  :version "28.1")
 
 (defface vc-dir-status-edited '((t :inherit font-lock-variable-name-face))
   "Face for edited status in VC-dir buffers."
-  :group 'vc)
+  :group 'vc
+  :version "28.1")
 
 (defface vc-dir-status-up-to-date '((t :inherit font-lock-builtin-face))
   "Face for up-to-date status in VC-dir buffers."
-  :group 'vc)
+  :group 'vc
+  :version "28.1")
 
 (defface vc-dir-status-ignored '((t :inherit shadow))
   "Face for ignored or empty values in VC-dir buffers."
-  :group 'vc)
+  :group 'vc
+  :version "28.1")
 
 ;; Used to store information for the files displayed in the directory buffer.
 ;; Each item displayed corresponds to one of these defstructs.
@@ -293,67 +302,67 @@ See `run-hooks'."
 (defvar vc-dir-mode-map
   (let ((map (make-sparse-keymap)))
     ;; VC commands
-    (define-key map "v" 'vc-next-action)   ;; C-x v v
-    (define-key map "=" 'vc-diff)         ;; C-x v =
-    (define-key map "D" 'vc-root-diff)    ;; C-x v D
-    (define-key map "i" 'vc-register)     ;; C-x v i
-    (define-key map "+" 'vc-update)       ;; C-x v +
+    (define-key map "v" #'vc-next-action)   ;; C-x v v
+    (define-key map "=" #'vc-diff)        ;; C-x v =
+    (define-key map "D" #'vc-root-diff)           ;; C-x v D
+    (define-key map "i" #'vc-register)    ;; C-x v i
+    (define-key map "+" #'vc-update)      ;; C-x v +
     ;; I'd prefer some kind of symmetry with vc-update:
-    (define-key map "P" 'vc-push)         ;; C-x v P
-    (define-key map "l" 'vc-print-log)    ;; C-x v l
-    (define-key map "L" 'vc-print-root-log) ;; C-x v L
-    (define-key map "I" 'vc-log-incoming)   ;; C-x v I
-    (define-key map "O" 'vc-log-outgoing)   ;; C-x v O
+    (define-key map "P" #'vc-push)        ;; C-x v P
+    (define-key map "l" #'vc-print-log)           ;; C-x v l
+    (define-key map "L" #'vc-print-root-log) ;; C-x v L
+    (define-key map "I" #'vc-log-incoming)   ;; C-x v I
+    (define-key map "O" #'vc-log-outgoing)   ;; C-x v O
     ;; More confusing than helpful, probably
-    ;;(define-key map "R" 'vc-revert) ;; u is taken by vc-dir-unmark.
-    ;;(define-key map "A" 'vc-annotate) ;; g is taken by revert-buffer
+    ;;(define-key map "R" #'vc-revert) ;; u is taken by vc-dir-unmark.
+    ;;(define-key map "A" #'vc-annotate) ;; g is taken by revert-buffer
     ;;                                     bound by `special-mode'.
     ;; Marking.
-    (define-key map "m" 'vc-dir-mark)
-    (define-key map "d" 'vc-dir-clean-files)
-    (define-key map "M" 'vc-dir-mark-all-files)
-    (define-key map "u" 'vc-dir-unmark)
-    (define-key map "U" 'vc-dir-unmark-all-files)
-    (define-key map "\C-?" 'vc-dir-unmark-file-up)
-    (define-key map "\M-\C-?" 'vc-dir-unmark-all-files)
+    (define-key map "m" #'vc-dir-mark)
+    (define-key map "d" #'vc-dir-clean-files)
+    (define-key map "M" #'vc-dir-mark-all-files)
+    (define-key map "u" #'vc-dir-unmark)
+    (define-key map "U" #'vc-dir-unmark-all-files)
+    (define-key map "\C-?" #'vc-dir-unmark-file-up)
+    (define-key map "\M-\C-?" #'vc-dir-unmark-all-files)
     ;; Movement.
-    (define-key map "n" 'vc-dir-next-line)
-    (define-key map " " 'vc-dir-next-line)
-    (define-key map "\t" 'vc-dir-next-directory)
-    (define-key map "p" 'vc-dir-previous-line)
-    (define-key map [?\S-\ ] 'vc-dir-previous-line)
-    (define-key map [backtab] 'vc-dir-previous-directory)
+    (define-key map "n" #'vc-dir-next-line)
+    (define-key map " " #'vc-dir-next-line)
+    (define-key map "\t" #'vc-dir-next-directory)
+    (define-key map "p" #'vc-dir-previous-line)
+    (define-key map [?\S-\ ] #'vc-dir-previous-line)
+    (define-key map [backtab] #'vc-dir-previous-directory)
     ;;; Rebind paragraph-movement commands.
-    (define-key map "\M-}" 'vc-dir-next-directory)
-    (define-key map "\M-{" 'vc-dir-previous-directory)
-    (define-key map [C-down] 'vc-dir-next-directory)
-    (define-key map [C-up] 'vc-dir-previous-directory)
+    (define-key map "\M-}" #'vc-dir-next-directory)
+    (define-key map "\M-{" #'vc-dir-previous-directory)
+    (define-key map [C-down] #'vc-dir-next-directory)
+    (define-key map [C-up] #'vc-dir-previous-directory)
     ;; The remainder.
-    (define-key map "f" 'vc-dir-find-file)
-    (define-key map "e" 'vc-dir-find-file) ; dired-mode compatibility
-    (define-key map "\C-m" 'vc-dir-find-file)
-    (define-key map "o" 'vc-dir-find-file-other-window)
-    (define-key map "\C-o" 'vc-dir-display-file)
-    (define-key map "\C-c\C-c" 'vc-dir-kill-dir-status-process)
-    (define-key map [down-mouse-3] 'vc-dir-menu)
+    (define-key map "f" #'vc-dir-find-file)
+    (define-key map "e" #'vc-dir-find-file) ; dired-mode compatibility
+    (define-key map "\C-m" #'vc-dir-find-file)
+    (define-key map "o" #'vc-dir-find-file-other-window)
+    (define-key map "\C-o" #'vc-dir-display-file)
+    (define-key map "\C-c\C-c" #'vc-dir-kill-dir-status-process)
+    (define-key map [down-mouse-3] #'vc-dir-menu)
     (define-key map [follow-link] 'mouse-face)
-    (define-key map "x" 'vc-dir-hide-up-to-date)
-    (define-key map [?\C-k] 'vc-dir-kill-line)
-    (define-key map "S" 'vc-dir-search) ;; FIXME: Maybe use A like dired?
-    (define-key map "Q" 'vc-dir-query-replace-regexp)
-    (define-key map (kbd "M-s a C-s")   'vc-dir-isearch)
-    (define-key map (kbd "M-s a M-C-s") 'vc-dir-isearch-regexp)
-    (define-key map "G" 'vc-dir-ignore)
+    (define-key map "x" #'vc-dir-hide-up-to-date)
+    (define-key map [?\C-k] #'vc-dir-kill-line)
+    (define-key map "S" #'vc-dir-search) ;; FIXME: Maybe use A like dired?
+    (define-key map "Q" #'vc-dir-query-replace-regexp)
+    (define-key map (kbd "M-s a C-s")   #'vc-dir-isearch)
+    (define-key map (kbd "M-s a M-C-s") #'vc-dir-isearch-regexp)
+    (define-key map "G" #'vc-dir-ignore)
 
     (let ((branch-map (make-sparse-keymap)))
       (define-key map "B" branch-map)
-      (define-key branch-map "c" 'vc-create-tag)
-      (define-key branch-map "l" 'vc-print-branch-log)
-      (define-key branch-map "s" 'vc-retrieve-tag))
+      (define-key branch-map "c" #'vc-create-tag)
+      (define-key branch-map "l" #'vc-print-branch-log)
+      (define-key branch-map "s" #'vc-retrieve-tag))
 
     (let ((mark-map (make-sparse-keymap)))
       (define-key map "*" mark-map)
-      (define-key mark-map "r" 'vc-dir-mark-registered-files))
+      (define-key mark-map "r" #'vc-dir-mark-registered-files))
 
     ;; Hook up the menu.
     (define-key map [menu-bar vc-dir-mode]
@@ -497,7 +506,7 @@ If NOINSERT, ignore elements on ENTRIES which are not in 
the ewoc."
               (t
                (unless noinsert
                  (ewoc-enter-before vc-ewoc node
-                                    (apply 'vc-dir-create-fileinfo entry)))
+                                    (apply #'vc-dir-create-fileinfo entry)))
                (setq entries (cdr entries))
                (setq entry (car entries))))))
           (t
@@ -513,7 +522,7 @@ If NOINSERT, ignore elements on ENTRIES which are not in 
the ewoc."
                   vc-ewoc node (vc-dir-create-fileinfo rd nil nil nil 
entrydir))))
              ;; Now insert the node itself.
              (ewoc-enter-before vc-ewoc node
-                                (apply 'vc-dir-create-fileinfo entry)))
+                                (apply #'vc-dir-create-fileinfo entry)))
            (setq entries (cdr entries) entry (car entries))))))
       ;; We're past the last node, all remaining entries go to the end.
       (unless (or node noinsert)
@@ -529,10 +538,10 @@ If NOINSERT, ignore elements on ENTRIES which are not in 
the ewoc."
                   vc-ewoc (vc-dir-create-fileinfo rd nil nil nil entrydir))))
              ;; Now insert the node itself.
              (ewoc-enter-last vc-ewoc
-                              (apply 'vc-dir-create-fileinfo entry))))))
+                              (apply #'vc-dir-create-fileinfo entry))))))
       (when to-remove
        (let ((inhibit-read-only t))
-         (apply 'ewoc-delete vc-ewoc (nreverse to-remove)))))))
+         (apply #'ewoc-delete vc-ewoc (nreverse to-remove)))))))
 
 (defun vc-dir-busy ()
   (and (buffer-live-p vc-dir-process-buffer)
@@ -873,7 +882,7 @@ system; see `vc-dir-delete-file'."
 The files will also be marked as deleted in the version control
 system."
   (interactive)
-  (mapc 'vc-delete-file (or (vc-dir-marked-files)
+  (mapc #'vc-delete-file (or (vc-dir-marked-files)
                             (list (vc-dir-current-file)))))
 
 (defun vc-dir-find-file ()
@@ -903,13 +912,13 @@ system."
   "Search for a string through all marked buffers using Isearch."
   (interactive)
   (multi-isearch-files
-   (mapcar 'car (vc-dir-marked-only-files-and-states))))
+   (mapcar #'car (vc-dir-marked-only-files-and-states))))
 
 (defun vc-dir-isearch-regexp ()
   "Search for a regexp through all marked buffers using Isearch."
   (interactive)
   (multi-isearch-files-regexp
-   (mapcar 'car (vc-dir-marked-only-files-and-states))))
+   (mapcar #'car (vc-dir-marked-only-files-and-states))))
 
 (defun vc-dir-search (regexp)
   "Search through all marked files for a match for REGEXP.
@@ -934,13 +943,13 @@ with the command \\[tags-loop-continue]."
          (query-replace-read-args
           "Query replace regexp in marked files" t t)))
      (list (nth 0 common) (nth 1 common) (nth 2 common))))
-  (dolist (file (mapcar 'car (vc-dir-marked-only-files-and-states)))
+  (dolist (file (mapcar #'car (vc-dir-marked-only-files-and-states)))
     (let ((buffer (get-file-buffer file)))
       (if (and buffer (with-current-buffer buffer
                        buffer-read-only))
          (error "File `%s' is visited read-only" file))))
   (fileloop-initialize-replace
-   from to (mapcar 'car (vc-dir-marked-only-files-and-states))
+   from to (mapcar #'car (vc-dir-marked-only-files-and-states))
    (if (equal from (downcase from)) nil 'default)
    delimited)
   (fileloop-continue))
@@ -1152,7 +1161,7 @@ the *vc-dir* buffer.
     (add-to-list 'vc-dir-buffers (current-buffer))
     ;; Make sure that if the directory buffer is killed, the update
     ;; process running in the background is also killed.
-    (add-hook 'kill-buffer-query-functions 'vc-dir-kill-query nil t)
+    (add-hook 'kill-buffer-query-functions #'vc-dir-kill-query nil t)
     (hack-dir-local-variables-non-file-buffer)
     (vc-dir-refresh)))
 
@@ -1267,7 +1276,7 @@ Throw an error if another update process is in progress."
                          vc-ewoc 'vc-dir-fileinfo->needs-update)))
                    (if remaining
                        (vc-dir-refresh-files
-                        (mapcar 'vc-dir-fileinfo->name remaining))
+                        (mapcar #'vc-dir-fileinfo->name remaining))
                      (setq mode-line-process nil)
                      (run-hooks 'vc-dir-refresh-hook))))))))))))
 
@@ -1321,7 +1330,7 @@ state of item at point, if any."
          (ewoc-delete vc-ewoc crt))
        (setq crt prev)))))
 
-(defalias 'vc-dir-hide-up-to-date 'vc-dir-hide-state)
+(defalias 'vc-dir-hide-up-to-date #'vc-dir-hide-state)
 
 (defun vc-dir-kill-line ()
   "Remove the current line from display."
@@ -1357,7 +1366,7 @@ state of item at point, if any."
        (unless (vc-compatible-state (cdr crt) state)
          (error "When applying VC operations to multiple files, the files are 
required\nto  be in similar VC states.\n%s in state %s clashes with %s in state 
%s"
                 (car crt) (cdr crt) (caar only-files-list) state)))
-      (setq only-files-list (mapcar 'car only-files-list))
+      (setq only-files-list (mapcar #'car only-files-list))
       (when (and state (not (eq state 'unregistered)))
        (setq model (vc-checkout-model vc-dir-backend only-files-list))))
     (list vc-dir-backend files only-files-list state model)))
@@ -1428,13 +1437,13 @@ These are the commands available for use in the file 
status buffer:
 
 (defvar vc-dir-status-mouse-map
   (let ((map (make-sparse-keymap)))
-    (define-key map [mouse-2] 'vc-dir-toggle-mark)
+    (define-key map [mouse-2] #'vc-dir-toggle-mark)
     map)
   "Local keymap for toggling mark.")
 
 (defvar vc-dir-filename-mouse-map
    (let ((map (make-sparse-keymap)))
-     (define-key map [mouse-2] 'vc-dir-find-file-other-window)
+     (define-key map [mouse-2] #'vc-dir-find-file-other-window)
     map)
   "Local keymap for visiting a file.")
 
diff --git a/lisp/vc/vc-dispatcher.el b/lisp/vc/vc-dispatcher.el
index 2573964..2b477df 100644
--- a/lisp/vc/vc-dispatcher.el
+++ b/lisp/vc/vc-dispatcher.el
@@ -242,7 +242,7 @@ CODE should be a function of no arguments."
      ((or (null proc) (eq (process-status proc) 'exit))
       ;; Make sure we've read the process's output before going further.
       (when proc (accept-process-output proc))
-      (if (functionp code) (funcall code) (eval code)))
+      (if (functionp code) (funcall code) (eval code t)))
      ;; If a process is running, add CODE to the sentinel
      ((eq (process-status proc) 'run)
       (vc-set-mode-line-busy-indicator)
@@ -267,7 +267,7 @@ and is passed 3 arguments: the COMMAND, the FILES and the 
FLAGS.")
 (defun vc-delistify (filelist)
   "Smash a FILELIST into a file list string suitable for info messages."
   ;; FIXME what about file names with spaces?
-  (if (not filelist) "."  (mapconcat 'identity filelist " ")))
+  (if (not filelist) "."  (mapconcat #'identity filelist " ")))
 
 (defcustom vc-tor nil
   "If non-nil, communicate with the repository site via Tor.
@@ -331,7 +331,7 @@ case, and the process object in the asynchronous case."
              ;; Run asynchronously.
              (let ((proc
                     (let ((process-connection-type nil))
-                      (apply 'start-file-process command (current-buffer)
+                      (apply #'start-file-process command (current-buffer)
                               command squeezed))))
                (when vc-command-messages
                  (let ((inhibit-message (eq (selected-window) 
(active-minibuffer-window))))
@@ -339,7 +339,7 @@ case, and the process object in the asynchronous case."
                 ;; Get rid of the default message insertion, in case we don't
                 ;; set a sentinel explicitly.
                (set-process-sentinel proc #'ignore)
-               (set-process-filter proc 'vc-process-filter)
+               (set-process-filter proc #'vc-process-filter)
                (setq status proc)
                (when vc-command-messages
                  (vc-run-delayed
@@ -351,7 +351,7 @@ case, and the process object in the asynchronous case."
              (let ((inhibit-message (eq (selected-window) 
(active-minibuffer-window))))
                (message "Running in foreground: %s" full-command)))
            (let ((buffer-undo-list t))
-             (setq status (apply 'process-file command nil t nil squeezed)))
+             (setq status (apply #'process-file command nil t nil squeezed)))
            (when (and (not (eq t okstatus))
                       (or (not (integerp status))
                           (and okstatus (< okstatus status))))
@@ -394,7 +394,7 @@ Display the buffer in some window, but don't select it."
       (insert "\"...\n")
       ;; Run in the original working directory.
       (let ((default-directory dir))
-       (apply 'vc-do-command t 'async command nil args)))
+       (apply #'vc-do-command t 'async command nil args)))
     (setq window (display-buffer buffer))
     (if window
        (set-window-start window new-window-start))
diff --git a/lisp/vc/vc-filewise.el b/lisp/vc/vc-filewise.el
index ee73aa6..e1b042a 100644
--- a/lisp/vc/vc-filewise.el
+++ b/lisp/vc/vc-filewise.el
@@ -1,4 +1,4 @@
-;;; vc-filewise.el --- common functions for file-oriented back ends.
+;;; vc-filewise.el --- common functions for file-oriented back ends.  -*- 
lexical-binding: t; -*-
 
 ;; Copyright (C) 1992-1996, 1998-2021 Free Software Foundation, Inc.
 
diff --git a/lisp/vc/vc-git.el b/lisp/vc/vc-git.el
index 25ae26d..fda8605 100644
--- a/lisp/vc/vc-git.el
+++ b/lisp/vc/vc-git.el
@@ -106,6 +106,7 @@
 ;;; Code:
 
 (require 'cl-lib)
+(require 'vc-dispatcher)
 (eval-when-compile
   (require 'subr-x) ; for string-trim-right
   (require 'vc)
@@ -251,7 +252,7 @@ included in the completions."
                ;; Do not use the `file-name-directory' here: git-ls-files
                ;; sometimes fails to return the correct status for relative
                ;; path specs.
-               ;; See also: http://marc.info/?l=git&m=125787684318129&w=2
+               ;; See also: https://marc.info/?l=git&m=125787684318129&w=2
                (name (file-relative-name file dir))
                (str (with-demoted-errors "Error: %S"
                       (cd dir)
@@ -658,29 +659,29 @@ or an empty string if none."
 
 (defvar vc-git-stash-shared-map
   (let ((map (make-sparse-keymap)))
-    (define-key map "S" 'vc-git-stash-snapshot)
-    (define-key map "C" 'vc-git-stash)
+    (define-key map "S" #'vc-git-stash-snapshot)
+    (define-key map "C" #'vc-git-stash)
     map))
 
 (defvar vc-git-stash-map
   (let ((map (make-sparse-keymap)))
     (set-keymap-parent map vc-git-stash-shared-map)
     ;; Turn off vc-dir marking
-    (define-key map [mouse-2] 'ignore)
-
-    (define-key map [down-mouse-3] 'vc-git-stash-menu)
-    (define-key map "\C-k" 'vc-git-stash-delete-at-point)
-    (define-key map "=" 'vc-git-stash-show-at-point)
-    (define-key map "\C-m" 'vc-git-stash-show-at-point)
-    (define-key map "A" 'vc-git-stash-apply-at-point)
-    (define-key map "P" 'vc-git-stash-pop-at-point)
+    (define-key map [mouse-2] #'ignore)
+
+    (define-key map [down-mouse-3] #'vc-git-stash-menu)
+    (define-key map "\C-k" #'vc-git-stash-delete-at-point)
+    (define-key map "=" #'vc-git-stash-show-at-point)
+    (define-key map "\C-m" #'vc-git-stash-show-at-point)
+    (define-key map "A" #'vc-git-stash-apply-at-point)
+    (define-key map "P" #'vc-git-stash-pop-at-point)
     map))
 
 (defvar vc-git-stash-button-map
   (let ((map (make-sparse-keymap)))
     (set-keymap-parent map vc-git-stash-shared-map)
-    (define-key map [mouse-2] 'push-button)
-    (define-key map "\C-m" 'push-button)
+    (define-key map [mouse-2] #'push-button)
+    (define-key map "\C-m" #'push-button)
     map))
 
 (defconst vc-git-stash-shared-help
@@ -871,7 +872,7 @@ The car of the list is the current branch."
     (when dlist
       (vc-git-command nil 0 dlist "add"))))
 
-(defalias 'vc-git-responsible-p 'vc-git-root)
+(defalias 'vc-git-responsible-p #'vc-git-root)
 
 (defun vc-git-unregister (file)
   (vc-git-command nil 0 file "rm" "-f" "--cached" "--"))
@@ -905,9 +906,9 @@ If toggling on, also insert its message into the buffer."
 
 (defvar vc-git-log-edit-mode-map
   (let ((map (make-sparse-keymap "Git-Log-Edit")))
-    (define-key map "\C-c\C-s" 'vc-git-log-edit-toggle-signoff)
-    (define-key map "\C-c\C-n" 'vc-git-log-edit-toggle-no-verify)
-    (define-key map "\C-c\C-e" 'vc-git-log-edit-toggle-amend)
+    (define-key map "\C-c\C-s" #'vc-git-log-edit-toggle-signoff)
+    (define-key map "\C-c\C-n" #'vc-git-log-edit-toggle-no-verify)
+    (define-key map "\C-c\C-e" #'vc-git-log-edit-toggle-amend)
     map))
 
 (define-derived-mode vc-git-log-edit-mode log-edit-mode "Log-Edit/git"
@@ -941,7 +942,7 @@ It is based on `log-edit-mode', and has Git-specific 
extensions.")
                (lambda (value) (when (equal value "yes") (list argument)))))
       ;; When operating on the whole tree, better pass "-a" than ".", since "."
       ;; fails when we're committing a merge.
-      (apply 'vc-git-command nil 0 (if only files)
+      (apply #'vc-git-command nil 0 (if only files)
              (nconc (if msg-file (list "commit" "-F"
                                        (file-local-name msg-file))
                       (list "commit" "-m"))
@@ -1024,13 +1025,13 @@ If PROMPT is non-nil, prompt for the Git command to 
run."
            args        (cddr args)))
     (setq args (nconc args extra-args))
     (require 'vc-dispatcher)
-    (apply 'vc-do-async-command buffer root git-program command args)
+    (apply #'vc-do-async-command buffer root git-program command args)
     (with-current-buffer buffer
       (vc-run-delayed
         (vc-compilation-mode 'git)
         (setq-local compile-command
                     (concat git-program " " command " "
-                            (mapconcat 'identity args " ")))
+                            (mapconcat #'identity args " ")))
         (setq-local compilation-directory root)
         ;; Either set `compilation-buffer-name-function' locally to nil
         ;; or use `compilation-arguments' to set `name-function'.
@@ -1068,7 +1069,7 @@ This prompts for a branch to merge from."
                               branches
                             (cons "FETCH_HEAD" branches))
                           nil t)))
-    (apply 'vc-do-async-command buffer root vc-git-program "merge"
+    (apply #'vc-do-async-command buffer root vc-git-program "merge"
           (list merge-source))
     (with-current-buffer buffer (vc-run-delayed (vc-compilation-mode 'git)))
     (vc-set-async-update buffer)))
@@ -1115,7 +1116,7 @@ This prompts for a branch to merge from."
         (vc-git-command nil 0 nil "reset"))
       (vc-resynch-buffer buffer-file-name t t)
       ;; Remove the hook so that it is not called multiple times.
-      (remove-hook 'after-save-hook 'vc-git-resolve-when-done t))))
+      (remove-hook 'after-save-hook #'vc-git-resolve-when-done t))))
 
 (defun vc-git-find-file-hook ()
   "Activate `smerge-mode' if there is a conflict."
@@ -1126,7 +1127,7 @@ This prompts for a branch to merge from."
                (re-search-forward "^<<<<<<< " nil 'noerror)))
     (smerge-start-session)
     (when vc-git-resolve-conflicts
-      (add-hook 'after-save-hook 'vc-git-resolve-when-done nil 'local))
+      (add-hook 'after-save-hook #'vc-git-resolve-when-done nil 'local))
     (vc-message-unresolved-conflicts buffer-file-name)))
 
 ;;; HISTORY FUNCTIONS
@@ -1154,7 +1155,7 @@ If LIMIT is a revision string, use it as an end-revision."
     ;; read-only.
     (let ((inhibit-read-only t))
       (with-current-buffer buffer
-       (apply 'vc-git-command buffer
+       (apply #'vc-git-command buffer
               'async files
               (append
                '("log" "--no-color")
@@ -1224,11 +1225,11 @@ log entries."
                       (read-shell-command
                         "Search log with command: "
                         (format "%s %s" vc-git-program
-                                (mapconcat 'identity args " "))
+                                (mapconcat #'identity args " "))
                         'vc-git-history)
                       " " t))))
     (vc-setup-buffer buffer)
-    (apply 'vc-git-command buffer 'async nil args)))
+    (apply #'vc-git-command buffer 'async nil args)))
 
 (defun vc-git-mergebase (rev1 &optional rev2)
   (unless rev2 (setq rev2 "HEAD"))
@@ -1299,7 +1300,7 @@ or BRANCH^ (where \"^\" can be repeated)."
 
 (defun vc-git-expanded-log-entry (revision)
   (with-temp-buffer
-    (apply 'vc-git-command t nil nil (list "log" revision "-1" "--"))
+    (apply #'vc-git-command t nil nil (list "log" revision "-1" "--"))
     (goto-char (point-min))
     (unless (eobp)
       ;; Indent the expanded log entry.
@@ -1415,7 +1416,7 @@ This requires git 1.8.4 or later, for the \"-L\" option 
of \"git log\"."
       (vc-git-command (or buffer "*vc-diff*") 1 files
                       "difftool" "--exit-code" "--no-prompt" "-x"
                       (concat "diff "
-                              (mapconcat 'identity
+                              (mapconcat #'identity
                                          (vc-switches nil 'diff) " "))
                       rev1 rev2 "--"))))
 
@@ -1776,7 +1777,7 @@ The difference to vc-do-command is that this function 
always invokes
             ,@(when revert-buffer-in-progress-p
                 '("GIT_OPTIONAL_LOCKS=0")))
           process-environment)))
-    (apply 'vc-do-command (or buffer "*vc*") okstatus vc-git-program
+    (apply #'vc-do-command (or buffer "*vc*") okstatus vc-git-program
           ;; https://debbugs.gnu.org/16897
           (unless (and (not (cdr-safe file-or-list))
                        (let ((file (or (car-safe file-or-list)
@@ -1810,10 +1811,10 @@ The difference to vc-do-command is that this function 
always invokes
            ,@(when revert-buffer-in-progress-p
                '("GIT_OPTIONAL_LOCKS=0")))
          process-environment)))
-    (apply 'process-file vc-git-program nil buffer nil "--no-pager" command 
args)))
+    (apply #'process-file vc-git-program nil buffer nil "--no-pager" command 
args)))
 
 (defun vc-git--out-ok (command &rest args)
-  (zerop (apply 'vc-git--call '(t nil) command args)))
+  (zerop (apply #'vc-git--call '(t nil) command args)))
 
 (defun vc-git--run-command-string (file &rest args)
   "Run a git command on FILE and return its output as string.
@@ -1821,7 +1822,7 @@ FILE can be nil."
   (let* ((ok t)
          (str (with-output-to-string
                 (with-current-buffer standard-output
-                  (unless (apply 'vc-git--out-ok
+                  (unless (apply #'vc-git--out-ok
                                 (if file
                                     (append args (list (file-relative-name
                                                         file)))
diff --git a/lisp/vc/vc-hg.el b/lisp/vc/vc-hg.el
index adb0fce..9faed10 100644
--- a/lisp/vc/vc-hg.el
+++ b/lisp/vc/vc-hg.el
@@ -124,8 +124,7 @@
   :type '(choice (const :tag "None" nil)
          (string :tag "Argument String")
          (repeat :tag "Argument List" :value ("") string))
-  :version "22.2"
-  :group 'vc-hg)
+  :version "22.2")
 
 (defcustom vc-hg-diff-switches t ; Hg doesn't support common args like -u
   "String or list of strings specifying switches for Hg diff under VC.
@@ -134,8 +133,7 @@ If nil, use the value of `vc-diff-switches'.  If t, use no 
switches."
                  (const :tag "None" t)
                  (string :tag "Argument String")
                  (repeat :tag "Argument List" :value ("") string))
-  :version "23.1"
-  :group 'vc-hg)
+  :version "23.1")
 
 (defcustom vc-hg-annotate-switches '("-u" "--follow")
   "String or list of strings specifying switches for hg annotate under VC.
@@ -145,8 +143,7 @@ switches."
                 (const :tag "None" t)
                 (string :tag "Argument String")
                 (repeat :tag "Argument List" :value ("") string))
-  :version "25.1"
-  :group 'vc-hg)
+  :version "25.1")
 
 (defcustom vc-hg-revert-switches nil
   "String or list of strings specifying switches for hg revert
@@ -154,13 +151,11 @@ under VC."
   :type '(choice (const :tag "None" nil)
                 (string :tag "Argument String")
                 (repeat :tag "Argument List" :value ("") string))
-  :version "27.1"
-  :group 'vc-hg)
+  :version "27.1")
 
 (defcustom vc-hg-program "hg"
   "Name of the Mercurial executable (excluding any arguments)."
-  :type 'string
-  :group 'vc-hg)
+  :type 'string)
 
 (defcustom vc-hg-root-log-format
   `(,(concat "{rev}:{ifeq(branch, 'default','', '{branch}')}"
@@ -183,7 +178,6 @@ REGEXP is a regular expression matching the resulting 
Mercurial
 output, and KEYWORDS is a list of `font-lock-keywords' for
 highlighting the Log View buffer."
   :type '(list string regexp (repeat sexp))
-  :group 'vc-hg
   :version "24.5")
 
 (defcustom vc-hg-create-bookmark t
@@ -311,8 +305,7 @@ If no list entry produces a useful revision, return `nil'."
                   (const :tag "Active bookmark" builtin-active-bookmark)
                   (string :tag "Hg template")
                   (function :tag "Custom")))
-  :version "26.1"
-  :group 'vc-hg)
+  :version "26.1")
 
 (defcustom vc-hg-use-file-version-for-mode-line-version nil
   "When enabled, the modeline contains revision information for the visited 
file.
@@ -320,8 +313,7 @@ When not, the revision in the modeline is for the repository
 working copy.  `nil' is the much faster setting for
 large repositories."
   :type 'boolean
-  :version "26.1"
-  :group 'vc-hg)
+  :version "26.1")
 
 (defun vc-hg--active-bookmark-internal (rev)
   (when (equal rev ".")
@@ -413,8 +405,7 @@ specific file to query."
   "String or list of strings specifying switches for hg log under VC."
   :type '(choice (const :tag "None" nil)
                  (string :tag "Argument String")
-                 (repeat :tag "Argument List" :value ("") string))
-  :group 'vc-hg)
+                 (repeat :tag "Argument List" :value ("") string)))
 
 (autoload 'vc-setup-buffer "vc-dispatcher")
 
@@ -442,7 +433,7 @@ If LIMIT is non-nil, show no more than this many entries."
   (let ((inhibit-read-only t))
     (with-current-buffer
        buffer
-      (apply 'vc-hg-command buffer 'async files "log"
+      (apply #'vc-hg-command buffer 'async files "log"
             (nconc
              (when start-revision (list (format "-r%s:0" start-revision)))
              (when limit (list "-l" (format "%s" limit)))
@@ -666,8 +657,7 @@ directly instead of always running Mercurial.  We try to be 
safe
 against Mercurial data structure format changes and always fall
 back to running Mercurial directly."
   :type 'boolean
-  :version "26.1"
-  :group 'vc-hg)
+  :version "26.1")
 
 (defsubst vc-hg--read-u8 ()
   "Read and advance over an unsigned byte.
@@ -1177,7 +1167,7 @@ hg binary."
   "Create a new Mercurial repository."
   (vc-hg-command nil 0 nil "init"))
 
-(defalias 'vc-hg-responsible-p 'vc-hg-root)
+(defalias 'vc-hg-responsible-p #'vc-hg-root)
 
 (defun vc-hg-unregister (file)
   "Unregister FILE from hg."
@@ -1200,7 +1190,7 @@ If toggling on, also insert its message into the buffer."
 
 (defvar vc-hg-log-edit-mode-map
   (let ((map (make-sparse-keymap "Hg-Log-Edit")))
-    (define-key map "\C-c\C-e" 'vc-hg-log-edit-toggle-amend)
+    (define-key map "\C-c\C-e" #'vc-hg-log-edit-toggle-amend)
     map))
 
 (define-derived-mode vc-hg-log-edit-mode log-edit-mode "Log-Edit/hg"
@@ -1214,7 +1204,7 @@ REV is ignored."
          (lambda (value)
            (when (equal value "yes")
              (list "--amend")))))
-    (apply 'vc-hg-command nil 0 files
+    (apply #'vc-hg-command nil 0 files
            (nconc (list "commit" "-m")
                   (log-edit-extract-headers `(("Author" . "--user")
                                               ("Date" . "--date")
@@ -1252,7 +1242,7 @@ REV is the revision to check out into WORKFILE."
     (unless (re-search-forward "^<<<<<<< " nil t)
       (vc-hg-command nil 0 buffer-file-name "resolve" "-m")
       ;; Remove the hook so that it is not called multiple times.
-      (remove-hook 'after-save-hook 'vc-hg-resolve-when-done t))))
+      (remove-hook 'after-save-hook #'vc-hg-resolve-when-done t))))
 
 (defun vc-hg-find-file-hook ()
   (when (and buffer-file-name
@@ -1268,7 +1258,7 @@ REV is the revision to check out into WORKFILE."
     ;; Hg may not recognize "conflict" as a state, but we can do better.
     (vc-file-setprop buffer-file-name 'vc-state 'conflict)
     (smerge-start-session)
-    (add-hook 'after-save-hook 'vc-hg-resolve-when-done nil t)
+    (add-hook 'after-save-hook #'vc-hg-resolve-when-done nil t)
     (vc-message-unresolved-conflicts buffer-file-name)))
 
 
@@ -1443,7 +1433,7 @@ commands, which only operated on marked files."
        (apply #'vc-hg-command
               nil 0 nil
               command
-              (apply 'nconc
+              (apply #'nconc
                      (mapcar (lambda (arg) (list "-r" arg)) marked-list)))
       (let* ((root (vc-hg-root default-directory))
             (buffer (format "*vc-hg : %s*" (expand-file-name root)))
@@ -1463,18 +1453,18 @@ commands, which only operated on marked files."
          (setq hg-program (car  args)
                command    (cadr args)
                args       (cddr args)))
-       (apply 'vc-do-async-command buffer root hg-program command args)
+       (apply #'vc-do-async-command buffer root hg-program command args)
         (with-current-buffer buffer
           (vc-run-delayed
             (dolist (cmd post-processing)
-              (apply 'vc-do-command buffer nil hg-program nil cmd))
+              (apply #'vc-do-command buffer nil hg-program nil cmd))
             (vc-compilation-mode 'hg)
             (setq-local compile-command
                         (concat hg-program " " command " "
-                                (mapconcat 'identity args " ")
+                                (mapconcat #'identity args " ")
                                 (mapconcat (lambda (args)
                                              (concat " && " hg-program " "
-                                                     (mapconcat 'identity
+                                                     (mapconcat #'identity
                                                                 args " ")))
                                            post-processing "")))
             (setq-local compilation-directory root)
@@ -1525,7 +1515,7 @@ This runs the command \"hg merge\"."
          ;; Disable pager.
          (process-environment (cons "HGPLAIN=1" process-environment))
          (branch (vc-read-revision "Revision to merge: ")))
-    (apply 'vc-do-async-command buffer root vc-hg-program
+    (apply #'vc-do-async-command buffer root vc-hg-program
            (append '("--config" "ui.report_untrusted=0" "merge")
                    (unless (string= branch "") (list branch))))
     (with-current-buffer buffer (vc-run-delayed (vc-compilation-mode 'hg)))
@@ -1540,7 +1530,8 @@ This function differs from vc-do-command in that it 
invokes
   ;; Disable pager.
   (let ((process-environment (cons "HGPLAIN=1" process-environment))
         (flags (append '("--config" "ui.report_untrusted=0") flags)))
-    (apply 'vc-do-command (or buffer "*vc*") okstatus vc-hg-program 
file-or-list
+    (apply #'vc-do-command (or buffer "*vc*")
+           okstatus vc-hg-program file-or-list
            (if (stringp vc-hg-global-switches)
                (cons vc-hg-global-switches flags)
              (append vc-hg-global-switches
diff --git a/lisp/vc/vc-hooks.el b/lisp/vc/vc-hooks.el
index f910f9d..4b3c829 100644
--- a/lisp/vc/vc-hooks.el
+++ b/lisp/vc/vc-hooks.el
@@ -50,50 +50,42 @@
 (defface vc-up-to-date-state
   '((default :inherit vc-state-base))
   "Face for VC modeline state when the file is up to date."
-  :version "25.1"
-  :group 'vc-faces)
+  :version "25.1")
 
 (defface vc-needs-update-state
   '((default :inherit vc-state-base))
   "Face for VC modeline state when the file needs update."
-  :version "25.1"
-  :group 'vc-faces)
+  :version "25.1")
 
 (defface vc-locked-state
   '((default :inherit vc-state-base))
   "Face for VC modeline state when the file locked."
-  :version "25.1"
-  :group 'vc-faces)
+  :version "25.1")
 
 (defface vc-locally-added-state
   '((default :inherit vc-state-base))
   "Face for VC modeline state when the file is locally added."
-  :version "25.1"
-  :group 'vc-faces)
+  :version "25.1")
 
 (defface vc-conflict-state
   '((default :inherit vc-state-base))
   "Face for VC modeline state when the file contains merge conflicts."
-  :version "25.1"
-  :group 'vc-faces)
+  :version "25.1")
 
 (defface vc-removed-state
   '((default :inherit vc-state-base))
   "Face for VC modeline state when the file was removed from the VC system."
-  :version "25.1"
-  :group 'vc-faces)
+  :version "25.1")
 
 (defface vc-missing-state
   '((default :inherit vc-state-base))
   "Face for VC modeline state when the file is missing from the file system."
-  :version "25.1"
-  :group 'vc-faces)
+  :version "25.1")
 
 (defface vc-edited-state
   '((default :inherit vc-state-base))
   "Face for VC modeline state when the file is edited."
-  :version "25.1"
-  :group 'vc-faces)
+  :version "25.1")
 
 ;; Customization Variables (the rest is in vc.el)
 
@@ -871,31 +863,31 @@ In the latter case, VC mode is deactivated for this 
buffer."
 ;; (autoload 'vc-prefix-map "vc" nil nil 'keymap)
 (defvar vc-prefix-map
   (let ((map (make-sparse-keymap)))
-    (define-key map "a" 'vc-update-change-log)
-    (define-key map "b" 'vc-switch-backend)
-    (define-key map "d" 'vc-dir)
-    (define-key map "g" 'vc-annotate)
-    (define-key map "G" 'vc-ignore)
-    (define-key map "h" 'vc-region-history)
-    (define-key map "i" 'vc-register)
-    (define-key map "l" 'vc-print-log)
-    (define-key map "L" 'vc-print-root-log)
-    (define-key map "I" 'vc-log-incoming)
-    (define-key map "O" 'vc-log-outgoing)
-    (define-key map "ML" 'vc-log-mergebase)
-    (define-key map "MD" 'vc-diff-mergebase)
-    (define-key map "m" 'vc-merge)
-    (define-key map "r" 'vc-retrieve-tag)
-    (define-key map "s" 'vc-create-tag)
-    (define-key map "u" 'vc-revert)
-    (define-key map "v" 'vc-next-action)
-    (define-key map "+" 'vc-update)
+    (define-key map "a" #'vc-update-change-log)
+    (define-key map "b" #'vc-switch-backend)
+    (define-key map "d" #'vc-dir)
+    (define-key map "g" #'vc-annotate)
+    (define-key map "G" #'vc-ignore)
+    (define-key map "h" #'vc-region-history)
+    (define-key map "i" #'vc-register)
+    (define-key map "l" #'vc-print-log)
+    (define-key map "L" #'vc-print-root-log)
+    (define-key map "I" #'vc-log-incoming)
+    (define-key map "O" #'vc-log-outgoing)
+    (define-key map "ML" #'vc-log-mergebase)
+    (define-key map "MD" #'vc-diff-mergebase)
+    (define-key map "m" #'vc-merge)
+    (define-key map "r" #'vc-retrieve-tag)
+    (define-key map "s" #'vc-create-tag)
+    (define-key map "u" #'vc-revert)
+    (define-key map "v" #'vc-next-action)
+    (define-key map "+" #'vc-update)
     ;; I'd prefer some kind of symmetry with vc-update:
-    (define-key map "P" 'vc-push)
-    (define-key map "=" 'vc-diff)
-    (define-key map "D" 'vc-root-diff)
-    (define-key map "~" 'vc-revision-other-window)
-    (define-key map "x" 'vc-delete-file)
+    (define-key map "P" #'vc-push)
+    (define-key map "=" #'vc-diff)
+    (define-key map "D" #'vc-root-diff)
+    (define-key map "~" #'vc-revision-other-window)
+    (define-key map "x" #'vc-delete-file)
     map))
 (fset 'vc-prefix-map vc-prefix-map)
 (define-key ctl-x-map "v" 'vc-prefix-map)
diff --git a/lisp/vc/vc-mtn.el b/lisp/vc/vc-mtn.el
index 3b610a1..ea69893 100644
--- a/lisp/vc/vc-mtn.el
+++ b/lisp/vc/vc-mtn.el
@@ -46,8 +46,7 @@ If nil, use the value of `vc-diff-switches'.  If t, use no 
switches."
                 (const :tag "None" t)
                 (string :tag "Argument String")
                 (repeat :tag "Argument List" :value ("") string))
-  :version "23.1"
-  :group 'vc-mtn)
+  :version "23.1")
 
 (defcustom vc-mtn-annotate-switches nil
   "String or list of strings specifying switches for mtn annotate under VC.
@@ -57,13 +56,11 @@ switches."
                 (const :tag "None" t)
                 (string :tag "Argument String")
                 (repeat :tag "Argument List" :value ("") string))
-  :version "25.1"
-  :group 'vc-mtn)
+  :version "25.1")
 
 (defcustom vc-mtn-program "mtn"
   "Name of the monotone executable."
-  :type 'string
-  :group 'vc-mtn)
+  :type 'string)
 
 ;; Clear up the cache to force vc-call to check again and discover
 ;; new functions when we reload this file.
@@ -115,7 +112,7 @@ switches."
   (let ((process-environment
          ;; Avoid localization of messages so we can parse the output.
          (cons "LC_MESSAGES=C" process-environment)))
-    (apply 'vc-do-command (or buffer "*vc*") okstatus vc-mtn-program
+    (apply #'vc-do-command (or buffer "*vc*") okstatus vc-mtn-program
            files flags)))
 
 (defun vc-mtn-state (file)
@@ -176,8 +173,7 @@ switches."
   '(("\\`[^:/#]*[:/#]" . ""))           ;Drop the host part.
   "Rewrite rules to shorten Mtn's revision names on the mode-line."
   :type '(repeat (cons regexp string))
-  :version "22.2"
-  :group 'vc-mtn)
+  :version "22.2")
 
 (defun vc-mtn-mode-line-string (file)
   "Return a string for `vc-mode-line' to put in the mode line for FILE."
@@ -203,7 +199,7 @@ switches."
 (declare-function log-edit-extract-headers "log-edit" (headers string))
 
 (defun vc-mtn-checkin (files comment &optional _rev)
-  (apply 'vc-mtn-command nil 0 files
+  (apply #'vc-mtn-command nil 0 files
         (nconc (list "commit" "-m")
                (log-edit-extract-headers '(("Author" . "--author")
                                            ("Date" . "--date"))
@@ -227,7 +223,7 @@ switches."
 _SHORTLOG is ignored.
 If START-REVISION is non-nil, it is the newest revision to show.
 If LIMIT is non-nil, show no more than this many entries."
-  (apply 'vc-mtn-command buffer 0 files "log"
+  (apply #'vc-mtn-command buffer 0 files "log"
         (append
          (when start-revision (list "--from" (format "%s" start-revision)))
          (when limit (list "--last" (format "%s" limit))))))
@@ -258,7 +254,7 @@ If LIMIT is non-nil, show no more than this many entries."
 
 (defun vc-mtn-diff (files &optional rev1 rev2 buffer _async)
   "Get a difference report using monotone between two revisions of FILES."
-  (apply 'vc-mtn-command (or buffer "*vc-diff*")
+  (apply #'vc-mtn-command (or buffer "*vc-diff*")
         1 ; bug#21969
         files "diff"
          (append
diff --git a/lisp/vc/vc-rcs.el b/lisp/vc/vc-rcs.el
index 8d64ee5..6ffc1a8 100644
--- a/lisp/vc/vc-rcs.el
+++ b/lisp/vc/vc-rcs.el
@@ -58,8 +58,7 @@
 If nil, VC itself computes this value when it is first needed."
   :type '(choice (const :tag "Auto" nil)
                 (string :tag "Specified")
-                (const :tag "Unknown" unknown))
-  :group 'vc-rcs)
+                (const :tag "Unknown" unknown)))
 
 (defcustom vc-rcs-register-switches nil
   "Switches for registering a file in RCS.
@@ -70,8 +69,7 @@ If t, use no switches."
                 (const :tag "None" t)
                 (string :tag "Argument String")
                 (repeat :tag "Argument List" :value ("") string))
-  :version "21.1"
-  :group 'vc-rcs)
+  :version "21.1")
 
 (defcustom vc-rcs-diff-switches nil
   "String or list of strings specifying switches for RCS diff under VC.
@@ -80,21 +78,18 @@ If nil, use the value of `vc-diff-switches'.  If t, use no 
switches."
                  (const :tag "None" t)
                 (string :tag "Argument String")
                 (repeat :tag "Argument List" :value ("") string))
-  :version "21.1"
-  :group 'vc-rcs)
+  :version "21.1")
 
 (defcustom vc-rcs-header '("$Id\ $")
   "Header keywords to be inserted by `vc-insert-headers'."
   :type '(repeat string)
-  :version "24.1"     ; no longer consult the obsolete vc-header-alist
-  :group 'vc-rcs)
+  :version "24.1")     ; no longer consult the obsolete vc-header-alist
 
 (defcustom vc-rcsdiff-knows-brief nil
   "Indicates whether rcsdiff understands the --brief option.
 The value is either `yes', `no', or nil.  If it is nil, VC tries
 to use --brief and sets this variable to remember whether it worked."
-  :type '(choice (const :tag "Work out" nil) (const yes) (const no))
-  :group 'vc-rcs)
+  :type '(choice (const :tag "Work out" nil) (const yes) (const no)))
 
 ;; This needs to be autoloaded because vc-rcs-registered uses it (via
 ;; vc-default-registered), and vc-hooks needs to be able to check
@@ -109,8 +104,7 @@ For a description of possible values, see 
`vc-check-master-templates'."
                 (repeat :tag "User-specified"
                         (choice string
                                 function)))
-  :version "21.1"
-  :group 'vc-rcs)
+  :version "21.1")
 
 
 ;;; Properties of the backend
@@ -379,7 +373,7 @@ whether to remove it."
   "Retrieve a copy of a saved version of FILE.  If FILE is a directory,
 attempt the checkout for all registered files beneath it."
   (if (file-directory-p file)
-      (mapc 'vc-rcs-checkout (vc-expand-dirs (list file) 'RCS))
+      (mapc #'vc-rcs-checkout (vc-expand-dirs (list file) 'RCS))
     (let ((file-buffer (get-file-buffer file))
          switches)
       (message "Checking out %s..." file)
@@ -445,7 +439,7 @@ attempt the checkout for all registered files beneath it."
   "Revert FILE to the version it was based on.  If FILE is a directory,
 revert all registered files beneath it."
   (if (file-directory-p file)
-      (mapc 'vc-rcs-revert (vc-expand-dirs (list file) 'RCS))
+      (mapc #'vc-rcs-revert (vc-expand-dirs (list file) 'RCS))
     (vc-do-command "*vc*" 0 "co" (vc-master-name file) "-f"
                   (concat (if (eq (vc-state file) 'edited) "-u" "-r")
                           (vc-working-revision file)))))
@@ -488,7 +482,7 @@ The changes are between FIRST-VERSION and SECOND-VERSION."
 If FILE is a directory, steal the lock on all registered files beneath it.
 Needs RCS 5.6.2 or later for -M."
   (if (file-directory-p file)
-      (mapc 'vc-rcs-steal-lock (vc-expand-dirs (list file) 'RCS))
+      (mapc #'vc-rcs-steal-lock (vc-expand-dirs (list file) 'RCS))
     (vc-do-command "*vc*" 0 "rcs" (vc-master-name file) "-M" (concat "-u" rev))
     ;; Do a real checkout after stealing the lock, so that we see
     ;; expanded headers.
@@ -539,7 +533,7 @@ Remaining arguments are ignored.
 If FILE is a directory the operation is applied to all registered
 files beneath it."
   (vc-do-command (or buffer "*vc*") 0 "rlog"
-                 (mapcar 'vc-master-name (vc-expand-dirs files 'RCS)))
+                 (mapcar #'vc-master-name (vc-expand-dirs files 'RCS)))
   (with-current-buffer (or buffer "*vc*")
     (vc-rcs-print-log-cleanup))
   (when limit 'limit-unsupported))
@@ -1344,7 +1338,7 @@ The `:insn' key is a keyword to distinguish it as a 
vc-rcs.el extension."
           (push `(,(to-eol)
                   ,(k-semi 'date
                            (lambda ()
-                             (let ((ls (mapcar 'string-to-number
+                             (let ((ls (mapcar #'string-to-number
                                                (split-string
                                                 (buffer-substring-no-properties
                                                  b e)
diff --git a/lisp/vc/vc-sccs.el b/lisp/vc/vc-sccs.el
index 3d3f404..92cce5f 100644
--- a/lisp/vc/vc-sccs.el
+++ b/lisp/vc/vc-sccs.el
@@ -55,8 +55,7 @@ If t, use no switches."
                 (const :tag "None" t)
                 (string :tag "Argument String")
                 (repeat :tag "Argument List" :value ("") string))
-  :version "21.1"
-  :group 'vc-sccs)
+  :version "21.1")
 
 (defcustom vc-sccs-diff-switches nil
   "String or list of strings specifying switches for SCCS diff under VC.
@@ -65,14 +64,12 @@ If nil, use the value of `vc-diff-switches'.  If t, use no 
switches."
                 (const :tag "None" t)
                 (string :tag "Argument String")
                 (repeat :tag "Argument List" :value ("") string))
-  :version "21.1"
-  :group 'vc-sccs)
+  :version "21.1")
 
 (defcustom vc-sccs-header '("%W%")
   "Header keywords to be inserted by `vc-insert-headers'."
   :type '(repeat string)
-  :version "24.1"     ; no longer consult the obsolete vc-header-alist
-  :group 'vc-sccs)
+  :version "24.1")     ; no longer consult the obsolete vc-header-alist
 
 ;; This needs to be autoloaded because vc-sccs-registered uses it (via
 ;; vc-default-registered), and vc-hooks needs to be able to check
@@ -87,8 +84,7 @@ For a description of possible values, see 
`vc-check-master-templates'."
                 (repeat :tag "User-specified"
                         (choice string
                                 function)))
-  :version "21.1"
-  :group 'vc-sccs)
+  :version "21.1")
 
 
 ;;;
@@ -163,7 +159,7 @@ For a description of possible values, see 
`vc-check-master-templates'."
   "Write the SCCS version of input file FILE to output file OUTFILE.
 Optional string REV is a revision."
   (with-temp-buffer
-    (apply 'vc-sccs-do-command t 0 "get" (vc-master-name file)
+    (apply #'vc-sccs-do-command t 0 "get" (vc-master-name file)
           (append '("-s" "-p" "-k") ; -k: no keyword expansion
                   (if rev (list (concat "-r" rev)))))
     (write-region nil nil outfile nil 'silent)))
@@ -185,7 +181,7 @@ Optional string REV is a revision."
 (defun vc-sccs-do-command (buffer okstatus command file-or-list &rest flags)
   ;; (let ((load-path (append vc-sccs-path load-path)))
   ;;   (apply 'vc-do-command buffer okstatus command file-or-list flags))
-  (apply 'vc-do-command (or buffer "*vc*") okstatus "sccs" file-or-list 
command flags))
+  (apply #'vc-do-command (or buffer "*vc*") okstatus "sccs" file-or-list 
command flags))
 
 (defun vc-sccs-create-repo ()
   "Create a new SCCS repository."
@@ -207,7 +203,7 @@ to the SCCS command."
       (let ((vc-master-name
             (or project-file
                 (format (car vc-sccs-master-templates) dirname basename))))
-       (apply 'vc-sccs-do-command nil 0 "admin" vc-master-name
+       (apply #'vc-sccs-do-command nil 0 "admin" vc-master-name
               "-fb"
               (concat "-i" (file-relative-name file))
               (and comment (concat "-y" comment))
@@ -225,14 +221,14 @@ to the SCCS command."
 (defun vc-sccs-checkin (files comment &optional rev)
   "SCCS-specific version of `vc-backend-checkin'."
   (dolist (file (vc-expand-dirs files 'SCCS))
-    (apply 'vc-sccs-do-command nil 0 "delta" (vc-master-name file)
+    (apply #'vc-sccs-do-command nil 0 "delta" (vc-master-name file)
            (if rev (concat "-r" rev))
           (concat "-y" comment)
           (vc-switches 'SCCS 'checkin))
        (vc-sccs-do-command nil 0 "get" (vc-master-name file))))
 
 (defun vc-sccs-find-revision (file rev buffer)
-  (apply 'vc-sccs-do-command
+  (apply #'vc-sccs-do-command
         buffer 0 "get" (vc-master-name file)
         "-s" ;; suppress diagnostic output
         "-p"
@@ -247,7 +243,7 @@ If FILE is a directory, all version-controlled files 
beneath are checked out.
 EDITABLE non-nil means that the file should be writable and
 locked.  REV is the revision to check out."
   (if (file-directory-p file)
-      (mapc 'vc-sccs-checkout (vc-expand-dirs (list file) 'SCCS))
+      (mapc #'vc-sccs-checkout (vc-expand-dirs (list file) 'SCCS))
     (let ((file-buffer (get-file-buffer file))
          switches)
       (message "Checking out %s..." file)
@@ -267,7 +263,7 @@ locked.  REV is the revision to check out."
            (and rev (or (string= rev "")
                         (not (stringp rev)))
                 (setq rev nil))
-           (apply 'vc-sccs-do-command nil 0 "get" (vc-master-name file)
+           (apply #'vc-sccs-do-command nil 0 "get" (vc-master-name file)
                   "-e"
                   (and rev (concat "-r" (vc-sccs-lookup-triple file rev)))
                   switches))))
@@ -277,7 +273,7 @@ locked.  REV is the revision to check out."
   "Revert FILE to the version it was based on. If FILE is a directory,
 revert all subfiles."
   (if (file-directory-p file)
-      (mapc 'vc-sccs-revert (vc-expand-dirs (list file) 'SCCS))
+      (mapc #'vc-sccs-revert (vc-expand-dirs (list file) 'SCCS))
     (vc-sccs-do-command nil 0 "unget" (vc-master-name file))
     (vc-sccs-do-command nil 0 "get" (vc-master-name file))
     ;; Checking out explicit revisions is not supported under SCCS, yet.
@@ -288,7 +284,7 @@ revert all subfiles."
 (defun vc-sccs-steal-lock (file &optional rev)
   "Steal the lock on the current workfile for FILE and revision REV."
   (if (file-directory-p file)
-      (mapc 'vc-sccs-steal-lock (vc-expand-dirs (list file) 'SCCS))
+      (mapc #'vc-sccs-steal-lock (vc-expand-dirs (list file) 'SCCS))
     (vc-sccs-do-command nil 0 "unget"
                        (vc-master-name file) "-n" (if rev (concat "-r" rev)))
     (vc-sccs-do-command nil 0 "get"
@@ -309,7 +305,7 @@ revert all subfiles."
   "Print commit log associated with FILES into specified BUFFER.
 Remaining arguments are ignored."
   (setq files (vc-expand-dirs files 'SCCS))
-  (vc-sccs-do-command buffer 0 "prs" (mapcar 'vc-master-name files))
+  (vc-sccs-do-command buffer 0 "prs" (mapcar #'vc-master-name files))
   (when limit 'limit-unsupported))
 
 (autoload 'vc-setup-buffer "vc-dispatcher")
@@ -338,7 +334,7 @@ Remaining arguments are ignored."
           (fake-command
            (format "diff%s %s"
                    (if fake-flags
-                       (concat " " (mapconcat 'identity fake-flags " "))
+                       (concat " " (mapconcat #'identity fake-flags " "))
                      "")
                    (vc-delistify files)))
           (status 0)
@@ -362,7 +358,7 @@ Remaining arguments are ignored."
                      (cons "LC_MESSAGES=C" process-environment))
                     (w32-quote-process-args t)
                     (this-status
-                     (apply 'process-file "diff" nil t nil
+                     (apply #'process-file "diff" nil t nil
                             (append (vc-switches 'SCCS 'diff)
                                     (list (file-local-name oldfile)
                                           (or newfile
diff --git a/lisp/vc/vc-src.el b/lisp/vc/vc-src.el
index 201d69d..faba5bc 100644
--- a/lisp/vc/vc-src.el
+++ b/lisp/vc/vc-src.el
@@ -97,13 +97,11 @@
 If nil, VC itself computes this value when it is first needed."
   :type '(choice (const :tag "Auto" nil)
                 (string :tag "Specified")
-                (const :tag "Unknown" unknown))
-  :group 'vc-src)
+                (const :tag "Unknown" unknown)))
 
 (defcustom vc-src-program "src"
   "Name of the SRC executable (excluding any arguments)."
-  :type 'string
-  :group 'vc-src)
+  :type 'string)
 
 (defcustom vc-src-diff-switches nil
   "String or list of strings specifying switches for SRC diff under VC.
@@ -111,8 +109,7 @@ If nil, use the value of `vc-diff-switches'.  If t, use no 
switches."
   :type '(choice (const :tag "Unspecified" nil)
                  (const :tag "None" t)
                 (string :tag "Argument String")
-                (repeat :tag "Argument List" :value ("") string))
-  :group 'vc-src)
+                (repeat :tag "Argument List" :value ("") string)))
 
 ;; This needs to be autoloaded because vc-src-registered uses it (via
 ;; vc-default-registered), and vc-hooks needs to be able to check
@@ -126,8 +123,7 @@ For a description of possible values, see 
`vc-check-master-templates'."
                        '("%s.src/%s,v"))
                 (repeat :tag "User-specified"
                         (choice string
-                                function)))
-  :group 'vc-src)
+                                function))))
 
 
 ;;; Properties of the backend
@@ -221,7 +217,7 @@ This function differs from vc-do-command in that it invokes 
`vc-src-program'."
           (setq file-list (list "--" file-or-list)))
          (file-or-list
           (setq file-list (cons "--" file-or-list))))
-    (apply 'vc-do-command (or buffer "*vc*") 0 vc-src-program file-list 
flags)))
+    (apply #'vc-do-command (or buffer "*vc*") 0 vc-src-program file-list 
flags)))
 
 (defun vc-src-working-revision (file)
   "SRC-specific version of `vc-working-revision'."
@@ -275,7 +271,7 @@ REV is the revision to check out into WORKFILE."
   "Revert FILE to the version it was based on.  If FILE is a directory,
 revert all registered files beneath it."
   (if (file-directory-p file)
-      (mapc 'vc-src-revert (vc-expand-dirs (list file) 'SRC))
+      (mapc #'vc-src-revert (vc-expand-dirs (list file) 'SRC))
     (vc-src-command nil file "co")))
 
 (defun vc-src-modify-change-comment (files rev comment)
@@ -290,8 +286,7 @@ directory the operation is applied to all registered files 
beneath it."
   "String or list of strings specifying switches for src log under VC."
   :type '(choice (const :tag "None" nil)
                  (string :tag "Argument String")
-                 (repeat :tag "Argument List" :value ("") string))
-  :group 'vc-src)
+                 (repeat :tag "Argument List" :value ("") string)))
 
 (defun vc-src-print-log (files buffer &optional shortlog _start-revision limit)
   "Print commit log associated with FILES into specified BUFFER.
@@ -307,7 +302,7 @@ If LIMIT is non-nil, show no more than this many entries."
   (let ((inhibit-read-only t))
     (with-current-buffer
        buffer
-      (apply 'vc-src-command buffer files (if shortlog "list" "log")
+      (apply #'vc-src-command buffer files (if shortlog "list" "log")
             (nconc
              ;;(when start-revision (list (format "%s-1" start-revision)))
              (when limit (list "-l" (format "%s" limit)))
diff --git a/lisp/vc/vc-svn.el b/lisp/vc/vc-svn.el
index 22becc9..c30920d 100644
--- a/lisp/vc/vc-svn.el
+++ b/lisp/vc/vc-svn.el
@@ -47,8 +47,7 @@
 ;; FIXME there is also svnadmin.
 (defcustom vc-svn-program "svn"
   "Name of the SVN executable."
-  :type 'string
-  :group 'vc-svn)
+  :type 'string)
 
 ;; Might be nice if svn defaulted to non-interactive if stdin not tty.
 ;; https://svn.haxx.se/dev/archive-2008-05/0762.shtml
@@ -64,8 +63,7 @@ hanging while prompting for authorization."
                 (repeat :tag "Argument List"
                         :value ("")
                         string))
-  :version "24.4"
-  :group 'vc-svn)
+  :version "24.4")
 
 (defcustom vc-svn-register-switches nil
   "Switches for registering a file into SVN.
@@ -76,8 +74,7 @@ If t, use no switches."
                 (const :tag "None" t)
                 (string :tag "Argument String")
                 (repeat :tag "Argument List" :value ("") string))
-  :version "22.1"
-  :group 'vc-svn)
+  :version "22.1")
 
 (defcustom vc-svn-diff-switches
   t                       ;`svn' doesn't support common args like -c or -b.
@@ -92,8 +89,7 @@ If you want to force an empty list of arguments, use t."
                 (repeat :tag "Argument List"
                         :value ("")
                         string))
-  :version "22.1"
-  :group 'vc-svn)
+  :version "22.1")
 
 (defcustom vc-svn-annotate-switches nil
   "String or list of strings specifying switches for svn annotate under VC.
@@ -103,14 +99,12 @@ switches."
                 (const :tag "None" t)
                 (string :tag "Argument String")
                 (repeat :tag "Argument List" :value ("") string))
-  :version "25.1"
-  :group 'vc-svn)
+  :version "25.1")
 
 (defcustom vc-svn-header '("$Id\ $")
   "Header keywords to be inserted by `vc-insert-headers'."
   :version "24.1"     ; no longer consult the obsolete vc-header-alist
-  :type '(repeat string)
-  :group 'vc-svn)
+  :type '(repeat string))
 
 ;; We want to autoload it for use by the autoloaded version of
 ;; vc-svn-registered, but we want the value to be compiled at startup, not
@@ -305,19 +299,19 @@ RESULT is a list of conses (FILE . STATE) for directory 
DIR."
 The COMMENT argument is ignored  This does an add but not a commit.
 Passes either `vc-svn-register-switches' or `vc-register-switches'
 to the SVN command."
-  (apply 'vc-svn-command nil 0 files "add" (vc-switches 'SVN 'register)))
+  (apply #'vc-svn-command nil 0 files "add" (vc-switches 'SVN 'register)))
 
 (defun vc-svn-root (file)
   (vc-find-root file vc-svn-admin-directory))
 
-(defalias 'vc-svn-responsible-p 'vc-svn-root)
+(defalias 'vc-svn-responsible-p #'vc-svn-root)
 
 (declare-function log-edit-extract-headers "log-edit" (headers string))
 
 (defun vc-svn-checkin (files comment &optional _extra-args-ignored)
   "SVN-specific version of `vc-backend-checkin'."
   (let ((status (apply
-                 'vc-svn-command nil 1 files "ci"
+                 #'vc-svn-command nil 1 files "ci"
                  (nconc (cons "-m" (log-edit-extract-headers nil comment))
                         (vc-switches 'SVN 'checkin)))))
     (set-buffer "*vc*")
@@ -345,7 +339,7 @@ to the SVN command."
 (defun vc-svn-find-revision (file rev buffer)
   "SVN-specific retrieval of a specified version into a buffer."
   (let (process-file-side-effects)
-    (apply 'vc-svn-command
+    (apply #'vc-svn-command
           buffer 0 file
           "cat"
           (and rev (not (string= rev ""))
@@ -391,7 +385,7 @@ DIRECTORY or absolute."
       nil
     ;; Check out a particular version (or recreate the file).
     (vc-file-setprop file 'vc-working-revision nil)
-    (apply 'vc-svn-command nil 0 file
+    (apply #'vc-svn-command nil 0 file
           "update"
           (cond
            ((null rev) "-rBASE")
@@ -563,27 +557,27 @@ If LIMIT is non-nil, show no more than this many entries."
       (goto-char (point-min))
       (if files
          (dolist (file files)
-                 (insert "Working file: " file "\n")
-                 (apply
-                  'vc-svn-command
-                  buffer
-                  'async
-                  (list file)
-                  "log"
-                  (append
-                   (list
-                    (if start-revision
-                        (format "-r%s:1" start-revision)
-                      ;; By default Subversion only shows the log up to the
-                      ;; working revision, whereas we also want the log of the
-                      ;; subsequent commits.  At least that's what the
-                      ;; vc-cvs.el code does.
-                      "-rHEAD:0"))
-                    (if (eq vc-log-view-type 'with-diff)
-                        (list "--diff"))
-                    (when limit (list "--limit" (format "%s" limit))))))
+           (insert "Working file: " file "\n")
+           (apply
+            #'vc-svn-command
+            buffer
+            'async
+            (list file)
+            "log"
+            (append
+             (list
+              (if start-revision
+                  (format "-r%s:1" start-revision)
+                ;; By default Subversion only shows the log up to the
+                ;; working revision, whereas we also want the log of the
+                ;; subsequent commits.  At least that's what the
+                ;; vc-cvs.el code does.
+                "-rHEAD:0"))
+              (if (eq vc-log-view-type 'with-diff)
+                  (list "--diff"))
+              (when limit (list "--limit" (format "%s" limit))))))
        ;; Dump log for the entire directory.
-       (apply 'vc-svn-command buffer 0 nil "log"
+       (apply #'vc-svn-command buffer 0 nil "log"
               (append
                (list
                 (if start-revision (format "-r%s" start-revision) "-rHEAD:0"))
@@ -611,8 +605,8 @@ If LIMIT is non-nil, show no more than this many entries."
            (if vc-svn-diff-switches
                (vc-switches 'SVN 'diff)
              (list (concat "--diff-cmd=" diff-command) "-x"
-                   (mapconcat 'identity (vc-switches nil 'diff) " ")))))
-      (apply 'vc-svn-command buffer
+                   (mapconcat #'identity (vc-switches nil 'diff) " ")))))
+      (apply #'vc-svn-command buffer
             (if async 'async 0)
             files "diff"
             (append
@@ -671,7 +665,7 @@ NAME is assumed to be a URL."
   "A wrapper around `vc-do-command' for use in vc-svn.el.
 The difference to vc-do-command is that this function always invokes `svn',
 and that it passes `vc-svn-global-switches' to it before FLAGS."
-  (apply 'vc-do-command (or buffer "*vc*") okstatus vc-svn-program file-or-list
+  (apply #'vc-do-command (or buffer "*vc*") okstatus vc-svn-program 
file-or-list
          (if (stringp vc-svn-global-switches)
              (cons vc-svn-global-switches flags)
            (append vc-svn-global-switches flags))))
@@ -683,7 +677,7 @@ and that it passes `vc-svn-global-switches' to it before 
FLAGS."
     (unless (re-search-forward "^<<<<<<< " nil t)
       (vc-svn-command nil 0 buffer-file-name "resolved")
       ;; Remove the hook so that it is not called multiple times.
-      (remove-hook 'after-save-hook 'vc-svn-resolve-when-done t))))
+      (remove-hook 'after-save-hook #'vc-svn-resolve-when-done t))))
 
 ;; Inspired by vc-arch-find-file-hook.
 (defun vc-svn-find-file-hook ()
@@ -696,7 +690,7 @@ and that it passes `vc-svn-global-switches' to it before 
FLAGS."
         ;; There are conflict markers.
         (progn
           (smerge-start-session)
-          (add-hook 'after-save-hook 'vc-svn-resolve-when-done nil t))
+          (add-hook 'after-save-hook #'vc-svn-resolve-when-done nil t))
       ;; There are no conflict markers.  This is problematic: maybe it means
       ;; the conflict has been resolved and we should immediately call "svn
       ;; resolved", or it means that the file's type does not allow Svn to
diff --git a/lisp/vc/vc.el b/lisp/vc/vc.el
index 00976a0..95126fa 100644
--- a/lisp/vc/vc.el
+++ b/lisp/vc/vc.el
@@ -1425,6 +1425,7 @@ first backend that could register the file is used."
   (let ((vc-handled-backends (list backend)))
     (call-interactively 'vc-register)))
 
+;;;###autoload
 (defun vc-ignore (file &optional directory remove)
   "Ignore FILE under the VCS of DIRECTORY.
 
@@ -1831,7 +1832,7 @@ Return t if the buffer had changes, nil otherwise."
          (backend (car vc-fileset))
          (first (car files))
          (rev1-default nil)
-         (rev2-default nil))
+         ) ;; (rev2-default nil)
     (cond
      ;; someday we may be able to do revision completion on non-singleton
      ;; filesets, but not yet.
@@ -1855,9 +1856,10 @@ Return t if the buffer had changes, nil otherwise."
                                     rev1-default "): ")
                           "Older revision: "))
            (rev2-prompt (concat "Newer revision (default "
-                                (or rev2-default "current source") "): "))
+                                ;; (or rev2-default
+                                "current source): "))
            (rev1 (vc-read-revision rev1-prompt files backend rev1-default))
-           (rev2 (vc-read-revision rev2-prompt files backend rev2-default)))
+           (rev2 (vc-read-revision rev2-prompt files backend nil))) ;; 
rev2-default
       (when (string= rev1 "") (setq rev1 nil))
       (when (string= rev2 "") (setq rev2 nil))
       (list files rev1 rev2))))
diff --git a/lisp/view.el b/lisp/view.el
index 026c1ec..3476ced 100644
--- a/lisp/view.el
+++ b/lisp/view.el
@@ -1,4 +1,4 @@
-;;; view.el --- peruse file or buffer without editing
+;;; view.el --- peruse file or buffer without editing  -*- lexical-binding: t 
-*-
 
 ;; Copyright (C) 1985, 1989, 1994-1995, 1997, 2000-2021 Free Software
 ;; Foundation, Inc.
@@ -26,9 +26,9 @@
 
 ;; This package provides the `view' minor mode documented in the Emacs
 ;; user's manual.
-;; View mode entry and exit is done through the functions view-mode-enter
-;; and view-mode-exit.  Use these functions to enter or exit view-mode from
-;; emacs lisp programs.
+;; View mode entry and exit is done through the functions `view-mode-enter'
+;; and `view-mode-exit'.  Use these functions to enter or exit `view-mode' from
+;; Emacs Lisp programs.
 ;; We use both view- and View- as prefix for symbols.  View- is used as
 ;; prefix for commands that have a key binding.  view- is used for commands
 ;; without key binding.  The purpose of this is to make it easier for a
@@ -36,11 +36,11 @@
 
 ;;; Suggested key bindings:
 ;;
-;; (define-key ctl-x-4-map "v" 'view-file-other-window)  ; ^x4v
-;; (define-key ctl-x-5-map "v" 'view-file-other-frame)  ; ^x5v
+;; (define-key ctl-x-4-map "v" #'view-file-other-window)  ; ^x4v
+;; (define-key ctl-x-5-map "v" #'view-file-other-frame)   ; ^x5v
 ;;
-;; You could also bind view-file, view-buffer, view-buffer-other-window and
-;; view-buffer-other-frame to keys.
+;; You could also bind `view-file', `view-buffer', `view-buffer-other-window' 
and
+;; `view-buffer-other-frame' to keys.
 
 ;;; Code:
 
@@ -51,31 +51,27 @@
   :group 'text)
 
 (defcustom view-highlight-face 'highlight
-   "The face used for highlighting the match found by View mode search."
-   :type 'face
-   :group 'view)
+  "The face used for highlighting the match found by View mode search."
+  :type 'face)
 
 (defcustom view-scroll-auto-exit nil
   "Non-nil means scrolling past the end of buffer exits View mode.
 A value of nil means attempting to scroll past the end of the buffer,
 only rings the bell and gives a message on how to leave."
-  :type 'boolean
-  :group 'view)
+  :type 'boolean)
 
 (defcustom view-try-extend-at-buffer-end nil
  "Non-nil means try to load more of file when reaching end of buffer.
 This variable is mainly intended to be temporarily set to non-nil by
-the F command in view-mode, but you can set it to t if you want the action
+the F command in `view-mode', but you can set it to t if you want the action
 for all scroll commands in view mode."
-  :type 'boolean
-  :group 'view)
+  :type 'boolean)
 
 ;;;###autoload
 (defcustom view-remove-frame-by-deleting t
   "Determine how View mode removes a frame no longer needed.
 If nil, make an icon of the frame.  If non-nil, delete the frame."
   :type 'boolean
-  :group 'view
   :version "23.1")
 
 (defcustom view-exits-all-viewing-windows nil
@@ -84,15 +80,13 @@ Commands that restore windows when finished viewing a 
buffer,
 apply to all windows that display the buffer and have restore
 information.  If `view-exits-all-viewing-windows' is nil, only
 the selected window is considered for restoring."
-  :type 'boolean
-  :group 'view)
+  :type 'boolean)
 
 (defcustom view-inhibit-help-message nil
   "Non-nil inhibits the help message shown upon entering View mode.
 This setting takes effect only when View mode is entered via an
 interactive command; otherwise the help message is not shown."
   :type 'boolean
-  :group 'view
   :version "22.1")
 
 ;;;###autoload
@@ -103,8 +97,7 @@ functions that enable or disable view mode.")
 
 (defcustom view-mode-hook nil
   "Normal hook run when starting to view a buffer or file."
-  :type 'hook
-  :group 'view)
+  :type 'hook)
 
 (defvar-local view-old-buffer-read-only nil)
 
@@ -154,62 +147,62 @@ This is local in each buffer, once it is used.")
 ;; Some redundant "less"-like key bindings below have been commented out.
 (defvar view-mode-map
   (let ((map (make-sparse-keymap)))
-    (define-key map "C" 'View-kill-and-leave)
-    (define-key map "c" 'View-leave)
-    (define-key map "Q" 'View-quit-all)
-    (define-key map "E" 'View-exit-and-edit)
-    ;; (define-key map "v" 'View-exit)
-    (define-key map "e" 'View-exit)
-    (define-key map "q" 'View-quit)
-    ;; (define-key map "N" 'View-search-last-regexp-backward)
-    (define-key map "p" 'View-search-last-regexp-backward)
-    (define-key map "n" 'View-search-last-regexp-forward)
-    ;; (define-key map "?" 'View-search-regexp-backward) ; Less does this.
-    (define-key map "\\" 'View-search-regexp-backward)
-    (define-key map "/" 'View-search-regexp-forward)
-    (define-key map "r" 'isearch-backward)
-    (define-key map "s" 'isearch-forward)
-    (define-key map "m" 'point-to-register)
-    (define-key map "'" 'register-to-point)
-    (define-key map "x" 'exchange-point-and-mark)
-    (define-key map "@" 'View-back-to-mark)
-    (define-key map "." 'set-mark-command)
-    (define-key map "%" 'View-goto-percent)
-    ;; (define-key map "G" 'View-goto-line-last)
-    (define-key map "g" 'View-goto-line)
-    (define-key map "=" 'what-line)
-    (define-key map "F" 'View-revert-buffer-scroll-page-forward)
-    ;; (define-key map "k" 'View-scroll-line-backward)
-    (define-key map "y" 'View-scroll-line-backward)
-    ;; (define-key map "j" 'View-scroll-line-forward)
-    (define-key map "\n" 'View-scroll-line-forward)
-    (define-key map "\r" 'View-scroll-line-forward)
-    (define-key map "u" 'View-scroll-half-page-backward)
-    (define-key map "d" 'View-scroll-half-page-forward)
-    (define-key map "z" 'View-scroll-page-forward-set-page-size)
-    (define-key map "w" 'View-scroll-page-backward-set-page-size)
-    ;; (define-key map "b" 'View-scroll-page-backward)
-    (define-key map "\C-?" 'View-scroll-page-backward)
-    ;; (define-key map "f" 'View-scroll-page-forward)
-    (define-key map " " 'View-scroll-page-forward)
-    (define-key map [?\S-\ ]  'View-scroll-page-backward)
-    (define-key map "o" 'View-scroll-to-buffer-end)
-    (define-key map ">" 'end-of-buffer)
-    (define-key map "<" 'beginning-of-buffer)
-    (define-key map "-" 'negative-argument)
-    (define-key map "9" 'digit-argument)
-    (define-key map "8" 'digit-argument)
-    (define-key map "7" 'digit-argument)
-    (define-key map "6" 'digit-argument)
-    (define-key map "5" 'digit-argument)
-    (define-key map "4" 'digit-argument)
-    (define-key map "3" 'digit-argument)
-    (define-key map "2" 'digit-argument)
-    (define-key map "1" 'digit-argument)
-    (define-key map "0" 'digit-argument)
-    (define-key map "H" 'describe-mode)
-    (define-key map "?" 'describe-mode)        ; Maybe do as less instead? See 
above.
-    (define-key map "h" 'describe-mode)
+    (define-key map "C" #'View-kill-and-leave)
+    (define-key map "c" #'View-leave)
+    (define-key map "Q" #'View-quit-all)
+    (define-key map "E" #'View-exit-and-edit)
+    ;; (define-key map "v" #'View-exit)
+    (define-key map "e" #'View-exit)
+    (define-key map "q" #'View-quit)
+    ;; (define-key map "N" #'View-search-last-regexp-backward)
+    (define-key map "p" #'View-search-last-regexp-backward)
+    (define-key map "n" #'View-search-last-regexp-forward)
+    ;; (define-key map "?" #'View-search-regexp-backward) ; Less does this.
+    (define-key map "\\" #'View-search-regexp-backward)
+    (define-key map "/" #'View-search-regexp-forward)
+    (define-key map "r" #'isearch-backward)
+    (define-key map "s" #'isearch-forward)
+    (define-key map "m" #'point-to-register)
+    (define-key map "'" #'register-to-point)
+    (define-key map "x" #'exchange-point-and-mark)
+    (define-key map "@" #'View-back-to-mark)
+    (define-key map "." #'set-mark-command)
+    (define-key map "%" #'View-goto-percent)
+    ;; (define-key map "G" #'View-goto-line-last)
+    (define-key map "g" #'View-goto-line)
+    (define-key map "=" #'what-line)
+    (define-key map "F" #'View-revert-buffer-scroll-page-forward)
+    ;; (define-key map "k" #'View-scroll-line-backward)
+    (define-key map "y" #'View-scroll-line-backward)
+    ;; (define-key map "j" #'View-scroll-line-forward)
+    (define-key map "\n" #'View-scroll-line-forward)
+    (define-key map "\r" #'View-scroll-line-forward)
+    (define-key map "u" #'View-scroll-half-page-backward)
+    (define-key map "d" #'View-scroll-half-page-forward)
+    (define-key map "z" #'View-scroll-page-forward-set-page-size)
+    (define-key map "w" #'View-scroll-page-backward-set-page-size)
+    ;; (define-key map "b" #'View-scroll-page-backward)
+    (define-key map "\C-?" #'View-scroll-page-backward)
+    ;; (define-key map "f" #'View-scroll-page-forward)
+    (define-key map " " #'View-scroll-page-forward)
+    (define-key map [?\S-\ ] #'View-scroll-page-backward)
+    (define-key map "o" #'View-scroll-to-buffer-end)
+    (define-key map ">" #'end-of-buffer)
+    (define-key map "<" #'beginning-of-buffer)
+    (define-key map "-" #'negative-argument)
+    (define-key map "9" #'digit-argument)
+    (define-key map "8" #'digit-argument)
+    (define-key map "7" #'digit-argument)
+    (define-key map "6" #'digit-argument)
+    (define-key map "5" #'digit-argument)
+    (define-key map "4" #'digit-argument)
+    (define-key map "3" #'digit-argument)
+    (define-key map "2" #'digit-argument)
+    (define-key map "1" #'digit-argument)
+    (define-key map "0" #'digit-argument)
+    (define-key map "H" #'describe-mode)
+    (define-key map "?" #'describe-mode)       ; Maybe do as less instead? See 
above.
+    (define-key map "h" #'describe-mode)
     map))
 
 ;;; Commands that enter or exit view mode.
@@ -220,7 +213,7 @@ This is local in each buffer, once it is used.")
 ;; types C-x C-q again to return to view mode.
 ;;;###autoload
 (defun kill-buffer-if-not-modified (buf)
-  "Like `kill-buffer', but does nothing if the buffer is modified."
+  "Like `kill-buffer', but does nothing if buffer BUF is modified."
   (let ((buf (get-buffer buf)))
     (and buf (not (buffer-modified-p buf))
         (kill-buffer buf))))
@@ -305,7 +298,7 @@ file: Users may suspend viewing in order to modify the 
buffer.
 Exiting View mode will then discard the user's edits.  Setting
 EXIT-ACTION to `kill-buffer-if-not-modified' avoids this.
 
-This function does not enable View mode if the buffer's major-mode
+This function does not enable View mode if the buffer's major mode
 has a `special' mode-class, because such modes usually have their
 own View-like bindings."
   (interactive "bView buffer: ")
@@ -331,7 +324,7 @@ Optional argument EXIT-ACTION is either nil or a function 
with buffer as
 argument.  This function is called when finished viewing buffer.  Use
 this argument instead of explicitly setting `view-exit-action'.
 
-This function does not enable View mode if the buffer's major-mode
+This function does not enable View mode if the buffer's major mode
 has a `special' mode-class, because such modes usually have their
 own View-like bindings."
   (interactive "bIn other window view buffer:\nP")
@@ -358,7 +351,7 @@ Optional argument EXIT-ACTION is either nil or a function 
with buffer as
 argument.  This function is called when finished viewing buffer.  Use
 this argument instead of explicitly setting `view-exit-action'.
 
-This function does not enable View mode if the buffer's major-mode
+This function does not enable View mode if the buffer's major mode
 has a `special' mode-class, because such modes usually have their
 own View-like bindings."
   (interactive "bView buffer in other frame: \nP")
@@ -662,8 +655,8 @@ previous state and go to previous buffer or window."
   (recenter '(1)))
 
 (defun view-page-size-default (lines)
-  ;; If LINES is nil, 0, or larger than `view-window-size', return nil.
-  ;; Otherwise, return LINES.
+  "If LINES is nil, 0, or larger than `view-window-size', return nil.
+Otherwise, return LINES."
   (and lines
        (not (zerop (setq lines (prefix-numeric-value lines))))
        (<= (abs lines)
@@ -671,7 +664,7 @@ previous state and go to previous buffer or window."
        (abs lines)))
 
 (defun view-set-half-page-size-default (lines)
-  ;; Get and maybe set half page size.
+  "Get and maybe set half page size."
   (if (not lines) (or view-half-page-size
                      (/ (view-window-size) 2))
     (setq view-half-page-size
@@ -749,7 +742,7 @@ invocations return to earlier marks."
           (if (view-really-at-end) (view-end-message)))))
 
 (defun view-really-at-end ()
-  ;; Return true if buffer end visible.  Maybe revert buffer and test.
+  "Return non-nil if buffer end visible.  Maybe revert buffer and test."
   (and (or (null scroll-error-top-bottom) (eobp))
        (pos-visible-in-window-p (point-max))
        (let ((buf (current-buffer))
@@ -772,7 +765,7 @@ invocations return to earlier marks."
               (pos-visible-in-window-p (point-max)))))))
 
 (defun view-end-message ()
-  ;; Tell that we are at end of buffer.
+  "Tell that we are at end of buffer."
   (goto-char (point-max))
   (if (window-parameter nil 'quit-restore)
       (message "End of buffer.  Type %s to quit viewing."
@@ -979,7 +972,7 @@ for highlighting the match that is found."
 ;; https://lists.gnu.org/r/bug-gnu-emacs/2007-09/msg00073.html
 (defun view-search-no-match-lines (times regexp)
   "Search for the TIMESth occurrence of a line with no match for REGEXP.
-If such a line is found, return non-nil and set the match-data to that line.
+If such a line is found, return non-nil and set the match data to that line.
 If TIMES is negative, search backwards."
   (let ((step (if (>= times 0) 1
                 (setq times (- times))
diff --git a/lisp/w32-fns.el b/lisp/w32-fns.el
index 9ef2da7..2548fa4 100644
--- a/lisp/w32-fns.el
+++ b/lisp/w32-fns.el
@@ -255,6 +255,7 @@ bit output with no translation."
   (w32-add-charset-info "iso8859-2" 'w32-charset-easteurope 28592)
   (w32-add-charset-info "iso8859-3" 'w32-charset-turkish 28593)
   (w32-add-charset-info "iso8859-4" 'w32-charset-baltic 28594)
+  (w32-add-charset-info "iso8859-5" 'w32-charset-russian 28595)
   (w32-add-charset-info "iso8859-6" 'w32-charset-arabic 28596)
   (w32-add-charset-info "iso8859-7" 'w32-charset-greek 28597)
   (w32-add-charset-info "iso8859-8" 'w32-charset-hebrew 1255)
diff --git a/lisp/wdired.el b/lisp/wdired.el
index a096abd..ff42d78 100644
--- a/lisp/wdired.el
+++ b/lisp/wdired.el
@@ -1,4 +1,4 @@
-;;; wdired.el --- Rename files editing their names in dired buffers -*- 
coding: utf-8; -*-
+;;; wdired.el --- Rename files editing their names in dired buffers -*- 
coding: utf-8; lexical-binding: t; -*-
 
 ;; Copyright (C) 2004-2021 Free Software Foundation, Inc.
 
@@ -85,15 +85,13 @@
 If nil, WDired doesn't require confirmation to change the file names,
 and the variable `wdired-confirm-overwrite' controls whether it is ok
 to overwrite files without asking."
-  :type 'boolean
-  :group 'wdired)
+  :type 'boolean)
 
 (defcustom wdired-confirm-overwrite t
   "If nil the renames can overwrite files without asking.
 This variable has no effect at all if `wdired-use-interactive-rename'
 is not nil."
-  :type 'boolean
-  :group 'wdired)
+  :type 'boolean)
 
 (defcustom wdired-use-dired-vertical-movement nil
   "If t, the \"up\" and \"down\" movement works as in Dired mode.
@@ -106,15 +104,13 @@ when editing several filenames.
 If nil, \"up\" and \"down\" movement is done as in any other buffer."
   :type '(choice (const :tag "As in any other mode" nil)
                 (const :tag "Smart cursor placement" sometimes)
-                (other :tag "As in dired mode" t))
-  :group 'wdired)
+                (other :tag "As in dired mode" t)))
 
 (defcustom wdired-allow-to-redirect-links t
   "If non-nil, the target of the symbolic links are editable.
 In systems without symbolic links support, this variable has no effect
 at all."
-  :type 'boolean
-  :group 'wdired)
+  :type 'boolean)
 
 (defcustom wdired-allow-to-change-permissions nil
   "If non-nil, the permissions bits of the files are editable.
@@ -135,8 +131,7 @@ Anyway, the real change of the permissions is done by the 
external
 program `dired-chmod-program', which must exist."
   :type '(choice (const :tag "Not allowed" nil)
                  (const :tag "Toggle/set bits" t)
-                (other :tag "Bits freely editable" advanced))
-  :group 'wdired)
+                (other :tag "Bits freely editable" advanced)))
 
 (defcustom wdired-keep-marker-rename t
   ;; Use t as default so that renamed files "take their markers with them".
@@ -149,8 +144,7 @@ See `dired-keep-marker-rename' if you want to do the same 
for files
 renamed by `dired-do-rename' and `dired-do-rename-regexp'."
   :type '(choice (const :tag "Keep" t)
                 (character :tag "Mark" :value ?R))
-  :version "24.3"
-  :group 'wdired)
+  :version "24.3")
 
 (defcustom wdired-create-parent-directories t
   "If non-nil, create parent directories of destination files.
@@ -159,51 +153,47 @@ nonexistent directory, wdired will create any parent 
directories
 necessary.  When nil, attempts to rename a file into a
 nonexistent directory will fail."
   :version "26.1"
-  :type 'boolean
-  :group 'wdired)
+  :type 'boolean)
 
 (defvar wdired-mode-map
   (let ((map (make-sparse-keymap)))
-    (define-key map "\C-x\C-s" 'wdired-finish-edit)
-    (define-key map "\C-c\C-c" 'wdired-finish-edit)
-    (define-key map "\C-c\C-k" 'wdired-abort-changes)
-    (define-key map "\C-c\C-[" 'wdired-abort-changes)
-    (define-key map "\C-x\C-q" 'wdired-exit)
-    (define-key map "\C-m"     'ignore)
-    (define-key map "\C-j"     'ignore)
-    (define-key map "\C-o"     'ignore)
-    (define-key map [up]       'wdired-previous-line)
-    (define-key map "\C-p"     'wdired-previous-line)
-    (define-key map [down]     'wdired-next-line)
-    (define-key map "\C-n"     'wdired-next-line)
-
-    (define-key map [menu-bar wdired]
-      (cons "WDired" (make-sparse-keymap "WDired")))
-    (define-key map [menu-bar wdired wdired-customize]
-      '("Options" . wdired-customize))
-    (define-key map [menu-bar wdired dashes]
-      '("--"))
-    (define-key map [menu-bar wdired wdired-abort-changes]
-      '(menu-item "Abort Changes" wdired-abort-changes
-                 :help "Abort changes and return to dired mode"))
-    (define-key map [menu-bar wdired wdired-finish-edit]
-      '("Commit Changes" . wdired-finish-edit))
-
-    (define-key map [remap upcase-word] 'wdired-upcase-word)
-    (define-key map [remap capitalize-word] 'wdired-capitalize-word)
-    (define-key map [remap downcase-word] 'wdired-downcase-word)
-
+    (define-key map "\C-x\C-s" #'wdired-finish-edit)
+    (define-key map "\C-c\C-c" #'wdired-finish-edit)
+    (define-key map "\C-c\C-k" #'wdired-abort-changes)
+    (define-key map "\C-c\C-[" #'wdired-abort-changes)
+    (define-key map "\C-x\C-q" #'wdired-exit)
+    (define-key map "\C-m"     #'undefined)
+    (define-key map "\C-j"     #'undefined)
+    (define-key map "\C-o"     #'undefined)
+    (define-key map [up]       #'wdired-previous-line)
+    (define-key map "\C-p"     #'wdired-previous-line)
+    (define-key map [down]     #'wdired-next-line)
+    (define-key map "\C-n"     #'wdired-next-line)
+    (define-key map [remap upcase-word] #'wdired-upcase-word)
+    (define-key map [remap capitalize-word] #'wdired-capitalize-word)
+    (define-key map [remap downcase-word] #'wdired-downcase-word)
+    (define-key map [remap self-insert-command] #'wdired--self-insert)
     map)
   "Keymap used in `wdired-mode'.")
 
+(easy-menu-define wdired-mode-menu wdired-mode-map
+  "Menu for `wdired-mode'."
+  '("WDired"
+    ["Commit Changes" wdired-finish-edit]
+    ["Abort Changes" wdired-abort-changes
+     :help "Abort changes and return to Dired mode"]
+    "---"
+    ["Options" wdired-customize]))
+
 (defvar wdired-mode-hook nil
   "Hooks run when changing to WDired mode.")
 
 ;; Local variables (put here to avoid compilation gripes)
-(defvar wdired-col-perm) ;; Column where the permission bits start
-(defvar wdired-old-content)
-(defvar wdired-old-point)
-(defvar wdired-old-marks)
+(defvar wdired--perm-beg) ;; Column where the permission bits start
+(defvar wdired--perm-end) ;; Column where the permission bits stop
+(defvar wdired--old-content)
+(defvar wdired--old-point)
+(defvar wdired--old-marks)
 
 (defun wdired-mode ()
   "Writable Dired (WDired) mode.
@@ -242,11 +232,12 @@ See `wdired-mode'."
   (interactive)
   (unless (derived-mode-p 'dired-mode)
     (error "Not a Dired buffer"))
-  (setq-local wdired-old-content
+  (setq-local wdired--old-content
               (buffer-substring (point-min) (point-max)))
-  (setq-local wdired-old-marks
+  (setq-local wdired--old-marks
               (dired-remember-marks (point-min) (point-max)))
-  (setq-local wdired-old-point (point))
+  (setq-local wdired--old-point (point))
+  (wdired--set-permission-bounds)
   (setq-local query-replace-skip-read-only t)
   (add-function :after-while (local 'isearch-filter-predicate)
                 #'wdired-isearch-filter-read-only)
@@ -254,21 +245,12 @@ See `wdired-mode'."
   (force-mode-line-update)
   (setq buffer-read-only nil)
   (dired-unadvertise default-directory)
-  (add-hook 'kill-buffer-hook 'wdired-check-kill-buffer nil t)
-  (add-hook 'after-change-functions 'wdired--restore-properties nil t)
+  (add-hook 'kill-buffer-hook #'wdired-check-kill-buffer nil t)
+  (add-hook 'before-change-functions #'wdired--before-change-fn nil t)
+  (add-hook 'after-change-functions #'wdired--restore-properties nil t)
   (setq major-mode 'wdired-mode)
   (setq mode-name "Editable Dired")
-  (setq revert-buffer-function 'wdired-revert)
-  ;; I temp disable undo for performance: since I'm going to clear the
-  ;; undo list, it can save more than a 9% of time with big
-  ;; directories because setting properties modify the undo-list.
-  (buffer-disable-undo)
-  (wdired-preprocess-files)
-  (if wdired-allow-to-change-permissions
-      (wdired-preprocess-perms))
-  (if (fboundp 'make-symbolic-link)
-      (wdired-preprocess-symlinks))
-  (buffer-enable-undo) ; Performance hack. See above.
+  (add-function :override (local 'revert-buffer-function) #'wdired-revert)
   (set-buffer-modified-p nil)
   (setq buffer-undo-list nil)
   (run-mode-hooks 'wdired-mode-hook)
@@ -276,6 +258,63 @@ See `wdired-mode'."
                 "Press \\[wdired-finish-edit] when finished \
 or \\[wdired-abort-changes] to abort changes")))
 
+(defun wdired--set-permission-bounds ()
+  (save-excursion
+    (goto-char (point-min))
+    (if (not (re-search-forward dired-re-perms nil t 1))
+        (progn
+          (setq-local wdired--perm-beg nil)
+          (setq-local wdired--perm-end nil))
+      (goto-char (match-beginning 0))
+      ;; Add 1 since the first char matched by `dired-re-perms' is the
+      ;; one describing the nature of the entry (dir/symlink/...) rather
+      ;; than its permissions.
+      (setq-local wdired--perm-beg (1+ (wdired--current-column)))
+      (goto-char (match-end 0))
+      (setq-local wdired--perm-end (wdired--current-column)))))
+
+(defun wdired--current-column ()
+  (- (point) (line-beginning-position)))
+
+(defun wdired--point-at-perms-p ()
+  (and wdired--perm-beg
+       (<= wdired--perm-beg (wdired--current-column) wdired--perm-end)))
+
+(defun wdired--line-preprocessed-p ()
+  (get-text-property (line-beginning-position) 'front-sticky))
+
+(defun wdired--self-insert ()
+  (interactive)
+  (if (wdired--line-preprocessed-p)
+      (call-interactively 'self-insert-command)
+    (wdired--before-change-fn (point) (point))
+    (let* ((map (get-text-property (point) 'keymap)))
+      (call-interactively (or (if map (lookup-key map (this-command-keys)))
+                              #'self-insert-command)))))
+
+(defun wdired--before-change-fn (beg end)
+  (save-excursion
+    ;; Make sure to process entire lines.
+    (goto-char end)
+    (setq end (line-end-position))
+    (goto-char beg)
+    (forward-line 0)
+
+    (while (< (point) end)
+      (unless (wdired--line-preprocessed-p)
+        (with-silent-modifications
+          (put-text-property (point) (1+ (point)) 'front-sticky t)
+          (wdired--preprocess-files)
+          (when wdired-allow-to-change-permissions
+            (wdired--preprocess-perms))
+          (when (fboundp 'make-symbolic-link)
+            (wdired--preprocess-symlinks))))
+      (forward-line))
+    (when (eobp)
+      (with-silent-modifications
+        ;; Is this good enough? Assumes no extra white lines from dired.
+        (put-text-property (1- (point-max)) (point-max) 'read-only t)))))
+
 (defun wdired-isearch-filter-read-only (beg end)
   "Skip matches that have a read-only property."
   (not (text-property-not-all (min beg end) (max beg end)
@@ -283,35 +322,28 @@ or \\[wdired-abort-changes] to abort changes")))
 
 ;; Protect the buffer so only the filenames can be changed, and put
 ;; properties so filenames (old and new) can be easily found.
-(defun wdired-preprocess-files ()
-  (put-text-property (point-min) (1+ (point-min))'front-sticky t)
+(defun wdired--preprocess-files ()
   (save-excursion
-    (goto-char (point-min))
-    (let ((b-protection (point))
-          (used-F (dired-check-switches dired-actual-switches "F" "classify"))
-         filename)
-      (while (not (eobp))
-       (setq filename (dired-get-filename nil t))
-        (when (and filename
-                  (not (member (file-name-nondirectory filename) '("." ".."))))
-         (dired-move-to-filename)
-         ;; The rear-nonsticky property below shall ensure that text preceding
-         ;; the filename can't be modified.
-         (add-text-properties
-          (1- (point)) (point) `(old-name ,filename rear-nonsticky 
(read-only)))
-         (put-text-property b-protection (point) 'read-only t)
-          (dired-move-to-end-of-filename t)
-         (put-text-property (point) (1+ (point)) 'end-name t))
-          (when (and used-F (looking-at "[*/@|=>]$")) (forward-char))
-          (when (save-excursion
-                  (and (re-search-backward
-                        dired-permission-flags-regexp nil t)
-                       (looking-at "l")
-                       (search-forward " -> " (line-end-position) t)))
-            (goto-char (line-end-position)))
-         (setq b-protection (point))
-        (forward-line))
-      (put-text-property b-protection (point-max) 'read-only t))))
+    (let ((used-F (dired-check-switches dired-actual-switches "F" "classify"))
+         (beg (point))
+          (filename (dired-get-filename nil t)))
+      (when (and filename
+                (not (member (file-name-nondirectory filename) '("." ".."))))
+       (dired-move-to-filename)
+       ;; The rear-nonsticky property below shall ensure that text preceding
+       ;; the filename can't be modified.
+       (add-text-properties
+        (1- (point)) (point) `(old-name ,filename rear-nonsticky (read-only)))
+       (put-text-property beg (point) 'read-only t)
+        (dired-move-to-end-of-filename t)
+       (put-text-property (point) (1+ (point)) 'end-name t))
+      (when (and used-F (looking-at "[*/@|=>]$")) (forward-char))
+      (when (save-excursion
+              (and (re-search-backward
+                    dired-permission-flags-regexp nil t)
+                   (looking-at "l")
+                   (search-forward " -> " (line-end-position) t)))
+        (goto-char (line-end-position))))))
 
 ;; This code is a copy of some dired-get-filename lines.
 (defsubst wdired-normalize-filename (file unquotep)
@@ -338,6 +370,7 @@ non-nil means return old filename."
   ;; FIXME: Use dired-get-filename's new properties.
   (let ((used-F (dired-check-switches dired-actual-switches "F" "classify"))
         beg end file)
+    (wdired--before-change-fn (point) (point))
     (save-excursion
       (setq end (line-end-position))
       (beginning-of-line)
@@ -374,7 +407,6 @@ non-nil means return old filename."
        (and file (> (length file) 0)
              (concat (dired-current-directory) file))))))
 
-
 (defun wdired-change-to-dired-mode ()
   "Change the mode back to dired."
   (or (eq major-mode 'wdired-mode)
@@ -391,18 +423,19 @@ non-nil means return old filename."
   (setq major-mode 'dired-mode)
   (setq mode-name "Dired")
   (dired-advertise)
-  (remove-hook 'kill-buffer-hook 'wdired-check-kill-buffer t)
-  (remove-hook 'after-change-functions 'wdired--restore-properties t)
-  (setq-local revert-buffer-function 'dired-revert))
-
+  (remove-hook 'kill-buffer-hook #'wdired-check-kill-buffer t)
+  (remove-hook 'before-change-functions #'wdired--before-change-fn t)
+  (remove-hook 'after-change-functions #'wdired--restore-properties t)
+  (remove-function (local 'revert-buffer-function) #'wdired-revert))
 
 (defun wdired-abort-changes ()
   "Abort changes and return to dired mode."
   (interactive)
+  (remove-hook 'before-change-functions #'wdired--before-change-fn t)
   (let ((inhibit-read-only t))
     (erase-buffer)
-    (insert wdired-old-content)
-    (goto-char wdired-old-point))
+    (insert wdired--old-content)
+    (goto-char wdired--old-point))
   (wdired-change-to-dired-mode)
   (set-buffer-modified-p nil)
   (setq buffer-undo-list nil)
@@ -424,13 +457,14 @@ non-nil means return old filename."
        (setq errors (cdr tmp-value))
        (setq changes (car tmp-value)))
       (when (and wdired-allow-to-change-permissions
-                (boundp 'wdired-col-perm)) ; could have been changed
+                wdired--perm-beg) ; could have been changed
        (setq tmp-value (wdired-do-perm-changes))
        (setq errors (+ errors (cdr tmp-value)))
        (setq changes (or changes (car tmp-value))))
       (goto-char (point-max))
       (while (not (bobp))
-       (setq file-old (wdired-get-filename nil t))
+       (setq file-old (and (wdired--line-preprocessed-p)
+                           (wdired-get-filename nil t)))
        (when file-old
          (setq file-new (wdired-get-filename))
           (if (equal file-new file-old)
@@ -442,11 +476,11 @@ non-nil means return old filename."
                (let ((mark (cond ((integerp wdired-keep-marker-rename)
                                   wdired-keep-marker-rename)
                                  (wdired-keep-marker-rename
-                                  (cdr (assoc file-old wdired-old-marks)))
+                                  (cdr (assoc file-old wdired--old-marks)))
                                  (t nil))))
                  (when mark
                    (push (cons (substitute-in-file-name file-new) mark)
-                         wdired-old-marks))))
+                         wdired--old-marks))))
               (push (cons file-old (substitute-in-file-name file-new))
                     files-renamed))))
        (forward-line -1)))
@@ -471,7 +505,7 @@ non-nil means return old filename."
          ;; Re-sort the buffer.
          (revert-buffer)
          (let ((inhibit-read-only t))
-           (dired-mark-remembered wdired-old-marks)))
+           (dired-mark-remembered wdired--old-marks)))
       (let ((inhibit-read-only t))
        (remove-text-properties (point-min) (point-max)
                                '(old-name nil end-name nil old-link nil
@@ -542,7 +576,7 @@ non-nil means return old filename."
               ;; So we must ensure dired-aux is loaded.
               (require 'dired-aux)
               (condition-case err
-                  (let ((dired-backup-overwrite nil))
+                  (dlet ((dired-backup-overwrite nil))
                     (and wdired-create-parent-directories
                          (wdired-create-parentdirs file-new))
                     (dired-rename-file file-ori file-new
@@ -715,21 +749,17 @@ says how many lines to move; default is one line."
       (dired-move-to-filename)))
 
 ;; Put the needed properties to allow the user to change links' targets
-(defun wdired-preprocess-symlinks ()
-  (let ((inhibit-read-only t))
-    (save-excursion
-      (goto-char (point-min))
-      (while (not (eobp))
-        (when (looking-at dired-re-sym)
-          (re-search-forward " -> \\(.*\\)$")
-         (put-text-property (1- (match-beginning 1))
-                            (match-beginning 1) 'old-link
-                            (match-string-no-properties 1))
-          (put-text-property (match-end 1) (1+ (match-end 1)) 'end-link t)
-          (unless wdired-allow-to-redirect-links
-            (put-text-property (match-beginning 0)
-                              (match-end 1) 'read-only t)))
-        (forward-line)))))
+(defun wdired--preprocess-symlinks ()
+  (save-excursion
+    (when (looking-at dired-re-sym)
+      (re-search-forward " -> \\(.*\\)$")
+      (put-text-property (1- (match-beginning 1))
+                        (match-beginning 1) 'old-link
+                        (match-string-no-properties 1))
+      (put-text-property (match-end 1) (1+ (match-end 1)) 'end-link t)
+      (unless wdired-allow-to-redirect-links
+        (put-text-property (match-beginning 0)
+                          (match-end 1) 'read-only t)))))
 
 (defun wdired-get-previous-link (&optional old move)
   "Return the next symlink target.
@@ -813,56 +843,49 @@ Like original function but it skips read-only words."
   (interactive "p")
   (wdired-xcase-word 'capitalize-word arg))
 
-
 ;; The following code deals with changing the access bits (or
 ;; permissions) of the files.
 
 (defvar wdired-perm-mode-map
   (let ((map (make-sparse-keymap)))
-    (define-key map " " 'wdired-toggle-bit)
-    (define-key map "r" 'wdired-set-bit)
-    (define-key map "w" 'wdired-set-bit)
-    (define-key map "x" 'wdired-set-bit)
-    (define-key map "-" 'wdired-set-bit)
-    (define-key map "S" 'wdired-set-bit)
-    (define-key map "s" 'wdired-set-bit)
-    (define-key map "T" 'wdired-set-bit)
-    (define-key map "t" 'wdired-set-bit)
-    (define-key map "s" 'wdired-set-bit)
-    (define-key map "l" 'wdired-set-bit)
-    (define-key map [down-mouse-1] 'wdired-mouse-toggle-bit)
+    (define-key map " " #'wdired-toggle-bit)
+    (define-key map "r" #'wdired-set-bit)
+    (define-key map "w" #'wdired-set-bit)
+    (define-key map "x" #'wdired-set-bit)
+    (define-key map "-" #'wdired-set-bit)
+    (define-key map "S" #'wdired-set-bit)
+    (define-key map "s" #'wdired-set-bit)
+    (define-key map "T" #'wdired-set-bit)
+    (define-key map "t" #'wdired-set-bit)
+    (define-key map "s" #'wdired-set-bit)
+    (define-key map "l" #'wdired-set-bit)
+    (define-key map [mouse-1] #'wdired-mouse-toggle-bit)
     map))
 
 ;; Put a keymap property to the permission bits of the files, and store the
 ;; original name and permissions as a property
-(defun wdired-preprocess-perms ()
-  (let ((inhibit-read-only t))
-    (setq-local wdired-col-perm nil)
-    (save-excursion
-      (goto-char (point-min))
-      (while (not (eobp))
-       (when (and (not (looking-at dired-re-sym))
-                  (wdired-get-filename)
-                  (re-search-forward dired-re-perms (line-end-position) 'eol))
-         (let ((begin (match-beginning 0))
-               (end (match-end 0)))
-           (unless wdired-col-perm
-             (setq wdired-col-perm (- (current-column) 9)))
-           (if (eq wdired-allow-to-change-permissions 'advanced)
-               (progn
-                 (put-text-property begin end 'read-only nil)
-                 ;; make first permission bit writable
-                 (put-text-property
-                  (1- begin) begin 'rear-nonsticky '(read-only)))
-             ;; avoid that keymap applies to text following permissions
-             (add-text-properties
-              (1+ begin) end
-              `(keymap ,wdired-perm-mode-map rear-nonsticky (keymap))))
-           (put-text-property end (1+ end) 'end-perm t)
-           (put-text-property
-            begin (1+ begin) 'old-perm (match-string-no-properties 0))))
-        (forward-line)
-       (beginning-of-line)))))
+(defun wdired--preprocess-perms ()
+  (save-excursion
+    (when (and (not (looking-at dired-re-sym))
+              (wdired-get-filename)
+              (re-search-forward dired-re-perms
+                                  (line-end-position) 'eol))
+      (let ((begin (match-beginning 0))
+           (end (match-end 0)))
+       (if (eq wdired-allow-to-change-permissions 'advanced)
+           (progn
+             (put-text-property begin end 'read-only nil)
+             ;; make first permission bit writable
+             (put-text-property
+              (1- begin) begin 'rear-nonsticky '(read-only)))
+         ;; avoid that keymap applies to text following permissions
+         (add-text-properties
+          (1+ begin) end
+          `(keymap ,wdired-perm-mode-map rear-nonsticky (keymap))))
+       (put-text-property end (1+ end) 'end-perm t)
+       (put-text-property
+        begin (1+ begin)
+         'old-perm (match-string-no-properties 0))))))
 
 (defun wdired-perm-allowed-in-pos (char pos)
   (cond
@@ -874,39 +897,30 @@ Like original function but it skips read-only words."
    ((memq char '(?t ?T)) (= pos 8))
    ((= char ?l)          (= pos 5))))
 
-(defun wdired-set-bit ()
+(defun wdired-set-bit (&optional char)
   "Set a permission bit character."
-  (interactive)
-  (if (wdired-perm-allowed-in-pos last-command-event
-                                  (- (current-column) wdired-col-perm))
-      (let ((new-bit (char-to-string last-command-event))
+  (interactive (list last-command-event))
+  (unless char (setq char last-command-event))
+  (if (wdired-perm-allowed-in-pos char
+                                  (- (wdired--current-column) 
wdired--perm-beg))
+      (let ((new-bit (char-to-string char))
             (inhibit-read-only t)
-           (pos-prop (- (point) (- (current-column) wdired-col-perm))))
-        (put-text-property 0 1 'keymap wdired-perm-mode-map new-bit)
-        (put-text-property 0 1 'read-only t new-bit)
+           (pos-prop (+ (line-beginning-position) wdired--perm-beg)))
+        (set-text-properties 0 1 (text-properties-at (point)) new-bit)
         (insert new-bit)
         (delete-char 1)
-       (put-text-property (1- pos-prop) pos-prop 'perm-changed t)
-       (put-text-property (1- (point)) (point) 'rear-nonsticky '(keymap)))
+       (put-text-property (1- pos-prop) pos-prop 'perm-changed t))
     (forward-char 1)))
 
 (defun wdired-toggle-bit ()
   "Toggle the permission bit at point."
   (interactive)
-  (let ((inhibit-read-only t)
-       (new-bit "-")
-       (pos-prop (- (point) (- (current-column) wdired-col-perm))))
-    (if (eq (char-after (point)) ?-)
-       (setq new-bit
-             (if (= (% (- (current-column) wdired-col-perm) 3) 0) "r"
-               (if (= (% (- (current-column) wdired-col-perm) 3) 1) "w"
-                 "x"))))
-    (put-text-property 0 1 'keymap wdired-perm-mode-map new-bit)
-    (put-text-property 0 1 'read-only t new-bit)
-    (insert new-bit)
-    (delete-char 1)
-    (put-text-property (1- pos-prop) pos-prop 'perm-changed t)
-    (put-text-property (1- (point)) (point) 'rear-nonsticky '(keymap))))
+  (wdired-set-bit
+   (cond
+    ((not (eq (char-after (point)) ?-)) ?-)
+    ((= (% (- (wdired--current-column) wdired--perm-beg) 3) 0) ?r)
+    ((= (% (- (wdired--current-column) wdired--perm-beg) 3) 1) ?w)
+    (t ?x))))
 
 (defun wdired-mouse-toggle-bit (event)
   "Toggle the permission bit that was left clicked."
diff --git a/lisp/wid-browse.el b/lisp/wid-browse.el
index 0864e1b..54b71c9 100644
--- a/lisp/wid-browse.el
+++ b/lisp/wid-browse.el
@@ -1,7 +1,7 @@
-;;; wid-browse.el --- functions for browsing widgets
-;;
+;;; wid-browse.el --- functions for browsing widgets  -*- lexical-binding: t 
-*-
+
 ;; Copyright (C) 1997, 2001-2021 Free Software Foundation, Inc.
-;;
+
 ;; Author: Per Abrahamsen <abraham@dina.kvl.dk>
 ;; Keywords: extensions
 ;; Package: emacs
@@ -22,12 +22,11 @@
 ;; along with GNU Emacs.  If not, see <https://www.gnu.org/licenses/>.
 
 ;;; Commentary:
-;;
+
 ;; Widget browser.  See `widget.el'.
 
 ;;; Code:
 
-(require 'easymenu)
 (require 'wid-edit)
 
 (defgroup widget-browse nil
@@ -39,7 +38,7 @@
 (defvar widget-browse-mode-map
   (let ((map (make-sparse-keymap)))
     (set-keymap-parent map widget-keymap)
-    (define-key map "q" 'bury-buffer)
+    (define-key map "q" #'bury-buffer)
     map)
   "Keymap for `widget-browse-mode'.")
 
@@ -56,11 +55,10 @@
     ["Browse At" widget-browse-at t]))
 
 (defcustom widget-browse-mode-hook nil
-  "Hook called when entering widget-browse-mode."
-  :type 'hook
-  :group 'widget-browse)
+  "Hook run after entering `widget-browse-mode'."
+  :type 'hook)
 
-(defun widget-browse-mode ()
+(define-derived-mode widget-browse-mode special-mode "Widget Browse"
   "Major mode for widget browser buffers.
 
 The following commands are available:
@@ -68,15 +66,7 @@ The following commands are available:
 \\[widget-forward]             Move to next button or editable field.
 \\[widget-backward]            Move to previous button or editable field.
 \\[widget-button-click]                Activate button under the mouse pointer.
-\\[widget-button-press]                Activate button under point.
-
-Entry to this mode calls the value of `widget-browse-mode-hook'
-if that value is non-nil."
-  (kill-all-local-variables)
-  (setq major-mode 'widget-browse-mode
-       mode-name "Widget")
-  (use-local-map widget-browse-mode-map)
-  (run-mode-hooks 'widget-browse-mode-hook))
+\\[widget-button-press]                Activate button under point.")
 
 (put 'widget-browse-mode 'mode-class 'special)
 
@@ -190,11 +180,11 @@ The :value of the widget should be the widget to be 
browsed."
   :action 'widget-browse-action)
 
 (defun widget-browse-action (widget &optional _event)
-  ;; Create widget browser for WIDGET's :value.
+  "Create widget browser for :value of WIDGET."
   (widget-browse (widget-get widget :value)))
 
 (defun widget-browse-value-create (widget)
-  ;; Insert type name.
+  "Insert type name for WIDGET."
   (let ((value (widget-get widget :value)))
     (cond ((symbolp value)
           (insert (symbol-name value)))
@@ -273,8 +263,6 @@ VALUE is assumed to be a list of widgets."
   "Minor mode for traversing widgets."
   :lighter " Widget")
 
-;;; The End:
-
 (provide 'wid-browse)
 
 ;;; wid-browse.el ends here
diff --git a/lisp/wid-edit.el b/lisp/wid-edit.el
index de2b5d4..e71290c 100644
--- a/lisp/wid-edit.el
+++ b/lisp/wid-edit.el
@@ -131,16 +131,21 @@ This exists as a variable so it can be set locally in 
certain buffers.")
                        (((class grayscale color)
                          (background light))
                         :background "gray85"
+                         ;; We use negative thickness of the horizontal box 
border line to
+                         ;; avoid making lines taller when fields become 
visible.
+                         :box (:line-width (1 . -1) :color "gray80")
                         :extend t)
                        (((class grayscale color)
                          (background dark))
                         :background "dim gray"
+                         :box (:line-width (1 . -1) :color "gray46")
                         :extend t)
                        (t
                         :slant italic
                         :extend t))
   "Face used for editable fields."
-  :group 'widget-faces)
+  :group 'widget-faces
+  :version "28.1")
 
 (defface widget-single-line-field '((((type tty))
                                     :background "green3"
@@ -4029,7 +4034,7 @@ is inline."
                    (mapcar #'length (defined-colors))))
   :tag "Color"
   :value "black"
-  :completions (or facemenu-color-alist (defined-colors))
+  :completions (defined-colors)
   :sample-face-get 'widget-color-sample-face-get
   :notify 'widget-color-notify
   :match #'widget-color-match
@@ -4044,7 +4049,10 @@ is inline."
    :tag " Choose " :action 'widget-color--choose-action)
   (widget-insert " "))
 
+(declare-function list-colors-display "facemenu")
+
 (defun widget-color--choose-action (widget &optional _event)
+  (require 'facemenu)
   (list-colors-display
    nil nil
    (let ((cbuf (current-buffer))
@@ -4067,8 +4075,11 @@ is inline."
        (list (cons 'foreground-color value))
       'default)))
 
+(declare-function facemenu-read-color "facemenu")
+
 (defun widget-color-action (widget &optional event)
   "Prompt for a color."
+  (require 'facemenu)
   (let* ((tag (widget-apply widget :menu-tag-get))
         (prompt (concat tag ": "))
         (answer (facemenu-read-color prompt)))
diff --git a/lisp/window.el b/lisp/window.el
index 2d0a73b..f27631b 100644
--- a/lisp/window.el
+++ b/lisp/window.el
@@ -4158,7 +4158,7 @@ returned by `window-start' and `window-point' 
respectively.
 
 This function is called only if `switch-to-buffer-preserve-window-point'
 evaluates non-nil."
-  (dolist (win (window-list))
+  (dolist (win (window-list nil 'no-minibuf))
     (let* ((buf   (window-buffer (or window win)))
            (start (window-start win))
            (pos   (window-point win))
@@ -4416,7 +4416,8 @@ WINDOW must be a live window and defaults to the selected 
one."
        window (assq-delete-all buffer (window-prev-buffers window))))
 
     ;; Don't record insignificant buffers.
-    (unless (eq (aref (buffer-name buffer) 0) ?\s)
+    (when (or (not (eq (aref (buffer-name buffer) 0) ?\s))
+              (minibufferp buffer))
       ;; Add an entry for buffer to WINDOW's previous buffers.
       (with-current-buffer buffer
        (let ((start (window-start window))
@@ -10252,6 +10253,28 @@ displaying that processes's buffer."
 (define-key ctl-x-4-map "1" 'same-window-prefix)
 (define-key ctl-x-4-map "4" 'other-window-prefix)
 
+(defvar other-window-repeat-map
+  (let ((map (make-sparse-keymap)))
+    (define-key map "o" 'other-window)
+    map)
+  "Keymap to repeat other-window key sequences.  Used in `repeat-mode'.")
+(put 'other-window 'repeat-map 'other-window-repeat-map)
+
+(defvar resize-window-repeat-map
+  (let ((map (make-sparse-keymap)))
+    ;; Standard keys:
+    (define-key map "^" 'enlarge-window)
+    (define-key map "}" 'enlarge-window-horizontally)
+    (define-key map "{" 'shrink-window-horizontally)
+    ;; Additional keys:
+    (define-key map "v" 'shrink-window)
+    map)
+  "Keymap to repeat window resizing commands.  Used in `repeat-mode'.")
+(put 'enlarge-window 'repeat-map 'resize-window-repeat-map)
+(put 'enlarge-window-horizontally 'repeat-map 'resize-window-repeat-map)
+(put 'shrink-window-horizontally 'repeat-map 'resize-window-repeat-map)
+(put 'shrink-window 'repeat-map 'resize-window-repeat-map)
+
 (provide 'window)
 
 ;;; window.el ends here
diff --git a/lisp/woman.el b/lisp/woman.el
index 9a03d30..505fdb4 100644
--- a/lisp/woman.el
+++ b/lisp/woman.el
@@ -1,4 +1,4 @@
-;;; woman.el --- browse UN*X manual pages `wo (without) man'
+;;; woman.el --- browse UN*X manual pages `wo (without) man'  -*- 
lexical-binding: t; -*-
 
 ;; Copyright (C) 2000-2021 Free Software Foundation, Inc.
 
@@ -69,13 +69,7 @@
 ;; Recommended use
 ;; ===============
 
-;; Put this in your .emacs:
-;;   (autoload 'woman "woman"
-;;             "Decode and browse a UN*X man page." t)
-;;   (autoload 'woman-find-file "woman"
-;;             "Find, decode and browse a specific UN*X man-page file." t)
-
-;; Then either (1 -- *RECOMMENDED*): If the `MANPATH' environment
+;; Either (1 -- *RECOMMENDED*): If the `MANPATH' environment
 ;; variable is set then WoMan will use it; otherwise you may need to
 ;; reset the Lisp variable `woman-manpath', and you may also want to
 ;; set the Lisp variable `woman-path'.  Please see the online
@@ -139,14 +133,8 @@
 ;; ==============================
 
 ;; WoMan supports the GNU Emacs customization facility, and puts
-;; a customization group called `WoMan' in the `Help' group under the
-;; top-level `Emacs' group.  In order to be able to customize WoMan
-;; without first loading it, add the following sexp to your .emacs:
-
-;;  (defgroup woman nil
-;;     "Browse UNIX manual pages `wo (without) man'."
-;;     :tag "WoMan" :group 'help :load "woman")
-
+;; a customization group called `woman' in the `help' group under the
+;; top-level `emacs' group.
 
 ;; WoMan currently runs two hooks: `woman-pre-format-hook' immediately
 ;; before formatting a buffer and `woman-post-format-hook' immediately
@@ -400,6 +388,8 @@
 
 ;;; Code:
 
+(eval-when-compile (require 'cl-lib))
+
 (defvar woman-version "0.551 (beta)" "WoMan version information.")
 (make-obsolete-variable 'woman-version nil "28.1")
 
@@ -430,14 +420,14 @@ As a special case, if PATHS is nil then replace it by 
calling
   ;; an empty substring of MANPATH denotes the default list.
   (if (memq system-type '(windows-nt ms-dos))
       (cond ((null paths)
-            (mapcar 'woman-Cyg-to-Win (woman-parse-man.conf)))
+            (mapcar #'woman-Cyg-to-Win (woman-parse-man.conf)))
            ((string-match-p ";" paths)
             ;; Assume DOS-style path-list...
             (mapcan                    ; splice list into list
              (lambda (x)
                (if x
                    (list x)
-                 (mapcar 'woman-Cyg-to-Win (woman-parse-man.conf))))
+                 (mapcar #'woman-Cyg-to-Win (woman-parse-man.conf))))
              (parse-colon-path paths)))
            ((string-match-p "\\`[a-zA-Z]:" paths)
             ;; Assume single DOS-style path...
@@ -446,7 +436,7 @@ As a special case, if PATHS is nil then replace it by 
calling
             ;; Assume UNIX/Cygwin-style path-list...
             (mapcan                    ; splice list into list
              (lambda (x)
-               (mapcar 'woman-Cyg-to-Win
+               (mapcar #'woman-Cyg-to-Win
                        (if x (list x) (woman-parse-man.conf))))
              (let ((path-separator ":"))
                (parse-colon-path paths)))))
@@ -521,7 +511,7 @@ Change only via `Customization' or the function `add-hook'."
 (defcustom woman-man.conf-path
   (let ((path '("/usr/lib" "/etc")))
     (cond ((eq system-type 'windows-nt)
-          (mapcar 'woman-Cyg-to-Win path))
+          (mapcar #'woman-Cyg-to-Win path))
          ((eq system-type 'darwin)
           (cons "/usr/share/misc" path))
          (t path)))
@@ -821,7 +811,7 @@ in the ncurses package include `toe.1m', `form.3x', etc.
 Note: an optional compression regexp will be appended, so this regexp
 MUST NOT end with any kind of string terminator such as $ or \\\\='."
   :type 'regexp
-  :set 'set-woman-file-regexp
+  :set #'set-woman-file-regexp
   :group 'woman-interface)
 
 (defcustom woman-file-compression-regexp
@@ -837,7 +827,7 @@ Should begin with \\. and end with \\\\=' and MUST NOT be 
optional."
   ;; not loaded by default!
   :version "24.1"                       ; added xz
   :type 'regexp
-  :set 'set-woman-file-regexp
+  :set #'set-woman-file-regexp
   :group 'woman-interface)
 
 (defcustom woman-use-own-frame nil
@@ -1198,7 +1188,7 @@ Called both to generate and to check the cache!"
              (setq dir (and (member (car dir) path) (cdr dir))))
            (when dir
               (cl-pushnew (substitute-in-file-name dir) lst :test #'equal))))
-       (mapcar 'substitute-in-file-name woman-path)))
+       (mapcar #'substitute-in-file-name woman-path)))
 
 (defun woman-read-directory-cache ()
   "Load the directory and topic cache.
@@ -1513,14 +1503,14 @@ Also make each path-info component into a list.
        (if (woman-not-member dir path) ; use each directory only once!
            (setq files (nconc files
                               (directory-files dir t topic-regexp))))))
-    (mapcar 'list files)))
+    (mapcar #'list files)))
 
 
 ;;; dired support
 
 (defun woman-dired-define-key (key)
   "Bind the argument KEY to the command `woman-dired-find-file'."
-  (define-key dired-mode-map key 'woman-dired-find-file))
+  (define-key dired-mode-map key #'woman-dired-find-file))
 
 (defsubst woman-dired-define-key-maybe (key)
   "If KEY is undefined in Dired, bind it to command `woman-dired-find-file'."
@@ -1532,7 +1522,7 @@ Also make each path-info component into a list.
   "Define dired keys to run WoMan according to `woman-dired-keys'."
   (if woman-dired-keys
       (if (listp woman-dired-keys)
-         (mapc 'woman-dired-define-key woman-dired-keys)
+         (mapc #'woman-dired-define-key woman-dired-keys)
        (woman-dired-define-key-maybe "w")
        (woman-dired-define-key-maybe "W")))
   (define-key-after (lookup-key dired-mode-map [menu-bar immediate])
@@ -1540,7 +1530,7 @@ Also make each path-info component into a list.
 
 (if (featurep 'dired)
     (woman-dired-define-keys)
-  (add-hook 'dired-mode-hook 'woman-dired-define-keys))
+  (add-hook 'dired-mode-hook #'woman-dired-define-keys))
 
 (declare-function dired-get-filename "dired"
                   (&optional localp no-error-if-not-filep))
@@ -1766,15 +1756,15 @@ Leave point at end of new text.  Return length of 
inserted text."
   (let ((map (make-sparse-keymap)))
     (set-keymap-parent map Man-mode-map)
 
-    (define-key map "R" 'woman-reformat-last-file)
-    (define-key map "w" 'woman)
-    (define-key map "\en" 'WoMan-next-manpage)
-    (define-key map "\ep" 'WoMan-previous-manpage)
-    (define-key map [M-mouse-2] 'woman-follow-word)
+    (define-key map "R" #'woman-reformat-last-file)
+    (define-key map "w" #'woman)
+    (define-key map "\en" #'WoMan-next-manpage)
+    (define-key map "\ep" #'WoMan-previous-manpage)
+    (define-key map [M-mouse-2] #'woman-follow-word)
 
     ;; We don't need to call `man' when we are in `woman-mode'.
-    (define-key map [remap man] 'woman)
-    (define-key map [remap man-follow] 'woman-follow)
+    (define-key map [remap man] #'woman)
+    (define-key map [remap man-follow] #'woman-follow)
     map)
   "Keymap for `woman-mode'.")
 
@@ -1868,30 +1858,22 @@ Argument EVENT is the invoking mouse event."
 
 (defvar bookmark-make-record-function)
 
-(define-derived-mode woman-mode special-mode "WoMan"
+(define-derived-mode woman-mode man-common "WoMan"
   "Turn on (most of) Man mode to browse a buffer formatted by WoMan.
 WoMan is an ELisp emulation of much of the functionality of the Emacs
 `man' command running the standard UN*X man and ?roff programs.
 WoMan author: F.J.Wright@Maths.QMW.ac.uk
 See `Man-mode' for additional details.
 \\{woman-mode-map}"
-  (let ((Man-build-page-list (symbol-function 'Man-build-page-list))
-       (Man-strip-page-headers (symbol-function 'Man-strip-page-headers))
-       (Man-unindent (symbol-function 'Man-unindent))
-       (Man-goto-page (symbol-function 'Man-goto-page)))
+  ;; FIXME: Should all this just be re-arranged so that this can just
+  ;; inherit `man-common' and be done with it?
+  (cl-letf (((symbol-function 'Man-build-page-list) #'ignore)
+           ((symbol-function 'Man-strip-page-headers) #'ignore)
+           ((symbol-function 'Man-unindent) #'ignore)
+           ((symbol-function 'Man-goto-page) #'ignore))
     ;; Prevent inappropriate operations:
-    (fset 'Man-build-page-list 'ignore)
-    (fset 'Man-strip-page-headers 'ignore)
-    (fset 'Man-unindent 'ignore)
-    (fset 'Man-goto-page 'ignore)
-    (unwind-protect
-       (delay-mode-hooks (Man-mode))
-      ;; Restore the status quo:
-      (fset 'Man-build-page-list Man-build-page-list)
-      (fset 'Man-strip-page-headers Man-strip-page-headers)
-      (fset 'Man-unindent Man-unindent)
-      (fset 'Man-goto-page Man-goto-page)
-      (setq tab-width woman-tab-width)))
+    (delay-mode-hooks (Man-mode)))
+  (setq tab-width woman-tab-width)
   (setq major-mode 'woman-mode
        mode-name "WoMan")
   ;; Don't show page numbers like Man-mode does.  (Online documents do
@@ -1902,7 +1884,7 @@ See `Man-mode' for additional details.
   (setq imenu-generic-expression woman-imenu-generic-expression)
   (setq-local imenu-space-replacement " ")
   ;; Bookmark support.
-  (setq-local bookmark-make-record-function 'woman-bookmark-make-record)
+  (setq-local bookmark-make-record-function #'woman-bookmark-make-record)
   ;; For reformat ...
   ;; necessary when reformatting a file in its old buffer:
   (setq imenu--last-menubar-index-alist nil)
@@ -2441,6 +2423,10 @@ Preserves location of `point'."
 
 (defvar woman0-rename-alist)           ; bound in woman0-roff-buffer
 
+;; Bound locally by woman[012]-roff-buffer, and woman0-macro.
+;; Use dynamically in woman-unquote and woman-forward-arg.
+(defvar woman-request)
+
 (defun woman0-roff-buffer (from)
   "Process conditional-type requests and user-defined macros.
 Start at FROM and re-scan new text as appropriate."
@@ -2760,15 +2746,16 @@ Optional argument APPEND, if non-nil, means append 
macro."
 
 ;; request may be used dynamically (woman-interpolate-macro calls
 ;; woman-forward-arg).
-(defun woman0-macro (woman-request)
-  "Process the macro call named WOMAN-REQUEST."
+(defun woman0-macro (request)
+  "Process the macro call named REQUEST."
   ;; Leaves point at start of new text.
-  (let ((macro (assoc woman-request woman0-macro-alist)))
+  (let ((woman-request request)
+        (macro (assoc request woman0-macro-alist)))
     (if macro
        (woman-interpolate-macro (cdr macro))
       ;; SHOULD DELETE THE UNINTERPRETED REQUEST!!!!!
       ;; Output this message once only per call (cf. strings)?
-      (WoMan-warn "Undefined macro %s not interpolated!" woman-request))))
+      (WoMan-warn "Undefined macro %s not interpolated!" request))))
 
 (defun woman-interpolate-macro (macro)
   "Interpolate (.de) or append (.am) expansion of MACRO into the buffer."
@@ -2992,11 +2979,6 @@ Useful for constructing the alist variable 
`woman-special-characters'."
 
 ;;; Formatting macros that do not cause a break:
 
-;; Bound locally by woman[012]-roff-buffer, and also, annoyingly and
-;; confusingly, as a function argument.  Use dynamically in
-;; woman-unquote and woman-forward-arg.
-(defvar woman-request)
-
 (defun woman-unquote (to)
   "Delete any double-quote characters between point and TO.
 Leave point at TO (which should be a marker)."
@@ -3077,7 +3059,7 @@ B-OR-I is the appropriate complete control line."
   ".SM -- Set the current line in small font, i.e. IGNORE!"
   nil)
 
-(defalias 'woman1-SB 'woman1-B)
+(defalias 'woman1-SB #'woman1-B)
 ;; .SB -- Set the current line in small bold font, i.e. just embolden!
 ;; (This is what /usr/local/share/groff/tmac/tmac.an does.  The
 ;; Linux man.7 is wrong about this!)
@@ -3207,27 +3189,27 @@ If optional arg CONCAT is non-nil then join arguments."
 ;;; Other non-breaking requests correctly ignored by nroff:
 
 (put 'woman1-ps 'notfont t)
-(defalias 'woman1-ps 'woman-delete-whole-line)
+(defalias 'woman1-ps #'woman-delete-whole-line)
   ;; .ps -- Point size -- IGNORE!
 
 (put 'woman1-ss 'notfont t)
-(defalias 'woman1-ss 'woman-delete-whole-line)
+(defalias 'woman1-ss #'woman-delete-whole-line)
   ;; .ss -- Space-character size -- IGNORE!
 
 (put 'woman1-cs 'notfont t)
-(defalias 'woman1-cs 'woman-delete-whole-line)
+(defalias 'woman1-cs #'woman-delete-whole-line)
   ;; .cs -- Constant character space (width) mode -- IGNORE!
 
 (put 'woman1-ne 'notfont t)
-(defalias 'woman1-ne 'woman-delete-whole-line)
+(defalias 'woman1-ne #'woman-delete-whole-line)
   ;; .ne -- Need vertical space -- IGNORE!
 
 (put 'woman1-vs 'notfont t)
-(defalias 'woman1-vs 'woman-delete-whole-line)
+(defalias 'woman1-vs #'woman-delete-whole-line)
   ;; .vs -- Vertical base line spacing -- IGNORE!
 
 (put 'woman1-bd 'notfont t)
-(defalias 'woman1-bd 'woman-delete-whole-line)
+(defalias 'woman1-bd #'woman-delete-whole-line)
   ;; .bd -- Embolden font -- IGNORE!
 
 ;;; Non-breaking SunOS-specific macros:
@@ -3238,7 +3220,7 @@ If optional arg CONCAT is non-nil then join arguments."
   (woman-forward-arg 'unquote 'concat))
 
 (put 'woman1-IX 'notfont t)
-(defalias 'woman1-IX 'woman-delete-whole-line)
+(defalias 'woman1-IX #'woman-delete-whole-line)
   ;; .IX -- Index macro, for Sun internal use -- IGNORE!
 
 
@@ -3587,7 +3569,7 @@ expression in parentheses.  Leaves point after the value."
                                  inc (cdr value)
                                  ;; eval internal (.X) registers
                                  ;; stored as lisp variable names:
-                                 value (eval (car value)))
+                                 value (eval (car value) t))
                            (if (and pm inc) ; auto-increment
                                (setq value
                                      (funcall (intern-soft pm) value inc)
@@ -3647,64 +3629,55 @@ expression in parentheses.  Leaves point after the 
value."
   "Process breaks.  Format paragraphs and headings."
   (let ((case-fold-search t)
        (to (make-marker))
-       (canonically-space-region
-        (symbol-function 'canonically-space-region))
-       (insert-and-inherit (symbol-function 'insert-and-inherit))
-       (set-text-properties (symbol-function 'set-text-properties))
        (woman-registers woman-registers)
        fn woman-request woman-translations
        tab-stop-list)
     (set-marker-insertion-type to t)
     ;; ?roff does not squeeze multiple spaces, but does fill, so...
-    (fset 'canonically-space-region 'ignore)
-    ;; Try to avoid spaces inheriting underlines from preceding text!
-    (fset 'insert-and-inherit (symbol-function 'insert))
-    (fset 'set-text-properties 'ignore)
-    (unwind-protect
-        (progn
-          (while
-              ;; Find next control line:
-              (re-search-forward woman-request-regexp nil t)
-            (cond
-             ;; Construct woman function to call:
-             ((setq fn (intern-soft
-                        (concat "woman2-"
-                                (setq woman-request (match-string 1)))))
-              ;; Delete request or macro name:
-              (woman-delete-match 0))
-             ;; Unrecognized request:
-             ((prog1 nil
-                ;; (WoMan-warn ".%s request ignored!" woman-request)
-                (WoMan-warn-ignored woman-request "ignored!")
-                ;; (setq fn 'woman2-LP)
-                ;; AVOID LEAVING A BLANK LINE!
-                ;; (setq fn 'woman2-format-paragraphs)
-                ))
-             ;; .LP assumes it is at eol and leaves a (blank) line,
-             ;; so leave point at end of line before paragraph:
-             ((or (looking-at "[ \t]*$") ; no argument
-                  woman-ignore)          ; ignore all
-              ;; (beginning-of-line) (kill-line)
-              ;; AVOID LEAVING A BLANK LINE!
-              (beginning-of-line) (woman-delete-line 1))
-             (t (end-of-line) (insert ?\n)))
-            (if (not (or fn
-                         (and (not (memq (following-char) '(?. ?')))
-                              (setq fn 'woman2-format-paragraphs))))
-                ()
-              ;; Find next control line:
-              (if (equal woman-request "TS")
-                  (set-marker to (woman-find-next-control-line "TE"))
-                (set-marker to (woman-find-next-control-line)))
-              ;; Call the appropriate function:
-              (funcall fn to)))
-          (if (not (eobp))             ; This should not happen, but ...
-              (woman2-format-paragraphs (copy-marker (point-max) t)
-                                        woman-left-margin)))
-      (fset 'canonically-space-region canonically-space-region)
-      (fset 'set-text-properties set-text-properties)
-      (fset 'insert-and-inherit insert-and-inherit)
-      (set-marker to nil))))
+    (cl-letf (((symbol-function 'canonically-space-region) #'ignore)
+              ;; Try to avoid spaces inheriting underlines from preceding text!
+              ((symbol-function 'insert-and-inherit) #'insert)
+              ((symbol-function 'set-text-properties) #'ignore))
+      (while
+          ;; Find next control line:
+          (re-search-forward woman-request-regexp nil t)
+        (cond
+         ;; Construct woman function to call:
+         ((setq fn (intern-soft
+                    (concat "woman2-"
+                            (setq woman-request (match-string 1)))))
+          ;; Delete request or macro name:
+          (woman-delete-match 0))
+         ;; Unrecognized request:
+         ((prog1 nil
+            ;; (WoMan-warn ".%s request ignored!" woman-request)
+            (WoMan-warn-ignored woman-request "ignored!")
+            ;; (setq fn 'woman2-LP)
+            ;; AVOID LEAVING A BLANK LINE!
+            ;; (setq fn 'woman2-format-paragraphs)
+            ))
+         ;; .LP assumes it is at eol and leaves a (blank) line,
+         ;; so leave point at end of line before paragraph:
+         ((or (looking-at "[ \t]*$")    ; no argument
+              woman-ignore)             ; ignore all
+          ;; (beginning-of-line) (kill-line)
+          ;; AVOID LEAVING A BLANK LINE!
+          (beginning-of-line) (woman-delete-line 1))
+         (t (end-of-line) (insert ?\n)))
+        (if (not (or fn
+                     (and (not (memq (following-char) '(?. ?')))
+                          (setq fn 'woman2-format-paragraphs))))
+            ()
+          ;; Find next control line:
+          (if (equal woman-request "TS")
+              (set-marker to (woman-find-next-control-line "TE"))
+            (set-marker to (woman-find-next-control-line)))
+          ;; Call the appropriate function:
+          (funcall fn to)))
+      (if (not (eobp))             ; This should not happen, but ...
+          (woman2-format-paragraphs (copy-marker (point-max) t)
+                                    woman-left-margin)))
+    (set-marker to nil)))
 
 (defun woman-find-next-control-line (&optional pat)
   "Find and return start of next control line.
@@ -3815,8 +3788,8 @@ Leave 1 blank line.  Format paragraphs upto TO."
   (setq woman-prevailing-indent woman-default-indent)
   (woman2-format-paragraphs to woman-left-margin))
 
-(defalias 'woman2-PP 'woman2-LP)
-(defalias 'woman2-P 'woman2-LP)
+(defalias 'woman2-PP #'woman2-LP)
+(defalias 'woman2-P #'woman2-LP)
 
 (defun woman2-ns (to)
   ".ns -- Turn on no-space mode.  Format paragraphs upto TO."
@@ -4287,16 +4260,16 @@ Set prevailing indent to amount of starting .RS."
 If no argument then use value of optional arg PREVIOUS if non-nil,
 otherwise set PREVIOUS.  Delete the whole remaining control line."
   (if (eolp)                           ; space already skipped
-      (set arg (if previous (eval previous) 0))
-    (if previous (set previous (eval arg)))
+      (set arg (if previous (symbol-value previous) 0))
+    (if previous (set previous (symbol-value arg)))
     (woman2-process-escapes-to-eol 'numeric)
     (let ((pm (if (looking-at "[+-]")
                (prog1 (following-char)
                  (forward-char 1))))
        (i (woman-parse-numeric-arg)))
     (cond ((null pm) (set arg i))
-         ((= pm ?+) (set arg (+ (eval arg) i)))
-         ((= pm ?-) (set arg (- (eval arg) i)))
+         ((= pm ?+) (set arg (+ (symbol-value arg) i)))
+         ((= pm ?-) (set arg (- (symbol-value arg) i)))
          ))
     (beginning-of-line))
   (woman-delete-line 1))               ; ignore any remaining arguments
@@ -4493,7 +4466,7 @@ Format paragraphs upto TO."
   (setq woman-nofill t)
   (woman2-format-paragraphs to))
 
-(defalias 'woman2-TE 'woman2-fi)
+(defalias 'woman2-TE #'woman2-fi)
   ;; ".TE -- End of table code for the tbl processor."
   ;; Turn filling and adjusting back on.
 
diff --git a/lisp/xdg.el b/lisp/xdg.el
index 0f0df53..1103949 100644
--- a/lisp/xdg.el
+++ b/lisp/xdg.el
@@ -256,8 +256,8 @@ which is expected to be ordered by priority as in
         (when (file-readable-p f)
           (insert-file-contents-literally f nil nil nil t)
           (goto-char (point-min))
-          (let (end)
-            (while (not (or (eobp) end))
+          (let () ;; end
+            (while (not (or (eobp))) ;; end
               (if (= (following-char) ?\[)
                   (progn (setq sec (char-after (1+ (point))))
                          (forward-line))
diff --git a/lwlib/Makefile.in b/lwlib/Makefile.in
index 28c16ac..fb0ae0e 100644
--- a/lwlib/Makefile.in
+++ b/lwlib/Makefile.in
@@ -26,6 +26,7 @@ all: liblw.a
 .PHONY: all
 
 srcdir=@srcdir@
+top_builddir=@top_builddir@
 # MinGW CPPFLAGS may use this.
 abs_top_srcdir=@abs_top_srcdir@
 VPATH=@srcdir@
@@ -56,23 +57,7 @@ TOOLKIT_OBJS = $(@X_TOOLKIT_TYPE@_OBJS)
 
 OBJS = lwlib.o $(TOOLKIT_OBJS) lwlib-utils.o
 
-# 'make' verbosity.
-AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
-
-AM_V_CC = $(am__v_CC_@AM_V@)
-am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@)
-am__v_CC_0 = @echo "  CC      " $@;
-am__v_CC_1 =
-
-AM_V_GEN = $(am__v_GEN_@AM_V@)
-am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
-am__v_GEN_0 = @echo "  GEN     " $@;
-am__v_GEN_1 =
-
-AM_V_at = $(am__v_at_@AM_V@)
-am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
-am__v_at_0 = @
-am__v_at_1 =
+-include ${top_builddir}/src/verbose.mk
 
 AUTO_DEPEND = @AUTO_DEPEND@
 DEPDIR = deps
diff --git a/nt/Makefile.in b/nt/Makefile.in
index aa3a762..0d44890 100644
--- a/nt/Makefile.in
+++ b/nt/Makefile.in
@@ -41,23 +41,8 @@ WERROR_CFLAGS = @WERROR_CFLAGS@
 # Program name transformation.
 TRANSFORM = @program_transform_name@
 
-# 'make' verbosity.
-AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
-
-AM_V_CC = $(am__v_CC_@AM_V@)
-am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@)
-am__v_CC_0 = @echo "  CC      " $@;
-am__v_CC_1 =
-
-AM_V_CCLD = $(am__v_CCLD_@AM_V@)
-am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@)
-am__v_CCLD_0 = @echo "  CCLD    " $@;
-am__v_CCLD_1 =
-
-AM_V_RC = $(am__v_RC_@AM_V@)
-am__v_RC_ = $(am__v_RC_@AM_DEFAULT_V@)
-am__v_RC_0 = @echo "  RC      " $@;
-am__v_RC_1 =
+top_builddir = @top_builddir@
+-include ${top_builddir}/src/verbose.mk
 
 # ==================== Where To Install Things ====================
 
diff --git a/oldXMenu/Makefile.in b/oldXMenu/Makefile.in
index 7ae355b..39fd155 100644
--- a/oldXMenu/Makefile.in
+++ b/oldXMenu/Makefile.in
@@ -43,6 +43,7 @@
 ### Code:
 
 srcdir=@srcdir@
+top_builddir = @top_builddir@
 # MinGW CPPFLAGS may use this.
 abs_top_srcdir=@abs_top_srcdir@
 VPATH=@srcdir@
@@ -93,23 +94,7 @@ OBJS =  Activate.o \
 all: libXMenu11.a
 .PHONY: all
 
-# 'make' verbosity.
-AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
-
-AM_V_CC = $(am__v_CC_@AM_V@)
-am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@)
-am__v_CC_0 = @echo "  CC      " $@;
-am__v_CC_1 =
-
-AM_V_GEN = $(am__v_GEN_@AM_V@)
-am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
-am__v_GEN_0 = @echo "  GEN     " $@;
-am__v_GEN_1 =
-
-AM_V_at = $(am__v_at_@AM_V@)
-am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
-am__v_at_0 = @
-am__v_at_1 =
+-include ${top_builddir}/src/verbose.mk
 
 AUTO_DEPEND = @AUTO_DEPEND@
 DEPDIR = deps
diff --git a/src/Makefile.in b/src/Makefile.in
index 4100edf..f3c545d 100644
--- a/src/Makefile.in
+++ b/src/Makefile.in
@@ -29,6 +29,7 @@ SHELL = @SHELL@
 # We use $(srcdir) explicitly in dependencies so as not to depend on VPATH.
 srcdir = @srcdir@
 top_srcdir = @top_srcdir@
+top_builddir = @top_builddir@
 # MinGW CPPFLAGS may use this.
 abs_top_srcdir=@abs_top_srcdir@
 VPATH = $(srcdir)
@@ -340,33 +341,7 @@ HAVE_PDUMPER = @HAVE_PDUMPER@
 ## invalidates the signature, we must re-sign to fix it.
 DO_CODESIGN=$(patsubst aarch64-apple-darwin%,yes,@configuration@)
 
-# 'make' verbosity.
-AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
-
-AM_V_CC = $(am__v_CC_@AM_V@)
-am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@)
-am__v_CC_0 = @echo "  CC      " $@;
-am__v_CC_1 =
-
-AM_V_CCLD = $(am__v_CCLD_@AM_V@)
-am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@)
-am__v_CCLD_0 = @echo "  CCLD    " $@;
-am__v_CCLD_1 =
-
-AM_V_GEN = $(am__v_GEN_@AM_V@)
-am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
-am__v_GEN_0 = @echo "  GEN     " $@;
-am__v_GEN_1 =
-
-AM_V_at = $(am__v_at_@AM_V@)
-am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
-am__v_at_0 = @
-am__v_at_1 =
-
-AM_V_NO_PD = $(am__v_NO_PD_@AM_V@)
-am__v_NO_PD_ = $(am__v_NO_PD_@AM_DEFAULT_V@)
-am__v_NO_PD_0 = --no-print-directory
-am__v_NO_PD_1 =
+-include ${top_builddir}/src/verbose.mk
 
 bootstrap_exe = ../src/bootstrap-emacs$(EXEEXT)
 ifeq ($(DUMPING),pdumper)
@@ -426,7 +401,7 @@ base_obj = dispnew.o frame.o scroll.o xdisp.o menu.o 
$(XMENU_OBJ) window.o \
        thread.o systhread.o \
        $(if $(HYBRID_MALLOC),sheap.o) \
        $(MSDOS_OBJ) $(MSDOS_X_OBJ) $(NS_OBJ) $(CYGWIN_OBJ) $(FONT_OBJ) \
-       $(W32_OBJ) $(WINDOW_SYSTEM_OBJ) $(XGSELOBJ) $(JSON_OBJ) $(GMP_OBJ)
+       $(W32_OBJ) $(WINDOW_SYSTEM_OBJ) $(XGSELOBJ) $(JSON_OBJ)
 obj = $(base_obj) $(NS_OBJC_OBJ)
 
 ## Object files used on some machine or other.
@@ -621,11 +596,6 @@ buildobj.h: Makefile
 
 GLOBAL_SOURCES = $(base_obj:.o=.c) $(NS_OBJC_OBJ:.o=.m)
 
-AM_V_GLOBALS = $(am__v_GLOBALS_@AM_V@)
-am__v_GLOBALS_ = $(am__v_GLOBALS_@AM_DEFAULT_V@)
-am__v_GLOBALS_0 = @echo "  GEN     " globals.h;
-am__v_GLOBALS_1 =
-
 gl-stamp: $(libsrc)/make-docfile$(EXEEXT) $(GLOBAL_SOURCES)
        $(AM_V_GLOBALS)$(libsrc)/make-docfile -d $(srcdir) -g $(obj) > 
globals.tmp
        $(AM_V_at)$(top_srcdir)/build-aux/move-if-change globals.tmp globals.h
@@ -724,7 +694,7 @@ bootstrap-clean: clean
        fi
 
 distclean: bootstrap-clean
-       rm -f Makefile lisp.mk
+       rm -f Makefile lisp.mk verbose.mk
        rm -fr $(DEPDIR)
 
 maintainer-clean: distclean
diff --git a/src/alloc.c b/src/alloc.c
index b86ed4e..e72fc4c 100644
--- a/src/alloc.c
+++ b/src/alloc.c
@@ -3498,6 +3498,38 @@ usage: (make-byte-code ARGLIST BYTE-CODE CONSTANTS DEPTH 
&optional DOCSTRING INT
   return val;
 }
 
+DEFUN ("make-closure", Fmake_closure, Smake_closure, 1, MANY, 0,
+       doc: /* Create a byte-code closure from PROTOTYPE and CLOSURE-VARS.
+Return a copy of PROTOTYPE, a byte-code object, with CLOSURE-VARS
+replacing the elements in the beginning of the constant-vector.
+usage: (make-closure PROTOTYPE &rest CLOSURE-VARS) */)
+  (ptrdiff_t nargs, Lisp_Object *args)
+{
+  Lisp_Object protofun = args[0];
+  CHECK_TYPE (COMPILEDP (protofun), Qbyte_code_function_p, protofun);
+
+  /* Create a copy of the constant vector, filling it with the closure
+     variables in the beginning.  (The overwritten part should just
+     contain placeholder values.) */
+  Lisp_Object proto_constvec = AREF (protofun, COMPILED_CONSTANTS);
+  ptrdiff_t constsize = ASIZE (proto_constvec);
+  ptrdiff_t nvars = nargs - 1;
+  if (nvars > constsize)
+    error ("Closure vars do not fit in constvec");
+  Lisp_Object constvec = make_uninit_vector (constsize);
+  memcpy (XVECTOR (constvec)->contents, args + 1, nvars * word_size);
+  memcpy (XVECTOR (constvec)->contents + nvars,
+         XVECTOR (proto_constvec)->contents + nvars,
+         (constsize - nvars) * word_size);
+
+  /* Return a copy of the prototype function with the new constant vector. */
+  ptrdiff_t protosize = PVSIZE (protofun);
+  struct Lisp_Vector *v = allocate_vectorlike (protosize, false);
+  v->header = XVECTOR (protofun)->header;
+  memcpy (v->contents, XVECTOR (protofun)->contents, protosize * word_size);
+  v->contents[COMPILED_CONSTANTS] = constvec;
+  return make_lisp_ptr (v, Lisp_Vectorlike);
+}
 
 
 /***********************************************************************
@@ -7573,6 +7605,7 @@ N should be nonnegative.  */);
   defsubr (&Srecord);
   defsubr (&Sbool_vector);
   defsubr (&Smake_byte_code);
+  defsubr (&Smake_closure);
   defsubr (&Smake_list);
   defsubr (&Smake_vector);
   defsubr (&Smake_record);
diff --git a/src/buffer.c b/src/buffer.c
index 80c799e..8e33162 100644
--- a/src/buffer.c
+++ b/src/buffer.c
@@ -292,6 +292,11 @@ bset_major_mode (struct buffer *b, Lisp_Object val)
   b->major_mode_ = val;
 }
 static void
+bset_local_minor_modes (struct buffer *b, Lisp_Object val)
+{
+  b->local_minor_modes_ = val;
+}
+static void
 bset_mark (struct buffer *b, Lisp_Object val)
 {
   b->mark_ = val;
@@ -893,6 +898,7 @@ CLONE nil means the indirect buffer's state is reset to 
default values.  */)
       bset_file_truename (b, Qnil);
       bset_display_count (b, make_fixnum (0));
       bset_backed_up (b, Qnil);
+      bset_local_minor_modes (b, Qnil);
       bset_auto_save_file_name (b, Qnil);
       set_buffer_internal_1 (b);
       Fset (intern ("buffer-save-without-query"), Qnil);
@@ -967,6 +973,7 @@ reset_buffer (register struct buffer *b)
   b->clip_changed = 0;
   b->prevent_redisplay_optimizations_p = 1;
   bset_backed_up (b, Qnil);
+  bset_local_minor_modes (b, Qnil);
   BUF_AUTOSAVE_MODIFF (b) = 0;
   b->auto_save_failure_time = 0;
   bset_auto_save_file_name (b, Qnil);
@@ -1935,8 +1942,8 @@ cleaning up all windows currently displaying the buffer 
to be killed. */)
     }
   /* Since we've unlinked the markers, the overlays can't be here any more
      either.  */
-  b->overlays_before = NULL;
-  b->overlays_after = NULL;
+  set_buffer_overlays_before (b, NULL);
+  set_buffer_overlays_after (b, NULL);
 
   /* Reset the local variables, so that this buffer's local values
      won't be protected from GC.  They would be protected
@@ -2412,6 +2419,7 @@ results, see Info node `(elisp)Swapping Text'.  */)
   swapfield (overlay_center, ptrdiff_t);
   swapfield_ (undo_list, Lisp_Object);
   swapfield_ (mark, Lisp_Object);
+  swapfield_ (mark_active, Lisp_Object); /* Belongs with the `mark'.  */
   swapfield_ (enable_multibyte_characters, Lisp_Object);
   swapfield_ (bidi_display_reordering, Lisp_Object);
   swapfield_ (bidi_paragraph_direction, Lisp_Object);
@@ -5151,6 +5159,7 @@ init_buffer_once (void)
   bset_auto_save_file_name (&buffer_local_flags, make_fixnum (-1));
   bset_read_only (&buffer_local_flags, make_fixnum (-1));
   bset_major_mode (&buffer_local_flags, make_fixnum (-1));
+  bset_local_minor_modes (&buffer_local_flags, make_fixnum (-1));
   bset_mode_name (&buffer_local_flags, make_fixnum (-1));
   bset_undo_list (&buffer_local_flags, make_fixnum (-1));
   bset_mark_active (&buffer_local_flags, make_fixnum (-1));
@@ -5617,6 +5626,12 @@ The default value (normally `fundamental-mode') affects 
new buffers.
 A value of nil means to use the current buffer's major mode, provided
 it is not marked as "special".  */);
 
+  DEFVAR_PER_BUFFER ("local-minor-modes",
+                    &BVAR (current_buffer, local_minor_modes),
+                    Qnil,
+                    doc: /* Minor modes currently active in the current buffer.
+This is a list of symbols, or nil if there are no minor modes active.  */);
+
   DEFVAR_PER_BUFFER ("mode-name", &BVAR (current_buffer, mode_name),
                      Qnil,
                     doc: /* Pretty name of current buffer's major mode.
diff --git a/src/buffer.h b/src/buffer.h
index 790291f..24e9c3f 100644
--- a/src/buffer.h
+++ b/src/buffer.h
@@ -338,6 +338,9 @@ struct buffer
   /* Symbol naming major mode (e.g., lisp-mode).  */
   Lisp_Object major_mode_;
 
+  /* Symbol listing all currently enabled minor modes.  */
+  Lisp_Object local_minor_modes_;
+
   /* Pretty name of major mode (e.g., "Lisp"). */
   Lisp_Object mode_name_;
 
diff --git a/src/callint.c b/src/callint.c
index d3f49bc..1862463 100644
--- a/src/callint.c
+++ b/src/callint.c
@@ -104,7 +104,14 @@ If the string begins with `^' and `shift-select-mode' is 
non-nil,
  Emacs first calls the function `handle-shift-selection'.
 You may use `@', `*', and `^' together.  They are processed in the
  order that they appear, before reading any arguments.
-usage: (interactive &optional ARG-DESCRIPTOR)  */
+
+If MODES is present, it should be a list of mode names (symbols) that
+this command is applicable for.  The main effect of this is that
+`M-x TAB' (by default) won't list this command if the current buffer's
+mode doesn't match the list.  That is, if either the major mode isn't
+derived from them, or (when it's a minor mode) the mode isn't in effect.
+
+usage: (interactive &optional ARG-DESCRIPTOR &rest MODES)  */
        attributes: const)
   (Lisp_Object args)
 {
diff --git a/src/callproc.c b/src/callproc.c
index cb72b07..cd0f67f 100644
--- a/src/callproc.c
+++ b/src/callproc.c
@@ -411,7 +411,11 @@ call_process (ptrdiff_t nargs, Lisp_Object *args, int 
filefd,
       /* If the buffer is (still) a list, it might be a (:file "file") spec. */
       if (CONSP (buffer) && EQ (XCAR (buffer), QCfile))
        {
-         output_file = Fexpand_file_name (XCAR (XCDR (buffer)),
+         Lisp_Object ofile = XCDR (buffer);
+         if (CONSP (ofile))
+           ofile = XCAR (ofile);
+         CHECK_STRING (ofile);
+         output_file = Fexpand_file_name (ofile,
                                           BVAR (current_buffer, directory));
          CHECK_STRING (output_file);
          buffer = Qnil;
diff --git a/src/coding.c b/src/coding.c
index 739dd6a..46e7fca 100644
--- a/src/coding.c
+++ b/src/coding.c
@@ -7799,7 +7799,13 @@ encode_coding (struct coding_system *coding)
     coding_set_source (coding);
     consume_chars (coding, translation_table, max_lookup);
     coding_set_destination (coding);
+    /* The CODING_MODE_LAST_BLOCK flag should be set only for the last
+       iteration of the encoding.  */
+    unsigned saved_mode = coding->mode;
+    if (coding->consumed_char < coding->src_chars)
+      coding->mode &= ~CODING_MODE_LAST_BLOCK;
     (*(coding->encoder)) (coding);
+    coding->mode = saved_mode;
   } while (coding->consumed_char < coding->src_chars);
 
   if (BUFFERP (coding->dst_object) && coding->produced_char > 0)
diff --git a/src/data.c b/src/data.c
index 38cde0f..3667b03 100644
--- a/src/data.c
+++ b/src/data.c
@@ -904,7 +904,17 @@ Value, if non-nil, is a list (interactive SPEC).  */)
   else if (COMPILEDP (fun))
     {
       if (PVSIZE (fun) > COMPILED_INTERACTIVE)
-       return list2 (Qinteractive, AREF (fun, COMPILED_INTERACTIVE));
+       {
+         Lisp_Object form = AREF (fun, COMPILED_INTERACTIVE);
+         if (VECTORP (form))
+           /* The vector form is the new form, where the first
+              element is the interactive spec, and the second is the
+              command modes. */
+           return list2 (Qinteractive, AREF (form, 0));
+         else
+           /* Old form -- just the interactive spec. */
+           return list2 (Qinteractive, form);
+       }
     }
 #ifdef HAVE_MODULES
   else if (MODULE_FUNCTIONP (fun))
@@ -920,10 +930,83 @@ Value, if non-nil, is a list (interactive SPEC).  */)
   else if (CONSP (fun))
     {
       Lisp_Object funcar = XCAR (fun);
-      if (EQ (funcar, Qclosure))
-       return Fassq (Qinteractive, Fcdr (Fcdr (XCDR (fun))));
-      else if (EQ (funcar, Qlambda))
-       return Fassq (Qinteractive, Fcdr (XCDR (fun)));
+      if (EQ (funcar, Qclosure)
+         || EQ (funcar, Qlambda))
+       {
+         Lisp_Object form = Fcdr (XCDR (fun));
+         if (EQ (funcar, Qclosure))
+           form = Fcdr (form);
+         Lisp_Object spec = Fassq (Qinteractive, form);
+         if (NILP (Fcdr (Fcdr (spec))))
+           return spec;
+         else
+           return list2 (Qinteractive, Fcar (Fcdr (spec)));
+       }
+    }
+  return Qnil;
+}
+
+DEFUN ("command-modes", Fcommand_modes, Scommand_modes, 1, 1, 0,
+       doc: /* Return the modes COMMAND is defined for.
+If COMMAND is not a command, the return value is nil.
+The value, if non-nil, is a list of mode name symbols.  */)
+  (Lisp_Object command)
+{
+  Lisp_Object fun = indirect_function (command); /* Check cycles.  */
+
+  if (NILP (fun))
+    return Qnil;
+
+  /* Use a `command-modes' property if present, analogous to the
+     function-documentation property.  */
+  fun = command;
+  while (SYMBOLP (fun))
+    {
+      Lisp_Object modes = Fget (fun, Qcommand_modes);
+      if (!NILP (modes))
+       return modes;
+      else
+       fun = Fsymbol_function (fun);
+    }
+
+  if (COMPILEDP (fun))
+    {
+      Lisp_Object form = AREF (fun, COMPILED_INTERACTIVE);
+      if (VECTORP (form))
+       /* New form -- the second element is the command modes. */
+       return AREF (form, 1);
+      else
+       /* Old .elc file -- no command modes. */
+       return Qnil;
+    }
+#ifdef HAVE_MODULES
+  else if (MODULE_FUNCTIONP (fun))
+    {
+      Lisp_Object form
+        = module_function_command_modes (XMODULE_FUNCTION (fun));
+      if (! NILP (form))
+        return form;
+    }
+#endif
+  else if (AUTOLOADP (fun))
+    {
+      Lisp_Object modes = Fnth (make_int (3), fun);
+      if (CONSP (modes))
+       return modes;
+      else
+       return Qnil;
+    }
+  else if (CONSP (fun))
+    {
+      Lisp_Object funcar = XCAR (fun);
+      if (EQ (funcar, Qclosure)
+         || EQ (funcar, Qlambda))
+       {
+         Lisp_Object form = Fcdr (XCDR (fun));
+         if (EQ (funcar, Qclosure))
+           form = Fcdr (form);
+         return Fcdr (Fcdr (Fassq (Qinteractive, form)));
+       }
     }
   return Qnil;
 }
@@ -1506,6 +1589,7 @@ All writes to aliases of SYMBOL will call WATCH-FUNCTION 
too.  */)
   (Lisp_Object symbol, Lisp_Object watch_function)
 {
   symbol = Findirect_variable (symbol);
+  CHECK_SYMBOL (symbol);
   set_symbol_trapped_write (symbol, SYMBOL_TRAPPED_WRITE);
   map_obarray (Vobarray, harmonize_variable_watchers, symbol);
 
@@ -3906,8 +3990,11 @@ syms_of_data (void)
   DEFSYM (Qinteractive_form, "interactive-form");
   DEFSYM (Qdefalias_fset_function, "defalias-fset-function");
 
+  DEFSYM (Qbyte_code_function_p, "byte-code-function-p");
+
   defsubr (&Sindirect_variable);
   defsubr (&Sinteractive_form);
+  defsubr (&Scommand_modes);
   defsubr (&Seq);
   defsubr (&Snull);
   defsubr (&Stype_of);
@@ -4030,6 +4117,7 @@ This variable cannot be set; trying to do so will signal 
an error.  */);
   DEFSYM (Qunlet, "unlet");
   DEFSYM (Qset, "set");
   DEFSYM (Qset_default, "set-default");
+  DEFSYM (Qcommand_modes, "command-modes");
   defsubr (&Sadd_variable_watcher);
   defsubr (&Sremove_variable_watcher);
   defsubr (&Sget_variable_watchers);
diff --git a/src/dispnew.c b/src/dispnew.c
index e603c67..f613f7b 100644
--- a/src/dispnew.c
+++ b/src/dispnew.c
@@ -3328,7 +3328,7 @@ update_frame_with_menu (struct frame *f, int row, int col)
 }
 
 /* Update the mouse position for a frame F.  This handles both
-   updating the display for mouse-face propreties and updating the
+   updating the display for mouse-face properties and updating the
    help echo text.
 
    Returns the number of events generated.  */
@@ -3588,6 +3588,7 @@ update_window (struct window *w, bool force_p)
       int yb;
       bool changed_p = 0, mouse_face_overwritten_p = 0;
       int n_updated = 0;
+      bool invisible_rows_marked = false;
 
 #ifdef HAVE_WINDOW_SYSTEM
       gui_update_window_begin (w);
@@ -3679,13 +3680,36 @@ update_window (struct window *w, bool force_p)
               tempted to optimize redisplay based on lines displayed
               in the first redisplay.  */
            if (MATRIX_ROW_BOTTOM_Y (row) >= yb)
-             for (i = vpos + 1; i < w->current_matrix->nrows - 1; ++i)
-               SET_MATRIX_ROW_ENABLED_P (w->current_matrix, i, false);
+             {
+               for (i = vpos + 1; i < w->current_matrix->nrows - 1; ++i)
+                 SET_MATRIX_ROW_ENABLED_P (w->current_matrix, i, false);
+               invisible_rows_marked = true;
+             }
          }
 
       /* Was display preempted?  */
       paused_p = row < end;
 
+      if (!paused_p && !invisible_rows_marked)
+       {
+         /* If we didn't mark the invisible rows in the current
+            matrix as invalid above, do that now.  This can happen if
+            scrolling_window updates the last visible rows of the
+            current matrix, in which case the above loop doesn't get
+            to examine the last visible row.  */
+         int i;
+         for (i = 0; i < w->current_matrix->nrows - 1; ++i)
+           {
+             struct glyph_row *current_row = MATRIX_ROW (w->current_matrix, i);
+             if (current_row->enabled_p
+                 && MATRIX_ROW_BOTTOM_Y (current_row) >= yb)
+               {
+                 for (++i ; i < w->current_matrix->nrows - 1; ++i)
+                   SET_MATRIX_ROW_ENABLED_P (w->current_matrix, i, false);
+               }
+           }
+       }
+
     set_cursor:
 
       /* Update the tab line after scrolling because a new tab
diff --git a/src/editfns.c b/src/editfns.c
index 991f79a..87e743a 100644
--- a/src/editfns.c
+++ b/src/editfns.c
@@ -1697,7 +1697,11 @@ they can be in either order.  */)
 DEFUN ("buffer-string", Fbuffer_string, Sbuffer_string, 0, 0, 0,
        doc: /* Return the contents of the current buffer as a string.
 If narrowing is in effect, this function returns only the visible part
-of the buffer.  */)
+of the buffer.
+
+This function copies the text properties of that part of the buffer
+into the result string; if you don’t want the text properties,
+use `buffer-substring-no-properties' instead.  */)
   (void)
 {
   return make_buffer_string_both (BEGV, BEGV_BYTE, ZV, ZV_BYTE, 1);
@@ -2945,7 +2949,7 @@ usage: (propertize STRING &rest PROPERTIES)  */)
 
   /* Number of args must be odd.  */
   if ((nargs & 1) == 0)
-    error ("Wrong number of arguments");
+    xsignal2 (Qwrong_number_of_arguments, Qpropertize, make_fixnum (nargs));
 
   properties = string = Qnil;
 
@@ -3134,7 +3138,7 @@ styled_format (ptrdiff_t nargs, Lisp_Object *args, bool 
message)
   char *format_start = SSDATA (args[0]);
   bool multibyte_format = STRING_MULTIBYTE (args[0]);
   ptrdiff_t formatlen = SBYTES (args[0]);
-  bool fmt_props = string_intervals (args[0]);
+  bool fmt_props = !!string_intervals (args[0]);
 
   /* Upper bound on number of format specs.  Each uses at least 2 chars.  */
   ptrdiff_t nspec_bound = SCHARS (args[0]) >> 1;
@@ -4448,6 +4452,7 @@ syms_of_editfns (void)
 {
   DEFSYM (Qbuffer_access_fontify_functions, "buffer-access-fontify-functions");
   DEFSYM (Qwall, "wall");
+  DEFSYM (Qpropertize, "propertize");
 
   DEFVAR_LISP ("inhibit-field-text-motion", Vinhibit_field_text_motion,
               doc: /* Non-nil means text motion commands don't notice fields.  
*/);
diff --git a/src/emacs-module.c b/src/emacs-module.c
index 894dffc..f8fb54c 100644
--- a/src/emacs-module.c
+++ b/src/emacs-module.c
@@ -549,7 +549,7 @@ struct Lisp_Module_Function
   union vectorlike_header header;
 
   /* Fields traced by GC; these must come first.  */
-  Lisp_Object documentation, interactive_form;
+  Lisp_Object documentation, interactive_form, command_modes;
 
   /* Fields ignored by GC.  */
   ptrdiff_t min_arity, max_arity;
@@ -646,6 +646,12 @@ module_function_interactive_form (const struct 
Lisp_Module_Function *fun)
   return fun->interactive_form;
 }
 
+Lisp_Object
+module_function_command_modes (const struct Lisp_Module_Function *fun)
+{
+  return fun->command_modes;
+}
+
 static emacs_value
 module_funcall (emacs_env *env, emacs_value func, ptrdiff_t nargs,
                emacs_value *args)
diff --git a/src/eval.c b/src/eval.c
index 3aff3b5..ddaa8ed 100644
--- a/src/eval.c
+++ b/src/eval.c
@@ -219,7 +219,7 @@ void
 init_eval_once (void)
 {
   /* Don't forget to update docs (lispref node "Local Variables").  */
-  max_specpdl_size = 1600; /* 1500 is not enough for cl-generic.el.  */
+  max_specpdl_size = 1800; /* See bug#46818.  */
   max_lisp_eval_depth = 800;
   Vrun_hooks = Qnil;
   pdumper_do_now_and_after_load (init_eval_once_for_pdumper);
@@ -1165,21 +1165,23 @@ usage: (catch TAG BODY...)  */)
    FUNC should return a Lisp_Object.
    This is how catches are done from within C code.  */
 
+/* MINIBUFFER_QUIT_LEVEL is to handle quitting from nested minibuffers by
+   throwing t to tag `exit'.
+   0 means there is no (throw 'exit t) in progress, or it wasn't from
+     a minibuffer which isn't the most nested;
+   N > 0 means the `throw' was done from the minibuffer at level N which
+     wasn't the most nested.  */
+EMACS_INT minibuffer_quit_level = 0;
+
 Lisp_Object
 internal_catch (Lisp_Object tag,
                Lisp_Object (*func) (Lisp_Object), Lisp_Object arg)
 {
-  /* MINIBUFFER_QUIT_LEVEL is to handle quitting from nested minibuffers by
-     throwing t to tag `exit'.
-     Value -1 means there is no (throw 'exit t) in progress;
-     0 means the `throw' wasn't done from an active minibuffer;
-     N > 0 means the `throw' was done from the minibuffer at level N.  */
-  static EMACS_INT minibuffer_quit_level = -1;
   /* This structure is made part of the chain `catchlist'.  */
   struct handler *c = push_handler (tag, CATCHER);
 
   if (EQ (tag, Qexit))
-    minibuffer_quit_level = -1;
+    minibuffer_quit_level = 0;
 
   /* Call FUNC.  */
   if (! sys_setjmp (c->jmp))
@@ -1194,22 +1196,16 @@ internal_catch (Lisp_Object tag,
       Lisp_Object val = handlerlist->val;
       clobbered_eassert (handlerlist == c);
       handlerlist = handlerlist->next;
-      if (EQ (tag, Qexit) && EQ (val, Qt))
+      if (EQ (tag, Qexit) && EQ (val, Qt) && minibuffer_quit_level > 0)
        /* If we've thrown t to tag `exit' from within a minibuffer, we
           exit all minibuffers more deeply nested than the current
           one.  */
        {
-         EMACS_INT mini_depth = this_minibuffer_depth (Qnil);
-         if (mini_depth && mini_depth != minibuffer_quit_level)
-           {
-             if (minibuffer_quit_level == -1)
-               minibuffer_quit_level = mini_depth;
-             if (minibuffer_quit_level
-                 && (minibuf_level > minibuffer_quit_level))
-               Fthrow (Qexit, Qt);
-           }
+         if (minibuf_level > minibuffer_quit_level
+             && !NILP (Fminibuffer_innermost_command_loop_p (Qnil)))
+            Fthrow (Qexit, Qt);
          else
-           minibuffer_quit_level = -1;
+           minibuffer_quit_level = 0;
        }
       return val;
     }
@@ -2084,14 +2080,21 @@ then strings and vectors are not accepted.  */)
 DEFUN ("autoload", Fautoload, Sautoload, 2, 5, 0,
        doc: /* Define FUNCTION to autoload from FILE.
 FUNCTION is a symbol; FILE is a file name string to pass to `load'.
+
 Third arg DOCSTRING is documentation for the function.
-Fourth arg INTERACTIVE if non-nil says function can be called interactively.
+
+Fourth arg INTERACTIVE if non-nil says function can be called
+interactively.  If INTERACTIVE is a list, it is interpreted as a list
+of modes the function is applicable for.
+
 Fifth arg TYPE indicates the type of the object:
    nil or omitted says FUNCTION is a function,
    `keymap' says FUNCTION is really a keymap, and
    `macro' or t says FUNCTION is really a macro.
+
 Third through fifth args give info about the real definition.
 They default to nil.
+
 If FUNCTION is already defined other than as an autoload,
 this does nothing and returns nil.  */)
   (Lisp_Object function, Lisp_Object file, Lisp_Object docstring, Lisp_Object 
interactive, Lisp_Object type)
diff --git a/src/filelock.c b/src/filelock.c
index 35baa0c..446a262 100644
--- a/src/filelock.c
+++ b/src/filelock.c
@@ -532,7 +532,7 @@ current_lock_owner (lock_info_type *owner, char *lfname)
   /* If nonexistent lock file, all is well; otherwise, got strange error. */
   lfinfolen = read_lock_data (lfname, owner->user);
   if (lfinfolen < 0)
-    return errno == ENOENT ? 0 : errno;
+    return errno == ENOENT || errno == ENOTDIR ? 0 : errno;
   if (MAX_LFINFO < lfinfolen)
     return ENAMETOOLONG;
   owner->user[lfinfolen] = 0;
@@ -719,8 +719,8 @@ lock_file (Lisp_Object fn)
     }
 }
 
-void
-unlock_file (Lisp_Object fn)
+static Lisp_Object
+unlock_file_body (Lisp_Object fn)
 {
   char *lfname;
   USE_SAFE_ALLOCA;
@@ -737,6 +737,23 @@ unlock_file (Lisp_Object fn)
     report_file_errno ("Unlocking file", filename, err);
 
   SAFE_FREE ();
+  return Qnil;
+}
+
+static Lisp_Object
+unlock_file_handle_error (Lisp_Object err)
+{
+  call1 (intern ("userlock--handle-unlock-error"), err);
+  return Qnil;
+}
+
+void
+unlock_file (Lisp_Object fn)
+{
+  internal_condition_case_1 (unlock_file_body,
+                            fn,
+                            list1(Qfile_error),
+                            unlock_file_handle_error);
 }
 
 #else  /* MSDOS */
@@ -790,7 +807,10 @@ DEFUN ("unlock-buffer", Funlock_buffer, Sunlock_buffer,
        0, 0, 0,
        doc: /* Unlock the file visited in the current buffer.
 If the buffer is not modified, this does nothing because the file
-should not be locked in that case.  */)
+should not be locked in that case.  It also does nothing if the
+current buffer is not visiting a file, or is not locked.  Handles file
+system errors by calling `display-warning' and continuing as if the
+error did not occur.  */)
   (void)
 {
   if (SAVE_MODIFF < MODIFF
diff --git a/src/fns.c b/src/fns.c
index c16f9c6..1758148 100644
--- a/src/fns.c
+++ b/src/fns.c
@@ -54,10 +54,55 @@ DEFUN ("identity", Fidentity, Sidentity, 1, 1, 0,
   return argument;
 }
 
+static Lisp_Object
+ccall2 (Lisp_Object (f) (ptrdiff_t nargs, Lisp_Object *args),
+        Lisp_Object arg1, Lisp_Object arg2)
+{
+  Lisp_Object args[2] = {arg1, arg2};
+  return f (2, args);
+}
+
+static Lisp_Object
+get_random_bignum (Lisp_Object limit)
+{
+  /* This is a naive transcription into bignums of the fixnum algorithm.
+     I'd be quite surprised if that's anywhere near the best algorithm
+     for it.  */
+  while (true)
+    {
+      Lisp_Object val = make_fixnum (0);
+      Lisp_Object lim = limit;
+      int bits = 0;
+      int bitsperiteration = FIXNUM_BITS - 1;
+      do
+        {
+          /* Shift by one so it is a valid positive fixnum.  */
+          EMACS_INT rand = get_random () >> 1;
+          Lisp_Object lrand = make_fixnum (rand);
+          bits += bitsperiteration;
+          val = ccall2 (Flogior,
+                        Fash (val, make_fixnum (bitsperiteration)),
+                        lrand);
+          lim = Fash (lim, make_fixnum (- bitsperiteration));
+        }
+      while (!EQ (lim, make_fixnum (0)));
+      /* Return the remainder, except reject the rare case where
+        get_random returns a number so close to INTMASK that the
+        remainder isn't random.  */
+      Lisp_Object remainder = Frem (val, limit);
+      if (!NILP (ccall2 (Fleq,
+                        ccall2 (Fminus, val, remainder),
+                        ccall2 (Fminus,
+                                Fash (make_fixnum (1), make_fixnum (bits)),
+                                limit))))
+       return remainder;
+    }
+}
+
 DEFUN ("random", Frandom, Srandom, 0, 1, 0,
        doc: /* Return a pseudo-random integer.
 By default, return a fixnum; all fixnums are equally likely.
-With positive fixnum LIMIT, return random integer in interval [0,LIMIT).
+With positive integer LIMIT, return random integer in interval [0,LIMIT).
 With argument t, set the random number seed from the system's entropy
 pool if available, otherwise from less-random volatile data such as the time.
 With a string argument, set the seed based on the string's contents.
@@ -71,6 +116,12 @@ See Info node `(elisp)Random Numbers' for more details.  */)
     init_random ();
   else if (STRINGP (limit))
     seed_random (SSDATA (limit), SBYTES (limit));
+  if (BIGNUMP (limit))
+    {
+      if (0 > mpz_sgn (*xbignum_val (limit)))
+        xsignal2 (Qwrong_type_argument, Qnatnump, limit);
+      return get_random_bignum (limit);
+    }
 
   val = get_random ();
   if (FIXNUMP (limit) && 0 < XFIXNUM (limit))
@@ -1816,7 +1867,8 @@ If SEQ is not a list, deletion is never performed 
destructively;
 instead this function creates and returns a new vector or string.
 
 Write `(setq foo (delete element foo))' to be sure of correctly
-changing the value of a sequence `foo'.  */)
+changing the value of a sequence `foo'.  See also `remove', which
+does not modify the argument.  */)
   (Lisp_Object elt, Lisp_Object seq)
 {
   if (VECTORP (seq))
@@ -2227,6 +2279,52 @@ merge (Lisp_Object org_l1, Lisp_Object org_l2, 
Lisp_Object pred)
     }
 }
 
+Lisp_Object
+merge_c (Lisp_Object org_l1, Lisp_Object org_l2, bool (*less) (Lisp_Object, 
Lisp_Object))
+{
+  Lisp_Object l1 = org_l1;
+  Lisp_Object l2 = org_l2;
+  Lisp_Object tail = Qnil;
+  Lisp_Object value = Qnil;
+
+  while (1)
+    {
+      if (NILP (l1))
+       {
+         if (NILP (tail))
+           return l2;
+         Fsetcdr (tail, l2);
+         return value;
+       }
+      if (NILP (l2))
+       {
+         if (NILP (tail))
+           return l1;
+         Fsetcdr (tail, l1);
+         return value;
+       }
+
+      Lisp_Object tem;
+      if (less (Fcar (l1), Fcar (l2)))
+       {
+         tem = l1;
+         l1 = Fcdr (l1);
+         org_l1 = l1;
+       }
+      else
+       {
+         tem = l2;
+         l2 = Fcdr (l2);
+         org_l2 = l2;
+       }
+      if (NILP (tail))
+       value = tem;
+      else
+       Fsetcdr (tail, tem);
+      tail = tem;
+    }
+}
+
 
 /* This does not check for quits.  That is safe since it must terminate.  */
 
@@ -2271,7 +2369,10 @@ This is the last value stored with `(put SYMBOL PROPNAME 
VALUE)'.  */)
 DEFUN ("plist-put", Fplist_put, Splist_put, 3, 3, 0,
        doc: /* Change value in PLIST of PROP to VAL.
 PLIST is a property list, which is a list of the form
-\(PROP1 VALUE1 PROP2 VALUE2 ...).  PROP is a symbol and VAL is any object.
+\(PROP1 VALUE1 PROP2 VALUE2 ...).
+
+The comparison with PROP is done using `eq'.
+
 If PROP is already a property on the list, its value is set to VAL,
 otherwise the new PROP VAL pair is added.  The new plist is returned;
 use `(setq x (plist-put x prop val))' to be sure to use the new value.
@@ -2873,6 +2974,9 @@ if `last-nonmenu-event' is nil, and `use-dialog-box' is 
non-nil.  */)
       return obj;
     }
 
+  if (use_short_answers)
+    return call1 (intern ("y-or-n-p"), prompt);
+
   AUTO_STRING (yes_or_no, "(yes or no) ");
   prompt = CALLN (Fconcat, prompt, yes_or_no);
 
@@ -3110,7 +3214,10 @@ suppressed.  */)
 DEFUN ("plist-member", Fplist_member, Splist_member, 2, 2, 0,
        doc: /* Return non-nil if PLIST has the property PROP.
 PLIST is a property list, which is a list of the form
-\(PROP1 VALUE1 PROP2 VALUE2 ...).  PROP is a symbol.
+\(PROP1 VALUE1 PROP2 VALUE2 ...).
+
+The comparison with PROP is done using `eq'.
+
 Unlike `plist-get', this allows you to distinguish between a missing
 property and a property with the value nil.
 The value is actually the tail of PLIST whose car is PROP.  */)
@@ -5904,6 +6011,15 @@ that disables the use of a file dialog, regardless of 
the value of
 this variable.  */);
   use_file_dialog = true;
 
+  DEFVAR_BOOL ("use-short-answers", use_short_answers,
+    doc: /* Non-nil means `yes-or-no-p' uses shorter answers "y" or "n".
+When non-nil, `yes-or-no-p' will use `y-or-n-p' to read the answer.
+We recommend against setting this variable non-nil, because `yes-or-no-p'
+is intended to be used when users are expected not to respond too
+quickly, but to take their time and perhaps think about the answer.
+The same variable also affects the function `read-answer'.  */);
+  use_short_answers = false;
+
   defsubr (&Sidentity);
   defsubr (&Srandom);
   defsubr (&Slength);
diff --git a/src/font.c b/src/font.c
index a59ebe2..7c1d1ff 100644
--- a/src/font.c
+++ b/src/font.c
@@ -4122,7 +4122,7 @@ representing the OpenType features supported by the font 
by this form:
 SCRIPT, LANGSYS, and FEATURE are all symbols representing OpenType
 Layout tags.
 
-In addition to the keys listed abobe, the following keys are reserved
+In addition to the keys listed above, the following keys are reserved
 for the specific meanings as below:
 
 The value of :combining-capability is non-nil if the font-backend of
diff --git a/src/frame.c b/src/frame.c
index 635fc94..66ae494 100644
--- a/src/frame.c
+++ b/src/frame.c
@@ -1487,7 +1487,7 @@ do_switch_frame (Lisp_Object frame, int track, int 
for_deletion, Lisp_Object nor
 #endif
     internal_last_event_frame = Qnil;
 
-  move_minibuffer_onto_frame ();
+  move_minibuffers_onto_frame (sf, for_deletion);
   return frame;
 }
 
@@ -3595,7 +3595,7 @@ check_frame_pixels (Lisp_Object size, Lisp_Object 
pixelwise, int item_size)
 }
 
 DEFUN ("set-frame-height", Fset_frame_height, Sset_frame_height, 2, 4,
-       "(list (selected-frame) (prefix-numeric-value current-prefix-arg))",
+       "(set-frame-property--interactive \"Frame height: \" (frame-height))",
        doc: /* Set text height of frame FRAME to HEIGHT lines.
 Optional third arg PRETEND non-nil means that redisplay should use
 HEIGHT lines but that the idea of the actual height of the frame should
@@ -3620,7 +3620,7 @@ If FRAME is nil, it defaults to the selected frame.  */)
 }
 
 DEFUN ("set-frame-width", Fset_frame_width, Sset_frame_width, 2, 4,
-       "(list (selected-frame) (prefix-numeric-value current-prefix-arg))",
+       "(set-frame-property--interactive \"Frame width: \" (frame-width))",
        doc: /* Set text width of frame FRAME to WIDTH columns.
 Optional third arg PRETEND non-nil means that redisplay should use WIDTH
 columns but that the idea of the actual width of the frame should not
@@ -3890,7 +3890,7 @@ frame_float (struct frame *f, Lisp_Object val, enum 
frame_float_type what,
              Lisp_Object frame;
 
              XSETFRAME (frame, f);
-             monitor_attributes = Fcar (call1 
(Qdisplay_monitor_attributes_list, frame));
+             monitor_attributes = call1 (Qframe_monitor_attributes, frame);
              if (NILP (monitor_attributes))
                {
                  /* No monitor attributes available.  */
@@ -5890,7 +5890,7 @@ syms_of_frame (void)
   DEFSYM (Qframep, "framep");
   DEFSYM (Qframe_live_p, "frame-live-p");
   DEFSYM (Qframe_windows_min_size, "frame-windows-min-size");
-  DEFSYM (Qdisplay_monitor_attributes_list, "display-monitor-attributes-list");
+  DEFSYM (Qframe_monitor_attributes, "frame-monitor-attributes");
   DEFSYM (Qwindow__pixel_to_total, "window--pixel-to-total");
   DEFSYM (Qexplicit_name, "explicit-name");
   DEFSYM (Qheight, "height");
diff --git a/src/gnutls.c b/src/gnutls.c
index aa245ee..4d5a909 100644
--- a/src/gnutls.c
+++ b/src/gnutls.c
@@ -625,6 +625,8 @@ gnutls_try_handshake (struct Lisp_Process *proc)
 
   while ((ret = gnutls_handshake (state)) < 0)
     {
+      if (gnutls_error_is_fatal (ret))
+       return emacs_gnutls_handle_error (state, ret);
       do
        ret = gnutls_handshake (state);
       while (ret == GNUTLS_E_INTERRUPTED);
diff --git a/src/gtkutil.c b/src/gtkutil.c
index 11e59b9..4634c35 100644
--- a/src/gtkutil.c
+++ b/src/gtkutil.c
@@ -5014,11 +5014,10 @@ update_frame_tool_bar (struct frame *f)
       GtkWidget *wbutton = NULL;
       Lisp_Object specified_file;
       bool vert_only = ! NILP (PROP (TOOL_BAR_ITEM_VERT_ONLY));
-      const char *label
-       = (EQ (style, Qimage) || (vert_only && horiz)) ? NULL
-       : STRINGP (PROP (TOOL_BAR_ITEM_LABEL))
-       ? SSDATA (PROP (TOOL_BAR_ITEM_LABEL))
-       : "";
+      Lisp_Object label
+       = (EQ (style, Qimage) || (vert_only && horiz))
+       ? Qnil
+       : PROP (TOOL_BAR_ITEM_LABEL);
 
       ti = gtk_toolbar_get_nth_item (GTK_TOOLBAR (wtoolbar), j);
 
@@ -5131,8 +5130,11 @@ update_frame_tool_bar (struct frame *f)
 
       /* If there is an existing widget, check if it's stale; if so,
         remove it and make a new tool item from scratch.  */
-      if (ti && xg_tool_item_stale_p (wbutton, stock_name, icon_name,
-                                     img, label, horiz))
+      if (ti && xg_tool_item_stale_p (wbutton, stock_name, icon_name, img,
+                                     NILP (label)
+                                     ? NULL
+                                     : STRINGP (label) ? SSDATA (label) : "",
+                                     horiz))
        {
          gtk_container_remove (GTK_CONTAINER (wtoolbar),
                                GTK_WIDGET (ti));
@@ -5189,7 +5191,11 @@ update_frame_tool_bar (struct frame *f)
 #else
          if (w) gtk_misc_set_padding (GTK_MISC (w), hmargin, vmargin);
 #endif
-          ti = xg_make_tool_item (f, w, &wbutton, label, i, horiz, text_image);
+          ti = xg_make_tool_item (f, w, &wbutton,
+                                 NILP (label)
+                                 ? NULL
+                                 : STRINGP (label) ? SSDATA (label) : "",
+                                 i, horiz, text_image);
           gtk_toolbar_insert (GTK_TOOLBAR (wtoolbar), ti, j);
         }
 
diff --git a/src/image.c b/src/image.c
index a124cf9..b85418c 100644
--- a/src/image.c
+++ b/src/image.c
@@ -135,6 +135,14 @@ typedef struct ns_bitmap_record Bitmap_Record;
 # define COLOR_TABLE_SUPPORT 1
 #endif
 
+#ifdef HAVE_RSVG
+#if defined HAVE_NS
+# define FRAME_SCALE_FACTOR(f) ns_frame_scale_factor (f)
+#else
+# define FRAME_SCALE_FACTOR(f) 1;
+#endif
+#endif
+
 static void image_disable_image (struct frame *, struct image *);
 static void image_edge_detection (struct frame *, struct image *, Lisp_Object,
                                   Lisp_Object);
@@ -2207,8 +2215,8 @@ image_set_transform (struct frame *f, struct image *img)
   /* SVGs are pre-scaled to the correct size.  */
   if (EQ (image_spec_value (img->spec, QCtype, NULL), Qsvg))
     {
-      width = img->width;
-      height = img->height;
+      width = img->width / FRAME_SCALE_FACTOR (f);
+      height = img->height / FRAME_SCALE_FACTOR (f);
     }
   else
 #endif
@@ -2219,12 +2227,17 @@ image_set_transform (struct frame *f, struct image *img)
   compute_image_rotation (img, &rotation);
 
 # if defined USE_CAIRO || defined HAVE_XRENDER || defined HAVE_NS
-  /* We want scale up operations to use a nearest neighbour filter to
+  /* We want scale up operations to use a nearest neighbor filter to
      show real pixels instead of munging them, but scale down
      operations to use a blended filter, to avoid aliasing and the like.
 
      TODO: implement for Windows.  */
-  bool scale_down = (width < img->width) || (height < img->height);
+  bool smoothing;
+  Lisp_Object s = image_spec_value (img->spec, QCtransform_smoothing, NULL);
+  if (NILP (s))
+    smoothing = (width < img->width) || (height < img->height);
+  else
+    smoothing = !NILP (s);
 # endif
 
   /* Perform scale transformation.  */
@@ -2338,13 +2351,13 @@ image_set_transform (struct frame *f, struct image *img)
   /* Under NS the transform is applied to the drawing surface at
      drawing time, so store it for later.  */
   ns_image_set_transform (img->pixmap, matrix);
-  ns_image_set_smoothing (img->pixmap, scale_down);
+  ns_image_set_smoothing (img->pixmap, smoothing);
 # elif defined USE_CAIRO
   cairo_matrix_t cr_matrix = {matrix[0][0], matrix[0][1], matrix[1][0],
                              matrix[1][1], matrix[2][0], matrix[2][1]};
   cairo_pattern_t *pattern = cairo_pattern_create_rgb (0, 0, 0);
   cairo_pattern_set_matrix (pattern, &cr_matrix);
-  cairo_pattern_set_filter (pattern, scale_down
+  cairo_pattern_set_filter (pattern, smoothing
                             ? CAIRO_FILTER_BEST : CAIRO_FILTER_NEAREST);
   /* Dummy solid color pattern just to record pattern matrix.  */
   img->cr_data = pattern;
@@ -2363,13 +2376,13 @@ image_set_transform (struct frame *f, struct image *img)
              XDoubleToFixed (matrix[2][2])}}};
 
       XRenderSetPictureFilter (FRAME_X_DISPLAY (f), img->picture,
-                               scale_down ? FilterBest : FilterNearest, 0, 0);
+                               smoothing ? FilterBest : FilterNearest, 0, 0);
       XRenderSetPictureTransform (FRAME_X_DISPLAY (f), img->picture, &tmat);
 
       if (img->mask_picture)
         {
           XRenderSetPictureFilter (FRAME_X_DISPLAY (f), img->mask_picture,
-                                   scale_down ? FilterBest : FilterNearest, 0, 
0);
+                                   smoothing ? FilterBest : FilterNearest, 0, 
0);
           XRenderSetPictureTransform (FRAME_X_DISPLAY (f), img->mask_picture,
                                       &tmat);
         }
@@ -3379,6 +3392,7 @@ static int
 xbm_scan (char **s, char *end, char *sval, int *ival)
 {
   unsigned char c UNINIT;
+  char *sval_end = sval + BUFSIZ;
 
  loop:
 
@@ -3438,7 +3452,7 @@ xbm_scan (char **s, char *end, char *sval, int *ival)
   else if (c_isalpha (c) || c == '_')
     {
       *sval++ = c;
-      while (*s < end
+      while (*s < end && sval < sval_end
             && (c = *(*s)++, (c_isalnum (c) || c == '_')))
        *sval++ = c;
       *sval = 0;
@@ -10008,6 +10022,9 @@ svg_load_image (struct frame *f, struct image *img, 
char *contents,
   compute_image_size (viewbox_width, viewbox_height, img->spec,
                       &width, &height);
 
+  width *= FRAME_SCALE_FACTOR (f);
+  height *= FRAME_SCALE_FACTOR (f);
+
   if (! check_image_size (f, width, height))
     {
       image_size_error ();
@@ -10684,6 +10701,7 @@ non-numeric, there is no explicit limit on the size of 
images.  */);
   DEFSYM (QCrotation, ":rotation");
   DEFSYM (QCmatrix, ":matrix");
   DEFSYM (QCscale, ":scale");
+  DEFSYM (QCtransform_smoothing, ":transform-smoothing");
   DEFSYM (QCcolor_adjustment, ":color-adjustment");
   DEFSYM (QCmask, ":mask");
 
diff --git a/src/indent.c b/src/indent.c
index 0a6b460..6246b54 100644
--- a/src/indent.c
+++ b/src/indent.c
@@ -1315,7 +1315,7 @@ compute_motion (ptrdiff_t from, ptrdiff_t frombyte, 
EMACS_INT fromvpos,
             j        ^---- next after the point
             ^---  next char. after the point.
             ----------
-                     In case of sigle-column character
+                     In case of single-column character
 
             ----------
             abcdefgh\\
diff --git a/src/json.c b/src/json.c
index 2901a20..3f1d27a 100644
--- a/src/json.c
+++ b/src/json.c
@@ -327,13 +327,14 @@ struct json_configuration {
   Lisp_Object false_object;
 };
 
-static json_t *lisp_to_json (Lisp_Object, struct json_configuration *conf);
+static json_t *lisp_to_json (Lisp_Object,
+                             const struct json_configuration *conf);
 
-/* Convert a Lisp object to a toplevel JSON object (array or object).  */
+/* Convert a Lisp object to a nonscalar JSON object (array or object).  */
 
 static json_t *
-lisp_to_json_toplevel_1 (Lisp_Object lisp,
-                         struct json_configuration *conf)
+lisp_to_json_nonscalar_1 (Lisp_Object lisp,
+                          const struct json_configuration *conf)
 {
   json_t *json;
   ptrdiff_t count;
@@ -448,16 +449,17 @@ lisp_to_json_toplevel_1 (Lisp_Object lisp,
   return json;
 }
 
-/* Convert LISP to a toplevel JSON object (array or object).  Signal
+/* Convert LISP to a nonscalar JSON object (array or object).  Signal
    an error of type `wrong-type-argument' if LISP is not a vector,
    hashtable, alist, or plist.  */
 
 static json_t *
-lisp_to_json_toplevel (Lisp_Object lisp, struct json_configuration *conf)
+lisp_to_json_nonscalar (Lisp_Object lisp,
+                        const struct json_configuration *conf)
 {
   if (++lisp_eval_depth > max_lisp_eval_depth)
     xsignal0 (Qjson_object_too_deep);
-  json_t *json = lisp_to_json_toplevel_1 (lisp, conf);
+  json_t *json = lisp_to_json_nonscalar_1 (lisp, conf);
   --lisp_eval_depth;
   return json;
 }
@@ -467,7 +469,7 @@ lisp_to_json_toplevel (Lisp_Object lisp, struct 
json_configuration *conf)
    JSON object.  */
 
 static json_t *
-lisp_to_json (Lisp_Object lisp, struct json_configuration *conf)
+lisp_to_json (Lisp_Object lisp, const struct json_configuration *conf)
 {
   if (EQ (lisp, conf->null_object))
     return json_check (json_null ());
@@ -499,7 +501,7 @@ lisp_to_json (Lisp_Object lisp, struct json_configuration 
*conf)
     }
 
   /* LISP now must be a vector, hashtable, alist, or plist.  */
-  return lisp_to_json_toplevel (lisp, conf);
+  return lisp_to_json_nonscalar (lisp, conf);
 }
 
 static void
@@ -557,15 +559,15 @@ DEFUN ("json-serialize", Fjson_serialize, 
Sjson_serialize, 1, MANY,
        NULL,
        doc: /* Return the JSON representation of OBJECT as a string.
 
-OBJECT must be a vector, hashtable, alist, or plist and its elements
-can recursively contain the Lisp equivalents to the JSON null and
-false values, t, numbers, strings, or other vectors hashtables, alists
-or plists.  t will be converted to the JSON true value.  Vectors will
-be converted to JSON arrays, whereas hashtables, alists and plists are
-converted to JSON objects.  Hashtable keys must be strings without
-embedded null characters and must be unique within each object.  Alist
-and plist keys must be symbols; if a key is duplicate, the first
-instance is used.
+OBJECT must be t, a number, string, vector, hashtable, alist, plist,
+or the Lisp equivalents to the JSON null and false values, and its
+elements must recursively consist of the same kinds of values.  t will
+be converted to the JSON true value.  Vectors will be converted to
+JSON arrays, whereas hashtables, alists and plists are converted to
+JSON objects.  Hashtable keys must be strings without embedded null
+characters and must be unique within each object.  Alist and plist
+keys must be symbols; if a key is duplicate, the first instance is
+used.
 
 The Lisp equivalents to the JSON null and false values are
 configurable in the arguments ARGS, a list of keyword/argument pairs:
@@ -603,12 +605,10 @@ usage: (json-serialize OBJECT &rest ARGS)  */)
     {json_object_hashtable, json_array_array, QCnull, QCfalse};
   json_parse_args (nargs - 1, args + 1, &conf, false);
 
-  json_t *json = lisp_to_json_toplevel (args[0], &conf);
+  json_t *json = lisp_to_json (args[0], &conf);
   record_unwind_protect_ptr (json_release_object, json);
 
-  /* If desired, we might want to add the following flags:
-     JSON_DECODE_ANY, JSON_ALLOW_NUL.  */
-  char *string = json_dumps (json, JSON_COMPACT);
+  char *string = json_dumps (json, JSON_COMPACT | JSON_ENCODE_ANY);
   if (string == NULL)
     json_out_of_memory ();
   record_unwind_protect_ptr (json_free, string);
@@ -723,12 +723,10 @@ usage: (json-insert OBJECT &rest ARGS)  */)
   move_gap_both (PT, PT_BYTE);
   struct json_insert_data data;
   data.inserted_bytes = 0;
-  /* If desired, we might want to add the following flags:
-     JSON_DECODE_ANY, JSON_ALLOW_NUL.  */
-  int status
-    /* Could have used json_dumpb, but that became available only in
-       Jansson 2.10, whereas we want to support 2.7 and upward.  */
-    = json_dump_callback (json, json_insert_callback, &data, JSON_COMPACT);
+  /* Could have used json_dumpb, but that became available only in
+     Jansson 2.10, whereas we want to support 2.7 and upward.  */
+  int status = json_dump_callback (json, json_insert_callback, &data,
+                                   JSON_COMPACT | JSON_ENCODE_ANY);
   if (status == -1)
     {
       if (CONSP (data.error))
@@ -791,7 +789,7 @@ usage: (json-insert OBJECT &rest ARGS)  */)
 /* Convert a JSON object to a Lisp object.  */
 
 static Lisp_Object ARG_NONNULL ((1))
-json_to_lisp (json_t *json, struct json_configuration *conf)
+json_to_lisp (json_t *json, const struct json_configuration *conf)
 {
   switch (json_typeof (json))
     {
@@ -932,12 +930,12 @@ DEFUN ("json-parse-string", Fjson_parse_string, 
Sjson_parse_string, 1, MANY,
        NULL,
        doc: /* Parse the JSON STRING into a Lisp object.
 This is essentially the reverse operation of `json-serialize', which
-see.  The returned object will be a vector, list, hashtable, alist, or
-plist.  Its elements will be the JSON null value, the JSON false
-value, t, numbers, strings, or further vectors, hashtables, alists, or
-plists.  If there are duplicate keys in an object, all but the last
-one are ignored.  If STRING doesn't contain a valid JSON object, this
-function signals an error of type `json-parse-error'.
+see.  The returned object will be the JSON null value, the JSON false
+value, t, a number, a string, a vector, a list, a hashtable, an alist,
+or a plist.  Its elements will be further objects of these types.  If
+there are duplicate keys in an object, all but the last one are
+ignored.  If STRING doesn't contain a valid JSON object, this function
+signals an error of type `json-parse-error'.
 
 The arguments ARGS are a list of keyword/argument pairs:
 
@@ -982,7 +980,8 @@ usage: (json-parse-string STRING &rest ARGS) */)
   json_parse_args (nargs - 1, args + 1, &conf, true);
 
   json_error_t error;
-  json_t *object = json_loads (SSDATA (encoded), 0, &error);
+  json_t *object
+    = json_loads (SSDATA (encoded), JSON_DECODE_ANY, &error);
   if (object == NULL)
     json_parse_error (&error);
 
@@ -1078,8 +1077,10 @@ usage: (json-parse-buffer &rest args) */)
   ptrdiff_t point = PT_BYTE;
   struct json_read_buffer_data data = {.point = point};
   json_error_t error;
-  json_t *object = json_load_callback (json_read_buffer_callback, &data,
-                                       JSON_DISABLE_EOF_CHECK, &error);
+  json_t *object
+    = json_load_callback (json_read_buffer_callback, &data,
+                          JSON_DECODE_ANY | JSON_DISABLE_EOF_CHECK,
+                          &error);
 
   if (object == NULL)
     json_parse_error (&error);
diff --git a/src/keyboard.c b/src/keyboard.c
index 9ee4c4f..266ebaa 100644
--- a/src/keyboard.c
+++ b/src/keyboard.c
@@ -3614,6 +3614,12 @@ kbd_buffer_store_buffered_event (union 
buffered_input_event *event,
     case ICONIFY_EVENT: ignore_event = Qiconify_frame; break;
     case DEICONIFY_EVENT: ignore_event = Qmake_frame_visible; break;
     case SELECTION_REQUEST_EVENT: ignore_event = Qselection_request; break;
+#ifdef USE_FILE_NOTIFY
+    case FILE_NOTIFY_EVENT: ignore_event = Qfile_notify; break;
+#endif
+#ifdef HAVE_DBUS
+    case DBUS_EVENT: ignore_event = Qdbus_event; break;
+#endif
     default: ignore_event = Qnil; break;
     }
 
@@ -6679,6 +6685,7 @@ parse_solitary_modifier (Lisp_Object symbol)
     case 'c':
       MULTI_LETTER_MOD (ctrl_modifier, "ctrl", 4);
       MULTI_LETTER_MOD (ctrl_modifier, "control", 7);
+      MULTI_LETTER_MOD (click_modifier, "click", 5);
       break;
 
     case 'H':
@@ -12380,8 +12387,6 @@ syms_of_keyboard_for_pdumper (void)
   eassert (initial_kboard == NULL);
   initial_kboard = allocate_kboard (Qt);
 
-  Vwhile_no_input_ignore_events = Qnil;
-
   inhibit_record_char = false;
 }
 
diff --git a/src/keymap.c b/src/keymap.c
index 782931f..bb26b63 100644
--- a/src/keymap.c
+++ b/src/keymap.c
@@ -2846,6 +2846,21 @@ DESCRIBER is the output function used; nil means use 
`princ'.  */)
   return unbind_to (count, Qnil);
 }
 
+static Lisp_Object fontify_key_properties;
+
+static Lisp_Object
+describe_key_maybe_fontify (Lisp_Object str, Lisp_Object prefix,
+                                  bool keymap_p)
+{
+  Lisp_Object key_desc = Fkey_description (str, prefix);
+  if (keymap_p)
+    Fadd_text_properties (make_fixnum (0),
+                         make_fixnum (SCHARS (key_desc)),
+                         fontify_key_properties,
+                         key_desc);
+  return key_desc;
+}
+
 DEFUN ("help--describe-vector", Fhelp__describe_vector, 
Shelp__describe_vector, 7, 7, 0,
        doc: /* Insert in the current buffer a description of the contents of 
VECTOR.
 Call DESCRIBER to insert the description of one value found in VECTOR.
@@ -3021,7 +3036,7 @@ describe_vector (Lisp_Object vector, Lisp_Object prefix, 
Lisp_Object args,
       if (!NILP (elt_prefix))
        insert1 (elt_prefix);
 
-      insert1 (Fkey_description (kludge, prefix));
+      insert1 (describe_key_maybe_fontify (kludge, prefix, keymap_p));
 
       /* Find all consecutive characters or rows that have the same
         definition.  But, if VECTOR is a char-table, we had better
@@ -3071,7 +3086,7 @@ describe_vector (Lisp_Object vector, Lisp_Object prefix, 
Lisp_Object args,
          if (!NILP (elt_prefix))
            insert1 (elt_prefix);
 
-         insert1 (Fkey_description (kludge, prefix));
+         insert1 (describe_key_maybe_fontify (kludge, prefix, keymap_p));
        }
 
       /* Print a description of the definition of this character.
@@ -3200,6 +3215,12 @@ be preferred.  */);
   staticpro (&where_is_cache);
   staticpro (&where_is_cache_keymaps);
 
+  DEFSYM (Qfont_lock_face, "font-lock-face");
+  DEFSYM (Qhelp_key_binding, "help-key-binding");
+  staticpro (&fontify_key_properties);
+  fontify_key_properties = Fcons (Qfont_lock_face,
+                                 Fcons (Qhelp_key_binding, Qnil));
+
   defsubr (&Skeymapp);
   defsubr (&Skeymap_parent);
   defsubr (&Skeymap_prompt);
diff --git a/src/lisp.h b/src/lisp.h
index 409a1e7..c67c8b0 100644
--- a/src/lisp.h
+++ b/src/lisp.h
@@ -3610,6 +3610,7 @@ extern void validate_subarray (Lisp_Object, Lisp_Object, 
Lisp_Object,
 extern Lisp_Object substring_both (Lisp_Object, ptrdiff_t, ptrdiff_t,
                                   ptrdiff_t, ptrdiff_t);
 extern Lisp_Object merge (Lisp_Object, Lisp_Object, Lisp_Object);
+extern Lisp_Object merge_c (Lisp_Object, Lisp_Object, bool (*) (Lisp_Object, 
Lisp_Object));
 extern Lisp_Object do_yes_or_no_p (Lisp_Object);
 extern int string_version_cmp (Lisp_Object, Lisp_Object);
 extern Lisp_Object concat2 (Lisp_Object, Lisp_Object);
@@ -4091,6 +4092,7 @@ intern_c_string (const char *str)
 }
 
 /* Defined in eval.c.  */
+extern EMACS_INT minibuffer_quit_level;
 extern Lisp_Object Vautoload_queue;
 extern Lisp_Object Vrun_hooks;
 extern Lisp_Object Vsignaling_function;
@@ -4220,6 +4222,8 @@ extern Lisp_Object module_function_documentation
   (struct Lisp_Module_Function const *);
 extern Lisp_Object module_function_interactive_form
   (const struct Lisp_Module_Function *);
+extern Lisp_Object module_function_command_modes
+  (const struct Lisp_Module_Function *);
 extern module_funcptr module_function_address
   (struct Lisp_Module_Function const *);
 extern void *module_function_data (const struct Lisp_Module_Function *);
@@ -4345,7 +4349,7 @@ extern void clear_regexp_cache (void);
 
 extern Lisp_Object Vminibuffer_list;
 extern Lisp_Object last_minibuf_string;
-extern void move_minibuffer_onto_frame (void);
+extern void move_minibuffers_onto_frame (struct frame *, bool);
 extern bool is_minibuffer (EMACS_INT, Lisp_Object);
 extern EMACS_INT this_minibuffer_depth (Lisp_Object);
 extern EMACS_INT minibuf_level;
@@ -4369,6 +4373,7 @@ extern void syms_of_casetab (void);
 
 /* Defined in keyboard.c.  */
 
+extern EMACS_INT command_loop_level;
 extern Lisp_Object echo_message_buffer;
 extern struct kboard *echo_kboard;
 extern void cancel_echoing (void);
diff --git a/src/marker.c b/src/marker.c
index 5979151..2b137b1 100644
--- a/src/marker.c
+++ b/src/marker.c
@@ -634,16 +634,15 @@ set_marker_restricted_both (Lisp_Object marker, 
Lisp_Object buffer,
 /* Detach a marker so that it no longer points anywhere and no longer
    slows down editing.  Do not free the marker, though, as a change
    function could have inserted it into an undo list (Bug#30931).  */
+
 void
 detach_marker (Lisp_Object marker)
 {
   Fset_marker (marker, Qnil, Qnil);
 }
 
-/* Remove MARKER from the chain of whatever buffer it is in,
-   leaving it points to nowhere.  This is called during garbage
-   collection, so we must be careful to ignore and preserve
-   mark bits, including those in chain fields of markers.  */
+/* Remove MARKER from the chain of whatever buffer it is in.  Set its
+   buffer NULL.  */
 
 void
 unchain_marker (register struct Lisp_Marker *marker)
diff --git a/src/minibuf.c b/src/minibuf.c
index 949c3d9..c9831fd 100644
--- a/src/minibuf.c
+++ b/src/minibuf.c
@@ -41,6 +41,7 @@ along with GNU Emacs.  If not, see 
<https://www.gnu.org/licenses/>.  */
    minibuffer recursions are encountered.  */
 
 Lisp_Object Vminibuffer_list;
+Lisp_Object Vcommand_loop_level_list;
 
 /* Data to remember during recursive minibuffer invocations.  */
 
@@ -58,12 +59,21 @@ Lisp_Object last_minibuf_string;
 
 static Lisp_Object minibuf_prompt;
 
+/* The frame containinug the most recently opened Minibuffer.  This is
+   used only when `minibuffer-follows-selected-frame' is neither nil
+   nor t.  */
+
+static Lisp_Object MB_frame;
+
 /* Width of current mini-buffer prompt.  Only set after display_line
    of the line that contains the prompt.  */
 
 static ptrdiff_t minibuf_prompt_width;
 
 static Lisp_Object nth_minibuffer (EMACS_INT depth);
+static EMACS_INT minibuf_c_loop_level (EMACS_INT depth);
+static void set_minibuffer_mode (Lisp_Object buf, EMACS_INT depth);
+static bool live_minibuffer_p (Lisp_Object);
 
 
 /* Return TRUE when a frame switch causes a minibuffer on the old
@@ -75,6 +85,7 @@ minibuf_follows_frame (void)
              Qt);
 }
 
+#if 0
 /* Return TRUE when a minibuffer always remains on the frame where it
    was first invoked. */
 static bool
@@ -82,6 +93,7 @@ minibuf_stays_put (void)
 {
   return NILP (Fdefault_toplevel_value (Qminibuffer_follows_selected_frame));
 }
+#endif
 
 /* Return TRUE when opening a (recursive) minibuffer causes
    minibuffers on other frames to move to the selected frame.  */
@@ -109,79 +121,85 @@ choose_minibuf_frame (void)
        emacs_abort ();
 
       minibuf_window = sf->minibuffer_window;
-      /* If we've still got another minibuffer open, use its mini-window
-         instead.  */
-      if (minibuf_level > 1 && minibuf_stays_put ())
-        {
-          Lisp_Object buffer = get_minibuffer (minibuf_level);
-          Lisp_Object tail, frame;
-
-          FOR_EACH_FRAME (tail, frame)
-            if (EQ (XWINDOW (XFRAME (frame)->minibuffer_window)->contents,
-                    buffer))
-              {
-                minibuf_window = XFRAME (frame)->minibuffer_window;
-                break;
-              }
-        }
     }
+}
 
-  if (minibuf_moves_frame_when_opened ()
-      && FRAMEP (selected_frame)
-      && FRAME_LIVE_P (XFRAME (selected_frame)))
-    /* Make sure no other frame has a minibuffer as its selected window,
-       because the text would not be displayed in it, and that would be
-       confusing.  Only allow the selected frame to do this,
-       and that only if the minibuffer is active.  */
-  {
-    Lisp_Object tail, frame;
-    struct frame *of;
-
-    FOR_EACH_FRAME (tail, frame)
-      if (!EQ (frame, selected_frame)
-          && minibuf_level > 1
-         /* The frame's minibuffer can be on a different frame.  */
-         && ! EQ (XWINDOW ((of = XFRAME (frame))->minibuffer_window)->frame,
-                  selected_frame))
-        {
-          if (MINI_WINDOW_P (XWINDOW (FRAME_SELECTED_WINDOW (of))))
-            Fset_frame_selected_window (frame, Fframe_first_window (frame),
-                                        Qnil);
-
-          if (!EQ (XWINDOW (of->minibuffer_window)->contents,
-                   nth_minibuffer (0)))
-            set_window_buffer (of->minibuffer_window,
-                               nth_minibuffer (0), 0, 0);
-        }
-  }
+/* If ENT1 has a higher minibuffer index than ENT2, return true.  More
+precisely, compare the buffer components of each window->prev_buffers
+entry.  */
+static bool
+minibuffer_ent_greater (Lisp_Object ent1, Lisp_Object ent2)
+{
+  return this_minibuffer_depth (Fcar (ent1))
+    > this_minibuffer_depth (Fcar (ent2)) ;
 }
 
-/* If `minibuffer_follows_selected_frame' is t and we have a
-   minibuffer, move it from its current frame to the selected frame.
-   This function is intended to be called from `do_switch_frame' in
-   frame.c.  */
-void move_minibuffer_onto_frame (void)
+/* Move the ordered "stack" of minibuffers from SOURCE_WINDOW to
+   DEST_WINDOW, interleaving those minibuffers with any in DEST_WINDOW
+   to produce an ordered combination.  The ordering is by minibuffer
+   depth.  A stack of minibuffers consists of the minibuffer currently
+   in DEST/SOURCE_WINDOW together with any recorded in the
+   ->prev_buffers field of the struct window.  */
+static void
+zip_minibuffer_stacks (Lisp_Object dest_window, Lisp_Object source_window)
 {
-  if (!minibuf_level)
-    return;
-  if (!minibuf_follows_frame ())
-    return;
-  if (FRAMEP (selected_frame)
-      && FRAME_LIVE_P (XFRAME (selected_frame))
-      && !EQ (minibuf_window, XFRAME (selected_frame)->minibuffer_window))
+  struct window *dw = XWINDOW (dest_window);
+  struct window *sw = XWINDOW (source_window);
+  Lisp_Object acc;
+  Lisp_Object d_ent;   /* Entry from dw->prev_buffers */
+
+  if (!live_minibuffer_p (dw->contents)
+      && NILP (dw->prev_buffers))
     {
-      EMACS_INT i;
-      struct frame *sf = XFRAME (selected_frame);
-      Lisp_Object old_frame = XWINDOW (minibuf_window)->frame;
-      struct frame *of = XFRAME (old_frame);
+      set_window_buffer (dest_window, sw->contents, 0, 0);
+      Fset_window_start (dest_window, Fwindow_start (source_window), Qnil);
+      Fset_window_point (dest_window, Fwindow_point (source_window));
+      dw->prev_buffers = sw->prev_buffers;
+      set_window_buffer (source_window, get_minibuffer (0), 0, 0);
+      sw->prev_buffers = Qnil;
+      return;
+    }
 
-      /* Stack up all the (recursively) open minibuffers on the selected
-         mini_window.  */
-      for (i = 1; i <= minibuf_level; i++)
-       set_window_buffer (sf->minibuffer_window, nth_minibuffer (i), 0, 0);
-      minibuf_window = sf->minibuffer_window;
-      if (of != sf)
-       set_window_buffer (of->minibuffer_window, get_minibuffer (0), 0, 0);
+  if (live_minibuffer_p (dw->contents))
+    call1 (Qrecord_window_buffer, dest_window);
+  if (live_minibuffer_p (sw->contents))
+    call1 (Qrecord_window_buffer, source_window);
+
+  acc = merge_c (dw->prev_buffers, sw->prev_buffers, minibuffer_ent_greater);
+
+  if (!NILP (acc))
+    {
+      d_ent = Fcar (acc);
+      acc = Fcdr (acc);
+      set_window_buffer (dest_window, Fcar (d_ent), 0, 0);
+      Fset_window_start (dest_window, Fcar (Fcdr (d_ent)), Qnil);
+      Fset_window_point (dest_window, Fcar (Fcdr (Fcdr (d_ent))));
+    }
+  dw->prev_buffers = acc;
+  sw->prev_buffers = Qnil;
+  set_window_buffer (source_window, get_minibuffer (0), 0, 0);
+}
+
+/* If `minibuffer_follows_selected_frame' is t, or we're about to
+   delete a frame which potentially "contains" minibuffers, move them
+   from the old frame to the selected frame.  This function is
+   intended to be called from `do_switch_frame' in frame.c.  OF is the
+   old frame, FOR_DELETION is true if OF is about to be deleted.  */
+void
+move_minibuffers_onto_frame (struct frame *of, bool for_deletion)
+{
+  struct frame *f = XFRAME (selected_frame);
+
+  minibuf_window = f->minibuffer_window;
+  if (!(minibuf_level
+       && (for_deletion || minibuf_follows_frame () || FRAME_INITIAL_P (of))))
+    return;
+  if (FRAME_LIVE_P (f)
+      && !EQ (f->minibuffer_window, of->minibuffer_window))
+    {
+      zip_minibuffer_stacks (f->minibuffer_window, of->minibuffer_window);
+      if (for_deletion && XFRAME (MB_frame) != of)
+       MB_frame = selected_frame;
     }
 }
 
@@ -213,6 +231,7 @@ without invoking the usual minibuffer commands.  */)
 /* Actual minibuffer invocation.  */
 
 static void read_minibuf_unwind (void);
+static void minibuffer_unwind (void);
 static void run_exit_minibuf_hook (void);
 
 
@@ -389,6 +408,21 @@ No argument or nil as argument means use the current 
buffer as BUFFER.  */)
     : Qnil;
 }
 
+DEFUN ("minibuffer-innermost-command-loop-p", 
Fminibuffer_innermost_command_loop_p,
+       Sminibuffer_innermost_command_loop_p, 0, 1, 0,
+       doc: /* Return t if BUFFER is a minibuffer at the current command loop 
level.
+No argument or nil as argument means use the current buffer as BUFFER.  */)
+  (Lisp_Object buffer)
+{
+  EMACS_INT depth;
+  if (NILP (buffer))
+    buffer = Fcurrent_buffer ();
+  depth = this_minibuffer_depth (buffer);
+  return depth && minibuf_c_loop_level (depth) == command_loop_level
+    ? Qt
+    : Qnil;
+}
+
 /* Return the nesting depth of the active minibuffer BUFFER, or 0 if
    BUFFER isn't such a thing.  If BUFFER is nil, this means use the current
    buffer.  */
@@ -420,12 +454,17 @@ confirm the aborting of the current minibuffer and all 
contained ones.  */)
 
   if (!minibuf_depth)
     error ("Not in a minibuffer");
+  if (NILP (Fminibuffer_innermost_command_loop_p (Qnil)))
+    error ("Not in most nested command loop");
   if (minibuf_depth < minibuf_level)
     {
       array[0] = fmt;
       array[1] = make_fixnum (minibuf_level - minibuf_depth + 1);
       if (!NILP (Fyes_or_no_p (Fformat (2, array))))
-       Fthrow (Qexit, Qt);
+       {
+         minibuffer_quit_level = minibuf_depth;
+         Fthrow (Qexit, Qt);
+       }
     }
   else
     Fthrow (Qexit, Qt);
@@ -508,6 +547,7 @@ read_minibuf (Lisp_Object map, Lisp_Object initial, 
Lisp_Object prompt,
   ptrdiff_t count = SPECPDL_INDEX ();
   Lisp_Object mini_frame, ambient_dir, minibuffer, input_method;
   Lisp_Object calling_frame = selected_frame;
+  Lisp_Object calling_window = selected_window;
   Lisp_Object enable_multibyte;
   EMACS_INT pos = 0;
   /* String to add to the history.  */
@@ -515,7 +555,6 @@ read_minibuf (Lisp_Object map, Lisp_Object initial, 
Lisp_Object prompt,
   Lisp_Object histval;
 
   Lisp_Object empty_minibuf;
-  Lisp_Object dummy, frame;
 
   specbind (Qminibuffer_default, defalt);
   specbind (Qinhibit_read_only, Qnil);
@@ -597,18 +636,24 @@ read_minibuf (Lisp_Object map, Lisp_Object initial, 
Lisp_Object prompt,
   mini_frame = WINDOW_FRAME (XWINDOW (minibuf_window));
 
   if (minibuf_level > 1
+      && !EQ (XWINDOW (XFRAME (selected_frame)->minibuffer_window)->frame,
+             MB_frame)
       && minibuf_moves_frame_when_opened ()
-      && !minibuf_follows_frame ())
+      && (!minibuf_follows_frame ()))
     {
-      EMACS_INT i;
+      struct frame *of = XFRAME (MB_frame);
 
-      /* Stack up the existing minibuffers on the current mini-window */
-      for (i = 1; i < minibuf_level; i++)
-       set_window_buffer (minibuf_window, nth_minibuffer (i), 0, 0);
+      zip_minibuffer_stacks (minibuf_window, of->minibuffer_window);
+      /* MB_frame's minibuffer can be on a different frame.  */
+      if (MINI_WINDOW_P (XWINDOW (FRAME_SELECTED_WINDOW (of))))
+       Fset_frame_selected_window (MB_frame,
+                                   Fframe_first_window (MB_frame), Qnil);
     }
+  MB_frame = XWINDOW (XFRAME (selected_frame)->minibuffer_window)->frame;
+  if (live_minibuffer_p (XWINDOW (minibuf_window)->contents))
+    call1 (Qrecord_window_buffer, minibuf_window);
 
-  record_unwind_protect_void (choose_minibuf_frame);
-
+  record_unwind_protect_void (minibuffer_unwind);
   record_unwind_protect (restore_window_configuration,
                          Fcons (Qt, Fcurrent_window_configuration (Qnil)));
 
@@ -640,7 +685,9 @@ read_minibuf (Lisp_Object map, Lisp_Object initial, 
Lisp_Object prompt,
   minibuf_save_list
     = Fcons (Voverriding_local_map,
             Fcons (minibuf_window,
-                   minibuf_save_list));
+                   Fcons (calling_frame,
+                          Fcons (calling_window,
+                                 minibuf_save_list))));
   minibuf_save_list
     = Fcons (minibuf_prompt,
             Fcons (make_fixnum (minibuf_prompt_width),
@@ -694,6 +741,7 @@ read_minibuf (Lisp_Object map, Lisp_Object initial, 
Lisp_Object prompt,
   /* Switch to the minibuffer.  */
 
   minibuffer = get_minibuffer (minibuf_level);
+  set_minibuffer_mode (minibuffer, minibuf_level);
   Fset_buffer (minibuffer);
 
   /* Defeat (setq-default truncate-lines t), since truncated lines do
@@ -738,23 +786,7 @@ read_minibuf (Lisp_Object map, Lisp_Object initial, 
Lisp_Object prompt,
      where there is an active minibuffer.
      Set them to point to ` *Minibuf-0*', which is always empty.  */
   empty_minibuf = get_minibuffer (0);
-
-  FOR_EACH_FRAME (dummy, frame)
-    {
-      Lisp_Object root_window = Fframe_root_window (frame);
-      Lisp_Object mini_window = XWINDOW (root_window)->next;
-      Lisp_Object buffer;
-
-      if (!NILP (mini_window) && !EQ (mini_window, minibuf_window)
-          && !NILP (Fwindow_minibuffer_p (mini_window)))
-        {
-          buffer = XWINDOW (mini_window)->contents;
-          if (!live_minibuffer_p (buffer))
-            /* Use set_window_buffer instead of Fset_window_buffer (see
-               discussion of bug#11984, bug#12025, bug#12026).  */
-            set_window_buffer (mini_window, empty_minibuf, 0, 0);
-        }
-    }
+  set_minibuffer_mode (empty_minibuf, 0);
 
   /* Display this minibuffer in the proper window.  */
   /* Use set_window_buffer instead of Fset_window_buffer (see
@@ -837,20 +869,6 @@ read_minibuf (Lisp_Object map, Lisp_Object initial, 
Lisp_Object prompt,
 
   recursive_edit_1 ();
 
-  /* We've exited the recursive edit without an error, so switch the
-     current window away from the expired minibuffer window.  */
-  {
-    Lisp_Object prev = Fprevious_window (minibuf_window, Qnil, Qnil);
-    /* PREV can be on a different frame when we have a minibuffer only
-       frame, the other frame's minibuffer window is MINIBUF_WINDOW,
-       and its "focus window" is also MINIBUF_WINDOW.  */
-    while (!EQ (prev, minibuf_window)
-          && !EQ (selected_frame, WINDOW_FRAME (XWINDOW (prev))))
-      prev = Fprevious_window (prev, Qnil, Qnil);
-    if (!EQ (prev, minibuf_window))
-      Fset_frame_selected_window (selected_frame, prev, Qnil);
-  }
-
   /* If cursor is on the minibuffer line,
      show the user we have exited by putting it in column 0.  */
   if (XWINDOW (minibuf_window)->cursor.vpos >= 0
@@ -890,7 +908,9 @@ read_minibuf (Lisp_Object map, Lisp_Object initial, 
Lisp_Object prompt,
   unbind_to (count, Qnil);
 
   /* Switch the frame back to the calling frame.  */
-  if (!EQ (selected_frame, calling_frame)
+  if ((!EQ (selected_frame, calling_frame)
+       || !EQ (XWINDOW (XFRAME (calling_frame)->minibuffer_window)->frame,
+              calling_frame))
       && FRAMEP (calling_frame)
       && FRAME_LIVE_P (XFRAME (calling_frame)))
     call2 (intern ("select-frame-set-input-focus"), calling_frame, Qnil);
@@ -959,11 +979,16 @@ Lisp_Object
 get_minibuffer (EMACS_INT depth)
 {
   Lisp_Object tail = Fnthcdr (make_fixnum (depth), Vminibuffer_list);
+  Lisp_Object cll_tail = Fnthcdr (make_fixnum (depth),
+                                 Vcommand_loop_level_list);
   if (NILP (tail))
     {
       tail = list1 (Qnil);
       Vminibuffer_list = nconc2 (Vminibuffer_list, tail);
+      cll_tail = list1 (Qnil);
+      Vcommand_loop_level_list = nconc2 (Vcommand_loop_level_list, cll_tail);
     }
+  XSETCAR (cll_tail, make_fixnum (depth ? command_loop_level : 0));
   Lisp_Object buf = Fcar (tail);
   if (NILP (buf) || !BUFFER_LIVE_P (XBUFFER (buf)))
     {
@@ -973,7 +998,6 @@ get_minibuffer (EMACS_INT depth)
       buf = Fget_buffer_create (lname, Qnil);
       /* Do this before set_minibuffer_mode.  */
       XSETCAR (tail, buf);
-      set_minibuffer_mode (buf, depth);
       /* Although the buffer's name starts with a space, undo should be
         enabled in it.  */
       Fbuffer_enable_undo (buf);
@@ -985,18 +1009,33 @@ get_minibuffer (EMACS_INT depth)
         while the buffer doesn't know about them any more.  */
       delete_all_overlays (XBUFFER (buf));
       reset_buffer (XBUFFER (buf));
-      set_minibuffer_mode (buf, depth);
     }
 
   return buf;
 }
 
+static EMACS_INT minibuf_c_loop_level (EMACS_INT depth)
+{
+  Lisp_Object cll = Fnth (make_fixnum (depth), Vcommand_loop_level_list);
+  if (FIXNUMP (cll))
+    return XFIXNUM (cll);
+  return 0;
+}
+
 static void
 run_exit_minibuf_hook (void)
 {
   safe_run_hooks (Qminibuffer_exit_hook);
 }
 
+/* This variable records the expired minibuffer's frame between the
+   calls of `read_minibuf_unwind' and `minibuffer_unwind'.  It should
+   be used only by these two functions.  Note that the same search
+   method for the MB's frame won't always work in `minibuffer_unwind'
+   because the intervening `restore-window-configuration' will have
+   changed the buffer in the mini-window.  */
+static Lisp_Object exp_MB_frame;
+
 /* This function is called on exiting minibuffer, whether normally or
    not, and it restores the current window, buffer, etc.  */
 
@@ -1004,17 +1043,38 @@ static void
 read_minibuf_unwind (void)
 {
   Lisp_Object old_deactivate_mark;
-  Lisp_Object window;
+  Lisp_Object calling_frame;
+  Lisp_Object calling_window;
   Lisp_Object future_mini_window;
+  Lisp_Object saved_selected_frame = selected_frame;
+  Lisp_Object window, frames;
+  struct window *w;
+  struct frame *f;
 
-  /* If this was a recursive minibuffer,
-     tie the minibuffer window back to the outer level minibuffer buffer.  */
-  minibuf_level--;
+  /* Locate the expired minibuffer.  */
+  FOR_EACH_FRAME (frames, exp_MB_frame)
+    {
+      f = XFRAME (exp_MB_frame);
+      window = f->minibuffer_window;
+      w = XWINDOW (window);
+      if (EQ (w->frame, exp_MB_frame)
+         && EQ (w->contents, nth_minibuffer (minibuf_level)))
+       goto found;
+    }
+  return; /* expired minibuffer not found.  Maybe we should output an
+            error, here. */
+
+ found:
+  if (!EQ (exp_MB_frame, saved_selected_frame))
+    do_switch_frame (exp_MB_frame, 0, 0, Qt); /* This also sets
+                                            minibuff_window */
 
-  window = minibuf_window;
   /* To keep things predictable, in case it matters, let's be in the
-     minibuffer when we reset the relevant variables.  */
-  Fset_buffer (XWINDOW (window)->contents);
+     minibuffer when we reset the relevant variables.  Don't depend on
+     `minibuf_window' here.  This could by now be the mini-window of any
+     frame.  */
+  Fset_buffer (nth_minibuffer (minibuf_level));
+  minibuf_level--;
 
   /* Restore prompt, etc, from outer minibuffer level.  */
   Lisp_Object key_vec = Fcar (minibuf_save_list);
@@ -1042,6 +1102,10 @@ read_minibuf_unwind (void)
 #endif
   future_mini_window = Fcar (minibuf_save_list);
   minibuf_save_list = Fcdr (minibuf_save_list);
+  calling_frame = Fcar (minibuf_save_list);
+  minibuf_save_list = Fcdr (minibuf_save_list);
+  calling_window = Fcar (minibuf_save_list);
+  minibuf_save_list = Fcdr (minibuf_save_list);
 
   /* Erase the minibuffer we were using at this level.  */
   {
@@ -1059,7 +1123,7 @@ read_minibuf_unwind (void)
      mini-window back to its normal size.  */
   if (minibuf_level == 0
       || !EQ (selected_frame, WINDOW_FRAME (XWINDOW (future_mini_window))))
-    resize_mini_window (XWINDOW (window), 0);
+    resize_mini_window (XWINDOW (minibuf_window), 0);
 
   /* Deal with frames that should be removed when exiting the
      minibuffer.  */
@@ -1090,7 +1154,66 @@ read_minibuf_unwind (void)
      to make sure we don't leave around bindings and stuff which only
      made sense during the read_minibuf invocation.  */
   call0 (intern ("minibuffer-inactive-mode"));
+
+  /* We've exited the recursive edit, so switch the current windows
+     away from the expired minibuffer window, both in the current
+     minibuffer's frame and the original calling frame.  */
+  choose_minibuf_frame ();
+  if (NILP (XWINDOW (minibuf_window)->prev_buffers))
+    {
+      if (!EQ (WINDOW_FRAME (XWINDOW (minibuf_window)), calling_frame))
+       {
+         Lisp_Object prev = Fprevious_window (minibuf_window, Qnil, Qnil);
+         /* PREV can be on a different frame when we have a minibuffer only
+            frame, the other frame's minibuffer window is MINIBUF_WINDOW,
+            and its "focus window" is also MINIBUF_WINDOW.  */
+         if (!EQ (prev, minibuf_window)
+             && EQ (WINDOW_FRAME (XWINDOW (prev)),
+                    WINDOW_FRAME (XWINDOW (minibuf_window))))
+           Fset_frame_selected_window (selected_frame, prev, Qnil);
+       }
+      else
+       Fset_frame_selected_window (calling_frame, calling_window, Qnil);
+    }
+
+  /* Restore the selected frame. */
+  if (!EQ (exp_MB_frame, saved_selected_frame))
+    do_switch_frame (saved_selected_frame, 0, 0, Qt);
+}
+
+/* Replace the expired minibuffer in frame exp_MB_frame with the next less
+   nested minibuffer in that frame, if any.  Otherwise, replace it
+   with the null minibuffer.  MINIBUF_WINDOW is not changed.  */
+static void
+minibuffer_unwind (void)
+{
+  struct frame *f;
+  struct window *w;
+  Lisp_Object window;
+  Lisp_Object entry;
+
+  f = XFRAME (exp_MB_frame);
+  window = f->minibuffer_window;
+  w = XWINDOW (window);
+  if (FRAME_LIVE_P (f))
+    {
+      /* minibuf_window = sf->minibuffer_window; */
+      if (!NILP (w->prev_buffers))
+       {
+         entry = Fcar (w->prev_buffers);
+         w->prev_buffers = Fcdr (w->prev_buffers);
+         set_window_buffer (window, Fcar (entry), 0, 0);
+         Fset_window_start (window, Fcar (Fcdr (entry)), Qnil);
+         Fset_window_point (window, Fcar (Fcdr (Fcdr (entry))));
+         /* set-window-configuration may/will have unselected the
+            mini-window as the selected window.  Restore it. */
+         Fset_frame_selected_window (exp_MB_frame, window, Qnil);
+       }
+      else
+       set_window_buffer (window, nth_minibuffer (0), 0, 0);
+    }
 }
+
 
 
 void
@@ -1367,8 +1490,8 @@ function, instead of the usual behavior.  */)
                                              STRING_MULTIBYTE (prompt));
            }
 
-         AUTO_STRING (format, "%s (default %s): ");
-         prompt = CALLN (Fformat, format, prompt,
+         prompt = CALLN (Ffuncall, intern("format-prompt"),
+                         prompt,
                          CONSP (def) ? XCAR (def) : def);
        }
 
@@ -2137,6 +2260,7 @@ void
 init_minibuf_once (void)
 {
   staticpro (&Vminibuffer_list);
+  staticpro (&Vcommand_loop_level_list);
   pdumper_do_now_and_after_load (init_minibuf_once_for_pdumper);
 }
 
@@ -2150,6 +2274,7 @@ init_minibuf_once_for_pdumper (void)
      restore from a dump file.  pdumper doesn't try to preserve
      frames, windows, and so on, so reset everything related here.  */
   Vminibuffer_list = Qnil;
+  Vcommand_loop_level_list = Qnil;
   minibuf_level = 0;
   minibuf_prompt = Qnil;
   minibuf_save_list = Qnil;
@@ -2161,6 +2286,9 @@ syms_of_minibuf (void)
 {
   staticpro (&minibuf_prompt);
   staticpro (&minibuf_save_list);
+  staticpro (&MB_frame);
+  MB_frame = Qnil;
+  staticpro (&exp_MB_frame);
 
   DEFSYM (Qminibuffer_follows_selected_frame,
           "minibuffer-follows-selected-frame");
@@ -2380,6 +2508,7 @@ instead. */);
 
   defsubr (&Sminibufferp);
   defsubr (&Sinnermost_minibuffer_p);
+  defsubr (&Sminibuffer_innermost_command_loop_p);
   defsubr (&Sabort_minibuffers);
   defsubr (&Sminibuffer_prompt_end);
   defsubr (&Sminibuffer_contents);
diff --git a/src/nsterm.h b/src/nsterm.h
index eae1d07..017c239 100644
--- a/src/nsterm.h
+++ b/src/nsterm.h
@@ -1252,6 +1252,7 @@ struct input_event;
 extern void ns_init_events (struct input_event *);
 extern void ns_finish_events (void);
 
+extern double ns_frame_scale_factor (struct frame *);
 
 #ifdef NS_IMPL_GNUSTEP
 extern char gnustep_base_version[];  /* version tracking */
diff --git a/src/nsterm.m b/src/nsterm.m
index 1b23286..bf175bb 100644
--- a/src/nsterm.m
+++ b/src/nsterm.m
@@ -857,6 +857,17 @@ ns_row_rect (struct window *w, struct glyph_row *row,
 }
 
 
+double
+ns_frame_scale_factor (struct frame *f)
+{
+#if defined (NS_IMPL_COCOA) && MAC_OS_X_VERSION_MAX_ALLOWED > 1060
+  return [[FRAME_NS_VIEW (f) window] backingScaleFactor];
+#else
+  return [[FRAME_NS_VIEW (f) window] userSpaceScaleFactor];
+#endif
+}
+
+
 /* ==========================================================================
 
     Focus (clipping) and screen update
@@ -7339,6 +7350,8 @@ not_in_argv (NSString *arg)
 
       [surface release];
       surface = nil;
+
+      [self setNeedsDisplay:YES];
     }
 #endif
 
@@ -7510,6 +7523,16 @@ not_in_argv (NSString *arg)
   [self initWithFrame: r];
   [self setAutoresizingMask: NSViewWidthSizable | NSViewHeightSizable];
 
+#ifdef NS_DRAW_TO_BUFFER
+  /* These settings mean AppKit will retain the contents of the frame
+     on resize.  Unfortunately it also means the frame will not be
+     automatically marked for display, but we can do that ourselves in
+     viewDidResize.  */
+  [self setLayerContentsRedrawPolicy:
+          NSViewLayerContentsRedrawOnSetNeedsDisplay];
+  [self setLayerContentsPlacement:NSViewLayerContentsPlacementTopLeft];
+#endif
+
   FRAME_NS_VIEW (f) = self;
   emacsframe = f;
 #ifdef NS_IMPL_COCOA
@@ -8354,6 +8377,11 @@ not_in_argv (NSString *arg)
       surface = [[EmacsSurface alloc] initWithSize:s
                                         ColorSpace:[[[self window] colorSpace]
                                                      CGColorSpace]];
+
+      /* Since we're using NSViewLayerContentsRedrawOnSetNeedsDisplay
+         the layer's scale factor is not set automatically, so do it
+         now.  */
+      [[self layer] setContentsScale:[[self window] backingScaleFactor]];
     }
 
   CGContextRef context = [surface getContext];
@@ -8383,13 +8411,16 @@ not_in_argv (NSString *arg)
 {
   NSTRACE ("EmacsView windowDidChangeBackingProperties:]");
 
-  NSRect frame = [self frame];
+  if ([self wantsUpdateLayer])
+    {
+      NSRect frame = [self frame];
 
-  [surface release];
-  surface = nil;
+      [surface release];
+      surface = nil;
 
-  ns_clear_frame (emacsframe);
-  expose_frame (emacsframe, 0, 0, NSWidth (frame), NSHeight (frame));
+      ns_clear_frame (emacsframe);
+      expose_frame (emacsframe, 0, 0, NSWidth (frame), NSHeight (frame));
+    }
 }
 #endif /* NS_DRAW_TO_BUFFER */
 
@@ -8453,6 +8484,33 @@ not_in_argv (NSString *arg)
 
 
 #ifdef NS_DRAW_TO_BUFFER
+/* If the frame has been garbaged but the toolkit wants to draw, for
+   example when resizing the frame, we end up with a blank screen.
+   Sometimes this results in an unpleasant flicker, so try to
+   redisplay before drawing.  */
+- (void)viewWillDraw
+{
+  if (FRAME_GARBAGED_P (emacsframe)
+      && !redisplaying_p
+      && [self wantsUpdateLayer])
+    {
+      /* If there is IO going on when redisplay is run here Emacs
+         crashes.  I think it's because this code will always be run
+         within the run loop and for whatever reason processing input
+         is dangerous.  This technique was stolen wholesale from
+         nsmenu.m and seems to work.  */
+      bool owfi = waiting_for_input;
+      waiting_for_input = 0;
+      block_input ();
+
+      redisplay ();
+
+      unblock_input ();
+      waiting_for_input = owfi;
+    }
+}
+
+
 - (BOOL)wantsUpdateLayer
 {
 #if MAC_OS_X_VERSION_MIN_REQUIRED < 101400
@@ -8469,6 +8527,13 @@ not_in_argv (NSString *arg)
 {
   NSTRACE ("[EmacsView updateLayer]");
 
+  /* We run redisplay on frames that are garbaged, but marked for
+     display, before updateLayer is called so if the frame is still
+     garbaged that means the last redisplay must have refused to
+     update the frame.  */
+  if (FRAME_GARBAGED_P (emacsframe))
+    return;
+
   /* This can fail to update the screen if the same surface is
      provided twice in a row, even if its contents have changed.
      There's a private method, -[CALayer setContentsChanged], that we
@@ -9704,7 +9769,7 @@ nswindow_orderedIndex_sort (id w1, id w2, void *c)
   for (id object in cache)
     CFRelease ((IOSurfaceRef)object);
 
-  [cache removeAllObjects];
+  [cache release];
 
   [super dealloc];
 }
diff --git a/src/pdumper.c b/src/pdumper.c
index c1388eb..fdd9b3b 100644
--- a/src/pdumper.c
+++ b/src/pdumper.c
@@ -162,11 +162,7 @@ ptrdiff_t_to_dump_off (ptrdiff_t value)
 static int
 dump_get_page_size (void)
 {
-#if defined (WINDOWSNT) || defined (CYGWIN)
-  return 64 * 1024;  /* Worst-case allocation granularity.  */
-#else
-  return getpagesize ();
-#endif
+  return 64 * 1024;
 }
 
 #define dump_offsetof(type, member)                             \
@@ -2692,7 +2688,7 @@ dump_hash_table (struct dump_context *ctx,
 static dump_off
 dump_buffer (struct dump_context *ctx, const struct buffer *in_buffer)
 {
-#if CHECK_STRUCTS && !defined HASH_buffer_99D642C1CB
+#if CHECK_STRUCTS && !defined HASH_buffer_F8FE65D42F
 # error "buffer changed. See CHECK_STRUCTS comment in config.h."
 #endif
   struct buffer munged_buffer = *in_buffer;
@@ -2703,6 +2699,7 @@ dump_buffer (struct dump_context *ctx, const struct 
buffer *in_buffer)
     buffer->window_count = 0;
   else
     eassert (buffer->window_count == -1);
+  buffer->local_minor_modes_ = Qnil;
   buffer->last_selected_window_ = Qnil;
   buffer->display_count_ = make_fixnum (0);
   buffer->clip_changed = 0;
diff --git a/src/process.c b/src/process.c
index 3beb9cf..b98bc29 100644
--- a/src/process.c
+++ b/src/process.c
@@ -8255,7 +8255,7 @@ init_process_emacs (int sockfd)
         private SIGCHLD handler, allowing catch_child_signal to copy
         it into lib_child_handler.
 
-         Unfortunatly in glib commit 2e471acf, the behavior changed to
+         Unfortunately in glib commit 2e471acf, the behavior changed to
          always install a signal handler when g_child_watch_source_new
          is called and not just the first time it's called.  Glib also
          now resets signal handlers to SIG_DFL when it no longer has a
diff --git a/src/sysdep.c b/src/sysdep.c
index 941b4e2..d940acc 100644
--- a/src/sysdep.c
+++ b/src/sysdep.c
@@ -1785,7 +1785,15 @@ handle_arith_signal (int sig)
 
 /* Alternate stack used by SIGSEGV handler below.  */
 
-static unsigned char sigsegv_stack[SIGSTKSZ];
+/* Storage for the alternate signal stack.
+   64 KiB is not too large for Emacs, and is large enough
+   for all known platforms.  Smaller sizes may run into trouble.
+   For example, libsigsegv 2.6 through 2.8 have a bug where some
+   architectures use more than the Linux default of an 8 KiB alternate
+   stack when deciding if a fault was caused by stack overflow.  */
+static max_align_t sigsegv_stack[(64 * 1024
+                                 + sizeof (max_align_t) - 1)
+                                / sizeof (max_align_t)];
 
 
 /* Return true if SIGINFO indicates a stack overflow.  */
@@ -2662,6 +2670,13 @@ void
 errputc (int c)
 {
   fputc_unlocked (c, errstream ());
+
+#ifdef WINDOWSNT
+  /* Flush stderr after outputting a newline since stderr is fully
+     buffered when redirected to a pipe, contrary to POSIX.  */
+  if (c == '\n')
+    fflush_unlocked (stderr);
+#endif
 }
 
 void
diff --git a/src/verbose.mk.in b/src/verbose.mk.in
new file mode 100644
index 0000000..e55fd63
--- /dev/null
+++ b/src/verbose.mk.in
@@ -0,0 +1,42 @@
+### verbose.mk --- Makefile fragment for GNU Emacs
+
+## Copyright (C) 2021 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/>.
+
+# 'make' verbosity.
+V = @AM_DEFAULT_VERBOSITY@
+ifeq (${V},1)
+AM_V_AR =
+AM_V_at =
+AM_V_CC =
+AM_V_CCLD =
+AM_V_ELC =
+AM_V_GEN =
+AM_V_GLOBALS =
+AM_V_NO_PD =
+AM_V_RC =
+else
+AM_V_AR = @echo "  AR      " $@;
+AM_V_at = @
+AM_V_CC = @echo "  CC      " $@;
+AM_V_CCLD = @echo "  CCLD    " $@;
+AM_V_ELC = @echo "  ELC     " $@;
+AM_V_GEN = @echo "  GEN     " $@;
+AM_V_GLOBALS = @echo "  GEN     " globals.h;
+AM_V_NO_PD = --no-print-directory
+AM_V_RC = @echo "  RC      " $@;
+endif
diff --git a/src/w32.c b/src/w32.c
index a3c247b..aade802 100644
--- a/src/w32.c
+++ b/src/w32.c
@@ -346,6 +346,7 @@ static BOOL g_b_init_get_adapters_addresses;
 static BOOL g_b_init_reg_open_key_ex_w;
 static BOOL g_b_init_reg_query_value_ex_w;
 static BOOL g_b_init_expand_environment_strings_w;
+static BOOL g_b_init_get_user_default_ui_language;
 
 BOOL g_b_init_compare_string_w;
 BOOL g_b_init_debug_break_process;
@@ -533,6 +534,7 @@ DWORD multiByteToWideCharFlags;
 typedef LONG (WINAPI *RegOpenKeyExW_Proc) (HKEY,LPCWSTR,DWORD,REGSAM,PHKEY);
 typedef LONG (WINAPI *RegQueryValueExW_Proc) 
(HKEY,LPCWSTR,LPDWORD,LPDWORD,LPBYTE,LPDWORD);
 typedef DWORD (WINAPI *ExpandEnvironmentStringsW_Proc) (LPCWSTR,LPWSTR,DWORD);
+typedef LANGID (WINAPI *GetUserDefaultUILanguage_Proc) (void);
 
   /* ** A utility function ** */
 static BOOL
@@ -1489,6 +1491,28 @@ expand_environment_strings_w (LPCWSTR lpSrc, LPWSTR 
lpDst, DWORD nSize)
   return s_pfn_Expand_Environment_Strings_w (lpSrc, lpDst, nSize);
 }
 
+static LANGID WINAPI
+get_user_default_ui_language (void)
+{
+  static GetUserDefaultUILanguage_Proc s_pfn_GetUserDefaultUILanguage = NULL;
+  HMODULE hm_kernel32 = NULL;
+
+  if (is_windows_9x () == TRUE)
+    return 0;
+
+  if (g_b_init_get_user_default_ui_language == 0)
+    {
+      g_b_init_get_user_default_ui_language = 1;
+      hm_kernel32 = LoadLibrary ("Kernel32.dll");
+      if (hm_kernel32)
+       s_pfn_GetUserDefaultUILanguage = (GetUserDefaultUILanguage_Proc)
+         get_proc_addr (hm_kernel32, "GetUserDefaultUILanguage");
+    }
+  if (s_pfn_GetUserDefaultUILanguage == NULL)
+    return 0;
+  return s_pfn_GetUserDefaultUILanguage ();
+}
+
 
 
 /* Return 1 if P is a valid pointer to an object of size SIZE.  Return
@@ -2947,6 +2971,32 @@ init_environment (char ** argv)
                      LOCALE_SABBREVLANGNAME | LOCALE_USE_CP_ACP,
                      locale_name, sizeof (locale_name)))
     {
+      /* Microsoft are migrating away of locale IDs, replacing them
+        with locale names, such as "en-US", and are therefore
+        deprecating the APIs which use LCID etc.  As part of that
+        deprecation, they don't bother inventing LCID and LANGID
+        codes for new locales and language/culture combinations;
+        instead, those get LCID of 0xC000 and LANGID of 0x2000, for
+        which the LCID/LANGID oriented APIs return "ZZZ" as the
+        "language name".  Such "language name" is useless for our
+        purposes.  So we instead use the default UI language, in the
+        hope of getting something usable.  */
+      if (strcmp (locale_name, "ZZZ") == 0)
+       {
+         LANGID lang_id = get_user_default_ui_language ();
+
+         if (lang_id != 0)
+           {
+             /* Disregard the sorting order differences between cultures.  */
+             LCID def_lcid = MAKELCID (lang_id, SORT_DEFAULT);
+             char locale_name_def[32];
+
+             if (GetLocaleInfo (def_lcid,
+                                LOCALE_SABBREVLANGNAME | LOCALE_USE_CP_ACP,
+                                locale_name_def, sizeof (locale_name_def)))
+               strcpy (locale_name, locale_name_def);
+           }
+       }
       for (i = 0; i < N_ENV_VARS; i++)
         {
           if (strcmp (env_vars[i].name, "LANG") == 0)
@@ -10580,6 +10630,7 @@ globals_of_w32 (void)
   g_b_init_expand_environment_strings_w = 0;
   g_b_init_compare_string_w = 0;
   g_b_init_debug_break_process = 0;
+  g_b_init_get_user_default_ui_language = 0;
   num_of_processors = 0;
   /* The following sets a handler for shutdown notifications for
      console apps. This actually applies to Emacs in both console and
diff --git a/src/w32fns.c b/src/w32fns.c
index 86c3db6..9db367b 100644
--- a/src/w32fns.c
+++ b/src/w32fns.c
@@ -3893,7 +3893,7 @@ deliver_wm_chars (int do_translate, HWND hwnd, UINT msg, 
UINT wParam,
                     Essentially, we have no information about the "role" of
                     modifiers on this key: which contribute into the
                     produced character (so "are consumed"), and which are
-                    "extra" (must attache to bindable events).
+                    "extra" (must attach to bindable events).
 
                     The default above would consume ALL modifiers, so the
                     character is reported "as is".  However, on many layouts
diff --git a/src/window.c b/src/window.c
index eb16e2a..4d5c7e7 100644
--- a/src/window.c
+++ b/src/window.c
@@ -6958,7 +6958,8 @@ the return value is nil.  Otherwise the value is t.  */)
 
          if (BUFFERP (w->contents)
              && !EQ (w->contents, p->buffer)
-             && BUFFER_LIVE_P (XBUFFER (p->buffer)))
+             && BUFFER_LIVE_P (XBUFFER (p->buffer))
+             && (NILP (Fminibufferp (p->buffer, Qnil))))
            /* If a window we restore gets another buffer, record the
               window's old buffer.  */
            call1 (Qrecord_window_buffer, window);
diff --git a/src/window.h b/src/window.h
index 79eb44e..b6f88e8 100644
--- a/src/window.h
+++ b/src/window.h
@@ -1120,10 +1120,6 @@ void set_window_buffer (Lisp_Object window, Lisp_Object 
buffer,
 
 extern Lisp_Object echo_area_window;
 
-/* Depth in recursive edits.  */
-
-extern EMACS_INT command_loop_level;
-
 /* Non-zero if we should redraw the mode lines on the next redisplay.
    Usually set to a unique small integer so we can track the main causes of
    full redisplays in `redisplay--mode-lines-cause'.  */
diff --git a/src/xdisp.c b/src/xdisp.c
index fb8eaf4..a405d51 100644
--- a/src/xdisp.c
+++ b/src/xdisp.c
@@ -9227,10 +9227,10 @@ move_it_in_display_line_to (struct it *it,
                      || prev_method == GET_FROM_STRING)
                  /* Passed TO_CHARPOS from left to right.  */
                  && ((prev_pos < to_charpos
-                      && IT_CHARPOS (*it) > to_charpos)
+                      && IT_CHARPOS (*it) >= to_charpos)
                      /* Passed TO_CHARPOS from right to left.  */
                      || (prev_pos > to_charpos
-                         && IT_CHARPOS (*it) < to_charpos)))))
+                         && IT_CHARPOS (*it) <= to_charpos)))))
        {
          if (it->line_wrap != WORD_WRAP || wrap_it.sp < 0)
            {
@@ -10049,7 +10049,10 @@ move_it_to (struct it *it, ptrdiff_t to_charpos, int 
to_x, int to_y, int to_vpos
          it->continuation_lines_width = 0;
          reseat_at_next_visible_line_start (it, false);
          if ((op & MOVE_TO_POS) != 0
-             && IT_CHARPOS (*it) > to_charpos)
+             && (IT_CHARPOS (*it) > to_charpos
+                 || (IT_CHARPOS (*it) == to_charpos
+                     && to_charpos == ZV
+                     && (ZV_BYTE <= 1 || FETCH_BYTE (ZV_BYTE - 1) != '\n'))))
            {
              reached = 9;
              goto out;
@@ -11854,18 +11857,27 @@ resize_mini_window (struct window *w, bool exact_p)
       max_height = clip_to_bounds (unit, max_height, windows_height);
 
       /* Find out the height of the text in the window.  */
-      if (it.line_wrap == TRUNCATE)
-       height = unit;
-      else
-       {
-         last_height = 0;
-         move_it_to (&it, ZV, -1, -1, -1, MOVE_TO_POS);
-         if (it.max_ascent == 0 && it.max_descent == 0)
-           height = it.current_y + last_height;
-         else
-           height = it.current_y + it.max_ascent + it.max_descent;
-         height -= min (it.extra_line_spacing, it.max_extra_line_spacing);
+      last_height = 0;
+      move_it_to (&it, ZV, -1, -1, -1, MOVE_TO_POS);
+      /* If move_it_to moved to the next visible line after EOB,
+        account for the height of the last full line.  */
+      if (it.max_ascent == 0 && it.max_descent == 0)
+       {
+         height = it.current_y;
+         /* Don't add the last line's height if lines are truncated
+            and the text doesn't end in a newline.
+            FIXME: if the text ends in a newline from a display
+            property or an overlay string, they lose: the mini-window
+            might not show the last empty line.  */
+         if (!(it.line_wrap == TRUNCATE
+               && it.current_x <= it.first_visible_x
+               && ZV_BYTE > 1
+               && FETCH_BYTE (ZV_BYTE - 1) != '\n'))
+           height += last_height;
        }
+      else
+       height = it.current_y + it.max_ascent + it.max_descent;
+      height -= min (it.extra_line_spacing, it.max_extra_line_spacing);
 
       /* Compute a suitable window start.  */
       if (height > max_height)
@@ -12638,9 +12650,8 @@ gui_consider_frame_title (Lisp_Object frame)
         mode_line_noprop_buf; then display the title.  */
       record_unwind_protect (unwind_format_mode_line,
                             format_mode_line_unwind_data
-                              (f, current_buffer, selected_window, false));
+                            (NULL, current_buffer, Qnil, false));
 
-      Fselect_window (f->selected_window, Qt);
       set_buffer_internal_1
        (XBUFFER (XWINDOW (f->selected_window)->contents));
       fmt = FRAME_ICONIFIED_P (f) ? Vicon_title_format : Vframe_title_format;
@@ -24106,7 +24117,8 @@ display_line (struct it *it, int cursor_vpos)
             the logical order.  */
          if (IT_BYTEPOS (*it) > BEG_BYTE)
            row->ends_at_zv_p =
-             IT_BYTEPOS (*it) >= ZV_BYTE && FETCH_BYTE (ZV_BYTE - 1) != '\n';
+             IT_BYTEPOS (*it) >= ZV_BYTE
+             && (ZV_BYTE <= 1 || FETCH_BYTE (ZV_BYTE - 1) != '\n');
          else
            row->ends_at_zv_p = false;
          break;
diff --git a/src/xfaces.c b/src/xfaces.c
index 1208713..ab4440f 100644
--- a/src/xfaces.c
+++ b/src/xfaces.c
@@ -289,7 +289,7 @@ along with GNU Emacs.  If not, see 
<https://www.gnu.org/licenses/>.  */
 /* Size of hash table of realized faces in face caches (should be a
    prime number).  */
 
-#define FACE_CACHE_BUCKETS_SIZE 1001
+#define FACE_CACHE_BUCKETS_SIZE 1009
 
 char unspecified_fg[] = "unspecified-fg", unspecified_bg[] = "unspecified-bg";
 
@@ -6034,10 +6034,11 @@ realize_gui_face (struct face_cache *cache, Lisp_Object 
attrs[LFACE_VECTOR_SIZE]
                face->box = FACE_RAISED_BOX;
              else if (EQ (value, Qpressed_button))
                face->box = FACE_SUNKEN_BOX;
-             else if (EQ (value, Qflat_button)) {
-               face->box = FACE_SIMPLE_BOX;
-               face->box_color = face->background;
-             }
+             else if (EQ (value, Qflat_button))
+               {
+                 face->box = FACE_SIMPLE_BOX;
+                 face->box_color = face->background;
+               }
            }
        }
     }
diff --git a/src/xfns.c b/src/xfns.c
index 481ee0e..0507dc8 100644
--- a/src/xfns.c
+++ b/src/xfns.c
@@ -2783,7 +2783,7 @@ xic_set_preeditarea (struct window *w, int x, int y)
   XVaNestedList attr;
   XPoint spot;
 
-  spot.x = WINDOW_TO_FRAME_PIXEL_X (w, x) + WINDOW_LEFT_FRINGE_WIDTH (w);
+  spot.x = WINDOW_TO_FRAME_PIXEL_X (w, x) + WINDOW_LEFT_FRINGE_WIDTH (w) + 
WINDOW_LEFT_MARGIN_WIDTH(w);
   spot.y = WINDOW_TO_FRAME_PIXEL_Y (w, y) + FONT_BASE (FRAME_FONT (f));
   attr = XVaCreateNestedList (0, XNSpotLocation, &spot, NULL);
   XSetICValues (FRAME_XIC (f), XNPreeditAttributes, attr, NULL);
@@ -4599,7 +4599,7 @@ On MS Windows, this just returns nil.  */)
     return Qnil;
 }
 
-#if !defined USE_GTK || !defined HAVE_GTK3
+#if !(defined USE_GTK && defined HAVE_GTK3)
 
 /* Store the geometry of the workarea on display DPYINFO into *RECT.
    Return false if and only if the workarea information cannot be
@@ -4662,6 +4662,9 @@ x_get_net_workarea (struct x_display_info *dpyinfo, 
XRectangle *rect)
 
   return result;
 }
+#endif /* !(USE_GTK && HAVE_GTK3) */
+
+#ifndef USE_GTK
 
 /* Return monitor number where F is "most" or closest to.  */
 static int
@@ -4877,6 +4880,8 @@ x_get_monitor_attributes_xrandr (struct x_display_info 
*dpyinfo)
     pxid = XRRGetOutputPrimary (dpy, dpyinfo->root_window);
 #endif
 
+#undef RANDR13_LIBRARY
+
   for (i = 0; i < n_monitors; ++i)
     {
       XRROutputInfo *info = XRRGetOutputInfo (dpy, resources,
diff --git a/test/Makefile.in b/test/Makefile.in
index f907602..ba35428 100644
--- a/test/Makefile.in
+++ b/test/Makefile.in
@@ -32,6 +32,7 @@ SHELL = @SHELL@
 
 srcdir = @srcdir@
 abs_top_srcdir=@abs_top_srcdir@
+top_builddir = @top_builddir@
 VPATH = $(srcdir)
 
 FIND_DELETE = @FIND_DELETE@
@@ -46,30 +47,16 @@ SO = @MODULES_SUFFIX@
 
 SEPCHAR = @SEPCHAR@
 
+-include ${top_builddir}/src/verbose.mk
 
-# 'make' verbosity.
-AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
-
-AM_V_CCLD = $(am__v_CCLD_@AM_V@)
-am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@)
-am__v_CCLD_0 = @echo "  CCLD    " $@;
-am__v_CCLD_1 =
-
-AM_V_ELC = $(am__v_ELC_@AM_V@)
-am__v_ELC_ = $(am__v_ELC_@AM_DEFAULT_V@)
-am__v_ELC_0 = @echo "  ELC     " $@;
-am__v_ELC_1 =
-
-AM_V_GEN = $(am__v_GEN_@AM_V@)
-am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
-am__v_GEN_0 = @echo "  GEN     " $@;
-am__v_GEN_1 =
-
-AM_V_at = $(am__v_at_@AM_V@)
-am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
-am__v_at_0 = @
-am__v_at_1 =
-
+# Load any GNU ELPA dependencies that are present, for optional tests.
+GNU_ELPA_DIRECTORY ?= $(srcdir)/../../elpa
+# Keep elpa_dependencies dependency-ordered.
+elpa_dependencies = \
+       url-http-ntlm/url-http-ntlm.el \
+       web-server/web-server.el
+elpa_els = $(addprefix $(GNU_ELPA_DIRECTORY)/packages/,$(elpa_dependencies))
+elpa_opts = $(foreach el,$(elpa_els),$(and $(wildcard $(el)),-L $(dir $(el)) 
-l $(el)))
 
 # We never change directory before running Emacs, so a relative file
 # name is fine, and makes life easier.  If we need to change
@@ -81,7 +68,7 @@ EMACS_EXTRAOPT=
 # Command line flags for Emacs.
 # Apparently MSYS bash would convert "-L :" to "-L ;" anyway,
 # but we might as well be explicit.
-EMACSOPT = --no-init-file --no-site-file --no-site-lisp -L 
"$(SEPCHAR)$(srcdir)" $(EMACS_EXTRAOPT)
+EMACSOPT = --no-init-file --no-site-file --no-site-lisp -L 
"$(SEPCHAR)$(srcdir)" $(elpa_opts) $(EMACS_EXTRAOPT)
 
 # Prevent any settings in the user environment causing problems.
 unexport EMACSDATA EMACSDOC EMACSPATH GREP_OPTIONS
@@ -105,7 +92,7 @@ export TEST_LOAD_EL ?= \
     $(if $(findstring $(MAKECMDGOALS), all check check-maybe),no,yes)
 
 # Additional settings for ert.
-ert_opts =
+ert_opts += $(elpa_opts)
 
 # Maximum length of lines in ert backtraces; nil for no limit.
 # (if empty, use the default ert-batch-backtrace-right-margin).
@@ -248,7 +235,7 @@ endef
 $(foreach test,${TESTS},$(eval $(call test_template,${test})))
 
 ## Get the tests for only a specific directory.
-SUBDIRS = $(sort $(shell find lib-src lisp src -type d ! -path "*resources*" 
-print))
+SUBDIRS = $(sort $(shell find lib-src lisp misc src -type d ! -path 
"*resources*" -print))
 
 define subdir_template
   .PHONY: check-$(subst /,-,$(1))
diff --git a/test/README b/test/README
index 5f3c10a..a348074 100644
--- a/test/README
+++ b/test/README
@@ -22,7 +22,10 @@ following tags are recognized:
 * :unstable
   The test is under development.  It shall run on demand only.
 
-The Makefile in this directory supports the following targets:
+The Makefile sets the environment variable $EMACS_TEST_DIRECTORY,
+which points to this directory.  This environment variable does not
+exist when the tests are run outside make.  The Makefile supports the
+following targets:
 
 * make check
   Run all tests as defined in the directory.  Expensive and unstable
@@ -106,7 +109,13 @@ tramp-tests.el).  Per default, a mock-up connection method 
is used
 to test a real remote connection, set $REMOTE_TEMPORARY_FILE_DIRECTORY
 to a suitable value in order to overwrite the default value:
 
-  env REMOTE_TEMPORARY_FILE_DIRECTORY=/ssh:host:/tmp make ...
+    env REMOTE_TEMPORARY_FILE_DIRECTORY=/ssh:host:/tmp make ...
+
+Some optional tests require packages from GNU ELPA.  By default
+../../elpa will be checked for these packages.  If GNU ELPA is checked
+out somewhere else, use
+
+    make GNU_ELPA_DIRECTORY=/path/to/elpa ...
 
 
 There are also continuous integration tests on
diff --git a/test/file-organization.org b/test/file-organization.org
index 7cf5b88..d1f92da 100644
--- a/test/file-organization.org
+++ b/test/file-organization.org
@@ -43,6 +43,10 @@ Similarly, tests of features implemented in C should reside 
in
 ~-tests.el~ added to the base-name of the tested source file.  Thus,
 tests for ~src/fileio.c~ should be in ~test/src/fileio-tests.el~.
 
+Some tests do not belong to any one particular file.  Such tests
+should be put in the ~misc~ directory and be given a descriptive name
+that does /not/ end with ~-tests.el~.
+
 There are also some test materials that cannot be run automatically
 (i.e. via ert).  These should be placed in ~/test/manual~; they are
 not run by the "make check" command and its derivatives.
diff --git a/test/infra/Dockerfile.emba b/test/infra/Dockerfile.emba
index 421264d..30a5897 100644
--- a/test/infra/Dockerfile.emba
+++ b/test/infra/Dockerfile.emba
@@ -28,7 +28,7 @@ FROM debian:stretch as emacs-base
 
 RUN apt-get update && \
     apt-get install -y --no-install-recommends -o=Dpkg::Use-Pty=0 \
-      libc-dev gcc g++ make autoconf automake libncurses-dev gnutls-dev git \
+      libc-dev gcc g++ make autoconf automake libncurses-dev gnutls-dev git 
texinfo \
     && rm -rf /var/lib/apt/lists/*
 
 FROM emacs-base as emacs-inotify
@@ -40,21 +40,22 @@ RUN apt-get update && \
 COPY . /checkout
 WORKDIR /checkout
 RUN ./autogen.sh autoconf
-RUN ./configure --without-makeinfo
+RUN ./configure
 RUN make -j4 bootstrap
 RUN make -j4
 
 FROM emacs-base as emacs-filenotify-gio
 
 RUN apt-get update && \
-    apt-get install -y --no-install-recommends -o=Dpkg::Use-Pty=0 
libglib2.0-dev libglib2.0-bin libglib2.0-0 \
+    apt-get install -y --no-install-recommends -o=Dpkg::Use-Pty=0 \
+      libglib2.0-dev libglib2.0-bin libglib2.0-0 \
     && rm -rf /var/lib/apt/lists/*
 
 COPY . /checkout
 WORKDIR /checkout
 RUN ./autogen.sh autoconf
-RUN ./configure --without-makeinfo --with-file-notification=gfile
-RUN make bootstrap
+RUN ./configure --with-file-notification=gfile
+RUN make -j4 bootstrap
 RUN make -j4
 
 FROM emacs-base as emacs-gnustep
@@ -66,6 +67,6 @@ RUN apt-get update && \
 COPY . /checkout
 WORKDIR /checkout
 RUN ./autogen.sh autoconf
-RUN ./configure --without-makeinfo --with-ns
-RUN make bootstrap
+RUN ./configure --with-ns
+RUN make -j4 bootstrap
 RUN make -j4
diff --git a/test/infra/gitlab-ci.yml b/test/infra/gitlab-ci.yml
index 5a0ab54..6355513 100644
--- a/test/infra/gitlab-ci.yml
+++ b/test/infra/gitlab-ci.yml
@@ -61,6 +61,8 @@ default:
     - docker login -u ${CI_REGISTRY_USER} -p ${CI_REGISTRY_PASSWORD} 
${CI_REGISTRY}
 
 .job-template:
+  variables:
+    test_name: ${CI_JOB_NAME}-${CI_COMMIT_SHORT_SHA}
   rules:
     - changes:
         - "**/Makefile.in"
@@ -95,14 +97,18 @@ default:
   artifacts:
     expire_in: 24 hrs
     paths: []
-      # - "test/**/*.log"
-      # - "**/*.log"
   # using the variables for each job
   script:
     - docker pull ${CI_REGISTRY_IMAGE}:${target}-${BUILD_TAG}
     # TODO: with make -j4 several of the tests were failing, for example 
shadowfile-tests, but passed without it
     - 'export PWD=$(pwd)'
-    - 'docker run -i --rm -e EMACS_EMBA_CI=${EMACS_EMBA_CI} --volumes-from 
$(docker ps -q -f "label=com.gitlab.gitlab-runner.job.id=${CI_JOB_ID}"):ro 
${CI_REGISTRY_IMAGE}:${target}-${BUILD_TAG} /bin/bash -c "git fetch ${PWD} HEAD 
&& echo checking out these updated files && git diff --name-only FETCH_HEAD && 
( git diff --name-only FETCH_HEAD | xargs git checkout -f FETCH_HEAD ) && make 
-j4 && make ${make_params}"'
+    - 'docker run -i -e EMACS_EMBA_CI=${EMACS_EMBA_CI} --volumes-from $(docker 
ps -q -f "label=com.gitlab.gitlab-runner.job.id=${CI_JOB_ID}"):ro --name 
${test_name} ${CI_REGISTRY_IMAGE}:${target}-${BUILD_TAG} /bin/bash -c "git 
fetch ${PWD} HEAD && echo checking out these updated files && git diff 
--name-only FETCH_HEAD && ( git diff --name-only FETCH_HEAD | xargs git 
checkout -f FETCH_HEAD ) && make -j4 && make ${make_params}"'
+  after_script:
+    # - docker ps -a
+    # - printenv
+    # - test -n "$(docker ps -aq -f name=${test_name})" && ( docker export 
${test_name} | tar -tvf - )
+    - test -n "$(docker ps -aq -f name=${test_name})" && docker cp 
${test_name}:checkout/test ${test_name}
+    - test -n "$(docker ps -aq -f name=${test_name})" && docker rm ${test_name}
 
 .build-template:
   rules:
@@ -133,6 +139,19 @@ default:
     - docker build --pull --target ${target} -t 
${CI_REGISTRY_IMAGE}:${target}-${BUILD_TAG} -f test/infra/Dockerfile.emba .
     - docker push ${CI_REGISTRY_IMAGE}:${target}-${BUILD_TAG}
 
+.test-template:
+  # Do not run fast and normal test jobs when scheduled
+  rules:
+    - if: '$CI_JOB_STAGE =~ "fast|normal" && $CI_PIPELINE_SOURCE == "schedule"'
+      when: never
+    - when: always
+  artifacts:
+    name: ${test_name}
+    public: true
+    expire_in: 1 week
+    paths:
+      - "${test_name}/**/*.log"
+
 .gnustep-template:
   rules:
     - if: '$CI_PIPELINE_SOURCE == "web"'
@@ -185,7 +204,7 @@ build-image-inotify:
 
 test-fast-inotify:
   stage: fast
-  extends: [.job-template]
+  extends: [.job-template, .test-template]
   variables:
     target: emacs-inotify
     make_params: "-C test check"
@@ -204,14 +223,14 @@ build-image-gnustep:
 
 test-lisp-inotify:
   stage: normal
-  extends: [.job-template]
+  extends: [.job-template, .test-template]
   variables:
     target: emacs-inotify
     make_params: "-C test check-lisp"
 
 test-lisp-net-inotify:
   stage: normal
-  extends: [.job-template]
+  extends: [.job-template, .test-template]
   variables:
     target: emacs-inotify
     make_params: "-C test check-lisp-net"
@@ -219,10 +238,10 @@ test-lisp-net-inotify:
 test-filenotify-gio:
   # This tests file monitor libraries gfilemonitor and gio.
   stage: platforms
-  extends: [.job-template, .filenotify-gio-template]
+  extends: [.job-template, .test-template, .filenotify-gio-template]
   variables:
     target: emacs-filenotify-gio
-    make_params: "-k -C test autorevert-tests filenotify-tests"
+    make_params: "-k -C test autorevert-tests.log filenotify-tests.log"
 
 test-gnustep:
   # This tests the GNUstep build process
@@ -235,7 +254,7 @@ test-gnustep:
 test-all-inotify:
   # This tests also file monitor libraries inotify and inotifywatch.
   stage: slow
-  extends: [.job-template]
+  extends: [.job-template, .test-template]
   rules:
     # note there's no "changes" section, so this always runs on a schedule
     - if: '$CI_PIPELINE_SOURCE == "web"'
diff --git a/test/lisp/autorevert-tests.el b/test/lisp/autorevert-tests.el
index 45cf635..5f27c2e 100644
--- a/test/lisp/autorevert-tests.el
+++ b/test/lisp/autorevert-tests.el
@@ -133,7 +133,9 @@ This expects `auto-revert--messages' to be bound by
                        (format-message
                         "Reverting buffer `%s'\\." (buffer-name buffer))
                        (or auto-revert--messages ""))))
-      (if (with-current-buffer buffer auto-revert-use-notify)
+      (if (and (or file-notify--library
+                   (file-remote-p temporary-file-directory))
+               (with-current-buffer buffer auto-revert-use-notify))
           (read-event nil nil 0.05)
         (sleep-for 0.05)))))
 
diff --git a/test/lisp/calc/calc-tests.el b/test/lisp/calc/calc-tests.el
index bdcf78e..c5aa5a3 100644
--- a/test/lisp/calc/calc-tests.el
+++ b/test/lisp/calc/calc-tests.el
@@ -707,6 +707,82 @@ An existing calc stack is reused, otherwise a new one is 
created."
                             (var c var-c))))))
     (calc-set-language nil)))
 
+(defvar var-g)
+
+;; Test `let'.
+(defmath test1 (x)
+  (let ((x (+ x 1))
+        (y (+ x 3)))
+    (let ((z (+ y 6)))
+      (* x y z g))))
+
+;; Test `let*'.
+(defmath test2 (x)
+  (let* ((y (+ x 1))
+         (z (+ y 3)))
+    (let* ((u (+ z 6)))
+      (* x y z u g))))
+
+;; Test `for'.
+(defmath test3 (x)
+  (let ((s 0))
+    (for ((ii 1 x)
+          (jj 1 ii))
+      (setq s (+ s (* ii jj))))
+    s))
+
+;; Test `for' with non-unit stride.
+(defmath test4 (x)
+  (let ((l nil))
+    (for ((ii 1 x 1)
+          (jj 1 10 ii))
+      (setq l ('cons jj l)))       ; Use Lisp `cons', not `calcFunc-cons'.
+    (reverse l)))
+
+;; Test `foreach'.
+(defmath test5 (x)
+  (let ((s 0))
+    (foreach ((a x)
+              (b a))
+      (setq s (+ s b)))
+    s))
+
+;; Test `break'.
+(defmath test6 (x)
+  (let ((a (for ((ii 1 10))
+             (when (= ii x)
+               (break (* ii 2)))))
+        (b (foreach ((e '(9 3 6)))
+             (when (= e x)
+               (break (- e 1))))))
+    (* a b)))
+
+;; Test `return' from `for'.
+(defmath test7 (x)
+  (for ((ii 1 10))
+    (when (= ii x)
+      (return (* ii 2))))
+  5)
+
+(ert-deftest calc-defmath ()
+  (let ((var-g 17))
+    (should (equal (calcFunc-test1 2) (* 3 5 11 17)))
+    (should (equal (calcFunc-test2 2) (* 2 3 6 12 17))))
+  (should (equal (calcFunc-test3 3)
+                 (+ (* 1 1)
+                    (* 2 1) (* 2 2)
+                    (* 3 1) (* 3 2) (* 3 3))))
+  (should (equal (calcFunc-test4 5)
+                 '( 1 2 3 4 5 6 7 8 9 10
+                    1 3 5 7 9
+                    1 4 7 10
+                    1 5 9
+                    1 6)))
+  (should (equal (calcFunc-test5 '((2 3) (5) (7 11 13)))
+                 (+ 2 3 5 7 11 13)))
+  (should (equal (calcFunc-test6 3) (* (* 3 2) (- 3 1))))
+  (should (equal (calcFunc-test7 3) (* 3 2))))
+
 (provide 'calc-tests)
 ;;; calc-tests.el ends here
 
diff --git 
a/test/lisp/calendar/icalendar-resources/import-rrule-anniversary.diary-american
 
b/test/lisp/calendar/icalendar-resources/import-rrule-anniversary.diary-american
index 7b86b55..2f7026a 100644
--- 
a/test/lisp/calendar/icalendar-resources/import-rrule-anniversary.diary-american
+++ 
b/test/lisp/calendar/icalendar-resources/import-rrule-anniversary.diary-american
@@ -1 +1 @@
-&%%(and (diary-anniversary 8 15 2004))  Maria Himmelfahrt
+&%%(diary-anniversary 8 15 2003)  Maria Himmelfahrt
diff --git 
a/test/lisp/calendar/icalendar-resources/import-rrule-anniversary.diary-european
 
b/test/lisp/calendar/icalendar-resources/import-rrule-anniversary.diary-european
index 3b82ec0..fa652db 100644
--- 
a/test/lisp/calendar/icalendar-resources/import-rrule-anniversary.diary-european
+++ 
b/test/lisp/calendar/icalendar-resources/import-rrule-anniversary.diary-european
@@ -1 +1 @@
-&%%(and (diary-anniversary 15 8 2004))  Maria Himmelfahrt
+&%%(diary-anniversary 15 8 2003)  Maria Himmelfahrt
diff --git 
a/test/lisp/calendar/icalendar-resources/import-rrule-anniversary.diary-iso 
b/test/lisp/calendar/icalendar-resources/import-rrule-anniversary.diary-iso
index 7fc9947..803dd36 100644
--- a/test/lisp/calendar/icalendar-resources/import-rrule-anniversary.diary-iso
+++ b/test/lisp/calendar/icalendar-resources/import-rrule-anniversary.diary-iso
@@ -1 +1 @@
-&%%(and (diary-anniversary 2004 8 15))  Maria Himmelfahrt
+&%%(diary-anniversary 2003 8 15)  Maria Himmelfahrt
diff --git 
a/test/lisp/calendar/icalendar-resources/import-rrule-yearly.diary-american 
b/test/lisp/calendar/icalendar-resources/import-rrule-yearly.diary-american
index a54780b..bc485d8 100644
--- a/test/lisp/calendar/icalendar-resources/import-rrule-yearly.diary-american
+++ b/test/lisp/calendar/icalendar-resources/import-rrule-yearly.diary-american
@@ -1 +1 @@
-&%%(and (diary-anniversary 9 19 2003)) 09:00-11:30 rrule yearly
+&%%(diary-anniversary 9 19 2002) 09:00-11:30 rrule yearly
diff --git 
a/test/lisp/calendar/icalendar-resources/import-rrule-yearly.diary-european 
b/test/lisp/calendar/icalendar-resources/import-rrule-yearly.diary-european
index a4bd81d..42509d4 100644
--- a/test/lisp/calendar/icalendar-resources/import-rrule-yearly.diary-european
+++ b/test/lisp/calendar/icalendar-resources/import-rrule-yearly.diary-european
@@ -1 +1 @@
-&%%(and (diary-anniversary 19 9 2003)) 09:00-11:30 rrule yearly
+&%%(diary-anniversary 19 9 2002) 09:00-11:30 rrule yearly
diff --git 
a/test/lisp/calendar/icalendar-resources/import-rrule-yearly.diary-iso 
b/test/lisp/calendar/icalendar-resources/import-rrule-yearly.diary-iso
index 65a7abe..72fe6e1 100644
--- a/test/lisp/calendar/icalendar-resources/import-rrule-yearly.diary-iso
+++ b/test/lisp/calendar/icalendar-resources/import-rrule-yearly.diary-iso
@@ -1 +1 @@
-&%%(and (diary-anniversary 2003 9 19)) 09:00-11:30 rrule yearly
+&%%(diary-anniversary 2002 9 19) 09:00-11:30 rrule yearly
diff --git a/test/lisp/calendar/icalendar-tests.el 
b/test/lisp/calendar/icalendar-tests.el
index 7993a1f..61d3c11 100644
--- a/test/lisp/calendar/icalendar-tests.el
+++ b/test/lisp/calendar/icalendar-tests.el
@@ -87,7 +87,7 @@
   (let* ((calendar-date-style 'iso)
          result)
     (setq result (icalendar--convert-anniversary-to-ical
-                  "" "%%(diary-anniversary 1964 6 30) g"))
+                  "" "%%(diary-anniversary 1963 6 30) g"))
     (should (consp result))
     (should (string= (concat
                       "\nDTSTART;VALUE=DATE:19640630"
@@ -353,7 +353,7 @@ END:VTIMEZONE
   (let ((calendar-date-style 'iso))
     ;; numeric iso
     (should (string= "20080511"
-                     (icalendar--datestring-to-isodate "2008 05 11")))
+                    (icalendar--datestring-to-isodate "2008 05 11")))
     (should (string= "20080531"
                     (icalendar--datestring-to-isodate "2008 05 31")))
     (should (string= "20080602"
@@ -384,7 +384,19 @@ END:VTIMEZONE
     (should (string= "20081105"
                     (icalendar--datestring-to-isodate "05 Nov 2008")))
     (should (string= "20081105"
-                    (icalendar--datestring-to-isodate "2008 Nov 05")))))
+                    (icalendar--datestring-to-isodate "2008 Nov 05")))
+
+    ;; non-numeric with day-shift and year-shift
+    (setq calendar-date-style nil)      ;not necessary for conversion
+    (should (string= "20210212"
+                    (icalendar--datestring-to-isodate "2021 Feb 11" 1)))
+    (should (string= "20210131"
+                    (icalendar--datestring-to-isodate "2021 Feb 11" -11)))
+    (should (string= "20200211"
+                    (icalendar--datestring-to-isodate "2021 Feb 11" nil -1)))
+    (should (string= "21010211"
+                    (icalendar--datestring-to-isodate "2021 Feb 11" nil 80)))
+    ))
 
 (ert-deftest icalendar--first-weekday-of-year ()
   "Test method for `icalendar-first-weekday-of-year'."
@@ -569,10 +581,10 @@ END:VEVENT
 
           ;; testcase: dtstart is mandatory
           (should (null (icalendar--convert-tz-offset
-                          '((TZOFFSETFROM nil "+0100")
-                            (TZOFFSETTO nil "+0200")
-                            (RRULE nil "FREQ=YEARLY;BYMONTH=3;BYDAY=-1SU"))
-                          t)))
+                         '((TZOFFSETFROM nil "+0100")
+                           (TZOFFSETTO nil "+0200")
+                           (RRULE nil "FREQ=YEARLY;BYMONTH=3;BYDAY=-1SU"))
+                         t)))
 
           ;; FIXME: rrule and rdate are NOT mandatory!  Must fix code
           ;; before activating these testcases
@@ -830,18 +842,18 @@ SUMMARY:yearly no time
   "Perform export test."
   ;; anniversaries
   (icalendar-tests--test-export
-   "%%(diary-anniversary 1989 10 3) anniversary no time"
-   "%%(diary-anniversary 3 10 1989) anniversary no time"
-   "%%(diary-anniversary 10 3 1989) anniversary no time"
+   "%%(diary-anniversary 1988 10 3) anniversary no time"
+   "%%(diary-anniversary 3 10 1988) anniversary no time"
+   "%%(diary-anniversary 10 3 1988) anniversary no time"
    "DTSTART;VALUE=DATE:19891003
 DTEND;VALUE=DATE:19891004
 RRULE:FREQ=YEARLY;INTERVAL=1;BYMONTH=10;BYMONTHDAY=03
 SUMMARY:anniversary no time
 ")
   (icalendar-tests--test-export
-   "%%(diary-anniversary 1989 10 3) 19:00-20:00 anniversary with time"
-   "%%(diary-anniversary 3 10 1989) 19:00-20:00 anniversary with time"
-   "%%(diary-anniversary 10 3 1989) 19:00-20:00 anniversary with time"
+   "%%(diary-anniversary 1988 10 3) 19:00-20:00 anniversary with time"
+   "%%(diary-anniversary 3 10 1988) 19:00-20:00 anniversary with time"
+   "%%(diary-anniversary 10 3 1988) 19:00-20:00 anniversary with time"
    "DTSTART;VALUE=DATE-TIME:19891003T190000
 DTEND;VALUE=DATE-TIME:19891004T200000
 RRULE:FREQ=YEARLY;INTERVAL=1;BYMONTH=10;BYMONTHDAY=03
@@ -891,12 +903,12 @@ SUMMARY:no alarm
 "
    nil)
 
-    ;; 10 minutes in advance, audio
-    (icalendar-tests--test-export
-     "2014 Nov 17 19:30 audio alarm"
-     "17 Nov 2014 19:30 audio alarm"
-     "Nov 17 2014 19:30 audio alarm"
-     "DTSTART;VALUE=DATE-TIME:20141117T193000
+  ;; 10 minutes in advance, audio
+  (icalendar-tests--test-export
+   "2014 Nov 17 19:30 audio alarm"
+   "17 Nov 2014 19:30 audio alarm"
+   "Nov 17 2014 19:30 audio alarm"
+   "DTSTART;VALUE=DATE-TIME:20141117T193000
 DTEND;VALUE=DATE-TIME:20141117T203000
 SUMMARY:audio alarm
 BEGIN:VALARM
@@ -904,14 +916,14 @@ ACTION:AUDIO
 TRIGGER:-PT10M
 END:VALARM
 "
-     '(10 ((audio))))
+   '(10 ((audio))))
 
-    ;; 20 minutes in advance, display
-    (icalendar-tests--test-export
-     "2014 Nov 17 19:30 display alarm"
-     "17 Nov 2014 19:30 display alarm"
-     "Nov 17 2014 19:30 display alarm"
-     "DTSTART;VALUE=DATE-TIME:20141117T193000
+  ;; 20 minutes in advance, display
+  (icalendar-tests--test-export
+   "2014 Nov 17 19:30 display alarm"
+   "17 Nov 2014 19:30 display alarm"
+   "Nov 17 2014 19:30 display alarm"
+   "DTSTART;VALUE=DATE-TIME:20141117T193000
 DTEND;VALUE=DATE-TIME:20141117T203000
 SUMMARY:display alarm
 BEGIN:VALARM
@@ -920,14 +932,14 @@ TRIGGER:-PT20M
 DESCRIPTION:display alarm
 END:VALARM
 "
-     '(20 ((display))))
+   '(20 ((display))))
 
-    ;; 66 minutes in advance, email
-    (icalendar-tests--test-export
-     "2014 Nov 17 19:30 email alarm"
-     "17 Nov 2014 19:30 email alarm"
-     "Nov 17 2014 19:30 email alarm"
-     "DTSTART;VALUE=DATE-TIME:20141117T193000
+  ;; 66 minutes in advance, email
+  (icalendar-tests--test-export
+   "2014 Nov 17 19:30 email alarm"
+   "17 Nov 2014 19:30 email alarm"
+   "Nov 17 2014 19:30 email alarm"
+   "DTSTART;VALUE=DATE-TIME:20141117T193000
 DTEND;VALUE=DATE-TIME:20141117T203000
 SUMMARY:email alarm
 BEGIN:VALARM
@@ -939,14 +951,14 @@ ATTENDEE:MAILTO:att.one@email.com
 ATTENDEE:MAILTO:att.two@email.com
 END:VALARM
 "
-     '(66 ((email ("att.one@email.com" "att.two@email.com")))))
+   '(66 ((email ("att.one@email.com" "att.two@email.com")))))
 
-    ;; 2 minutes in advance, all alarms
-    (icalendar-tests--test-export
-     "2014 Nov 17 19:30 all alarms"
-     "17 Nov 2014 19:30 all alarms"
-     "Nov 17 2014 19:30 all alarms"
-     "DTSTART;VALUE=DATE-TIME:20141117T193000
+  ;; 2 minutes in advance, all alarms
+  (icalendar-tests--test-export
+   "2014 Nov 17 19:30 all alarms"
+   "17 Nov 2014 19:30 all alarms"
+   "Nov 17 2014 19:30 all alarms"
+   "DTSTART;VALUE=DATE-TIME:20141117T193000
 DTEND;VALUE=DATE-TIME:20141117T203000
 SUMMARY:all alarms
 BEGIN:VALARM
@@ -967,7 +979,7 @@ TRIGGER:-PT2M
 DESCRIPTION:all alarms
 END:VALARM
 "
-     '(2 ((email ("att.one@email.com" "att.two@email.com")) (audio) 
(display)))))
+   '(2 ((email ("att.one@email.com" "att.two@email.com")) (audio) (display)))))
 
 ;; ======================================================================
 ;; Import tests
@@ -1247,7 +1259,7 @@ Argument INPUT icalendar event string."
            (find-file temp-ics)
            (goto-char (point-min))
            ;;(when (re-search-forward "\nUID:.*\n" nil t)
-             ;;(replace-match "\n"))
+           ;;(replace-match "\n"))
            (let ((cycled (buffer-substring-no-properties (point-min) 
(point-max))))
              (should (string= org-input cycled)))))
       ;; clean up
@@ -1276,8 +1288,8 @@ DESCRIPTION:beschreibung!
 LOCATION:nowhere
 ORGANIZER:ulf
 ")
-    (icalendar-tests--test-cycle
-     "UID:4711
+  (icalendar-tests--test-cycle
+   "UID:4711
 DTSTART;VALUE=DATE:19190909
 DTEND;VALUE=DATE:19190910
 RRULE:FREQ=YEARLY;INTERVAL=1;BYMONTH=09;BYMONTHDAY=09
@@ -1377,7 +1389,7 @@ SUMMARY:ff")
    "
 >>> anniversaries:
 
-%%(diary-anniversary 3 28 1991) aa birthday (%d years old)"
+%%(diary-anniversary 3 28 1990) aa birthday (%d years old)"
    "DTSTART;VALUE=DATE:19910328
 DTEND;VALUE=DATE:19910329
 RRULE:FREQ=YEARLY;INTERVAL=1;BYMONTH=03;BYMONTHDAY=28
@@ -1387,7 +1399,7 @@ SUMMARY:aa birthday (%d years old)
   (icalendar-tests--test-export
    nil
    nil
-   "%%(diary-anniversary 5 17 1957) bb birthday (%d years old)"
+   "%%(diary-anniversary 5 17 1956) bb birthday (%d years old)"
    "DTSTART;VALUE=DATE:19570517
 DTEND;VALUE=DATE:19570518
 RRULE:FREQ=YEARLY;INTERVAL=1;BYMONTH=05;BYMONTHDAY=17
@@ -1396,7 +1408,7 @@ SUMMARY:bb birthday (%d years old)")
   (icalendar-tests--test-export
    nil
    nil
-   "%%(diary-anniversary 6 8 1997) cc birthday (%d years old)"
+   "%%(diary-anniversary 6 8 1996) cc birthday (%d years old)"
    "DTSTART;VALUE=DATE:19970608
 DTEND;VALUE=DATE:19970609
 RRULE:FREQ=YEARLY;INTERVAL=1;BYMONTH=06;BYMONTHDAY=08
@@ -1405,7 +1417,7 @@ SUMMARY:cc birthday (%d years old)")
   (icalendar-tests--test-export
    nil
    nil
-   "%%(diary-anniversary 7 22 1983) dd (%d years ago...!)"
+   "%%(diary-anniversary 7 22 1982) dd (%d years ago...!)"
    "DTSTART;VALUE=DATE:19830722
 DTEND;VALUE=DATE:19830723
 RRULE:FREQ=YEARLY;INTERVAL=1;BYMONTH=07;BYMONTHDAY=22
@@ -1414,7 +1426,7 @@ SUMMARY:dd (%d years ago...!)")
   (icalendar-tests--test-export
    nil
    nil
-   "%%(diary-anniversary 8 1 1988) ee birthday (%d years old)"
+   "%%(diary-anniversary 8 1 1987) ee birthday (%d years old)"
    "DTSTART;VALUE=DATE:19880801
 DTEND;VALUE=DATE:19880802
 RRULE:FREQ=YEARLY;INTERVAL=1;BYMONTH=08;BYMONTHDAY=01
@@ -1423,7 +1435,7 @@ SUMMARY:ee birthday (%d years old)")
   (icalendar-tests--test-export
    nil
    nil
-   "%%(diary-anniversary 9 21 1957) ff birthday (%d years old)"
+   "%%(diary-anniversary 9 21 1956) ff birthday (%d years old)"
    "DTSTART;VALUE=DATE:19570921
 DTEND;VALUE=DATE:19570922
 RRULE:FREQ=YEARLY;INTERVAL=1;BYMONTH=09;BYMONTHDAY=21
diff --git a/test/lisp/cedet/semantic-utest-c.el 
b/test/lisp/cedet/semantic-utest-c.el
index a7cbe11..d08c79c 100644
--- a/test/lisp/cedet/semantic-utest-c.el
+++ b/test/lisp/cedet/semantic-utest-c.el
@@ -43,7 +43,6 @@
 (defvar semantic-lex-c-nested-namespace-ignore-second)
 
 ;;; Code:
-;;;###autoload
 (ert-deftest semantic-test-c-preprocessor-simulation ()
   "Run parsing test for C from the test directory."
   :tags '(:expensive-test)
diff --git a/test/lisp/cedet/semantic-utest.el 
b/test/lisp/cedet/semantic-utest.el
index 67de4a5..172ab62 100644
--- a/test/lisp/cedet/semantic-utest.el
+++ b/test/lisp/cedet/semantic-utest.el
@@ -1,6 +1,6 @@
 ;;; semantic-utest.el --- Tests for semantic's parsing system. -*- 
lexical-binding:t -*-
 
-;;; Copyright (C) 2003-2004, 2007-2021 Free Software Foundation, Inc.
+;; Copyright (C) 2003-2021  Free Software Foundation, Inc.
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
 
diff --git a/test/lisp/cedet/semantic/bovine/gcc-tests.el 
b/test/lisp/cedet/semantic/bovine/gcc-tests.el
index e1a18c6..93677d6 100644
--- a/test/lisp/cedet/semantic/bovine/gcc-tests.el
+++ b/test/lisp/cedet/semantic/bovine/gcc-tests.el
@@ -1,6 +1,6 @@
 ;;; gcc-tests.el --- Tests for semantic/bovine/gcc.el  -*- lexical-binding:t 
-*-
 
-;;; Copyright (C) 2003-2004, 2007-2021 Free Software Foundation, Inc.
+;; Copyright (C) 2003-2021  Free Software Foundation, Inc.
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
 
diff --git a/test/lisp/cedet/semantic/format-resources/test-fmt.el 
b/test/lisp/cedet/semantic/format-resources/test-fmt.el
index 941aaae..8458a8e 100644
--- a/test/lisp/cedet/semantic/format-resources/test-fmt.el
+++ b/test/lisp/cedet/semantic/format-resources/test-fmt.el
@@ -1,6 +1,6 @@
 ;;; test-fmt.el --- test semantic tag formatting  -*- lexical-binding: t -*-
 
-;;; Copyright (C) 2012, 2019-2021 Free Software Foundation, Inc.
+;; Copyright (C) 2012-2021  Free Software Foundation, Inc.
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
 
diff --git a/test/lisp/cedet/semantic/format-tests.el 
b/test/lisp/cedet/semantic/format-tests.el
index e82c97b..149f408 100644
--- a/test/lisp/cedet/semantic/format-tests.el
+++ b/test/lisp/cedet/semantic/format-tests.el
@@ -1,6 +1,6 @@
 ;;; semantic/format-tests.el --- Parsing / Formatting tests -*- 
lexical-binding:t -*-
 
-;;; Copyright (C) 2003-2004, 2007-2021 Free Software Foundation, Inc.
+;; Copyright (C) 2003-2021  Free Software Foundation, Inc.
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
 
diff --git a/test/lisp/cedet/semantic/fw-tests.el 
b/test/lisp/cedet/semantic/fw-tests.el
index 62d665d..7b1cd21 100644
--- a/test/lisp/cedet/semantic/fw-tests.el
+++ b/test/lisp/cedet/semantic/fw-tests.el
@@ -1,6 +1,6 @@
 ;;; fw-tests.el --- Tests for semantic/fw.el  -*- lexical-binding:t -*-
 
-;;; Copyright (C) 2003-2004, 2007-2021 Free Software Foundation, Inc.
+;; Copyright (C) 2003-2021  Free Software Foundation, Inc.
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
 
diff --git a/test/lisp/comint-tests.el b/test/lisp/comint-tests.el
index de1bc54..8a9a41f 100644
--- a/test/lisp/comint-tests.el
+++ b/test/lisp/comint-tests.el
@@ -44,6 +44,7 @@
     "Password (again):"
     "Enter password:"
     "Enter Auth Password:" ; OpenVPN (Bug#35724)
+    "Verify password: "    ; zip -e zipfile.zip ... (Bug#47209)
     "Mot de Passe :" ; localized (Bug#29729)
     "Passwort:") ; localized
   "List of strings that should match `comint-password-prompt-regexp'.")
diff --git a/test/lisp/custom-tests.el b/test/lisp/custom-tests.el
index 10854c7..02a9239 100644
--- a/test/lisp/custom-tests.el
+++ b/test/lisp/custom-tests.el
@@ -24,70 +24,108 @@
 
 (require 'wid-edit)
 (require 'cus-edit)
-(require 'seq) ; For `seq-find'.
+
+(defmacro custom-tests--with-temp-dir (&rest body)
+  "Eval BODY with `temporary-file-directory' bound to a fresh directory.
+Ensure the directory is recursively deleted after the fact."
+  (declare (debug t) (indent 0))
+  (let ((dir (make-symbol "dir")))
+    `(let ((,dir (file-name-as-directory (make-temp-file "custom-tests-" t))))
+       (unwind-protect
+           (let ((temporary-file-directory ,dir))
+             ,@body)
+         (delete-directory ,dir t)))))
 
 (ert-deftest custom-theme--load-path ()
   "Test `custom-theme--load-path' behavior."
-  (let ((tmpdir (file-name-as-directory (make-temp-file "custom-tests-" t))))
-    (unwind-protect
-        ;; Create all temporary files under the same deletable parent.
-        (let ((temporary-file-directory tmpdir))
-          ;; Path is empty.
-          (let ((custom-theme-load-path ()))
-            (should (null (custom-theme--load-path))))
-
-          ;; Path comprises non-existent file.
-          (let* ((name (make-temp-name tmpdir))
-                 (custom-theme-load-path (list name)))
-            (should (not (file-exists-p name)))
-            (should (null (custom-theme--load-path))))
-
-          ;; Path comprises existing file.
-          (let* ((file (make-temp-file "file"))
-                 (custom-theme-load-path (list file)))
-            (should (file-exists-p file))
-            (should (not (file-directory-p file)))
-            (should (null (custom-theme--load-path))))
-
-          ;; Path comprises existing directory.
-          (let* ((dir (make-temp-file "dir" t))
-                 (custom-theme-load-path (list dir)))
-            (should (file-directory-p dir))
-            (should (equal (custom-theme--load-path) custom-theme-load-path)))
-
-          ;; Expand `custom-theme-directory' path element.
-          (let ((custom-theme-load-path '(custom-theme-directory)))
-            (let ((custom-theme-directory (make-temp-name tmpdir)))
-              (should (not (file-exists-p custom-theme-directory)))
-              (should (null (custom-theme--load-path))))
-            (let ((custom-theme-directory (make-temp-file "file")))
-              (should (file-exists-p custom-theme-directory))
-              (should (not (file-directory-p custom-theme-directory)))
-              (should (null (custom-theme--load-path))))
-            (let ((custom-theme-directory (make-temp-file "dir" t)))
-              (should (file-directory-p custom-theme-directory))
-              (should (equal (custom-theme--load-path)
-                             (list custom-theme-directory)))))
-
-          ;; Expand t path element.
-          (let ((custom-theme-load-path '(t)))
-            (let ((data-directory (make-temp-name tmpdir)))
-              (should (not (file-exists-p data-directory)))
-              (should (null (custom-theme--load-path))))
-            (let ((data-directory tmpdir)
-                  (themedir (expand-file-name "themes" tmpdir)))
-              (should (not (file-exists-p themedir)))
-              (should (null (custom-theme--load-path)))
-              (with-temp-file themedir)
-              (should (file-exists-p themedir))
-              (should (not (file-directory-p themedir)))
-              (should (null (custom-theme--load-path)))
-              (delete-file themedir)
-              (make-directory themedir)
-              (should (file-directory-p themedir))
-              (should (equal (custom-theme--load-path) (list themedir))))))
-      (when (file-directory-p tmpdir)
-        (delete-directory tmpdir t)))))
+  (custom-tests--with-temp-dir
+    ;; Path is empty.
+    (let ((custom-theme-load-path ()))
+      (should (null (custom-theme--load-path))))
+
+    ;; Path comprises non-existent file.
+    (let* ((name (make-temp-name temporary-file-directory))
+           (custom-theme-load-path (list name)))
+      (should (not (file-exists-p name)))
+      (should (null (custom-theme--load-path))))
+
+    ;; Path comprises existing file.
+    (let* ((file (make-temp-file "file"))
+           (custom-theme-load-path (list file)))
+      (should (file-exists-p file))
+      (should (not (file-directory-p file)))
+      (should (null (custom-theme--load-path))))
+
+    ;; Path comprises existing directory.
+    (let* ((dir (make-temp-file "dir" t))
+           (custom-theme-load-path (list dir)))
+      (should (file-directory-p dir))
+      (should (equal (custom-theme--load-path) custom-theme-load-path)))
+
+    ;; Expand `custom-theme-directory' path element.
+    (let ((custom-theme-load-path '(custom-theme-directory)))
+      (let ((custom-theme-directory (make-temp-name temporary-file-directory)))
+        (should (not (file-exists-p custom-theme-directory)))
+        (should (null (custom-theme--load-path))))
+      (let ((custom-theme-directory (make-temp-file "file")))
+        (should (file-exists-p custom-theme-directory))
+        (should (not (file-directory-p custom-theme-directory)))
+        (should (null (custom-theme--load-path))))
+      (let ((custom-theme-directory (make-temp-file "dir" t)))
+        (should (file-directory-p custom-theme-directory))
+        (should (equal (custom-theme--load-path)
+                       (list custom-theme-directory)))))
+
+    ;; Expand t path element.
+    (let ((custom-theme-load-path '(t)))
+      (let ((data-directory (make-temp-name temporary-file-directory)))
+        (should (not (file-exists-p data-directory)))
+        (should (null (custom-theme--load-path))))
+      (let ((data-directory temporary-file-directory)
+            (themedir (expand-file-name "themes" temporary-file-directory)))
+        (should (not (file-exists-p themedir)))
+        (should (null (custom-theme--load-path)))
+        (with-temp-file themedir)
+        (should (file-exists-p themedir))
+        (should (not (file-directory-p themedir)))
+        (should (null (custom-theme--load-path)))
+        (delete-file themedir)
+        (make-directory themedir)
+        (should (file-directory-p themedir))
+        (should (equal (custom-theme--load-path) (list themedir)))))))
+
+(ert-deftest custom-tests-require-theme ()
+  "Test `require-theme'."
+  (custom-tests--with-temp-dir
+    (let* ((default-directory temporary-file-directory)
+           (custom-theme-load-path (list default-directory))
+           (load-path ()))
+      ;; Generate some `.el' and `.elc' files.
+      (with-temp-file "custom-tests--a.el"
+        (insert "(provide 'custom-tests--a)"))
+      (make-empty-file "custom-tests--b.el")
+      (with-temp-file "custom-tests--b.elc"
+        (byte-compile-insert-header nil (current-buffer))
+        (insert "(provide 'custom-tests--b)"))
+      (make-empty-file "custom-tests--c.el")
+      (with-temp-file "custom-tests--d.elc"
+        (byte-compile-insert-header nil (current-buffer)))
+      ;; Load them.
+      (dolist (feature '(a b c d e))
+        (should-not (featurep (intern (format "custom-tests--%s" feature)))))
+      (should (eq (require-theme 'custom-tests--a) 'custom-tests--a))
+      (delete-file "custom-tests--a.el")
+      (dolist (feature '(custom-tests--a custom-tests--b))
+        (should (eq (require-theme feature) feature))
+        (should (featurep feature)))
+      (dolist (feature '(custom-tests--c custom-tests--d))
+        (dolist (noerror '(nil t))
+          (let ((err (should-error (require-theme feature noerror))))
+            (should (string-search "failed to provide feature" (cadr err))))))
+      (should-error (require-theme 'custom-tests--e) :type 'file-missing)
+      (should-not (require-theme 'custom-tests--e t))
+      (dolist (feature '(custom-tests--c custom-tests--d custom-tests--e))
+        (should-not (featurep feature))))))
 
 (defcustom custom--test-user-option 'foo
   "User option for test."
@@ -145,17 +183,6 @@
                                (widget-apply field :value-to-internal 
origvalue)
                                "bar"))))))
 
-(defconst custom-test-admin-cus-test
-  (expand-file-name "admin/cus-test.el" source-directory))
-
-(declare-function cus-test-opts custom-test-admin-cus-test)
-
-(ert-deftest check-for-wrong-custom-types ()
-  :tags '(:expensive-test)
-  (skip-unless (file-readable-p custom-test-admin-cus-test))
-  (load custom-test-admin-cus-test)
-  (should (null (cus-test-opts t))))
-
 (ert-deftest custom-test-enable-theme-keeps-settings ()
   "Test that enabling a theme doesn't change its settings."
   (let* ((custom-theme-load-path `(,(ert-resource-directory)))
diff --git a/test/lisp/electric-tests.el b/test/lisp/electric-tests.el
index 62a42b7..44b3d8b 100644
--- a/test/lisp/electric-tests.el
+++ b/test/lisp/electric-tests.el
@@ -50,7 +50,8 @@
   `(call-with-saved-electric-modes #'(lambda () ,@body)))
 
 (defun electric-pair-test-for (fixture where char expected-string
-                                       expected-point mode bindings fixture-fn)
+                                       expected-point mode bindings
+                                       fixture-fn &optional doc-string)
   (with-temp-buffer
     (funcall mode)
     (insert fixture)
@@ -63,6 +64,14 @@
             (mapcar #'car bindings)
             (mapcar #'cdr bindings)
           (call-interactively (key-binding `[,last-command-event])))))
+    (when
+        (and doc-string
+             (not
+              (and
+               (equal (buffer-substring-no-properties (point-min) (point-max))
+                      expected-string)
+               (equal (point) expected-point))))
+      (message "\n%s\n" doc-string))
     (should (equal (buffer-substring-no-properties (point-min) (point-max))
                    expected-string))
     (should (equal (point)
@@ -109,14 +118,9 @@
            (fixture (format "%s%s%s" prefix fixture suffix))
            (expected-string (format "%s%s%s" prefix expected-string suffix))
            (expected-point (+ (length prefix) expected-point))
-           (pos (+ (length prefix) pos)))
-      `(ert-deftest ,(intern (format "electric-pair-%s-at-point-%s-in-%s%s"
-                                     name
-                                     (1+ pos)
-                                     mode
-                                     extra-desc))
-           ()
-         ,(format "Electricity test in a `%s' buffer.\n
+           (pos (+ (length prefix) pos))
+           (doc-string
+            (format "Electricity test in a `%s' buffer.\n
 Start with point at %d in a %d-char-long buffer
 like this one:
 
@@ -143,7 +147,14 @@ The buffer's contents should %s:
                   char
                   (if (string= fixture expected-string) "stay" "become")
                   (replace-regexp-in-string "\n" "\\\\n" expected-string)
-                  expected-point)
+                  expected-point)))
+      `(ert-deftest ,(intern (format "electric-pair-%s-at-point-%s-in-%s%s"
+                                     name
+                                     (1+ pos)
+                                     mode
+                                     extra-desc))
+           ()
+         ,doc-string
          (electric-pair-test-for ,fixture
                                  ,(1+ pos)
                                  ,char
@@ -151,7 +162,8 @@ The buffer's contents should %s:
                                  ,expected-point
                                  ',mode
                                  ,bindings
-                                 ,fixture-fn)))))
+                                 ,fixture-fn
+                                 ,doc-string)))))
 
 (cl-defmacro define-electric-pair-test
     (name fixture
diff --git a/test/lisp/emacs-lisp/bindat-tests.el 
b/test/lisp/emacs-lisp/bindat-tests.el
index a9a8819..911a5f0 100644
--- a/test/lisp/emacs-lisp/bindat-tests.el
+++ b/test/lisp/emacs-lisp/bindat-tests.el
@@ -1,4 +1,4 @@
-;;; bindat-tests.el --- tests for bindat.el  -*- lexical-binding: t; coding: 
utf-8; -*-
+;;; bindat-tests.el --- tests for bindat.el  -*- lexical-binding: t -*-
 
 ;; Copyright (C) 2019-2021 Free Software Foundation, Inc.
 
@@ -23,44 +23,50 @@
 (require 'bindat)
 (require 'cl-lib)
 
-(defvar header-bindat-spec
-  '((dest-ip ip)
+(bindat-defmacro ip () "An IPv4 address"     '(vec 4 byte))
+
+(defconst header-bindat-spec
+  (bindat-type
+    (dest-ip ip)
     (src-ip ip)
-    (dest-port u16)
-    (src-port u16)))
+    (dest-port uint 16)
+    (src-port uint 16)))
 
-(defvar data-bindat-spec
-  '((type u8)
+(defconst data-bindat-spec
+  (bindat-type
+    (type u8)
     (opcode u8)
-    (length u16r) ;; little endian order
+    (length uintr 16) ;; little endian order
     (id strz 8)
-    (data vec (length))
-    (align 4)))
+    (data vec length)
+    (_ align 4)))
+
 
-(defvar packet-bindat-spec
-  '((header struct header-bindat-spec)
+(defconst packet-bindat-spec
+  (bindat-type
+    (header type header-bindat-spec)
     (items u8)
-    (fill 3)
-    (item repeat (items)
-          (struct data-bindat-spec))))
+    (_ fill 3)
+    (item repeat items
+          (_ type data-bindat-spec))))
 
-(defvar struct-bindat
+(defconst struct-bindat
   '((header
      (dest-ip . [192 168 1 100])
      (src-ip . [192 168 1 101])
      (dest-port . 284)
      (src-port . 5408))
     (items . 2)
-    (item ((data . [1 2 3 4 5])
-           (id . "ABCDEF")
-           (length . 5)
+    (item ((type . 2)
            (opcode . 3)
-           (type . 2))
-          ((data . [6 7 8 9 10 11 12])
-           (id . "BCDEFG")
-           (length . 7)
+           (length . 5)
+           (id . "ABCDEF")
+           (data . [1 2 3 4 5]))
+          ((type . 1)
            (opcode . 4)
-           (type . 1)))))
+           (length . 7)
+           (id . "BCDEFG")
+           (data . [6 7 8 9 10 11 12])))))
 
 (ert-deftest bindat-test-pack ()
   (should (equal
@@ -74,27 +80,7 @@
   (should (equal
            (bindat-unpack packet-bindat-spec
                           (bindat-pack packet-bindat-spec struct-bindat))
-           '((item
-              ((data .
-                    [1 2 3 4 5])
-               (id . "ABCDEF")
-               (length . 5)
-               (opcode . 3)
-               (type . 2))
-              ((data .
-                    [6 7 8 9 10 11 12])
-               (id . "BCDEFG")
-               (length . 7)
-               (opcode . 4)
-               (type . 1)))
-             (items . 2)
-             (header
-              (src-port . 5408)
-              (dest-port . 284)
-              (src-ip .
-                     [192 168 1 101])
-              (dest-ip .
-                       [192 168 1 100]))))))
+           struct-bindat)))
 
 (ert-deftest bindat-test-pack/multibyte-string-fails ()
   (should-error (bindat-pack nil nil "ö")))
@@ -118,4 +104,62 @@
   (should (equal (bindat-ip-to-string [192 168 0 1]) "192.168.0.1"))
   (should (equal (bindat-ip-to-string "\300\250\0\1") "192.168.0.1")))
 
+(defconst bindat-test--int-websocket-type
+  (bindat-type
+    :pack-var value
+    (n1 u8
+        :pack-val (if (< value 126) value (if (< value 65536) 126 127)))
+    (n2 uint (pcase n1 (127 64) (126 16) (_ 0))
+        :pack-val value)
+    :unpack-val (if (< n1 126) n1 n2)))
+
+(ert-deftest bindat-test--pack-val ()
+  ;; This is intended to test the :(un)pack-val feature that offers
+  ;; control over the unpacked representation of the data.
+  (dolist (n '(0 42 125 126 127 128 150 255 5000 65535 65536 8769786876))
+    (should
+     (equal (bindat-unpack bindat-test--int-websocket-type
+                           (bindat-pack bindat-test--int-websocket-type n))
+            n))))
+
+(ert-deftest bindat-test--sint ()
+  (dotimes (kind 32)
+    (let ((bitlen (* 8 (/ kind 2)))
+          (r (zerop (% kind 2))))
+      (dotimes (_ 100)
+        (let* ((n (random (ash 1 bitlen)))
+               (i (- n (ash 1 (1- bitlen)))))
+          (should (equal (bindat-unpack
+                          (bindat-type sint bitlen r)
+                          (bindat-pack (bindat-type sint bitlen r) i))
+                         i))
+          (when (>= i 0)
+            (should (equal (bindat-pack
+                            (bindat-type if r (uintr bitlen) (uint bitlen)) i)
+                           (bindat-pack (bindat-type sint bitlen r) i)))
+            (should (equal (bindat-unpack
+                            (bindat-type if r (uintr bitlen) (uint bitlen))
+                            (bindat-pack (bindat-type sint bitlen r) i))
+                           i))))))))
+
+(defconst bindat-test--LEB128
+  (bindat-type
+   letrec ((loop
+            (struct :pack-var n
+                    (head u8
+                          :pack-val (+ (logand n 127) (if (> n 127) 128 0)))
+                    (tail if (< head 128) (unit 0) loop
+                          :pack-val (ash n -7))
+                    :unpack-val (+ (logand head 127) (ash tail 7)))))
+   loop))
+
+(ert-deftest bindat-test--recursive ()
+  (dotimes (n 10)
+    (let ((max (ash 1 (* n 10))))
+      (dotimes (_ 10)
+        (let ((n (random max)))
+          (should (equal (bindat-unpack bindat-test--LEB128
+                                        (bindat-pack bindat-test--LEB128 n))
+                         n)))))))
+
 ;;; bindat-tests.el ends here
diff --git a/test/lisp/emacs-lisp/bytecomp-tests.el 
b/test/lisp/emacs-lisp/bytecomp-tests.el
index bc623d3..5147cd2 100644
--- a/test/lisp/emacs-lisp/bytecomp-tests.el
+++ b/test/lisp/emacs-lisp/bytecomp-tests.el
@@ -495,6 +495,7 @@ Subtests signal errors if something goes wrong."
       (insert "\n"))))
 
 (defun test-byte-comp-compile-and-load (compile &rest forms)
+  (declare (indent 1))
   (let ((elfile nil)
         (elcfile nil))
     (unwind-protect
@@ -513,7 +514,6 @@ Subtests signal errors if something goes wrong."
            (load elfile nil 'nomessage))
       (when elfile (delete-file elfile))
       (when elcfile (delete-file elcfile)))))
-(put 'test-byte-comp-compile-and-load 'lisp-indent-function 1)
 
 (ert-deftest test-byte-comp-macro-expansion ()
   (test-byte-comp-compile-and-load t
@@ -1168,6 +1168,65 @@ mountpoint (Bug#44631)."
       (with-demoted-errors "Error cleaning up directory: %s"
         (delete-directory directory :recursive)))))
 
+(defun bytecomp-tests--get-vars ()
+  (list (ignore-errors (symbol-value 'bytecomp-tests--var1))
+        (ignore-errors (symbol-value 'bytecomp-tests--var2))))
+
+(ert-deftest bytecomp-local-defvar ()
+  "Check that local `defvar' declarations work correctly, both
+interpreted and compiled."
+  (let ((lexical-binding t))
+    (let ((fun '(lambda ()
+                  (defvar bytecomp-tests--var1)
+                  (let ((bytecomp-tests--var1 'a)    ; dynamic
+                        (bytecomp-tests--var2 'b))   ; still lexical
+                    (ignore bytecomp-tests--var2)    ; avoid warning
+                    (bytecomp-tests--get-vars)))))
+      (should (listp fun))      ; Guard against overzealous refactoring!
+      (should (equal (funcall (eval fun t)) '(a nil)))
+      (should (equal (funcall (byte-compile fun)) '(a nil)))
+      )
+
+    ;; `progn' does not constitute a lexical scope for `defvar' (bug#46387).
+    (let ((fun '(lambda ()
+                  (progn
+                    (defvar bytecomp-tests--var1)
+                    (defvar bytecomp-tests--var2))
+                  (let ((bytecomp-tests--var1 'c)
+                        (bytecomp-tests--var2 'd))
+                    (bytecomp-tests--get-vars)))))
+      (should (listp fun))
+      (should (equal (funcall (eval fun t)) '(c d)))
+      (should (equal (funcall (byte-compile fun)) '(c d))))))
+
+(ert-deftest bytecomp-reify-function ()
+  "Check that closures that modify their bound variables are
+compiled correctly."
+  (cl-letf ((lexical-binding t)
+            ((symbol-function 'counter) nil))
+    (let ((x 0))
+      (defun counter () (cl-incf x))
+      (should (equal (counter) 1))
+      (should (equal (counter) 2))
+      ;; byte compiling should not cause counter to always return the
+      ;; same value (bug#46834)
+      (byte-compile 'counter)
+      (should (equal (counter) 3))
+      (should (equal (counter) 4)))
+    (let ((x 0))
+      (let ((x 1))
+        (defun counter () x)
+        (should (equal (counter) 1))
+        ;; byte compiling should not cause the outer binding to shadow
+        ;; the inner one (bug#46834)
+        (byte-compile 'counter)
+        (should (equal (counter) 1))))))
+
+(ert-deftest bytecomp-string-vs-docstring ()
+  ;; Don't confuse a string return value for a docstring.
+  (let ((lexical-binding t))
+    (should (equal (funcall (byte-compile '(lambda (x) "foo")) 'dummy) 
"foo"))))
+
 ;; Local Variables:
 ;; no-byte-compile: t
 ;; End:
diff --git a/test/lisp/emacs-lisp/cconv-tests.el 
b/test/lisp/emacs-lisp/cconv-tests.el
index 5173733..5aeed0c 100644
--- a/test/lisp/emacs-lisp/cconv-tests.el
+++ b/test/lisp/emacs-lisp/cconv-tests.el
@@ -182,7 +182,14 @@
   (should (eq (cconv-tests-cl-defsubst) 'cl-defsubst-result)))
 
 (ert-deftest cconv-convert-lambda-lifted ()
-  "Bug#30872."
+  ;; Verify that lambda-lifting is actually performed at all.
+  (should (equal (cconv-closure-convert
+                  '#'(lambda (x) (let ((f #'(lambda () (+ x 1))))
+                                   (funcall f))))
+                 '#'(lambda (x) (let ((f #'(lambda (x) (+ x 1))))
+                                  (funcall f x)))))
+
+  ;; Bug#30872.
   (should
    (equal (funcall
            (byte-compile
diff --git a/test/lisp/emacs-lisp/checkdoc-tests.el 
b/test/lisp/emacs-lisp/checkdoc-tests.el
index cf7baf4..7a7aa9f 100644
--- a/test/lisp/emacs-lisp/checkdoc-tests.el
+++ b/test/lisp/emacs-lisp/checkdoc-tests.el
@@ -52,49 +52,31 @@
     (insert "(cl-defmethod foo ((a (eql smthg)) (b list)) \"Return A+B.\")")
     (checkdoc-defun)))
 
-(ert-deftest checkdoc-cl-defun-with-key-ok ()
-  "Checkdoc should be happy with a cl-defun using &key."
-  (with-temp-buffer
-    (emacs-lisp-mode)
-    (insert "(cl-defun foo (&key a (b 27)) \"Return :A+:B.\")")
-    (checkdoc-defun)))
-
-(ert-deftest checkdoc-cl-defun-with-allow-other-keys-ok ()
-  "Checkdoc should be happy with a cl-defun using &allow-other-keys."
-  (with-temp-buffer
-    (emacs-lisp-mode)
-    (insert "(cl-defun foo (&key a &allow-other-keys) \"Return :A.\")")
-    (checkdoc-defun)))
-
-(ert-deftest checkdoc-cl-defun-with-default-optional-value-ok ()
-  "Checkdoc should be happy with a cl-defun using default values for optional 
args."
+(ert-deftest checkdoc-cl-defmethod-qualified-ok ()
+  "Checkdoc should be happy with a `cl-defmethod' using qualifiers."
   (with-temp-buffer
     (emacs-lisp-mode)
-    ;; B is optional and equals 1+a if not provided. HAS-BS is non-nil
-    ;; if B was provided in the call:
-    (insert "(cl-defun foo (a &optional (b (1+ a) has-bs)) \"Return A + B.\")")
+    (insert "(cl-defmethod test :around ((a (eql smthg))) \"Return A.\")")
     (checkdoc-defun)))
 
-(ert-deftest checkdoc-cl-defun-with-destructuring-ok ()
-  "Checkdoc should be happy with a cl-defun destructuring its arguments."
+(ert-deftest checkdoc-cl-defmethod-with-extra-qualifier-ok ()
+  "Checkdoc should be happy with a :extra qualified `cl-defmethod'."
   (with-temp-buffer
     (emacs-lisp-mode)
-    (insert "(cl-defun foo ((a b &optional c) d) \"Return A+B+C+D.\")")
-    (checkdoc-defun)))
+    (insert "(cl-defmethod foo :extra \"foo\" ((a (eql smthg))) \"Return 
A.\")")
+    (checkdoc-defun))
 
-(ert-deftest checkdoc-cl-defmethod-ok ()
-  "Checkdoc should be happy with a simple correct cl-defmethod."
   (with-temp-buffer
     (emacs-lisp-mode)
-    (insert "(cl-defmethod foo (a) \"Return A.\")")
+    (insert
+     "(cl-defmethod foo :extra \"foo\" :after ((a (eql smthg))) \"Return 
A.\")")
     (checkdoc-defun)))
 
-(ert-deftest checkdoc-cl-defmethod-with-types-ok ()
-  "Checkdoc should be happy with a cl-defmethod using types."
+(ert-deftest checkdoc-cl-defmethod-with-extra-qualifier-and-nil-args-ok ()
+  "Checkdoc should be happy with a 0-arity :extra qualified `cl-defmethod'."
   (with-temp-buffer
     (emacs-lisp-mode)
-    ;; this method matches if A is the symbol `smthg' and if b is a list:
-    (insert "(cl-defmethod foo ((a (eql smthg)) (b list)) \"Return A+B.\")")
+    (insert "(cl-defmethod foo :extra \"foo\" () \"Return A.\")")
     (checkdoc-defun)))
 
 (ert-deftest checkdoc-cl-defun-with-key-ok ()
diff --git a/test/lisp/emacs-lisp/cl-generic-tests.el 
b/test/lisp/emacs-lisp/cl-generic-tests.el
index 4a01623..9312fb4 100644
--- a/test/lisp/emacs-lisp/cl-generic-tests.el
+++ b/test/lisp/emacs-lisp/cl-generic-tests.el
@@ -269,9 +269,7 @@ Edebug symbols (Bug#42672)."
               (when (memq name instrumented-names)
                 (error "Duplicate definition of `%s'" name))
               (push name instrumented-names)
-              (edebug-new-definition name)))
-           ;; Make generated symbols reproducible.
-           (gensym-counter 10000))
+              (edebug-new-definition name))))
       (eval-buffer)
       (should (equal
                (reverse instrumented-names)
@@ -280,11 +278,11 @@ Edebug symbols (Bug#42672)."
                ;; FIXME: We'd rather have names such as
                ;; `cl-defgeneric/edebug/method/1 ((_ number))', but
                ;; that requires further changes to Edebug.
-               (list (intern "cl-generic-:method@10000 ((_ number))")
-                     (intern "cl-generic-:method@10001 ((_ string))")
-                     (intern "cl-generic-:method@10002 :around ((_ number))")
+               (list (intern "cl-defgeneric/edebug/method/1 (number)")
+                     (intern "cl-defgeneric/edebug/method/1 (string)")
+                     (intern "cl-defgeneric/edebug/method/1 :around (number)")
                      'cl-defgeneric/edebug/method/1
-                     (intern "cl-generic-:method@10003 ((_ number))")
+                     (intern "cl-defgeneric/edebug/method/2 (number)")
                      'cl-defgeneric/edebug/method/2))))))
 
 (provide 'cl-generic-tests)
diff --git a/test/lisp/emacs-lisp/cl-macs-tests.el 
b/test/lisp/emacs-lisp/cl-macs-tests.el
index 2e5f302..dd64876 100644
--- a/test/lisp/emacs-lisp/cl-macs-tests.el
+++ b/test/lisp/emacs-lisp/cl-macs-tests.el
@@ -617,11 +617,26 @@ collection clause."
   (cl-labels ((len (xs) (if xs (1+ (len (cdr xs))) 0)))
     (should (equal (len (make-list 42 t)) 42)))
 
-  ;; Simple tail-recursive function.
-  (cl-labels ((len (xs n) (if xs (len (cdr xs) (1+ n)) n)))
-    (should (equal (len (make-list 42 t) 0) 42))
-    ;; Should not bump into stack depth limits.
-    (should (equal (len (make-list 42000 t) 0) 42000)))
+  (let ((list-42 (make-list 42 t))
+        (list-42k (make-list 42000 t)))
+
+    (cl-labels
+        ;; Simple tail-recursive function.
+        ((len (xs n) (if xs (len (cdr xs) (1+ n)) n))
+         ;; Slightly obfuscated version to exercise tail calls from
+         ;; `let', `progn', `and' and `or'.
+         (len2 (xs n) (or (and (not xs) n)
+                          (let (n1)
+                            (and xs
+                                 (progn (setq n1 (1+ n))
+                                        (len2 (cdr xs) n1)))))))
+      (should (equal (len nil 0) 0))
+      (should (equal (len2 nil 0) 0))
+      (should (equal (len list-42 0) 42))
+      (should (equal (len2 list-42 0) 42))
+      ;; Should not bump into stack depth limits.
+      (should (equal (len list-42k 0) 42000))
+      (should (equal (len2 list-42k 0) 42000))))
 
   ;; Check that non-recursive functions are handled more efficiently.
   (should (pcase (macroexpand '(cl-labels ((f (x) (+ x 1))) (f 5)))
@@ -633,4 +648,9 @@ collection clause."
                      #'len))
             (`(function (lambda (,_ ,_) . ,_)) t))))
 
+(ert-deftest cl-macs--progv ()
+  (should (= (cl-progv '(test test) '(1 2) test) 2))
+  (should (equal (cl-progv '(test1 test2) '(1 2) (list test1 test2))
+                 '(1 2))))
+
 ;;; cl-macs-tests.el ends here
diff --git a/test/lisp/emacs-lisp/edebug-resources/edebug-test-code.el 
b/test/lisp/emacs-lisp/edebug-resources/edebug-test-code.el
index f8ca39c..9257f16 100644
--- a/test/lisp/emacs-lisp/edebug-resources/edebug-test-code.el
+++ b/test/lisp/emacs-lisp/edebug-resources/edebug-test-code.el
@@ -62,12 +62,12 @@
 
 (defun edebug-test-code-format-vector-node (node)
   !start!(concat "["
-          (apply 'concat (mapcar 'edebug-test-code-format-node node))!apply!
+          (apply #'concat (mapcar #'edebug-test-code-format-node node))!apply!
           "]"))
 
 (defun edebug-test-code-format-list-node (node)
   !start!(concat "{"
-          (apply 'concat (mapcar 'edebug-test-code-format-node node))!apply!
+          (apply #'concat (mapcar #'edebug-test-code-format-node node))!apply!
           "}"))
 
 (defun edebug-test-code-format-node (node)
@@ -137,5 +137,21 @@
                                ,(cons func args))))
     (wrap + 1 x)))
 
+(defun edebug-test-code-cl-flet1 ()
+  (cl-flet
+      ;; This `&rest' sexp head should not collide with
+      ;; the Edebug spec elem of the same name.
+      ((f (&rest x) x)
+       (gate (x) (+ x 5)))
+    ;; This call to `gate' shouldn't collide with the Edebug spec elem
+    ;; of the same name.
+    (message "Hi %s" (gate 7))))
+
+(defun edebug-test-code-use-gv-expander (x)
+  (declare (gv-expander
+            (lambda (do)
+              (funcall do `(car ,x) (lambda (v) `(setcar ,x ,v))))))
+  (car x))
+
 (provide 'edebug-test-code)
 ;;; edebug-test-code.el ends here
diff --git a/test/lisp/emacs-lisp/edebug-tests.el 
b/test/lisp/emacs-lisp/edebug-tests.el
index 6a6080d..dcb261c 100644
--- a/test/lisp/emacs-lisp/edebug-tests.el
+++ b/test/lisp/emacs-lisp/edebug-tests.el
@@ -219,16 +219,16 @@ index."
     (with-current-buffer (find-file-noselect edebug-tests-temp-file)
       (setq saved-local-map overriding-local-map)
       (setq overriding-local-map edebug-tests-keymap)
-      (add-hook 'post-command-hook 'edebug-tests-post-command))
+      (add-hook 'post-command-hook #'edebug-tests-post-command))
     (advice-add 'exit-recursive-edit
-                :around 'edebug-tests-preserve-keyboard-macro-state)
+                :around #'edebug-tests-preserve-keyboard-macro-state)
     (unwind-protect
         (kmacro-call-macro nil nil nil kbdmac)
       (advice-remove 'exit-recursive-edit
-                     'edebug-tests-preserve-keyboard-macro-state)
+                     #'edebug-tests-preserve-keyboard-macro-state)
       (with-current-buffer (find-file-noselect edebug-tests-temp-file)
         (setq overriding-local-map saved-local-map)
-        (remove-hook 'post-command-hook 'edebug-tests-post-command)))))
+        (remove-hook 'post-command-hook #'edebug-tests-post-command)))))
 
 (defun edebug-tests-preserve-keyboard-macro-state (orig &rest args)
   "Call ORIG with ARGS preserving the value of `executing-kbd-macro'.
@@ -857,12 +857,14 @@ test and possibly others should be updated."
 (ert-deftest edebug-tests-trivial-backquote ()
   "Edebug can instrument a trivial backquote expression (Bug#23651)."
   (edebug-tests-with-normal-env
-   (read-only-mode -1)
-   (delete-region (point-min) (point-max))
-   (insert  "`1")
-   (read-only-mode)
+   (let ((inhibit-read-only t))
+     (delete-region (point-min) (point-max))
+     (insert  "`1"))
    (edebug-eval-defun nil)
-   (should (string-match-p (regexp-quote "1 (#o1, #x1, ?\\C-a)")
+   ;; `eval-defun' outputs its message to the echo area in a rather
+   ;; funny way, so the "1" and the " (#o1, #x1, ?\C-a)" end up placed
+   ;; there in separate pieces (via `print' rather than via `message').
+   (should (string-match-p (regexp-quote " (#o1, #x1, ?\\C-a)")
                            edebug-tests-messages))
    (setq edebug-tests-messages "")
 
@@ -912,13 +914,17 @@ test and possibly others should be updated."
 (ert-deftest edebug-tests-cl-macrolet ()
   "Edebug can instrument `cl-macrolet' expressions. (Bug#29919)"
   (edebug-tests-with-normal-env
-   (edebug-tests-setup-@ "use-cl-macrolet" '(10) t)
+   (edebug-tests-locate-def "use-cl-macrolet")
    (edebug-tests-run-kbd-macro
-    "@ SPC SPC"
+    "C-u C-M-x SPC"
     (edebug-tests-should-be-at "use-cl-macrolet" "func")
-    (edebug-tests-should-match-result-in-messages "+")
-    "g"
-    (should (equal edebug-tests-@-result "The result of applying + to (1 x) is 
11")))))
+    (edebug-tests-should-match-result-in-messages "+"))
+   (let ((edebug-initial-mode 'Go-nonstop))
+     (edebug-tests-setup-@ "use-cl-macrolet" '(10) t))
+   (edebug-tests-run-kbd-macro
+    "@ SPC g"
+    (should (equal edebug-tests-@-result "The result of applying + to (1 x) is 
11"))
+     )))
 
 (ert-deftest edebug-tests-backtrace-goto-source ()
   "Edebug can jump to instrumented source from its *Edebug-Backtrace* buffer."
@@ -951,8 +957,41 @@ primary ones (Bug#42671)."
       (should
        (equal
         defined-symbols
-        (list (intern "edebug-cl-defmethod-qualifier :around ((_ number))")
-              (intern "edebug-cl-defmethod-qualifier ((_ number))")))))))
+        (list (intern "edebug-cl-defmethod-qualifier :around (number)")
+              (intern "edebug-cl-defmethod-qualifier (number)")))))))
+
+(ert-deftest edebug-tests--conflicting-internal-names ()
+  "Check conflicts between form's head symbols and Edebug spec elements."
+  (edebug-tests-with-normal-env
+   (edebug-tests-setup-@ "cl-flet1" '(10) t)))
+
+(ert-deftest edebug-tests-gv-expander ()
+  "Edebug can instrument `gv-expander' expressions."
+  (edebug-tests-with-normal-env
+   (edebug-tests-setup-@ "use-gv-expander" nil t)
+   (should (equal
+            (catch 'text
+              (run-at-time 0 nil
+                           (lambda () (throw 'text (buffer-substring (point) 
(+ (point) 5)))))
+              (eval '(setf (edebug-test-code-use-gv-expander (cons 'a 'b)) 3) 
t))
+            "(func"))))
+
+(defun edebug-tests--read (form spec)
+  (with-temp-buffer
+    (print form (current-buffer))
+    (goto-char (point-min))
+    (cl-letf ((edebug-all-forms t)
+              ((get (car form) 'edebug-form-spec) spec))
+      (edebug--read nil (current-buffer)))))
+
+(ert-deftest edebug-tests--&rest-behavior ()
+  ;; `&rest' is documented to allow the last "repetition" to be aborted early.
+  (should (edebug-tests--read '(dummy x 1 y 2 z)
+                              '(&rest symbolp integerp)))
+  ;; `&rest' should notice here that the "symbolp integerp" sequence
+  ;; is not respected.
+  (should-error (edebug-tests--read '(dummy x 1 2 y)
+                                    '(&rest symbolp integerp))))
 
 (ert-deftest edebug-tests-cl-flet ()
   "Check that Edebug can instrument `cl-flet' forms without name
@@ -976,23 +1015,19 @@ clashes (Bug#41853)."
            ;; Make generated symbols reproducible.
            (gensym-counter 10000))
       (eval-buffer)
-      (should (equal (reverse instrumented-names)
+      ;; Use `format' so as to throw away differences due to
+      ;; interned/uninterned symbols.
+      (should (equal (format "%s" (reverse instrumented-names))
                      ;; The outer definitions come after the inner
                      ;; ones because their body ends later.
-                     ;; FIXME: There are twice as many inner
-                     ;; definitions as expected due to Bug#41988.
-                     ;; Once that bug is fixed, remove the duplicates.
                      ;; FIXME: We'd rather have names such as
                      ;; `edebug-tests-cl-flet-1@inner@cl-flet@10000',
                      ;; but that requires further changes to Edebug.
-                     '(inner@cl-flet@10000
-                       inner@cl-flet@10001
-                       inner@cl-flet@10002
-                       inner@cl-flet@10003
-                       edebug-tests-cl-flet-1
-                       inner@cl-flet@10004
-                       inner@cl-flet@10005
-                       edebug-tests-cl-flet-2))))))
+                     (format "%s" '(inner@cl-flet@10000
+                                    inner@cl-flet@10001
+                                    edebug-tests-cl-flet-1
+                                    inner@cl-flet@10002
+                                    edebug-tests-cl-flet-2)))))))
 
 (ert-deftest edebug-tests-duplicate-symbol-backtrack ()
   "Check that Edebug doesn't create duplicate symbols when
diff --git a/test/lisp/emacs-lisp/ert-tests.el 
b/test/lisp/emacs-lisp/ert-tests.el
index bdacb08..5c96961 100644
--- a/test/lisp/emacs-lisp/ert-tests.el
+++ b/test/lisp/emacs-lisp/ert-tests.el
@@ -814,7 +814,7 @@ This macro is used to test if macroexpansion in `should' 
works."
                   :body (lambda () (should (integerp (ert-fail "Boo"))))))))
     (should (ert-test-failed-p result))
     (should (equal (ert-test-failed-condition result)
-                   '(ert-test-failed ("Boo"))))))
+                   '(ert-test-failed "Boo")))))
 
 
 (provide 'ert-tests)
diff --git a/test/lisp/emacs-lisp/generator-tests.el 
b/test/lisp/emacs-lisp/generator-tests.el
index ffcd16a..a1b9f64 100644
--- a/test/lisp/emacs-lisp/generator-tests.el
+++ b/test/lisp/emacs-lisp/generator-tests.el
@@ -45,6 +45,7 @@
 BODY twice: once using ordinary `eval' and once using
 lambda-generators.  The test ensures that the two forms produce
 identical output."
+  (declare (indent 1))
   `(progn
      (ert-deftest ,name ()
        (should
@@ -62,8 +63,6 @@ identical output."
            (let ((cps-inhibit-atomic-optimization t))
              (iter-lambda () (iter-yield (progn ,@body)))))))))))
 
-(put 'cps-testcase 'lisp-indent-function 1)
-
 (defvar *cps-test-i* nil)
 (defun cps-get-test-i ()
   *cps-test-i*)
diff --git a/test/lisp/emacs-lisp/macroexp-resources/m1.el 
b/test/lisp/emacs-lisp/macroexp-resources/m1.el
new file mode 100644
index 0000000..96b5f70
--- /dev/null
+++ b/test/lisp/emacs-lisp/macroexp-resources/m1.el
@@ -0,0 +1,36 @@
+;;; m1.el --- Some sample code for macroexp-tests    -*- lexical-binding: t; 
-*-
+
+;; Copyright (C) 2021  Free Software Foundation, Inc.
+
+;; Author: Stefan Monnier <monnier@iro.umontreal.ca>
+;; Keywords:
+
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program.  If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;;
+
+;;; Code:
+
+(defconst macroexp--m1-tests-filename (macroexp-file-name))
+
+(eval-when-compile
+  (defconst macroexp--m1-tests-comp-filename (macroexp-file-name)))
+
+(defun macroexp--m1-tests-file-name ()
+  (macroexp--test-get-file-name))
+
+(provide 'm1)
+;;; m1.el ends here
diff --git a/test/lisp/emacs-lisp/macroexp-resources/m2.el 
b/test/lisp/emacs-lisp/macroexp-resources/m2.el
new file mode 100644
index 0000000..4f2b96d
--- /dev/null
+++ b/test/lisp/emacs-lisp/macroexp-resources/m2.el
@@ -0,0 +1,33 @@
+;;; m2.el --- More sample code for macroexp-tests    -*- lexical-binding: t; 
-*-
+
+;; Copyright (C) 2021  Free Software Foundation, Inc.
+
+;; Author: Stefan Monnier <monnier@iro.umontreal.ca>
+;; Keywords:
+
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program.  If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;;
+
+;;; Code:
+
+(defconst macroexp--m2-tests-filename (macroexp-file-name))
+
+(byte-compile-file (expand-file-name
+                    "m1.el" (file-name-directory macroexp--m2-tests-filename)))
+
+(provide 'm2)
+;;; m2.el ends here
diff --git a/test/lisp/emacs-lisp/macroexp-tests.el 
b/test/lisp/emacs-lisp/macroexp-tests.el
new file mode 100644
index 0000000..89d3882
--- /dev/null
+++ b/test/lisp/emacs-lisp/macroexp-tests.el
@@ -0,0 +1,72 @@
+;;; macroexp-tests.el --- Tests for macroexp.el      -*- lexical-binding: t; 
-*-
+
+;; Copyright (C) 2021  Free Software Foundation, Inc.
+
+;; Author: Stefan Monnier <monnier@iro.umontreal.ca>
+;; Keywords:
+
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program.  If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;;
+
+;;; Code:
+
+(ert-deftest macroexp--tests-fgrep ()
+  (should (equal (macroexp--fgrep '((x) (y)) '([x] z ((u))))
+                 '((x))))
+  (should (equal (macroexp--fgrep '((x) (y)) '#2=([y] ((y #2#))))
+                 '((y))))
+  (should (equal (macroexp--fgrep '((x) (y)) '#2=([r] ((a x)) a b c d . #2#))
+                 '((x)))))
+
+(defconst macroexp--tests-filename (macroexp-file-name))
+
+(defmacro macroexp--test-get-file-name () (macroexp-file-name))
+
+(ert-deftest macroexp--tests-file-name ()
+  (should (string-match
+           "\\`macroexp-tests.elc?\\'"
+           (file-name-nondirectory macroexp--tests-filename)))
+  (let ((rsrc-dir (expand-file-name
+                   "macroexp-resources"
+                   (file-name-directory macroexp--tests-filename))))
+    (with-current-buffer
+        (find-file-noselect (expand-file-name "m1.el" rsrc-dir))
+      (defvar macroexp--m1-tests-filename)
+      (declare-function macroexp--m1-tests-file-name "m1" ())
+      ;; `macroexp-file-name' should work with `eval-buffer'.
+      (eval-buffer)
+      (should (equal "m1.el"
+                     (file-name-nondirectory macroexp--m1-tests-filename)))
+      (should (equal "m1.el"
+                     (file-name-nondirectory (macroexp--m1-tests-file-name))))
+      (search-forward "macroexp--m1-tests-filename")
+      (makunbound 'macroexp--m1-tests-filename)
+      ;; `macroexp-file-name' should also work with `eval-defun'.
+      (eval-defun nil)
+      (should (equal "m1.el"
+                     (file-name-nondirectory macroexp--m1-tests-filename))))
+
+    ;; Test the case where we load a file which byte-compiles another.
+    (defvar macroexp--m1-tests-comp-filename)
+    (makunbound 'macroexp--m1-tests-comp-filename)
+    (load (expand-file-name "m2.el" rsrc-dir))
+    (should (equal "m1.el"
+                   (file-name-nondirectory 
macroexp--m1-tests-comp-filename)))))
+
+
+(provide 'macroexp-tests)
+;;; macroexp-tests.el ends here
diff --git a/test/lisp/emacs-lisp/map-tests.el 
b/test/lisp/emacs-lisp/map-tests.el
index 9a2cd42..67666d8 100644
--- a/test/lisp/emacs-lisp/map-tests.el
+++ b/test/lisp/emacs-lisp/map-tests.el
@@ -22,7 +22,7 @@
 
 ;;; Commentary:
 
-;; Tests for map.el
+;; Tests for map.el.
 
 ;;; Code:
 
@@ -30,12 +30,10 @@
 (require 'map)
 
 (defmacro with-maps-do (var &rest body)
-  "Successively bind VAR to an alist, vector and hash-table.
+  "Successively bind VAR to an alist, plist, vector, and hash-table.
 Each map is built from the following alist data:
-'((0 . 3) (1 . 4) (2 . 5)).
-Evaluate BODY for each created map.
-
-\(fn (var map) body)"
+  \\='((0 . 3) (1 . 4) (2 . 5)).
+Evaluate BODY for each created map."
   (declare (indent 1) (debug (symbolp body)))
   (let ((alist (make-symbol "alist"))
         (plist (make-symbol "plist"))
@@ -53,43 +51,62 @@ Evaluate BODY for each created map.
       (dolist (,var (list ,alist ,plist ,vec ,ht))
         ,@body))))
 
+(defmacro with-empty-maps-do (var &rest body)
+  "Like `with-maps-do', but with empty maps."
+  (declare (indent 1) (debug (symbolp body)))
+  `(dolist (,var (list (list) (vector) (make-hash-table)))
+     ,@body))
+
+(ert-deftest test-map-plist-p ()
+  "Test `map--plist-p'."
+  (with-empty-maps-do map
+    (should-not (map--plist-p map)))
+  (should-not (map--plist-p ""))
+  (should-not (map--plist-p '((()))))
+  (should (map--plist-p '(:a)))
+  (should (map--plist-p '(a)))
+  (should (map--plist-p '(nil)))
+  (should (map--plist-p '(""))))
+
 (ert-deftest test-map-elt ()
   (with-maps-do map
     (should (= 3 (map-elt map 0)))
     (should (= 4 (map-elt map 1)))
     (should (= 5 (map-elt map 2)))
-    (should (null (map-elt map -1)))
-    (should (null (map-elt map 4)))))
+    (should-not (map-elt map -1))
+    (should-not (map-elt map 4))
+    (should-not (map-elt map 0.1))))
 
 (ert-deftest test-map-elt-default ()
   (with-maps-do map
-    (should (= 5 (map-elt map 7 5)))))
+    (should (= 5 (map-elt map 7 5)))
+    (should (= 5 (map-elt map 0.1 5))))
+  (with-empty-maps-do map
+    (should (= 5 (map-elt map 0 5)))))
 
 (ert-deftest test-map-elt-testfn ()
   (let ((map (list (cons "a" 1) (cons "b" 2)))
         ;; Make sure to use a non-eq "a", even when compiled.
         (noneq-key (string ?a)))
     (should-not (map-elt map noneq-key))
-    (should (map-elt map noneq-key nil 'equal))))
+    (should (map-elt map noneq-key nil #'equal))))
 
 (ert-deftest test-map-elt-with-nil-value ()
-  (should (null (map-elt '((a . 1)
-                           (b))
-                         'b
-                         '2))))
+  (should-not (map-elt '((a . 1) (b)) 'b 2)))
 
 (ert-deftest test-map-put! ()
   (with-maps-do map
     (setf (map-elt map 2) 'hello)
     (should (eq (map-elt map 2) 'hello)))
   (with-maps-do map
-    (map-put map 2 'hello)
+    (with-suppressed-warnings ((obsolete map-put))
+      (map-put map 2 'hello))
     (should (eq (map-elt map 2) 'hello)))
   (with-maps-do map
     (map-put! map 2 'hello)
     (should (eq (map-elt map 2) 'hello))
     (if (not (or (hash-table-p map)
-                 (and (listp map) (not (listp (car map)))))) ;plist!
+                 (map--plist-p map)))
         (should-error (map-put! map 5 'value)
                       ;; For vectors, it could arguably signal
                       ;; map-not-inplace as well, but it currently doesn't.
@@ -97,49 +114,88 @@ Evaluate BODY for each created map.
                                 'map-not-inplace
                               'error))
       (map-put! map 5 'value)
-      (should (eq (map-elt map 5) 'value))))
-  (let ((ht (make-hash-table)))
-    (setf (map-elt ht 2) 'a)
-    (should (eq (map-elt ht 2)
-                'a)))
-  (let ((alist '((0 . a) (1 . b) (2 . c))))
-    (setf (map-elt alist 2) 'a)
-    (should (eq (map-elt alist 2)
-                'a)))
-  (let ((vec [3 4 5]))
-    (should-error (setf (map-elt vec 3) 6))))
+      (should (eq (map-elt map 5) 'value)))))
+
+(ert-deftest test-map-put!-new-keys ()
+  "Test `map-put!' with new keys."
+  (with-maps-do map
+    (let ((size (map-length map)))
+      (if (arrayp map)
+          (progn
+            (should-error (setf (map-elt map 'k) 'v))
+            (should-error (setf (map-elt map size) 'v)))
+        (setf (map-elt map 'k) 'v)
+        (should (eq (map-elt map 'k) 'v))
+        (setf (map-elt map size) 'v)
+        (should (eq (map-elt map size) 'v))))))
 
 (ert-deftest test-map-put-alist-new-key ()
   "Regression test for Bug#23105."
-  (let ((alist '((0 . a))))
-    (map-put alist 2 'b)
-    (should (eq (map-elt alist 2)
-                'b))))
+  (let ((alist (list (cons 0 'a))))
+    (with-suppressed-warnings ((obsolete map-put))
+      (map-put alist 2 'b))
+    (should (eq (map-elt alist 2) 'b))))
 
 (ert-deftest test-map-put-testfn-alist ()
   (let ((alist (list (cons "a" 1) (cons "b" 2)))
         ;; Make sure to use a non-eq "a", even when compiled.
         (noneq-key (string ?a)))
-    (map-put alist noneq-key 3 #'equal)
-    (should-not (cddr alist))
-    (map-put alist noneq-key 9 #'eql)
-    (should (cddr alist))))
+    (with-suppressed-warnings ((obsolete map-put))
+      (map-put alist noneq-key 3 #'equal)
+      (should-not (cddr alist))
+      (map-put alist noneq-key 9 #'eql)
+      (should (cddr alist)))))
 
 (ert-deftest test-map-put-return-value ()
   (let ((ht (make-hash-table)))
-    (should (eq (map-put ht 'a 'hello) 'hello))))
+    (with-suppressed-warnings ((obsolete map-put))
+      (should (eq (map-put ht 'a 'hello) 'hello)))))
+
+(ert-deftest test-map-insert-empty ()
+  "Test `map-insert' on empty maps."
+  (with-empty-maps-do map
+    (if (arrayp map)
+        (should-error (map-insert map 0 6))
+      (let ((new (map-insert map 0 6)))
+        (should-not (eq map new))
+        (should-not (map-pairs map))
+        (should (= (map-elt new 0) 6))))))
+
+(ert-deftest test-map-insert ()
+  "Test `map-insert'."
+  (with-maps-do map
+    (let ((pairs (map-pairs map))
+          (size (map-length map))
+          (new (map-insert map 0 6)))
+      (should-not (eq map new))
+      (should (equal (map-pairs map) pairs))
+      (should (= (map-elt new 0) 6))
+      (if (arrayp map)
+          (should-error (map-insert map size 7))
+        (setq new (map-insert map size 7))
+        (should-not (eq map new))
+        (should (equal (map-pairs map) pairs))
+        (should (= (map-elt new size) 7))))))
 
 (ert-deftest test-map-delete ()
   (with-maps-do map
-    (map-delete map 1)
-    (should (null (map-elt map 1))))
+    (should (map-elt map 1))
+    (should (eq map (map-delete map 1)))
+    (should-not (map-elt map 1)))
   (with-maps-do map
-    (map-delete map -2)
-    (should (null (map-elt map -2)))))
+    (should-not (map-elt map -2))
+    (should (eq map (map-delete map -2)))
+    (should-not (map-elt map -2)))
+  (with-maps-do map
+    ;; Check for OBOE.
+    (let ((key (map-length map)))
+      (should-not (map-elt map key))
+      (should (eq map (map-delete map key)))
+      (should-not (map-elt map key)))))
 
-(ert-deftest test-map-delete-return-value ()
-  (let ((ht (make-hash-table)))
-    (should (eq (map-delete ht 'a) ht))))
+(ert-deftest test-map-delete-empty ()
+  (with-empty-maps-do map
+    (should (eq map (map-delete map t)))))
 
 (ert-deftest test-map-nested-elt ()
   (let ((vec [a b [c d [e f]]]))
@@ -149,8 +205,9 @@ Evaluate BODY for each created map.
                        (d . 3)
                        (e . ((f . 4)
                              (g . 5))))))))
-    (should (eq (map-nested-elt alist '(b e f))
-                4)))
+    (should (eq (map-nested-elt alist '(b e f)) 4)))
+  (let ((plist '(a 1 b (c 2 d 3 e (f 4 g 5)))))
+    (should (eq (map-nested-elt plist '(b e f)) 4)))
   (let ((ht (make-hash-table)))
     (setf (map-elt ht 'a) 1)
     (setf (map-elt ht 'b) (make-hash-table))
@@ -160,214 +217,238 @@ Evaluate BODY for each created map.
 
 (ert-deftest test-map-nested-elt-default ()
   (let ((vec [a b [c d]]))
-    (should (null (map-nested-elt vec '(2 3))))
-    (should (null (map-nested-elt vec '(2 1 1))))
+    (should-not (map-nested-elt vec '(2 3)))
+    (should-not (map-nested-elt vec '(2 1 1)))
     (should (= 4 (map-nested-elt vec '(2 1 1) 4)))))
 
 (ert-deftest test-mapp ()
-  (should (mapp nil))
-  (should (mapp '((a . b) (c . d))))
-  (should (mapp '(a b c d)))
-  (should (mapp []))
-  (should (mapp [1 2 3]))
-  (should (mapp (make-hash-table)))
+  (with-empty-maps-do map
+    (should (mapp map)))
+  (with-maps-do map
+    (should (mapp map)))
+  (should (mapp ""))
   (should (mapp "hello"))
-  (should (not (mapp 1)))
-  (should (not (mapp 'hello))))
+  (should-not (mapp 1))
+  (should-not (mapp 'hello)))
 
 (ert-deftest test-map-keys ()
   (with-maps-do map
     (should (equal (map-keys map) '(0 1 2))))
-  (should (null (map-keys nil)))
-  (should (null (map-keys []))))
+  (with-empty-maps-do map
+    (should-not (map-keys map))))
 
 (ert-deftest test-map-values ()
   (with-maps-do map
-    (should (equal (map-values map) '(3 4 5)))))
+    (should (equal (map-values map) '(3 4 5))))
+  (with-empty-maps-do map
+    (should-not (map-values map))))
 
 (ert-deftest test-map-pairs ()
   (with-maps-do map
-    (should (equal (map-pairs map) '((0 . 3)
-                                     (1 . 4)
-                                     (2 . 5))))))
+    (should (equal (map-pairs map)
+                   '((0 . 3)
+                     (1 . 4)
+                     (2 . 5)))))
+  (with-empty-maps-do map
+    (should-not (map-pairs map))))
 
 (ert-deftest test-map-length ()
-  (let ((ht (make-hash-table)))
-    (puthash 'a 1 ht)
-    (puthash 'b 2 ht)
-    (puthash 'c 3 ht)
-    (puthash 'd 4 ht)
-    (should (= 0 (map-length nil)))
-    (should (= 0 (map-length [])))
-    (should (= 0 (map-length (make-hash-table))))
-    (should (= 5 (map-length [0 1 2 3 4])))
-    (should (= 2 (map-length '((a . 1) (b . 2)))))
-    (should (= 4 (map-length ht)))))
+  (with-empty-maps-do map
+    (should (zerop (map-length map))))
+  (with-maps-do map
+    (should (= 3 (map-length map))))
+  (should (= 1 (map-length '(nil 1))))
+  (should (= 2 (map-length '(nil 1 t 2))))
+  (should (= 2 (map-length '((a . 1) (b . 2)))))
+  (should (= 5 (map-length [0 1 2 3 4])))
+  (should (= 4 (map-length #s(hash-table data (a 1 b 2 c 3 d 4))))))
 
 (ert-deftest test-map-copy ()
   (with-maps-do map
     (let ((copy (map-copy map)))
-      (should (equal (map-keys map) (map-keys copy)))
-      (should (equal (map-values map) (map-values copy)))
-      (should (not (eq map copy))))))
+      (should (equal (map-pairs map) (map-pairs copy)))
+      (should-not (eq map copy))
+      (map-put! map 0 0)
+      (should-not (equal (map-pairs map) (map-pairs copy)))))
+  (with-empty-maps-do map
+    (should-not (map-pairs (map-copy map)))))
+
+(ert-deftest test-map-copy-alist ()
+  "Test use of `copy-alist' for alists."
+  (let* ((cons (list 'a 1 2))
+         (alist (list cons))
+         (copy (map-copy alist)))
+    (setcar cons 'b)
+    (should (equal alist '((b 1 2))))
+    (should (equal copy '((a 1 2))))
+    (setcar (cdr cons) 0)
+    (should (equal alist '((b 0 2))))
+    (should (equal copy '((a 0 2))))
+    (setcdr cons 3)
+    (should (equal alist '((b . 3))))
+    (should (equal copy '((a 0 2))))))
 
 (ert-deftest test-map-apply ()
-  (with-maps-do map
-    (should (equal (map-apply (lambda (k v) (cons (int-to-string k) v))
-                              map)
-                   '(("0" . 3) ("1" . 4) ("2" . 5)))))
-  (let ((vec [a b c]))
-    (should (equal (map-apply (lambda (k v) (cons (1+ k) v))
-                              vec)
-                   '((1 . a)
-                     (2 . b)
-                     (3 . c))))))
+  (let ((fn (lambda (k v) (cons (number-to-string k) v))))
+    (with-maps-do map
+      (should (equal (map-apply fn map)
+                     '(("0" . 3) ("1" . 4) ("2" . 5)))))
+    (with-empty-maps-do map
+      (should-not (map-apply fn map)))))
 
 (ert-deftest test-map-do ()
-  (with-maps-do map
-    (let ((result nil))
-      (map-do (lambda (k v)
-                (push (list (int-to-string k) v) result))
-              map)
-      (should (equal result '(("2" 5) ("1" 4) ("0" 3)))))))
+  (let* (res
+         (fn (lambda (k v)
+               (push (list (number-to-string k) v) res))))
+    (with-empty-maps-do map
+      (should-not (map-do fn map))
+      (should-not res))
+    (with-maps-do map
+      (setq res nil)
+      (should-not (map-do fn map))
+      (should (equal res '(("2" 5) ("1" 4) ("0" 3)))))))
 
 (ert-deftest test-map-keys-apply ()
   (with-maps-do map
-    (should (equal (map-keys-apply (lambda (k) (int-to-string k))
-                                   map)
-                   '("0" "1" "2"))))
-  (let ((vec [a b c]))
-    (should (equal (map-keys-apply (lambda (k) (1+ k))
-                                   vec)
-                   '(1 2 3)))))
+    (should (equal (map-keys-apply #'1+ map) '(1 2 3))))
+  (with-empty-maps-do map
+    (let (ks)
+      (should-not (map-keys-apply (lambda (k) (push k ks)) map))
+      (should-not ks))))
 
 (ert-deftest test-map-values-apply ()
   (with-maps-do map
-    (should (equal (map-values-apply (lambda (v) (1+ v))
-                                     map)
-                   '(4 5 6))))
-  (let ((vec [a b c]))
-    (should (equal (map-values-apply (lambda (v) (symbol-name v))
-                                     vec)
-                   '("a" "b" "c")))))
+    (should (equal (map-values-apply #'1+ map) '(4 5 6))))
+  (with-empty-maps-do map
+    (let (vs)
+      (should-not (map-values-apply (lambda (v) (push v vs)) map))
+      (should-not vs))))
 
 (ert-deftest test-map-filter ()
   (with-maps-do map
-    (should (equal (map-keys (map-filter (lambda (_k v)
-                                           (<= 4 v))
-                                         map))
-                   '(1 2)))
-    (should (null (map-filter (lambda (k _v)
-                                (eq 'd k))
-                              map))))
-  (should (null (map-filter (lambda (_k v)
-                              (eq 3 v))
-                            [1 2 4 5])))
-  (should (equal (map-filter (lambda (k _v)
-                               (eq 3 k))
-                             [1 2 4 5])
-                 '((3 . 5)))))
+    (should (equal (map-filter (lambda (_k v) (> v 3)) map)
+                   '((1 . 4) (2 . 5))))
+    (should (equal (map-filter #'always map) (map-pairs map)))
+    (should-not (map-filter #'ignore map)))
+  (with-empty-maps-do map
+    (should-not (map-filter #'always map))
+    (should-not (map-filter #'ignore map))))
 
 (ert-deftest test-map-remove ()
   (with-maps-do map
-    (should (equal (map-keys (map-remove (lambda (_k v)
-                                           (>= v 4))
-                                         map))
-                   '(0)))
-    (should (equal (map-keys (map-remove (lambda (k _v)
-                                           (eq 'd k))
-                                         map))
-                   (map-keys map))))
-  (should (equal (map-remove (lambda (_k v)
-                               (eq 3 v))
-                             [1 2 4 5])
-                 '((0 . 1)
-                   (1 . 2)
-                   (2 . 4)
-                   (3 . 5))))
-  (should (null (map-remove (lambda (k _v)
-                              (>= k 0))
-                            [1 2 4 5]))))
+    (should (equal (map-remove (lambda (_k v) (> v 3)) map)
+                   '((0 . 3))))
+    (should (equal (map-remove #'ignore map) (map-pairs map)))
+    (should-not (map-remove #'always map)))
+  (with-empty-maps-do map
+    (should-not (map-remove #'always map))
+    (should-not (map-remove #'ignore map))))
 
 (ert-deftest test-map-empty-p ()
-  (should (map-empty-p nil))
-  (should (not (map-empty-p '((a . b) (c . d)))))
-  (should (map-empty-p []))
-  (should (not (map-empty-p [1 2 3])))
-  (should (map-empty-p (make-hash-table)))
-  (should (not (map-empty-p "hello")))
-  (should (map-empty-p "")))
+  (with-empty-maps-do map
+    (should (map-empty-p map)))
+  (should (map-empty-p ""))
+  (should-not (map-empty-p '((a . b) (c . d))))
+  (should-not (map-empty-p [1 2 3]))
+  (should-not (map-empty-p "hello")))
 
 (ert-deftest test-map-contains-key ()
-  (should (map-contains-key '((a . 1) (b . 2)) 'a))
-  (should (not (map-contains-key '((a . 1) (b . 2)) 'c)))
-  (should (map-contains-key '(("a" . 1)) "a"))
-  (should (not (map-contains-key '(("a" . 1)) "a" #'eq)))
-  (should (map-contains-key [a b c] 2))
-  (should (not (map-contains-key [a b c] 3))))
+  (with-empty-maps-do map
+    (should-not (map-contains-key map -1))
+    (should-not (map-contains-key map 0))
+    (should-not (map-contains-key map 1))
+    (should-not (map-contains-key map (map-length map))))
+  (with-maps-do map
+    (should-not (map-contains-key map -1))
+    (should (map-contains-key map 0))
+    (should (map-contains-key map 1))
+    (should-not (map-contains-key map (map-length map)))))
+
+(ert-deftest test-map-contains-key-testfn ()
+  "Test `map-contains-key' under different equalities."
+  (let ((key (string ?a))
+        (plist '("a" 1 a 2))
+        (alist '(("a" . 1) (a . 2))))
+    (should (map-contains-key alist 'a))
+    (should (map-contains-key plist 'a))
+    (should (map-contains-key alist 'a #'eq))
+    (should (map-contains-key plist 'a #'eq))
+    (should (map-contains-key alist key))
+    (should-not (map-contains-key plist key))
+    (should-not (map-contains-key alist key #'eq))
+    (should-not (map-contains-key plist key #'eq))))
 
 (ert-deftest test-map-some ()
   (with-maps-do map
-    (should (map-some (lambda (k _v)
-                        (eq 1 k))
-                      map))
-    (should-not (map-some (lambda (k _v)
-                            (eq 'd k))
-                          map)))
-  (let ((vec [a b c]))
-    (should (map-some (lambda (k _v)
-                        (> k 1))
-                      vec))
-    (should-not (map-some (lambda (k _v)
-                            (> k 3))
-                          vec))))
+    (should (eq (map-some (lambda (k _v) (and (= k 1) 'found)) map)
+                'found))
+    (should-not (map-some #'ignore map)))
+  (with-empty-maps-do map
+    (should-not (map-some #'always map))
+    (should-not (map-some #'ignore map))))
 
 (ert-deftest test-map-every-p ()
   (with-maps-do map
-    (should (map-every-p (lambda (k _v)
-                           k)
-                         map))
-    (should (not (map-every-p (lambda (_k _v)
-                                nil)
-                              map))))
-  (let ((vec [a b c]))
-    (should (map-every-p (lambda (k _v)
-                           (>= k 0))
-                         vec))
-    (should (not (map-every-p (lambda (k _v)
-                                (> k 3))
-                              vec)))))
+    (should (map-every-p #'always map))
+    (should-not (map-every-p #'ignore map))
+    (should-not (map-every-p (lambda (k _v) (zerop k)) map)))
+  (with-empty-maps-do map
+    (should (map-every-p #'always map))
+    (should (map-every-p #'ignore map))
+    (should (map-every-p (lambda (k _v) (zerop k)) map))))
 
 (ert-deftest test-map-into ()
-  (let* ((alist '((a . 1) (b . 2)))
+  (let* ((plist '(a 1 b 2))
+         (alist '((a . 1) (b . 2)))
          (ht (map-into alist 'hash-table))
          (ht2 (map-into alist '(hash-table :test equal))))
     (should (hash-table-p ht))
-    (should (equal (map-into (map-into alist 'hash-table) 'list)
-                   alist))
-    (should (listp (map-into ht 'list)))
-    (should (equal (map-keys (map-into (map-into ht 'list) 'hash-table))
-                   (map-keys ht)))
-    (should (equal (map-values (map-into (map-into ht 'list) 'hash-table))
-                   (map-values ht)))
+    (should (equal (map-into ht 'list) alist))
+    (should (equal (map-pairs (map-into (map-into ht 'list) 'hash-table))
+                   (map-pairs ht)))
     (should (equal (map-into ht 'alist) (map-into ht2 'alist)))
-    (should (eq (hash-table-test ht2) 'equal))
-    (should (null (map-into nil 'list)))
-    (should (map-empty-p (map-into nil 'hash-table)))
-    (should-error (map-into [1 2 3] 'string))))
+    (should (equal (map-into alist 'list) alist))
+    (should (equal (map-into alist 'alist) alist))
+    (should (equal (map-into alist 'plist) plist))
+    (should (equal (map-into plist 'alist) alist))
+    (should (equal (map-into plist 'plist) plist)))
+  (should-error (map-into [1 2 3] 'string) :type 'cl-no-applicable-method))
+
+(ert-deftest test-map-into-hash-test ()
+  "Test `map-into' with different hash-table test functions."
+  (should (eq (hash-table-test (map-into () 'hash-table)) #'equal))
+  (should (eq (hash-table-test (map-into () '(hash-table))) #'eql))
+  (should (eq (hash-table-test (map-into () '(hash-table :test eq))) #'eq))
+  (should (eq (hash-table-test (map-into () '(hash-table :test eql))) #'eql))
+  (should (eq (hash-table-test (map-into () '(hash-table :test equal)))
+              #'equal)))
+
+(ert-deftest test-map-into-empty ()
+  "Test `map-into' with empty maps."
+  (with-empty-maps-do map
+    (should-not (map-into map 'list))
+    (should-not (map-into map 'alist))
+    (should-not (map-into map 'plist))
+    (should (map-empty-p (map-into map 'hash-table)))))
 
 (ert-deftest test-map-let ()
   (map-let (foo bar baz) '((foo . 1) (bar . 2))
     (should (= foo 1))
     (should (= bar 2))
-    (should (null baz)))
+    (should-not baz))
   (map-let (('foo a)
             ('bar b)
             ('baz c))
       '((foo . 1) (bar . 2))
     (should (= a 1))
     (should (= b 2))
-    (should (null c))))
+    (should-not c)))
+
+(ert-deftest test-map-merge ()
+  "Test `map-merge'."
+  (should (equal (map-merge 'list '(a 1) '((b . 2) (c . 3))
+                            #s(hash-table data (c 4)))
+                 '((c . 4) (b . 2) (a . 1)))))
 
 (ert-deftest test-map-merge-with ()
   (should (equal (map-merge-with 'list #'+
@@ -376,6 +457,19 @@ Evaluate BODY for each created map.
                                  '((1 . 1) (2 . 5) (3 . 0)))
                  '((3 . 0) (2 . 9) (1 . 6)))))
 
+(ert-deftest test-map-merge-empty ()
+  "Test merging of empty maps."
+  (should-not (map-merge 'list))
+  (should-not (map-merge 'alist))
+  (should-not (map-merge 'plist))
+  (should-not (map-merge-with 'list #'+))
+  (should-not (map-merge-with 'alist #'+))
+  (should-not (map-merge-with 'plist #'+))
+  (should (map-empty-p (map-merge 'hash-table)))
+  (should (map-empty-p (map-merge-with 'hash-table #'+)))
+  (should-error (map-merge 'array) :type 'cl-no-applicable-method)
+  (should-error (map-merge-with 'array #'+) :type 'cl-no-applicable-method))
+
 (ert-deftest test-map-plist-pcase ()
   (let ((plist '(:one 1 :two 2)))
     (should (equal (pcase-let (((map :one (:two two)) plist))
diff --git a/test/lisp/emacs-lisp/pcase-tests.el 
b/test/lisp/emacs-lisp/pcase-tests.el
index e6f4c09..2120139 100644
--- a/test/lisp/emacs-lisp/pcase-tests.el
+++ b/test/lisp/emacs-lisp/pcase-tests.el
@@ -75,8 +75,29 @@
 (ert-deftest pcase-tests-vectors ()
   (should (equal (pcase [1 2] (`[,x] 1) (`[,x ,y] (+ x y))) 3)))
 
-;; Local Variables:
-;; no-byte-compile: t
-;; End:
+(ert-deftest pcase-tests-bug14773 ()
+  (let ((f (lambda (x)
+             (pcase 'dummy
+               ((and (let var x) (guard var)) 'left)
+               ((and (let var (not x)) (guard var)) 'right)))))
+    (should (equal (funcall f t) 'left))
+    (should (equal (funcall f nil) 'right))))
+
+(ert-deftest pcase-tests-bug46786 ()
+  (let ((self 'outer))
+    (ignore self)
+    (should (equal (cl-macrolet ((show-self () `(list 'self self)))
+                     (pcase-let ((`(,self ,_self2) '(inner "2")))
+                       (show-self)))
+                   '(self inner)))))
+
+(ert-deftest pcase-tests-or-vars ()
+  (let ((f (lambda (v)
+             (pcase v
+               ((or (and 'b1 (let x1 4) (let x2 5))
+                    (and 'b2 (let y1 8) (let y2 9)))
+                (list x1 x2 y1 y2))))))
+    (should (equal (funcall f 'b1) '(4 5 nil nil)))
+    (should (equal (funcall f 'b2) '(nil nil 8 9)))))
 
 ;;; pcase-tests.el ends here.
diff --git a/test/lisp/emacs-lisp/rx-tests.el b/test/lisp/emacs-lisp/rx-tests.el
index 63d7c7b..2dd1bca 100644
--- a/test/lisp/emacs-lisp/rx-tests.el
+++ b/test/lisp/emacs-lisp/rx-tests.el
@@ -156,6 +156,8 @@
           ".....")))
 
 (ert-deftest rx-pcase ()
+  (should (equal (pcase "i18n" ((rx (let x (+ digit))) (list 'ok x)))
+                 '(ok "18")))
   (should (equal (pcase "a 1 2 3 1 1 b"
                    ((rx (let u (+ digit)) space
                         (let v (+ digit)) space
@@ -171,7 +173,23 @@
   (should (equal (pcase "abc"
                    ((rx (? (let x alpha)) (?? (let y alnum)) ?c)
                     (list x y)))
-                 '("a" "b"))))
+                 '("a" "b")))
+  (should (equal (pcase 'not-a-string
+                   ((rx nonl) 'wrong)
+                   (_ 'correct))
+                 'correct))
+  (should (equal (pcase "PQR"
+                   ((and (rx (let a nonl)) (rx ?z))
+                    (list 'one a))
+                   ((rx (let b ?Q))
+                    (list 'two b)))
+                 '(two "Q")))
+  (should (equal (pcase-let (((rx ?B (let z nonl)) "ABC"))
+                   (list 'ok z))
+                 '(ok "C")))
+  (should (equal (pcase-let* (((rx ?E (let z nonl)) "DEF"))
+                   (list 'ok z))
+                 '(ok "F"))))
 
 (ert-deftest rx-kleene ()
   "Test greedy and non-greedy repetition operators."
@@ -388,6 +406,8 @@
 (ert-deftest rx-regexp ()
   (should (equal (rx (regexp "abc") (regex "[de]"))
                  "\\(?:abc\\)[de]"))
+  (should (equal (rx "a" (regexp "$"))
+                 "a\\(?:$\\)"))
   (let ((x "a*"))
     (should (equal (rx (regexp x) "b")
                    "\\(?:a*\\)b"))
diff --git a/test/lisp/erc/erc-tests.el b/test/lisp/erc/erc-tests.el
index 26e14b9..d133972 100644
--- a/test/lisp/erc/erc-tests.el
+++ b/test/lisp/erc/erc-tests.el
@@ -23,6 +23,7 @@
 
 (require 'ert)
 (require 'erc)
+(require 'erc-ring)
 
 (ert-deftest erc--read-time-period ()
   (cl-letf (((symbol-function 'read-string) (lambda (&rest _) "")))
@@ -45,3 +46,66 @@
 
   (cl-letf (((symbol-function 'read-string) (lambda (&rest _) "1d")))
     (should (equal (erc--read-time-period "foo: ") 86400))))
+
+(ert-deftest erc-ring-previous-command-base-case ()
+  (ert-info ("Create ring when nonexistent and do nothing")
+    (let (erc-input-ring
+          erc-input-ring-index)
+      (erc-previous-command)
+      (should (ring-p erc-input-ring))
+      (should (zerop (ring-length erc-input-ring)))
+      (should-not erc-input-ring-index)))
+  (should-not erc-input-ring))
+
+(ert-deftest erc-ring-previous-command ()
+  (with-current-buffer (get-buffer-create "*#fake*")
+    (erc-mode)
+    (insert "\n\n")
+    (setq erc-input-marker (make-marker) ; these are all local
+          erc-insert-marker (make-marker)
+          erc-send-completed-hook nil)
+    (set-marker erc-insert-marker (point-max))
+    (erc-display-prompt)
+    (should (= (point) erc-input-marker))
+    (add-hook 'erc-pre-send-functions #'erc-add-to-input-ring nil t)
+    ;;
+    (cl-letf (((symbol-function 'erc-process-input-line)
+               (lambda (&rest _)
+                 (insert-before-markers
+                  (erc-display-message-highlight 'notice "echo: one\n"))))
+              ((symbol-function 'erc-command-no-process-p)
+               (lambda (&rest _) t)))
+      (ert-info ("Create ring, populate, recall")
+        (insert "/one")
+        (erc-send-current-line)
+        (should (ring-p erc-input-ring))
+        (should (zerop (ring-member erc-input-ring "/one"))) ; equal
+        (should (save-excursion (forward-line -1) (goto-char (point-at-bol))
+                                (looking-at-p "[*]+ echo: one")))
+        (should-not erc-input-ring-index)
+        (erc-bol)
+        (should (looking-at "$"))
+        (erc-previous-command)
+        (erc-bol)
+        (should (looking-at "/one"))
+        (should (zerop erc-input-ring-index)))
+      (ert-info ("Back to one")
+        (should (= (ring-length erc-input-ring) (1+ erc-input-ring-index)))
+        (erc-previous-command)
+        (should-not erc-input-ring-index)
+        (erc-bol)
+        (should (looking-at "$"))
+        (should (equal (ring-ref erc-input-ring 0) "/one")))
+      (ert-info ("Swap input after prompt with previous (#bug46339)")
+        (insert "abc")
+        (erc-previous-command)
+        (should (= 1 erc-input-ring-index))
+        (erc-bol)
+        (should (looking-at "/one"))
+        (should (equal (ring-ref erc-input-ring 0) "abc"))
+        (should (equal (ring-ref erc-input-ring 1) "/one"))
+        (erc-next-command)
+        (erc-bol)
+        (should (looking-at "abc")))))
+  (when noninteractive
+    (kill-buffer "*#fake*")))
diff --git a/test/lisp/filenotify-tests.el b/test/lisp/filenotify-tests.el
index d73b072..4a2f1f9 100644
--- a/test/lisp/filenotify-tests.el
+++ b/test/lisp/filenotify-tests.el
@@ -107,19 +107,19 @@ There are different timeouts for local and remote file 
notification libraries."
    (cond
     ;; gio/gpollfilemonitor.c declares POLL_TIME_SECS 5.  So we must
     ;; wait at least this time in the GPollFileMonitor case.  A
-    ;; similar timeout seems to be needed in the GFamFileMonitor case,
-    ;; at least on cygwin.
-    ((memq (file-notify--test-monitor) '(GFamFileMonitor GPollFileMonitor)) 7)
-    ((string-equal (file-notify--test-library) "gvfs-monitor-dir.exe") 1)
+    ;; similar timeout seems to be needed in the
+    ;; GFam{File,Directory}Monitor case.  So we use a large timeout
+    ;; for any monitor.
+    ((file-notify--test-monitor) 7)
     ((file-remote-p temporary-file-directory) 0.1)
     (t 0.01))))
 
 (defun file-notify--test-timeout ()
   "Timeout to wait for arriving a bunch of events, in seconds."
   (cond
+   ((eq system-type 'cygwin) 10)
    ((file-remote-p temporary-file-directory) 6)
    ((string-equal (file-notify--test-library) "w32notify") 4)
-   ((eq system-type 'cygwin) 6)
    (t 3)))
 
 (defmacro file-notify--test-wait-for-events (timeout until)
@@ -256,24 +256,37 @@ remote host, or nil."
 
 (defun file-notify--test-monitor ()
   "The used monitor for the test, as a symbol.
-This returns only for the local case and gfilenotify; otherwise it is nil.
-`file-notify--test-desc' must be a valid watch descriptor."
+This returns only for (local) gfilenotify or (remote) gio library;
+otherwise it is nil.  `file-notify--test-desc' must be a valid
+watch descriptor."
   ;; We cache the result, because after `file-notify-rm-watch',
   ;; `gfile-monitor-name' does not return a proper result anymore.
-  ;; But we still need this information.
-  ;; So far, we know the monitors GFamFileMonitor, GFenFileMonitor,
-  ;; GInotifyFileMonitor, GKqueueFileMonitor and GPollFileMonitor.
-  (or (cdr (assq file-notify--test-desc file-notify--test-monitors))
-      (progn
-       (add-to-list
-        'file-notify--test-monitors
-        (cons file-notify--test-desc
-              (if (file-remote-p temporary-file-directory)
-                  (tramp-get-connection-property
-                   file-notify--test-desc "gio-file-monitor" nil)
-                (and (functionp 'gfile-monitor-name)
-                     (gfile-monitor-name file-notify--test-desc)))))
-       (cdr (assq file-notify--test-desc file-notify--test-monitors)))))
+  ;; But we still need this information.  So far, we know the monitors
+  ;; GFamFileMonitor (gfilenotify on cygwin), GFamDirectoryMonitor
+  ;; (gfilenotify on Solaris), GInotifyFileMonitor (gfilenotify and
+  ;; gio on GNU/Linux), GKqueueFileMonitor (gfilenotify and gio on
+  ;; FreeBSD) and GPollFileMonitor (gio on cygwin).
+  (when file-notify--test-desc
+    (or (alist-get file-notify--test-desc file-notify--test-monitors)
+        (when (member (file-notify--test-library) '("gfilenotify" "gio"))
+         (add-to-list
+          'file-notify--test-monitors
+          (cons file-notify--test-desc
+                (if (file-remote-p temporary-file-directory)
+                     ;; `file-notify--test-desc' is the connection process.
+                     (progn
+                       (while (not (tramp-connection-property-p
+                                   file-notify--test-desc "gio-file-monitor"))
+                         (accept-process-output file-notify--test-desc 0))
+                      (tramp-get-connection-property
+                       file-notify--test-desc "gio-file-monitor" nil))
+                  (and (functionp 'gfile-monitor-name)
+                       (gfile-monitor-name file-notify--test-desc)))))
+          ;; If we don't know the monitor, there are good chances the
+          ;; test will fail.  We let it fail already here, in order to
+          ;; know the real reason.
+          (should (alist-get file-notify--test-desc 
file-notify--test-monitors)))
+       (alist-get file-notify--test-desc file-notify--test-monitors))))
 
 (defmacro file-notify--deftest-remote (test docstring &optional unstable)
   "Define ert `TEST-remote' for remote files.
@@ -484,6 +497,9 @@ If UNSTABLE is non-nil, the test is tagged as `:unstable'."
                    (file-notify-add-watch
                     file-notify--test-tmpfile
                     '(change) #'second-callback)))
+            ;; `file-notify-rm-watch' confuses `file-notify--test-monitor'.
+            ;; Initialize it in time.
+            (file-notify--test-monitor)
             ;; Remove first watch.
             (file-notify-rm-watch file-notify--test-desc)
             ;; Only the second callback shall run.
@@ -547,6 +563,10 @@ and the event to `file-notify--test-events'."
            file-notify--test-results
            (append file-notify--test-results `(,result))))))
 
+(defun file-notify--test-event-actions ()
+  "Helper function to return retrieved actions, as list."
+  (mapcar #'file-notify--test-event-action file-notify--test-events))
+
 (defun file-notify--test-with-actions-check (actions)
   "Check whether received actions match one of the ACTIONS alternatives."
   (let (result)
@@ -555,22 +575,25 @@ and the event to `file-notify--test-events'."
             (or result
                 (if (eq (car elt) :random)
                     (equal (sort (cdr elt) 'string-lessp)
-                           (sort (mapcar #'file-notify--test-event-action
-                                         file-notify--test-events)
+                           (sort (file-notify--test-event-actions)
                                  'string-lessp))
-                  (equal elt (mapcar #'file-notify--test-event-action
-                                     file-notify--test-events))))))))
+                  (equal elt (file-notify--test-event-actions))))))
+    ;; Do not report result in case we debug.  Write messages instead.
+    (if file-notify-debug
+        (prog1 t
+          (if result
+              (message "Success\n%s" (file-notify--test-event-actions))
+            (message (file-notify--test-with-actions-explainer actions))))
+      result)))
 
 (defun file-notify--test-with-actions-explainer (actions)
   "Explain why `file-notify--test-with-actions-check' fails."
   (if (null (cdr actions))
       (format "Received actions do not match expected actions\n%s\n%s"
-              (mapcar #'file-notify--test-event-action 
file-notify--test-events)
-              (car actions))
+              (file-notify--test-event-actions) (car actions))
     (format
      "Received actions do not match any sequence of expected actions\n%s\n%s"
-     (mapcar #'file-notify--test-event-action file-notify--test-events)
-     actions)))
+     (file-notify--test-event-actions) actions)))
 
 (put 'file-notify--test-with-actions-check 'ert-explainer
      'file-notify--test-with-actions-explainer)
@@ -592,6 +615,9 @@ delivered."
             (mapcar
              (lambda (x) (length (if (eq (car x) :random) (cdr x) x)))
              actions)))
+          ;; Don't stop while debugging.
+          (while-no-input-ignore-events
+           (cons 'file-notify while-no-input-ignore-events))
           create-lockfiles)
      ;; Flush pending actions.
      (file-notify--test-read-event)
@@ -632,16 +658,11 @@ delivered."
                 '(change) #'file-notify--test-event-handler)))
         (file-notify--test-with-actions
             (cond
-             ;; gvfs-monitor-dir on cygwin does not detect the
-             ;; `created' event reliably.
-            ((string-equal (file-notify--test-library) "gvfs-monitor-dir.exe")
-             '((deleted stopped)
-               (created deleted stopped)))
-             ;; cygwin does not raise a `changed' event.
-             ((eq system-type 'cygwin)
-              '(created deleted stopped))
-            ;; GKqueueFileMonitor does not report the `changed' event.
-            ((equal (file-notify--test-monitor) 'GKqueueFileMonitor)
+            ;; GFam{File,Directory}Monitor, GKqueueFileMonitor and
+            ;; GPollFileMonitor do not report the `changed' event.
+            ((memq (file-notify--test-monitor)
+                    '(GFamFileMonitor GFamDirectoryMonitor
+                      GKqueueFileMonitor GPollFileMonitor))
              '(created deleted stopped))
              (t '(created changed deleted stopped)))
           (write-region
@@ -668,13 +689,14 @@ delivered."
                '(change) #'file-notify--test-event-handler)))
         (file-notify--test-with-actions
            (cond
-             ;; gvfs-monitor-dir on cygwin does not detect the
-             ;; `changed' event reliably.
-            ((string-equal (file-notify--test-library) "gvfs-monitor-dir.exe")
+            ;; GFam{File,Directory}Monitor and GPollFileMonitor do
+             ;; not detect the `changed' event reliably.
+            ((memq (file-notify--test-monitor)
+                    '(GFamFileMonitor GFamDirectoryMonitor GPollFileMonitor))
              '((deleted stopped)
                (changed deleted stopped)))
             ;; GKqueueFileMonitor does not report the `changed' event.
-            ((equal (file-notify--test-monitor) 'GKqueueFileMonitor)
+            ((eq (file-notify--test-monitor) 'GKqueueFileMonitor)
              '(deleted stopped))
             ;; There could be one or two `changed' events.
             (t '((changed deleted stopped)
@@ -709,25 +731,22 @@ delivered."
             ;; events for the watched directory.
             ((string-equal (file-notify--test-library) "w32notify")
              '(created changed deleted))
-             ;; gvfs-monitor-dir on cygwin does not detect the
-             ;; `created' event reliably.
-            ((string-equal
-              (file-notify--test-library) "gvfs-monitor-dir.exe")
-             '((deleted stopped)
-               (created deleted stopped)))
              ;; On emba, `deleted' and `stopped' events of the
              ;; directory are not detected.
              ((getenv "EMACS_EMBA_CI")
               '(created changed deleted))
             ;; There are two `deleted' events, for the file and for
-            ;; the directory.  Except for cygwin and kqueue.  And
-            ;; cygwin does not raise a `changed' event.
-            ((eq system-type 'cygwin)
+            ;; the directory.  Except for
+            ;; GFam{File,Directory}Monitor, GPollFileMonitor and
+            ;; kqueue.  And GFam{File,Directory}Monitor and
+            ;; GPollFileMonitordo not raise a `changed' event.
+            ((memq (file-notify--test-monitor)
+                    '(GFamFileMonitor GFamDirectoryMonitor GPollFileMonitor))
              '(created deleted stopped))
             ((string-equal (file-notify--test-library) "kqueue")
              '(created changed deleted stopped))
             ;; GKqueueFileMonitor does not report the `changed' event.
-            ((equal (file-notify--test-monitor) 'GKqueueFileMonitor)
+            ((eq (file-notify--test-monitor) 'GKqueueFileMonitor)
              '(created deleted deleted stopped))
             (t '(created changed deleted deleted stopped)))
          (write-region
@@ -762,15 +781,12 @@ delivered."
              '(created changed created changed
                changed changed changed
                deleted deleted))
-             ;; gvfs-monitor-dir on cygwin does not detect the
-             ;; `created' event reliably.
-            ((string-equal
-              (file-notify--test-library) "gvfs-monitor-dir.exe")
-             '((deleted stopped)
-               (created created deleted stopped)))
             ;; There are three `deleted' events, for two files and
-            ;; for the directory.  Except for cygwin and kqueue.
-            ((eq system-type 'cygwin)
+            ;; for the directory.  Except for
+            ;; GFam{File,Directory}Monitor, GPollFileMonitor and
+            ;; kqueue.
+            ((memq (file-notify--test-monitor)
+                    '(GFamFileMonitor GFamDirectoryMonitor GPollFileMonitor))
              '(created created changed changed deleted stopped))
             ((string-equal (file-notify--test-library) "kqueue")
              '(created changed created changed deleted stopped))
@@ -779,7 +795,7 @@ delivered."
              ((getenv "EMACS_EMBA_CI")
               '(created changed created changed deleted deleted))
             ;; GKqueueFileMonitor does not report the `changed' event.
-            ((equal (file-notify--test-monitor) 'GKqueueFileMonitor)
+            ((eq (file-notify--test-monitor) 'GKqueueFileMonitor)
              '(created created deleted deleted deleted stopped))
             (t '(created changed created changed
                  deleted deleted deleted stopped)))
@@ -819,26 +835,23 @@ delivered."
             ;; events for the watched directory.
             ((string-equal (file-notify--test-library) "w32notify")
              '(created changed renamed deleted))
-             ;; gvfs-monitor-dir on cygwin does not detect the
-             ;; `created' event reliably.
-            ((string-equal
-              (file-notify--test-library) "gvfs-monitor-dir.exe")
-             '((deleted stopped)
-               (created deleted stopped)))
              ;; On emba, `deleted' and `stopped' events of the
              ;; directory are not detected.
              ((getenv "EMACS_EMBA_CI")
               '(created changed renamed deleted))
             ;; There are two `deleted' events, for the file and for
-            ;; the directory.  Except for cygwin and kqueue.  And
-            ;; cygwin raises `created' and `deleted' events instead
-            ;; of a `renamed' event.
-            ((eq system-type 'cygwin)
+            ;; the directory.  Except for
+            ;; GFam{File,Directory}Monitor, GPollfileMonitor and
+            ;; kqueue.  And GFam{File,Directory}Monitor and
+            ;; GPollFileMonitor raise `created' and `deleted' events
+            ;; instead of a `renamed' event.
+            ((memq (file-notify--test-monitor)
+                    '(GFamFileMonitor GFamDirectoryMonitor GPollFileMonitor))
              '(created created deleted deleted stopped))
             ((string-equal (file-notify--test-library) "kqueue")
              '(created changed renamed deleted stopped))
             ;; GKqueueFileMonitor does not report the `changed' event.
-            ((equal (file-notify--test-monitor) 'GKqueueFileMonitor)
+            ((eq (file-notify--test-monitor) 'GKqueueFileMonitor)
              '(created renamed deleted deleted stopped))
             (t '(created changed renamed deleted deleted stopped)))
          (write-region
@@ -857,8 +870,8 @@ delivered."
     (file-notify--test-cleanup))
 
   (unwind-protect
-      ;; Check attribute change.  Does not work for cygwin.
-      (unless (eq system-type 'cygwin)
+      ;; Check attribute change.
+      (progn
        (setq file-notify--test-tmpfile (file-notify--test-make-temp-name))
        (write-region
         "any text" nil file-notify--test-tmpfile nil 'no-message)
@@ -876,12 +889,21 @@ delivered."
             ((string-equal (file-notify--test-library) "w32notify")
              '((changed changed)
                (changed changed changed changed)))
-            ;; GKqueueFileMonitor does not report the `attribute-changed' 
event.
-            ((equal (file-notify--test-monitor) 'GKqueueFileMonitor) nil)
-            ;; For kqueue and in the remote case, `write-region'
-            ;; raises also an `attribute-changed' event.
-            ((or (string-equal (file-notify--test-library) "kqueue")
-                 (file-remote-p temporary-file-directory))
+            ;; GFam{File,Directory}Monitor, GKqueueFileMonitor and
+            ;; GPollFileMonitor do not report the `attribute-changed'
+            ;; event.
+            ((memq (file-notify--test-monitor)
+                    '(GFamFileMonitor GFamDirectoryMonitor
+                      GKqueueFileMonitor GPollFileMonitor))
+              '())
+            ;; For GInotifyFileMonitor,`write-region' raises
+            ;; also an `attribute-changed' event on gio.
+            ((and (string-equal (file-notify--test-library) "gio")
+                   (eq (file-notify--test-monitor) 'GInotifyFileMonitor))
+             '(attribute-changed attribute-changed attribute-changed))
+            ;; For kqueue, `write-region' raises also an
+            ;; `attribute-changed' event.
+             ((string-equal (file-notify--test-library) "kqueue")
              '(attribute-changed attribute-changed attribute-changed))
             (t '(attribute-changed attribute-changed)))
          (write-region
@@ -946,7 +968,7 @@ delivered."
 
            ;; GKqueueFileMonitor does not report the `changed' event.
            (skip-unless
-            (not (equal (file-notify--test-monitor) 'GKqueueFileMonitor)))
+             (not (eq (file-notify--test-monitor) 'GKqueueFileMonitor)))
 
            ;; Check, that file notification has been used.
            (should auto-revert-mode)
@@ -1046,13 +1068,14 @@ delivered."
        (should (file-notify-valid-p file-notify--test-desc))
         (file-notify--test-with-actions
            (cond
-             ;; gvfs-monitor-dir on cygwin does not detect the
-             ;; `changed' event reliably.
-            ((string-equal (file-notify--test-library) "gvfs-monitor-dir.exe")
+            ;; GFam{File,Directory}Monitor do not
+             ;; detect the `changed' event reliably.
+            ((memq (file-notify--test-monitor)
+                    '(GFamFileMonitor GFamDirectoryMonitor))
              '((deleted stopped)
                (changed deleted stopped)))
             ;; GKqueueFileMonitor does not report the `changed' event.
-            ((equal (file-notify--test-monitor) 'GKqueueFileMonitor)
+            ((eq (file-notify--test-monitor) 'GKqueueFileMonitor)
              '(deleted stopped))
             ;; There could be one or two `changed' events.
             (t '((changed deleted stopped)
@@ -1090,21 +1113,18 @@ delivered."
               ;; events for the watched directory.
               ((string-equal (file-notify--test-library) "w32notify")
                '(created changed deleted))
-               ;; gvfs-monitor-dir on cygwin does not detect the
-               ;; `created' event reliably.
-              ((string-equal
-                 (file-notify--test-library) "gvfs-monitor-dir.exe")
-               '((deleted stopped)
-                 (created deleted stopped)))
               ;; There are two `deleted' events, for the file and for
-              ;; the directory.  Except for cygwin and kqueue.  And
-              ;; cygwin does not raise a `changed' event.
-              ((eq system-type 'cygwin)
+              ;; the directory.  Except for
+              ;; GFam{File,Directory}Monitor, GPollFileMonitor and
+              ;; kqueue.  And GFam{File,Directory}Monitor and
+              ;; GPollfileMonitor do not raise a `changed' event.
+              ((memq (file-notify--test-monitor)
+                      '(GFamFileMonitor GFamDirectoryMonitor GPollFileMonitor))
                '(created deleted stopped))
               ((string-equal (file-notify--test-library) "kqueue")
                '(created changed deleted stopped))
               ;; GKqueueFileMonitor does not report the `changed' event.
-              ((equal (file-notify--test-monitor) 'GKqueueFileMonitor)
+              ((eq (file-notify--test-monitor) 'GKqueueFileMonitor)
                '(created deleted deleted stopped))
               (t '(created changed deleted deleted stopped)))
            (write-region
@@ -1205,7 +1225,7 @@ delivered."
          file-notify--test-tmpfile
          '(change) #'file-notify--test-event-handler)))
   (unwind-protect
-      (let ((n 1000)
+      (let ((n 10);00)
             source-file-list target-file-list
             (default-directory file-notify--test-tmpfile))
         (dotimes (i n)
@@ -1234,9 +1254,11 @@ delivered."
                (dotimes (_i n)
                  (setq r (append '(deleted renamed) r)))
                r))
-            ;; cygwin fires `changed' and `deleted' events, sometimes
-            ;; in random order.
-            ((eq system-type 'cygwin)
+            ;; GFam{File,Directory}Monitor and GPollFileMonitor fire
+            ;; `changed' and `deleted' events, sometimes in random
+            ;; order.
+            ((memq (file-notify--test-monitor)
+                    '(GFamFileMonitor GFamDirectoryMonitor GPollFileMonitor))
              (let (r)
                (dotimes (_i n)
                  (setq r (append '(changed deleted) r)))
@@ -1285,7 +1307,7 @@ delivered."
         (file-notify--test-with-actions
            (cond
             ;; GKqueueFileMonitor does not report the `changed' event.
-            ((equal (file-notify--test-monitor) 'GKqueueFileMonitor) nil)
+            ((eq (file-notify--test-monitor) 'GKqueueFileMonitor) '())
              ;; There could be one or two `changed' events.
             (t '((changed)
                  (changed changed))))
@@ -1323,11 +1345,13 @@ delivered."
         (should (file-notify-valid-p file-notify--test-desc))
         (file-notify--test-with-actions
             (cond
-             ;; On cygwin we only get the `changed' event.
-             ((eq system-type 'cygwin)
-              '(changed))
+            ;; GFam{File,Directory}Monitor and GPollFileMonitor
+            ;; report only the `changed' event.
+            ((memq (file-notify--test-monitor)
+                    '(GFamFileMonitor GFamDirectoryMonitor GPollFileMonitor))
+             '(changed))
             ;; GKqueueFileMonitor does not report the `changed' event.
-            ((equal (file-notify--test-monitor) 'GKqueueFileMonitor)
+            ((eq (file-notify--test-monitor) 'GKqueueFileMonitor)
              '(renamed created))
              (t '(renamed created changed)))
           ;; The file is renamed when creating a backup.  It shall
@@ -1398,7 +1422,7 @@ the file watch."
         (should (file-notify-valid-p file-notify--test-desc1))
         (should (file-notify-valid-p file-notify--test-desc2))
         (should-not (equal file-notify--test-desc1 file-notify--test-desc2))
-        (let ((n 100))
+        (let ((n 10));0))
           ;; Run the test.
           (file-notify--test-with-actions
               ;; There could be one or two `changed' events.
@@ -1455,10 +1479,13 @@ the file watch."
         ;; Now we delete the directory.
         (file-notify--test-with-actions
             (cond
-             ;; In kqueue and for cygwin, just one `deleted' event for
-             ;; the directory is received.
-             ((or (eq system-type 'cygwin)
-                 (string-equal (file-notify--test-library) "kqueue"))
+             ;; GFam{File,Directory}Monitor, GPollFileMonitor and
+             ;; kqueue raise just one `deleted' event for the
+             ;; directory.
+            ((memq (file-notify--test-monitor)
+                    '(GFamFileMonitor GFamDirectoryMonitor GPollFileMonitor))
+              '(deleted stopped))
+            ((string-equal (file-notify--test-library) "kqueue")
               '(deleted stopped))
              (t (append
                  ;; The directory monitor raises a `deleted' event for
diff --git a/test/lisp/files-tests.el b/test/lisp/files-tests.el
index 149cc68..3371657 100644
--- a/test/lisp/files-tests.el
+++ b/test/lisp/files-tests.el
@@ -192,14 +192,37 @@ form.")
 (ert-deftest files-tests-bug-21454 ()
   "Test for https://debbugs.gnu.org/21454 ."
   (let ((input-result
-         '(("/foo/bar//baz/:/bar/foo/baz//" nil ("/foo/bar/baz/" 
"/bar/foo/baz/"))
-           ("/foo/bar/:/bar/qux/:/qux/foo" nil ("/foo/bar/" "/bar/qux/" 
"/qux/foo/"))
-           ("//foo/bar/:/bar/qux/:/qux/foo/" nil ("/foo/bar/" "/bar/qux/" 
"/qux/foo/"))
-           ("/foo/bar/:/bar/qux/:/qux/foo/" nil ("/foo/bar/" "/bar/qux/" 
"/qux/foo/"))
-           ("/foo//bar/:/bar/qux/:/qux/foo/" nil ("/foo/bar/" "/bar/qux/" 
"/qux/foo/"))
-           ("/foo//bar/:/bar/qux/:/qux/foo" nil ("/foo/bar/" "/bar/qux/" 
"/qux/foo/"))
-           ("/foo/bar" "$FOO/baz/:/qux/foo/" ("/foo/bar/baz/" "/qux/foo/"))
-           ("//foo/bar/" "$FOO/baz/:/qux/foo/" ("/foo/bar/baz/" "/qux/foo/"))))
+         (if (memq system-type '(windows-nt ms-dos))
+             '(("x:/foo/bar//baz/;y:/bar/foo/baz//" nil
+                ("x:/foo/bar/baz/" "y:/bar/foo/baz/"))
+               ("x:/foo/bar/;y:/bar/qux/;z:/qux/foo" nil
+                ("x:/foo/bar/" "y:/bar/qux/" "z:/qux/foo/"))
+               ("x://foo/bar/;y:/bar/qux/;z:/qux/foo/" nil
+                ("x:/foo/bar/" "y:/bar/qux/" "z:/qux/foo/"))
+               ("x:/foo/bar/;y:/bar/qux/;z:/qux/foo/" nil
+                ("x:/foo/bar/" "y:/bar/qux/" "z:/qux/foo/"))
+               ("x:/foo//bar/;y:/bar/qux/;z:/qux/foo/" nil
+                ("x:/foo/bar/" "y:/bar/qux/" "z:/qux/foo/"))
+               ("x:/foo//bar/;y:/bar/qux/;z:/qux/foo" nil
+                ("x:/foo/bar/" "y:/bar/qux/" "z:/qux/foo/"))
+               ("x:/foo/bar" "$FOO/baz/;z:/qux/foo/"
+                ("x:/foo/bar/baz/" "z:/qux/foo/"))
+               ("x://foo/bar/" "$FOO/baz/;z:/qux/foo/"
+                ("x:/foo/bar/baz/" "z:/qux/foo/")))
+           '(("/foo/bar//baz/:/bar/foo/baz//" nil
+              ("/foo/bar/baz/" "/bar/foo/baz/"))
+             ("/foo/bar/:/bar/qux/:/qux/foo" nil
+              ("/foo/bar/" "/bar/qux/" "/qux/foo/"))
+             ("//foo/bar/:/bar/qux/:/qux/foo/" nil
+              ("/foo/bar/" "/bar/qux/" "/qux/foo/"))
+             ("/foo/bar/:/bar/qux/:/qux/foo/" nil
+              ("/foo/bar/" "/bar/qux/" "/qux/foo/"))
+             ("/foo//bar/:/bar/qux/:/qux/foo/" nil
+              ("/foo/bar/" "/bar/qux/" "/qux/foo/"))
+             ("/foo//bar/:/bar/qux/:/qux/foo" nil
+              ("/foo/bar/" "/bar/qux/" "/qux/foo/"))
+             ("/foo/bar" "$FOO/baz/:/qux/foo/" ("/foo/bar/baz/" "/qux/foo/"))
+             ("//foo/bar/" "$FOO/baz/:/qux/foo/" ("/foo/bar/baz/" 
"/qux/foo/")))))
         (foo-env (getenv "FOO"))
         (bar-env (getenv "BAR")))
     (unwind-protect
@@ -857,10 +880,15 @@ unquoted file names."
                                  (find-backup-file-name tmpfile)))))))
 
 (ert-deftest files-tests-file-name-non-special-get-file-buffer ()
+  ;; Make sure these buffers don't exist.
   (files-tests--with-temp-non-special (tmpfile nospecial)
-    (should-not (get-file-buffer nospecial)))
+    (let ((fbuf (get-file-buffer nospecial)))
+      (if fbuf (kill-buffer fbuf))
+      (should-not (get-file-buffer nospecial))))
   (files-tests--with-temp-non-special-and-file-name-handler (tmpfile nospecial)
-    (should-not (get-file-buffer nospecial))))
+    (let ((fbuf (get-file-buffer nospecial)))
+      (if fbuf (kill-buffer fbuf))
+      (should-not (get-file-buffer nospecial)))))
 
 (ert-deftest files-tests-file-name-non-special-insert-directory ()
   (files-tests--with-temp-non-special (tmpdir nospecial-dir t)
@@ -1363,8 +1391,11 @@ See <https://debbugs.gnu.org/36401>."
       (should (not (eq major-mode 'text-mode))))))
 
 (ert-deftest files-colon-path ()
-  (should (equal (parse-colon-path "/foo//bar/baz")
-                 '("/foo/bar/baz/"))))
+  (if (memq system-type '(windows-nt ms-dos))
+      (should (equal (parse-colon-path "x:/foo//bar/baz")
+                     '("x:/foo/bar/baz/")))
+    (should (equal (parse-colon-path "/foo//bar/baz")
+                 '("/foo/bar/baz/")))))
 
 (ert-deftest files-test-magic-mode-alist-doctype ()
   "Test that DOCTYPE and variants put files in mhtml-mode."
diff --git a/test/lisp/help-tests.el b/test/lisp/help-tests.el
index 8034764..b2fec5c 100644
--- a/test/lisp/help-tests.el
+++ b/test/lisp/help-tests.el
@@ -26,6 +26,7 @@
 
 (require 'ert)
 (eval-when-compile (require 'cl-lib))
+(require 'text-property-search) ; for `text-property-search-forward'
 
 (ert-deftest help-split-fundoc-SECTION ()
   "Test new optional arg SECTION."
@@ -60,9 +61,8 @@
 (defmacro with-substitute-command-keys-test (&rest body)
   `(cl-flet* ((test
                (lambda (orig result)
-                 (should (equal-including-properties
-                          (substitute-command-keys orig)
-                          result))))
+                 (should (equal (substitute-command-keys orig)
+                                result))))
               (test-re
                (lambda (orig regexp)
                  (should (string-match (concat "^" regexp "$")
@@ -222,6 +222,24 @@ M-s                next-matching-history-element
 (define-minor-mode help-tests-minor-mode
   "Minor mode for testing shadowing.")
 
+(ert-deftest help-tests-substitute-command-keys/add-key-face ()
+  (should (equal (substitute-command-keys "\\[next-line]")
+                 (propertize "C-n"
+                             'face 'help-key-binding
+                             'font-lock-face 'help-key-binding))))
+
+(ert-deftest help-tests-substitute-command-keys/add-key-face-listing ()
+  (with-temp-buffer
+    (insert (substitute-command-keys "\\{help-tests-minor-mode-map}"))
+    (goto-char (point-min))
+    (text-property-search-forward 'face 'help-key-binding)
+    (should (looking-at "C-e"))
+    ;; Don't fontify trailing whitespace.
+    (should-not (get-text-property (+ (point) 3) 'face))
+    (text-property-search-forward 'face 'help-key-binding)
+    (should (looking-at "x"))
+    (should-not (get-text-property (+ (point) 1) 'face))))
+
 (ert-deftest help-tests-substitute-command-keys/test-mode ()
   (with-substitute-command-keys-test
    (with-temp-buffer
diff --git a/test/lisp/image-tests.el b/test/lisp/image-tests.el
index ab7585c..2f7afa2 100644
--- a/test/lisp/image-tests.el
+++ b/test/lisp/image-tests.el
@@ -25,7 +25,7 @@
   (require 'cl-lib))
 
 (defconst image-tests--emacs-images-directory
-  (expand-file-name "../etc/images" (getenv "EMACS_TEST_DIRECTORY"))
+  (expand-file-name "images" data-directory)
   "Directory containing Emacs images.")
 
 (ert-deftest image--set-property ()
@@ -48,6 +48,19 @@
     (setf (image-property image :width) nil)
     (should (equal image '(image)))))
 
+(ert-deftest image-find-image ()
+  (find-image '((:type xpm :file "undo.xpm")))
+  (find-image '((:type png :file "newsticker/rss-feed.png" :ascent center))))
+
+(ert-deftest image-type-from-file-name ()
+  (should (eq (image-type-from-file-name "foo.jpg") 'jpeg))
+  (should (eq (image-type-from-file-name "foo.png") 'png)))
+
+(ert-deftest image-type/from-filename ()
+  ;; On emba, `image-load-path' does not exist.
+  (skip-unless (bound-and-true-p image-load-path))
+  (should (eq (image-type "foo.jpg") 'jpeg)))
+
 (ert-deftest image-type-from-file-header-test ()
   "Test image-type-from-file-header."
   (should (eq (if (image-type-available-p 'svg) 'svg)
diff --git a/test/lisp/json-tests.el b/test/lisp/json-tests.el
index 11b61d8..f400fb0 100644
--- a/test/lisp/json-tests.el
+++ b/test/lisp/json-tests.el
@@ -329,13 +329,13 @@ Point is moved to beginning of the buffer."
           (should (equal (read str) res)))))))
 
 (ert-deftest test-json-encode-number ()
-  (should (equal (json-encode-number 0) "0"))
-  (should (equal (json-encode-number -0) "0"))
-  (should (equal (json-encode-number 3) "3"))
-  (should (equal (json-encode-number -5) "-5"))
-  (should (equal (json-encode-number 123.456) "123.456"))
+  (should (equal (json-encode 0) "0"))
+  (should (equal (json-encode -0) "0"))
+  (should (equal (json-encode 3) "3"))
+  (should (equal (json-encode -5) "-5"))
+  (should (equal (json-encode 123.456) "123.456"))
   (let ((bignum (1+ most-positive-fixnum)))
-    (should (equal (json-encode-number bignum)
+    (should (equal (json-encode bignum)
                    (number-to-string bignum)))))
 
 ;;; Strings
@@ -404,6 +404,8 @@ Point is moved to beginning of the buffer."
     (should (equal (json-read-string) "abcαβγ")))
   (json-tests--with-temp-buffer "\"\\nasd\\u0444\\u044b\\u0432fgh\\t\""
     (should (equal (json-read-string) "\nasdфывfgh\t")))
+  (json-tests--with-temp-buffer "\"abc\uFFFFαβγ𝔸𝐁𝖢\\\"\\\\\""
+    (should (equal (json-read-string) "abc\uFFFFαβγ𝔸𝐁𝖢\"\\")))
   ;; Bug#24784
   (json-tests--with-temp-buffer "\"\\uD834\\uDD1E\""
     (should (equal (json-read-string) "\U0001D11E")))
@@ -418,21 +420,37 @@ Point is moved to beginning of the buffer."
   (should (equal (json-encode-string "foo") "\"foo\""))
   (should (equal (json-encode-string "a\n\fb") "\"a\\n\\fb\""))
   (should (equal (json-encode-string "\nasdфыв\u001f\u007ffgh\t")
-                 "\"\\nasdфыв\\u001f\u007ffgh\\t\"")))
+                 "\"\\nasdфыв\\u001f\u007ffgh\\t\""))
+  ;; Bug#43549.
+  (should (equal (json-encode-string (propertize "foo" 'read-only t))
+                 "\"foo\""))
+  (should (equal (json-encode-string "a\0b") "\"a\\u0000b\""))
+  (should (equal (json-encode-string "abc\uFFFFαβγ𝔸𝐁𝖢\"\\")
+                 "\"abc\uFFFFαβγ𝔸𝐁𝖢\\\"\\\\\"")))
 
 (ert-deftest test-json-encode-key ()
-  (should (equal (json-encode-key "") "\"\""))
-  (should (equal (json-encode-key '##) "\"\""))
-  (should (equal (json-encode-key :) "\"\""))
-  (should (equal (json-encode-key "foo") "\"foo\""))
-  (should (equal (json-encode-key 'foo) "\"foo\""))
-  (should (equal (json-encode-key :foo) "\"foo\""))
-  (should (equal (should-error (json-encode-key 5))
-                 '(json-key-format 5)))
-  (should (equal (should-error (json-encode-key ["foo"]))
-                 '(json-key-format ["foo"])))
-  (should (equal (should-error (json-encode-key '("foo")))
-                 '(json-key-format ("foo")))))
+  (with-suppressed-warnings ((obsolete json-encode-key))
+    (should (equal (json-encode-key '##) "\"\""))
+    (should (equal (json-encode-key :) "\"\""))
+    (should (equal (json-encode-key "") "\"\""))
+    (should (equal (json-encode-key 'a) "\"a\""))
+    (should (equal (json-encode-key :a) "\"a\""))
+    (should (equal (json-encode-key "a") "\"a\""))
+    (should (equal (json-encode-key t) "\"t\""))
+    (should (equal (json-encode-key :t) "\"t\""))
+    (should (equal (json-encode-key "t") "\"t\""))
+    (should (equal (json-encode-key nil) "\"nil\""))
+    (should (equal (json-encode-key :nil) "\"nil\""))
+    (should (equal (json-encode-key "nil") "\"nil\""))
+    (should (equal (json-encode-key ":a") "\":a\""))
+    (should (equal (json-encode-key ":t") "\":t\""))
+    (should (equal (json-encode-key ":nil") "\":nil\""))
+    (should (equal (should-error (json-encode-key 5))
+                   '(json-key-format 5)))
+    (should (equal (should-error (json-encode-key ["foo"]))
+                   '(json-key-format ["foo"])))
+    (should (equal (should-error (json-encode-key '("foo")))
+                   '(json-key-format ("foo"))))))
 
 ;;; Objects
 
@@ -569,12 +587,32 @@ Point is moved to beginning of the buffer."
 (ert-deftest test-json-encode-hash-table ()
   (let ((json-encoding-object-sort-predicate nil)
         (json-encoding-pretty-print nil))
-    (should (equal (json-encode-hash-table #s(hash-table)) "{}"))
-    (should (equal (json-encode-hash-table #s(hash-table data (a 1)))
+    (should (equal (json-encode #s(hash-table)) "{}"))
+    (should (equal (json-encode #s(hash-table data (a 1))) "{\"a\":1}"))
+    (should (equal (json-encode #s(hash-table data (t 1))) "{\"t\":1}"))
+    (should (equal (json-encode #s(hash-table data (nil 1))) "{\"nil\":1}"))
+    (should (equal (json-encode #s(hash-table data (:a 1))) "{\"a\":1}"))
+    (should (equal (json-encode #s(hash-table data (:t 1))) "{\"t\":1}"))
+    (should (equal (json-encode #s(hash-table data (:nil 1))) "{\"nil\":1}"))
+    (should (equal (json-encode #s(hash-table test equal data ("a" 1)))
                    "{\"a\":1}"))
-    (should (member (json-encode-hash-table #s(hash-table data (b 2 a 1)))
+    (should (equal (json-encode #s(hash-table test equal data ("t" 1)))
+                   "{\"t\":1}"))
+    (should (equal (json-encode #s(hash-table test equal data ("nil" 1)))
+                   "{\"nil\":1}"))
+    (should (equal (json-encode #s(hash-table test equal data (":a" 1)))
+                   "{\":a\":1}"))
+    (should (equal (json-encode #s(hash-table test equal data (":t" 1)))
+                   "{\":t\":1}"))
+    (should (equal (json-encode #s(hash-table test equal data (":nil" 1)))
+                   "{\":nil\":1}"))
+    (should (member (json-encode #s(hash-table data (t 2 :nil 1)))
+                    '("{\"nil\":1,\"t\":2}" "{\"t\":2,\"nil\":1}")))
+    (should (member (json-encode #s(hash-table test equal data (:t 2 ":t" 1)))
+                    '("{\":t\":1,\"t\":2}" "{\"t\":2,\":t\":1}")))
+    (should (member (json-encode #s(hash-table data (b 2 a 1)))
                     '("{\"a\":1,\"b\":2}" "{\"b\":2,\"a\":1}")))
-    (should (member (json-encode-hash-table #s(hash-table data (c 3 b 2 a 1)))
+    (should (member (json-encode #s(hash-table data (c 3 b 2 a 1)))
                     '("{\"a\":1,\"b\":2,\"c\":3}"
                       "{\"a\":1,\"c\":3,\"b\":2}"
                       "{\"b\":2,\"a\":1,\"c\":3}"
@@ -587,13 +625,12 @@ Point is moved to beginning of the buffer."
         (json-encoding-pretty-print t)
         (json-encoding-default-indentation " ")
         (json-encoding-lisp-style-closings nil))
-    (should (equal (json-encode-hash-table #s(hash-table)) "{}"))
-    (should (equal (json-encode-hash-table #s(hash-table data (a 1)))
-                   "{\n \"a\": 1\n}"))
-    (should (member (json-encode-hash-table #s(hash-table data (b 2 a 1)))
+    (should (equal (json-encode #s(hash-table)) "{}"))
+    (should (equal (json-encode #s(hash-table data (a 1))) "{\n \"a\": 1\n}"))
+    (should (member (json-encode #s(hash-table data (b 2 a 1)))
                     '("{\n \"a\": 1,\n \"b\": 2\n}"
                       "{\n \"b\": 2,\n \"a\": 1\n}")))
-    (should (member (json-encode-hash-table #s(hash-table data (c 3 b 2 a 1)))
+    (should (member (json-encode #s(hash-table data (c 3 b 2 a 1)))
                     '("{\n \"a\": 1,\n \"b\": 2,\n \"c\": 3\n}"
                       "{\n \"a\": 1,\n \"c\": 3,\n \"b\": 2\n}"
                       "{\n \"b\": 2,\n \"a\": 1,\n \"c\": 3\n}"
@@ -606,13 +643,12 @@ Point is moved to beginning of the buffer."
         (json-encoding-pretty-print t)
         (json-encoding-default-indentation " ")
         (json-encoding-lisp-style-closings t))
-    (should (equal (json-encode-hash-table #s(hash-table)) "{}"))
-    (should (equal (json-encode-hash-table #s(hash-table data (a 1)))
-                   "{\n \"a\": 1}"))
-    (should (member (json-encode-hash-table #s(hash-table data (b 2 a 1)))
+    (should (equal (json-encode #s(hash-table)) "{}"))
+    (should (equal (json-encode #s(hash-table data (a 1))) "{\n \"a\": 1}"))
+    (should (member (json-encode #s(hash-table data (b 2 a 1)))
                     '("{\n \"a\": 1,\n \"b\": 2}"
                       "{\n \"b\": 2,\n \"a\": 1}")))
-    (should (member (json-encode-hash-table #s(hash-table data (c 3 b 2 a 1)))
+    (should (member (json-encode #s(hash-table data (c 3 b 2 a 1)))
                     '("{\n \"a\": 1,\n \"b\": 2,\n \"c\": 3}"
                       "{\n \"a\": 1,\n \"c\": 3,\n \"b\": 2}"
                       "{\n \"b\": 2,\n \"a\": 1,\n \"c\": 3}"
@@ -630,7 +666,7 @@ Point is moved to beginning of the buffer."
                      (#s(hash-table data (c 3 b 2 a 1))
                         . "{\"a\":1,\"b\":2,\"c\":3}")))
       (let ((copy (map-pairs in)))
-        (should (equal (json-encode-hash-table in) out))
+        (should (equal (json-encode in) out))
         ;; Ensure sorting isn't destructive.
         (should (seq-set-equal-p (map-pairs in) copy))))))
 
@@ -638,7 +674,16 @@ Point is moved to beginning of the buffer."
   (let ((json-encoding-object-sort-predicate nil)
         (json-encoding-pretty-print nil))
     (should (equal (json-encode-alist ()) "{}"))
-    (should (equal (json-encode-alist '((a . 1))) "{\"a\":1}"))
+    (should (equal (json-encode-alist '((a . 1) (t . 2) (nil . 3)))
+                   "{\"a\":1,\"t\":2,\"nil\":3}"))
+    (should (equal (json-encode-alist '((:a . 1) (:t . 2) (:nil . 3)))
+                   "{\"a\":1,\"t\":2,\"nil\":3}"))
+    (should (equal (json-encode-alist '(("a" . 1) ("t" . 2) ("nil" . 3)))
+                   "{\"a\":1,\"t\":2,\"nil\":3}"))
+    (should (equal (json-encode-alist '((":a" . 1) (":t" . 2) (":nil" . 3)))
+                   "{\":a\":1,\":t\":2,\":nil\":3}"))
+    (should (equal (json-encode-alist '((t . 1) (:nil . 2) (":nil" . 3)))
+                   "{\"t\":1,\"nil\":2,\":nil\":3}"))
     (should (equal (json-encode-alist '((b . 2) (a . 1))) "{\"b\":2,\"a\":1}"))
     (should (equal (json-encode-alist '((c . 3) (b . 2) (a . 1)))
                    "{\"c\":3,\"b\":2,\"a\":1}"))))
@@ -687,8 +732,14 @@ Point is moved to beginning of the buffer."
     (should (equal (json-encode-plist ()) "{}"))
     (should (equal (json-encode-plist '(:a 1)) "{\"a\":1}"))
     (should (equal (json-encode-plist '(:b 2 :a 1)) "{\"b\":2,\"a\":1}"))
-    (should (equal (json-encode-plist '(:c 3 :b 2 :a 1))
-                   "{\"c\":3,\"b\":2,\"a\":1}"))))
+    (should (equal (json-encode-plist '(":d" 4 "c" 3 b 2 :a 1))
+                   "{\":d\":4,\"c\":3,\"b\":2,\"a\":1}"))
+    (should (equal (json-encode-plist '(nil 2 t 1))
+                   "{\"nil\":2,\"t\":1}"))
+    (should (equal (json-encode-plist '(:nil 2 :t 1))
+                   "{\"nil\":2,\"t\":1}"))
+    (should (equal (json-encode-plist '(":nil" 4 "nil" 3 ":t" 2 "t" 1))
+                   "{\":nil\":4,\"nil\":3,\":t\":2,\"t\":1}"))))
 
 (ert-deftest test-json-encode-plist-pretty ()
   (let ((json-encoding-object-sort-predicate nil)
@@ -728,38 +779,42 @@ Point is moved to beginning of the buffer."
         (should (equal in copy))))))
 
 (ert-deftest test-json-encode-list ()
+  "Test `json-encode-list' or its more moral equivalents."
   (let ((json-encoding-object-sort-predicate nil)
         (json-encoding-pretty-print nil))
-    (should (equal (json-encode-list ()) "{}"))
-    (should (equal (json-encode-list '(a)) "[\"a\"]"))
-    (should (equal (json-encode-list '(:a)) "[\"a\"]"))
-    (should (equal (json-encode-list '("a")) "[\"a\"]"))
-    (should (equal (json-encode-list '(a 1)) "[\"a\",1]"))
-    (should (equal (json-encode-list '("a" 1)) "[\"a\",1]"))
-    (should (equal (json-encode-list '(:a 1)) "{\"a\":1}"))
-    (should (equal (json-encode-list '((a . 1))) "{\"a\":1}"))
-    (should (equal (json-encode-list '((:a . 1))) "{\"a\":1}"))
-    (should (equal (json-encode-list '(:b 2 :a)) "[\"b\",2,\"a\"]"))
-    (should (equal (json-encode-list '(4 3 2 1)) "[4,3,2,1]"))
-    (should (equal (json-encode-list '(b 2 a 1)) "[\"b\",2,\"a\",1]"))
-    (should (equal (json-encode-list '(:b 2 :a 1)) "{\"b\":2,\"a\":1}"))
-    (should (equal (json-encode-list '((b . 2) (a . 1))) "{\"b\":2,\"a\":1}"))
-    (should (equal (json-encode-list '((:b . 2) (:a . 1)))
+    ;; Trick `json-encode' into using `json--print-list'.
+    (let ((json-null (list nil)))
+      (should (equal (json-encode ()) "{}")))
+    (should (equal (json-encode '(a)) "[\"a\"]"))
+    (should (equal (json-encode '(:a)) "[\"a\"]"))
+    (should (equal (json-encode '("a")) "[\"a\"]"))
+    (should (equal (json-encode '(a 1)) "[\"a\",1]"))
+    (should (equal (json-encode '("a" 1)) "[\"a\",1]"))
+    (should (equal (json-encode '(:a 1)) "{\"a\":1}"))
+    (should (equal (json-encode '((a . 1))) "{\"a\":1}"))
+    (should (equal (json-encode '((:a . 1))) "{\"a\":1}"))
+    (should (equal (json-encode '(:b 2 :a)) "[\"b\",2,\"a\"]"))
+    (should (equal (json-encode '(4 3 2 1)) "[4,3,2,1]"))
+    (should (equal (json-encode '(b 2 a 1)) "[\"b\",2,\"a\",1]"))
+    (should (equal (json-encode '(:b 2 :a 1)) "{\"b\":2,\"a\":1}"))
+    (should (equal (json-encode '((b . 2) (a . 1))) "{\"b\":2,\"a\":1}"))
+    (should (equal (json-encode '((:b . 2) (:a . 1)))
                    "{\"b\":2,\"a\":1}"))
-    (should (equal (json-encode-list '((a) 1)) "[[\"a\"],1]"))
-    (should (equal (json-encode-list '((:a) 1)) "[[\"a\"],1]"))
-    (should (equal (json-encode-list '(("a") 1)) "[[\"a\"],1]"))
-    (should (equal (json-encode-list '((a 1) 2)) "[[\"a\",1],2]"))
-    (should (equal (json-encode-list '((:a 1) 2)) "[{\"a\":1},2]"))
-    (should (equal (json-encode-list '(((a . 1)) 2)) "[{\"a\":1},2]"))
-    (should (equal (json-encode-list '(:a 1 :b (2))) "{\"a\":1,\"b\":[2]}"))
-    (should (equal (json-encode-list '((a . 1) (b 2))) "{\"a\":1,\"b\":[2]}"))
-    (should-error (json-encode-list '(a . 1)) :type 'wrong-type-argument)
-    (should-error (json-encode-list '((a . 1) 2)) :type 'wrong-type-argument)
-    (should (equal (should-error (json-encode-list []))
-                   '(json-error [])))
-    (should (equal (should-error (json-encode-list [a]))
-                   '(json-error [a])))))
+    (should (equal (json-encode '((a) 1)) "[[\"a\"],1]"))
+    (should (equal (json-encode '((:a) 1)) "[[\"a\"],1]"))
+    (should (equal (json-encode '(("a") 1)) "[[\"a\"],1]"))
+    (should (equal (json-encode '((a 1) 2)) "[[\"a\",1],2]"))
+    (should (equal (json-encode '((:a 1) 2)) "[{\"a\":1},2]"))
+    (should (equal (json-encode '(((a . 1)) 2)) "[{\"a\":1},2]"))
+    (should (equal (json-encode '(:a 1 :b (2))) "{\"a\":1,\"b\":[2]}"))
+    (should (equal (json-encode '((a . 1) (b 2))) "{\"a\":1,\"b\":[2]}"))
+    (should-error (json-encode '(a . 1)) :type 'wrong-type-argument)
+    (should-error (json-encode '((a . 1) 2)) :type 'wrong-type-argument)
+    (with-suppressed-warnings ((obsolete json-encode-list))
+      (should (equal (should-error (json-encode-list []))
+                     '(json-error [])))
+      (should (equal (should-error (json-encode-list [a]))
+                     '(json-error [a]))))))
 
 ;;; Arrays
 
@@ -950,7 +1005,13 @@ nil, ORIGINAL should stay unchanged by pretty-printing."
   ;; Nested array.
   (json-tests-equal-pretty-print
    "{\"key\":[1,2]}"
-   "{\n  \"key\": [\n    1,\n    2\n  ]\n}"))
+   "{\n  \"key\": [\n    1,\n    2\n  ]\n}")
+  ;; Confusable keys (bug#24252, bug#42545).
+  (json-tests-equal-pretty-print
+   (concat "{\"t\":1,\"nil\":2,\":t\":3,\":nil\":4,"
+           "\"null\":5,\":json-null\":6,\":json-false\":7}")
+   (concat "{\n  \"t\": 1,\n  \"nil\": 2,\n  \":t\": 3,\n  \":nil\": 4,"
+           "\n  \"null\": 5,\n  \":json-null\": 6,\n  \":json-false\": 7\n}")))
 
 (ert-deftest test-json-pretty-print-array ()
   ;; Empty.
diff --git a/test/lisp/jsonrpc-tests.el b/test/lisp/jsonrpc-tests.el
index ea340c3..92306d1 100644
--- a/test/lisp/jsonrpc-tests.el
+++ b/test/lisp/jsonrpc-tests.el
@@ -244,7 +244,7 @@
                        :timeout 1)
       ;; Wait another 0.5 secs just in case the success handlers of
       ;; one of these last two requests didn't quite have a chance to
-      ;; run (Emacs 25.2 apparentely needs this).
+      ;; run (Emacs 25.2 apparently needs this).
       (accept-process-output nil 0.5)
       (should second-deferred-went-through-p)
       (should (eq 1 n-deferred-1))
diff --git a/test/lisp/kmacro-tests.el b/test/lisp/kmacro-tests.el
index c891072..8736f7f 100644
--- a/test/lisp/kmacro-tests.el
+++ b/test/lisp/kmacro-tests.el
@@ -519,7 +519,7 @@ This is a regression test for: Bug#3412, Bug#11817."
     (should (eq saved-binding (key-binding "\C-a")))))
 
 (kmacro-tests-deftest kmacro-tests-name-or-bind-to-key-when-no-macro ()
-  "Bind to key, symbol or register fails when when no macro exists."
+  "Bind to key, symbol or register fails when no macro exists."
   (should-error (kmacro-bind-to-key nil))
   (should-error (kmacro-name-last-macro 'kmacro-tests-symbol-for-test))
   (should-error (kmacro-to-register)))
diff --git a/test/lisp/mail/mail-utils-tests.el 
b/test/lisp/mail/mail-utils-tests.el
new file mode 100644
index 0000000..5b54f24
--- /dev/null
+++ b/test/lisp/mail/mail-utils-tests.el
@@ -0,0 +1,104 @@
+;;; mail-utils-tests.el --- tests for mail-utils.el  -*- lexical-binding: t -*-
+
+;; Copyright (C) 2021 Free Software Foundation, Inc.
+
+;; Author: Stefan Kangas <stefankangas@gmail.com>
+
+;; 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:
+
+;;; Code:
+
+(require 'ert)
+(require 'sasl)
+(require 'mail-utils)
+
+(ert-deftest mail-utils-tests-mail-quote-printable ()
+  (should (equal (mail-quote-printable "abc") "abc"))
+  (should (equal (mail-quote-printable "åäö") "=E5=E4=F6"))
+  (should (equal (mail-quote-printable "åäö" t) "=?ISO-8859-1?Q?=E5=E4=F6?=")))
+
+(ert-deftest mail-utils-tests-mail-quote-printable-region ()
+  (with-temp-buffer
+    (insert "?=\"\"")
+    (mail-quote-printable-region (point-min) (point-max))
+    (should (equal (buffer-string) "=3F=3D=22=22")))
+  (with-temp-buffer
+    (insert "x")
+    (mail-quote-printable-region (point-min) (point-max) t)
+    (should (equal (buffer-string) "=?=?ISO-8859-1?Q?x"))))
+
+(ert-deftest mail-utils-tests-mail-unquote-printable ()
+  (should (equal (mail-unquote-printable "=E5=E4=F6") "åäö"))
+  (should (equal (mail-unquote-printable "=?ISO-8859-1?Q?=E5=E4=F6?=" t) 
"åäö")))
+
+(ert-deftest mail-utils-tests-mail-unquote-printable-region ()
+  (with-temp-buffer
+    (insert "=E5=E4=F6")
+    (mail-unquote-printable-region (point-min) (point-max))
+    (should (equal (buffer-string) "åäö")))
+  (with-temp-buffer
+    (insert "=?ISO-8859-1?Q?=E5=E4=F6?=")
+    (mail-unquote-printable-region (point-min) (point-max) t)
+    (should (equal (buffer-string) "åäö"))))
+
+(ert-deftest mail-utils-tests-mail-strip-quoted-names ()
+  (should (equal (mail-strip-quoted-names
+                  "\"foo\" <foo@example.org>, bar@example.org")
+                 "foo@example.org, bar@example.org")))
+
+(ert-deftest mail-utils-tests-mail-dont-reply-to ()
+  (let ((mail-dont-reply-to-names "foo@example.org"))
+    (should (equal (mail-dont-reply-to "foo@example.org, bar@example.org")
+                   "bar@example.org"))))
+
+
+(ert-deftest mail-utils-tests-mail-fetch-field ()
+  (with-temp-buffer
+    (insert "Foo: bar\nBaz: zut")
+    (should (equal (mail-fetch-field "Foo") "bar"))))
+
+(ert-deftest mail-utils-tests-mail-parse-comma-list ()
+  (with-temp-buffer
+    (insert "foo@example.org,bar@example.org,baz@example.org")
+    (goto-char (point-min))
+    (should (equal (mail-parse-comma-list)
+                   '("baz@example.org" "bar@example.org" "foo@example.org")))))
+
+(ert-deftest mail-utils-tests-mail-comma-list-regexp ()
+  (should (equal (mail-comma-list-regexp
+                  "foo@example.org,bar@example.org,baz@example.org")
+                 "foo@example.org\\|bar@example.org\\|baz@example.org")))
+
+(ert-deftest mail-utils-tests-mail-rfc822-time-zone ()
+  (should (stringp (mail-rfc822-time-zone (current-time)))))
+
+(ert-deftest mail-utils-test-mail-rfc822-date/contains-year ()
+  (should (string-match (rx " 20" digit digit " ")
+                        (mail-rfc822-date))))
+
+(ert-deftest mail-utils-test-mail-mbox-from ()
+  (with-temp-buffer
+    (insert "Subject: Hello
+From: jrh@example.org
+To: emacs-devel@gnu.org
+Date: Sun, 07 Feb 2021 22:46:37 -0500")
+    (should (equal (mail-mbox-from)
+                   "From jrh@example.org Sun Feb  7 22:46:37 2021\n"))))
+
+(provide 'mail-utils-tests)
+;;; mail-utils-tests.el ends here
diff --git a/test/lisp/minibuffer-tests.el b/test/lisp/minibuffer-tests.el
index 7349b19..791e51c 100644
--- a/test/lisp/minibuffer-tests.el
+++ b/test/lisp/minibuffer-tests.el
@@ -125,5 +125,11 @@
      '(("completion1" "prefix1" #("suffix1" 0 7 (face shadow)))))
     (should (equal (get-text-property 19 'face) 'shadow))))
 
+(ert-deftest completion-pcm--optimize-pattern ()
+  (should (equal (completion-pcm--optimize-pattern '("buf" point "f"))
+                 '("buf" point "f")))
+  (should (equal (completion-pcm--optimize-pattern '(any "" any))
+                 '(any))))
+
 (provide 'minibuffer-tests)
 ;;; minibuffer-tests.el ends here
diff --git a/test/lisp/net/network-stream-tests.el 
b/test/lisp/net/network-stream-tests.el
index e0a06a2..1a4cc74 100644
--- a/test/lisp/net/network-stream-tests.el
+++ b/test/lisp/net/network-stream-tests.el
@@ -307,6 +307,7 @@
                                           :name "bar"
                                           :buffer (generate-new-buffer "*foo*")
                                           :nowait t
+                                          :family 'ipv4
                                           :tls-parameters
                                           (cons 'gnutls-x509pki
                                                 (gnutls-boot-parameters
diff --git a/test/lisp/net/ntlm-resources/authinfo 
b/test/lisp/net/ntlm-resources/authinfo
new file mode 100644
index 0000000..698391e
--- /dev/null
+++ b/test/lisp/net/ntlm-resources/authinfo
@@ -0,0 +1 @@
+machine localhost port http user ntlm password ntlm
diff --git a/test/lisp/net/ntlm-tests.el b/test/lisp/net/ntlm-tests.el
index 6408ac1..2420b3b 100644
--- a/test/lisp/net/ntlm-tests.el
+++ b/test/lisp/net/ntlm-tests.el
@@ -17,11 +17,26 @@
 ;; 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:
+
+;; Run this with `NTLM_TESTS_VERBOSE=1' to get verbose debugging.
+
+;;; Code:
+
 (require 'ert)
+(require 'ert-x)
 (require 'ntlm)
 
+(defsubst ntlm-tests-message (format-string &rest arguments)
+  "Print a message conditional on an environment variable being set.
+FORMAT-STRING and ARGUMENTS are passed to the message function."
+  (when (getenv "NTLM_TESTS_VERBOSE")
+    (apply #'message (concat "ntlm-tests: " format-string) arguments)))
+
+
 ;; This is the Lisp bignum implementation of `ntlm--time-to-timestamp',
 ;; for reference.
+
 (defun ntlm-tests--time-to-timestamp (time)
   "Convert TIME to an NTLMv2 timestamp.
 Return a unibyte string representing the number of tenths of a
@@ -49,4 +64,357 @@ signed integer.  TIME must be on the form (HIGH LOW USEC 
PSEC)."
     (should (equal (ntlm--time-to-timestamp time)
                    (ntlm-tests--time-to-timestamp time)))))
 
+(defvar ntlm-tests--username-oem "ntlm"
+  "The username for NTLM authentication tests, in OEM string encoding.")
+(defvar ntlm-tests--username-unicode
+  (ntlm-ascii2unicode ntlm-tests--username-oem
+                     (length ntlm-tests--username-oem))
+  "The username for NTLM authentication tests, in Unicode string encoding.")
+
+(defvar ntlm-tests--password "ntlm"
+  "The password used for NTLM authentication tests.")
+
+(defvar ntlm-tests--client-supports-unicode nil
+  "Non-nil if client supports Unicode strings.
+If client only supports OEM strings, nil.")
+
+(defvar ntlm-tests--challenge nil "The global random challenge.")
+
+(defun ntlm-server-build-type-2 ()
+  "Return an NTLM Type 2 message as a string.
+This string will be returned from the NTLM server to the NTLM client."
+  (let ((target (if ntlm-tests--client-supports-unicode
+                   (ntlm-ascii2unicode "DOMAIN" (length "DOMAIN"))
+                 "DOMAIN"))
+       (target-information ntlm-tests--password)
+       ;; Flag byte 1 flags.
+       (_negotiate-unicode 1)
+       (negotiate-oem 2)
+       (request-target 4)
+       ;; Flag byte 2 flags.
+       (negotiate-ntlm 2)
+       (_negotiate-local-call 4)
+       (_negotiate-always-sign 8)
+       ;; Flag byte 3 flags.
+       (_target-type-domain 1)
+       (_target-type-server 2)
+       (target-type-share 4)
+       (_negotiate-ntlm2-key 8)
+       (negotiate-target-information 128)
+       ;; Flag byte 4 flags, unused.
+       (_negotiate-128 32)
+       (_negotiate-56 128))
+    (concat
+     ;; Signature.
+     "NTLMSSP" (unibyte-string 0)
+     ;; Type 2.
+     (unibyte-string 2 0 0 0)
+     ;; Target length
+     (unibyte-string (length target) 0)
+     ;; Target allocated space.
+     (unibyte-string (length target) 0)
+     ;; Target offset.
+     (unibyte-string 48 0 0 0)
+     ;; Flags.
+     ;; Flag byte 1.
+     ;; Tell the client that this test server only supports OEM
+     ;; strings.  This test server will handle Unicode strings
+     ;; anyway though.
+     (unibyte-string (logior negotiate-oem request-target))
+     ;; Flag byte 2.
+     (unibyte-string negotiate-ntlm)
+     ;; Flag byte 3.
+     (unibyte-string (logior negotiate-target-information target-type-share))
+     ;; Flag byte 4.   Not sure what 2 means here.
+     (unibyte-string 2)
+     ;; Challenge.  Set this to (unibyte-string 1 2 3 4 5 6 7 8)
+     ;; instead of (ntlm-generate-nonce) to hold constant for
+     ;; debugging.
+     (setq ntlm-tests--challenge (ntlm-generate-nonce))
+     ;; Context.
+     (make-string 8 0)
+     (unibyte-string (length target-information) 0)
+     (unibyte-string (length target-information) 0)
+     (unibyte-string 54 0 0 0)
+     target
+     target-information)))
+
+(defun ntlm-server-hash (challenge blob username password)
+  "Hash CHALLENGE, BLOB, USERNAME and PASSWORD for a Type 3 check."
+  (hmac-md5 (concat challenge blob)
+           (hmac-md5 (concat
+                      (upcase
+                       ;; This calculation always uses
+                       ;; Unicode username, even when the
+                       ;; server only supports OEM strings.
+                       (ntlm-ascii2unicode username (length username))) "")
+                     (cadr (ntlm-get-password-hashes password)))))
+
+(defun ntlm-server-check-authorization (authorization-string)
+  "Return t if AUTHORIZATION-STRING correctly authenticates the user."
+  (let* ((binary (base64-decode-string
+                 (caddr (split-string authorization-string " "))))
+        (_lm-response-length (md4-unpack-int16 (substring binary 12 14)))
+        (_lm-response-offset
+         (cdr (md4-unpack-int32 (substring binary 16 20))))
+        (ntlm-response-length (md4-unpack-int16 (substring binary 20 22)))
+        (ntlm-response-offset
+         (cdr (md4-unpack-int32 (substring binary 24 28))))
+        (ntlm-hash
+         (substring binary ntlm-response-offset (+ ntlm-response-offset 16)))
+        (username-length (md4-unpack-int16 (substring binary 36 38)))
+        (username-offset (cdr (md4-unpack-int32 (substring binary 40 44))))
+        (username (substring binary username-offset
+                             (+ username-offset username-length))))
+    (if (equal ntlm-response-length 24)
+       (let* ((expected
+               (ntlm-smb-owf-encrypt
+                (cadr (ntlm-get-password-hashes ntlm-tests--password))
+                ntlm-tests--challenge))
+              (received (substring binary ntlm-response-offset
+                                   (+ ntlm-response-offset
+                                      ntlm-response-length))))
+         (ntlm-tests-message "Got NTLMv1 response:")
+         (ntlm-tests-message "Expected hash:     ===%S===" expected)
+         (ntlm-tests-message "Got      hash:     ===%S===" received)
+         (ntlm-tests-message "Expected username: ===%S==="
+                             ntlm-tests--username-oem)
+         (ntlm-tests-message "Got      username: ===%S===" username)
+         (and (or (equal username ntlm-tests--username-oem)
+                  (equal username ntlm-tests--username-unicode))
+              (equal expected received)))
+      (let* ((ntlm-response-blob
+             (substring binary (+ ntlm-response-offset 16)
+                        (+ (+ ntlm-response-offset 16)
+                           (- ntlm-response-length 16))))
+            (_ntlm-timestamp (substring ntlm-response-blob 8 16))
+            (_ntlm-nonce (substring ntlm-response-blob 16 24))
+            (_target-length (md4-unpack-int16 (substring binary 28 30)))
+            (_target-offset
+             (cdr (md4-unpack-int32 (substring binary 32 36))))
+            (_workstation-length (md4-unpack-int16 (substring binary 44 46)))
+            (_workstation-offset
+             (cdr (md4-unpack-int32 (substring binary 48 52)))))
+       (cond
+        ;; This test server claims to only support OEM strings,
+        ;; but also checks Unicode strings.
+        ((or (equal username ntlm-tests--username-oem)
+             (equal username ntlm-tests--username-unicode))
+         (let* ((password ntlm-tests--password)
+                (ntlm-hash-from-type-3 (ntlm-server-hash
+                                        ntlm-tests--challenge
+                                        ntlm-response-blob
+                                        ;; Always -oem since
+                                        ;; `ntlm-server-hash'
+                                        ;; always converts it to
+                                        ;; Unicode.
+                                        ntlm-tests--username-oem
+                                        password)))
+           (ntlm-tests-message "Got NTLMv2 response:")
+           (ntlm-tests-message "Expected hash: ==%S==" ntlm-hash)
+           (ntlm-tests-message "Got      hash: ==%S==" ntlm-hash-from-type-3)
+           (ntlm-tests-message "Expected username: ===%S==="
+                               ntlm-tests--username-oem)
+           (ntlm-tests-message "      or username: ===%S==="
+                    ntlm-tests--username-unicode)
+           (ntlm-tests-message "Got      username: ===%S===" username)
+           (equal ntlm-hash ntlm-hash-from-type-3)))
+        (t
+         nil))))))
+
+(require 'eieio)
+(require 'cl-lib)
+
+;; Silence some byte-compiler warnings that occur when
+;; web-server/web-server.el is not found.
+(declare-function ws-send nil)
+(declare-function ws-parse-request nil)
+(declare-function ws-start nil)
+(declare-function ws-stop-all nil)
+
+(require 'web-server nil t)
+(require 'url-http-ntlm nil t)
+
+(defun ntlm-server-do-token (request _process)
+  "Process an NTLM client's REQUEST.
+PROCESS is unused."
+  (with-slots (process headers) request
+    (let* ((header-alist (cdr headers))
+          (authorization-header (assoc ':AUTHORIZATION header-alist))
+          (authorization-string (cdr authorization-header)))
+      (if (and (stringp authorization-string)
+              (string-match "NTLM " authorization-string))
+         (let* ((challenge (substring authorization-string (match-end 0)))
+                (binary (base64-decode-string challenge))
+                (type (aref binary 8))
+                ;; Flag byte 1 flags.
+                (negotiate-unicode 1)
+                (negotiate-oem 2)
+                (flags-byte-1 (aref binary 12))
+                (client-supports-unicode
+                 (not (zerop (logand flags-byte-1 negotiate-unicode))))
+                (client-supports-oem
+                 (not (zerop (logand flags-byte-1 negotiate-oem))))
+                (connection-header (assoc ':CONNECTION header-alist))
+                (_keep-alive
+                 (when connection-header (cdr connection-header)))
+                (response
+                 (cl-case type
+                   (1
+                    ;; Return Type 2 message.
+                    (when (and (not client-supports-unicode)
+                               (not client-supports-oem))
+                      (warn (concat
+                             "Weird client supports neither Unicode"
+                             " nor OEM strings, using OEM.")))
+                    (setq ntlm-tests--client-supports-unicode
+                          client-supports-unicode)
+                    (concat
+                     "HTTP/1.1 401 Unauthorized\r\n"
+                     "WWW-Authenticate: NTLM "
+                     (base64-encode-string
+                      (ntlm-server-build-type-2) t) "\r\n"
+                     "WWW-Authenticate: Negotiate\r\n"
+                     "WWW-Authenticate: Basic realm=\"domain\"\r\n"
+                     "Content-Length: 0\r\n\r\n"))
+                   (3
+                    (if (ntlm-server-check-authorization
+                         authorization-string)
+                        "HTTP/1.1 200 OK\r\n\r\nAuthenticated.\r\n"
+                      (progn
+                        (if process
+                            (set-process-filter process nil)
+                          (error "Type 3 message found first?"))
+                        (concat "HTTP/1.1 401 Unauthorized\r\n\r\n"
+                                "Access Denied.\r\n")))))))
+           (if response
+               (ws-send process response)
+             (when process
+               (set-process-filter process nil)))
+           (when (equal type 3)
+             (set-process-filter process nil)
+             (process-send-eof process)))
+       (progn
+         ;; Did not get NTLM anything.
+         (set-process-filter process nil)
+         (process-send-eof process)
+         (concat "HTTP/1.1 401 Unauthorized\r\n\r\n"
+                 "Access Denied.\r\n"))))))
+
+(defun ntlm-server-filter (process string)
+  "Read from PROCESS a STRING and treat it as a request from an NTLM client."
+  (let ((request (make-instance 'ws-request
+                               :process process :pending string)))
+    (if (ws-parse-request request)
+       (ntlm-server-do-token request process)
+      (error "Failed to parse request"))))
+
+(defun ntlm-server-handler (request)
+  "Handle an HTTP REQUEST."
+  (with-slots (process headers) request
+    (let* ((header-alist (cdr headers))
+          (authorization-header (assoc ':AUTHORIZATION header-alist))
+          (connection-header (assoc ':CONNECTION header-alist))
+          (keep-alive (when connection-header (cdr connection-header)))
+          (response (concat
+                     "HTTP/1.1 401 Unauthorized\r\n"
+                     "WWW-Authenticate: Negotiate\r\n"
+                     "WWW-Authenticate: NTLM\r\n"
+                     "WWW-Authenticate: Basic realm=\"domain\"\r\n"
+                     "Content-Length: 0\r\n\r\n")))
+      (if (null authorization-header)
+         ;; Tell client to use NTLM.    Firefox will create a new
+         ;; connection.
+         (progn
+           (process-send-string process response)
+           (process-send-eof process))
+       (progn
+         (ntlm-server-do-token request nil)
+         (set-process-filter process #'ntlm-server-filter)
+         (if (equal (upcase keep-alive) "KEEP-ALIVE")
+             :keep-alive
+           (error "NTLM server expects keep-alive connection header")))))))
+
+(defun ntlm-server-start ()
+  "Start an NTLM server on port 8080 for testing."
+  (ws-start 'ntlm-server-handler 8080))
+
+(defun ntlm-server-stop ()
+  "Stop the NTLM server."
+  (ws-stop-all))
+
+(defvar ntlm-tests--result-buffer nil "Final NTLM result buffer.")
+
+(require 'url)
+
+(defun ntlm-tests--url-retrieve-internal-around (original &rest arguments)
+  "Save the result buffer from a `url-retrieve-internal' to a global variable.
+ORIGINAL is the original `url-retrieve-internal' function and
+ARGUMENTS are passed to it."
+  (setq ntlm-tests--result-buffer (apply original arguments)))
+
+(defun ntlm-tests--authenticate ()
+  "Authenticate using credentials from the authinfo resource file."
+  (setq ntlm-tests--result-buffer nil)
+  (let ((auth-sources (list (ert-resource-file "authinfo")))
+       (auth-source-do-cache nil)
+       (auth-source-debug (when (getenv "NTLM_TESTS_VERBOSE") 'trivia)))
+    (ntlm-tests-message "Using auth-sources: %S" auth-sources)
+    (url-retrieve-synchronously "http://localhost:8080";))
+  (sleep-for 0.1)
+  (ntlm-tests-message "Results are in: %S" ntlm-tests--result-buffer)
+  (with-current-buffer ntlm-tests--result-buffer
+    (buffer-string)))
+
+(defun ntlm-tests--start-server-authenticate-stop-server ()
+  "Start an NTLM server, authenticate against it, then stop the server."
+  (advice-add #'url-retrieve-internal
+             :around #'ntlm-tests--url-retrieve-internal-around)
+  (ntlm-server-stop)
+  (ntlm-server-start)
+  (let ((result (ntlm-tests--authenticate)))
+    (advice-remove #'url-retrieve-internal
+                  #'ntlm-tests--url-retrieve-internal-around)
+    (ntlm-server-stop)
+    result))
+
+(defvar ntlm-tests--successful-result
+  (concat "HTTP/1.1 200 OK\n\nAuthenticated." (unibyte-string 13) "\n")
+  "Expected result of successful NTLM authentication.")
+
+(require 'find-func)
+(defun ntlm-tests--ensure-ws-parse-ntlm-support ()
+  "Ensure NTLM special-case in `ws-parse'."
+  (let* ((hit (find-function-search-for-symbol
+              'ws-parse nil (locate-file "web-server.el" load-path)))
+        (buffer (car hit))
+        (position (cdr hit)))
+    (with-current-buffer buffer
+      (goto-char position)
+      (search-forward-regexp
+       ":NTLM" (save-excursion (forward-sexp) (point)) t))))
+
+(require 'lisp-mnt)
+(defvar ntlm-tests--dependencies-present
+  (and (featurep 'url-http-ntlm)
+       (version<= "2.0.4"
+                 (lm-version (locate-file "url-http-ntlm.el" load-path)))
+       (featurep 'web-server)
+       (ntlm-tests--ensure-ws-parse-ntlm-support))
+  "Non-nil if GNU ELPA test dependencies were loaded.")
+
+(ert-deftest ntlm-authentication ()
+  "Check ntlm.el's implementation of NTLM authentication over HTTP."
+  (skip-unless ntlm-tests--dependencies-present)
+  (should (equal (ntlm-tests--start-server-authenticate-stop-server)
+                ntlm-tests--successful-result)))
+
+(ert-deftest ntlm-authentication-old-compatibility-level ()
+  (skip-unless ntlm-tests--dependencies-present)
+  (setq ntlm-compatibility-level 0)
+  (should (equal (ntlm-tests--start-server-authenticate-stop-server)
+                ntlm-tests--successful-result)))
+
 (provide 'ntlm-tests)
+
+;;; ntlm-tests.el ends here
diff --git a/test/lisp/net/puny-tests.el b/test/lisp/net/puny-tests.el
index b37168f..28c0d49 100644
--- a/test/lisp/net/puny-tests.el
+++ b/test/lisp/net/puny-tests.el
@@ -39,10 +39,12 @@
   (should (string= (puny-decode-string "xn--9dbdkw") "חנוך")))
 
 (ert-deftest puny-test-encode-domain ()
-  (should (string= (puny-encode-domain "åäö.se") "xn--4cab6c.se")))
+  (should (string= (puny-encode-domain "åäö.se") "xn--4cab6c.se"))
+  (should (string= (puny-encode-domain "яндекс.рф") "xn--d1acpjx3f.xn--p1ai")))
 
 (ert-deftest puny-test-decode-domain ()
-  (should (string= (puny-decode-domain "xn--4cab6c.se") "åäö.se")))
+  (should (string= (puny-decode-domain "xn--4cab6c.se") "åäö.se"))
+  (should (string= (puny-decode-domain "xn--d1acpjx3f.xn--p1ai") "яндекс.рф")))
 
 (ert-deftest puny-highly-restrictive-domain-p ()
   (should (puny-highly-restrictive-domain-p "foo.bar.org"))
diff --git a/test/lisp/net/socks-tests.el b/test/lisp/net/socks-tests.el
index b378ed2..71bdd74 100644
--- a/test/lisp/net/socks-tests.el
+++ b/test/lisp/net/socks-tests.el
@@ -21,68 +21,151 @@
 
 ;;; Code:
 
+(require 'ert)
 (require 'socks)
 (require 'url-http)
 
-(defvar socks-tests-canned-server-port nil)
+(ert-deftest socks-tests-auth-registration-and-suite-offer ()
+  (ert-info ("Default favors user/pass auth")
+    (should (equal socks-authentication-methods
+                   '((2 "Username/Password" . socks-username/password-auth)
+                     (0 "No authentication" . identity))))
+    (should (equal "\2\0\2" (socks-build-auth-list)))) ; length [offer ...]
+  (let (socks-authentication-methods)
+    (ert-info ("Empty selection/no methods offered")
+      (should (equal "\0" (socks-build-auth-list))))
+    (ert-info ("Simulate library defaults")
+      (socks-register-authentication-method 0 "No authentication"
+                                            'identity)
+      (should (equal socks-authentication-methods
+                     '((0 "No authentication" . identity))))
+      (should (equal "\1\0" (socks-build-auth-list)))
+      (socks-register-authentication-method 2 "Username/Password"
+                                            'socks-username/password-auth)
+      (should (equal socks-authentication-methods
+                     '((2 "Username/Password" . socks-username/password-auth)
+                       (0 "No authentication" . identity))))
+      (should (equal "\2\0\2" (socks-build-auth-list))))
+    (ert-info ("Removal")
+      (socks-unregister-authentication-method 2)
+      (should (equal socks-authentication-methods
+                     '((0 "No authentication" . identity))))
+      (should (equal "\1\0" (socks-build-auth-list)))
+      (socks-unregister-authentication-method 0)
+      (should-not socks-authentication-methods)
+      (should (equal "\0" (socks-build-auth-list))))))
 
-(defun socks-tests-canned-server-create (verbatim patterns)
-  "Create a fake SOCKS server and return the process.
+(ert-deftest socks-tests-filter-response-parsing-v4 ()
+  "Ensure new chunks added on right (Bug#45162)."
+  (let* ((buf (generate-new-buffer "*test-socks-filter*"))
+         (proc (start-process "test-socks-filter" buf "sleep" "1")))
+    (process-put proc 'socks t)
+    (process-put proc 'socks-state socks-state-waiting)
+    (process-put proc 'socks-server-protocol 4)
+    (ert-info ("Receive initial incomplete segment")
+      (socks-filter proc (concat [0 90 0 0 93 184 216]))
+      ;; From example.com: OK status ^      ^ msg start
+      (ert-info ("State still set to waiting")
+        (should (eq (process-get proc 'socks-state) socks-state-waiting)))
+      (ert-info ("Response field is nil because processing incomplete")
+        (should-not (process-get proc 'socks-response)))
+      (ert-info ("Scratch field holds stashed partial payload")
+        (should (string= (concat [0 90 0 0 93 184 216])
+                         (process-get proc 'socks-scratch)))))
+    (ert-info ("Last part arrives")
+      (socks-filter proc "\42") ; ?\" 34
+      (ert-info ("State transitions to complete (length check passes)")
+        (should (eq (process-get proc 'socks-state) socks-state-connected)))
+      (ert-info ("Scratch and response fields hold stash w. last chunk")
+        (should (string= (concat [0 90 0 0 93 184 216 34])
+                         (process-get proc 'socks-response)))
+        (should (string= (process-get proc 'socks-response)
+                         (process-get proc 'socks-scratch)))))
+    (delete-process proc)
+    (kill-buffer buf)))
 
-`VERBATIM' and `PATTERNS' are dotted alists containing responses.
-Requests are tried in order.  On failure, an error is raised."
-  (let* ((buf (generate-new-buffer "*canned-socks-server*"))
+(ert-deftest socks-tests-filter-response-parsing-v5 ()
+  "Ensure new chunks added on right (Bug#45162)."
+  (let* ((buf (generate-new-buffer "*test-socks-filter*"))
+         (proc (start-process "test-socks-filter" buf "sleep" "1")))
+    (process-put proc 'socks t)
+    (process-put proc 'socks-state socks-state-waiting)
+    (process-put proc 'socks-server-protocol 5)
+    (ert-info ("Receive initial incomplete segment")
+      ;; From fedora.org: 2605:bc80:3010:600:dead:beef:cafe:fed9
+      ;; 5004 ~~> Version Status (OK) NOOP Addr-Type (4 -> IPv6)
+      (socks-filter proc "\5\0\0\4\x26\x05\xbc\x80\x30\x10\x00\x60")
+      (ert-info ("State still waiting and response emtpy")
+        (should (eq (process-get proc 'socks-state) socks-state-waiting))
+        (should-not (process-get proc 'socks-response)))
+      (ert-info ("Scratch field holds partial payload of pending msg")
+        (should (string= "\5\0\0\4\x26\x05\xbc\x80\x30\x10\x00\x60"
+                         (process-get proc 'socks-scratch)))))
+    (ert-info ("Middle chunk arrives")
+      (socks-filter proc "\xde\xad\xbe\xef\xca\xfe\xfe\xd9")
+      (ert-info ("State and response fields still untouched")
+        (should (eq (process-get proc 'socks-state) socks-state-waiting))
+        (should-not (process-get proc 'socks-response)))
+      (ert-info ("Scratch contains new arrival appended (on RHS)")
+        (should (string=  (concat "\5\0\0\4"
+                                  "\x26\x05\xbc\x80\x30\x10\x00\x60"
+                                  "\xde\xad\xbe\xef\xca\xfe\xfe\xd9")
+                          (process-get proc 'socks-scratch)))))
+    (ert-info ("Final part arrives (port number)")
+      (socks-filter proc "\0\0")
+      (ert-info ("State transitions to complete")
+        (should (eq (process-get proc 'socks-state) socks-state-connected)))
+      (ert-info ("Scratch and response fields show last chunk appended")
+        (should (string=  (concat "\5\0\0\4"
+                                  "\x26\x05\xbc\x80\x30\x10\x00\x60"
+                                  "\xde\xad\xbe\xef\xca\xfe\xfe\xd9"
+                                  "\0\0")
+                          (process-get proc 'socks-scratch)))
+        (should (string= (process-get proc 'socks-response)
+                         (process-get proc 'socks-scratch)))))
+    (delete-process proc)
+    (kill-buffer buf)))
+
+(defvar socks-tests-canned-server-patterns nil
+  "Alist containing request/response cons pairs to be tried in order.
+Vectors must match verbatim. Strings are considered regex patterns.")
+
+(defun socks-tests-canned-server-create ()
+  "Create and return a fake SOCKS server."
+  (let* ((port (nth 2 socks-server))
+         (name (format "socks-server:%d" port))
+         (pats socks-tests-canned-server-patterns)
          (filt (lambda (proc line)
-                 (let ((resp (or (assoc-default line verbatim
-                                                (lambda (k s) ; s is line
-                                                  (string= (concat k) s)))
-                                 (assoc-default line patterns
-                                                (lambda (p s)
-                                                  (string-match-p p s))))))
-                   (unless resp
+                 (pcase-let ((`(,pat . ,resp) (pop pats)))
+                   (unless (or (and (vectorp pat) (equal pat (vconcat line)))
+                               (string-match-p pat line))
                      (error "Unknown request: %s" line))
                    (let ((print-escape-control-characters t))
-                     (princ (format "<- %s\n" (prin1-to-string line)) buf)
-                     (princ (format "-> %s\n" (prin1-to-string resp)) buf))
+                     (message "[%s] <- %s" name (prin1-to-string line))
+                     (message "[%s] -> %s" name (prin1-to-string resp)))
                    (process-send-string proc (concat resp)))))
-         (srv (make-network-process :server 1
-                                    :buffer buf
-                                    :filter filt
-                                    :name "server"
-                                    :family 'ipv4
-                                    :host 'local
-                                    :service socks-tests-canned-server-port)))
-    (set-process-query-on-exit-flag srv nil)
-    (princ (format "[%s] Listening on localhost:10080\n" srv) buf)
-    srv))
-
-;; Add ([5 3 0 1 2] . [5 2]) to the `verbatim' list below to validate
-;; against curl 7.71 with the following options:
-;; $ curl --verbose -U foo:bar --proxy socks5h://127.0.0.1:10080 example.com
-;;
-;; If later implementing version 4a, try these:
-;; [4 1 0 80 0 0 0 1 0 ?e ?x ?a ?m ?p ?l ?e ?. ?c ?o ?m 0] . [0 90 0 0 0 0 0 0]
-;; $ curl --verbose --proxy socks4a://127.0.0.1:10080 example.com
+         (serv (make-network-process :server 1
+                                     :buffer (get-buffer-create name)
+                                     :filter filt
+                                     :name name
+                                     :family 'ipv4
+                                     :host 'local
+                                     :coding 'binary
+                                     :service port)))
+    (set-process-query-on-exit-flag serv nil)
+    serv))
 
-(ert-deftest socks-tests-auth-filter-url-http ()
-  "Verify correct handling of SOCKS5 user/pass authentication."
-  (let* ((socks-server '("server" "127.0.0.1" 10080 5))
-         (socks-username "foo")
-         (socks-password "bar")
-         (url-gateway-method 'socks)
+(defvar socks-tests--hello-world-http-request-pattern
+  (cons "^GET /" (concat "HTTP/1.1 200 OK\r\n"
+                         "Content-Type: text/plain\r\n"
+                         "Content-Length: 13\r\n\r\n"
+                         "Hello World!\n")))
+
+(defun socks-tests-perform-hello-world-http-request ()
+  "Start canned server, validate hello-world response, and finalize."
+  (let* ((url-gateway-method 'socks)
          (url (url-generic-parse-url "http://example.com";))
-         (verbatim '(([5 2 0 2] . [5 2])
-                     ([1 3 ?f ?o ?o 3 ?b ?a ?r] . [1 0])
-                     ([5 1 0 3 11 ?e ?x ?a ?m ?p ?l ?e ?. ?c ?o ?m 0 80]
-                      . [5 0 0 1 0 0 0 0 0 0])))
-         (patterns
-          `(("^GET /" . ,(concat "HTTP/1.1 200 OK\r\n"
-                                 "Content-Type: text/plain; charset=UTF-8\r\n"
-                                 "Content-Length: 13\r\n\r\n"
-                                 "Hello World!\n"))))
-         (socks-tests-canned-server-port 10080)
-         (server (socks-tests-canned-server-create verbatim patterns))
-         (tries 10)
+         (server (socks-tests-canned-server-create))
          ;;
          done
          ;;
@@ -90,14 +173,112 @@ Requests are tried in order.  On failure, an error is 
raised."
                (goto-char (point-min))
                (should (search-forward "Hello World" nil t))
                (setq done t)))
-         (buf (url-http url cb '(nil))))
-    (ert-info ("Connect to HTTP endpoint over SOCKS5 with USER/PASS method")
-      (while (and (not done) (< 0 (cl-decf tries))) ; cl-lib via url-http
-        (sleep-for 0.1)))
+         (inhibit-message noninteractive)
+         (buf (url-http url cb '(nil)))
+         (proc (get-buffer-process buf))
+         (attempts 10))
+    (while (and (not done) (< 0 (cl-decf attempts)))
+      (sleep-for 0.1))
     (should done)
     (delete-process server)
+    (delete-process proc) ; otherwise seems client proc is sometimes reused
     (kill-buffer (process-buffer server))
     (kill-buffer buf)
     (ignore url-gateway-method)))
 
+;; Unlike curl, socks.el includes the ID field (but otherwise matches):
+;; $ curl --proxy socks4://127.0.0.1:1080 example.com
+
+(ert-deftest socks-tests-v4-basic ()
+  "Show correct preparation of SOCKS4 connect command (Bug#46342)."
+  (let ((socks-server '("server" "127.0.0.1" 10079 4))
+        (url-user-agent "Test/4-basic")
+        (socks-tests-canned-server-patterns
+         `(([4 1 0 80 93 184 216 34 ?f ?o ?o 0] . [0 90 0 0 0 0 0 0])
+           ,socks-tests--hello-world-http-request-pattern))
+        socks-nslookup-program)
+    (ert-info ("Make HTTP request over SOCKS4")
+      (cl-letf (((symbol-function 'socks-nslookup-host)
+                 (lambda (host)
+                   (should (equal host "example.com"))
+                   (list 93 184 216 34)))
+                ((symbol-function 'user-full-name)
+                 (lambda () "foo")))
+        (socks-tests-perform-hello-world-http-request)))))
+
+;; Replace first pattern below with ([5 3 0 1 2] . [5 2]) to validate
+;; against curl 7.71 with the following options:
+;; $ curl --verbose -U foo:bar --proxy socks5h://127.0.0.1:10080 example.com
+
+(ert-deftest socks-tests-v5-auth-user-pass ()
+  "Verify correct handling of SOCKS5 user/pass authentication."
+  (should (assq 2 socks-authentication-methods))
+  (let ((socks-server '("server" "127.0.0.1" 10080 5))
+        (socks-username "foo")
+        (socks-password "bar")
+        (url-user-agent "Test/auth-user-pass")
+        (socks-tests-canned-server-patterns
+         `(([5 2 0 2] . [5 2])
+           ([1 3 ?f ?o ?o 3 ?b ?a ?r] . [1 0])
+           ([5 1 0 3 11 ?e ?x ?a ?m ?p ?l ?e ?. ?c ?o ?m 0 80]
+            . [5 0 0 1 0 0 0 0 0 0])
+           ,socks-tests--hello-world-http-request-pattern)))
+    (ert-info ("Make HTTP request over SOCKS5 with USER/PASS auth method")
+      (socks-tests-perform-hello-world-http-request))))
+
+;; Services (like Tor) may be configured without auth but for some
+;; reason still prefer the user/pass method over none when offered both.
+;; Given this library's defaults, the scenario below is possible.
+;;
+;; FYI: RFC 1929 doesn't say that a username or password is required
+;; but notes that the length of both fields should be at least one.
+;; However, both socks.el and curl send zero-length fields (though
+;; curl drops the user part too when the password is empty).
+;;
+;; From Tor's docs /socks-extensions.txt, 1.1 Extent of support:
+;; > We allow username/password fields of this message to be empty ...
+;; line 41 in blob 5fd1f828f3e9d014f7b65fa3bd1d33c39e4129e2
+;; https://gitweb.torproject.org/torspec.git/tree/socks-extensions.txt
+;;
+;; To verify against curl 7.71, swap out the first two pattern pairs
+;; with ([5 3 0 1 2] . [5 2]) and ([1 0 0] . [1 0]), then run:
+;; $ curl verbose -U "foo:" --proxy socks5h://127.0.0.1:10081 example.com
+
+(ert-deftest socks-tests-v5-auth-user-pass-blank ()
+  "Verify correct SOCKS5 user/pass authentication with empty pass."
+  (should (assq 2 socks-authentication-methods))
+  (let ((socks-server '("server" "127.0.0.1" 10081 5))
+        (socks-username "foo") ; defaults to (user-login-name)
+        (socks-password "") ; simulate user hitting enter when prompted
+        (url-user-agent "Test/auth-user-pass-blank")
+        (socks-tests-canned-server-patterns
+         `(([5 2 0 2] . [5 2])
+           ([1 3 ?f ?o ?o 0] . [1 0])
+           ([5 1 0 3 11 ?e ?x ?a ?m ?p ?l ?e ?. ?c ?o ?m 0 80]
+            . [5 0 0 1 0 0 0 0 0 0])
+           ,socks-tests--hello-world-http-request-pattern)))
+    (ert-info ("Make HTTP request over SOCKS5 with USER/PASS auth method")
+      (socks-tests-perform-hello-world-http-request))))
+
+;; Swap out ([5 2 0 1] . [5 0]) with the first pattern below to validate
+;; against curl 7.71 with the following options:
+;; $ curl --verbose --proxy socks5h://127.0.0.1:10082 example.com
+
+(ert-deftest socks-tests-v5-auth-none ()
+  "Verify correct handling of SOCKS5 when auth method 0 requested."
+  (let ((socks-server '("server" "127.0.0.1" 10082 5))
+        (socks-authentication-methods (append socks-authentication-methods
+                                              nil))
+        (url-user-agent "Test/auth-none")
+        (socks-tests-canned-server-patterns
+         `(([5 1 0] . [5 0])
+           ([5 1 0 3 11 ?e ?x ?a ?m ?p ?l ?e ?. ?c ?o ?m 0 80]
+            . [5 0 0 1 0 0 0 0 0 0])
+           ,socks-tests--hello-world-http-request-pattern)))
+    (socks-unregister-authentication-method 2)
+    (should-not (assq 2 socks-authentication-methods))
+    (ert-info ("Make HTTP request over SOCKS5 with no auth method")
+      (socks-tests-perform-hello-world-http-request)))
+  (should (assq 2 socks-authentication-methods)))
+
 ;;; socks-tests.el ends here
diff --git a/test/lisp/net/tramp-tests.el b/test/lisp/net/tramp-tests.el
index f488392..be428fc 100644
--- a/test/lisp/net/tramp-tests.el
+++ b/test/lisp/net/tramp-tests.el
@@ -2182,6 +2182,16 @@ is greater than 10.
       (expand-file-name ".." "./"))
     (concat (file-remote-p tramp-test-temporary-file-directory) "/"))))
 
+(ert-deftest tramp-test05-expand-file-name-top ()
+  "Check `expand-file-name'."
+  (skip-unless (tramp--test-enabled))
+  (skip-unless (not (tramp--test-ange-ftp-p)))
+
+  (let ((dir (concat (file-remote-p tramp-test-temporary-file-directory) "/")))
+    (dolist (local '("." ".."))
+      (should (string-equal (expand-file-name local dir) dir))
+      (should (string-equal (expand-file-name (concat dir local)) dir)))))
+
 (ert-deftest tramp-test06-directory-file-name ()
   "Check `directory-file-name'.
 This checks also `file-name-as-directory', `file-name-directory',
@@ -2814,9 +2824,10 @@ This tests also `file-directory-p' and 
`file-accessible-directory-p'."
          (should (file-exists-p (expand-file-name "bla" tmp-name2)))
          (should-error
           (delete-directory tmp-name1 nil 'trash)
-          ;; tramp-rclone.el calls the local `delete-directory'.
-          ;; This raises another error.
-          :type (if (tramp--test-rclone-p) 'error 'file-error))
+          ;; tramp-rclone.el and tramp-sshfs.el call the local
+          ;; `delete-directory'.  This raises another error.
+          :type (if (or (tramp--test-rclone-p) (tramp--test-sshfs-p))
+                    'error 'file-error))
          (delete-directory tmp-name1 'recursive 'trash)
          (should-not (file-directory-p tmp-name1))
          (should
@@ -3244,8 +3255,8 @@ This tests also `file-directory-p' and 
`file-accessible-directory-p'."
        (ignore-errors (delete-directory tmp-name1 'recursive))))))
 
 ;; Method "smb" supports `make-symbolic-link' only if the remote host
-;; has CIFS capabilities.  tramp-adb.el, tramp-gvfs.el and
-;; tramp-rclone.el do not support symbolic links at all.
+;; has CIFS capabilities.  tramp-adb.el, tramp-gvfs.el, tramp-rclone.el
+;; and tramp-sshfs.el do not support symbolic links at all.
 (defmacro tramp--test-ignore-make-symbolic-link-error (&rest body)
   "Run BODY, ignoring \"make-symbolic-link not supported\" file error."
   (declare (indent defun) (debug (body)))
@@ -3526,7 +3537,7 @@ They might differ only in time attributes or directory 
size."
 This tests also `file-executable-p', `file-writable-p' and `set-file-modes'."
   (skip-unless (tramp--test-enabled))
   (skip-unless
-   (or (tramp--test-sh-p) (tramp--test-sudoedit-p)
+   (or (tramp--test-sh-p) (tramp--test-sshfs-p) (tramp--test-sudoedit-p)
        ;; Not all tramp-gvfs.el methods support changing the file mode.
        (and
        (tramp--test-gvfs-p)
@@ -4357,11 +4368,15 @@ This tests also `make-symbolic-link', `file-truename' 
and `add-name-to-file'."
          (and (featurep 'tramp-test-load) (unload-feature 'tramp-test-load))
          (delete-file tmp-name))))))
 
+(defun tramp--test-shell-file-name ()
+  "Return default remote shell.."
+  (if (tramp--test-adb-p) "/system/bin/sh" "/bin/sh"))
+
 (ert-deftest tramp-test28-process-file ()
   "Check `process-file'."
   :tags '(:expensive-test)
   (skip-unless (tramp--test-enabled))
-  (skip-unless (or (tramp--test-adb-p) (tramp--test-sh-p)))
+  (skip-unless (or (tramp--test-adb-p) (tramp--test-sh-p) 
(tramp--test-sshfs-p)))
   (skip-unless (not (tramp--test-crypt-p)))
 
   (dolist (quoted (if (tramp--test-expensive-test) '(nil t) '(nil)))
@@ -4378,25 +4393,27 @@ This tests also `make-symbolic-link', `file-truename' 
and `add-name-to-file'."
            (should-not (zerop (process-file "binary-does-not-exist")))
            ;; Return exit code.
            (should (= 42 (process-file
-                          (if (tramp--test-adb-p) "/system/bin/sh" "/bin/sh")
+                          (tramp--test-shell-file-name)
                           nil nil nil "-c" "exit 42")))
            ;; Return exit code in case the process is interrupted,
            ;; and there's no indication for a signal describing string.
-           (let (process-file-return-signal-string)
-             (should
-              (= (+ 128 2)
-                 (process-file
-                  (if (tramp--test-adb-p) "/system/bin/sh" "/bin/sh")
-                  nil nil nil "-c" "kill -2 $$"))))
+           (unless (tramp--test-sshfs-p)
+             (let (process-file-return-signal-string)
+               (should
+                (= (+ 128 2)
+                   (process-file
+                    (tramp--test-shell-file-name)
+                    nil nil nil "-c" "kill -2 $$")))))
            ;; Return string in case the process is interrupted and
            ;; there's an indication for a signal describing string.
-           (let ((process-file-return-signal-string t))
-             (should
-              (string-match-p
-               "Interrupt\\|Signal 2"
-               (process-file
-                (if (tramp--test-adb-p) "/system/bin/sh" "/bin/sh")
-                nil nil nil "-c" "kill -2 $$"))))
+           (unless (tramp--test-sshfs-p)
+             (let ((process-file-return-signal-string t))
+               (should
+                (string-match-p
+                 "Interrupt\\|Signal 2"
+                 (process-file
+                  (tramp--test-shell-file-name)
+                  nil nil nil "-c" "kill -2 $$")))))
 
            (with-temp-buffer
              (write-region "foo" nil tmp-name)
@@ -4440,7 +4457,7 @@ This tests also `make-symbolic-link', `file-truename' and 
`add-name-to-file'."
   "Check `start-file-process'."
   :tags '(:expensive-test)
   (skip-unless (tramp--test-enabled))
-  (skip-unless (or (tramp--test-adb-p) (tramp--test-sh-p)))
+  (skip-unless (or (tramp--test-adb-p) (tramp--test-sh-p) 
(tramp--test-sshfs-p)))
   (skip-unless (not (tramp--test-crypt-p)))
 
   (dolist (quoted (if (tramp--test-expensive-test) '(nil t) '(nil)))
@@ -4560,7 +4577,7 @@ If UNSTABLE is non-nil, the test is tagged as 
`:unstable'."
   "Check `make-process'."
   :tags '(:expensive-test)
   (skip-unless (tramp--test-enabled))
-  (skip-unless (or (tramp--test-adb-p) (tramp--test-sh-p)))
+  (skip-unless (or (tramp--test-adb-p) (tramp--test-sh-p) 
(tramp--test-sshfs-p)))
   (skip-unless (not (tramp--test-crypt-p)))
   ;; `make-process' supports file name handlers since Emacs 27.
   (skip-unless (tramp--test-emacs27-p))
@@ -4788,7 +4805,7 @@ INPUT, if non-nil, is a string sent to the process."
   ;; Prior Emacs 27, `shell-file-name' was hard coded as "/bin/sh" for
   ;; remote processes in Emacs.  That doesn't work for tramp-adb.el.
   (skip-unless (or (and (tramp--test-adb-p) (tramp--test-emacs27-p))
-                  (tramp--test-sh-p)))
+                  (tramp--test-sh-p) (tramp--test-sshfs-p)))
   (skip-unless (not (tramp--test-crypt-p)))
 
   (dolist (quoted (if (tramp--test-expensive-test) '(nil t) '(nil)))
@@ -4887,7 +4904,7 @@ INPUT, if non-nil, is a string sent to the process."
   :tags '(:expensive-test :unstable)
   (skip-unless (tramp--test-enabled))
   (skip-unless nil)
-  (skip-unless (or (tramp--test-adb-p) (tramp--test-sh-p)))
+  (skip-unless (or (tramp--test-adb-p) (tramp--test-sh-p) 
(tramp--test-sshfs-p)))
   (skip-unless (not (tramp--test-crypt-p)))
   ;; Prior Emacs 27, `shell-command-dont-erase-buffer' wasn't working properly.
   (skip-unless (tramp--test-emacs27-p))
@@ -5092,8 +5109,10 @@ INPUT, if non-nil, is a string sent to the process."
             (string-match-p
              (regexp-quote envvar)
              ;; We must remove PS1, the output is truncated otherwise.
+             ;; We must suppress "_=VAR...".
              (funcall
-              this-shell-command-to-string "printenv | grep -v PS1")))))))))
+              this-shell-command-to-string
+              "printenv | grep -v PS1 | grep -v _=")))))))))
 
 (tramp--test--deftest-direct-async-process tramp-test33-environment-variables
   "Check that remote processes set / unset environment variables properly.
@@ -5210,7 +5229,7 @@ Use direct async.")
   ;; Prior Emacs 27, `shell-file-name' was hard coded as "/bin/sh" for
   ;; remote processes in Emacs.  That doesn't work for tramp-adb.el.
   (skip-unless (or (and (tramp--test-adb-p) (tramp--test-emacs27-p))
-                  (tramp--test-sh-p)))
+                  (tramp--test-sh-p) (tramp--test-sshfs-p)))
   (skip-unless (not (tramp--test-crypt-p)))
   ;; Since Emacs 26.1.
   (skip-unless (and (fboundp 'connection-local-set-profile-variables)
@@ -5232,8 +5251,7 @@ Use direct async.")
          (with-no-warnings
            (connection-local-set-profile-variables
             'remote-sh
-            `((explicit-shell-file-name
-               . ,(if (tramp--test-adb-p) "/system/bin/sh" "/bin/sh"))
+            `((explicit-shell-file-name . ,(tramp--test-shell-file-name))
               (explicit-sh-args . ("-c" "echo foo"))))
            (connection-local-set-profiles
             `(:application tramp
@@ -5267,7 +5285,7 @@ Use direct async.")
 (ert-deftest tramp-test35-exec-path ()
   "Check `exec-path' and `executable-find'."
   (skip-unless (tramp--test-enabled))
-  (skip-unless (or (tramp--test-adb-p) (tramp--test-sh-p)))
+  (skip-unless (or (tramp--test-adb-p) (tramp--test-sh-p) 
(tramp--test-sshfs-p)))
   (skip-unless (not (tramp--test-crypt-p)))
   ;; Since Emacs 27.1.
   (skip-unless (fboundp 'exec-path))
@@ -5807,6 +5825,11 @@ Additionally, ls does not support \"--dired\"."
        "^\\(afp\\|davs?\\|smb\\)$"
        (file-remote-p tramp-test-temporary-file-directory 'method))))
 
+(defun tramp--test-sshfs-p ()
+  "Check, whether the remote host is offered by sshfs.
+This requires restrictions of file name syntax."
+  (tramp-sshfs-file-name-p tramp-test-temporary-file-directory))
+
 (defun tramp--test-sudoedit-p ()
   "Check, whether the sudoedit method is used."
   (tramp-sudoedit-file-name-p tramp-test-temporary-file-directory))
@@ -6102,7 +6125,6 @@ Use the `stat' command."
   (skip-unless (tramp--test-sh-p))
   (skip-unless (not (tramp--test-rsync-p)))
   (skip-unless (not (tramp--test-windows-nt-and-pscp-psftp-p)))
-  (skip-unless (or (tramp--test-emacs26-p) (not (tramp--test-rclone-p))))
   ;; We cannot use `tramp-test-vec', because this fails during compilation.
   (with-parsed-tramp-file-name tramp-test-temporary-file-directory nil
     (skip-unless (tramp-get-remote-stat v)))
@@ -6122,7 +6144,6 @@ Use the `perl' command."
   (skip-unless (tramp--test-sh-p))
   (skip-unless (not (tramp--test-rsync-p)))
   (skip-unless (not (tramp--test-windows-nt-and-pscp-psftp-p)))
-  (skip-unless (or (tramp--test-emacs26-p) (not (tramp--test-rclone-p))))
   ;; We cannot use `tramp-test-vec', because this fails during compilation.
   (with-parsed-tramp-file-name tramp-test-temporary-file-directory nil
     (skip-unless (tramp-get-remote-perl v)))
@@ -6145,7 +6166,6 @@ Use the `ls' command."
   (skip-unless (tramp--test-sh-p))
   (skip-unless (not (tramp--test-rsync-p)))
   (skip-unless (not (tramp--test-windows-nt-and-pscp-psftp-p)))
-  (skip-unless (or (tramp--test-emacs26-p) (not (tramp--test-rclone-p))))
 
   (let ((tramp-connection-properties
         (append
@@ -6231,7 +6251,6 @@ Use the `stat' command."
   (skip-unless (not (tramp--test-windows-nt-and-pscp-psftp-p)))
   (skip-unless (not (tramp--test-ksh-p)))
   (skip-unless (not (tramp--test-crypt-p)))
-  (skip-unless (or (tramp--test-emacs26-p) (not (tramp--test-rclone-p))))
   ;; We cannot use `tramp-test-vec', because this fails during compilation.
   (with-parsed-tramp-file-name tramp-test-temporary-file-directory nil
     (skip-unless (tramp-get-remote-stat v)))
@@ -6255,7 +6274,6 @@ Use the `perl' command."
   (skip-unless (not (tramp--test-windows-nt-and-pscp-psftp-p)))
   (skip-unless (not (tramp--test-ksh-p)))
   (skip-unless (not (tramp--test-crypt-p)))
-  (skip-unless (or (tramp--test-emacs26-p) (not (tramp--test-rclone-p))))
   ;; We cannot use `tramp-test-vec', because this fails during compilation.
   (with-parsed-tramp-file-name tramp-test-temporary-file-directory nil
     (skip-unless (tramp-get-remote-perl v)))
@@ -6282,7 +6300,6 @@ Use the `ls' command."
   (skip-unless (not (tramp--test-windows-nt-and-pscp-psftp-p)))
   (skip-unless (not (tramp--test-ksh-p)))
   (skip-unless (not (tramp--test-crypt-p)))
-  (skip-unless (or (tramp--test-emacs26-p) (not (tramp--test-rclone-p))))
 
   (let ((tramp-connection-properties
         (append
@@ -6323,6 +6340,7 @@ Use the `ls' command."
   "Set \"process-name\" and \"process-buffer\" connection properties.
 The values are derived from PROC.  Run BODY.
 This is needed in timer functions as well as process filters and sentinels."
+  ;; FIXME: For tramp-sshfs.el, `processp' does not work.
   (declare (indent 1) (debug (processp body)))
   `(let* ((v (tramp-get-connection-property ,proc "vector" nil))
          (pname (tramp-get-connection-property v "process-name" nil))
@@ -6372,7 +6390,7 @@ process sentinels.  They shall not disturb each other."
     (define-key special-event-map [sigusr1] #'tramp--test-timeout-handler)
     (let* (;; For the watchdog.
           (default-directory (expand-file-name temporary-file-directory))
-          (shell-file-name (if (tramp--test-adb-p) "/system/bin/sh" "/bin/sh"))
+          (shell-file-name (tramp--test-shell-file-name))
           ;; It doesn't work on w32 systems.
           (watchdog
             (start-process-shell-command
@@ -6730,8 +6748,8 @@ Since it unloads Tramp, it shall be the last test to run."
 If INTERACTIVE is non-nil, the tests are run interactively."
   (interactive "p")
   (funcall
-   (if interactive
-       #'ert-run-tests-interactively #'ert-run-tests-batch) "^tramp"))
+   (if interactive #'ert-run-tests-interactively #'ert-run-tests-batch)
+   "^tramp"))
 
 ;; TODO:
 
@@ -6747,9 +6765,10 @@ If INTERACTIVE is non-nil, the tests are run 
interactively."
 ;; * Work on skipped tests.  Make a comment, when it is impossible.
 ;; * Revisit expensive tests, once problems in `tramp-error' are solved.
 ;; * Fix `tramp-test06-directory-file-name' for `ftp'.
-;; * Implement `tramp-test31-interrupt-process' for `adb' and for
-;;   direct async processes.
-;; * Fix `tramp-test44-threads'.
+;; * Implement `tramp-test31-interrupt-process' for `adb', `sshfs' and
+;;   for direct async processes.
+;; * Check, why direct async processes do not work for
+;;   `tramp-test43-asynchronous-requests'.
 
 (provide 'tramp-tests)
 
diff --git a/test/lisp/cedet/inversion-tests.el 
b/test/lisp/obsolete/inversion-tests.el
similarity index 100%
rename from test/lisp/cedet/inversion-tests.el
rename to test/lisp/obsolete/inversion-tests.el
diff --git a/test/lisp/progmodes/cperl-mode-resources/grammar.pl 
b/test/lisp/progmodes/cperl-mode-resources/grammar.pl
new file mode 100644
index 0000000..c05fd7e
--- /dev/null
+++ b/test/lisp/progmodes/cperl-mode-resources/grammar.pl
@@ -0,0 +1,158 @@
+use 5.024;
+use strict;
+use warnings;
+
+sub outside {
+    say "Line @{[__LINE__]}: package '@{[__PACKAGE__]}'";
+}
+
+package Package;
+
+=head1 NAME
+
+grammar - A Test resource for regular expressions
+
+=head1 SYNOPSIS
+
+A Perl file showing a variety of declarations
+
+=head1 DESCRIPTION
+
+This file offers several syntactical constructs for packages,
+subroutines, and POD to test the imenu capabilities of CPerl mode.
+
+Perl offers syntactical variations for package and subroutine
+declarations.  Packages may, or may not, have a version and may, or
+may not, have a block of code attached to them.  Subroutines can have
+old-style prototypes, attributes, and signatures which are still
+experimental but widely accepted.
+
+Various Extensions and future Perl versions will probably add new
+keywords for "class" and "method", both with syntactical extras of
+their own.
+
+This test file tries to keep up with them.
+
+=head2 Details
+
+The code is supposed to identify and exclude false positives,
+e.g. declarations in a string or in POD, as well as POD in a string.
+These should not go into the imenu index.
+
+=cut
+
+our $VERSION = 3.1415;
+say "Line @{[__LINE__]}: package '@{[__PACKAGE__]}', version $VERSION";
+
+sub in_package {
+    # Special test for POD: A line which looks like POD, but actually
+    # is part of a multiline string.  In the case shown here, the
+    # semicolon is not part of the string, but POD headings go to the
+    # end of the line.  The code needs to distinguish between a POD
+    # heading "This Is Not A Pod/;" and a multiline string.
+    my $not_a_pod = q/Another false positive:
+
+=head1 This Is Not A Pod/;
+
+}
+
+sub Shoved::elsewhere {
+    say "Line @{[__LINE__]}: package '@{[__PACKAGE__]}', sub 
Shoved::elsewhere";
+}
+
+sub prototyped ($$) {
+    ...;
+}
+
+package Versioned::Package 0.07;
+say "Line @{[__LINE__]}: package '@{[__PACKAGE__]}', version $VERSION";
+
+sub versioned {
+    # This sub is in package Versioned::Package
+    say "sub 'versioned' in package '", __PACKAGE__, "'";
+}
+
+versioned();
+
+my $false_positives = <<'EOH';
+The following declarations are not supposed to be recorded for imenu.
+They are in a HERE-doc, which is a generic comment in CPerl mode.
+
+package Don::T::Report::This;
+sub this_is_no_sub {
+    my $self = shuffle;
+}
+
+And this is not a POD heading:
+
+=head1 Not a POD heading, just a string.
+
+EOH
+
+package Block {
+    our $VERSION = 2.7182;
+    say "Line @{[__LINE__]}: package '@{[__PACKAGE__]}', version $VERSION";
+
+    sub attr:lvalue {
+        say "sub 'attr' in package '", __PACKAGE__, "'";
+    }
+
+    attr();
+
+    package Block::Inner {
+        # This hopefully doesn't happen too often.
+        say "Line @{[__LINE__]}: package '@{[__PACKAGE__]}', version $VERSION";
+    }
+
+    # Now check that we're back to package "Block"
+    say "Line @{[__LINE__]}: package '@{[__PACKAGE__]}', version $VERSION";
+}
+
+sub outer {
+    # This is in package Versioned::Package
+    say "Line @{[__LINE__]}: package '@{[__PACKAGE__]}', version $VERSION";
+}
+
+outer();
+
+package Versioned::Block 42 {
+    say "Line @{[__LINE__]}: package '@{[__PACKAGE__]}', version $VERSION";
+
+    my sub lexical {
+        say "sub 'lexical' in package '", __PACKAGE__, "'";
+    }
+
+    lexical();
+
+    use experimental 'signatures';
+    sub signatured :prototype($@) ($self,@rest)
+    {
+        ...;
+    }
+}
+
+# After all is said and done, we're back in package Versioned::Package.
+say "We're in package '", __PACKAGE__, "' now.";
+say "Now try to call a subroutine which went out of scope:";
+eval { lexical() };
+say $@ if $@;
+
+# Now back to Package. This must not appear separately in the
+# hierarchy list.
+package Package;
+
+our sub in_package_again {
+    say "Line @{[__LINE__]}: package '@{[__PACKAGE__]}', version $VERSION";
+}
+
+
+package :: {
+    # This is just a weird, but legal, package name.
+    say "Line @{[__LINE__]}: package '@{[__PACKAGE__]}', version $VERSION";
+
+    in_package_again(); # weird, but calls the sub from above
+}
+
+Shoved::elsewhere();
+
+1;
diff --git a/test/lisp/progmodes/cperl-mode-tests.el 
b/test/lisp/progmodes/cperl-mode-tests.el
index 943c454..14bc48b 100644
--- a/test/lisp/progmodes/cperl-mode-tests.el
+++ b/test/lisp/progmodes/cperl-mode-tests.el
@@ -135,6 +135,28 @@ point in the distant past, and is still broken in 
perl-mode. "
         (should (equal (nth 3 (syntax-ppss)) nil))
         (should (equal (nth 4 (syntax-ppss)) t))))))
 
+(ert-deftest cperl-test-fontify-declarations ()
+  "Test that declarations and package usage use consistent fontification."
+  (with-temp-buffer
+    (funcall cperl-test-mode)
+    (insert "package Foo::Bar;\n")
+    (insert "use Fee::Fie::Foe::Foo\n;")
+    (insert "my $xyzzy = 'PLUGH';\n")
+    (goto-char (point-min))
+    (font-lock-ensure)
+    (search-forward "Bar")
+    (should (equal (get-text-property (match-beginning 0) 'face)
+                   'font-lock-function-name-face))
+    (search-forward "use") ; This was buggy in perl-mode
+    (should (equal (get-text-property (match-beginning 0) 'face)
+                   'font-lock-keyword-face))
+    (search-forward "my")
+    (should (equal (get-text-property (match-beginning 0) 'face)
+                   'font-lock-keyword-face))))
+
+(defvar perl-continued-statement-offset)
+(defvar perl-indent-level)
+
 (ert-deftest cperl-test-heredocs ()
   "Test that HERE-docs are fontified with the appropriate face."
   (require 'perl-mode)
@@ -166,6 +188,101 @@ point in the distant past, and is still broken in 
perl-mode. "
                        (if (match-beginning 3) 0
                          perl-indent-level)))))))
 
+;;; Grammar based tests: unit tests
+
+(defun cperl-test--validate-regexp (regexp valid &optional invalid)
+  "Runs tests for elements of VALID and INVALID lists against REGEXP.
+Tests with elements from VALID must match, tests with elements
+from INVALID must not match.  The match string must be equal to
+the whole string."
+  (funcall cperl-test-mode)
+  (dolist (string valid)
+    (should (string-match regexp string))
+    (should (string= (match-string 0 string) string)))
+  (when invalid
+    (dolist (string invalid)
+       (should-not
+       (and (string-match regexp string)
+           (string= (match-string 0 string) string))))))
+
+(ert-deftest cperl-test-ws-regexp ()
+  "Tests capture of very simple regular expressions (yawn)."
+  (let ((valid
+        '(" " "\t" "\n"))
+       (invalid
+        '("a" "  " "")))
+    (cperl-test--validate-regexp cperl--ws-regexp
+                                valid invalid)))
+
+(ert-deftest cperl-test-ws-or-comment-regexp ()
+  "Tests sequences of whitespace and comment lines."
+  (let ((valid
+        `(" " "\t#\n" "\n# \n"
+          ,(concat "# comment\n" "# comment\n" "\n" "#comment\n")))
+       (invalid
+        '("=head1 NAME\n" )))
+    (cperl-test--validate-regexp cperl--ws-or-comment-regexp
+                                valid invalid)))
+
+(ert-deftest cperl-test-version-regexp ()
+  "Tests the regexp for recommended syntax of versions in Perl."
+  (let ((valid
+        '("1" "1.1" "1.1_1" "5.032001"
+          "v120.100.103"))
+       (invalid
+        '("alpha" "0." ".123" "1E2"
+          "v1.1" ; a "v" version string needs at least 3 components
+          ;; bad examples from "Version numbers should be boring"
+          ;; by xdg AKA David A. Golden
+          "1.20alpha" "2.34beta2" "2.00R3")))
+    (cperl-test--validate-regexp cperl--version-regexp
+                                valid invalid)))
+
+(ert-deftest cperl-test-package-regexp ()
+  "Tests the regular expression of Perl package names with versions.
+Also includes valid cases with whitespace in strange places."
+  (let ((valid
+        '("package Foo"
+          "package Foo::Bar"
+          "package Foo::Bar v1.2.3"
+          "package Foo::Bar::Baz 1.1"
+          "package \nFoo::Bar\n 1.00"))
+       (invalid
+        '("package Foo;"          ; semicolon must not be included
+          "package Foo 1.1 {"     ; nor the opening brace
+          "packageFoo"            ; not a package declaration
+          "package Foo1.1"        ; invalid package name
+          "class O3D::Sphere")))  ; class not yet supported
+    (cperl-test--validate-regexp cperl--package-regexp
+                                valid invalid)))
+
+;;; Function test: Building an index for imenu
+
+(ert-deftest cperl-test-imenu-index ()
+  "Test index creation for imenu.
+This test relies on the specific layout of the index alist as
+created by CPerl mode, so skip it for Perl mode."
+  (skip-unless (eq cperl-test-mode #'cperl-mode))
+  (with-temp-buffer
+    (insert-file-contents (ert-resource-file "grammar.pl"))
+    (cperl-mode)
+    (let ((index (cperl-imenu--create-perl-index))
+          current-list)
+      (setq current-list (assoc-string "+Unsorted List+..." index))
+      (should current-list)
+      (let ((expected '("(main)::outside"
+                        "Package::in_package"
+                        "Shoved::elsewhere"
+                        "Package::prototyped"
+                        "Versioned::Package::versioned"
+                        "Block::attr"
+                        "Versioned::Package::outer"
+                        "lexical"
+                        "Versioned::Block::signatured"
+                        "Package::in_package_again")))
+        (dolist (sub expected)
+          (should (assoc-string sub index)))))))
+
 ;;; Tests for issues reported in the Bug Tracker
 
 (defun cperl-test--run-bug-10483 ()
@@ -352,4 +469,30 @@ have a face property."
     ;; The yadda-yadda operator should not be in a string.
     (should (equal (nth 8 (cperl-test-ppss code "\\.")) nil))))
 
+(ert-deftest cperl-test-bug-47112 ()
+  "Check that in a bareword starting with a quote-like operator
+followed by an underscore is not interpreted as that quote-like
+operator.  Also check that a quote-like operator followed by a
+colon (which is, like ?_, a symbol in CPerl mode) _is_ identified
+as that quote like operator."
+  (with-temp-buffer
+    (funcall cperl-test-mode)
+    (insert "sub y_max { q:bar:; y _bar_foo_; }")
+    (goto-char (point-min))
+    (syntax-propertize (point-max))
+    (font-lock-ensure)
+    (search-forward "max")
+    (should (equal (get-text-property (match-beginning 0) 'face)
+                   'font-lock-function-name-face))
+    (search-forward "bar")
+    (should (equal (get-text-property (match-beginning 0) 'face)
+                   'font-lock-string-face))
+    ; perl-mode doesn't highlight
+    (when (eq cperl-test-mode #'cperl-mode)
+      (search-forward "_")
+      (should (equal (get-text-property (match-beginning 0) 'face)
+                     (if (eq cperl-test-mode #'cperl-mode)
+                         'font-lock-constant-face
+                       font-lock-string-face))))))
+
 ;;; cperl-mode-tests.el ends here
diff --git a/test/lisp/progmodes/elisp-mode-tests.el 
b/test/lisp/progmodes/elisp-mode-tests.el
index badcad6..f47d54e 100644
--- a/test/lisp/progmodes/elisp-mode-tests.el
+++ b/test/lisp/progmodes/elisp-mode-tests.el
@@ -398,18 +398,21 @@ to (xref-elisp-test-descr-to-target xref)."
     "(cl-defstruct (xref-elisp-location")
    ))
 
+(require 'em-xtra)
+(require 'find-dired)
 (xref-elisp-deftest find-defs-defalias-defun-el
-  (elisp--xref-find-definitions 'Buffer-menu-sort)
+  (elisp--xref-find-definitions 'eshell/ff)
   (list
-   (xref-make "(defalias Buffer-menu-sort)"
+   (xref-make "(defalias eshell/ff)"
              (xref-make-elisp-location
-              'Buffer-menu-sort 'defalias
-              (expand-file-name "../../../lisp/buff-menu.elc" emacs-test-dir)))
-   (xref-make "(defun tabulated-list-sort)"
+              'eshell/ff 'defalias
+              (expand-file-name "../../../lisp/eshell/em-xtra.elc"
+                                 emacs-test-dir)))
+   (xref-make "(defun find-name-dired)"
              (xref-make-elisp-location
-              'tabulated-list-sort nil
-              (expand-file-name "../../../lisp/emacs-lisp/tabulated-list.el" 
emacs-test-dir)))
-   ))
+              'find-name-dired nil
+              (expand-file-name "../../../lisp/find-dired.el"
+                                 emacs-test-dir)))))
 
 ;; FIXME: defconst
 
diff --git a/test/lisp/progmodes/f90-tests.el b/test/lisp/progmodes/f90-tests.el
index b3d1222..330eab3 100644
--- a/test/lisp/progmodes/f90-tests.el
+++ b/test/lisp/progmodes/f90-tests.el
@@ -22,9 +22,6 @@
 
 ;;; Commentary:
 
-;; This file does not have "test" in the name, because it lives under
-;; a test/ directory, so that would be superfluous.
-
 ;;; Code:
 
 (require 'ert)
diff --git a/test/lisp/progmodes/xref-resources/file1.txt 
b/test/lisp/progmodes/xref-resources/file1.txt
index 5d7cc54..85b92f1 100644
--- a/test/lisp/progmodes/xref-resources/file1.txt
+++ b/test/lisp/progmodes/xref-resources/file1.txt
@@ -1,2 +1,2 @@
-foo foo
+ foo foo
 bar
diff --git a/test/lisp/progmodes/xref-resources/file3.txt 
b/test/lisp/progmodes/xref-resources/file3.txt
new file mode 100644
index 0000000..6283185
--- /dev/null
+++ b/test/lisp/progmodes/xref-resources/file3.txt
@@ -0,0 +1 @@
+ match some words match more match ends here
diff --git a/test/lisp/progmodes/xref-tests.el 
b/test/lisp/progmodes/xref-tests.el
index b4b5e4d..9982c32 100644
--- a/test/lisp/progmodes/xref-tests.el
+++ b/test/lisp/progmodes/xref-tests.el
@@ -59,15 +59,33 @@
     (should (string-match-p "file1\\.txt\\'" (xref-location-group (nth 1 
locs))))
     (should (equal 1 (xref-location-line (nth 0 locs))))
     (should (equal 1 (xref-location-line (nth 1 locs))))
-    (should (equal 0 (xref-location-column (nth 0 locs))))
-    (should (equal 4 (xref-location-column (nth 1 locs))))))
+    (should (equal 1 (xref-file-location-column (nth 0 locs))))
+    (should (equal 5 (xref-file-location-column (nth 1 locs))))))
 
 (ert-deftest xref-matches-in-directory-finds-an-empty-line-regexp-match ()
   (let ((locs (xref-tests--locations-in-data-dir "^$")))
     (should (= 1 (length locs)))
     (should (string-match-p "file2\\.txt\\'" (xref-location-group (nth 0 
locs))))
     (should (equal 1 (xref-location-line (nth 0 locs))))
-    (should (equal 0 (xref-location-column (nth 0 locs))))))
+    (should (equal 0 (xref-file-location-column (nth 0 locs))))))
+
+(ert-deftest xref-matches-in-files-includes-matches-from-all-the-files ()
+  (let ((matches (xref-matches-in-files "bar"
+                                        (directory-files xref-tests--data-dir t
+                                                         "\\`[^.]"))))
+    (should (= 2 (length matches)))
+    (should (cl-every
+             (lambda (match) (equal (xref-item-summary match) "bar"))
+             matches))))
+
+(ert-deftest xref-matches-in-files-trims-summary-for-matches-on-same-line ()
+  (let ((matches (xref-matches-in-files "match"
+                                        (directory-files xref-tests--data-dir t
+                                                         "\\`[^.]"))))
+    (should (= 3 (length matches)))
+    (should
+     (equal (mapcar #'xref-item-summary matches)
+            '(" match some words " "match more " "match ends here")))))
 
 (ert-deftest xref--buf-pairs-iterator-groups-markers-by-buffers-1 ()
   (let* ((xrefs (xref-tests--matches-in-data-dir "foo"))
@@ -99,18 +117,18 @@
     (should (null (marker-position (cdr (nth 0 (cdr cons2))))))))
 
 (ert-deftest xref--xref-file-name-display-is-abs ()
-  (let ((xref-file-name-display 'abs)
-        ;; Some older BSD find versions can produce '//' in the output.
-        (expected (list
-                   (concat xref-tests--data-dir "/?file1.txt")
-                   (concat xref-tests--data-dir "/?file2.txt")))
-        (actual (delete-dups
-                 (mapcar 'xref-location-group
-                         (xref-tests--locations-in-data-dir 
"\\(bar\\|foo\\)")))))
-    (should (and (= (length expected) (length actual))
-                 (cl-every (lambda (e1 e2)
-                             (string-match-p e1 e2))
-                           expected actual)))))
+  (let* ((xref-file-name-display 'abs)
+         ;; Some older BSD find versions can produce '//' in the output.
+         (expected (list
+                    (concat xref-tests--data-dir "/?file1.txt")
+                    (concat xref-tests--data-dir "/?file2.txt")))
+         (actual (delete-dups
+                  (mapcar 'xref-location-group
+                          (xref-tests--locations-in-data-dir 
"\\(bar\\|foo\\)")))))
+    (should (= (length expected) (length actual)))
+    (should (cl-every (lambda (e1 e2)
+                        (string-match-p e1 e2))
+                      expected actual))))
 
 (ert-deftest xref--xref-file-name-display-is-nondirectory ()
   (let ((xref-file-name-display 'nondirectory))
diff --git a/test/lisp/simple-tests.el b/test/lisp/simple-tests.el
index f2ddc2e..601eca6 100644
--- a/test/lisp/simple-tests.el
+++ b/test/lisp/simple-tests.el
@@ -465,8 +465,124 @@ See bug#35036."
     (simple-tests--exec '(backward-char undo-redo undo-redo))
     (should (equal (buffer-string) "abc"))
     (simple-tests--exec '(backward-char undo-redo undo-redo))
+    (should (equal (buffer-string) "abcde"))))
+
+(ert-deftest simple-tests--undo-in-region ()
+  ;; Test undo/redo in region.
+  (with-temp-buffer
+    ;; Enable `transient-mark-mode' so `region-active-p' works as
+    ;; expected. `region-active-p' is used to determine whether to
+    ;; perform regional undo in `undo'.
+    (transient-mark-mode)
+    (buffer-enable-undo)
+    (dolist (x '("a" "b" "c" "d" "e"))
+      (insert x)
+      (undo-boundary))
+    (should (equal (buffer-string) "abcde"))
+    ;; The test does this: activate region, `undo', break the undo
+    ;; chain (by deactivating and reactivating the region), then
+    ;; `undo-only'.  There used to be a bug in
+    ;; `undo-make-selective-list' that makes `undo-only' error out in
+    ;; that case, which is fixed by in the same commit as this change.
+    (simple-tests--exec '(move-beginning-of-line
+                          push-mark-command
+                          forward-char
+                          forward-char
+                          undo))
+    (should (equal (buffer-string) "acde"))
+    (simple-tests--exec '(move-beginning-of-line
+                          push-mark-command
+                          forward-char
+                          forward-char
+                          undo-only))
     (should (equal (buffer-string) "abcde"))
-    ))
+    ;; Rest are simple redo in region tests.
+    (simple-tests--exec '(undo-redo))
+    (should (equal (buffer-string) "acde"))
+    (simple-tests--exec '(undo-redo))
+    (should (equal (buffer-string) "abcde"))))
+
+(defun simple-tests--sans-leading-nil (lst)
+  "Return LST sans the leading nils."
+  (while (and (consp lst) (null (car lst)))
+    (setq lst (cdr lst)))
+  lst)
+
+(ert-deftest simple-tests--undo-equiv-table ()
+  (with-temp-buffer
+    (buffer-enable-undo)
+    (transient-mark-mode)
+    (let ((ul-hash-table (make-hash-table :test #'equal)))
+      (dolist (x '("a" "b" "c"))
+        (insert x)
+        (puthash x (simple-tests--sans-leading-nil buffer-undo-list)
+                 ul-hash-table)
+        (undo-boundary))
+      (should (equal (buffer-string) "abc"))
+      ;; Tests mappings in `undo-equiv-table'.
+      (simple-tests--exec '(undo))
+      (should (equal (buffer-string) "ab"))
+      (should (eq (gethash (simple-tests--sans-leading-nil
+                            buffer-undo-list)
+                           undo-equiv-table)
+                  (gethash "b" ul-hash-table)))
+      (simple-tests--exec '(backward-char undo))
+      (should (equal (buffer-string) "abc"))
+      (should (eq (gethash (simple-tests--sans-leading-nil
+                            buffer-undo-list)
+                           undo-equiv-table)
+                  (gethash "c" ul-hash-table)))
+      ;; Undo in region should map to 'undo-in-region.
+      (simple-tests--exec '(backward-char
+                            push-mark-command
+                            move-end-of-line
+                            undo))
+      (should (equal (buffer-string) "ab"))
+      (should (eq (gethash (simple-tests--sans-leading-nil
+                            buffer-undo-list)
+                           undo-equiv-table)
+                  'undo-in-region))
+      ;; The undo that undoes to the beginning should map to t.
+      (deactivate-mark 'force)
+      (simple-tests--exec '(backward-char
+                            undo undo undo
+                            undo undo undo))
+      (should (equal (buffer-string) ""))
+      (should (eq (gethash (simple-tests--sans-leading-nil
+                            buffer-undo-list)
+                           undo-equiv-table)
+                  t))
+      ;; Erroneous nil undo should map to 'empty.
+      (insert "a")
+      (undo-boundary)
+      (push nil buffer-undo-list)
+      (simple-tests--exec '(backward-char undo))
+      (should (equal (buffer-string) "a"))
+      (should (eq (gethash (simple-tests--sans-leading-nil
+                            buffer-undo-list)
+                           undo-equiv-table)
+                  'empty))
+      ;; But if the previous record is a redo record, its mapping
+      ;; shouldn't change.
+      (insert "e")
+      (undo-boundary)
+      (should (equal (buffer-string) "ea"))
+      (puthash "e" (simple-tests--sans-leading-nil buffer-undo-list)
+               ul-hash-table)
+      (insert "a")
+      (undo-boundary)
+      (simple-tests--exec '(backward-char undo))
+      (should (equal (buffer-string) "ea"))
+      (push nil buffer-undo-list)
+      (simple-tests--exec '(forward-char undo))
+      ;; Buffer content should change since we just undid a nil
+      ;; record.
+      (should (equal (buffer-string) "ea"))
+      ;; The previous redo record shouldn't map to empty.
+      (should (equal (gethash (simple-tests--sans-leading-nil
+                               buffer-undo-list)
+                              undo-equiv-table)
+                     (gethash "e" ul-hash-table))))))
 
 ;;; undo auto-boundary tests
 (ert-deftest undo-auto-boundary-timer ()
diff --git a/test/lisp/subr-tests.el b/test/lisp/subr-tests.el
index fc5a1eb..7a116aa 100644
--- a/test/lisp/subr-tests.el
+++ b/test/lisp/subr-tests.el
@@ -78,10 +78,14 @@
 
 (ert-deftest subr-test-define-prefix-command ()
   (define-prefix-command 'foo-prefix-map)
+  (defvar foo-prefix-map)
+  (declare-function foo-prefix-map "subr-tests")
   (should (keymapp foo-prefix-map))
   (should (fboundp #'foo-prefix-map))
   ;; With optional argument.
   (define-prefix-command 'bar-prefix 'bar-prefix-map)
+  (defvar bar-prefix-map)
+  (declare-function bar-prefix "subr-tests")
   (should (keymapp bar-prefix-map))
   (should (fboundp #'bar-prefix))
   ;; Returns the symbol.
@@ -531,7 +535,8 @@ See https://debbugs.gnu.org/cgi/bugreport.cgi?bug=19350.";
   (should (equal (string-replace "a" "aa" "aaa") "aaaaaa"))
   (should (equal (string-replace "abc" "defg" "abc") "defg"))
 
-  (should-error (string-replace "" "x" "abc")))
+  (should (equal (should-error (string-replace "" "x" "abc"))
+                 '(wrong-length-argument 0))))
 
 (ert-deftest subr-replace-regexp-in-string ()
   (should (equal (replace-regexp-in-string "a+" "xy" "abaabbabaaba")
diff --git a/test/lisp/textmodes/dns-mode-tests.el 
b/test/lisp/textmodes/dns-mode-tests.el
index 694d683..8bc4873 100644
--- a/test/lisp/textmodes/dns-mode-tests.el
+++ b/test/lisp/textmodes/dns-mode-tests.el
@@ -25,6 +25,27 @@
 (require 'ert)
 (require 'dns-mode)
 
+(ert-deftest dns-mode-tests-dns-mode-soa-increment-serial ()
+  (with-temp-buffer
+    (insert "$TTL 86400
+@   IN  SOA     ns.icann.org. noc.dns.icann.org. (
+        2015080302  ;Serial
+        7200        ;Refresh
+        3600        ;Retry
+        1209600     ;Expire
+        3600        ;Negative response caching TTL\n)")
+    (dns-mode-soa-increment-serial)
+    ;; Number is updated from 2015080302 to the current date
+    ;; (actually, just ensure the year part is later than 2020).
+    (should (string-match "\\$TTL 86400
+@   IN  SOA     ns.icann.org. noc.dns.icann.org. (
+        20[2-9][0-9]+  ;Serial
+        7200        ;Refresh
+        3600        ;Retry
+        1209600     ;Expire
+        3600        ;Negative response caching TTL\n)"
+                          (buffer-string)))))
+
 ;;; IPv6 reverse zones
 (ert-deftest dns-mode-ipv6-conversion ()
   (let ((address "2001:db8::42"))
diff --git a/test/lisp/thumbs-tests.el b/test/lisp/thumbs-tests.el
new file mode 100644
index 0000000..ee09613
--- /dev/null
+++ b/test/lisp/thumbs-tests.el
@@ -0,0 +1,34 @@
+;;; thumbs-tests.el --- tests for thumbs.el  -*- lexical-binding: t -*-
+
+;; Copyright (C) 2021 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs.  If not, see <https://www.gnu.org/licenses/>.
+
+;;; Code:
+
+(require 'ert)
+(require 'thumbs)
+
+(ert-deftest thumbs-tests-thumbsdir/create-if-missing ()
+  (let ((thumbs-thumbsdir (make-temp-file "thumbs-test" t)))
+    (unwind-protect
+        (progn
+          (delete-directory thumbs-thumbsdir)
+          (should (file-directory-p (thumbs-thumbsdir))))
+      (delete-directory thumbs-thumbsdir))))
+
+(provide 'thumbs-tests)
+;;; thumbs-tests.el ends here
diff --git a/test/manual/biditest.el b/test/manual/biditest.el
index dc78ef5..a77fc15 100644
--- a/test/manual/biditest.el
+++ b/test/manual/biditest.el
@@ -1,4 +1,4 @@
-;;; biditest.el --- test bidi reordering in GNU Emacs display engine.
+;;; biditest.el --- test bidi reordering in GNU Emacs display engine.  -*- 
lexical-binding: t; -*-
 
 ;; Copyright (C) 2013-2021 Free Software Foundation, Inc.
 
@@ -54,7 +54,7 @@ The resulting file should be viewed with 
`inhibit-bidi-mirroring' set to t."
                (resolved-paragraph (match-string 3))
                ;; FIXME: Should compare LEVELS with what the display
                ;; engine actually produced.
-               (levels (match-string 4))
+               ;;(levels (match-string 4))
                (indices (match-string 5)))
            (setq codes (split-string codes " ")
                  indices (split-string indices " "))
@@ -120,4 +120,4 @@ BidiCharacterTest.txt file."
   (interactive)
   (message "%s" (bidi-resolved-levels)))
 
-(define-key global-map [f8] 'bidi-levels)
+(define-key global-map [f8] #'bidi-levels)
diff --git a/test/manual/cedet/cedet-utests.el 
b/test/manual/cedet/cedet-utests.el
index e421054..d68b5b8 100644
--- a/test/manual/cedet/cedet-utests.el
+++ b/test/manual/cedet/cedet-utests.el
@@ -1,4 +1,4 @@
-;;; cedet-utests.el --- Run all unit tests in the CEDET suite.
+;;; cedet-utests.el --- Run all unit tests in the CEDET suite.  -*- 
lexical-binding: t; -*-
 
 ;; Copyright (C) 2008-2021 Free Software Foundation, Inc.
 
@@ -120,9 +120,9 @@
 EXIT-ON-ERROR causes the test suite to exit on an error, instead
 of just logging the error."
   (interactive)
-  (if (or (not (featurep 'semantic/db-mode))
-         (not (semanticdb-minor-mode-p)))
-      (error "CEDET Tests require semantic-mode to be enabled"))
+  (unless (and (fboundp 'semanticdb-minor-mode-p)
+               (semanticdb-minor-mode-p))
+    (error "CEDET Tests require semantic-mode to be enabled"))
   (dolist (L cedet-utest-libs)
     (load-file (expand-file-name (concat L ".el") cedet-utest-directory)))
   (cedet-utest-log-setup "ALL TESTS")
@@ -170,6 +170,8 @@ of just logging the error."
   (declare (obsolete nil "27.1"))
   noninteractive)
 
+(defvar srecode-map-save-file)
+
 ;;;###autoload
 (defun cedet-utest-batch ()
   "Run the CEDET unit test in BATCH mode."
@@ -178,6 +180,7 @@ of just logging the error."
   (condition-case err
       (when (catch 'cedet-utest-exit-on-error
              ;; Get basic semantic features up.
+             ;; FIXME: I can't see any such function in our code!
              (semantic-load-enable-minimum-features)
              ;; Disables all caches related to semantic DB so all
              ;; tests run as if we have bootstrapped CEDET for the
@@ -231,8 +234,7 @@ Optional argument TITLE is the title of this testing 
session."
       (setq cedet-utest-frame (make-frame cedet-utest-frame-parameters)))
     (when (or (not cedet-utest-buffer) (not (buffer-live-p 
cedet-utest-buffer)))
       (setq cedet-utest-buffer (get-buffer-create "*CEDET utest log*")))
-    (save-excursion
-      (set-buffer cedet-utest-buffer)
+    (with-current-buffer cedet-utest-buffer
       (setq cedet-utest-last-log-item nil)
       (when (not cedet-running-master-tests)
        (erase-buffer))
@@ -254,7 +256,7 @@ Argument START and END bound the time being calculated."
      (- (car (cdr end)) (car (cdr start)))
      (/ (- (car (cdr (cdr end))) (car (cdr (cdr start)))) 1000000.0)))
 
-(defun cedet-utest-log-shutdown (title &optional errorcondition)
+(defun cedet-utest-log-shutdown (title &optional _errorcondition)
   "Shut-down a larger test suite.
 TITLE is the section that is done.
 ERRORCONDITION is some error that may have occurred during testing."
@@ -274,8 +276,7 @@ ERRORCONDITION is some error that may have occurred during 
testing."
        (message "     Elapsed Time %.2f Seconds\n"
                 (cedet-utest-elapsed-time startime endtime)))
 
-    (save-excursion
-      (set-buffer cedet-utest-buffer)
+    (with-current-buffer cedet-utest-buffer
       (goto-char (point-max))
       (insert "\n>> Test Suite " title " ended at @ "
              (format-time-string "%c" endtime) "\n"
@@ -305,12 +306,11 @@ ERRORCONDITION is some error that may have occurred 
during testing."
   "Hook run after the current log command was run."
     (if noninteractive
        (message "")
-      (save-excursion
-       (set-buffer cedet-utest-buffer)
+      (with-current-buffer cedet-utest-buffer
        (goto-char (point-max))
        (insert "\n\n")))
     (setq cedet-utest-last-log-item nil)
-    (remove-hook 'post-command-hook 'cedet-utest-post-command-hook)
+    (remove-hook 'post-command-hook #'cedet-utest-post-command-hook)
     )
 
 (defun cedet-utest-add-log-item-start (item)
@@ -318,12 +318,11 @@ ERRORCONDITION is some error that may have occurred 
during testing."
   (unless (equal item cedet-utest-last-log-item)
     (setq cedet-utest-last-log-item item)
     ;; This next line makes sure we clear out status during logging.
-    (add-hook 'post-command-hook 'cedet-utest-post-command-hook)
+    (add-hook 'post-command-hook #'cedet-utest-post-command-hook)
 
     (if noninteractive
        (message " - Running %s ..." item)
-      (save-excursion
-       (set-buffer cedet-utest-buffer)
+      (with-current-buffer cedet-utest-buffer
        (goto-char (point-max))
        (when (not (bolp)) (insert "\n"))
        (insert "Running " item " ... ")
@@ -343,8 +342,7 @@ Optional argument PRECR indicates to prefix the done msg w/ 
a newline."
          (message "   * %s {%s}" (or err "done") notes)
        (message "   * %s" (or err "done")))
     ;; Interactive-mode - insert into the buffer.
-    (save-excursion
-      (set-buffer cedet-utest-buffer)
+    (with-current-buffer cedet-utest-buffer
       (goto-char (point-max))
       (when precr (insert "\n"))
       (if err
@@ -378,12 +376,11 @@ Optional argument PRECR indicates to prefix the done msg 
w/ a newline."
   "Log the text string FORMAT.
 The rest of the ARGS are used to fill in FORMAT with `format'."
   (if noninteractive
-      (apply 'message format args)
-    (save-excursion
-      (set-buffer cedet-utest-buffer)
+      (apply #'message format args)
+    (with-current-buffer cedet-utest-buffer
       (goto-char (point-max))
       (when (not (bolp)) (insert "\n"))
-      (insert (apply 'format format args))
+      (insert (apply #'format format args))
       (insert "\n")
       (sit-for 0)
       ))
@@ -396,11 +393,15 @@ The rest of the ARGS are used to fill in FORMAT with 
`format'."
   "Test the lightening function for pulsing a line.
 When optional NO-ERROR don't throw an error if we can't run tests."
   (interactive)
-  (if (or (not pulse-flag) (not (pulse-available-p)))
+  (if (not (and (bound-and-true-p pulse-flag)
+                (fboundp 'pulse-available-p)
+                (pulse-available-p)))
       (if no-error
          nil
        (error (concat "Pulse test only works on versions of Emacs"
                       " that support pulsing")))
+    (declare-function pulse-momentary-highlight-overlay
+                      "pulse.el" (o &optional face))
     ;; Run the tests
     (when (called-interactively-p 'interactive)
       (message "<Press a key> Pulse one line.")
diff --git a/test/manual/cedet/semantic-tests.el 
b/test/manual/cedet/semantic-tests.el
index 3d72fa2..7169c78 100644
--- a/test/manual/cedet/semantic-tests.el
+++ b/test/manual/cedet/semantic-tests.el
@@ -1,6 +1,6 @@
-;;; semantic-utest.el --- Miscellaneous Semantic tests.
+;;; semantic-utest.el --- Miscellaneous Semantic tests.  -*- lexical-binding: 
t; -*-
 
-;;; Copyright (C) 2003-2004, 2007-2021 Free Software Foundation, Inc.
+;; Copyright (C) 2003-2021  Free Software Foundation, Inc.
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
 
@@ -64,10 +64,12 @@ run the test again")))
   "Find the first loaded ebrowse table, and dump out the contents."
   (interactive)
   (let ((db semanticdb-database-list)
-       (ab nil))
+       ;; (ab nil)
+       )
     (while db
       (when (semanticdb-project-database-ebrowse-p (car db))
-       (setq ab (data-debug-new-buffer "*EBROWSE Database*"))
+       ;; (setq ab
+             (data-debug-new-buffer "*EBROWSE Database*") ;;)
        (data-debug-insert-thing (car db) "*" "")
        (setq db nil)
        )
@@ -100,7 +102,7 @@ If optional arg STANDARDFILE is non-nil, use a standard 
file w/ global enabled."
                 (set-buffer (find-file-noselect 
semanticdb-test-gnu-global-startfile)))
               (semanticdb-enable-gnu-global-in-buffer))))
 
-    (let* ((db (semanticdb-project-database-global "global"))
+    (let* ((db (semanticdb-project-database-global)) ;; "global"
           (tab (semanticdb-file-table db (buffer-file-name)))
           (result (semanticdb-deep-find-tags-for-completion-method tab 
searchfor))
           )
@@ -127,8 +129,7 @@ Optional argument ARG specifies not to use color."
        (princ (car fns))
        (princ ":\n ")
        (let ((s (funcall (car fns) tag par (not arg))))
-         (save-excursion
-           (set-buffer "*format-tag*")
+         (with-current-buffer "*format-tag*"
            (goto-char (point-max))
            (insert s)))
        (setq fns (cdr fns))))
@@ -163,7 +164,7 @@ Optional argument ARG specifies not to use color."
   "Test `semantic-idle-scheduler-work-parse-neighboring-files' and time it."
   (interactive)
   (let ((start (current-time))
-       (junk (semantic-idle-scheduler-work-parse-neighboring-files)))
+       (_junk (semantic-idle-scheduler-work-parse-neighboring-files)))
     (message "Work took %.2f seconds." (semantic-elapsed-time start nil))))
 
 ;;; From semantic-lex:
@@ -210,6 +211,8 @@ Analyze the area between BEG and END."
     (semantic-lex-spp-table-write-slot-value
      (semantic-lex-spp-save-table))))
 
+(defvar cedet-utest-directory) ;From test/manual/cedet/cedet-utests.el?
+
 (defun semantic-lex-spp-write-utest ()
   "Unit test using the test spp file to test the slot write fcn."
   (interactive)
@@ -258,7 +261,7 @@ tag that contains point, and return that."
         (Lcount 0))
     (when (semantic-tag-p target)
       (semantic-symref-hits-in-region
-       target (lambda (start end prefix) (setq Lcount (1+ Lcount)))
+       target (lambda (_start _end _prefix) (setq Lcount (1+ Lcount)))
        (semantic-tag-start tag)
        (semantic-tag-end tag))
       (when (called-interactively-p 'interactive)
diff --git a/test/manual/image-circular-tests.el 
b/test/manual/image-circular-tests.el
index 3d1d232..7abb94d 100644
--- a/test/manual/image-circular-tests.el
+++ b/test/manual/image-circular-tests.el
@@ -1,4 +1,4 @@
-;;; image-circular-tests.el --- test image functions with circular objects
+;;; image-circular-tests.el --- test image functions with circular objects  
-*- lexical-binding: t; -*-
 
 ;; Copyright (C) 2019, 2021 Free Software Foundation, Inc.
 
diff --git a/test/manual/image-size-tests.el b/test/manual/image-size-tests.el
index 489b397..f7c2bf7 100644
--- a/test/manual/image-size-tests.el
+++ b/test/manual/image-size-tests.el
@@ -1,4 +1,4 @@
-;;; image-size-tests.el -- tests for image scaling
+;;; image-size-tests.el -- tests for image scaling  -*- lexical-binding: t; -*-
 
 ;; Copyright (C) 2017-2021 Free Software Foundation, Inc.
 
@@ -45,7 +45,8 @@
          (= (cdr size) height))))
 
 (defun image-size-tests ()
-  (unless (imagemagick-types)
+  (unless (and (fboundp 'imagemagick-types)
+               (imagemagick-types))
     (error "This only makes sense if ImageMagick is installed"))
   ;; Test the image that's wider than it is tall.
   ;; Default sizes.
diff --git a/test/manual/redisplay-testsuite.el 
b/test/manual/redisplay-testsuite.el
index 48f3788..8e90f2d 100644
--- a/test/manual/redisplay-testsuite.el
+++ b/test/manual/redisplay-testsuite.el
@@ -1,4 +1,4 @@
-;;; redisplay-testsuite.el --- Test suite for redisplay.
+;;; redisplay-testsuite.el --- Test suite for redisplay.  -*- lexical-binding: 
t; -*-
 
 ;; Copyright (C) 2009-2021 Free Software Foundation, Inc.
 
diff --git a/test/misc/test-custom-deps.el b/test/misc/test-custom-deps.el
new file mode 100644
index 0000000..f072add
--- /dev/null
+++ b/test/misc/test-custom-deps.el
@@ -0,0 +1,42 @@
+;;; test-custom-deps.el --- Test custom deps  -*- lexical-binding:t -*-
+
+;; Copyright (C) 2021 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:
+
+;; The command `cus-test-deps' loads all (!) custom dependencies and
+;; reports about load errors.
+
+;;; Code:
+
+(require 'ert)
+
+(defconst custom-test-admin-cus-test
+  (expand-file-name "admin/cus-test.el" source-directory))
+
+(declare-function cus-test-deps custom-test-admin-cus-test)
+(defvar cus-test-deps-errors)  ; from admin/cus-tests.el
+
+(ert-deftest test-custom-deps ()
+  :tags '(:expensive-test)
+  (skip-unless (file-readable-p custom-test-admin-cus-test))
+  (load custom-test-admin-cus-test)
+  (cus-test-deps)
+  (should-not cus-test-deps-errors))
+
+;;; test-custom-deps.el ends here
diff --git a/test/misc/test-custom-libs.el b/test/misc/test-custom-libs.el
new file mode 100644
index 0000000..cc2be99
--- /dev/null
+++ b/test/misc/test-custom-libs.el
@@ -0,0 +1,48 @@
+;;; test-custom-libs.el --- Test custom loads  -*- lexical-binding:t -*-
+
+;; Copyright (C) 2021 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs.  If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; This file runs for all libraries with autoloads separate emacs
+;; processes of the form "emacs -batch -l LIB".
+
+;;; Code:
+
+(require 'ert)
+
+(defconst custom-test-admin-cus-test
+  (expand-file-name "admin/cus-test.el" source-directory))
+
+(declare-function cus-test-libs custom-test-admin-cus-test)
+(defvar cus-test-libs-errors)  ; from admin/cus-tests.el
+
+;; FIXME: Currently fails for:
+;;        - lisp/term/ns-win.el
+;;        - lisp/org/org-num.el
+(ert-deftest test-custom-libs ()
+  :tags '(:expensive-test)
+  :expected-result :failed ; FIXME: See above.
+  ;; This test is very slow, and IMO not worth the time it takes.
+  (skip-unless (not (getenv "EMACS_HYDRA_CI")))
+  (skip-unless (file-readable-p custom-test-admin-cus-test))
+  (load custom-test-admin-cus-test)
+  (cus-test-libs t)
+  (should-not cus-test-libs-errors))
+
+;;; test-custom-deps.el ends here
diff --git a/test/misc/test-custom-noloads.el b/test/misc/test-custom-noloads.el
new file mode 100644
index 0000000..6fa6a6c
--- /dev/null
+++ b/test/misc/test-custom-noloads.el
@@ -0,0 +1,45 @@
+;;; test-custom-deps.el --- Test custom noloads  -*- lexical-binding:t -*-
+
+;; Copyright (C) 2021 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:
+
+;; The command `cus-test-noloads' returns a list of variables which
+;; are somewhere declared as custom options, but not loaded by
+;; `custom-load-symbol'.
+
+;;; Code:
+
+(require 'ert)
+
+(defconst custom-test-admin-cus-test
+  (expand-file-name "admin/cus-test.el" source-directory))
+
+(declare-function cus-test-noloads custom-test-admin-cus-test)
+(defvar cus-test-vars-not-cus-loaded)  ; from admin/cus-tests.el
+
+;; FIXME: Multiple failures here.
+(ert-deftest custom-test-load ()
+  :tags '(:expensive-test :unstable)
+  :expected-result :failed ; FIXME: See above.
+  (skip-unless (file-readable-p custom-test-admin-cus-test))
+  (load custom-test-admin-cus-test)
+  (cus-test-noloads)
+  (should-not cus-test-vars-not-cus-loaded))
+
+;;; test-custom-deps.el ends here
diff --git a/test/misc/test-custom-opts.el b/test/misc/test-custom-opts.el
new file mode 100644
index 0000000..fa6b9e6
--- /dev/null
+++ b/test/misc/test-custom-opts.el
@@ -0,0 +1,39 @@
+;;; test-custom-opts.el --- Test custom opts  -*- lexical-binding:t -*-
+
+;; Copyright (C) 2021 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:
+
+;; The command `cus-test-opts' tests many (all?) custom options.
+
+;;; Code:
+
+(require 'ert)
+
+(defconst custom-test-admin-cus-test
+  (expand-file-name "admin/cus-test.el" source-directory))
+
+(declare-function cus-test-opts custom-test-admin-cus-test)
+
+(ert-deftest check-for-wrong-custom-opts ()
+  :tags '(:expensive-test)
+  (skip-unless (file-readable-p custom-test-admin-cus-test))
+  (load custom-test-admin-cus-test)
+  (should (null (cus-test-opts t))))
+
+;;; test-custom-opts.el ends here
diff --git a/test/src/data-tests.el b/test/src/data-tests.el
index 03d867f..b1e5fa0 100644
--- a/test/src/data-tests.el
+++ b/test/src/data-tests.el
@@ -358,12 +358,35 @@ comparing the subr with a much slower lisp 
implementation."
             (should (equal (symbol-value var) 42))
             (should (equal (default-value var) (symbol-value var)))
             (set var 123)
+            (should (not (local-variable-p var)))
             (should (equal (symbol-value var) 123))
             (should (equal (default-value var) (symbol-value var)))) ;bug#44733
           (should (equal (symbol-value var) def))
           (should (equal (default-value var) (symbol-value var))))
         (should (equal (default-value var) def))))))
 
+(ert-deftest data-tests--let-buffer-local-no-unwind-other-buffers ()
+  "Test that a let-binding for a buffer-local unwinds only current-buffer."
+  (let ((blvar (make-symbol "blvar")))
+    (set-default blvar 0)
+    (make-variable-buffer-local blvar)
+    (dolist (var (list blvar 'left-margin))
+      (let* ((def (default-value var))
+             (newdef (+ def 1))
+             (otherbuf (generate-new-buffer "otherbuf")))
+        (with-temp-buffer
+          (cl-progv (list var) (list newdef)
+            (with-current-buffer otherbuf
+              (set var 123)
+              (should (local-variable-p var))
+              (should (equal (symbol-value var) 123))
+              (should (equal (default-value var) newdef))))
+          (with-current-buffer otherbuf
+            (should (local-variable-p var))
+            (should (equal (symbol-value var) 123))
+            (should (equal (default-value var) def)))
+          )))))
+
 (ert-deftest binding-test-makunbound ()
   "Tests of makunbound, from the manual."
   (with-current-buffer binding-test-buffer-B
diff --git a/test/src/editfns-tests.el b/test/src/editfns-tests.el
index dcec971..ea80da4 100644
--- a/test/src/editfns-tests.el
+++ b/test/src/editfns-tests.el
@@ -128,6 +128,10 @@
              (format (concat "%-3d/" s) 12)
              #("12 /X" 4 5 (prop "val"))))))
 
+(ert-deftest propertize/error-even-number-of-args ()
+  "Number of args for `propertize' must be odd."
+  (should-error (propertize "foo" 'bar) :type 'wrong-number-of-arguments))
+
 ;; Tests for bug#5131.
 (defun transpose-test-reverse-word (start end)
   "Reverse characters in a word by transposing pairs of characters."
diff --git a/test/src/filelock-tests.el b/test/src/filelock-tests.el
new file mode 100644
index 0000000..a96d6d6
--- /dev/null
+++ b/test/src/filelock-tests.el
@@ -0,0 +1,183 @@
+;;; filelock-tests.el --- test file locking -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2021  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 this program.  If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; This file tests code in src/filelock.c and, to some extent, the
+;; related code in src/fileio.c.
+;;
+;; See also (info "(emacs)Interlocking") and (info "(elisp)File Locks")
+
+;;; Code:
+
+(require 'cl-macs)
+(require 'ert)
+(require 'seq)
+
+(defun filelock-tests--fixture (test-function)
+  "Call TEST-FUNCTION under a test fixture.
+Create a test directory and a buffer whose `buffer-file-name' and
+`buffer-file-truename' are a file within it, then call
+TEST-FUNCTION.  Finally, delete the buffer and the test
+directory."
+  (let* ((temp-dir (make-temp-file "filelock-tests" t))
+         (name (concat (file-name-as-directory temp-dir)
+                       "userfile"))
+         (create-lockfiles t))
+    (unwind-protect
+        (with-temp-buffer
+          (setq buffer-file-name name
+                buffer-file-truename name)
+          (unwind-protect
+              (save-current-buffer
+                (funcall test-function))
+            ;; Set `buffer-file-truename' nil to prevent unlocking,
+            ;; which might prompt the user and/or signal errors.
+            (setq buffer-file-name nil
+                  buffer-file-truename nil)))
+      (delete-directory temp-dir t nil))))
+
+(defun filelock-tests--make-lock-name (file-name)
+  "Return the lock file name for FILE-NAME.
+Equivalent logic in Emacs proper is implemented in C and
+unavailable to Lisp."
+  (concat (file-name-directory (expand-file-name file-name))
+          ".#"
+          (file-name-nondirectory file-name)))
+
+(defun filelock-tests--spoil-lock-file (file-name)
+  "Spoil the lock file for FILE-NAME.
+Cause Emacs to report errors for various file locking operations
+on FILE-NAME going forward.  Create a file that is incompatible
+with Emacs' file locking protocol, but uses the same name as
+FILE-NAME's lock file.  A directory file is used, which is
+portable in practice."
+  (make-directory (filelock-tests--make-lock-name file-name)))
+
+(defun filelock-tests--unspoil-lock-file (file-name)
+  "Remove the lock file spoiler for FILE-NAME.
+See `filelock-tests--spoil-lock-file'."
+  (delete-directory (filelock-tests--make-lock-name file-name) t))
+
+(defun filelock-tests--should-be-locked ()
+  "Abort the current test if the current buffer is not locked.
+Exception: on systems without lock file support, aborts the
+current test if the current file is locked (which should never
+the case)."
+  (if (eq system-type 'ms-dos)
+      (should-not (file-locked-p buffer-file-truename))
+    (should (file-locked-p buffer-file-truename))))
+
+(ert-deftest filelock-tests-lock-unlock-no-errors ()
+  "Check that locking and unlocking works without error."
+  (filelock-tests--fixture
+   (lambda ()
+     (should-not (file-locked-p (buffer-file-name)))
+
+     ;; inserting text should lock the buffer's file.
+     (insert "this locks the buffer's file")
+     (filelock-tests--should-be-locked)
+     (unlock-buffer)
+     (set-buffer-modified-p nil)
+     (should-not (file-locked-p (buffer-file-name)))
+
+     ;; `set-buffer-modified-p' should lock the buffer's file.
+     (set-buffer-modified-p t)
+     (filelock-tests--should-be-locked)
+     (unlock-buffer)
+     (should-not (file-locked-p (buffer-file-name)))
+
+     (should-not (file-locked-p (buffer-file-name))))))
+
+(ert-deftest filelock-tests-lock-spoiled ()
+  "Check `lock-buffer' ."
+  (skip-unless (not (eq system-type 'ms-dos))) ; no filelock support
+  (filelock-tests--fixture
+   (lambda ()
+     (filelock-tests--spoil-lock-file buffer-file-truename)
+     ;; FIXME: errors when locking a file are ignored; should they be?
+     (set-buffer-modified-p t)
+     (filelock-tests--unspoil-lock-file buffer-file-truename)
+     (should-not (file-locked-p buffer-file-truename)))))
+
+(ert-deftest filelock-tests-file-locked-p-spoiled ()
+  "Check that `file-locked-p' fails if the lockfile is \"spoiled\"."
+  (skip-unless (not (eq system-type 'ms-dos))) ; no filelock support
+  (filelock-tests--fixture
+   (lambda ()
+     (filelock-tests--spoil-lock-file buffer-file-truename)
+     (let ((err (should-error (file-locked-p (buffer-file-name)))))
+       (should (equal (seq-subseq err 0 2)
+                      '(file-error "Testing file lock")))))))
+
+(ert-deftest filelock-tests-unlock-spoiled ()
+  "Check that `unlock-buffer' fails if the lockfile is \"spoiled\"."
+  (skip-unless (not (eq system-type 'ms-dos))) ; no filelock support
+  (filelock-tests--fixture
+   (lambda ()
+     ;; Set the buffer modified with file locking temporarily
+     ;; disabled.
+     (let ((create-lockfiles nil))
+       (set-buffer-modified-p t))
+     (should-not (file-locked-p buffer-file-truename))
+     (filelock-tests--spoil-lock-file buffer-file-truename)
+
+     ;; Errors from `unlock-buffer' should call
+     ;; `userlock--handle-unlock-error' (bug#46397).
+     (let (errors)
+       (cl-letf (((symbol-function 'userlock--handle-unlock-error)
+                  (lambda (err) (push err errors))))
+         (unlock-buffer))
+       (should (consp errors))
+       (should (equal '(file-error "Unlocking file")
+                      (seq-subseq (car errors) 0 2)))
+       (should (equal (length errors) 1))))))
+
+(ert-deftest filelock-tests-kill-buffer-spoiled ()
+  "Check that `kill-buffer' fails if a lockfile is \"spoiled\"."
+  (skip-unless (not (eq system-type 'ms-dos))) ; no filelock support
+  (filelock-tests--fixture
+   (lambda ()
+     ;; Set the buffer modified with file locking temporarily
+     ;; disabled.
+     (let ((create-lockfiles nil))
+       (set-buffer-modified-p t))
+     (should-not (file-locked-p buffer-file-truename))
+     (filelock-tests--spoil-lock-file buffer-file-truename)
+
+     ;; Kill the current buffer.  Because the buffer is modified Emacs
+     ;; will attempt to unlock it.  Temporarily bind `yes-or-no-p' to
+     ;; a function that fakes a "yes" answer for the "Buffer modified;
+     ;; kill anyway?" prompt.
+     ;;
+     ;; File errors from unlocking files should call
+     ;; `userlock--handle-unlock-error' (bug#46397).
+     (let (errors)
+       (cl-letf (((symbol-function 'yes-or-no-p)
+                  (lambda (&rest _) t))
+                 ((symbol-function 'userlock--handle-unlock-error)
+                  (lambda (err) (push err errors))))
+         (kill-buffer))
+       (should (consp errors))
+       (should (equal '(file-error "Unlocking file")
+                      (seq-subseq (car errors) 0 2)))
+       (should (equal (length errors) 1))))))
+
+(provide 'filelock-tests)
+;;; filelock-tests.el ends here
diff --git a/test/src/json-tests.el b/test/src/json-tests.el
index 4be11b8..908945f 100644
--- a/test/src/json-tests.el
+++ b/test/src/json-tests.el
@@ -51,6 +51,34 @@
       (should (equal (json-parse-buffer) lisp))
       (should (eobp)))))
 
+(ert-deftest json-serialize/roundtrip-scalars ()
+  "Check that Bug#42994 is fixed."
+  (skip-unless (fboundp 'json-serialize))
+  (dolist (case '((:null "null")
+                  (:false "false")
+                  (t "true")
+                  (0 "0")
+                  (123 "123")
+                  (-456 "-456")
+                  (3.75 "3.75")
+                  ;; The noncharacter U+FFFF should be passed through,
+                  ;; cf. 
https://www.unicode.org/faq/private_use.html#noncharacters.
+                  ("abc\uFFFFαβγ𝔸𝐁𝖢\"\\"
+                   "\"abc\uFFFFαβγ𝔸𝐁𝖢\\\"\\\\\"")))
+    (cl-destructuring-bind (lisp json) case
+      (ert-info ((format "%S ↔ %S" lisp json))
+        (should (equal (json-serialize lisp) json))
+        (with-temp-buffer
+          (json-insert lisp)
+          (should (equal (buffer-string) json))
+          (should (eobp)))
+        (should (equal (json-parse-string json) lisp))
+        (with-temp-buffer
+          (insert json)
+          (goto-char 1)
+          (should (equal (json-parse-buffer) lisp))
+          (should (eobp)))))))
+
 (ert-deftest json-serialize/object ()
   (skip-unless (fboundp 'json-serialize))
   (let ((table (make-hash-table :test #'equal)))
diff --git a/test/src/keyboard-tests.el b/test/src/keyboard-tests.el
index 607d2ea..41c8cdd 100644
--- a/test/src/keyboard-tests.el
+++ b/test/src/keyboard-tests.el
@@ -23,14 +23,15 @@
 
 (ert-deftest keyboard-unread-command-events ()
   "Test `unread-command-events'."
-  (should (equal (progn (push ?\C-a unread-command-events)
-                        (read-event nil nil 1))
-                 ?\C-a))
-  (should (equal (progn (run-with-timer
-                         1 nil
-                         (lambda () (push '(t . ?\C-b) unread-command-events)))
-                        (read-event nil nil 2))
-                 ?\C-b)))
+  (let ((unread-command-events nil))
+    (should (equal (progn (push ?\C-a unread-command-events)
+                          (read-event nil nil 1))
+                   ?\C-a))
+    (should (equal (progn (run-with-timer
+                           1 nil
+                           (lambda () (push '(t . ?\C-b) 
unread-command-events)))
+                          (read-event nil nil 2))
+                   ?\C-b))))
 
 (ert-deftest keyboard-lossage-size ()
   "Test `lossage-size'."
@@ -46,6 +47,28 @@
     (should-error (lossage-size (1- min-value)))
     (should (= lossage-orig (lossage-size lossage-orig)))))
 
+;; FIXME: This test doesn't currently work :-(
+;; (ert-deftest keyboard-tests--echo-keystrokes-bug15332 ()
+;;   (let ((msgs '())
+;;         (unread-command-events nil)
+;;         (redisplay--interactive t)
+;;         (echo-keystrokes 2))
+;;     (setq unread-command-events '(?\C-u))
+;;     (let* ((timer1
+;;         (run-with-timer 3 1
+;;                         (lambda ()
+;;                           (setq unread-command-events '(?5)))))
+;;        (timer2
+;;         (run-with-timer 2.5 1
+;;                         (lambda ()
+;;                           (push (current-message) msgs)))))
+;;       (run-with-timer 5 nil
+;;                   (lambda ()
+;;                     (cancel-timer timer1)
+;;                     (cancel-timer timer2)
+;;                     (throw 'exit msgs)))
+;;       (recursive-edit)
+;;       (should (equal msgs '("C-u 55-" "C-u 5-" "C-u-"))))))
 
 (provide 'keyboard-tests)
 ;;; keyboard-tests.el ends here
diff --git a/test/src/keymap-tests.el b/test/src/keymap-tests.el
index d4f5fc3..a9b0cb5 100644
--- a/test/src/keymap-tests.el
+++ b/test/src/keymap-tests.el
@@ -63,10 +63,66 @@
     (keymap--get-keyelt object t)
     (should menu-item-filter-ran)))
 
+(ert-deftest keymap-define-key/undefined ()
+  ;;  nil (means key is undefined in this keymap),
+  (let ((map (make-keymap)))
+    (define-key map [?a] nil)
+    (should-not (lookup-key map [?a]))))
+
+(ert-deftest keymap-define-key/keyboard-macro ()
+  ;;  a string (treated as a keyboard macro),
+  (let ((map (make-keymap)))
+    (define-key map [?a] "abc")
+    (should (equal (lookup-key map [?a]) "abc"))))
+
+(ert-deftest keymap-define-key/lambda ()
+  (let ((map (make-keymap)))
+    (define-key map [?a] (lambda () (interactive) nil))
+    (should (functionp (lookup-key map [?a])))))
+
+(ert-deftest keymap-define-key/keymap ()
+  ;;  a keymap (to define a prefix key),
+  (let ((map (make-keymap))
+        (map2 (make-keymap)))
+    (define-key map [?a] map2)
+    (define-key map2 [?b] 'foo)
+    (should (eq (lookup-key map [?a ?b]) 'foo))))
+
+(ert-deftest keymap-define-key/menu-item ()
+  ;;  or an extended menu item definition.
+  ;;  (See info node ‘(elisp)Extended Menu Items’.)
+  (let ((map (make-sparse-keymap))
+        (menu (make-sparse-keymap)))
+    (define-key menu [new-file]
+      '(menu-item "Visit New File..." find-file
+                  :enable (menu-bar-non-minibuffer-window-p)
+                  :help "Specify a new file's name, to edit the file"))
+    (define-key map [menu-bar file] (cons "File" menu))
+    (should (eq (lookup-key map [menu-bar file new-file]) 'find-file))))
+
 (ert-deftest keymap-lookup-key ()
   (let ((map (make-keymap)))
     (define-key map [?a] 'foo)
-    (should (eq (lookup-key map [?a]) 'foo))))
+    (should (eq (lookup-key map [?a]) 'foo))
+    (should-not (lookup-key map [?b]))))
+
+(ert-deftest keymap-lookup-key/list-of-keymaps ()
+  (let ((map1 (make-keymap))
+        (map2 (make-keymap)))
+    (define-key map1 [?a] 'foo)
+    (define-key map2 [?b] 'bar)
+    (should (eq (lookup-key (list map1 map2) [?a]) 'foo))
+    (should (eq (lookup-key (list map1 map2) [?b]) 'bar))
+    (should-not (lookup-key (list map1 map2) [?c]))))
+
+(ert-deftest keymap-lookup-key/too-long ()
+  (let ((map (make-keymap)))
+    (define-key map (kbd "C-c f") 'foo)
+    (should (= (lookup-key map (kbd "C-c f x")) 2))))
+
+;; TODO: Write test for the ACCEPT-DEFAULT argument.
+;; (ert-deftest keymap-lookup-key/accept-default ()
+;;   ...)
 
 (ert-deftest describe-buffer-bindings/header-in-current-buffer ()
   "Header should be inserted into the current buffer.
diff --git a/test/src/process-tests.el b/test/src/process-tests.el
index e62bcb3..b64c82c 100644
--- a/test/src/process-tests.el
+++ b/test/src/process-tests.el
@@ -26,7 +26,6 @@
 (require 'cl-lib)
 (require 'ert)
 (require 'puny)
-(require 'rx)
 (require 'subr-x)
 (require 'dns)
 
@@ -348,8 +347,7 @@ See Bug#30460."
                                                   invocation-directory))
                  :stop t))))
 
-;; All the following tests require working DNS, which appears not to
-;; be the case for hydra.nixos.org, so disable them there for now.
+;; The following tests require working DNS
 
 ;; This will need updating when IANA assign more IPv6 global ranges.
 (defun ipv6-is-available ()
@@ -360,9 +358,16 @@ See Bug#30460."
                (= (logand (aref elt 0) #xe000) #x2000)))
         (network-interface-list))))
 
+;; Check if the Internet seems to be working.  Mainly to pacify
+;; Debian's CI system.
+(defvar internet-is-working
+  (progn
+    (require 'dns)
+    (dns-query "google.com")))
+
 (ert-deftest lookup-family-specification ()
   "`network-lookup-address-info' should only accept valid family symbols."
-  (skip-unless (not (getenv "EMACS_HYDRA_CI")))
+  (skip-unless internet-is-working)
   (with-timeout (60 (ert-fail "Test timed out"))
   (should-error (network-lookup-address-info "localhost" 'both))
   (should (network-lookup-address-info "localhost" 'ipv4))
@@ -371,20 +376,20 @@ See Bug#30460."
 
 (ert-deftest lookup-unicode-domains ()
   "Unicode domains should fail."
-  (skip-unless (not (getenv "EMACS_HYDRA_CI")))
+  (skip-unless internet-is-working)
   (with-timeout (60 (ert-fail "Test timed out"))
   (should-error (network-lookup-address-info "faß.de"))
   (should (network-lookup-address-info (puny-encode-domain "faß.de")))))
 
 (ert-deftest unibyte-domain-name ()
   "Unibyte domain names should work."
-  (skip-unless (not (getenv "EMACS_HYDRA_CI")))
+  (skip-unless internet-is-working)
   (with-timeout (60 (ert-fail "Test timed out"))
   (should (network-lookup-address-info (string-to-unibyte "google.com")))))
 
 (ert-deftest lookup-google ()
   "Check that we can look up google IP addresses."
-  (skip-unless (not (getenv "EMACS_HYDRA_CI")))
+  (skip-unless internet-is-working)
   (with-timeout (60 (ert-fail "Test timed out"))
   (let ((addresses-both (network-lookup-address-info "google.com"))
         (addresses-v4 (network-lookup-address-info "google.com" 'ipv4)))
@@ -396,10 +401,12 @@ See Bug#30460."
 
 (ert-deftest non-existent-lookup-failure ()
   "Check that looking up non-existent domain returns nil."
-  (skip-unless (not (getenv "EMACS_HYDRA_CI")))
+  (skip-unless internet-is-working)
   (with-timeout (60 (ert-fail "Test timed out"))
   (should (eq nil (network-lookup-address-info "emacs.invalid")))))
 
+;; End of tests requiring DNS
+
 (defmacro process-tests--ignore-EMFILE (&rest body)
   "Evaluate BODY, ignoring EMFILE errors."
   (declare (indent 0) (debug t))
diff --git a/test/src/undo-tests.el b/test/src/undo-tests.el
index 055bf10..a658bcc 100644
--- a/test/src/undo-tests.el
+++ b/test/src/undo-tests.el
@@ -46,6 +46,7 @@
 ;;; Code:
 
 (require 'ert)
+(require 'facemenu)
 
 (ert-deftest undo-test0 ()
   "Test basics of \\[undo]."
@@ -87,6 +88,7 @@
 
 (ert-deftest undo-test1 ()
   "Test undo of \\[undo] command (redo)."
+  (require 'facemenu)
   (with-temp-buffer
     (buffer-enable-undo)
     (undo-boundary)



reply via email to

[Prev in Thread] Current Thread [Next in Thread]